1 | /********************************************************************** <BR>
|
---|
2 | This file is part of Crack dot Com's free source code release of
|
---|
3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
4 | information about compiling & licensing issues visit this URL</a>
|
---|
5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
7 | ***********************************************************************/
|
---|
8 |
|
---|
9 | //{{{ Dirent for Mac
|
---|
10 | /****************************************************************************************
|
---|
11 | *
|
---|
12 | * Notes:
|
---|
13 | * From: 'dirent.c' by George T. Talbot
|
---|
14 | *
|
---|
15 | * Modifications:
|
---|
16 | *
|
---|
17 | * 1) These routines will NOT work under A/UX.
|
---|
18 | * 2) WD = working directory
|
---|
19 | * 3) CD = change directory
|
---|
20 | * 4) FS = file system
|
---|
21 | * 5) Mac filesystems allow spaces as part of pathnames!
|
---|
22 | * 6) All routines which return a path use the default Macintosh path separator,
|
---|
23 | * a colon (":").
|
---|
24 | *
|
---|
25 | ****************************************************************************************/
|
---|
26 | //}}}
|
---|
27 |
|
---|
28 | #include "dirent.hh"
|
---|
29 | //#include <pascal.h>
|
---|
30 | #include <string.h>
|
---|
31 |
|
---|
32 | OSErr dd_errno; /* Global errno to check after calls to dirent routines */
|
---|
33 | char *dd_separator = ":"; /* If you're feeling brave, change this to "/" */
|
---|
34 | int dd_xform_seps = false;
|
---|
35 |
|
---|
36 |
|
---|
37 | void PtoCstr(unsigned char *st)
|
---|
38 | //{{{
|
---|
39 | {
|
---|
40 | int len = st[0];
|
---|
41 |
|
---|
42 | memcpy(st,st+1,len);
|
---|
43 | st[len] = 0;
|
---|
44 | }
|
---|
45 | //}}}
|
---|
46 |
|
---|
47 |
|
---|
48 | void CtoPstr(char *st)
|
---|
49 | //{{{
|
---|
50 | {
|
---|
51 | int len = strlen(st);
|
---|
52 |
|
---|
53 | memcpy(st+1,st,len);
|
---|
54 | st[0] = len;
|
---|
55 | }
|
---|
56 | //}}}
|
---|
57 |
|
---|
58 |
|
---|
59 | DIR *opendir(char *dirname)
|
---|
60 | // This function, given a Macintosh-style pathname, will open a directory to that path.
|
---|
61 | //{{{
|
---|
62 | /****************************************************************************************
|
---|
63 | * NOTES: 1) passing in nil will get you the current directory.
|
---|
64 | * 2) ".:", "..:" & "Å:" are supported at the beginning of paths ONLY
|
---|
65 | * by this routine.
|
---|
66 | * 3) "/" will be turned into ":" by this routine.
|
---|
67 | *
|
---|
68 | * Calls: PBHGetVol(), PBHGetCatInfo(), PBHSetVol(), hopendir(), CtoPstr()
|
---|
69 | * Called By: <general purpose>
|
---|
70 | * Globals Used: dd_errno
|
---|
71 | * Parameters: pointer to C-string pathname or nil for current directory
|
---|
72 | * Returns: pointer to directory management block or nil & dd_errno will be set
|
---|
73 | ****************************************************************************************/
|
---|
74 | {
|
---|
75 | WDPBRec pb;
|
---|
76 | CInfoPBRec cpb;
|
---|
77 | short vRefNum;
|
---|
78 | long dirID;
|
---|
79 | char *dname;
|
---|
80 | DIR *temp;
|
---|
81 | char path_temp[MAXPATHLEN+1]; /* Temporary area for building pathname */
|
---|
82 |
|
---|
83 | /* Save the current path */
|
---|
84 | pb.ioCompletion = nil;
|
---|
85 | pb.ioNamePtr = nil;
|
---|
86 |
|
---|
87 | if (dd_errno = PBHGetVol(&pb, false))
|
---|
88 | return nil;
|
---|
89 |
|
---|
90 | vRefNum = pb.ioWDVRefNum;
|
---|
91 | dirID = pb.ioWDDirID;
|
---|
92 |
|
---|
93 | /* dname points to the desired pathname */
|
---|
94 | dname = dirname;
|
---|
95 |
|
---|
96 | /* If no pathname was passed in, or there are no ".", ".." or "Å" special directory
|
---|
97 | * names, then handle the pathname as normal.
|
---|
98 | */
|
---|
99 | if (dirname == nil)
|
---|
100 | goto opendir_fallthrough;
|
---|
101 |
|
---|
102 | /* If there's not '.', '..' or 'Å', fall through */
|
---|
103 | if ((dirname[0] != '.') && (dirname[0] != 'Å'))
|
---|
104 | goto opendir_fallthrough;
|
---|
105 |
|
---|
106 | /* If there's a 'Å', treat it like '..' */
|
---|
107 | if (dirname[0] == 'Å')
|
---|
108 | {
|
---|
109 | dname = &(dirname[1]);
|
---|
110 | goto path_dotdot;
|
---|
111 | }
|
---|
112 |
|
---|
113 | /* If the pathname has "." (current directory) in front of it... */
|
---|
114 | if (dirname[1] != '.')
|
---|
115 | {
|
---|
116 | /* Skip over the "." and fall through */
|
---|
117 | dname = &(dirname[1]);
|
---|
118 | goto opendir_fallthrough;
|
---|
119 | }
|
---|
120 |
|
---|
121 | /* Skip over the ".." */
|
---|
122 | dname = &(dirname[2]);
|
---|
123 |
|
---|
124 | path_dotdot:
|
---|
125 | /* If we get here, the directory has ".." in front of it... */
|
---|
126 |
|
---|
127 | /* First, get the directory info on the current directory. We do this so
|
---|
128 | * that we can get the directory's parent
|
---|
129 | */
|
---|
130 | cpb.dirInfo.ioCompletion = nil;
|
---|
131 | cpb.dirInfo.ioNamePtr = (unsigned char *)path_temp;
|
---|
132 | /* Unused, but must be set because of
|
---|
133 | * bug in Apple File Sharing.
|
---|
134 | */
|
---|
135 | cpb.dirInfo.ioVRefNum = vRefNum;
|
---|
136 | cpb.dirInfo.ioFDirIndex = -1;
|
---|
137 | cpb.dirInfo.ioDrDirID = dirID;
|
---|
138 |
|
---|
139 | if (dd_errno = PBGetCatInfo(&cpb, false))
|
---|
140 | return nil;
|
---|
141 |
|
---|
142 | /* Temporarily CD to the parent directory */
|
---|
143 | pb.ioCompletion = nil;
|
---|
144 | pb.ioNamePtr = nil;
|
---|
145 | pb.ioVRefNum = pb.ioWDVRefNum;
|
---|
146 | pb.ioWDDirID = cpb.dirInfo.ioDrParID;
|
---|
147 |
|
---|
148 | if (dd_errno = PBHSetVol(&pb, false))
|
---|
149 | return nil;
|
---|
150 |
|
---|
151 | /* This is the common code for all three cases above */
|
---|
152 | opendir_fallthrough:
|
---|
153 | /* If the pathname is too long (this is a Macintosh FS constraint), then return */
|
---|
154 | if (strlen(dname) > MAXPATHLEN)
|
---|
155 | {
|
---|
156 | /* Set the error */
|
---|
157 | dd_errno = bdNamErr;
|
---|
158 | temp = nil;
|
---|
159 |
|
---|
160 | /* Go to the common exit, where we CD back to the saved WD */
|
---|
161 | goto opendir_exit;
|
---|
162 | }
|
---|
163 |
|
---|
164 | /* If this call was passed a pathname */
|
---|
165 | if (dname != nil)
|
---|
166 | {
|
---|
167 | /* Copy the pathname into a temp */
|
---|
168 | strcpy(path_temp, dname);
|
---|
169 |
|
---|
170 | /* Turn it into a Pascal string for the Mac FS */
|
---|
171 | CtoPstr(path_temp);
|
---|
172 |
|
---|
173 | /* Change any "/" to ":" for the Mac FS */
|
---|
174 | if (dd_xform_seps)
|
---|
175 | {
|
---|
176 | int i;
|
---|
177 |
|
---|
178 | for (i=1; i<= path_temp[0]; ++i)
|
---|
179 | if (path_temp[i] == '/')
|
---|
180 | path_temp[i] = ':';
|
---|
181 | }
|
---|
182 |
|
---|
183 | /* Try and open the directory */
|
---|
184 | temp = hopendir(path_temp, 0, 0);
|
---|
185 | }
|
---|
186 | else
|
---|
187 | /* If this call wasn't passed a pathname, then we call hopendir() with nil to
|
---|
188 | * tell it to open the current working directory.
|
---|
189 | */
|
---|
190 | temp = hopendir(nil, 0, 0);
|
---|
191 |
|
---|
192 | /* This is the common exit code which restores the current WD */
|
---|
193 | opendir_exit:
|
---|
194 | pb.ioCompletion = nil;
|
---|
195 | pb.ioNamePtr = nil;
|
---|
196 | pb.ioVRefNum = vRefNum;
|
---|
197 | pb.ioWDDirID = dirID;
|
---|
198 |
|
---|
199 | if (dd_errno = PBHSetVol(&pb, false))
|
---|
200 | {
|
---|
201 | /* If this call failed, then get rid of the structures created by hopendir() */
|
---|
202 | closedir(temp);
|
---|
203 | return nil;
|
---|
204 | }
|
---|
205 |
|
---|
206 | return temp;
|
---|
207 | }
|
---|
208 | //}}}
|
---|
209 |
|
---|
210 |
|
---|
211 | DIR *hopendir(char *dirname, short vRefNum, long dirID)
|
---|
212 | // This function actually opens the directory. If you feel brave, you can call it.
|
---|
213 | // If you pass in a dirname, then set vRefNum and dirID to 0. All named opens are
|
---|
214 | // relative to the current WD. If you pass in vRefNum and dirID, then don't bother
|
---|
215 | // passing in a name. This routine WILL CHANGE YOUR CURRENT WORKING DIRECTORY!
|
---|
216 | //{{{
|
---|
217 | /****************************************************************************************
|
---|
218 | * Calls: NewHandle(), PBHGetCatInfo(), PBHSetVol(), PtoCstr(), BlockMove(),
|
---|
219 | * DisposHandle(), MoveHHi(), HLock(), MemError()
|
---|
220 | * Called By: opendir(), and you if you feel brave.
|
---|
221 | * Globals Used: dd_errno
|
---|
222 | * Parameters: pointer to Pascal-string pathname, vRefNum, dirID of desired
|
---|
223 | * directory. If you pass in a WDRefNum as the vRefNum, set dirID to 0
|
---|
224 | * Returns: pointer to directory management block or nil & dd_errno will be set
|
---|
225 | ****************************************************************************************/
|
---|
226 | {
|
---|
227 | DIR **curh, *cur;
|
---|
228 | CInfoPBRec cpb;
|
---|
229 | WDPBRec pb;
|
---|
230 | Str63 name;
|
---|
231 |
|
---|
232 | /* Get memory for the directory structure */
|
---|
233 | curh = (DIR **) NewHandle(sizeof(DIR));
|
---|
234 |
|
---|
235 | /* Did we get it? */
|
---|
236 | if (curh == nil)
|
---|
237 | {
|
---|
238 | dd_errno = MemError();
|
---|
239 | return nil;
|
---|
240 | }
|
---|
241 |
|
---|
242 | /* Move it high and lock it */
|
---|
243 | MoveHHi((Handle)curh);
|
---|
244 | HLock((Handle)curh);
|
---|
245 | cur = *curh;
|
---|
246 |
|
---|
247 | /* If we're supposed to open anything but the current directory, set the current
|
---|
248 | * working directory to the desired directory.
|
---|
249 | */
|
---|
250 | if ((dirname != nil) || (vRefNum != 0) || (dirID != 0))
|
---|
251 | {
|
---|
252 | pb.ioCompletion = nil;
|
---|
253 | pb.ioNamePtr = (unsigned char *)dirname;
|
---|
254 | pb.ioVRefNum = vRefNum;
|
---|
255 | pb.ioWDDirID = dirID;
|
---|
256 |
|
---|
257 | if (dd_errno = PBHSetVol(&pb, false))
|
---|
258 | goto failure_exit;
|
---|
259 | }
|
---|
260 |
|
---|
261 | cur->dd_buf = nil;
|
---|
262 |
|
---|
263 | /* Get info on the desired directory (its name, etc.) */
|
---|
264 | cpb.dirInfo.ioCompletion = nil;
|
---|
265 | cpb.dirInfo.ioNamePtr = name;
|
---|
266 | cpb.dirInfo.ioVRefNum = vRefNum;
|
---|
267 | cpb.dirInfo.ioFDirIndex = -1;
|
---|
268 | cpb.dirInfo.ioDrDirID = dirID;
|
---|
269 |
|
---|
270 | if (dd_errno = PBGetCatInfo(&cpb, false))
|
---|
271 | goto failure_exit;
|
---|
272 |
|
---|
273 | /* Save the directory info */
|
---|
274 | cur->dir_fsp.vRefNum = vRefNum;
|
---|
275 | cur->dd_fd = cpb.dirInfo.ioDrDirID;
|
---|
276 | cur->dd_parent = cpb.dirInfo.ioDrParID;
|
---|
277 |
|
---|
278 | BlockMove(name, cur->dir_fsp.name, sizeof(Str63));
|
---|
279 |
|
---|
280 | /* Convert the name to a C-style string */
|
---|
281 | PtoCstr(cur->dir_fsp.name);
|
---|
282 |
|
---|
283 | /* Set up our directory structure to read the first entry */
|
---|
284 | cur->dd_off = 1;
|
---|
285 | cur->dd_numents = cpb.dirInfo.ioDrNmFls;
|
---|
286 | cur->dd_cached = false;
|
---|
287 |
|
---|
288 | return cur;
|
---|
289 |
|
---|
290 | /* This code is branched-to in case of error. It frees up the memory and returns. */
|
---|
291 | failure_exit:
|
---|
292 | DisposHandle((Handle) curh);
|
---|
293 | return nil;
|
---|
294 | }
|
---|
295 | //}}}
|
---|
296 |
|
---|
297 |
|
---|
298 | long telldir(DIR *dirp)
|
---|
299 | // This function returns the index of the directory entry to be next read.
|
---|
300 | //{{{
|
---|
301 | /****************************************************************************************
|
---|
302 | * Calls: nothing
|
---|
303 | * Called By: <general purpose>
|
---|
304 | * Globals Used: none
|
---|
305 | * Parameters: pointer to the directory management block
|
---|
306 | * Returns: index of the next directory entry to be read.
|
---|
307 | ****************************************************************************************/
|
---|
308 | {
|
---|
309 | if (dirp->dd_off > dirp->dd_numents)
|
---|
310 | return -1;
|
---|
311 | else
|
---|
312 | return dirp->dd_off-1; /* The -1 is because Macs start at 1 & not 0 for dir index,
|
---|
313 | * and this is a little more POSIX.
|
---|
314 | */
|
---|
315 | }
|
---|
316 | //}}}
|
---|
317 |
|
---|
318 |
|
---|
319 | int closedir(DIR *dirp)
|
---|
320 | // This function closes the directory opened with opendir() or hopendir()
|
---|
321 | //{{{
|
---|
322 | /****************************************************************************************
|
---|
323 | * Calls: DisposHandle(), RecoverHandle()
|
---|
324 | * Called By: <general purpose>
|
---|
325 | * Globals Used: none
|
---|
326 | * Parameters: pointer to the directory management block
|
---|
327 | * Returns: 0 (always successful)
|
---|
328 | ****************************************************************************************/
|
---|
329 | {
|
---|
330 | struct dirent **cur;
|
---|
331 |
|
---|
332 | /* Dispose of any directory entries read in. */
|
---|
333 | cur = dirp->dd_buf;
|
---|
334 |
|
---|
335 | dd_errno = noErr;
|
---|
336 |
|
---|
337 | while (cur)
|
---|
338 | {
|
---|
339 | struct dirent **next;
|
---|
340 |
|
---|
341 | next = (*cur)->next;
|
---|
342 |
|
---|
343 | DisposHandle((Handle) cur);
|
---|
344 |
|
---|
345 | if (dd_errno == noErr)
|
---|
346 | dd_errno = MemError();
|
---|
347 |
|
---|
348 | cur = next;
|
---|
349 | }
|
---|
350 |
|
---|
351 | /* Dispose of the directory managment block */
|
---|
352 | DisposHandle(RecoverHandle((Ptr) dirp));
|
---|
353 |
|
---|
354 | if (dd_errno == noErr)
|
---|
355 | dd_errno = MemError();
|
---|
356 |
|
---|
357 | return dd_errno?-1:0;
|
---|
358 | }
|
---|
359 | //}}}
|
---|
360 |
|
---|
361 |
|
---|
362 | void seekdir(DIR *dirp, long loc)
|
---|
363 | // This function sets the index of the next-read directory entry. It will also search
|
---|
364 | // the list of read entries so that an entry won't be read from disk more than once.
|
---|
365 | //{{{
|
---|
366 | /****************************************************************************************
|
---|
367 | * Calls: nothing
|
---|
368 | * Called By: <general purpose>
|
---|
369 | * Globals Used: none
|
---|
370 | * Parameters: pointer to the directory management block, index of directory
|
---|
371 | * Returns: nothing
|
---|
372 | ****************************************************************************************/
|
---|
373 | {
|
---|
374 | struct dirent **cur;
|
---|
375 |
|
---|
376 | dirp->dd_off = loc+1; /* The +1 is because the Mac indexes directories
|
---|
377 | * from 1 and not 0 and we want to be a little bit
|
---|
378 | * POSIX
|
---|
379 | */
|
---|
380 |
|
---|
381 | /* Search through the entries that we've read already */
|
---|
382 | cur = dirp->dd_buf;
|
---|
383 |
|
---|
384 | while (cur)
|
---|
385 | {
|
---|
386 | /* If we find the entry that we've seeked to, set up so that readdir() will
|
---|
387 | * return this one instead of reading a new one.
|
---|
388 | */
|
---|
389 | if (loc == (*cur)->d_off)
|
---|
390 | {
|
---|
391 | dirp->dd_cached = true;
|
---|
392 | dirp->dd_cache_hint = cur;
|
---|
393 |
|
---|
394 | return;
|
---|
395 | }
|
---|
396 |
|
---|
397 | cur = (*cur)->next;
|
---|
398 | }
|
---|
399 |
|
---|
400 | /* If we didn't find it, then tell readdir() to get the entry from the FS */
|
---|
401 | dirp->dd_cached = false;
|
---|
402 | }
|
---|
403 | //}}}
|
---|
404 |
|
---|
405 |
|
---|
406 | struct dirent *readdir(DIR *dirp)
|
---|
407 | // This function will read the next directory entry from disk. It will return nil and
|
---|
408 | // set dd_errno to noErr when the end of the directory is reached. It will avoid
|
---|
409 | // reading directory entries from disk more than once.
|
---|
410 | //{{{
|
---|
411 | /****************************************************************************************
|
---|
412 | * Calls: nothing
|
---|
413 | * Called By: <general purpose>
|
---|
414 | * Globals Used: none
|
---|
415 | * Parameters: pointer to the directory management block
|
---|
416 | * Returns: pointer to directory entry or nil if an error occurred and dd_errno
|
---|
417 | * will be set. If the last entry has already been read, this will
|
---|
418 | * return nil and dd_errno will be set to noErr.
|
---|
419 | ****************************************************************************************/
|
---|
420 | {
|
---|
421 | CInfoPBRec cpb;
|
---|
422 | struct dirent **meh, *me;
|
---|
423 |
|
---|
424 | /* If the entry has been read already, then return the already present entry */
|
---|
425 | if (dirp->dd_cached)
|
---|
426 | me = *(dirp->dd_cache_hint);
|
---|
427 | else
|
---|
428 | /* Otherwise, read it from disk... */
|
---|
429 | {
|
---|
430 | /* Past the end of the directory? */
|
---|
431 | if (dirp->dd_off > dirp->dd_numents)
|
---|
432 | {
|
---|
433 | dd_errno = noErr;
|
---|
434 | return nil;
|
---|
435 | }
|
---|
436 |
|
---|
437 | /* Allocate space for a new entry */
|
---|
438 | meh = (struct dirent **) NewHandle(sizeof(struct dirent));
|
---|
439 |
|
---|
440 | /* Enough memory? */
|
---|
441 | if (meh == nil)
|
---|
442 | {
|
---|
443 | dd_errno = MemError();
|
---|
444 | return nil;
|
---|
445 | }
|
---|
446 |
|
---|
447 | /* Lock the entry */
|
---|
448 | MoveHHi((Handle) meh);
|
---|
449 | HLock((Handle) meh);
|
---|
450 |
|
---|
451 | me = *meh;
|
---|
452 |
|
---|
453 | /* Get the entry's info from disk */
|
---|
454 | me->fsp.name[0] = 0;
|
---|
455 |
|
---|
456 | cpb.dirInfo.ioCompletion = nil;
|
---|
457 | cpb.dirInfo.ioNamePtr = me->fsp.name;
|
---|
458 | cpb.dirInfo.ioVRefNum = dirp->dir_fsp.vRefNum;
|
---|
459 | cpb.dirInfo.ioFDirIndex = dirp->dd_off;
|
---|
460 | cpb.dirInfo.ioDrDirID = dirp->dd_fd;
|
---|
461 |
|
---|
462 | if (dd_errno = PBGetCatInfo(&cpb, false))
|
---|
463 | {
|
---|
464 | DisposHandle((Handle) meh);
|
---|
465 | return nil;
|
---|
466 | }
|
---|
467 |
|
---|
468 | /* Set up the dirent structure */
|
---|
469 | me->d_off = dirp->dd_off-1;
|
---|
470 | me->fsp.vRefNum = cpb.dirInfo.ioVRefNum;
|
---|
471 | me->d_fileno = cpb.dirInfo.ioDrDirID;
|
---|
472 | me->d_parent = cpb.dirInfo.ioDrParID;
|
---|
473 |
|
---|
474 | /* C strings only! */
|
---|
475 | PtoCstr(me->fsp.name);
|
---|
476 |
|
---|
477 | /* Add it to the list for this directory */
|
---|
478 | me->next = dirp->dd_buf;
|
---|
479 |
|
---|
480 | dirp->dd_buf = meh;
|
---|
481 | }
|
---|
482 |
|
---|
483 | /* Seek to the next entry */
|
---|
484 | seekdir(dirp, dirp->dd_off);
|
---|
485 |
|
---|
486 | /* Return what we've found */
|
---|
487 | return me;
|
---|
488 | }
|
---|
489 | //}}}
|
---|
490 |
|
---|
491 | OSErr hgetwd(short vRefNum, long startDirID, char *path, int max_path_len, char *sep)
|
---|
492 | // This function will give an absolute pathname to a given directory.
|
---|
493 | //{{{
|
---|
494 | /****************************************************************************************
|
---|
495 | * Calls: NewPtr(), DisposPtr(), PBGetCatInfo()
|
---|
496 | * Called By: <general purpose>
|
---|
497 | * Globals Used: none
|
---|
498 | * Parameters: vRefNum and startDirID of desired path, pointer to path name storage,
|
---|
499 | * length of path name storage, pointer to C-string separator.
|
---|
500 | * Returns: bdNamErr if the path would overflow the storage,
|
---|
501 | * some other error code if something else happened,
|
---|
502 | * or noErr on success.
|
---|
503 | ****************************************************************************************/
|
---|
504 | {
|
---|
505 | long curDirID;
|
---|
506 | OSErr err;
|
---|
507 | CInfoPBRec pb;
|
---|
508 | Str63 name;
|
---|
509 | char *temp_path;
|
---|
510 |
|
---|
511 | /* Start with an empty path */
|
---|
512 | path[0] = 0;
|
---|
513 |
|
---|
514 | /* Get memory for a temporary path */
|
---|
515 | temp_path = (char *) NewPtr(max_path_len);
|
---|
516 |
|
---|
517 | if (temp_path == nil)
|
---|
518 | return MemError();
|
---|
519 |
|
---|
520 | /* Start at the given directory */
|
---|
521 | curDirID = startDirID;
|
---|
522 |
|
---|
523 | do
|
---|
524 | {
|
---|
525 | /* Get cat info for the current directory */
|
---|
526 | name[0] = 0;
|
---|
527 |
|
---|
528 | pb.dirInfo.ioCompletion = nil;
|
---|
529 | pb.dirInfo.ioNamePtr = name;
|
---|
530 | pb.dirInfo.ioVRefNum = vRefNum;
|
---|
531 | pb.dirInfo.ioFDirIndex = -1;
|
---|
532 | pb.dirInfo.ioDrDirID = curDirID;
|
---|
533 |
|
---|
534 | if (err = PBGetCatInfo(&pb, false))
|
---|
535 | {
|
---|
536 | DisposPtr((Ptr) temp_path);
|
---|
537 | return err;
|
---|
538 | }
|
---|
539 |
|
---|
540 | /* Convert name to a C string */
|
---|
541 | PtoCstr(name);
|
---|
542 |
|
---|
543 | /* Check that we don't overflow storage */
|
---|
544 | if ((strlen((char*)name) + strlen(path) + strlen(sep)) >= max_path_len)
|
---|
545 | {
|
---|
546 | DisposPtr((Ptr) temp_path);
|
---|
547 | return bdNamErr;
|
---|
548 | }
|
---|
549 |
|
---|
550 | /* Prepend the name and separator */
|
---|
551 | strcpy(temp_path, path);
|
---|
552 | strcpy(path, (char*)name);
|
---|
553 | strcat(path, sep);
|
---|
554 | strcat(path, temp_path);
|
---|
555 |
|
---|
556 | /* Move "up" one directory */
|
---|
557 | curDirID = pb.dirInfo.ioDrParID;
|
---|
558 | }
|
---|
559 | /* Until we hit the root directory */
|
---|
560 | while (pb.dirInfo.ioDrDirID != fsRtDirID);
|
---|
561 |
|
---|
562 | /* Get rid of our temp storage and return */
|
---|
563 | DisposPtr((Ptr) temp_path);
|
---|
564 |
|
---|
565 | return MemError();
|
---|
566 | }
|
---|
567 | //}}}
|
---|
568 |
|
---|
569 |
|
---|
570 | int chdir(char *path)
|
---|
571 | // This function will change the current working directory.
|
---|
572 | //{{{
|
---|
573 | /****************************************************************************************
|
---|
574 | * Calls: opendir(), closedir(), PBHSetVol()
|
---|
575 | * Called By: <general purpose>
|
---|
576 | * Globals Used: none
|
---|
577 | * Parameters: C-string pathname.
|
---|
578 | * Returns: -1 on failure, 0 on success. Sets dd_errno on failure.
|
---|
579 | ****************************************************************************************/
|
---|
580 | {
|
---|
581 | DIR *d;
|
---|
582 | short vRefNum;
|
---|
583 | long dirID;
|
---|
584 | WDPBRec pb;
|
---|
585 |
|
---|
586 | /* Open the directory */
|
---|
587 | d = opendir(path);
|
---|
588 |
|
---|
589 | if (d == nil)
|
---|
590 | return -1;
|
---|
591 |
|
---|
592 | /* Get the Mac FS identification for this directory */
|
---|
593 | vRefNum = d->dd_volume;
|
---|
594 | dirID = d->dd_fd;
|
---|
595 |
|
---|
596 | /* Close the directory */
|
---|
597 | closedir(d);
|
---|
598 |
|
---|
599 | /* CD to the new directory */
|
---|
600 | pb.ioCompletion = nil;
|
---|
601 | pb.ioNamePtr = nil;
|
---|
602 | pb.ioVRefNum = vRefNum;
|
---|
603 | pb.ioWDDirID = dirID;
|
---|
604 |
|
---|
605 | dd_errno = PBHSetVol(&pb, false);
|
---|
606 |
|
---|
607 | return dd_errno?-1:0;
|
---|
608 | }
|
---|
609 | //}}}
|
---|
610 |
|
---|
611 |
|
---|
612 | char *getwd(char *path)
|
---|
613 | // This function will get the current working directory's path.
|
---|
614 | //{{{
|
---|
615 | /****************************************************************************************
|
---|
616 | * Calls: PBHGetVol(), hgetwd()
|
---|
617 | * Called By: <general purpose>
|
---|
618 | * Globals Used: none
|
---|
619 | * Parameters: pointer to a buffer of MAXPATHLEN bytes.
|
---|
620 | * Returns: pointer to the buffer on success, on failure, nil and dd_errno will
|
---|
621 | * be set.
|
---|
622 | ****************************************************************************************/
|
---|
623 | {
|
---|
624 | WDPBRec pb;
|
---|
625 |
|
---|
626 | /* Get the current working directory */
|
---|
627 | pb.ioCompletion = nil;
|
---|
628 | pb.ioNamePtr = nil;
|
---|
629 |
|
---|
630 | if (dd_errno = PBHGetVol(&pb, false))
|
---|
631 | return nil;
|
---|
632 |
|
---|
633 | /* Transform it into a path */
|
---|
634 | if (dd_errno = hgetwd(pb.ioWDVRefNum, pb.ioWDDirID, path, MAXPATHLEN-1, dd_separator))
|
---|
635 | return nil;
|
---|
636 |
|
---|
637 | return path;
|
---|
638 | }
|
---|
639 | //}}}
|
---|
640 |
|
---|
641 |
|
---|
642 | char *pathdir(DIR *dirp, char *path)
|
---|
643 | // This function will get the path to a given (already opened) directory.
|
---|
644 | //{{{
|
---|
645 | /****************************************************************************************
|
---|
646 | * Calls: hgetwd()
|
---|
647 | * Called By: <general purpose>
|
---|
648 | * Globals Used: none
|
---|
649 | * Parameters: pointer to a buffer of MAXPATHLEN bytes.
|
---|
650 | * Returns: pointer to the buffer on success, on failure, nil and dd_errno will
|
---|
651 | * be set.
|
---|
652 | ****************************************************************************************/
|
---|
653 | {
|
---|
654 | if (dd_errno = hgetwd(dirp->dd_volume, dirp->dd_fd, path, MAXPATHLEN-1, dd_separator))
|
---|
655 | return nil;
|
---|
656 |
|
---|
657 | return path;
|
---|
658 | }
|
---|
659 | //}}}
|
---|
660 |
|
---|
661 |
|
---|
662 | //{{{ Emacs Locals
|
---|
663 | // Local Variables:
|
---|
664 | // folded-file: t
|
---|
665 | // End:
|
---|
666 | //}}}
|
---|