Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6725 | siemargl | 1 | /* |
2 | Copyright (c) 1990-2003 Info-ZIP. All rights reserved. |
||
3 | |||
4 | See the accompanying file LICENSE, version 2000-Apr-09 or later |
||
5 | (the contents of which are also included in zip.h) for terms of use. |
||
6 | If, for some reason, all these files are missing, the Info-ZIP license |
||
7 | also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html |
||
8 | */ |
||
9 | /*--------------------------------------------------------------------------- |
||
10 | |||
11 | pathname.c |
||
12 | |||
13 | Function dealing with the pathname. Mostly C-string work. |
||
14 | |||
15 | ---------------------------------------------------------------------------*/ |
||
16 | |||
17 | /*****************************************************************************/ |
||
18 | /* Includes */ |
||
19 | /*****************************************************************************/ |
||
20 | |||
21 | #include |
||
22 | #include |
||
23 | #include |
||
24 | #include |
||
25 | |||
26 | #include "pathname.h" |
||
27 | #include "helpers.h" |
||
28 | #include "macstuff.h" |
||
29 | |||
30 | |||
31 | /*****************************************************************************/ |
||
32 | /* Global Vars */ |
||
33 | /*****************************************************************************/ |
||
34 | |||
35 | const char ResourceMark[] = "XtraStuf.mac:"; /* see also macos.c */ |
||
36 | |||
37 | |||
38 | #include "zip.h" |
||
39 | |||
40 | |||
41 | |||
42 | |||
43 | /*****************************************************************************/ |
||
44 | /* Functions */ |
||
45 | /*****************************************************************************/ |
||
46 | |||
47 | |||
48 | /* |
||
49 | *---------------------------------------------------------------------- |
||
50 | * |
||
51 | * FSpFindFolder -- |
||
52 | * |
||
53 | * This function is a version of the FindFolder function that |
||
54 | * returns the result as a FSSpec rather than a vRefNum and dirID. |
||
55 | * |
||
56 | * Results: |
||
57 | * Results will be simaler to that of the FindFolder function. |
||
58 | * |
||
59 | * Side effects: |
||
60 | * None. |
||
61 | * |
||
62 | *---------------------------------------------------------------------- |
||
63 | */ |
||
64 | |||
65 | OSErr |
||
66 | FSpFindFolder( |
||
67 | short vRefNum, /* Volume reference number. */ |
||
68 | OSType folderType, /* Folder type taken by FindFolder. */ |
||
69 | Boolean createFolder, /* Should we create it if non-existant. */ |
||
70 | FSSpec *spec) /* Pointer to resulting directory. */ |
||
71 | { |
||
72 | short foundVRefNum; |
||
73 | long foundDirID; |
||
74 | OSErr err; |
||
75 | |||
76 | err = FindFolder(vRefNum, folderType, createFolder, |
||
77 | &foundVRefNum, &foundDirID); |
||
78 | if (err != noErr) { |
||
79 | return err; |
||
80 | } |
||
81 | |||
82 | err = FSMakeFSSpecCompat(foundVRefNum, foundDirID, "\p", spec); |
||
83 | return err; |
||
84 | } |
||
85 | |||
86 | |||
87 | /* |
||
88 | ** return volumename from pathname |
||
89 | ** |
||
90 | */ |
||
91 | |||
92 | unsigned short GetVolumeFromPath(const char *FullPath, char *VolumeName) |
||
93 | { |
||
94 | const char *VolEnd, *tmpPtr1; |
||
95 | char *tmpPtr2 = VolumeName; |
||
96 | |||
97 | AssertStr(FullPath,"GetVolumeFromPath") |
||
98 | |||
99 | for (VolEnd = FullPath; *VolEnd != '\0' && *VolEnd != ':'; VolEnd++) |
||
100 | ; |
||
101 | if (*VolEnd == '\0') return 0; |
||
102 | |||
103 | for (tmpPtr1 = FullPath; tmpPtr1 != VolEnd;) |
||
104 | { |
||
105 | *tmpPtr2++ = *tmpPtr1++; |
||
106 | } |
||
107 | |||
108 | *tmpPtr2 = '\0'; |
||
109 | |||
110 | return (unsigned short) strlen(VolumeName); |
||
111 | } |
||
112 | |||
113 | |||
114 | |||
115 | /***********************************/ |
||
116 | /* Function FindNewExtractFolder() */ |
||
117 | /***********************************/ |
||
118 | |||
119 | char *FindNewExtractFolder(char *ExtractPath, Boolean uniqueFolder) |
||
120 | { |
||
121 | char buffer[NAME_MAX], *tmpPtr, *namePtr; |
||
122 | char *last_dotpos = ExtractPath; |
||
123 | short count = 0, folderCount = 0; |
||
124 | OSErr err; |
||
125 | FSSpec Spec; |
||
126 | long theDirID; |
||
127 | Boolean isDirectory; |
||
128 | unsigned short namelen, pathlen = strlen(ExtractPath); |
||
129 | unsigned long ext_length = 0; |
||
130 | unsigned long num_to_cut = 0; |
||
131 | long firstpart_length = pathlen; |
||
132 | |||
133 | AssertStr(ExtractPath,"FindNewExtractFolder ExtractPath == NULL") |
||
134 | |||
135 | for (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++) |
||
136 | if (*tmpPtr == ':') |
||
137 | { |
||
138 | folderCount++; |
||
139 | namePtr = tmpPtr; |
||
140 | } |
||
141 | |||
142 | if (folderCount > 1) { |
||
143 | namelen = strlen(namePtr); |
||
144 | } else { |
||
145 | namelen = strlen(ExtractPath); |
||
146 | } |
||
147 | |||
148 | if (uniqueFolder) { |
||
149 | for (count = 0; count < 99; count++) |
||
150 | { |
||
151 | memset(buffer,0,sizeof(buffer)); |
||
152 | |||
153 | if (namelen >= 28) |
||
154 | ExtractPath[pathlen-2] = 0x0; |
||
155 | else |
||
156 | ExtractPath[pathlen-1] = 0x0; |
||
157 | |||
158 | sprintf(buffer,"%s%d",ExtractPath,count); |
||
159 | GetCompletePath(ExtractPath, buffer, &Spec,&err); |
||
160 | err = FSpGetDirectoryID(&Spec, &theDirID, &isDirectory); |
||
161 | if (err == -43) break; |
||
162 | } |
||
163 | } else { |
||
164 | /* Look for the last extension pos */ |
||
165 | for (tmpPtr = ExtractPath; *tmpPtr; tmpPtr++) |
||
166 | if (*tmpPtr == '.') last_dotpos = tmpPtr; |
||
167 | |||
168 | ext_length = strlen(last_dotpos); |
||
169 | |||
170 | if (ext_length < 6) { /* up to 5 chars are treated as a */ |
||
171 | /* normal extension like ".html" or ".class" */ |
||
172 | int nameLength = last_dotpos - ExtractPath; |
||
173 | if (nameLength > 1) { |
||
174 | ExtractPath[nameLength] = 0x0; |
||
175 | } else { |
||
176 | ExtractPath[pathlen-1] = 0x0; |
||
177 | } |
||
178 | } else { |
||
179 | ExtractPath[pathlen-1] = 0x0; |
||
180 | } |
||
181 | |||
182 | GetCompletePath(ExtractPath, ExtractPath, &Spec,&err); |
||
183 | } |
||
184 | |||
185 | /* Foldernames must always end with a colon */ |
||
186 | sstrcat(ExtractPath,":"); |
||
187 | return ExtractPath; |
||
188 | } |
||
189 | |||
190 | |||
191 | |||
192 | /* |
||
193 | ** creates an archive file name |
||
194 | ** |
||
195 | */ |
||
196 | |||
197 | void createArchiveName(char *thePath) |
||
198 | { |
||
199 | char *tmpPtr, *namePtr; |
||
200 | short folderCount = 0; |
||
201 | unsigned short namelen, pathlen = strlen(thePath); |
||
202 | |||
203 | if (thePath[pathlen-1] == ':') thePath[pathlen-1] = 0x0; |
||
204 | |||
205 | for (tmpPtr = thePath; *tmpPtr; tmpPtr++) |
||
206 | if (*tmpPtr == ':') |
||
207 | { |
||
208 | folderCount++; |
||
209 | namePtr = tmpPtr; |
||
210 | } |
||
211 | |||
212 | namelen = strlen(namePtr); |
||
213 | |||
214 | /* we have to eliminate illegal chars: |
||
215 | * The name space for Mac filenames and Zip filenames (unix style names) |
||
216 | * do both include all printable extended-ASCII characters. The only |
||
217 | * difference we have to take care of is the single special character |
||
218 | * used as path delimiter: |
||
219 | * ':' on MacOS and '/' on Unix and '\\' on Dos. |
||
220 | * So, to convert between Mac filenames and Unix filenames without any |
||
221 | * loss of information, we simply interchange ':' and '/'. Additionally, |
||
222 | * we try to convert the coding of the extended-ASCII characters into |
||
223 | * InfoZip's standard ISO 8859-1 codepage table. |
||
224 | */ |
||
225 | MakeCompatibleString(namePtr, '/', '_', '.', '-', -1); |
||
226 | |||
227 | /* Avoid filenames like: "Archive..zip" */ |
||
228 | if (thePath[pathlen-1] == '.') |
||
229 | { |
||
230 | thePath[pathlen-1] = 0; |
||
231 | } |
||
232 | |||
233 | if (folderCount >= 1) |
||
234 | { /* path contains at least one folder */ |
||
235 | |||
236 | if (namelen >= 28) |
||
237 | { |
||
238 | pathlen = pathlen-4; |
||
239 | } |
||
240 | |||
241 | thePath[pathlen] = '.'; |
||
242 | thePath[pathlen+1] = 'z'; |
||
243 | thePath[pathlen+2] = 'i'; |
||
244 | thePath[pathlen+3] = 'p'; |
||
245 | thePath[pathlen+4] = 0x0; |
||
246 | return; |
||
247 | } |
||
248 | else |
||
249 | { /* path contains no folder */ |
||
250 | FindDesktopFolder(thePath); |
||
251 | createArchiveName(thePath); |
||
252 | } |
||
253 | } |
||
254 | |||
255 | |||
256 | |||
257 | /* |
||
258 | ** finds the desktop-folder on a volume with |
||
259 | ** largest amount of free-space. |
||
260 | */ |
||
261 | |||
262 | void FindDesktopFolder(char *Path) |
||
263 | { |
||
264 | char buffer[255]; |
||
265 | FSSpec volumes[50]; /* 50 Volumes should be enough */ |
||
266 | short actVolCount, volIndex = 1, VolCount = 0; |
||
267 | OSErr err; |
||
268 | short i, foundVRefNum; |
||
269 | FSSpec spec; |
||
270 | UInt64 freeBytes; |
||
271 | UInt64 totalBytes; |
||
272 | UInt64 MaxFreeBytes; |
||
273 | |||
274 | err = OnLine(volumes, 50, &actVolCount, &volIndex); |
||
275 | printerr("OnLine:", (err != -35) && (err != 0), err, __LINE__, __FILE__, ""); |
||
276 | |||
277 | MaxFreeBytes = 0; |
||
278 | |||
279 | for (i=0; i < actVolCount; i++) |
||
280 | { |
||
281 | XGetVInfo(volumes[i].vRefNum, |
||
282 | volumes[i].name, |
||
283 | &volumes[i].vRefNum, |
||
284 | &freeBytes, |
||
285 | &totalBytes); |
||
286 | |||
287 | if (MaxFreeBytes < freeBytes) { |
||
288 | MaxFreeBytes = freeBytes; |
||
289 | foundVRefNum = volumes[i].vRefNum; |
||
290 | } |
||
291 | |||
292 | if ((freeBytes == 0) && (MaxFreeBytes < freeBytes)) { |
||
293 | MaxFreeBytes = freeBytes; |
||
294 | foundVRefNum = volumes[i].vRefNum; |
||
295 | } |
||
296 | |||
297 | } |
||
298 | |||
299 | FSpFindFolder(foundVRefNum, kDesktopFolderType, |
||
300 | kDontCreateFolder,&spec); |
||
301 | |||
302 | GetFullPathFromSpec(buffer, &spec , &err); |
||
303 | sstrcat(buffer,Path); |
||
304 | sstrcpy(Path,buffer); |
||
305 | } |
||
306 | |||
307 | |||
308 | /* |
||
309 | ** return the path without the filename |
||
310 | ** |
||
311 | */ |
||
312 | |||
313 | char *TruncFilename(char *DirPath, const char *FilePath) |
||
314 | { |
||
315 | char *tmpPtr; |
||
316 | char *dirPtr = NULL; |
||
317 | |||
318 | AssertStr(DirPath,"TruncFilename") |
||
319 | Assert_it(Spec,"TruncFilename","") |
||
320 | |||
321 | sstrcpy(DirPath, FilePath); |
||
322 | |||
323 | for (tmpPtr = DirPath; *tmpPtr; tmpPtr++) |
||
324 | if (*tmpPtr == ':') |
||
325 | dirPtr = tmpPtr; |
||
326 | |||
327 | if (dirPtr) |
||
328 | *++dirPtr = '\0'; |
||
329 | else |
||
330 | printerr("TruncFilename: FilePath has no Folders", -1, |
||
331 | -1, __LINE__, __FILE__, FilePath); |
||
332 | |||
333 | return DirPath; |
||
334 | } |
||
335 | |||
336 | |||
337 | |||
338 | /* |
||
339 | ** return only filename |
||
340 | ** |
||
341 | */ |
||
342 | |||
343 | char *GetFilename(char *FileName, const char *FilePath) |
||
344 | { |
||
345 | const char *tmpPtr; |
||
346 | const char *dirPtr = NULL; |
||
347 | |||
348 | Assert_it(FileName,"GetFilename","") |
||
349 | Assert_it(FilePath,"GetFilename","") |
||
350 | |||
351 | for (tmpPtr = FilePath; *tmpPtr; tmpPtr++) |
||
352 | { |
||
353 | if (*tmpPtr == ':') |
||
354 | { |
||
355 | dirPtr = tmpPtr; |
||
356 | } |
||
357 | } |
||
358 | |||
359 | if (dirPtr) |
||
360 | { |
||
361 | ++dirPtr; /* jump over the ':' */ |
||
362 | } |
||
363 | else |
||
364 | { |
||
365 | return strcpy(FileName, FilePath); /* FilePath has no Folders */ |
||
366 | } |
||
367 | |||
368 | return strcpy(FileName, dirPtr); |
||
369 | } |
||
370 | |||
371 | |||
372 | |||
373 | /* |
||
374 | ** return fullpathname from folder/dir-id |
||
375 | ** |
||
376 | */ |
||
377 | |||
378 | char *GetFullPathFromID(char *CompletePath, short vRefNum, long dirID, |
||
379 | ConstStr255Param name, OSErr *err) |
||
380 | { |
||
381 | FSSpec spec; |
||
382 | |||
383 | *err = FSMakeFSSpecCompat(vRefNum, dirID, name, &spec); |
||
384 | printerr("FSMakeFSSpecCompat:", (*err != -43) && (*err != 0), *err, |
||
385 | __LINE__, __FILE__, ""); |
||
386 | if ( (*err == noErr) || (*err == fnfErr) ) |
||
387 | { |
||
388 | return GetFullPathFromSpec(CompletePath, &spec, err); |
||
389 | } |
||
390 | |||
391 | return NULL; |
||
392 | } |
||
393 | |||
394 | |||
395 | |||
396 | /* |
||
397 | ** convert real-filename to archive-filename |
||
398 | ** |
||
399 | */ |
||
400 | |||
401 | char *Real2RfDfFilen(char *RfDfFilen, const char *RealPath, |
||
402 | short CurrentFork, short MacZipMode, Boolean DataForkOnly) |
||
403 | { |
||
404 | |||
405 | AssertStr(RealPath,"Real2RfDfFilen") |
||
406 | AssertStr(RfDfFilen,"Real2RfDfFilen") |
||
407 | |||
408 | if (DataForkOnly) /* make no changes */ |
||
409 | { |
||
410 | return sstrcpy(RfDfFilen, RealPath); |
||
411 | } |
||
412 | |||
413 | switch (MacZipMode) |
||
414 | { |
||
415 | case JohnnyLee_EF: |
||
416 | { |
||
417 | sstrcpy(RfDfFilen, RealPath); |
||
418 | if (CurrentFork == DataFork) /* data-fork */ |
||
419 | return sstrcat(RfDfFilen, "d"); |
||
420 | if (CurrentFork == ResourceFork) /* resource-fork */ |
||
421 | return sstrcat(RfDfFilen, "r"); |
||
422 | break; |
||
423 | } |
||
424 | |||
425 | case NewZipMode_EF: |
||
426 | { |
||
427 | switch (CurrentFork) |
||
428 | { |
||
429 | case DataFork: |
||
430 | { |
||
431 | sstrcpy(RfDfFilen, RealPath); |
||
432 | return RfDfFilen; /* data-fork */ |
||
433 | break; |
||
434 | } |
||
435 | case ResourceFork: |
||
436 | { |
||
437 | sstrcpy(RfDfFilen, ResourceMark); |
||
438 | sstrcat(RfDfFilen, RealPath); /* resource-fork */ |
||
439 | return RfDfFilen; |
||
440 | break; |
||
441 | } |
||
442 | default: |
||
443 | { |
||
444 | printerr("Real2RfDfFilen:", -1, -1, |
||
445 | __LINE__, __FILE__, RealPath); |
||
446 | return NULL; /* function should never reach this point */ |
||
447 | } |
||
448 | } |
||
449 | break; |
||
450 | } |
||
451 | default: |
||
452 | { |
||
453 | printerr("Real2RfDfFilen:", -1, -1, __LINE__, __FILE__, RealPath); |
||
454 | return NULL; /* function should never reach this point */ |
||
455 | } |
||
456 | } |
||
457 | |||
458 | printerr("Real2RfDfFilen:", -1, -1, __LINE__, __FILE__, RealPath); |
||
459 | return NULL; /* function should never come reach this point */ |
||
460 | } |
||
461 | |||
462 | |||
463 | |||
464 | /* |
||
465 | ** convert archive-filename into a real filename |
||
466 | ** |
||
467 | */ |
||
468 | |||
469 | char *RfDfFilen2Real(char *RealFn, const char *RfDfFilen, short MacZipMode, |
||
470 | Boolean DataForkOnly, short *CurrentFork) |
||
471 | { |
||
472 | short length; |
||
473 | int result; |
||
474 | |||
475 | AssertStr(RfDfFilen,"RfDfFilen2Real") |
||
476 | |||
477 | if (DataForkOnly || |
||
478 | (MacZipMode == UnKnown_EF) || |
||
479 | (MacZipMode < JohnnyLee_EF)) |
||
480 | { |
||
481 | *CurrentFork = DataFork; |
||
482 | return sstrcpy(RealFn,RfDfFilen); |
||
483 | } |
||
484 | |||
485 | result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2); |
||
486 | if (result == 0) |
||
487 | { |
||
488 | MacZipMode = NewZipMode_EF; |
||
489 | } |
||
490 | |||
491 | switch (MacZipMode) |
||
492 | { |
||
493 | case JohnnyLee_EF: |
||
494 | { |
||
495 | sstrcpy(RealFn, RfDfFilen); |
||
496 | length = strlen(RealFn); /* determine Fork type */ |
||
497 | if (RealFn[length-1] == 'd') *CurrentFork = DataFork; |
||
498 | else *CurrentFork = ResourceFork; |
||
499 | RealFn[length-1] = '\0'; /* simply cut one char */ |
||
500 | return RealFn; |
||
501 | break; |
||
502 | } |
||
503 | |||
504 | case NewZipMode_EF: |
||
505 | { /* determine Fork type */ |
||
506 | result = strncmp(RfDfFilen, ResourceMark, sizeof(ResourceMark)-2); |
||
507 | if (result != 0) |
||
508 | { |
||
509 | *CurrentFork = DataFork; |
||
510 | sstrcpy(RealFn, RfDfFilen); |
||
511 | return RealFn; /* data-fork */ |
||
512 | } |
||
513 | else |
||
514 | { |
||
515 | *CurrentFork = ResourceFork; |
||
516 | if (strlen(RfDfFilen) > (sizeof(ResourceMark) - 1)) |
||
517 | { |
||
518 | sstrcpy(RealFn, &RfDfFilen[sizeof(ResourceMark)-1]); |
||
519 | } |
||
520 | else RealFn[0] = '\0'; |
||
521 | return RealFn; /* resource-fork */ |
||
522 | } |
||
523 | break; |
||
524 | } |
||
525 | default: |
||
526 | { |
||
527 | *CurrentFork = NoFork; |
||
528 | printerr("RfDfFilen2Real():", -1, MacZipMode, |
||
529 | __LINE__, __FILE__, RfDfFilen); |
||
530 | return NULL; /* function should never reach this point */ |
||
531 | } |
||
532 | } |
||
533 | |||
534 | printerr("RfDfFilen2Real():", -1, MacZipMode, __LINE__, __FILE__, RfDfFilen); |
||
535 | return NULL; /* function should never reach this point */ |
||
536 | } |
||
537 | |||
538 | |||
539 | |||
540 | /* |
||
541 | ** return the applications name (argv[0]) |
||
542 | ** |
||
543 | */ |
||
544 | |||
545 | char *GetAppName(void) |
||
546 | { |
||
547 | ProcessSerialNumber psn; |
||
548 | static Str255 AppName; |
||
549 | ProcessInfoRec pinfo; |
||
550 | OSErr err; |
||
551 | |||
552 | GetCurrentProcess(&psn); |
||
553 | pinfo.processName = AppName; |
||
554 | pinfo.processInfoLength = sizeof(pinfo); |
||
555 | pinfo.processAppSpec = NULL; |
||
556 | |||
557 | err = GetProcessInformation(&psn,&pinfo); |
||
558 | AppName[AppName[0]+1] = 0x00; |
||
559 | |||
560 | return (char *)&AppName[1]; |
||
561 | } |
||
562 | |||
563 | |||
564 | |||
565 | /* |
||
566 | ** return fullpathname from FSSpec |
||
567 | ** |
||
568 | */ |
||
569 | |||
570 | char *GetFullPathFromSpec(char *FullPath, FSSpec *Spec, OSErr *err) |
||
571 | { |
||
572 | Handle hFullPath; |
||
573 | short len; |
||
574 | |||
575 | Assert_it(Spec,"GetFullPathFromSpec","") |
||
576 | |||
577 | *err = FSpGetFullPath(Spec, &len, &hFullPath); |
||
578 | printerr("FSpGetFullPath:", (*err != -43) && (*err != 0), *err, |
||
579 | __LINE__, __FILE__, ""); |
||
580 | |||
581 | memmove(FullPath, (Handle) *hFullPath, len); |
||
582 | FullPath[len] = '\0'; /* make c-string */ |
||
583 | |||
584 | DisposeHandle((Handle)hFullPath); /* we don't need it any more */ |
||
585 | |||
586 | printerr("Warning path length exceeds limit: ", len >= NAME_MAX, len, |
||
587 | __LINE__, __FILE__, " chars "); |
||
588 | |||
589 | return FullPath; |
||
590 | } |
||
591 | |||
592 | |||
593 | |||
594 | |||
595 | /* |
||
596 | * This function expands a given partial path to a complete path. |
||
597 | * Path expansions are relative to the running app. |
||
598 | * This function follows the notation: |
||
599 | * 1. relative path: |
||
600 | * a: ":subfolder:filename" -> ":current folder:subfolder:filename" |
||
601 | * b: "::folder2:filename" -> folder2 is beside the current |
||
602 | * folder on the same level |
||
603 | * c: "filename" -> in current folder |
||
604 | * |
||
605 | * An absolute path will be returned. |
||
606 | |||
607 | The following characteristics of Macintosh pathnames should be noted: |
||
608 | |||
609 | A full pathname never begins with a colon, but must contain at |
||
610 | least one colon. |
||
611 | A partial pathname always begins with a colon separator except in |
||
612 | the case where the file partial pathname is a simple file or |
||
613 | directory name. |
||
614 | Single trailing separator colons in full or partial pathnames are |
||
615 | ignored except in the case of full pathnames to volumes. |
||
616 | In full pathnames to volumes, the trailing separator colon is required. |
||
617 | Consecutive separator colons can be used to ascend a level from a |
||
618 | directory to its parent directory. Two consecutive separator colons |
||
619 | will ascend one level, three consecutive separator colons will ascend |
||
620 | two levels, and so on. Ascending can only occur from a directory; |
||
621 | not a file. |
||
622 | */ |
||
623 | |||
624 | char *GetCompletePath(char *CompletePath, const char *name, FSSpec *Spec, |
||
625 | OSErr *err) |
||
626 | { |
||
627 | Boolean hasDirName = false; |
||
628 | char currentdir[NAME_MAX]; |
||
629 | char *tmpPtr; |
||
630 | unsigned short pathlen; |
||
631 | |||
632 | AssertStr(name,"GetCompletePath") |
||
633 | Assert_it(Spec,"GetCompletePath","") |
||
634 | Assert_it((CompletePath != name),"GetCompletePath","") |
||
635 | |||
636 | for (tmpPtr = name; *tmpPtr; tmpPtr++) |
||
637 | if (*tmpPtr == ':') hasDirName = true; |
||
638 | |||
639 | if (name[0] != ':') /* case c: path including volume name or only filename */ |
||
640 | { |
||
641 | if (hasDirName) |
||
642 | { /* okey, starts with volume name, so it must be a complete path */ |
||
643 | sstrcpy(CompletePath, name); |
||
644 | } |
||
645 | else |
||
646 | { /* only filename: add cwd and return */ |
||
647 | getcwd(currentdir, NAME_MAX); |
||
648 | sstrcat(currentdir, name); |
||
649 | sstrcpy(CompletePath, currentdir); |
||
650 | } |
||
651 | } |
||
652 | else if (name[1] == ':') /* it's case b: "::folder2:filename" */ |
||
653 | { |
||
654 | printerr("GetCompletePath ", -1, *err, __LINE__, __FILE__, "not implemented"); |
||
655 | /* it's not yet implemented; do we really need this case ?*/ |
||
656 | return NULL; |
||
657 | } |
||
658 | else /* it's case a: ":subfolder:filename" */ |
||
659 | { |
||
660 | getcwd(CompletePath, NAME_MAX); /* we don't need a second colon */ |
||
661 | CompletePath[strlen(CompletePath)-1] = '\0'; |
||
662 | sstrcat(CompletePath, name); |
||
663 | } |
||
664 | |||
665 | pathlen = strlen(CompletePath); |
||
666 | *err = FSpLocationFromFullPath(pathlen, CompletePath, Spec); |
||
667 | |||
668 | return CompletePath; |
||
669 | } |
||
670 | |||
671 | |||
672 | |||
673 | char *MakeFilenameShorter(const char *LongFilename) |
||
674 | { |
||
675 | static char filename[35]; /* contents should be never longer than 32 chars */ |
||
676 | static unsigned char Num = 0; /* change the number for every call */ |
||
677 | /* this var will rollover without a problem */ |
||
678 | char tempLongFilename[1024], charnum[5]; |
||
679 | char *last_dotpos = tempLongFilename; |
||
680 | unsigned long full_length = strlen(LongFilename); |
||
681 | unsigned long ext_length = 0; |
||
682 | unsigned long num_to_cut = 0; |
||
683 | long firstpart_length; |
||
684 | char *tmpPtr; |
||
685 | short MaxLength = 31; |
||
686 | |||
687 | if (full_length <= MaxLength) /* filename is not long */ |
||
688 | { |
||
689 | return strcpy(filename,LongFilename); |
||
690 | } |
||
691 | |||
692 | Num++; |
||
693 | strcpy(tempLongFilename,LongFilename); |
||
694 | |||
695 | /* Look for the last extension pos */ |
||
696 | for (tmpPtr = tempLongFilename; *tmpPtr; tmpPtr++) |
||
697 | if (*tmpPtr == '.') last_dotpos = tmpPtr; |
||
698 | |||
699 | ext_length = strlen(last_dotpos); |
||
700 | firstpart_length = last_dotpos - tempLongFilename; |
||
701 | |||
702 | if (ext_length > 6) /* up to 5 chars are treated as a */ |
||
703 | { /* normal extension like ".html" or ".class" */ |
||
704 | firstpart_length = 0; |
||
705 | } |
||
706 | |||
707 | num_to_cut = full_length - MaxLength; |
||
708 | |||
709 | /* number the files to make the names unique */ |
||
710 | sprintf(charnum,"~%x", Num); |
||
711 | num_to_cut += strlen(charnum); |
||
712 | |||
713 | if (firstpart_length == 0) |
||
714 | { |
||
715 | firstpart_length = full_length; |
||
716 | tempLongFilename[firstpart_length - num_to_cut] = 0; |
||
717 | sprintf(filename,"%s%s", tempLongFilename, charnum); |
||
718 | } |
||
719 | else |
||
720 | { |
||
721 | tempLongFilename[firstpart_length - num_to_cut] = 0; |
||
722 | sprintf(filename,"%s%s%s", tempLongFilename, charnum, last_dotpos); |
||
723 | } |
||
724 | |||
725 | return filename; |
||
726 | }=>>>>>>> |