blob: df96d42b936dd97b401d14a52ef2136c7a9c3f26 [file] [log] [blame]
Guido van Rossumd4d77281994-08-19 10:51:31 +00001/* Get full pathname of current working directory. The pathname is
2 copied to the parameter array 'cwd', and a pointer to this array
3 is also returned as function result. If an error occurred, however,
4 the return value is NULL but 'cwd' is filled with an error message.
5
6 BUG: expect spectacular crashes when called from a directory whose
7 path would be over MAXPATH bytes long (files in such directories are
8 not reachable by full pathname).
9
10 Starting with the dir ID returned by PBHGetVol, we do successive
11 PBGetCatInfo's to get a component of the path until we reach the
12 root (recognized by a dir ID of 2). We move up along the path
13 using the dir ID of the parent directory returned by PBGetCatInfo.
14
15 Then we catenate the components found in reverse order with the volume
16 name (already gotten from PBHGetVol), with intervening and trailing
17 colons
18
19 The code works correctly on MFS disks (where it always returns the
20 volume name) by simply skipping the PBGetCatinfo calls in that case.
21 There is a 'bug' in PBGetCatInfo when called for an MFS disk (with
22 HFS running): it then seems to call PBHGetVInfo, which returns a
23 larger parameter block. But we won't run into this problem because
24 we never call PBGetCatInfo for the root (assuming that PBHGetVol
25 still sets the root ID in this case).
26
27 Public domain by Guido van Rossum, CWI, Amsterdam (July 1987).
28*/
29
Guido van Rossum739267b1994-08-29 08:42:37 +000030#include "macdefs.h"
Jack Jansen2d391f22000-07-14 22:18:32 +000031#include <stdio.h>
Guido van Rossumd4d77281994-08-19 10:51:31 +000032
33#define ROOTID 2 /* Root directory ID */
34
35char *
Jack Jansen9ae898b2000-07-11 21:16:03 +000036getwd(char *cwd)
Guido van Rossumd4d77281994-08-19 10:51:31 +000037{
38 /* Universal parameter block. */
39 union {
Guido van Rossumd4d77281994-08-19 10:51:31 +000040 struct HFileInfo f;
41 struct DirInfo d;
42 struct WDPBRec w;
Guido van Rossumd4d77281994-08-19 10:51:31 +000043 } pb;
44 char buf[MAXPATH]; /* Buffer to store the name components */
45 char *ecwd, *ebuf; /* Pointers to end of used part of cwd and buf */
46 int err; /* Error code of last I/O call */
47
48 /* First, get the default volume name and working directory ID. */
49
50 pb.w.ioNamePtr= (unsigned char *)cwd;
Jack Jansen9e1be971997-04-08 15:24:17 +000051 err= PBHGetVolSync(&pb.w);
Guido van Rossumd4d77281994-08-19 10:51:31 +000052 if (err != noErr) {
Jack Jansen9e1be971997-04-08 15:24:17 +000053 sprintf(cwd, "I/O error %d in PBHGetVolSync", err);
Guido van Rossumd4d77281994-08-19 10:51:31 +000054 return NULL;
55 }
Jack Jansen74a1e632000-07-14 22:37:27 +000056#if TARGET_API_MAC_CARBON
Jack Jansen2b44ba52000-06-02 21:38:19 +000057 p2cstrcpy(cwd, (StringPtr)cwd);
58 ecwd = strchr(cwd, EOS);
59#else
Guido van Rossum5bc76cd1995-02-17 14:24:11 +000060 ecwd= strchr((const char *)p2cstr((unsigned char*)cwd), EOS);
Jack Jansen2b44ba52000-06-02 21:38:19 +000061#endif
Guido van Rossumd4d77281994-08-19 10:51:31 +000062 ebuf= buf;
63 *ebuf = EOS;
64
65 /* Next, if at least we're running HFS, walk up the path. */
66
Jack Jansen2b44ba52000-06-02 21:38:19 +000067 {
Guido van Rossumd4d77281994-08-19 10:51:31 +000068 long dirid= pb.w.ioWDDirID;
69 pb.d.ioVRefNum= pb.w.ioWDVRefNum;
70 while (dirid != ROOTID) {
71 pb.d.ioNamePtr= (unsigned char *) ++ebuf;
72 pb.d.ioFDirIndex= -1;
73 pb.d.ioDrDirID= dirid;
Jack Jansen9e1be971997-04-08 15:24:17 +000074 err= PBGetCatInfoSync((CInfoPBPtr)&pb.d);
Guido van Rossumd4d77281994-08-19 10:51:31 +000075 if (err != noErr) {
Jack Jansen9e1be971997-04-08 15:24:17 +000076 sprintf(cwd, "I/O error %d in PBGetCatInfoSync", err);
Guido van Rossumd4d77281994-08-19 10:51:31 +000077 return NULL;
78 }
79 dirid= pb.d.ioDrParID;
Jack Jansen74a1e632000-07-14 22:37:27 +000080#if TARGET_API_MAC_CARBON
Jack Jansen2b44ba52000-06-02 21:38:19 +000081 p2cstrcpy(ebuf, (StringPtr)ebuf);
82 ebuf += strlen(ebuf);
83#else
Guido van Rossum5bc76cd1995-02-17 14:24:11 +000084 ebuf += strlen((const char *)p2cstr((unsigned char *)ebuf));
Jack Jansen2b44ba52000-06-02 21:38:19 +000085#endif
Guido van Rossumd4d77281994-08-19 10:51:31 +000086 /* Should check for buf overflow */
87 }
88 }
89
90 /* Finally, reverse the list of components and append it to cwd.
91 Ebuf points at the EOS after last component,
92 and there is an EOS before the first component.
93 If there are no components, ebuf equals buf (but there
94 is still an EOS where it points).
95 Ecwd points at the EOS after the path built up so far,
96 initially the volume name.
97 We break out of the loop in the middle, thus
98 appending a colon at the end in all cases. */
99
100 for (;;) {
101 *ecwd++ = ':';
102 if (ebuf == buf)
103 break;
104 do { } while (*--ebuf != EOS); /* Find component start */
105 strcpy(ecwd, ebuf+1);
106 ecwd= strchr(ecwd, EOS);
107 }
108 *ecwd= EOS;
109 return cwd;
110}