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