VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/obsolete/nsFileSpecMac.cpp@ 4837

Last change on this file since 4837 was 1, checked in by vboxsync, 54 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 49.1 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38// This file is included by nsFile.cp, and includes the Macintosh-specific
39// implementations.
40
41
42#include <string.h>
43
44#include "prtypes.h"
45#include "nscore.h"
46
47#include "FullPath.h"
48#include "FileCopy.h"
49#include "MoreFilesExtras.h"
50
51#include <Aliases.h>
52#include <Folders.h>
53#include <Math64.h>
54#include <TextUtils.h>
55#include <Processes.h>
56#include <limits.h> // ULONG_MAX
57
58#include "nsFileSpec.h"
59#include "nsEscape.h"
60#include "nsXPIDLString.h"
61
62
63const unsigned char* kAliasHavenFolderName = "\pnsAliasHaven";
64
65//========================================================================================
66namespace MacFileHelpers
67//========================================================================================
68{
69 inline void PLstrcpy(Str255 dst, ConstStr255Param src)
70 {
71 memcpy(dst, src, 1 + src[0]);
72 }
73
74 void PLstrcpy(Str255 dst, const char* src, int inMaxLen=255);
75 void PLstrncpy(Str255 dst, const char* src, int inMaxLen);
76
77 void SwapSlashColon(char * s);
78 OSErr FSSpecFromUnixPath(
79 const char * unixPath,
80 FSSpec& ioSpec,
81 Boolean hexDecode,
82 Boolean resolveAlias,
83 Boolean allowPartial = false,
84 Boolean createDirs = false);
85 char* MacPathFromUnixPath(
86 const char* unixPath,
87 Boolean hexDecode);
88 char* EncodeMacPath(
89 char* inPath, // NOT const - gets clobbered
90 Boolean prependSlash,
91 Boolean doEscape );
92 OSErr FSSpecFromPathname(
93 const char* inPathNamePtr,
94 FSSpec& ioSpec,
95 Boolean inCreateDirs);
96 char* PathNameFromFSSpec(
97 const FSSpec& inSpec );
98 OSErr CreateFolderInFolder(
99 short refNum, // Parent directory/volume
100 long dirID,
101 ConstStr255Param folderName, // Name of the new folder
102 short& outRefNum, // Volume of the created folder
103 long& outDirID); //
104
105 // Some routines to support an "alias haven" directory. Aliases in this directory
106 // are never resolved. There is a ResolveAlias here that respects that. This is
107 // to support attaching of aliases in mail.
108 void EnsureAliasHaven();
109 void SetNoResolve(Boolean inResolve);
110 PRBool IsAliasSafe(const FSSpec& inSpec);
111 OSErr MakeAliasSafe(FSSpec& inOutSpec);
112 OSErr ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased);
113
114 Boolean sNoResolve = false;
115 long sAliasHavenDirID = 0;
116 short sAliasHavenVRefNum = 0;
117} // namespace MacFileHelpers
118
119//----------------------------------------------------------------------------------------
120void MacFileHelpers::PLstrcpy(Str255 dst, const char* src, int inMax)
121//----------------------------------------------------------------------------------------
122{
123 int srcLength = strlen(src);
124 NS_ASSERTION(srcLength <= inMax, "Oops, string is too long!");
125 if (srcLength > inMax)
126 srcLength = inMax;
127 dst[0] = srcLength;
128 memcpy(&dst[1], src, srcLength);
129}
130
131//----------------------------------------------------------------------------------------
132void MacFileHelpers::PLstrncpy(Str255 dst, const char* src, int inMax)
133//----------------------------------------------------------------------------------------
134{
135 int srcLength = strlen(src);
136 if (srcLength > inMax)
137 srcLength = inMax;
138 dst[0] = srcLength;
139 memcpy(&dst[1], src, srcLength);
140}
141
142//-----------------------------------
143void MacFileHelpers::SwapSlashColon(char * s)
144//-----------------------------------
145
146{
147 while (*s)
148 {
149 if (*s == '/')
150 *s++ = ':';
151 else if (*s == ':')
152 *s++ = '/';
153 else
154 *s++;
155 }
156} // MacFileHelpers::SwapSlashColon
157
158//-----------------------------------
159char* MacFileHelpers::EncodeMacPath(
160 char* inPath, // NOT const, gets clobbered
161 Boolean prependSlash,
162 Boolean doEscape )
163// Transforms Macintosh style path into Unix one
164// Method: Swap ':' and '/', hex escape the result
165//-----------------------------------
166{
167 if (inPath == nsnull)
168 return nsnull;
169 int pathSize = strlen(inPath);
170
171 // XP code sometimes chokes if there's a final slash in the unix path.
172 // Since correct mac paths to folders and volumes will end in ':', strip this
173 // first.
174 char* c = inPath + pathSize - 1;
175 if (*c == ':')
176 {
177 *c = 0;
178 pathSize--;
179 }
180
181 char * newPath = nsnull;
182 char * finalPath = nsnull;
183
184 if (prependSlash)
185 {
186 newPath = new char[pathSize + 2];
187 newPath[0] = ':'; // It will be converted to '/'
188 memcpy(&newPath[1], inPath, pathSize + 1);
189 }
190 else
191 {
192 newPath = new char[pathSize + 1];
193 strcpy(newPath, inPath);
194 }
195 if (newPath)
196 {
197 SwapSlashColon( newPath );
198 if (doEscape)
199 {
200 finalPath = nsEscape(newPath, url_Path);
201 delete [] newPath;
202 }
203 else
204 finalPath = newPath;
205 }
206 delete [] inPath;
207 return finalPath;
208} // MacFileHelpers::EncodeMacPath
209
210//----------------------------------------------------------------------------------------
211inline void MacFileHelpers::SetNoResolve(Boolean inResolve)
212//----------------------------------------------------------------------------------------
213{
214 sNoResolve = inResolve;
215} // MacFileHelpers::SetNoResolve
216
217//----------------------------------------------------------------------------------------
218OSErr MacFileHelpers::MakeAliasSafe(FSSpec& inOutSpec)
219// Pass in the spec of an alias. This copies the file to the safe haven folder, and
220// returns the spec of the copy to the caller
221//----------------------------------------------------------------------------------------
222{
223 EnsureAliasHaven();
224 nsFileSpec dstDirSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\p");
225
226 // Make sure its name is unique
227 nsFileSpec havenSpec(sAliasHavenVRefNum, sAliasHavenDirID, "\pG'day");
228 if (havenSpec.Valid())
229 havenSpec.MakeUnique(inOutSpec.name);
230 // Copy the file into the haven directory
231 if (havenSpec.Valid())
232 {
233 OSErr err = ::FSpFileCopy(
234 &inOutSpec,
235 dstDirSpec,
236 havenSpec.GetLeafPName(),
237 nil, 0, true);
238 // Return the spec of the copy to the caller.
239 if (err != noErr)
240 return err;
241 inOutSpec = havenSpec;
242 }
243 return noErr;
244} // MacFileHelpers::MakeAliasSafe
245
246//----------------------------------------------------------------------------------------
247char* MacFileHelpers::MacPathFromUnixPath(const char* unixPath, Boolean hexDecode)
248//----------------------------------------------------------------------------------------
249{
250 // Relying on the fact that the unix path is always longer than the mac path:
251 size_t len = strlen(unixPath);
252 char* result = new char[len + 2]; // ... but allow for the initial colon in a partial name
253 // REMEMBER: at the end we call SwapSlashColon, so bear that in mind when you see
254 // this code using '/' as a separator in what is supposed to be a Macintosh path!
255 if (result)
256 {
257 char* dst = result;
258 const char* src = unixPath;
259 if (*src == '/') // * full path
260 src++;
261 else if (strchr(src, '/') && *src != '.')
262 {
263 // * partial path, and not just a leaf name. The '.' test is there because
264 // the loop below will add sufficient colons in that case.
265 *dst++ = '/';
266 }
267 // Copy src to dst, but watch out for .. and .
268 char c = '/';
269 do
270 {
271 char cprev = c; // remember the previous char (initially /)
272 c = *src++;
273 if (c == '.' && cprev == '/')
274 {
275 char* dstSaved = dst;
276 // Special cases: "." and "..". Convert to ':' and '::'
277 *dst++ = '/'; // . becomes :
278 c = *src++;
279 if (c == '.')
280 {
281 *dst++ = '/'; // .. becomes ::
282 c = *src++;
283 }
284 if (c == '/')
285 {
286 // ../ becomes :: so just skip the slash
287 // ./ becomes : " " " " "
288 src++;
289 }
290 else if (c)
291 {
292 // Oh. A file called ".foo" or "..foo"
293 // Back up and just do the normal thing.
294 src -= (dst - dstSaved);
295 dst = dstSaved;
296 // Since c is not '/', we won't do this stuff on the
297 // next iteration.
298 }
299 continue;
300 }
301 else if (c == '/' && cprev == '/')
302 {
303 // Hmm. A 'run on' path with two slashes right next to each other.
304 // This is an illegal path, but, hey, we'll be tough and try to
305 // deal with it (especially since '::' has loaded semantics in
306 // a Mac path)
307 continue;
308 }
309 *dst++ = c;
310 } while (c);
311 if (hexDecode)
312 nsUnescape(result); // Hex Decode
313 MacFileHelpers::SwapSlashColon(result);
314 }
315 return result;
316} // MacFileHelpers::MacPathFromUnixPath
317
318//----------------------------------------------------------------------------------------
319OSErr MacFileHelpers::FSSpecFromPathname(
320 const char* inPathNamePtr,
321 FSSpec& ioSpec, // used as in-parameter for a relative path.
322 Boolean inCreateDirs)
323// FSSpecFromPathname reverses PathNameFromFSSpec.
324// It returns a FSSpec given a c string which is a mac pathname.
325//----------------------------------------------------------------------------------------
326{
327 OSErr err;
328 // Simplify this routine to use FSMakeFSSpec if length < 255. Otherwise use the MoreFiles
329 // routine FSpLocationFromFullPath, which allocates memory, to handle longer pathnames.
330
331 short inVRefNum = ioSpec.vRefNum;
332 long inParID = ioSpec.parID;
333
334 size_t inLength = strlen(inPathNamePtr);
335 bool isRelative = (strchr(inPathNamePtr, ':') == 0 || *inPathNamePtr == ':');
336#ifdef NS_DEBUG
337 // Attempt to catch people sending unix paths in to routines that expect native ones.
338 NS_ASSERTION(strchr(inPathNamePtr, '/') == 0,
339 "Possible unix path where native path is required");
340#endif
341 if (inLength < 255)
342 {
343 Str255 pascalpath;
344 MacFileHelpers::PLstrcpy(pascalpath, inPathNamePtr);
345 if (isRelative)
346 err = ::FSMakeFSSpec(inVRefNum, inParID, pascalpath, &ioSpec);
347 else
348 err = ::FSMakeFSSpec(0, 0, pascalpath, &ioSpec);
349 }
350 else if (!isRelative)
351 err = FSpLocationFromFullPath(inLength, inPathNamePtr, &ioSpec);
352 else
353 err = bdNamErr;
354
355 if ((err == dirNFErr || err == bdNamErr) && inCreateDirs)
356 {
357 const char* path = inPathNamePtr;
358 if (isRelative)
359 {
360 ioSpec.vRefNum = inVRefNum;
361 ioSpec.parID = inParID;
362 }
363 else
364 {
365 ioSpec.vRefNum = 0;
366 ioSpec.parID = 0;
367 }
368 do {
369 // Locate the colon that terminates the node.
370 // But if we've a partial path (starting with a colon), find the second one.
371 const char* nextColon = strchr(path + (*path == ':'), ':');
372 // Well, if there are no more colons, point to the end of the string.
373 if (!nextColon)
374 nextColon = path + strlen(path);
375
376 // Make a pascal string out of this node. Include initial
377 // and final colon, if any!
378 Str255 ppath;
379 MacFileHelpers::PLstrncpy(ppath, path, nextColon - path + 1);
380
381 // Use this string as a relative path using the directory created
382 // on the previous round (or directory 0,0 on the first round).
383 err = ::FSMakeFSSpec(ioSpec.vRefNum, ioSpec.parID, ppath, &ioSpec);
384
385 // If this was the leaf node, then we are done.
386 if (!*nextColon)
387 break;
388
389 // Since there's more to go, we have to get the directory ID, which becomes
390 // the parID for the next round.
391 if (err == noErr)
392 {
393 // The directory (or perhaps a file) exists. Find its dirID.
394 long dirID;
395 Boolean isDirectory;
396 err = ::FSpGetDirectoryID(&ioSpec, &dirID, &isDirectory);
397 if (!isDirectory)
398 return dupFNErr; // oops! a file exists with that name.
399 if (err)
400 return err;
401 ioSpec.parID = dirID;
402 }
403 else if (err == fnfErr)
404 {
405 // If we got "file not found", then
406 // we need to create a directory.
407 err = ::FSpDirCreate(&ioSpec, smCurrentScript, &ioSpec.parID);
408 // For some reason, this usually returns fnfErr, even though it works.
409 if (err == fnfErr)
410 err = noErr;
411 }
412 if (err != noErr)
413 return err;
414 path = nextColon; // next round
415 } while (1);
416 }
417 return err;
418} // MacFileHelpers::FSSpecFromPathname
419
420//----------------------------------------------------------------------------------------
421OSErr MacFileHelpers::CreateFolderInFolder(
422 short refNum, // Parent directory/volume
423 long dirID,
424 ConstStr255Param folderName, // Name of the new folder
425 short& outRefNum, // Volume of the created folder
426 long& outDirID) //
427// Creates a folder named 'folderName' inside a folder.
428// The errors returned are same as PBDirCreate
429//----------------------------------------------------------------------------------------
430{
431 HFileParam hpb;
432 hpb.ioVRefNum = refNum;
433 hpb.ioDirID = dirID;
434 hpb.ioNamePtr = (StringPtr)&folderName;
435
436 OSErr err = PBDirCreateSync((HParmBlkPtr)&hpb);
437 if (err == noErr)
438 {
439 outRefNum = hpb.ioVRefNum;
440 outDirID = hpb.ioDirID;
441 }
442 else
443 {
444 outRefNum = 0;
445 outDirID = 0;
446 }
447 return err;
448} // MacFileHelpers::CreateFolderInFolder
449
450//----------------------------------------------------------------------------------------
451void MacFileHelpers::EnsureAliasHaven()
452//----------------------------------------------------------------------------------------
453{
454 // Alias Haven is a directory in which we never resolve aliases.
455 if (sAliasHavenVRefNum != 0)
456 return;
457
458
459 FSSpec temp;
460 if (FindFolder(0, kTemporaryFolderType, true, & temp.vRefNum, &temp.parID) == noErr)
461 {
462 CreateFolderInFolder(
463 temp.vRefNum, // Parent directory/volume
464 temp.parID,
465 kAliasHavenFolderName, // Name of the new folder
466 sAliasHavenVRefNum, // Volume of the created folder
467 sAliasHavenDirID);
468 }
469} // MacFileHelpers::EnsureAliasHaven
470
471//----------------------------------------------------------------------------------------
472PRBool MacFileHelpers::IsAliasSafe(const FSSpec& inSpec)
473// Returns true if the alias is in the alias haven directory, or if alias resolution
474// has been turned off.
475//----------------------------------------------------------------------------------------
476{
477 return sNoResolve
478 || (inSpec.parID == sAliasHavenDirID && inSpec.vRefNum == sAliasHavenVRefNum);
479} // MacFileHelpers::IsAliasSafe
480
481//----------------------------------------------------------------------------------------
482OSErr MacFileHelpers::ResolveAliasFile(FSSpec& inOutSpec, Boolean& wasAliased)
483//----------------------------------------------------------------------------------------
484{
485 wasAliased = false;
486 if (IsAliasSafe(inOutSpec))
487 return noErr;
488 Boolean dummy;
489 return ::ResolveAliasFile(&inOutSpec, TRUE, &dummy, &wasAliased);
490} // MacFileHelpers::ResolveAliasFile
491
492//-----------------------------------
493OSErr MacFileHelpers::FSSpecFromUnixPath(
494 const char * unixPath,
495 FSSpec& ioSpec,
496 Boolean hexDecode,
497 Boolean resolveAlias,
498 Boolean allowPartial,
499 Boolean createDirs)
500// File spec from URL. Reverses GetURLFromFileSpec
501// Its input is only the <path> part of the URL
502// JRM 97/01/08 changed this so that if it's a partial path (doesn't start with '/'),
503// then it is combined with inOutSpec's vRefNum and parID to form a new spec.
504//-----------------------------------
505{
506 if (unixPath == nsnull)
507 return badFidErr;
508 char* macPath = MacPathFromUnixPath(unixPath, hexDecode);
509 if (!macPath)
510 return memFullErr;
511
512 OSErr err = noErr;
513 if (!allowPartial)
514 {
515 NS_ASSERTION(*unixPath == '/' /*full path*/, "Not a full Unix path!");
516 }
517 err = FSSpecFromPathname(macPath, ioSpec, createDirs);
518 if (err == fnfErr)
519 err = noErr;
520 Boolean dummy;
521 if (err == noErr && resolveAlias) // Added
522 err = MacFileHelpers::ResolveAliasFile(ioSpec, dummy);
523 delete [] macPath;
524 NS_ASSERTION(err==noErr||err==fnfErr||err==dirNFErr||err==nsvErr, "Not a path!");
525 return err;
526} // MacFileHelpers::FSSpecFromLocalUnixPath
527
528//-----------------------------------
529char* MacFileHelpers::PathNameFromFSSpec( const FSSpec& inSpec )
530// Returns a full pathname to the given file
531// Returned value is allocated with new [], and must be freed with delete []
532// For consistency and to work under OS X this creates an nsILocalFileMac and has it do the work.
533//-----------------------------------
534{
535 char* result = nil;
536 nsresult rv;
537
538 FSSpec nonConstSpec = inSpec;
539 nsCAutoString path;
540 nsCOMPtr<nsILocalFileMac> macFile;
541
542 rv = NS_NewLocalFileWithFSSpec(&nonConstSpec, PR_TRUE, getter_AddRefs(macFile));
543 if (NS_FAILED(rv)) return nsnull;
544 nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(macFile, &rv));
545 if (NS_FAILED(rv)) return nsnull;
546 rv = localFile->GetNativePath(path);
547 if (NS_FAILED(rv)) return nsnull;
548 PRInt32 strLen = path.Length();
549 result = new char [strLen + 1];
550 if (!result) return nsnull;
551 memcpy(result, path.get(), strLen);
552 result[ strLen ] = 0;
553
554 return result;
555} // MacFileHelpers::PathNameFromFSSpec
556
557
558#pragma mark -
559
560//========================================================================================
561// Macintosh nsFileSpec implementation
562//========================================================================================
563
564//----------------------------------------------------------------------------------------
565nsFileSpec::nsFileSpec()
566//----------------------------------------------------------------------------------------
567{
568// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
569 Clear();
570}
571
572//----------------------------------------------------------------------------------------
573nsFileSpec::nsFileSpec(const FSSpec& inSpec, PRBool resolveAlias)
574//----------------------------------------------------------------------------------------
575: mSpec(inSpec)
576, mError(NS_OK)
577{
578// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
579 if (resolveAlias)
580 {
581 PRBool dummy;
582 ResolveSymlink(dummy);
583 }
584}
585
586//----------------------------------------------------------------------------------------
587void nsFileSpec::operator = (const FSSpec& inSpec)
588//----------------------------------------------------------------------------------------
589{
590 mSpec = inSpec;
591 mError = NS_OK;
592}
593
594//----------------------------------------------------------------------------------------
595nsFileSpec::nsFileSpec(const nsFileSpec& inSpec)
596//----------------------------------------------------------------------------------------
597: mSpec(inSpec.mSpec)
598, mError(inSpec.Error())
599{
600// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
601}
602
603//----------------------------------------------------------------------------------------
604nsFileSpec::nsFileSpec(const char* inNativePathString, PRBool inCreateDirs)
605//----------------------------------------------------------------------------------------
606{
607// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
608 Clear(); // this sets mError to NS_ERROR_NOT_INITIALIZED
609
610 if (inNativePathString)
611 {
612 mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname(
613 inNativePathString, mSpec, inCreateDirs));
614 if (mError == NS_FILE_RESULT(fnfErr))
615 mError = NS_OK;
616 }
617
618} // nsFileSpec::nsFileSpec
619
620//----------------------------------------------------------------------------------------
621nsFileSpec::nsFileSpec(const nsString& inNativePathString, PRBool inCreateDirs)
622//----------------------------------------------------------------------------------------
623{
624// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
625 Clear(); // this sets mError to NS_ERROR_NOT_INITIALIZED
626
627 mError = NS_FILE_RESULT(
628 MacFileHelpers::FSSpecFromPathname(
629 NS_LossyConvertUCS2toASCII(inNativePathString).get(),
630 mSpec, inCreateDirs));
631 if (mError == NS_FILE_RESULT(fnfErr))
632 mError = NS_OK;
633
634} // nsFileSpec::nsFileSpec
635
636//----------------------------------------------------------------------------------------
637nsFileSpec::nsFileSpec(short vRefNum, long parID, ConstStr255Param fileName, PRBool resolveAlias)
638//----------------------------------------------------------------------------------------
639{
640// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
641 mError = NS_FILE_RESULT(::FSMakeFSSpec(vRefNum, parID, fileName, &mSpec));
642 if (mError == NS_FILE_RESULT(fnfErr))
643 mError = NS_OK;
644
645 if (resolveAlias)
646 {
647 PRBool dummy;
648 ResolveSymlink(dummy);
649 }
650}
651
652//----------------------------------------------------------------------------------------
653nsFileSpec::nsFileSpec(const nsFilePath& inPath)
654//----------------------------------------------------------------------------------------
655{
656// NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
657 *this = inPath.GetFileSpec();
658}
659
660//----------------------------------------------------------------------------------------
661void nsFileSpec::operator = (const char* inString)
662//----------------------------------------------------------------------------------------
663{
664 Clear(); // this sets mError to NS_ERROR_NOT_INITIALIZED
665
666 if (inString)
667 {
668 mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname(inString, mSpec, true));
669 if (mError == NS_FILE_RESULT(fnfErr))
670 mError = NS_OK;
671 }
672
673} // nsFileSpec::operator =
674
675//----------------------------------------------------------------------------------------
676void nsFileSpec::operator = (const nsFileSpec& inSpec)
677//----------------------------------------------------------------------------------------
678{
679 mPath.SetToEmpty();
680 mSpec.vRefNum = inSpec.mSpec.vRefNum;
681 mSpec.parID = inSpec.mSpec.parID;
682
683 PRInt32 copySize = inSpec.mSpec.name[0] + 1;
684 if (copySize > sizeof(inSpec.mSpec.name))
685 copySize = sizeof(inSpec.mSpec.name);
686 memcpy(mSpec.name, inSpec.mSpec.name, copySize);
687 mError = inSpec.Error(); // note that the error is propagated
688} // nsFileSpec::operator =
689
690//----------------------------------------------------------------------------------------
691void nsFileSpec::operator = (const nsFilePath& inPath)
692//----------------------------------------------------------------------------------------
693{
694 *this = inPath.GetFileSpec();
695} // nsFileSpec::operator =
696
697//----------------------------------------------------------------------------------------
698inline void nsFileSpec::Clear()
699//----------------------------------------------------------------------------------------
700{
701 mPath.SetToEmpty();
702 mSpec.vRefNum = 0;
703 mSpec.parID = 0;
704 mSpec.name[0] = 0;
705 mError = NS_ERROR_NOT_INITIALIZED;
706}
707
708//----------------------------------------------------------------------------------------
709PRBool nsFileSpec::Exists() const
710//----------------------------------------------------------------------------------------
711{
712 if (NS_FAILED(mError)) return PR_FALSE;
713 FSSpec temp;
714 return ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, mSpec.name, &temp) == noErr;
715} // nsFileSpec::Exists()
716
717//----------------------------------------------------------------------------------------
718void nsFileSpec::GetModDate(TimeStamp& outStamp) const
719//----------------------------------------------------------------------------------------
720{
721 CInfoPBRec pb;
722 if (GetCatInfo(pb) == noErr)
723 outStamp = ((DirInfo*)&pb)->ioDrMdDat; // The mod date is in the same spot for files and dirs.
724 else
725 outStamp = 0;
726} // nsFileSpec::GetModDate
727
728//----------------------------------------------------------------------------------------
729PRUint32 nsFileSpec::GetFileSize() const
730//----------------------------------------------------------------------------------------
731{
732 CInfoPBRec pb;
733 if (noErr == GetCatInfo(pb))
734 return (PRUint32)((HFileInfo*)&pb)->ioFlLgLen;
735 return 0;
736} // nsFileSpec::GetFileSize
737
738//----------------------------------------------------------------------------------------
739void nsFileSpec::SetLeafName(const char* inLeafName)
740// In leaf name can actually be a partial path...
741//----------------------------------------------------------------------------------------
742{
743 NS_ASSERTION(inLeafName, "Attempt to set leaf name with a null string");
744
745 mPath.SetToEmpty();
746
747 if (inLeafName)
748 {
749 // what about long relative paths? Hmm? We don't have a routine for this anywhere.
750 Str255 partialPath;
751 MacFileHelpers::PLstrcpy(partialPath, inLeafName);
752 mError = NS_FILE_RESULT(
753 ::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, partialPath, &mSpec));
754 if (mError == NS_FILE_RESULT(fnfErr))
755 mError = NS_OK;
756 }
757
758} // nsFileSpec::SetLeafName
759
760//----------------------------------------------------------------------------------------
761char* nsFileSpec::GetLeafName() const
762// Result needs to be nsCRT::free()ed.
763//----------------------------------------------------------------------------------------
764{
765 char leaf[sizeof(mSpec.name)];
766 memcpy(leaf, &mSpec.name[1], mSpec.name[0]);
767 leaf[mSpec.name[0]] = '\0';
768 return nsCRT::strdup(leaf);
769} // nsFileSpec::GetLeafName
770
771//----------------------------------------------------------------------------------------
772void nsFileSpec::MakeAliasSafe()
773//----------------------------------------------------------------------------------------
774{
775 mPath.SetToEmpty();
776 mError = NS_FILE_RESULT(MacFileHelpers::MakeAliasSafe(mSpec));
777} // nsFileSpec::MakeAliasSafe
778
779//----------------------------------------------------------------------------------------
780void nsFileSpec::MakeUnique(ConstStr255Param inSuggestedLeafName)
781//----------------------------------------------------------------------------------------
782{
783 mPath.SetToEmpty();
784 if (inSuggestedLeafName[0] > 0)
785 MacFileHelpers::PLstrcpy(mSpec.name, inSuggestedLeafName);
786
787 MakeUnique();
788} // nsFileSpec::MakeUnique
789
790//----------------------------------------------------------------------------------------
791PRBool nsFileSpec::IsFile() const
792//----------------------------------------------------------------------------------------
793{
794 long dirID;
795 Boolean isDirectory;
796 return (noErr == ::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && !isDirectory);
797} // nsFileSpec::IsFile
798
799//----------------------------------------------------------------------------------------
800PRBool nsFileSpec::IsDirectory() const
801//----------------------------------------------------------------------------------------
802{
803 long dirID;
804 Boolean isDirectory;
805 return (noErr == ::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory) && isDirectory);
806} // nsFileSpec::IsDirectory
807
808//----------------------------------------------------------------------------------------
809PRBool nsFileSpec::IsHidden() const
810//----------------------------------------------------------------------------------------
811{
812 CInfoPBRec cInfo;
813 PRBool hidden = PR_FALSE;
814
815 if (noErr == GetCatInfo(cInfo))
816 if (cInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsInvisible)
817 hidden = PR_TRUE;
818
819 return hidden;
820} // nsFileSpec::IsHidden
821
822//----------------------------------------------------------------------------------------
823PRBool nsFileSpec::IsSymlink() const
824//----------------------------------------------------------------------------------------
825{
826 CInfoPBRec cInfo;
827 PRBool hidden = PR_FALSE;
828
829 if (noErr == GetCatInfo(cInfo))
830 if (cInfo.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias)
831 hidden = PR_TRUE;
832
833 return hidden;
834} // nsFileSpec::IsSymlink
835
836//----------------------------------------------------------------------------------------
837nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased)
838//----------------------------------------------------------------------------------------
839{
840 Boolean wasAliased2; // Type conversion Boolean <--> PRBool
841 OSErr err = MacFileHelpers::ResolveAliasFile(mSpec, wasAliased2);
842 if (wasAliased2)
843 {
844 mError = NS_FILE_RESULT(err);
845 wasAliased = PR_TRUE;
846 }
847 else
848 wasAliased = PR_FALSE;
849
850 return mError;
851} // nsFileSpec::ResolveSymlink
852
853//----------------------------------------------------------------------------------------
854void nsFileSpec::GetParent(nsFileSpec& outSpec) const
855//----------------------------------------------------------------------------------------
856{
857 if (NS_SUCCEEDED(mError))
858 outSpec.mError = NS_FILE_RESULT(::FSMakeFSSpec(mSpec.vRefNum, mSpec.parID, nsnull, outSpec));
859} // nsFileSpec::GetParent
860
861//----------------------------------------------------------------------------------------
862void nsFileSpec::operator += (const char* inRelativePath)
863//----------------------------------------------------------------------------------------
864{
865 NS_ASSERTION(inRelativePath, "Attempt to append relative path with null path");
866
867 // Invalidate the path cache string, since we're changing ourselves.
868 mPath.SetToEmpty();
869
870 // if we are already bad, don't allow appendage
871 if (NS_FAILED(Error()))
872 {
873 NS_WARNING("trying to append to a bad nsFileSpec");
874 return;
875 }
876
877 // Find the dirID of the directory described by this spec
878 long dirID;
879 Boolean isDirectory;
880 mError = NS_FILE_RESULT(::FSpGetDirectoryID(&mSpec, &dirID, &isDirectory));
881 if (NS_FAILED(mError) || !isDirectory || !inRelativePath)
882 return;
883 // mSpec.vRefNum is already correct.
884 mSpec.parID = dirID;
885
886 // Next, determine if it is a UNIX or Mac style path. Now, Macintosh relative paths
887 // are either leaf names (in which the distinction between unix and macintosh
888 // relative paths disappears) or they start with a colon. If we find an initial colon,
889 // then assume it's a macintosh path.
890 // If it is a UNIX path (including just a leaf name), we will also look for ':' and
891 // assert if we find one.
892 if (*inRelativePath != ':')
893 {
894 // Looks like a UNIX path (including possibly just a leaf name)
895 NS_ASSERTION(strchr(inRelativePath, ':') == nsnull, "Can not determine path type");
896 // Convert unix path (which is unencoded) to a spec
897 mError = NS_FILE_RESULT(
898 MacFileHelpers::FSSpecFromUnixPath(inRelativePath, mSpec, false, false, true, true));
899 }
900 else
901 {
902 // We must be a mac path!
903 mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromPathname(inRelativePath, mSpec, true));
904 }
905 if (mError == NS_FILE_RESULT(fnfErr))
906 mError = NS_OK;
907
908} // nsFileSpec::operator +=
909
910//----------------------------------------------------------------------------------------
911void nsFileSpec::CreateDirectory(int /* unix mode */)
912//----------------------------------------------------------------------------------------
913{
914 long ignoredDirID;
915 OSErr err = ::FSpDirCreate(&mSpec, smCurrentScript, &ignoredDirID);
916 // it's OK if the dir already exists
917 if (err != noErr && IsDirectory())
918 err = noErr;
919
920 mError = NS_FILE_RESULT(err);
921
922} // nsFileSpec::CreateDirectory
923
924//----------------------------------------------------------------------------------------
925void nsFileSpec::Delete(PRBool inRecursive) const
926//----------------------------------------------------------------------------------------
927{
928 OSErr anErr;
929
930 nsresult& mutableError = const_cast<nsFileSpec*>(this)->mError;
931 if (inRecursive)
932 {
933 // MoreFilesExtras
934 anErr = ::DeleteDirectory(
935 mSpec.vRefNum,
936 mSpec.parID,
937 const_cast<unsigned char*>(mSpec.name));
938 }
939 else
940 anErr = ::FSpDelete(&mSpec);
941
942 if (anErr == fnfErr) // deleting a file that doesn't exist isn't an error!
943 anErr = noErr;
944
945 mutableError = NS_FILE_RESULT(anErr);
946
947} // nsFileSpec::Delete
948
949//----------------------------------------------------------------------------------------
950void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
951//----------------------------------------------------------------------------------------
952{
953 if (IsDirectory())
954 {
955 if (!(newDir.Exists()))
956 {
957 newDir.CreateDirectory();
958 }
959
960 for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
961 {
962 nsFileSpec& child = (nsFileSpec&)i;
963
964 if (child.IsDirectory())
965 {
966 nsFileSpec tmpDirSpec(newDir);
967
968 char *leafname = child.GetLeafName();
969 tmpDirSpec += leafname;
970 nsCRT::free(leafname);
971
972 child.RecursiveCopy(tmpDirSpec);
973 }
974 else
975 {
976 child.RecursiveCopy(newDir);
977 }
978 }
979 }
980 else
981 {
982 nsFileSpec& filePath = (nsFileSpec&) *this;
983
984 if (!(newDir.Exists()))
985 {
986 newDir.CreateDirectory();
987 }
988
989 filePath.CopyToDir(newDir);
990 }
991} // nsFileSpec::RecursiveCopy
992
993//----------------------------------------------------------------------------------------
994nsresult nsFileSpec::Truncate(PRInt32 aNewLength) const
995//----------------------------------------------------------------------------------------
996{
997 short refNum;
998 OSErr err;
999
1000 // First see if we have an internal error set
1001 if (NS_FAILED(mError))
1002 return mError;
1003
1004 // Need to open the file to trunc
1005 if (::FSpOpenDF(&mSpec, fsWrPerm, &refNum) != noErr)
1006 return NS_FILE_FAILURE;
1007
1008 err = ::SetEOF(refNum, aNewLength);
1009
1010 // Close the file unless we got an error that it was already closed
1011 if (err != fnOpnErr)
1012 (void)::FSClose(refNum);
1013
1014 if (err != noErr)
1015 return NS_FILE_FAILURE;
1016
1017 return NS_OK;
1018} // nsFileSpec::Truncate
1019
1020//----------------------------------------------------------------------------------------
1021nsresult nsFileSpec::Rename(const char* inNewName)
1022//----------------------------------------------------------------------------------------
1023{
1024 NS_ASSERTION(inNewName, "Attempt to rename with null new name");
1025
1026 if (strchr(inNewName, '/'))
1027 return NS_FILE_FAILURE; // no relative paths here!
1028
1029 Str255 pName;
1030 MacFileHelpers::PLstrcpy(pName, inNewName);
1031 if (::FSpRename(&mSpec, pName) != noErr)
1032 return NS_FILE_FAILURE;
1033 SetLeafName(inNewName);
1034 return NS_OK;
1035} // nsFileSpec::Rename
1036
1037//----------------------------------------------------------------------------------------
1038nsresult nsFileSpec::CopyToDir(const nsFileSpec& newParentDir) const
1039//----------------------------------------------------------------------------------------
1040{
1041 // We can only copy into a directory, and (for now) can not copy entire directories
1042
1043 if (!newParentDir.IsDirectory() || (IsDirectory() ) )
1044 return NS_FILE_FAILURE;
1045
1046 nsresult rv = NS_FILE_RESULT(::FSpFileCopy(&mSpec,
1047 &newParentDir.mSpec,
1048 const_cast<StringPtr>(GetLeafPName()),
1049 nsnull,
1050 0,
1051 true));
1052
1053 return rv;
1054
1055} // nsFileSpec::CopyToDir
1056
1057//----------------------------------------------------------------------------------------
1058nsresult nsFileSpec::MoveToDir(const nsFileSpec& newParentDir)
1059//----------------------------------------------------------------------------------------
1060{
1061 // We can only move into a directory
1062
1063 if (!newParentDir.IsDirectory())
1064 return NS_FILE_FAILURE;
1065
1066 nsresult result = NS_FILE_RESULT(::FSpMoveRenameCompat(&mSpec,
1067 &newParentDir.mSpec,
1068 const_cast<StringPtr>(GetLeafPName())));
1069
1070 if ( NS_SUCCEEDED(result) )
1071 {
1072 char* leafName = GetLeafName();
1073 *this = newParentDir + leafName;
1074 nsCRT::free(leafName);
1075 }
1076 return result;
1077} // nsFileSpec::MoveToDir
1078
1079//----------------------------------------------------------------------------------------
1080nsresult nsFileSpec::Execute(const char* /*args - how can this be cross-platform? problem! */ ) const
1081//----------------------------------------------------------------------------------------
1082{
1083 if (IsDirectory())
1084 return NS_FILE_FAILURE;
1085
1086 LaunchParamBlockRec launchThis;
1087 launchThis.launchAppSpec = const_cast<FSSpec*>(&mSpec);
1088 launchThis.launchAppParameters = nsnull; // args;
1089 /* launch the thing */
1090 launchThis.launchBlockID = extendedBlock;
1091 launchThis.launchEPBLength = extendedBlockLen;
1092 launchThis.launchFileFlags = nsnull;
1093 launchThis.launchControlFlags = launchContinue + launchNoFileFlags + launchUseMinimum;
1094 launchThis.launchControlFlags += launchDontSwitch;
1095
1096 nsresult result = NS_FILE_RESULT(::LaunchApplication(&launchThis));
1097 return result;
1098
1099} // nsFileSpec::Execute
1100
1101//----------------------------------------------------------------------------------------
1102OSErr nsFileSpec::GetCatInfo(CInfoPBRec& outInfo) const
1103//----------------------------------------------------------------------------------------
1104{
1105 DirInfo *dipb=(DirInfo *)&outInfo;
1106 dipb->ioCompletion = nsnull;
1107 dipb->ioFDirIndex = 0; // use dirID and name
1108 dipb->ioVRefNum = mSpec.vRefNum;
1109 dipb->ioDrDirID = mSpec.parID;
1110 dipb->ioNamePtr = const_cast<nsFileSpec*>(this)->mSpec.name;
1111 return PBGetCatInfoSync(&outInfo);
1112} // nsFileSpec::GetCatInfo()
1113
1114//----------------------------------------------------------------------------------------
1115OSErr nsFileSpec::SetFileTypeAndCreator(OSType type, OSType creator)
1116//----------------------------------------------------------------------------------------
1117{
1118 FInfo info;
1119 OSErr err = ::FSpGetFInfo(&mSpec, &info);
1120 if (err != noErr)
1121 return err;
1122 info.fdType = type;
1123 info.fdCreator = creator;
1124 err = ::FSpSetFInfo(&mSpec, &info);
1125 return err;
1126}
1127
1128//----------------------------------------------------------------------------------------
1129OSErr nsFileSpec::GetFileTypeAndCreator(OSType* type, OSType* creator)
1130//----------------------------------------------------------------------------------------
1131{
1132 FInfo info;
1133 OSErr err = ::FSpGetFInfo(&mSpec, &info);
1134 if (err != noErr)
1135 return err;
1136 *type = info.fdType;
1137 *creator = info.fdCreator;
1138 return noErr;
1139}
1140
1141//----------------------------------------------------------------------------------------
1142PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
1143//----------------------------------------------------------------------------------------
1144{
1145 PRInt64 space64Bits;
1146
1147 LL_I2L(space64Bits , LONG_MAX);
1148
1149 XVolumeParam pb;
1150 pb.ioCompletion = nsnull;
1151 pb.ioVolIndex = 0;
1152 pb.ioNamePtr = nsnull;
1153 pb.ioVRefNum = mSpec.vRefNum;
1154
1155 // PBXGetVolInfoSync works on HFS+ volumes too!
1156 OSErr err = ::PBXGetVolInfoSync(&pb);
1157
1158 if (err == noErr)
1159 {
1160#ifdef HAVE_LONG_LONG
1161 space64Bits = pb.ioVFreeBytes;
1162#else
1163 const UnsignedWide& freeBytes = UInt64ToUnsignedWide(pb.ioVFreeBytes);
1164 space64Bits.lo = freeBytes.lo;
1165 space64Bits.hi = freeBytes.hi;
1166#endif
1167 }
1168
1169 return space64Bits;
1170} // nsFileSpec::GetDiskSpace()
1171
1172//----------------------------------------------------------------------------------------
1173const char* nsFileSpec::GetCString() const
1174// This is the only conversion to const char* that is provided, and it allows the
1175// path to be "passed" to NSPR file routines. This practice is VERY EVIL and should only
1176// be used to support legacy code. Using it guarantees bugs on Macintosh. The string is
1177// cached and freed by the nsFileSpec destructor, so do not delete (or free) it.
1178//----------------------------------------------------------------------------------------
1179{
1180 if (mPath.IsEmpty())
1181 {
1182 char* path = MacFileHelpers::PathNameFromFSSpec(mSpec);
1183 if (path != NULL) {
1184 const_cast<nsFileSpec*>(this)->mPath = path; // operator =() copies the string!!!
1185 delete[] path;
1186 } else {
1187 const_cast<nsFileSpec*>(this)->mError = NS_ERROR_OUT_OF_MEMORY;
1188 }
1189 }
1190 return mPath;
1191}
1192
1193#pragma mark -
1194
1195//========================================================================================
1196// Macintosh nsFilePath implementation
1197//========================================================================================
1198
1199//----------------------------------------------------------------------------------------
1200static void AssignFromPath(nsFilePath& ioPath, const char* inString, PRBool inCreateDirs)
1201//----------------------------------------------------------------------------------------
1202{
1203 NS_ASSERTION(inString, "AssignFromPath called with null inString");
1204 NS_ASSERTION(strstr(inString, kFileURLPrefix) != inString, "URL passed as path");
1205
1206 FSSpec spec;
1207 spec.vRefNum = 0;
1208 spec.parID = 0;
1209 spec.name[0] = 0;
1210 MacFileHelpers::FSSpecFromUnixPath(
1211 inString,
1212 spec,
1213 false,
1214 true, // resolve alias
1215 true,
1216 inCreateDirs);
1217 // Now we have a spec,
1218 // Invoke operator = (const nsFileSpec&) to do the rest.
1219 // Why didn't we just say mPath = inString to get the path? Well, we want it to be
1220 // canonical and absolute.
1221 ioPath = spec;
1222}
1223
1224//----------------------------------------------------------------------------------------
1225nsFilePath::nsFilePath(const char* inString, PRBool inCreateDirs)
1226//----------------------------------------------------------------------------------------
1227{
1228 AssignFromPath(*this, inString, inCreateDirs);
1229} //nsFilePath::nsFilePath
1230
1231//----------------------------------------------------------------------------------------
1232nsFilePath::nsFilePath(const nsString& inString, PRBool inCreateDirs)
1233//----------------------------------------------------------------------------------------
1234{
1235 AssignFromPath(*this, NS_LossyConvertUCS2toASCII(inString).get(),
1236 inCreateDirs);
1237}
1238
1239//----------------------------------------------------------------------------------------
1240void nsFilePath::operator = (const char* inString)
1241//----------------------------------------------------------------------------------------
1242{
1243 AssignFromPath(*this, inString, PR_FALSE);
1244}
1245
1246//----------------------------------------------------------------------------------------
1247nsFilePath::nsFilePath(const nsFileSpec& inSpec)
1248//----------------------------------------------------------------------------------------
1249{
1250 *this = inSpec;
1251}
1252
1253//----------------------------------------------------------------------------------------
1254nsFilePath::nsFilePath(const nsFileURL& inOther)
1255//----------------------------------------------------------------------------------------
1256{
1257 *this = inOther;
1258}
1259
1260//----------------------------------------------------------------------------------------
1261void nsFilePath::operator = (const nsFileSpec& inSpec)
1262//----------------------------------------------------------------------------------------
1263{
1264 char * path = MacFileHelpers::PathNameFromFSSpec(inSpec);
1265 path = MacFileHelpers::EncodeMacPath(path, true, false);
1266 mPath = path;
1267 nsCRT::free(path);
1268 mFileSpec = inSpec;
1269} // nsFilePath::operator =
1270
1271//----------------------------------------------------------------------------------------
1272void nsFilePath::operator = (const nsFileURL& inOther)
1273//----------------------------------------------------------------------------------------
1274{
1275 char * path = MacFileHelpers::PathNameFromFSSpec(inOther.mFileSpec);
1276 path = MacFileHelpers::EncodeMacPath(path, true, false);
1277 mPath = path;
1278 nsCRT::free(path);
1279 mFileSpec = inOther.GetFileSpec();
1280}
1281
1282#pragma mark -
1283
1284//========================================================================================
1285// nsFileURL implementation
1286//========================================================================================
1287
1288//----------------------------------------------------------------------------------------
1289nsFileURL::nsFileURL(const char* inString, PRBool inCreateDirs)
1290//----------------------------------------------------------------------------------------
1291: mURL(inString)
1292{
1293 NS_ASSERTION(inString, "nsFileURL constructed with null inString");
1294 NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
1295 mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath(
1296 inString + kFileURLPrefixLength,
1297 mFileSpec.mSpec,
1298 true, // need to decode
1299 false, // resolve alias
1300 false, // must be a full path
1301 inCreateDirs));
1302 if (mFileSpec.mError == NS_FILE_RESULT(fnfErr))
1303 mFileSpec.mError = NS_OK;
1304} // nsFileURL::nsFileURL
1305
1306//----------------------------------------------------------------------------------------
1307nsFileURL::nsFileURL(const nsString& inString, PRBool inCreateDirs)
1308//----------------------------------------------------------------------------------------
1309: mURL(nsnull)
1310{
1311 NS_LossyConvertUCS2toASCII cstring(inString);
1312 mURL = cstring.get();
1313 NS_ASSERTION(strstr(cstring.get(), kFileURLPrefix) == cstring.get(),
1314 "Not a URL!");
1315 mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath(
1316 cstring.get() + kFileURLPrefixLength,
1317 mFileSpec.mSpec,
1318 true, // need to decode
1319 false, // resolve alias
1320 false, // must be a full path
1321 inCreateDirs));
1322 if (mFileSpec.mError == NS_FILE_RESULT(fnfErr))
1323 mFileSpec.mError = NS_OK;
1324} // nsFileURL::nsFileURL
1325
1326//----------------------------------------------------------------------------------------
1327nsFileURL::nsFileURL(const nsFilePath& inOther)
1328//----------------------------------------------------------------------------------------
1329{
1330 *this = inOther.GetFileSpec();
1331} // nsFileURL::nsFileURL
1332
1333//----------------------------------------------------------------------------------------
1334nsFileURL::nsFileURL(const nsFileSpec& inOther)
1335//----------------------------------------------------------------------------------------
1336{
1337 *this = inOther;
1338} // nsFileURL::nsFileURL
1339
1340//----------------------------------------------------------------------------------------
1341void nsFileURL::operator = (const nsFilePath& inOther)
1342//----------------------------------------------------------------------------------------
1343{
1344 *this = inOther.GetFileSpec();
1345} // nsFileURL::operator =
1346
1347//----------------------------------------------------------------------------------------
1348void nsFileURL::operator = (const nsFileSpec& inOther)
1349//----------------------------------------------------------------------------------------
1350{
1351 mFileSpec = inOther;
1352 char* path = MacFileHelpers::PathNameFromFSSpec( mFileSpec );
1353 char* encodedPath = MacFileHelpers::EncodeMacPath(path, true, true);
1354 nsSimpleCharString encodedURL(kFileURLPrefix);
1355 encodedURL += encodedPath;
1356 nsCRT::free(encodedPath);
1357 mURL = encodedURL;
1358 if (encodedURL[encodedURL.Length() - 1] != '/' && inOther.IsDirectory())
1359 mURL += "/";
1360} // nsFileURL::operator =
1361
1362//----------------------------------------------------------------------------------------
1363void nsFileURL::operator = (const char* inString)
1364//----------------------------------------------------------------------------------------
1365{
1366 NS_ASSERTION(inString, "nsFileURL operator= constructed with null inString");
1367
1368 mURL = inString;
1369 NS_ASSERTION(strstr(inString, kFileURLPrefix) == inString, "Not a URL!");
1370 mFileSpec.mError = NS_FILE_RESULT(MacFileHelpers::FSSpecFromUnixPath(
1371 inString + kFileURLPrefixLength,
1372 mFileSpec.mSpec,
1373 true, // need to decode
1374 true, // resolve alias
1375 false, // must be a full path
1376 false)); // don't create dirs.
1377 if (mFileSpec.mError == NS_FILE_RESULT(fnfErr))
1378 mFileSpec.mError = NS_OK;
1379} // nsFileURL::operator =
1380
1381#pragma mark -
1382
1383//========================================================================================
1384// nsDirectoryIterator
1385//========================================================================================
1386
1387//----------------------------------------------------------------------------------------
1388nsDirectoryIterator::nsDirectoryIterator(
1389 const nsFileSpec& inDirectory
1390, PRBool resolveSymLinks)
1391//----------------------------------------------------------------------------------------
1392 : mCurrent(inDirectory)
1393 , mExists(false)
1394 , mResoveSymLinks(resolveSymLinks)
1395 , mIndex(-1)
1396{
1397 CInfoPBRec pb;
1398 OSErr err = inDirectory.GetCatInfo(pb);
1399
1400 // test that we have got a directory back, not a file
1401 DirInfo* dipb = (DirInfo*)&pb;
1402 if (err != noErr || !( dipb->ioFlAttrib & 0x0010))
1403 return;
1404 // Sorry about this, there seems to be a bug in CWPro 4:
1405 FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&();
1406 mVRefNum = currentSpec.vRefNum;
1407 mParID = dipb->ioDrDirID;
1408 mMaxIndex = pb.dirInfo.ioDrNmFls;
1409 mIndex = 0; // ready to increment
1410 ++(*this); // the pre-increment operator
1411
1412} // nsDirectoryIterator::nsDirectoryIterator
1413
1414//----------------------------------------------------------------------------------------
1415OSErr nsDirectoryIterator::SetToIndex()
1416//----------------------------------------------------------------------------------------
1417{
1418 CInfoPBRec cipb;
1419 DirInfo *dipb=(DirInfo *)&cipb;
1420 Str255 objectName;
1421 dipb->ioCompletion = nsnull;
1422 dipb->ioFDirIndex = mIndex;
1423 // Sorry about this, there seems to be a bug in CWPro 4:
1424 FSSpec& currentSpec = mCurrent.nsFileSpec::operator FSSpec&();
1425 dipb->ioVRefNum = mVRefNum; /* Might need to use vRefNum, not sure*/
1426 dipb->ioDrDirID = mParID;
1427 dipb->ioNamePtr = objectName;
1428 OSErr err = PBGetCatInfoSync(&cipb);
1429 FSSpec temp;
1430 if (err == noErr)
1431 err = FSMakeFSSpec(mVRefNum, mParID, objectName, &temp);
1432 mCurrent = temp; // use the operator: it clears the string cache.
1433 mExists = err == noErr;
1434
1435 if (mExists && mResoveSymLinks)
1436 {
1437 PRBool ignore;
1438 mCurrent.ResolveSymlink(ignore);
1439 }
1440 return err;
1441} // nsDirectoryIterator::SetToIndex()
1442
1443//----------------------------------------------------------------------------------------
1444nsDirectoryIterator& nsDirectoryIterator::operator -- ()
1445//----------------------------------------------------------------------------------------
1446{
1447 mExists = false;
1448 while (--mIndex > 0)
1449 {
1450 OSErr err = SetToIndex();
1451 if (err == noErr)
1452 break;
1453 }
1454 return *this;
1455} // nsDirectoryIterator::operator --
1456
1457//----------------------------------------------------------------------------------------
1458nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
1459//----------------------------------------------------------------------------------------
1460{
1461 mExists = false;
1462 if (mIndex >= 0) // probably trying to use a file as a directory!
1463 while (++mIndex <= mMaxIndex)
1464 {
1465 OSErr err = SetToIndex();
1466 if (err == noErr)
1467 break;
1468 }
1469 return *this;
1470} // nsDirectoryIterator::operator ++
1471
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use