1 | /* -*- Mode: C; tab-width: 2; 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) 2001, 2002
|
---|
20 | * the Initial Developer. All Rights Reserved.
|
---|
21 | *
|
---|
22 | * Contributor(s):
|
---|
23 | * Conrad Carlen <ccarlen@netscape.com>
|
---|
24 | * Jungshik Shin <jshin@mailaps.org>
|
---|
25 | * Asaf Romano <mozilla.mano@sent.com>
|
---|
26 | * Mark Mentovai <mark@moxienet.com>
|
---|
27 | *
|
---|
28 | * Alternatively, the contents of this file may be used under the terms of
|
---|
29 | * either the GNU General Public License Version 2 or later (the "GPL"), or
|
---|
30 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
---|
31 | * in which case the provisions of the GPL or the LGPL are applicable instead
|
---|
32 | * of those above. If you wish to allow use of your version of this file only
|
---|
33 | * under the terms of either the GPL or the LGPL, and not to allow others to
|
---|
34 | * use your version of this file under the terms of the MPL, indicate your
|
---|
35 | * decision by deleting the provisions above and replace them with the notice
|
---|
36 | * and other provisions required by the GPL or the LGPL. If you do not delete
|
---|
37 | * the provisions above, a recipient may use your version of this file under
|
---|
38 | * the terms of any one of the MPL, the GPL or the LGPL.
|
---|
39 | *
|
---|
40 | * ***** END LICENSE BLOCK ***** */
|
---|
41 |
|
---|
42 | #include "nsLocalFile.h"
|
---|
43 | #include "nsDirectoryServiceDefs.h"
|
---|
44 |
|
---|
45 | #include "nsString.h"
|
---|
46 | #include "nsReadableUtils.h"
|
---|
47 | #include "nsIDirectoryEnumerator.h"
|
---|
48 | #include "nsISimpleEnumerator.h"
|
---|
49 | #include "nsITimelineService.h"
|
---|
50 | #include "nsVoidArray.h"
|
---|
51 |
|
---|
52 | #include "plbase64.h"
|
---|
53 | #include "prmem.h"
|
---|
54 | #include "nsCRT.h"
|
---|
55 | #include "nsHashKeys.h"
|
---|
56 |
|
---|
57 | #include "MoreFilesX.h"
|
---|
58 | #include "FSCopyObject.h"
|
---|
59 | #include "nsAutoBuffer.h"
|
---|
60 | #include "nsTraceRefcntImpl.h"
|
---|
61 |
|
---|
62 | // Mac Includes
|
---|
63 | #include <Carbon/Carbon.h>
|
---|
64 |
|
---|
65 | // Unix Includes
|
---|
66 | #include <unistd.h>
|
---|
67 | #include <sys/stat.h>
|
---|
68 | #include <stdlib.h>
|
---|
69 |
|
---|
70 | #if !defined(MAC_OS_X_VERSION_10_4) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
|
---|
71 | #define GetAliasSizeFromRecord(aliasRecord) aliasRecord.aliasSize
|
---|
72 | #else
|
---|
73 | #define GetAliasSizeFromRecord(aliasRecord) GetAliasSizeFromPtr(&aliasRecord)
|
---|
74 | #endif
|
---|
75 |
|
---|
76 | #define CHECK_mBaseRef() \
|
---|
77 | PR_BEGIN_MACRO \
|
---|
78 | if (!mBaseRef) \
|
---|
79 | return NS_ERROR_NOT_INITIALIZED; \
|
---|
80 | PR_END_MACRO
|
---|
81 |
|
---|
82 | //*****************************************************************************
|
---|
83 | // Static Function Prototypes
|
---|
84 | //*****************************************************************************
|
---|
85 |
|
---|
86 | static nsresult MacErrorMapper(OSErr inErr);
|
---|
87 | static OSErr FindRunningAppBySignature(OSType aAppSig, ProcessSerialNumber& outPsn);
|
---|
88 | static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult);
|
---|
89 |
|
---|
90 | //*****************************************************************************
|
---|
91 | // Local Helper Classes
|
---|
92 | //*****************************************************************************
|
---|
93 |
|
---|
94 | #pragma mark -
|
---|
95 | #pragma mark [FSRef operator==]
|
---|
96 |
|
---|
97 | bool operator==(const FSRef& lhs, const FSRef& rhs)
|
---|
98 | {
|
---|
99 | return (::FSCompareFSRefs(&lhs, &rhs) == noErr);
|
---|
100 | }
|
---|
101 |
|
---|
102 | #pragma mark -
|
---|
103 | #pragma mark [StFollowLinksState]
|
---|
104 |
|
---|
105 | class StFollowLinksState
|
---|
106 | {
|
---|
107 | public:
|
---|
108 | StFollowLinksState(nsLocalFile& aFile) :
|
---|
109 | mFile(aFile)
|
---|
110 | {
|
---|
111 | mFile.GetFollowLinks(&mSavedState);
|
---|
112 | }
|
---|
113 |
|
---|
114 | StFollowLinksState(nsLocalFile& aFile, PRBool followLinksState) :
|
---|
115 | mFile(aFile)
|
---|
116 | {
|
---|
117 | mFile.GetFollowLinks(&mSavedState);
|
---|
118 | mFile.SetFollowLinks(followLinksState);
|
---|
119 | }
|
---|
120 |
|
---|
121 | ~StFollowLinksState()
|
---|
122 | {
|
---|
123 | mFile.SetFollowLinks(mSavedState);
|
---|
124 | }
|
---|
125 |
|
---|
126 | private:
|
---|
127 | nsLocalFile& mFile;
|
---|
128 | PRBool mSavedState;
|
---|
129 | };
|
---|
130 |
|
---|
131 | #pragma mark -
|
---|
132 | #pragma mark [nsDirEnumerator]
|
---|
133 |
|
---|
134 | class nsDirEnumerator : public nsISimpleEnumerator,
|
---|
135 | public nsIDirectoryEnumerator
|
---|
136 | {
|
---|
137 | public:
|
---|
138 |
|
---|
139 | NS_DECL_ISUPPORTS
|
---|
140 |
|
---|
141 | nsDirEnumerator() :
|
---|
142 | mIterator(nsnull),
|
---|
143 | mFSRefsArray(nsnull),
|
---|
144 | mArrayCnt(0), mArrayIndex(0)
|
---|
145 | {
|
---|
146 | }
|
---|
147 |
|
---|
148 | nsresult Init(nsILocalFileMac* parent)
|
---|
149 | {
|
---|
150 | NS_ENSURE_ARG(parent);
|
---|
151 |
|
---|
152 | OSErr err;
|
---|
153 | nsresult rv;
|
---|
154 | FSRef parentRef;
|
---|
155 |
|
---|
156 | rv = parent->GetFSRef(&parentRef);
|
---|
157 | if (NS_FAILED(rv))
|
---|
158 | return rv;
|
---|
159 |
|
---|
160 | mFSRefsArray = (FSRef *)nsMemory::Alloc(sizeof(FSRef)
|
---|
161 | * kRequestCountPerIteration);
|
---|
162 | if (!mFSRefsArray)
|
---|
163 | return NS_ERROR_OUT_OF_MEMORY;
|
---|
164 |
|
---|
165 | err = ::FSOpenIterator(&parentRef, kFSIterateFlat, &mIterator);
|
---|
166 | if (err != noErr)
|
---|
167 | return MacErrorMapper(err);
|
---|
168 |
|
---|
169 | return NS_OK;
|
---|
170 | }
|
---|
171 |
|
---|
172 | NS_IMETHOD HasMoreElements(PRBool *result)
|
---|
173 | {
|
---|
174 | if (mNext == nsnull) {
|
---|
175 | if (mArrayIndex >= mArrayCnt) {
|
---|
176 | ItemCount actualCnt;
|
---|
177 | OSErr err = ::FSGetCatalogInfoBulk(mIterator,
|
---|
178 | kRequestCountPerIteration,
|
---|
179 | &actualCnt,
|
---|
180 | nsnull,
|
---|
181 | kFSCatInfoNone,
|
---|
182 | nsnull,
|
---|
183 | mFSRefsArray,
|
---|
184 | nsnull,
|
---|
185 | nsnull);
|
---|
186 |
|
---|
187 | if (err == noErr || err == errFSNoMoreItems) {
|
---|
188 | mArrayCnt = actualCnt;
|
---|
189 | mArrayIndex = 0;
|
---|
190 | }
|
---|
191 | }
|
---|
192 | if (mArrayIndex < mArrayCnt) {
|
---|
193 | nsLocalFile *newFile = new nsLocalFile;
|
---|
194 | if (!newFile)
|
---|
195 | return NS_ERROR_OUT_OF_MEMORY;
|
---|
196 | FSRef fsRef = mFSRefsArray[mArrayIndex];
|
---|
197 | if (NS_FAILED(newFile->InitWithFSRef(&fsRef)))
|
---|
198 | return NS_ERROR_FAILURE;
|
---|
199 | mArrayIndex++;
|
---|
200 | mNext = newFile;
|
---|
201 | }
|
---|
202 | }
|
---|
203 | *result = mNext != nsnull;
|
---|
204 | if (!*result)
|
---|
205 | Close();
|
---|
206 | return NS_OK;
|
---|
207 | }
|
---|
208 |
|
---|
209 | NS_IMETHOD GetNext(nsISupports **result)
|
---|
210 | {
|
---|
211 | NS_ENSURE_ARG_POINTER(result);
|
---|
212 | *result = nsnull;
|
---|
213 |
|
---|
214 | nsresult rv;
|
---|
215 | PRBool hasMore;
|
---|
216 | rv = HasMoreElements(&hasMore);
|
---|
217 | if (NS_FAILED(rv)) return rv;
|
---|
218 |
|
---|
219 | *result = mNext; // might return nsnull
|
---|
220 | NS_IF_ADDREF(*result);
|
---|
221 |
|
---|
222 | mNext = nsnull;
|
---|
223 | return NS_OK;
|
---|
224 | }
|
---|
225 |
|
---|
226 | NS_IMETHOD GetNextFile(nsIFile **result)
|
---|
227 | {
|
---|
228 | *result = nsnull;
|
---|
229 | PRBool hasMore = PR_FALSE;
|
---|
230 | nsresult rv = HasMoreElements(&hasMore);
|
---|
231 | if (NS_FAILED(rv) || !hasMore)
|
---|
232 | return rv;
|
---|
233 | *result = mNext;
|
---|
234 | NS_IF_ADDREF(*result);
|
---|
235 | mNext = nsnull;
|
---|
236 | return NS_OK;
|
---|
237 | }
|
---|
238 |
|
---|
239 | NS_IMETHOD Close()
|
---|
240 | {
|
---|
241 | if (mIterator) {
|
---|
242 | ::FSCloseIterator(mIterator);
|
---|
243 | mIterator = nsnull;
|
---|
244 | }
|
---|
245 | if (mFSRefsArray) {
|
---|
246 | nsMemory::Free(mFSRefsArray);
|
---|
247 | mFSRefsArray = nsnull;
|
---|
248 | }
|
---|
249 | return NS_OK;
|
---|
250 | }
|
---|
251 |
|
---|
252 | private:
|
---|
253 | ~nsDirEnumerator()
|
---|
254 | {
|
---|
255 | Close();
|
---|
256 | }
|
---|
257 |
|
---|
258 | protected:
|
---|
259 | // According to Apple doc, request the number of objects
|
---|
260 | // per call that will fit in 4 VM pages.
|
---|
261 | enum {
|
---|
262 | kRequestCountPerIteration = ((4096 * 4) / sizeof(FSRef))
|
---|
263 | };
|
---|
264 |
|
---|
265 | nsCOMPtr<nsILocalFileMac> mNext;
|
---|
266 |
|
---|
267 | FSIterator mIterator;
|
---|
268 | FSRef *mFSRefsArray;
|
---|
269 | PRInt32 mArrayCnt, mArrayIndex;
|
---|
270 | };
|
---|
271 |
|
---|
272 | NS_IMPL_ISUPPORTS2(nsDirEnumerator, nsISimpleEnumerator, nsIDirectoryEnumerator)
|
---|
273 |
|
---|
274 | #pragma mark -
|
---|
275 | #pragma mark [StAEDesc]
|
---|
276 |
|
---|
277 | class StAEDesc: public AEDesc
|
---|
278 | {
|
---|
279 | public:
|
---|
280 | StAEDesc()
|
---|
281 | {
|
---|
282 | descriptorType = typeNull;
|
---|
283 | dataHandle = nil;
|
---|
284 | }
|
---|
285 |
|
---|
286 | ~StAEDesc()
|
---|
287 | {
|
---|
288 | ::AEDisposeDesc(this);
|
---|
289 | }
|
---|
290 | };
|
---|
291 |
|
---|
292 | #define FILENAME_BUFFER_SIZE 512
|
---|
293 |
|
---|
294 | //*****************************************************************************
|
---|
295 | // nsLocalFile
|
---|
296 | //*****************************************************************************
|
---|
297 |
|
---|
298 | const char nsLocalFile::kPathSepChar = '/';
|
---|
299 | const PRUnichar nsLocalFile::kPathSepUnichar = '/';
|
---|
300 |
|
---|
301 | // The HFS+ epoch is Jan. 1, 1904 GMT - differs from HFS in which times were local
|
---|
302 | // The NSPR epoch is Jan. 1, 1970 GMT
|
---|
303 | // 2082844800 is the difference in seconds between those dates
|
---|
304 | const PRInt64 nsLocalFile::kJanuaryFirst1970Seconds = 2082844800LL;
|
---|
305 |
|
---|
306 | #pragma mark -
|
---|
307 | #pragma mark [CTORs/DTOR]
|
---|
308 |
|
---|
309 | nsLocalFile::nsLocalFile() :
|
---|
310 | mBaseRef(nsnull),
|
---|
311 | mTargetRef(nsnull),
|
---|
312 | mCachedFSRefValid(PR_FALSE),
|
---|
313 | mFollowLinks(PR_TRUE),
|
---|
314 | mFollowLinksDirty(PR_TRUE)
|
---|
315 | {
|
---|
316 | }
|
---|
317 |
|
---|
318 | nsLocalFile::nsLocalFile(const nsLocalFile& src) :
|
---|
319 | mBaseRef(src.mBaseRef),
|
---|
320 | mTargetRef(src.mTargetRef),
|
---|
321 | mCachedFSRef(src.mCachedFSRef),
|
---|
322 | mCachedFSRefValid(src.mCachedFSRefValid),
|
---|
323 | mFollowLinks(src.mFollowLinks),
|
---|
324 | mFollowLinksDirty(src.mFollowLinksDirty)
|
---|
325 | {
|
---|
326 | // A CFURLRef is immutable so no need to copy, just retain.
|
---|
327 | if (mBaseRef)
|
---|
328 | ::CFRetain(mBaseRef);
|
---|
329 | if (mTargetRef)
|
---|
330 | ::CFRetain(mTargetRef);
|
---|
331 | }
|
---|
332 |
|
---|
333 | nsLocalFile::~nsLocalFile()
|
---|
334 | {
|
---|
335 | if (mBaseRef)
|
---|
336 | ::CFRelease(mBaseRef);
|
---|
337 | if (mTargetRef)
|
---|
338 | ::CFRelease(mTargetRef);
|
---|
339 | }
|
---|
340 |
|
---|
341 |
|
---|
342 | //*****************************************************************************
|
---|
343 | // nsLocalFile::nsISupports
|
---|
344 | //*****************************************************************************
|
---|
345 | #pragma mark -
|
---|
346 | #pragma mark [nsISupports]
|
---|
347 |
|
---|
348 | NS_IMPL_THREADSAFE_ISUPPORTS4(nsLocalFile,
|
---|
349 | nsILocalFileMac,
|
---|
350 | nsILocalFile,
|
---|
351 | nsIFile,
|
---|
352 | nsIHashable)
|
---|
353 |
|
---|
354 | NS_METHOD nsLocalFile::nsLocalFileConstructor(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
|
---|
355 | {
|
---|
356 | NS_ENSURE_ARG_POINTER(aInstancePtr);
|
---|
357 | NS_ENSURE_NO_AGGREGATION(outer);
|
---|
358 |
|
---|
359 | nsLocalFile* inst = new nsLocalFile();
|
---|
360 | if (inst == NULL)
|
---|
361 | return NS_ERROR_OUT_OF_MEMORY;
|
---|
362 |
|
---|
363 | nsresult rv = inst->QueryInterface(aIID, aInstancePtr);
|
---|
364 | if (NS_FAILED(rv))
|
---|
365 | {
|
---|
366 | delete inst;
|
---|
367 | return rv;
|
---|
368 | }
|
---|
369 | return NS_OK;
|
---|
370 | }
|
---|
371 |
|
---|
372 |
|
---|
373 | //*****************************************************************************
|
---|
374 | // nsLocalFile::nsIFile
|
---|
375 | //*****************************************************************************
|
---|
376 | #pragma mark -
|
---|
377 | #pragma mark [nsIFile]
|
---|
378 |
|
---|
379 | /* void append (in AString node); */
|
---|
380 | NS_IMETHODIMP nsLocalFile::Append(const nsAString& aNode)
|
---|
381 | {
|
---|
382 | return AppendNative(NS_ConvertUTF16toUTF8(aNode));
|
---|
383 | }
|
---|
384 |
|
---|
385 | /* [noscript] void appendNative (in ACString node); */
|
---|
386 | NS_IMETHODIMP nsLocalFile::AppendNative(const nsACString& aNode)
|
---|
387 | {
|
---|
388 | // Check we are correctly initialized.
|
---|
389 | CHECK_mBaseRef();
|
---|
390 |
|
---|
391 | nsACString::const_iterator start, end;
|
---|
392 | aNode.BeginReading(start);
|
---|
393 | aNode.EndReading(end);
|
---|
394 | if (FindCharInReadable(kPathSepChar, start, end))
|
---|
395 | return NS_ERROR_FILE_UNRECOGNIZED_PATH;
|
---|
396 |
|
---|
397 | CFStringRef nodeStrRef = ::CFStringCreateWithCString(kCFAllocatorDefault,
|
---|
398 | PromiseFlatCString(aNode).get(),
|
---|
399 | kCFStringEncodingUTF8);
|
---|
400 | if (nodeStrRef) {
|
---|
401 | CFURLRef newRef = ::CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
|
---|
402 | mBaseRef, nodeStrRef, PR_FALSE);
|
---|
403 | ::CFRelease(nodeStrRef);
|
---|
404 | if (newRef) {
|
---|
405 | SetBaseRef(newRef);
|
---|
406 | ::CFRelease(newRef);
|
---|
407 | return NS_OK;
|
---|
408 | }
|
---|
409 | }
|
---|
410 | return NS_ERROR_FAILURE;
|
---|
411 | }
|
---|
412 |
|
---|
413 | /* void normalize (); */
|
---|
414 | NS_IMETHODIMP nsLocalFile::Normalize()
|
---|
415 | {
|
---|
416 | // Check we are correctly initialized.
|
---|
417 | CHECK_mBaseRef();
|
---|
418 |
|
---|
419 | // CFURL doesn't doesn't seem to resolve paths containing relative
|
---|
420 | // components, so we'll nick the stdlib code from nsLocalFileUnix
|
---|
421 | UInt8 path[PATH_MAX] = "";
|
---|
422 | Boolean success;
|
---|
423 | success = ::CFURLGetFileSystemRepresentation(mBaseRef, true, path, PATH_MAX);
|
---|
424 | if (!success)
|
---|
425 | return NS_ERROR_FAILURE;
|
---|
426 |
|
---|
427 | char resolved_path[PATH_MAX] = "";
|
---|
428 | char *resolved_path_ptr = nsnull;
|
---|
429 | resolved_path_ptr = realpath((char*)path, resolved_path);
|
---|
430 |
|
---|
431 | // if there is an error, the return is null.
|
---|
432 | if (!resolved_path_ptr)
|
---|
433 | return NSRESULT_FOR_ERRNO();
|
---|
434 |
|
---|
435 | // Need to know whether we're a directory to create a new CFURLRef
|
---|
436 | PRBool isDirectory;
|
---|
437 | nsresult rv = IsDirectory(&isDirectory);
|
---|
438 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
439 |
|
---|
440 | rv = NS_ERROR_FAILURE;
|
---|
441 | CFStringRef pathStrRef =
|
---|
442 | ::CFStringCreateWithCString(kCFAllocatorDefault,
|
---|
443 | resolved_path,
|
---|
444 | kCFStringEncodingUTF8);
|
---|
445 | if (pathStrRef) {
|
---|
446 | CFURLRef newURLRef =
|
---|
447 | ::CFURLCreateWithFileSystemPath(kCFAllocatorDefault, pathStrRef,
|
---|
448 | kCFURLPOSIXPathStyle, isDirectory);
|
---|
449 | if (newURLRef) {
|
---|
450 | SetBaseRef(newURLRef);
|
---|
451 | ::CFRelease(newURLRef);
|
---|
452 | rv = NS_OK;
|
---|
453 | }
|
---|
454 | ::CFRelease(pathStrRef);
|
---|
455 | }
|
---|
456 |
|
---|
457 | return rv;
|
---|
458 | }
|
---|
459 |
|
---|
460 | /* void create (in unsigned long type, in unsigned long permissions); */
|
---|
461 | NS_IMETHODIMP nsLocalFile::Create(PRUint32 type, PRUint32 permissions)
|
---|
462 | {
|
---|
463 | if (type != NORMAL_FILE_TYPE && type != DIRECTORY_TYPE)
|
---|
464 | return NS_ERROR_FILE_UNKNOWN_TYPE;
|
---|
465 |
|
---|
466 | // Check we are correctly initialized.
|
---|
467 | CHECK_mBaseRef();
|
---|
468 |
|
---|
469 | nsStringArray nonExtantNodes;
|
---|
470 | CFURLRef pathURLRef = mBaseRef;
|
---|
471 | FSRef pathFSRef;
|
---|
472 | CFStringRef leafStrRef = nsnull;
|
---|
473 | nsAutoBuffer<UniChar, FILENAME_BUFFER_SIZE> buffer;
|
---|
474 | Boolean success;
|
---|
475 |
|
---|
476 | // Work backwards through the path to find the last node which
|
---|
477 | // exists. Place the nodes which don't exist in an array and we'll
|
---|
478 | // create those below.
|
---|
479 | while ((success = ::CFURLGetFSRef(pathURLRef, &pathFSRef)) == false) {
|
---|
480 | leafStrRef = ::CFURLCopyLastPathComponent(pathURLRef);
|
---|
481 | if (!leafStrRef)
|
---|
482 | break;
|
---|
483 | CFIndex leafLen = ::CFStringGetLength(leafStrRef);
|
---|
484 | if (!buffer.EnsureElemCapacity(leafLen + 1))
|
---|
485 | break;
|
---|
486 | ::CFStringGetCharacters(leafStrRef, CFRangeMake(0, leafLen), buffer.get());
|
---|
487 | buffer.get()[leafLen] = '\0';
|
---|
488 | nonExtantNodes.AppendString(nsString(nsDependentString(buffer.get())));
|
---|
489 | ::CFRelease(leafStrRef);
|
---|
490 | leafStrRef = nsnull;
|
---|
491 |
|
---|
492 | // Get the parent of the leaf for the next go round
|
---|
493 | CFURLRef parent = ::CFURLCreateCopyDeletingLastPathComponent(NULL, pathURLRef);
|
---|
494 | if (!parent)
|
---|
495 | break;
|
---|
496 | if (pathURLRef != mBaseRef)
|
---|
497 | ::CFRelease(pathURLRef);
|
---|
498 | pathURLRef = parent;
|
---|
499 | }
|
---|
500 | if (pathURLRef != mBaseRef)
|
---|
501 | ::CFRelease(pathURLRef);
|
---|
502 | if (leafStrRef != nsnull)
|
---|
503 | ::CFRelease(leafStrRef);
|
---|
504 | if (!success)
|
---|
505 | return NS_ERROR_FAILURE;
|
---|
506 | PRInt32 nodesToCreate = nonExtantNodes.Count();
|
---|
507 | if (nodesToCreate == 0)
|
---|
508 | return NS_ERROR_FILE_ALREADY_EXISTS;
|
---|
509 |
|
---|
510 | OSErr err;
|
---|
511 | nsAutoString nextNodeName;
|
---|
512 | for (PRInt32 i = nodesToCreate - 1; i > 0; i--) {
|
---|
513 | nonExtantNodes.StringAt(i, nextNodeName);
|
---|
514 | err = ::FSCreateDirectoryUnicode(&pathFSRef,
|
---|
515 | nextNodeName.Length(),
|
---|
516 | (const UniChar *)nextNodeName.get(),
|
---|
517 | kFSCatInfoNone,
|
---|
518 | nsnull, &pathFSRef, nsnull, nsnull);
|
---|
519 | if (err != noErr)
|
---|
520 | return MacErrorMapper(err);
|
---|
521 | }
|
---|
522 | nonExtantNodes.StringAt(0, nextNodeName);
|
---|
523 | if (type == NORMAL_FILE_TYPE) {
|
---|
524 | err = ::FSCreateFileUnicode(&pathFSRef,
|
---|
525 | nextNodeName.Length(),
|
---|
526 | (const UniChar *)nextNodeName.get(),
|
---|
527 | kFSCatInfoNone,
|
---|
528 | nsnull, nsnull, nsnull);
|
---|
529 | }
|
---|
530 | else {
|
---|
531 | err = ::FSCreateDirectoryUnicode(&pathFSRef,
|
---|
532 | nextNodeName.Length(),
|
---|
533 | (const UniChar *)nextNodeName.get(),
|
---|
534 | kFSCatInfoNone,
|
---|
535 | nsnull, nsnull, nsnull, nsnull);
|
---|
536 | }
|
---|
537 |
|
---|
538 | return MacErrorMapper(err);
|
---|
539 | }
|
---|
540 |
|
---|
541 | /* attribute AString leafName; */
|
---|
542 | NS_IMETHODIMP nsLocalFile::GetLeafName(nsAString& aLeafName)
|
---|
543 | {
|
---|
544 | nsCAutoString nativeString;
|
---|
545 | nsresult rv = GetNativeLeafName(nativeString);
|
---|
546 | if (NS_FAILED(rv))
|
---|
547 | return rv;
|
---|
548 | CopyUTF8toUTF16NFC(nativeString, aLeafName);
|
---|
549 | return NS_OK;
|
---|
550 | }
|
---|
551 |
|
---|
552 | NS_IMETHODIMP nsLocalFile::SetLeafName(const nsAString& aLeafName)
|
---|
553 | {
|
---|
554 | return SetNativeLeafName(NS_ConvertUTF16toUTF8(aLeafName));
|
---|
555 | }
|
---|
556 |
|
---|
557 | /* [noscript] attribute ACString nativeLeafName; */
|
---|
558 | NS_IMETHODIMP nsLocalFile::GetNativeLeafName(nsACString& aNativeLeafName)
|
---|
559 | {
|
---|
560 | // Check we are correctly initialized.
|
---|
561 | CHECK_mBaseRef();
|
---|
562 |
|
---|
563 | nsresult rv = NS_ERROR_FAILURE;
|
---|
564 | CFStringRef leafStrRef = ::CFURLCopyLastPathComponent(mBaseRef);
|
---|
565 | if (leafStrRef) {
|
---|
566 | rv = CFStringReftoUTF8(leafStrRef, aNativeLeafName);
|
---|
567 | ::CFRelease(leafStrRef);
|
---|
568 | }
|
---|
569 | return rv;
|
---|
570 | }
|
---|
571 |
|
---|
572 | NS_IMETHODIMP nsLocalFile::SetNativeLeafName(const nsACString& aNativeLeafName)
|
---|
573 | {
|
---|
574 | // Check we are correctly initialized.
|
---|
575 | CHECK_mBaseRef();
|
---|
576 |
|
---|
577 | nsresult rv = NS_ERROR_FAILURE;
|
---|
578 | CFURLRef parentURLRef = ::CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, mBaseRef);
|
---|
579 | if (parentURLRef) {
|
---|
580 | CFStringRef nodeStrRef = ::CFStringCreateWithCString(kCFAllocatorDefault,
|
---|
581 | PromiseFlatCString(aNativeLeafName).get(),
|
---|
582 | kCFStringEncodingUTF8);
|
---|
583 |
|
---|
584 | if (nodeStrRef) {
|
---|
585 | CFURLRef newURLRef = ::CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,
|
---|
586 | parentURLRef, nodeStrRef, PR_FALSE);
|
---|
587 | if (newURLRef) {
|
---|
588 | SetBaseRef(newURLRef);
|
---|
589 | ::CFRelease(newURLRef);
|
---|
590 | rv = NS_OK;
|
---|
591 | }
|
---|
592 | ::CFRelease(nodeStrRef);
|
---|
593 | }
|
---|
594 | ::CFRelease(parentURLRef);
|
---|
595 | }
|
---|
596 | return rv;
|
---|
597 | }
|
---|
598 |
|
---|
599 | /* void copyTo (in nsIFile newParentDir, in AString newName); */
|
---|
600 | NS_IMETHODIMP nsLocalFile::CopyTo(nsIFile *newParentDir, const nsAString& newName)
|
---|
601 | {
|
---|
602 | return CopyInternal(newParentDir, newName, PR_FALSE);
|
---|
603 | }
|
---|
604 |
|
---|
605 | /* [noscrpit] void CopyToNative (in nsIFile newParentDir, in ACString newName); */
|
---|
606 | NS_IMETHODIMP nsLocalFile::CopyToNative(nsIFile *newParentDir, const nsACString& newName)
|
---|
607 | {
|
---|
608 | return CopyInternal(newParentDir, NS_ConvertUTF8toUTF16(newName), PR_FALSE);
|
---|
609 | }
|
---|
610 |
|
---|
611 | /* void copyToFollowingLinks (in nsIFile newParentDir, in AString newName); */
|
---|
612 | NS_IMETHODIMP nsLocalFile::CopyToFollowingLinks(nsIFile *newParentDir, const nsAString& newName)
|
---|
613 | {
|
---|
614 | return CopyInternal(newParentDir, newName, PR_TRUE);
|
---|
615 | }
|
---|
616 |
|
---|
617 | /* [noscript] void copyToFollowingLinksNative (in nsIFile newParentDir, in ACString newName); */
|
---|
618 | NS_IMETHODIMP nsLocalFile::CopyToFollowingLinksNative(nsIFile *newParentDir, const nsACString& newName)
|
---|
619 | {
|
---|
620 | return CopyInternal(newParentDir, NS_ConvertUTF8toUTF16(newName), PR_TRUE);
|
---|
621 | }
|
---|
622 |
|
---|
623 | /* void moveTo (in nsIFile newParentDir, in AString newName); */
|
---|
624 | NS_IMETHODIMP nsLocalFile::MoveTo(nsIFile *newParentDir, const nsAString& newName)
|
---|
625 | {
|
---|
626 | return MoveToNative(newParentDir, NS_ConvertUTF16toUTF8(newName));
|
---|
627 | }
|
---|
628 |
|
---|
629 | /* [noscript] void moveToNative (in nsIFile newParentDir, in ACString newName); */
|
---|
630 | NS_IMETHODIMP nsLocalFile::MoveToNative(nsIFile *newParentDir, const nsACString& newName)
|
---|
631 | {
|
---|
632 | // Check we are correctly initialized.
|
---|
633 | CHECK_mBaseRef();
|
---|
634 |
|
---|
635 | StFollowLinksState followLinks(*this, PR_FALSE);
|
---|
636 |
|
---|
637 | PRBool isDirectory;
|
---|
638 | nsresult rv = IsDirectory(&isDirectory);
|
---|
639 | if (NS_FAILED(rv))
|
---|
640 | return rv;
|
---|
641 |
|
---|
642 | // Get the source path.
|
---|
643 | nsCAutoString srcPath;
|
---|
644 | rv = GetNativePath(srcPath);
|
---|
645 | if (NS_FAILED(rv))
|
---|
646 | return rv;
|
---|
647 |
|
---|
648 | // Build the destination path.
|
---|
649 | nsCOMPtr<nsIFile> parentDir = newParentDir;
|
---|
650 | if (!parentDir) {
|
---|
651 | if (newName.IsEmpty())
|
---|
652 | return NS_ERROR_INVALID_ARG;
|
---|
653 | rv = GetParent(getter_AddRefs(parentDir));
|
---|
654 | if (NS_FAILED(rv))
|
---|
655 | return rv;
|
---|
656 | }
|
---|
657 | else {
|
---|
658 | PRBool exists;
|
---|
659 | rv = parentDir->Exists(&exists);
|
---|
660 | if (NS_FAILED(rv))
|
---|
661 | return rv;
|
---|
662 | if (!exists) {
|
---|
663 | rv = parentDir->Create(nsIFile::DIRECTORY_TYPE, 0777);
|
---|
664 | if (NS_FAILED(rv))
|
---|
665 | return rv;
|
---|
666 | }
|
---|
667 | }
|
---|
668 |
|
---|
669 | nsCAutoString destPath;
|
---|
670 | rv = parentDir->GetNativePath(destPath);
|
---|
671 | if (NS_FAILED(rv))
|
---|
672 | return rv;
|
---|
673 |
|
---|
674 | if (!newName.IsEmpty())
|
---|
675 | destPath.Append(NS_LITERAL_CSTRING("/") + newName);
|
---|
676 | else {
|
---|
677 | nsCAutoString leafName;
|
---|
678 | rv = GetNativeLeafName(leafName);
|
---|
679 | if (NS_FAILED(rv))
|
---|
680 | return rv;
|
---|
681 | destPath.Append(NS_LITERAL_CSTRING("/") + leafName);
|
---|
682 | }
|
---|
683 |
|
---|
684 | // Perform the move.
|
---|
685 | if (rename(srcPath.get(), destPath.get()) != 0) {
|
---|
686 | if (errno == EXDEV) {
|
---|
687 | // Can't move across volume (device) boundaries. Copy and remove.
|
---|
688 | rv = CopyToNative(parentDir, newName);
|
---|
689 | if (NS_SUCCEEDED(rv)) {
|
---|
690 | // Permit removal failure.
|
---|
691 | Remove(PR_TRUE);
|
---|
692 | }
|
---|
693 | }
|
---|
694 | else
|
---|
695 | rv = NSRESULT_FOR_ERRNO();
|
---|
696 |
|
---|
697 | if (NS_FAILED(rv))
|
---|
698 | return rv;
|
---|
699 | }
|
---|
700 |
|
---|
701 | // Update |this| to refer to the moved file.
|
---|
702 | CFURLRef newBaseRef =
|
---|
703 | ::CFURLCreateFromFileSystemRepresentation(NULL, (UInt8*)destPath.get(),
|
---|
704 | destPath.Length(), isDirectory);
|
---|
705 | if (!newBaseRef)
|
---|
706 | return NS_ERROR_FAILURE;
|
---|
707 | SetBaseRef(newBaseRef);
|
---|
708 | ::CFRelease(newBaseRef);
|
---|
709 |
|
---|
710 | return rv;
|
---|
711 | }
|
---|
712 |
|
---|
713 | /* void remove (in boolean recursive); */
|
---|
714 | NS_IMETHODIMP nsLocalFile::Remove(PRBool recursive)
|
---|
715 | {
|
---|
716 | // Check we are correctly initialized.
|
---|
717 | CHECK_mBaseRef();
|
---|
718 |
|
---|
719 | // XXX If we're an alias, never remove target
|
---|
720 | StFollowLinksState followLinks(*this, PR_FALSE);
|
---|
721 |
|
---|
722 | PRBool isDirectory;
|
---|
723 | nsresult rv = IsDirectory(&isDirectory);
|
---|
724 | if (NS_FAILED(rv))
|
---|
725 | return rv;
|
---|
726 |
|
---|
727 | if (recursive && isDirectory) {
|
---|
728 | FSRef fsRef;
|
---|
729 | rv = GetFSRefInternal(fsRef);
|
---|
730 | if (NS_FAILED(rv))
|
---|
731 | return rv;
|
---|
732 |
|
---|
733 | // Call MoreFilesX to do a recursive removal.
|
---|
734 | OSStatus err = ::FSDeleteContainer(&fsRef);
|
---|
735 | rv = MacErrorMapper(err);
|
---|
736 | }
|
---|
737 | else {
|
---|
738 | nsCAutoString path;
|
---|
739 | rv = GetNativePath(path);
|
---|
740 | if (NS_FAILED(rv))
|
---|
741 | return rv;
|
---|
742 |
|
---|
743 | const char* pathPtr = path.get();
|
---|
744 | int status;
|
---|
745 | if (isDirectory)
|
---|
746 | status = rmdir(pathPtr);
|
---|
747 | else
|
---|
748 | status = unlink(pathPtr);
|
---|
749 |
|
---|
750 | if (status != 0)
|
---|
751 | rv = NSRESULT_FOR_ERRNO();
|
---|
752 | }
|
---|
753 |
|
---|
754 | mCachedFSRefValid = PR_FALSE;
|
---|
755 | return rv;
|
---|
756 | }
|
---|
757 |
|
---|
758 | /* attribute unsigned long permissions; */
|
---|
759 | NS_IMETHODIMP nsLocalFile::GetPermissions(PRUint32 *aPermissions)
|
---|
760 | {
|
---|
761 | NS_ENSURE_ARG_POINTER(aPermissions);
|
---|
762 |
|
---|
763 | FSRef fsRef;
|
---|
764 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
765 | if (NS_FAILED(rv))
|
---|
766 | return rv;
|
---|
767 |
|
---|
768 | FSCatalogInfo catalogInfo;
|
---|
769 | OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoPermissions, &catalogInfo,
|
---|
770 | nsnull, nsnull, nsnull);
|
---|
771 | if (err != noErr)
|
---|
772 | return MacErrorMapper(err);
|
---|
773 | FSPermissionInfo *permPtr = (FSPermissionInfo*)catalogInfo.permissions;
|
---|
774 | *aPermissions = permPtr->mode;
|
---|
775 | return NS_OK;
|
---|
776 | }
|
---|
777 |
|
---|
778 | NS_IMETHODIMP nsLocalFile::SetPermissions(PRUint32 aPermissions)
|
---|
779 | {
|
---|
780 | FSRef fsRef;
|
---|
781 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
782 | if (NS_FAILED(rv))
|
---|
783 | return rv;
|
---|
784 |
|
---|
785 | FSCatalogInfo catalogInfo;
|
---|
786 | OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoPermissions, &catalogInfo,
|
---|
787 | nsnull, nsnull, nsnull);
|
---|
788 | if (err != noErr)
|
---|
789 | return MacErrorMapper(err);
|
---|
790 | FSPermissionInfo *permPtr = (FSPermissionInfo*)catalogInfo.permissions;
|
---|
791 | permPtr->mode = (UInt16)aPermissions;
|
---|
792 | err = ::FSSetCatalogInfo(&fsRef, kFSCatInfoPermissions, &catalogInfo);
|
---|
793 | return MacErrorMapper(err);
|
---|
794 | }
|
---|
795 |
|
---|
796 | /* attribute unsigned long permissionsOfLink; */
|
---|
797 | NS_IMETHODIMP nsLocalFile::GetPermissionsOfLink(PRUint32 *aPermissionsOfLink)
|
---|
798 | {
|
---|
799 | NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
|
---|
800 | return NS_ERROR_NOT_IMPLEMENTED;
|
---|
801 | }
|
---|
802 |
|
---|
803 | NS_IMETHODIMP nsLocalFile::SetPermissionsOfLink(PRUint32 aPermissionsOfLink)
|
---|
804 | {
|
---|
805 | NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
|
---|
806 | return NS_ERROR_NOT_IMPLEMENTED;
|
---|
807 | }
|
---|
808 |
|
---|
809 | /* attribute PRInt64 lastModifiedTime; */
|
---|
810 | NS_IMETHODIMP nsLocalFile::GetLastModifiedTime(PRInt64 *aLastModifiedTime)
|
---|
811 | {
|
---|
812 | // Check we are correctly initialized.
|
---|
813 | CHECK_mBaseRef();
|
---|
814 |
|
---|
815 | NS_ENSURE_ARG_POINTER(aLastModifiedTime);
|
---|
816 |
|
---|
817 | FSRef fsRef;
|
---|
818 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
819 | if (NS_FAILED(rv))
|
---|
820 | return rv;
|
---|
821 |
|
---|
822 | FSCatalogInfo catalogInfo;
|
---|
823 | OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoContentMod, &catalogInfo,
|
---|
824 | nsnull, nsnull, nsnull);
|
---|
825 | if (err != noErr)
|
---|
826 | return MacErrorMapper(err);
|
---|
827 | *aLastModifiedTime = HFSPlustoNSPRTime(catalogInfo.contentModDate);
|
---|
828 | return NS_OK;
|
---|
829 | }
|
---|
830 |
|
---|
831 | NS_IMETHODIMP nsLocalFile::SetLastModifiedTime(PRInt64 aLastModifiedTime)
|
---|
832 | {
|
---|
833 | // Check we are correctly initialized.
|
---|
834 | CHECK_mBaseRef();
|
---|
835 |
|
---|
836 | OSErr err;
|
---|
837 | nsresult rv;
|
---|
838 | FSRef fsRef;
|
---|
839 | FSCatalogInfo catalogInfo;
|
---|
840 |
|
---|
841 | rv = GetFSRefInternal(fsRef);
|
---|
842 | if (NS_FAILED(rv))
|
---|
843 | return rv;
|
---|
844 |
|
---|
845 | FSRef parentRef;
|
---|
846 | PRBool notifyParent;
|
---|
847 |
|
---|
848 | /* Get the node flags, the content modification date and time, and the parent ref */
|
---|
849 | err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags + kFSCatInfoContentMod,
|
---|
850 | &catalogInfo, NULL, NULL, &parentRef);
|
---|
851 | if (err != noErr)
|
---|
852 | return MacErrorMapper(err);
|
---|
853 |
|
---|
854 | /* Notify the parent if this is a file */
|
---|
855 | notifyParent = (0 == (catalogInfo.nodeFlags & kFSNodeIsDirectoryMask));
|
---|
856 |
|
---|
857 | NSPRtoHFSPlusTime(aLastModifiedTime, catalogInfo.contentModDate);
|
---|
858 | err = ::FSSetCatalogInfo(&fsRef, kFSCatInfoContentMod, &catalogInfo);
|
---|
859 | if (err != noErr)
|
---|
860 | return MacErrorMapper(err);
|
---|
861 |
|
---|
862 | /* Send a notification for the parent of the file, or for the directory */
|
---|
863 | err = FNNotify(notifyParent ? &parentRef : &fsRef, kFNDirectoryModifiedMessage, kNilOptions);
|
---|
864 | if (err != noErr)
|
---|
865 | return MacErrorMapper(err);
|
---|
866 |
|
---|
867 | return NS_OK;
|
---|
868 | }
|
---|
869 |
|
---|
870 | /* attribute PRInt64 lastModifiedTimeOfLink; */
|
---|
871 | NS_IMETHODIMP nsLocalFile::GetLastModifiedTimeOfLink(PRInt64 *aLastModifiedTimeOfLink)
|
---|
872 | {
|
---|
873 | NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
|
---|
874 | return NS_ERROR_NOT_IMPLEMENTED;
|
---|
875 | }
|
---|
876 | NS_IMETHODIMP nsLocalFile::SetLastModifiedTimeOfLink(PRInt64 aLastModifiedTimeOfLink)
|
---|
877 | {
|
---|
878 | NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
|
---|
879 | return NS_ERROR_NOT_IMPLEMENTED;
|
---|
880 | }
|
---|
881 |
|
---|
882 | /* attribute PRInt64 fileSize; */
|
---|
883 | NS_IMETHODIMP nsLocalFile::GetFileSize(PRInt64 *aFileSize)
|
---|
884 | {
|
---|
885 | NS_ENSURE_ARG_POINTER(aFileSize);
|
---|
886 | *aFileSize = 0;
|
---|
887 |
|
---|
888 | FSRef fsRef;
|
---|
889 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
890 | if (NS_FAILED(rv))
|
---|
891 | return rv;
|
---|
892 |
|
---|
893 | FSCatalogInfo catalogInfo;
|
---|
894 | OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags + kFSCatInfoDataSizes, &catalogInfo,
|
---|
895 | nsnull, nsnull, nsnull);
|
---|
896 | if (err != noErr)
|
---|
897 | return MacErrorMapper(err);
|
---|
898 |
|
---|
899 | // FSGetCatalogInfo can return a bogus size for directories sometimes, so only
|
---|
900 | // rely on the answer for files
|
---|
901 | if ((catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) == 0)
|
---|
902 | *aFileSize = catalogInfo.dataLogicalSize;
|
---|
903 | return NS_OK;
|
---|
904 | }
|
---|
905 |
|
---|
906 | NS_IMETHODIMP nsLocalFile::SetFileSize(PRInt64 aFileSize)
|
---|
907 | {
|
---|
908 | // Check we are correctly initialized.
|
---|
909 | CHECK_mBaseRef();
|
---|
910 |
|
---|
911 | FSRef fsRef;
|
---|
912 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
913 | if (NS_FAILED(rv))
|
---|
914 | return rv;
|
---|
915 |
|
---|
916 | SInt16 refNum;
|
---|
917 | OSErr err = ::FSOpenFork(&fsRef, 0, nsnull, fsWrPerm, &refNum);
|
---|
918 | if (err != noErr)
|
---|
919 | return MacErrorMapper(err);
|
---|
920 | err = ::FSSetForkSize(refNum, fsFromStart, aFileSize);
|
---|
921 | ::FSCloseFork(refNum);
|
---|
922 |
|
---|
923 | return MacErrorMapper(err);
|
---|
924 | }
|
---|
925 |
|
---|
926 | /* readonly attribute PRInt64 fileSizeOfLink; */
|
---|
927 | NS_IMETHODIMP nsLocalFile::GetFileSizeOfLink(PRInt64 *aFileSizeOfLink)
|
---|
928 | {
|
---|
929 | // Check we are correctly initialized.
|
---|
930 | CHECK_mBaseRef();
|
---|
931 |
|
---|
932 | NS_ENSURE_ARG_POINTER(aFileSizeOfLink);
|
---|
933 |
|
---|
934 | StFollowLinksState followLinks(*this, PR_FALSE);
|
---|
935 | return GetFileSize(aFileSizeOfLink);
|
---|
936 | }
|
---|
937 |
|
---|
938 | /* readonly attribute AString target; */
|
---|
939 | NS_IMETHODIMP nsLocalFile::GetTarget(nsAString& aTarget)
|
---|
940 | {
|
---|
941 | NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
|
---|
942 | return NS_ERROR_NOT_IMPLEMENTED;
|
---|
943 | }
|
---|
944 |
|
---|
945 | /* [noscript] readonly attribute ACString nativeTarget; */
|
---|
946 | NS_IMETHODIMP nsLocalFile::GetNativeTarget(nsACString& aNativeTarget)
|
---|
947 | {
|
---|
948 | NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
|
---|
949 | return NS_ERROR_NOT_IMPLEMENTED;
|
---|
950 | }
|
---|
951 |
|
---|
952 | /* readonly attribute AString path; */
|
---|
953 | NS_IMETHODIMP nsLocalFile::GetPath(nsAString& aPath)
|
---|
954 | {
|
---|
955 | nsCAutoString nativeString;
|
---|
956 | nsresult rv = GetNativePath(nativeString);
|
---|
957 | if (NS_FAILED(rv))
|
---|
958 | return rv;
|
---|
959 | CopyUTF8toUTF16NFC(nativeString, aPath);
|
---|
960 | return NS_OK;
|
---|
961 | }
|
---|
962 |
|
---|
963 | /* [noscript] readonly attribute ACString nativePath; */
|
---|
964 | NS_IMETHODIMP nsLocalFile::GetNativePath(nsACString& aNativePath)
|
---|
965 | {
|
---|
966 | // Check we are correctly initialized.
|
---|
967 | CHECK_mBaseRef();
|
---|
968 |
|
---|
969 | nsresult rv = NS_ERROR_FAILURE;
|
---|
970 | CFStringRef pathStrRef = ::CFURLCopyFileSystemPath(mBaseRef, kCFURLPOSIXPathStyle);
|
---|
971 | if (pathStrRef) {
|
---|
972 | rv = CFStringReftoUTF8(pathStrRef, aNativePath);
|
---|
973 | ::CFRelease(pathStrRef);
|
---|
974 | }
|
---|
975 | return rv;
|
---|
976 | }
|
---|
977 |
|
---|
978 | /* boolean exists (); */
|
---|
979 | NS_IMETHODIMP nsLocalFile::Exists(PRBool *_retval)
|
---|
980 | {
|
---|
981 | // Check we are correctly initialized.
|
---|
982 | CHECK_mBaseRef();
|
---|
983 |
|
---|
984 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
985 | *_retval = PR_FALSE;
|
---|
986 |
|
---|
987 | FSRef fsRef;
|
---|
988 | if (NS_SUCCEEDED(GetFSRefInternal(fsRef, PR_TRUE))) {
|
---|
989 | *_retval = PR_TRUE;
|
---|
990 | }
|
---|
991 |
|
---|
992 | return NS_OK;
|
---|
993 | }
|
---|
994 |
|
---|
995 | /* boolean isWritable (); */
|
---|
996 | NS_IMETHODIMP nsLocalFile::IsWritable(PRBool *_retval)
|
---|
997 | {
|
---|
998 | // Check we are correctly initialized.
|
---|
999 | CHECK_mBaseRef();
|
---|
1000 |
|
---|
1001 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1002 | *_retval = PR_FALSE;
|
---|
1003 |
|
---|
1004 | FSRef fsRef;
|
---|
1005 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
1006 | if (NS_FAILED(rv))
|
---|
1007 | return rv;
|
---|
1008 | if (::FSCheckLock(&fsRef) == noErr) {
|
---|
1009 | PRUint32 permissions;
|
---|
1010 | rv = GetPermissions(&permissions);
|
---|
1011 | if (NS_FAILED(rv))
|
---|
1012 | return rv;
|
---|
1013 | *_retval = ((permissions & S_IWUSR) != 0);
|
---|
1014 | }
|
---|
1015 | return NS_OK;
|
---|
1016 | }
|
---|
1017 |
|
---|
1018 | /* boolean isReadable (); */
|
---|
1019 | NS_IMETHODIMP nsLocalFile::IsReadable(PRBool *_retval)
|
---|
1020 | {
|
---|
1021 | // Check we are correctly initialized.
|
---|
1022 | CHECK_mBaseRef();
|
---|
1023 |
|
---|
1024 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1025 | *_retval = PR_FALSE;
|
---|
1026 |
|
---|
1027 | PRUint32 permissions;
|
---|
1028 | nsresult rv = GetPermissions(&permissions);
|
---|
1029 | if (NS_FAILED(rv))
|
---|
1030 | return rv;
|
---|
1031 | *_retval = ((permissions & S_IRUSR) != 0);
|
---|
1032 | return NS_OK;
|
---|
1033 | }
|
---|
1034 |
|
---|
1035 | /* boolean isExecutable (); */
|
---|
1036 | NS_IMETHODIMP nsLocalFile::IsExecutable(PRBool *_retval)
|
---|
1037 | {
|
---|
1038 | // Check we are correctly initialized.
|
---|
1039 | CHECK_mBaseRef();
|
---|
1040 |
|
---|
1041 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1042 | *_retval = PR_FALSE;
|
---|
1043 |
|
---|
1044 | FSRef fsRef;
|
---|
1045 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
1046 | if (NS_FAILED(rv))
|
---|
1047 | return rv;
|
---|
1048 |
|
---|
1049 | LSRequestedInfo theInfoRequest = kLSRequestAllInfo;
|
---|
1050 | LSItemInfoRecord theInfo;
|
---|
1051 | if (::LSCopyItemInfoForRef(&fsRef, theInfoRequest, &theInfo) == noErr) {
|
---|
1052 | if ((theInfo.flags & kLSItemInfoIsApplication) != 0)
|
---|
1053 | *_retval = PR_TRUE;
|
---|
1054 | }
|
---|
1055 | return NS_OK;
|
---|
1056 | }
|
---|
1057 |
|
---|
1058 | /* boolean isHidden (); */
|
---|
1059 | NS_IMETHODIMP nsLocalFile::IsHidden(PRBool *_retval)
|
---|
1060 | {
|
---|
1061 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1062 | *_retval = PR_FALSE;
|
---|
1063 |
|
---|
1064 | FSRef fsRef;
|
---|
1065 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
1066 | if (NS_FAILED(rv))
|
---|
1067 | return rv;
|
---|
1068 |
|
---|
1069 | FSCatalogInfo catalogInfo;
|
---|
1070 | HFSUniStr255 leafName;
|
---|
1071 | OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &catalogInfo,
|
---|
1072 | &leafName, nsnull, nsnull);
|
---|
1073 | if (err != noErr)
|
---|
1074 | return MacErrorMapper(err);
|
---|
1075 |
|
---|
1076 | FileInfo *fInfoPtr = (FileInfo *)(catalogInfo.finderInfo); // Finder flags are in the same place whether we use FileInfo or FolderInfo
|
---|
1077 | if ((fInfoPtr->finderFlags & kIsInvisible) != 0) {
|
---|
1078 | *_retval = PR_TRUE;
|
---|
1079 | }
|
---|
1080 | else {
|
---|
1081 | // If the leaf name begins with a '.', consider it invisible
|
---|
1082 | if (leafName.length >= 1 && leafName.unicode[0] == UniChar('.'))
|
---|
1083 | *_retval = PR_TRUE;
|
---|
1084 | }
|
---|
1085 | return NS_OK;
|
---|
1086 | }
|
---|
1087 |
|
---|
1088 | /* boolean isDirectory (); */
|
---|
1089 | NS_IMETHODIMP nsLocalFile::IsDirectory(PRBool *_retval)
|
---|
1090 | {
|
---|
1091 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1092 | *_retval = PR_FALSE;
|
---|
1093 |
|
---|
1094 | FSRef fsRef;
|
---|
1095 | nsresult rv = GetFSRefInternal(fsRef, PR_FALSE);
|
---|
1096 | if (NS_FAILED(rv))
|
---|
1097 | return rv;
|
---|
1098 |
|
---|
1099 | FSCatalogInfo catalogInfo;
|
---|
1100 | OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags, &catalogInfo,
|
---|
1101 | nsnull, nsnull, nsnull);
|
---|
1102 | if (err != noErr)
|
---|
1103 | return MacErrorMapper(err);
|
---|
1104 | *_retval = ((catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) != 0);
|
---|
1105 | return NS_OK;
|
---|
1106 | }
|
---|
1107 |
|
---|
1108 | /* boolean isFile (); */
|
---|
1109 | NS_IMETHODIMP nsLocalFile::IsFile(PRBool *_retval)
|
---|
1110 | {
|
---|
1111 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1112 | *_retval = PR_FALSE;
|
---|
1113 |
|
---|
1114 | FSRef fsRef;
|
---|
1115 | nsresult rv = GetFSRefInternal(fsRef, PR_FALSE);
|
---|
1116 | if (NS_FAILED(rv))
|
---|
1117 | return rv;
|
---|
1118 |
|
---|
1119 | FSCatalogInfo catalogInfo;
|
---|
1120 | OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags, &catalogInfo,
|
---|
1121 | nsnull, nsnull, nsnull);
|
---|
1122 | if (err != noErr)
|
---|
1123 | return MacErrorMapper(err);
|
---|
1124 | *_retval = ((catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) == 0);
|
---|
1125 | return NS_OK;
|
---|
1126 | }
|
---|
1127 |
|
---|
1128 | /* boolean isSymlink (); */
|
---|
1129 | NS_IMETHODIMP nsLocalFile::IsSymlink(PRBool *_retval)
|
---|
1130 | {
|
---|
1131 | // Check we are correctly initialized.
|
---|
1132 | CHECK_mBaseRef();
|
---|
1133 |
|
---|
1134 | NS_ENSURE_ARG(_retval);
|
---|
1135 | *_retval = PR_FALSE;
|
---|
1136 |
|
---|
1137 | // Check we are correctly initialized.
|
---|
1138 | CHECK_mBaseRef();
|
---|
1139 |
|
---|
1140 | FSRef fsRef;
|
---|
1141 | if (::CFURLGetFSRef(mBaseRef, &fsRef)) {
|
---|
1142 | Boolean isAlias, isFolder;
|
---|
1143 | if (::FSIsAliasFile(&fsRef, &isAlias, &isFolder) == noErr)
|
---|
1144 | *_retval = isAlias;
|
---|
1145 | }
|
---|
1146 | return NS_OK;
|
---|
1147 | }
|
---|
1148 |
|
---|
1149 | /* boolean isSpecial (); */
|
---|
1150 | NS_IMETHODIMP nsLocalFile::IsSpecial(PRBool *_retval)
|
---|
1151 | {
|
---|
1152 | NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
|
---|
1153 | return NS_ERROR_NOT_IMPLEMENTED;
|
---|
1154 | }
|
---|
1155 |
|
---|
1156 | /* nsIFile clone (); */
|
---|
1157 | NS_IMETHODIMP nsLocalFile::Clone(nsIFile **_retval)
|
---|
1158 | {
|
---|
1159 | // Just copy-construct ourselves
|
---|
1160 | *_retval = new nsLocalFile(*this);
|
---|
1161 | if (!*_retval)
|
---|
1162 | return NS_ERROR_OUT_OF_MEMORY;
|
---|
1163 |
|
---|
1164 | NS_ADDREF(*_retval);
|
---|
1165 |
|
---|
1166 | return NS_OK;
|
---|
1167 | }
|
---|
1168 |
|
---|
1169 | /* boolean equals (in nsIFile inFile); */
|
---|
1170 | NS_IMETHODIMP nsLocalFile::Equals(nsIFile *inFile, PRBool *_retval)
|
---|
1171 | {
|
---|
1172 | return EqualsInternal(inFile, PR_TRUE, _retval);
|
---|
1173 | }
|
---|
1174 |
|
---|
1175 | nsresult
|
---|
1176 | nsLocalFile::EqualsInternal(nsISupports* inFile, PRBool aUpdateCache,
|
---|
1177 | PRBool *_retval)
|
---|
1178 | {
|
---|
1179 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1180 | *_retval = PR_FALSE;
|
---|
1181 |
|
---|
1182 | nsCOMPtr<nsILocalFileMac> inMacFile(do_QueryInterface(inFile));
|
---|
1183 | if (!inFile)
|
---|
1184 | return NS_OK;
|
---|
1185 |
|
---|
1186 | nsLocalFile* inLF =
|
---|
1187 | NS_STATIC_CAST(nsLocalFile*, (nsILocalFileMac*) inMacFile);
|
---|
1188 |
|
---|
1189 | // If both exist, compare FSRefs
|
---|
1190 | FSRef thisFSRef, inFSRef;
|
---|
1191 | nsresult rv1 = GetFSRefInternal(thisFSRef, aUpdateCache);
|
---|
1192 | nsresult rv2 = inLF->GetFSRefInternal(inFSRef, aUpdateCache);
|
---|
1193 | if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) {
|
---|
1194 | *_retval = (thisFSRef == inFSRef);
|
---|
1195 | return NS_OK;
|
---|
1196 | }
|
---|
1197 | // If one exists and the other doesn't, not equal
|
---|
1198 | if (rv1 != rv2)
|
---|
1199 | return NS_OK;
|
---|
1200 |
|
---|
1201 | // Arg, we have to get their paths and compare
|
---|
1202 | nsCAutoString thisPath, inPath;
|
---|
1203 | if (NS_FAILED(GetNativePath(thisPath)))
|
---|
1204 | return NS_ERROR_FAILURE;
|
---|
1205 | if (NS_FAILED(inMacFile->GetNativePath(inPath)))
|
---|
1206 | return NS_ERROR_FAILURE;
|
---|
1207 | *_retval = thisPath.Equals(inPath);
|
---|
1208 |
|
---|
1209 | return NS_OK;
|
---|
1210 | }
|
---|
1211 |
|
---|
1212 | /* boolean contains (in nsIFile inFile, in boolean recur); */
|
---|
1213 | NS_IMETHODIMP nsLocalFile::Contains(nsIFile *inFile, PRBool recur, PRBool *_retval)
|
---|
1214 | {
|
---|
1215 | // Check we are correctly initialized.
|
---|
1216 | CHECK_mBaseRef();
|
---|
1217 |
|
---|
1218 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1219 | *_retval = PR_FALSE;
|
---|
1220 |
|
---|
1221 | PRBool isDir;
|
---|
1222 | nsresult rv = IsDirectory(&isDir);
|
---|
1223 | if (NS_FAILED(rv))
|
---|
1224 | return rv;
|
---|
1225 | if (!isDir)
|
---|
1226 | return NS_OK; // must be a dir to contain someone
|
---|
1227 |
|
---|
1228 | nsCAutoString thisPath, inPath;
|
---|
1229 | if (NS_FAILED(GetNativePath(thisPath)) || NS_FAILED(inFile->GetNativePath(inPath)))
|
---|
1230 | return NS_ERROR_FAILURE;
|
---|
1231 | size_t thisPathLen = thisPath.Length();
|
---|
1232 | if ((inPath.Length() > thisPathLen + 1) && (strncasecmp(thisPath.get(), inPath.get(), thisPathLen) == 0)) {
|
---|
1233 | // Now make sure that the |inFile|'s path has a separator at thisPathLen,
|
---|
1234 | // and there's at least one more character after that.
|
---|
1235 | if (inPath[thisPathLen] == kPathSepChar)
|
---|
1236 | *_retval = PR_TRUE;
|
---|
1237 | }
|
---|
1238 | return NS_OK;
|
---|
1239 | }
|
---|
1240 |
|
---|
1241 | /* readonly attribute nsIFile parent; */
|
---|
1242 | NS_IMETHODIMP nsLocalFile::GetParent(nsIFile * *aParent)
|
---|
1243 | {
|
---|
1244 | NS_ENSURE_ARG_POINTER(aParent);
|
---|
1245 | *aParent = nsnull;
|
---|
1246 |
|
---|
1247 | // Check we are correctly initialized.
|
---|
1248 | CHECK_mBaseRef();
|
---|
1249 |
|
---|
1250 | nsLocalFile *newFile = nsnull;
|
---|
1251 |
|
---|
1252 | // If it can be determined without error that a file does not
|
---|
1253 | // have a parent, return nsnull for the parent and NS_OK as the result.
|
---|
1254 | // See bug 133617.
|
---|
1255 | nsresult rv = NS_OK;
|
---|
1256 | CFURLRef parentURLRef = ::CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, mBaseRef);
|
---|
1257 | if (parentURLRef) {
|
---|
1258 | rv = NS_ERROR_FAILURE;
|
---|
1259 | newFile = new nsLocalFile;
|
---|
1260 | if (newFile) {
|
---|
1261 | rv = newFile->InitWithCFURL(parentURLRef);
|
---|
1262 | if (NS_SUCCEEDED(rv)) {
|
---|
1263 | NS_ADDREF(*aParent = newFile);
|
---|
1264 | rv = NS_OK;
|
---|
1265 | }
|
---|
1266 | }
|
---|
1267 | ::CFRelease(parentURLRef);
|
---|
1268 | }
|
---|
1269 | return rv;
|
---|
1270 | }
|
---|
1271 |
|
---|
1272 | /* readonly attribute nsISimpleEnumerator directoryEntries; */
|
---|
1273 | NS_IMETHODIMP nsLocalFile::GetDirectoryEntries(nsISimpleEnumerator **aDirectoryEntries)
|
---|
1274 | {
|
---|
1275 | NS_ENSURE_ARG_POINTER(aDirectoryEntries);
|
---|
1276 | *aDirectoryEntries = nsnull;
|
---|
1277 |
|
---|
1278 | nsresult rv;
|
---|
1279 | PRBool isDir;
|
---|
1280 | rv = IsDirectory(&isDir);
|
---|
1281 | if (NS_FAILED(rv))
|
---|
1282 | return rv;
|
---|
1283 | if (!isDir)
|
---|
1284 | return NS_ERROR_FILE_NOT_DIRECTORY;
|
---|
1285 |
|
---|
1286 | nsDirEnumerator* dirEnum = new nsDirEnumerator;
|
---|
1287 | if (dirEnum == nsnull)
|
---|
1288 | return NS_ERROR_OUT_OF_MEMORY;
|
---|
1289 | NS_ADDREF(dirEnum);
|
---|
1290 | rv = dirEnum->Init(this);
|
---|
1291 | if (NS_FAILED(rv)) {
|
---|
1292 | NS_RELEASE(dirEnum);
|
---|
1293 | return rv;
|
---|
1294 | }
|
---|
1295 | *aDirectoryEntries = dirEnum;
|
---|
1296 |
|
---|
1297 | return NS_OK;
|
---|
1298 | }
|
---|
1299 |
|
---|
1300 |
|
---|
1301 | //*****************************************************************************
|
---|
1302 | // nsLocalFile::nsILocalFile
|
---|
1303 | //*****************************************************************************
|
---|
1304 | #pragma mark -
|
---|
1305 | #pragma mark [nsILocalFile]
|
---|
1306 |
|
---|
1307 | /* void initWithPath (in AString filePath); */
|
---|
1308 | NS_IMETHODIMP nsLocalFile::InitWithPath(const nsAString& filePath)
|
---|
1309 | {
|
---|
1310 | return InitWithNativePath(NS_ConvertUTF16toUTF8(filePath));
|
---|
1311 | }
|
---|
1312 |
|
---|
1313 | /* [noscript] void initWithNativePath (in ACString filePath); */
|
---|
1314 | NS_IMETHODIMP nsLocalFile::InitWithNativePath(const nsACString& filePath)
|
---|
1315 | {
|
---|
1316 | nsCAutoString fixedPath;
|
---|
1317 | if (Substring(filePath, 0, 2).EqualsLiteral("~/")) {
|
---|
1318 | nsCOMPtr<nsIFile> homeDir;
|
---|
1319 | nsCAutoString homePath;
|
---|
1320 | nsresult rv = NS_GetSpecialDirectory(NS_OS_HOME_DIR,
|
---|
1321 | getter_AddRefs(homeDir));
|
---|
1322 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
1323 | rv = homeDir->GetNativePath(homePath);
|
---|
1324 | NS_ENSURE_SUCCESS(rv, rv);
|
---|
1325 |
|
---|
1326 | fixedPath = homePath + Substring(filePath, 1, filePath.Length() - 1);
|
---|
1327 | }
|
---|
1328 | else if (filePath.IsEmpty() || filePath.First() != '/')
|
---|
1329 | return NS_ERROR_FILE_UNRECOGNIZED_PATH;
|
---|
1330 | else
|
---|
1331 | fixedPath.Assign(filePath);
|
---|
1332 |
|
---|
1333 | // A path with consecutive '/'s which are not between
|
---|
1334 | // nodes crashes CFURLGetFSRef(). Consecutive '/'s which
|
---|
1335 | // are between actual nodes are OK. So, convert consecutive
|
---|
1336 | // '/'s to a single one.
|
---|
1337 | fixedPath.ReplaceSubstring("//", "/");
|
---|
1338 |
|
---|
1339 | #if 1 // bird: hack to fix RegistryLocationForSpec issues with /path/to/./components
|
---|
1340 | fixedPath.ReplaceSubstring("/./", "/");
|
---|
1341 | size_t len = fixedPath.Length();
|
---|
1342 | while (len > 2)
|
---|
1343 | {
|
---|
1344 | size_t choplen = 0;
|
---|
1345 | if (!strcmp(fixedPath.get() + len - 2, "/."))
|
---|
1346 | choplen = 2;
|
---|
1347 | else if (!strcmp(fixedPath.get() + len - 1, "/"))
|
---|
1348 | choplen = 1;
|
---|
1349 | else
|
---|
1350 | break;
|
---|
1351 | fixedPath = StringHead(fixedPath, len - choplen);
|
---|
1352 | }
|
---|
1353 | // bird: another hack for the issue with VirtualBoxVM and symlinks...
|
---|
1354 | char tmpBuf[PATH_MAX];
|
---|
1355 | if (realpath(fixedPath.get(), tmpBuf))
|
---|
1356 | fixedPath = tmpBuf;
|
---|
1357 | #endif
|
---|
1358 |
|
---|
1359 | // On 10.2, huge paths also crash CFURLGetFSRef()
|
---|
1360 | if (fixedPath.Length() > PATH_MAX)
|
---|
1361 | return NS_ERROR_FILE_NAME_TOO_LONG;
|
---|
1362 |
|
---|
1363 | CFStringRef pathAsCFString;
|
---|
1364 | CFURLRef pathAsCFURL;
|
---|
1365 |
|
---|
1366 | pathAsCFString = ::CFStringCreateWithCString(nsnull, fixedPath.get(), kCFStringEncodingUTF8);
|
---|
1367 | if (!pathAsCFString)
|
---|
1368 | return NS_ERROR_FAILURE;
|
---|
1369 | pathAsCFURL = ::CFURLCreateWithFileSystemPath(nsnull, pathAsCFString, kCFURLPOSIXPathStyle, PR_FALSE);
|
---|
1370 | if (!pathAsCFURL) {
|
---|
1371 | ::CFRelease(pathAsCFString);
|
---|
1372 | return NS_ERROR_FAILURE;
|
---|
1373 | }
|
---|
1374 | SetBaseRef(pathAsCFURL);
|
---|
1375 | ::CFRelease(pathAsCFURL);
|
---|
1376 | ::CFRelease(pathAsCFString);
|
---|
1377 | return NS_OK;
|
---|
1378 | }
|
---|
1379 |
|
---|
1380 | /* void initWithFile (in nsILocalFile aFile); */
|
---|
1381 | NS_IMETHODIMP nsLocalFile::InitWithFile(nsILocalFile *aFile)
|
---|
1382 | {
|
---|
1383 | NS_ENSURE_ARG(aFile);
|
---|
1384 |
|
---|
1385 | nsCOMPtr<nsILocalFileMac> aFileMac(do_QueryInterface(aFile));
|
---|
1386 | if (!aFileMac)
|
---|
1387 | return NS_ERROR_UNEXPECTED;
|
---|
1388 | CFURLRef urlRef;
|
---|
1389 | nsresult rv = aFileMac->GetCFURL(&urlRef);
|
---|
1390 | if (NS_FAILED(rv))
|
---|
1391 | return rv;
|
---|
1392 | rv = InitWithCFURL(urlRef);
|
---|
1393 | ::CFRelease(urlRef);
|
---|
1394 | return rv;
|
---|
1395 | }
|
---|
1396 |
|
---|
1397 | /* attribute PRBool followLinks; */
|
---|
1398 | NS_IMETHODIMP nsLocalFile::GetFollowLinks(PRBool *aFollowLinks)
|
---|
1399 | {
|
---|
1400 | NS_ENSURE_ARG_POINTER(aFollowLinks);
|
---|
1401 |
|
---|
1402 | *aFollowLinks = mFollowLinks;
|
---|
1403 | return NS_OK;
|
---|
1404 | }
|
---|
1405 |
|
---|
1406 | NS_IMETHODIMP nsLocalFile::SetFollowLinks(PRBool aFollowLinks)
|
---|
1407 | {
|
---|
1408 | if (aFollowLinks != mFollowLinks) {
|
---|
1409 | mFollowLinks = aFollowLinks;
|
---|
1410 | UpdateTargetRef();
|
---|
1411 | }
|
---|
1412 | return NS_OK;
|
---|
1413 | }
|
---|
1414 |
|
---|
1415 | /* [noscript] PRFileDescStar openNSPRFileDesc (in long flags, in long mode); */
|
---|
1416 | NS_IMETHODIMP nsLocalFile::OpenNSPRFileDesc(PRInt32 flags, PRInt32 mode, PRFileDesc **_retval)
|
---|
1417 | {
|
---|
1418 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1419 |
|
---|
1420 | nsCAutoString path;
|
---|
1421 | nsresult rv = GetPathInternal(path);
|
---|
1422 | if (NS_FAILED(rv))
|
---|
1423 | return rv;
|
---|
1424 |
|
---|
1425 | *_retval = PR_Open(path.get(), flags, mode);
|
---|
1426 | if (! *_retval)
|
---|
1427 | return NS_ErrorAccordingToNSPR();
|
---|
1428 |
|
---|
1429 | return NS_OK;
|
---|
1430 | }
|
---|
1431 |
|
---|
1432 | /* [noscript] FILE openANSIFileDesc (in string mode); */
|
---|
1433 | NS_IMETHODIMP nsLocalFile::OpenANSIFileDesc(const char *mode, FILE **_retval)
|
---|
1434 | {
|
---|
1435 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1436 |
|
---|
1437 | nsCAutoString path;
|
---|
1438 | nsresult rv = GetPathInternal(path);
|
---|
1439 | if (NS_FAILED(rv))
|
---|
1440 | return rv;
|
---|
1441 |
|
---|
1442 | *_retval = fopen(path.get(), mode);
|
---|
1443 | if (! *_retval)
|
---|
1444 | return NS_ERROR_FAILURE;
|
---|
1445 |
|
---|
1446 | return NS_OK;
|
---|
1447 | }
|
---|
1448 |
|
---|
1449 | /* [noscript] PRLibraryStar load (); */
|
---|
1450 | NS_IMETHODIMP nsLocalFile::Load(PRLibrary **_retval)
|
---|
1451 | {
|
---|
1452 | // Check we are correctly initialized.
|
---|
1453 | CHECK_mBaseRef();
|
---|
1454 |
|
---|
1455 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1456 |
|
---|
1457 | NS_TIMELINE_START_TIMER("PR_LoadLibrary");
|
---|
1458 |
|
---|
1459 | nsCAutoString path;
|
---|
1460 | nsresult rv = GetPathInternal(path);
|
---|
1461 | if (NS_FAILED(rv))
|
---|
1462 | return rv;
|
---|
1463 |
|
---|
1464 | #ifdef NS_BUILD_REFCNT_LOGGING
|
---|
1465 | nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
|
---|
1466 | #endif
|
---|
1467 |
|
---|
1468 | *_retval = PR_LoadLibrary(path.get());
|
---|
1469 |
|
---|
1470 | #ifdef NS_BUILD_REFCNT_LOGGING
|
---|
1471 | nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
|
---|
1472 | #endif
|
---|
1473 |
|
---|
1474 | NS_TIMELINE_STOP_TIMER("PR_LoadLibrary");
|
---|
1475 | NS_TIMELINE_MARK_TIMER1("PR_LoadLibrary", path.get());
|
---|
1476 |
|
---|
1477 | if (!*_retval)
|
---|
1478 | return NS_ERROR_FAILURE;
|
---|
1479 |
|
---|
1480 | return NS_OK;
|
---|
1481 | }
|
---|
1482 |
|
---|
1483 | /* readonly attribute PRInt64 diskSpaceAvailable; */
|
---|
1484 | NS_IMETHODIMP nsLocalFile::GetDiskSpaceAvailable(PRInt64 *aDiskSpaceAvailable)
|
---|
1485 | {
|
---|
1486 | // Check we are correctly initialized.
|
---|
1487 | CHECK_mBaseRef();
|
---|
1488 |
|
---|
1489 | NS_ENSURE_ARG_POINTER(aDiskSpaceAvailable);
|
---|
1490 |
|
---|
1491 | FSRef fsRef;
|
---|
1492 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
1493 | if (NS_FAILED(rv))
|
---|
1494 | return rv;
|
---|
1495 |
|
---|
1496 | OSErr err;
|
---|
1497 | FSCatalogInfo catalogInfo;
|
---|
1498 | err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoVolume, &catalogInfo,
|
---|
1499 | nsnull, nsnull, nsnull);
|
---|
1500 | if (err != noErr)
|
---|
1501 | return MacErrorMapper(err);
|
---|
1502 |
|
---|
1503 | FSVolumeInfo volumeInfo;
|
---|
1504 | err = ::FSGetVolumeInfo(catalogInfo.volume, 0, nsnull, kFSVolInfoSizes,
|
---|
1505 | &volumeInfo, nsnull, nsnull);
|
---|
1506 | if (err != noErr)
|
---|
1507 | return MacErrorMapper(err);
|
---|
1508 |
|
---|
1509 | *aDiskSpaceAvailable = volumeInfo.freeBytes;
|
---|
1510 | return NS_OK;
|
---|
1511 | }
|
---|
1512 |
|
---|
1513 | /* void appendRelativePath (in AString relativeFilePath); */
|
---|
1514 | NS_IMETHODIMP nsLocalFile::AppendRelativePath(const nsAString& relativeFilePath)
|
---|
1515 | {
|
---|
1516 | return AppendRelativeNativePath(NS_ConvertUTF16toUTF8(relativeFilePath));
|
---|
1517 | }
|
---|
1518 |
|
---|
1519 | /* [noscript] void appendRelativeNativePath (in ACString relativeFilePath); */
|
---|
1520 | NS_IMETHODIMP nsLocalFile::AppendRelativeNativePath(const nsACString& relativeFilePath)
|
---|
1521 | {
|
---|
1522 | if (relativeFilePath.IsEmpty())
|
---|
1523 | return NS_OK;
|
---|
1524 | // No leading '/'
|
---|
1525 | if (relativeFilePath.First() == '/')
|
---|
1526 | return NS_ERROR_FILE_UNRECOGNIZED_PATH;
|
---|
1527 |
|
---|
1528 | // Parse the nodes and call Append() for each
|
---|
1529 | nsACString::const_iterator nodeBegin, pathEnd;
|
---|
1530 | relativeFilePath.BeginReading(nodeBegin);
|
---|
1531 | relativeFilePath.EndReading(pathEnd);
|
---|
1532 | nsACString::const_iterator nodeEnd(nodeBegin);
|
---|
1533 |
|
---|
1534 | while (nodeEnd != pathEnd) {
|
---|
1535 | FindCharInReadable(kPathSepChar, nodeEnd, pathEnd);
|
---|
1536 | nsresult rv = AppendNative(Substring(nodeBegin, nodeEnd));
|
---|
1537 | if (NS_FAILED(rv))
|
---|
1538 | return rv;
|
---|
1539 | if (nodeEnd != pathEnd) // If there's more left in the string, inc over the '/' nodeEnd is on.
|
---|
1540 | ++nodeEnd;
|
---|
1541 | nodeBegin = nodeEnd;
|
---|
1542 | }
|
---|
1543 | return NS_OK;
|
---|
1544 | }
|
---|
1545 |
|
---|
1546 | /* attribute ACString persistentDescriptor; */
|
---|
1547 | NS_IMETHODIMP nsLocalFile::GetPersistentDescriptor(nsACString& aPersistentDescriptor)
|
---|
1548 | {
|
---|
1549 | FSRef fsRef;
|
---|
1550 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
1551 | if (NS_FAILED(rv))
|
---|
1552 | return rv;
|
---|
1553 |
|
---|
1554 | AliasHandle aliasH;
|
---|
1555 | OSErr err = ::FSNewAlias(nsnull, &fsRef, &aliasH);
|
---|
1556 | if (err != noErr)
|
---|
1557 | return MacErrorMapper(err);
|
---|
1558 |
|
---|
1559 | PRUint32 bytes = ::GetHandleSize((Handle) aliasH);
|
---|
1560 | ::HLock((Handle) aliasH);
|
---|
1561 | // Passing nsnull for dest makes NULL-term string
|
---|
1562 | char* buf = PL_Base64Encode((const char*)*aliasH, bytes, nsnull);
|
---|
1563 | ::DisposeHandle((Handle) aliasH);
|
---|
1564 | NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
|
---|
1565 |
|
---|
1566 | aPersistentDescriptor = buf;
|
---|
1567 | PR_Free(buf);
|
---|
1568 |
|
---|
1569 | return NS_OK;
|
---|
1570 | }
|
---|
1571 |
|
---|
1572 | NS_IMETHODIMP nsLocalFile::SetPersistentDescriptor(const nsACString& aPersistentDescriptor)
|
---|
1573 | {
|
---|
1574 | if (aPersistentDescriptor.IsEmpty())
|
---|
1575 | return NS_ERROR_INVALID_ARG;
|
---|
1576 |
|
---|
1577 | // Support pathnames as user-supplied descriptors if they begin with '/'
|
---|
1578 | // or '~'. These characters do not collide with the base64 set used for
|
---|
1579 | // encoding alias records.
|
---|
1580 | char first = aPersistentDescriptor.First();
|
---|
1581 | if (first == '/' || first == '~')
|
---|
1582 | return InitWithNativePath(aPersistentDescriptor);
|
---|
1583 |
|
---|
1584 | nsresult rv = NS_OK;
|
---|
1585 |
|
---|
1586 | PRUint32 dataSize = aPersistentDescriptor.Length();
|
---|
1587 | char* decodedData = PL_Base64Decode(PromiseFlatCString(aPersistentDescriptor).get(), dataSize, nsnull);
|
---|
1588 | if (!decodedData) {
|
---|
1589 | NS_ERROR("SetPersistentDescriptor was given bad data");
|
---|
1590 | return NS_ERROR_FAILURE;
|
---|
1591 | }
|
---|
1592 |
|
---|
1593 | // Cast to an alias record and resolve.
|
---|
1594 | AliasRecord aliasHeader = *(AliasPtr)decodedData;
|
---|
1595 | PRInt32 aliasSize = GetAliasSizeFromRecord(aliasHeader);
|
---|
1596 | if (aliasSize > (dataSize * 3) / 4) { // be paranoid about having too few data
|
---|
1597 | PR_Free(decodedData);
|
---|
1598 | return NS_ERROR_FAILURE;
|
---|
1599 | }
|
---|
1600 |
|
---|
1601 | // Move the now-decoded data into the Handle.
|
---|
1602 | // The size of the decoded data is 3/4 the size of the encoded data. See plbase64.h
|
---|
1603 | Handle newHandle = nsnull;
|
---|
1604 | if (::PtrToHand(decodedData, &newHandle, aliasSize) != noErr)
|
---|
1605 | rv = NS_ERROR_OUT_OF_MEMORY;
|
---|
1606 | PR_Free(decodedData);
|
---|
1607 | if (NS_FAILED(rv))
|
---|
1608 | return rv;
|
---|
1609 |
|
---|
1610 | Boolean changed;
|
---|
1611 | FSRef resolvedFSRef;
|
---|
1612 | OSErr err = ::FSResolveAlias(nsnull, (AliasHandle)newHandle, &resolvedFSRef, &changed);
|
---|
1613 |
|
---|
1614 | rv = MacErrorMapper(err);
|
---|
1615 | DisposeHandle(newHandle);
|
---|
1616 | if (NS_FAILED(rv))
|
---|
1617 | return rv;
|
---|
1618 |
|
---|
1619 | return InitWithFSRef(&resolvedFSRef);
|
---|
1620 | }
|
---|
1621 |
|
---|
1622 | /* void reveal (); */
|
---|
1623 | NS_IMETHODIMP nsLocalFile::Reveal()
|
---|
1624 | {
|
---|
1625 | FSRef fsRefToReveal;
|
---|
1626 | AppleEvent aeEvent = {0, nil};
|
---|
1627 | AppleEvent aeReply = {0, nil};
|
---|
1628 | StAEDesc aeDirDesc, listElem, myAddressDesc, fileList;
|
---|
1629 | OSErr err;
|
---|
1630 | ProcessSerialNumber process;
|
---|
1631 |
|
---|
1632 | nsresult rv = GetFSRefInternal(fsRefToReveal);
|
---|
1633 | if (NS_FAILED(rv))
|
---|
1634 | return rv;
|
---|
1635 |
|
---|
1636 | err = ::FindRunningAppBySignature ('MACS', process);
|
---|
1637 | if (err == noErr) {
|
---|
1638 | err = ::AECreateDesc(typeProcessSerialNumber, (Ptr)&process, sizeof(process), &myAddressDesc);
|
---|
1639 | if (err == noErr) {
|
---|
1640 | // Create the FinderEvent
|
---|
1641 | err = ::AECreateAppleEvent(kAEMiscStandards, kAEMakeObjectsVisible, &myAddressDesc,
|
---|
1642 | kAutoGenerateReturnID, kAnyTransactionID, &aeEvent);
|
---|
1643 | if (err == noErr) {
|
---|
1644 | // Create the file list
|
---|
1645 | err = ::AECreateList(nil, 0, false, &fileList);
|
---|
1646 | if (err == noErr) {
|
---|
1647 | FSSpec fsSpecToReveal;
|
---|
1648 | err = ::FSRefMakeFSSpec(&fsRefToReveal, &fsSpecToReveal);
|
---|
1649 | if (err == noErr) {
|
---|
1650 | err = ::AEPutPtr(&fileList, 0, typeFSS, &fsSpecToReveal, sizeof(FSSpec));
|
---|
1651 | if (err == noErr) {
|
---|
1652 | err = ::AEPutParamDesc(&aeEvent, keyDirectObject, &fileList);
|
---|
1653 | if (err == noErr) {
|
---|
1654 | err = ::AESend(&aeEvent, &aeReply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
|
---|
1655 | if (err == noErr)
|
---|
1656 | ::SetFrontProcess(&process);
|
---|
1657 | }
|
---|
1658 | }
|
---|
1659 | }
|
---|
1660 | }
|
---|
1661 | }
|
---|
1662 | }
|
---|
1663 | }
|
---|
1664 |
|
---|
1665 | return NS_OK;
|
---|
1666 | }
|
---|
1667 |
|
---|
1668 | /* void launch (); */
|
---|
1669 | NS_IMETHODIMP nsLocalFile::Launch()
|
---|
1670 | {
|
---|
1671 | FSRef fsRef;
|
---|
1672 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
1673 | if (NS_FAILED(rv))
|
---|
1674 | return rv;
|
---|
1675 |
|
---|
1676 | OSErr err = ::LSOpenFSRef(&fsRef, NULL);
|
---|
1677 | return MacErrorMapper(err);
|
---|
1678 | }
|
---|
1679 |
|
---|
1680 |
|
---|
1681 | //*****************************************************************************
|
---|
1682 | // nsLocalFile::nsILocalFileMac
|
---|
1683 | //*****************************************************************************
|
---|
1684 | #pragma mark -
|
---|
1685 | #pragma mark [nsILocalFileMac]
|
---|
1686 |
|
---|
1687 | /* void initWithCFURL (in CFURLRef aCFURL); */
|
---|
1688 | NS_IMETHODIMP nsLocalFile::InitWithCFURL(CFURLRef aCFURL)
|
---|
1689 | {
|
---|
1690 | NS_ENSURE_ARG(aCFURL);
|
---|
1691 |
|
---|
1692 | SetBaseRef(aCFURL);
|
---|
1693 | return NS_OK;
|
---|
1694 | }
|
---|
1695 |
|
---|
1696 | /* void initWithFSRef ([const] in FSRefPtr aFSRef); */
|
---|
1697 | NS_IMETHODIMP nsLocalFile::InitWithFSRef(const FSRef *aFSRef)
|
---|
1698 | {
|
---|
1699 | NS_ENSURE_ARG(aFSRef);
|
---|
1700 | nsresult rv = NS_ERROR_FAILURE;
|
---|
1701 |
|
---|
1702 | CFURLRef newURLRef = ::CFURLCreateFromFSRef(kCFAllocatorDefault, aFSRef);
|
---|
1703 | if (newURLRef) {
|
---|
1704 | SetBaseRef(newURLRef);
|
---|
1705 | ::CFRelease(newURLRef);
|
---|
1706 | rv = NS_OK;
|
---|
1707 | }
|
---|
1708 | return rv;
|
---|
1709 | }
|
---|
1710 |
|
---|
1711 | /* void initWithFSSpec ([const] in FSSpecPtr aFileSpec); */
|
---|
1712 | NS_IMETHODIMP nsLocalFile::InitWithFSSpec(const FSSpec *aFileSpec)
|
---|
1713 | {
|
---|
1714 | NS_ENSURE_ARG(aFileSpec);
|
---|
1715 |
|
---|
1716 | FSRef fsRef;
|
---|
1717 | OSErr err = ::FSpMakeFSRef(aFileSpec, &fsRef);
|
---|
1718 | if (err == noErr)
|
---|
1719 | return InitWithFSRef(&fsRef);
|
---|
1720 | else if (err == fnfErr) {
|
---|
1721 | CInfoPBRec pBlock;
|
---|
1722 | FSSpec parentDirSpec;
|
---|
1723 |
|
---|
1724 | memset(&pBlock, 0, sizeof(CInfoPBRec));
|
---|
1725 | parentDirSpec.name[0] = 0;
|
---|
1726 | pBlock.dirInfo.ioVRefNum = aFileSpec->vRefNum;
|
---|
1727 | pBlock.dirInfo.ioDrDirID = aFileSpec->parID;
|
---|
1728 | pBlock.dirInfo.ioNamePtr = (StringPtr)parentDirSpec.name;
|
---|
1729 | pBlock.dirInfo.ioFDirIndex = -1; //get info on parID
|
---|
1730 | err = ::PBGetCatInfoSync(&pBlock);
|
---|
1731 | if (err != noErr)
|
---|
1732 | return MacErrorMapper(err);
|
---|
1733 |
|
---|
1734 | parentDirSpec.vRefNum = aFileSpec->vRefNum;
|
---|
1735 | parentDirSpec.parID = pBlock.dirInfo.ioDrParID;
|
---|
1736 | err = ::FSpMakeFSRef(&parentDirSpec, &fsRef);
|
---|
1737 | if (err != noErr)
|
---|
1738 | return MacErrorMapper(err);
|
---|
1739 | HFSUniStr255 unicodeName;
|
---|
1740 | err = ::HFSNameGetUnicodeName(aFileSpec->name, kTextEncodingUnknown, &unicodeName);
|
---|
1741 | if (err != noErr)
|
---|
1742 | return MacErrorMapper(err);
|
---|
1743 | nsresult rv = InitWithFSRef(&fsRef);
|
---|
1744 | if (NS_FAILED(rv))
|
---|
1745 | return rv;
|
---|
1746 | return Append(nsDependentString(unicodeName.unicode, unicodeName.length));
|
---|
1747 | }
|
---|
1748 | return MacErrorMapper(err);
|
---|
1749 | }
|
---|
1750 |
|
---|
1751 | /* void initToAppWithCreatorCode (in OSType aAppCreator); */
|
---|
1752 | NS_IMETHODIMP nsLocalFile::InitToAppWithCreatorCode(OSType aAppCreator)
|
---|
1753 | {
|
---|
1754 | FSRef fsRef;
|
---|
1755 | OSErr err = ::LSFindApplicationForInfo(aAppCreator, nsnull, nsnull, &fsRef, nsnull);
|
---|
1756 | if (err != noErr)
|
---|
1757 | return MacErrorMapper(err);
|
---|
1758 | return InitWithFSRef(&fsRef);
|
---|
1759 | }
|
---|
1760 |
|
---|
1761 | /* CFURLRef getCFURL (); */
|
---|
1762 | NS_IMETHODIMP nsLocalFile::GetCFURL(CFURLRef *_retval)
|
---|
1763 | {
|
---|
1764 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1765 | CFURLRef whichURLRef = mFollowLinks ? mTargetRef : mBaseRef;
|
---|
1766 | if (whichURLRef)
|
---|
1767 | ::CFRetain(whichURLRef);
|
---|
1768 | *_retval = whichURLRef;
|
---|
1769 | return whichURLRef ? NS_OK : NS_ERROR_FAILURE;
|
---|
1770 | }
|
---|
1771 |
|
---|
1772 | /* FSRef getFSRef (); */
|
---|
1773 | NS_IMETHODIMP nsLocalFile::GetFSRef(FSRef *_retval)
|
---|
1774 | {
|
---|
1775 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1776 | return GetFSRefInternal(*_retval);
|
---|
1777 | }
|
---|
1778 |
|
---|
1779 | /* FSSpec getFSSpec (); */
|
---|
1780 | NS_IMETHODIMP nsLocalFile::GetFSSpec(FSSpec *_retval)
|
---|
1781 | {
|
---|
1782 | NS_ENSURE_ARG_POINTER(_retval);
|
---|
1783 |
|
---|
1784 | // Check we are correctly initialized.
|
---|
1785 | CHECK_mBaseRef();
|
---|
1786 |
|
---|
1787 | OSErr err;
|
---|
1788 | FSRef fsRef;
|
---|
1789 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
1790 | if (NS_SUCCEEDED(rv)) {
|
---|
1791 | // If the leaf node exists, things are simple.
|
---|
1792 | err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNone,
|
---|
1793 | nsnull, nsnull, _retval, nsnull);
|
---|
1794 | return MacErrorMapper(err);
|
---|
1795 | }
|
---|
1796 | else if (rv == NS_ERROR_FILE_NOT_FOUND) {
|
---|
1797 | // If the parent of the leaf exists, make an FSSpec from that.
|
---|
1798 | CFURLRef parentURLRef = ::CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, mBaseRef);
|
---|
1799 | if (!parentURLRef)
|
---|
1800 | return NS_ERROR_FAILURE;
|
---|
1801 |
|
---|
1802 | err = fnfErr;
|
---|
1803 | if (::CFURLGetFSRef(parentURLRef, &fsRef)) {
|
---|
1804 | FSCatalogInfo catalogInfo;
|
---|
1805 | if ((err = ::FSGetCatalogInfo(&fsRef,
|
---|
1806 | kFSCatInfoVolume + kFSCatInfoNodeID + kFSCatInfoTextEncoding,
|
---|
1807 | &catalogInfo, nsnull, nsnull, nsnull)) == noErr) {
|
---|
1808 | nsAutoString leafName;
|
---|
1809 | if (NS_SUCCEEDED(GetLeafName(leafName))) {
|
---|
1810 | Str31 hfsName;
|
---|
1811 | if ((err = ::UnicodeNameGetHFSName(leafName.Length(),
|
---|
1812 | leafName.get(),
|
---|
1813 | catalogInfo.textEncodingHint,
|
---|
1814 | catalogInfo.nodeID == fsRtDirID,
|
---|
1815 | hfsName)) == noErr)
|
---|
1816 | err = ::FSMakeFSSpec(catalogInfo.volume, catalogInfo.nodeID, hfsName, _retval);
|
---|
1817 | }
|
---|
1818 | }
|
---|
1819 | }
|
---|
1820 | ::CFRelease(parentURLRef);
|
---|
1821 | rv = MacErrorMapper(err);
|
---|
1822 | }
|
---|
1823 | return rv;
|
---|
1824 | }
|
---|
1825 |
|
---|
1826 | /* readonly attribute PRInt64 fileSizeWithResFork; */
|
---|
1827 | NS_IMETHODIMP nsLocalFile::GetFileSizeWithResFork(PRInt64 *aFileSizeWithResFork)
|
---|
1828 | {
|
---|
1829 | NS_ENSURE_ARG_POINTER(aFileSizeWithResFork);
|
---|
1830 |
|
---|
1831 | FSRef fsRef;
|
---|
1832 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
1833 | if (NS_FAILED(rv))
|
---|
1834 | return rv;
|
---|
1835 |
|
---|
1836 | FSCatalogInfo catalogInfo;
|
---|
1837 | OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoDataSizes + kFSCatInfoRsrcSizes,
|
---|
1838 | &catalogInfo, nsnull, nsnull, nsnull);
|
---|
1839 | if (err != noErr)
|
---|
1840 | return MacErrorMapper(err);
|
---|
1841 |
|
---|
1842 | *aFileSizeWithResFork = catalogInfo.dataLogicalSize + catalogInfo.rsrcLogicalSize;
|
---|
1843 | return NS_OK;
|
---|
1844 | }
|
---|
1845 |
|
---|
1846 | /* attribute OSType fileType; */
|
---|
1847 | NS_IMETHODIMP nsLocalFile::GetFileType(OSType *aFileType)
|
---|
1848 | {
|
---|
1849 | NS_ENSURE_ARG_POINTER(aFileType);
|
---|
1850 |
|
---|
1851 | FSRef fsRef;
|
---|
1852 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
1853 | if (NS_FAILED(rv))
|
---|
1854 | return rv;
|
---|
1855 |
|
---|
1856 | FinderInfo fInfo;
|
---|
1857 | OSErr err = ::FSGetFinderInfo(&fsRef, &fInfo, nsnull, nsnull);
|
---|
1858 | if (err != noErr)
|
---|
1859 | return MacErrorMapper(err);
|
---|
1860 | *aFileType = fInfo.file.fileType;
|
---|
1861 | return NS_OK;
|
---|
1862 | }
|
---|
1863 |
|
---|
1864 | NS_IMETHODIMP nsLocalFile::SetFileType(OSType aFileType)
|
---|
1865 | {
|
---|
1866 | FSRef fsRef;
|
---|
1867 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
1868 | if (NS_FAILED(rv))
|
---|
1869 | return rv;
|
---|
1870 |
|
---|
1871 | OSErr err = ::FSChangeCreatorType(&fsRef, 0, aFileType);
|
---|
1872 | return MacErrorMapper(err);
|
---|
1873 | }
|
---|
1874 |
|
---|
1875 | /* attribute OSType fileCreator; */
|
---|
1876 | NS_IMETHODIMP nsLocalFile::GetFileCreator(OSType *aFileCreator)
|
---|
1877 | {
|
---|
1878 | NS_ENSURE_ARG_POINTER(aFileCreator);
|
---|
1879 |
|
---|
1880 | FSRef fsRef;
|
---|
1881 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
1882 | if (NS_FAILED(rv))
|
---|
1883 | return rv;
|
---|
1884 |
|
---|
1885 | FinderInfo fInfo;
|
---|
1886 | OSErr err = ::FSGetFinderInfo(&fsRef, &fInfo, nsnull, nsnull);
|
---|
1887 | if (err != noErr)
|
---|
1888 | return MacErrorMapper(err);
|
---|
1889 | *aFileCreator = fInfo.file.fileCreator;
|
---|
1890 | return NS_OK;
|
---|
1891 | }
|
---|
1892 |
|
---|
1893 | NS_IMETHODIMP nsLocalFile::SetFileCreator(OSType aFileCreator)
|
---|
1894 | {
|
---|
1895 | FSRef fsRef;
|
---|
1896 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
1897 | if (NS_FAILED(rv))
|
---|
1898 | return rv;
|
---|
1899 |
|
---|
1900 | OSErr err = ::FSChangeCreatorType(&fsRef, aFileCreator, 0);
|
---|
1901 | return MacErrorMapper(err);
|
---|
1902 | }
|
---|
1903 |
|
---|
1904 | /* void setFileTypeAndCreatorFromMIMEType (in string aMIMEType); */
|
---|
1905 | NS_IMETHODIMP nsLocalFile::SetFileTypeAndCreatorFromMIMEType(const char *aMIMEType)
|
---|
1906 | {
|
---|
1907 | // XXX - This should be cut from the API. Would create an evil dependency.
|
---|
1908 | NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
|
---|
1909 | return NS_ERROR_NOT_IMPLEMENTED;
|
---|
1910 | }
|
---|
1911 |
|
---|
1912 | /* void setFileTypeAndCreatorFromExtension (in string aExtension); */
|
---|
1913 | NS_IMETHODIMP nsLocalFile::SetFileTypeAndCreatorFromExtension(const char *aExtension)
|
---|
1914 | {
|
---|
1915 | // XXX - This should be cut from the API. Would create an evil dependency.
|
---|
1916 | NS_ERROR("NS_ERROR_NOT_IMPLEMENTED");
|
---|
1917 | return NS_ERROR_NOT_IMPLEMENTED;
|
---|
1918 | }
|
---|
1919 |
|
---|
1920 | /* void launchWithDoc (in nsILocalFile aDocToLoad, in boolean aLaunchInBackground); */
|
---|
1921 | NS_IMETHODIMP nsLocalFile::LaunchWithDoc(nsILocalFile *aDocToLoad, PRBool aLaunchInBackground)
|
---|
1922 | {
|
---|
1923 | PRBool isExecutable;
|
---|
1924 | nsresult rv = IsExecutable(&isExecutable);
|
---|
1925 | if (NS_FAILED(rv))
|
---|
1926 | return rv;
|
---|
1927 | if (!isExecutable)
|
---|
1928 | return NS_ERROR_FILE_EXECUTION_FAILED;
|
---|
1929 |
|
---|
1930 | FSRef appFSRef, docFSRef;
|
---|
1931 | rv = GetFSRefInternal(appFSRef);
|
---|
1932 | if (NS_FAILED(rv))
|
---|
1933 | return rv;
|
---|
1934 |
|
---|
1935 | if (aDocToLoad) {
|
---|
1936 | nsCOMPtr<nsILocalFileMac> macDoc = do_QueryInterface(aDocToLoad);
|
---|
1937 | rv = macDoc->GetFSRef(&docFSRef);
|
---|
1938 | if (NS_FAILED(rv))
|
---|
1939 | return rv;
|
---|
1940 | }
|
---|
1941 |
|
---|
1942 | LSLaunchFlags theLaunchFlags = kLSLaunchDefaults;
|
---|
1943 | LSLaunchFSRefSpec thelaunchSpec;
|
---|
1944 |
|
---|
1945 | if (aLaunchInBackground)
|
---|
1946 | theLaunchFlags |= kLSLaunchDontSwitch;
|
---|
1947 | memset(&thelaunchSpec, 0, sizeof(LSLaunchFSRefSpec));
|
---|
1948 |
|
---|
1949 | thelaunchSpec.appRef = &appFSRef;
|
---|
1950 | if (aDocToLoad) {
|
---|
1951 | thelaunchSpec.numDocs = 1;
|
---|
1952 | thelaunchSpec.itemRefs = &docFSRef;
|
---|
1953 | }
|
---|
1954 | thelaunchSpec.launchFlags = theLaunchFlags;
|
---|
1955 |
|
---|
1956 | OSErr err = ::LSOpenFromRefSpec(&thelaunchSpec, NULL);
|
---|
1957 | if (err != noErr)
|
---|
1958 | return MacErrorMapper(err);
|
---|
1959 |
|
---|
1960 | return NS_OK;
|
---|
1961 | }
|
---|
1962 |
|
---|
1963 | /* void openDocWithApp (in nsILocalFile aAppToOpenWith, in boolean aLaunchInBackground); */
|
---|
1964 | NS_IMETHODIMP nsLocalFile::OpenDocWithApp(nsILocalFile *aAppToOpenWith, PRBool aLaunchInBackground)
|
---|
1965 | {
|
---|
1966 | nsresult rv;
|
---|
1967 | OSErr err;
|
---|
1968 |
|
---|
1969 | FSRef docFSRef, appFSRef;
|
---|
1970 | rv = GetFSRefInternal(docFSRef);
|
---|
1971 | if (NS_FAILED(rv))
|
---|
1972 | return rv;
|
---|
1973 |
|
---|
1974 | if (aAppToOpenWith) {
|
---|
1975 | nsCOMPtr<nsILocalFileMac> appFileMac = do_QueryInterface(aAppToOpenWith, &rv);
|
---|
1976 | if (!appFileMac)
|
---|
1977 | return rv;
|
---|
1978 |
|
---|
1979 | PRBool isExecutable;
|
---|
1980 | rv = appFileMac->IsExecutable(&isExecutable);
|
---|
1981 | if (NS_FAILED(rv))
|
---|
1982 | return rv;
|
---|
1983 | if (!isExecutable)
|
---|
1984 | return NS_ERROR_FILE_EXECUTION_FAILED;
|
---|
1985 |
|
---|
1986 | rv = appFileMac->GetFSRef(&appFSRef);
|
---|
1987 | if (NS_FAILED(rv))
|
---|
1988 | return rv;
|
---|
1989 | }
|
---|
1990 | else {
|
---|
1991 | OSType fileCreator;
|
---|
1992 | rv = GetFileCreator(&fileCreator);
|
---|
1993 | if (NS_FAILED(rv))
|
---|
1994 | return rv;
|
---|
1995 |
|
---|
1996 | err = ::LSFindApplicationForInfo(fileCreator, nsnull, nsnull, &appFSRef, nsnull);
|
---|
1997 | if (err != noErr)
|
---|
1998 | return MacErrorMapper(err);
|
---|
1999 | }
|
---|
2000 |
|
---|
2001 | LSLaunchFlags theLaunchFlags = kLSLaunchDefaults;
|
---|
2002 | LSLaunchFSRefSpec thelaunchSpec;
|
---|
2003 |
|
---|
2004 | if (aLaunchInBackground)
|
---|
2005 | theLaunchFlags |= kLSLaunchDontSwitch;
|
---|
2006 | memset(&thelaunchSpec, 0, sizeof(LSLaunchFSRefSpec));
|
---|
2007 |
|
---|
2008 | thelaunchSpec.appRef = &appFSRef;
|
---|
2009 | thelaunchSpec.numDocs = 1;
|
---|
2010 | thelaunchSpec.itemRefs = &docFSRef;
|
---|
2011 | thelaunchSpec.launchFlags = theLaunchFlags;
|
---|
2012 |
|
---|
2013 | err = ::LSOpenFromRefSpec(&thelaunchSpec, NULL);
|
---|
2014 | if (err != noErr)
|
---|
2015 | return MacErrorMapper(err);
|
---|
2016 |
|
---|
2017 | return NS_OK;
|
---|
2018 | }
|
---|
2019 |
|
---|
2020 | /* boolean isPackage (); */
|
---|
2021 | NS_IMETHODIMP nsLocalFile::IsPackage(PRBool *_retval)
|
---|
2022 | {
|
---|
2023 | NS_ENSURE_ARG(_retval);
|
---|
2024 | *_retval = PR_FALSE;
|
---|
2025 |
|
---|
2026 | FSRef fsRef;
|
---|
2027 | nsresult rv = GetFSRefInternal(fsRef);
|
---|
2028 | if (NS_FAILED(rv))
|
---|
2029 | return rv;
|
---|
2030 |
|
---|
2031 | FSCatalogInfo catalogInfo;
|
---|
2032 | OSErr err = ::FSGetCatalogInfo(&fsRef, kFSCatInfoNodeFlags + kFSCatInfoFinderInfo,
|
---|
2033 | &catalogInfo, nsnull, nsnull, nsnull);
|
---|
2034 | if (err != noErr)
|
---|
2035 | return MacErrorMapper(err);
|
---|
2036 | if ((catalogInfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) {
|
---|
2037 | FileInfo *fInfoPtr = (FileInfo *)(catalogInfo.finderInfo);
|
---|
2038 | if ((fInfoPtr->finderFlags & kHasBundle) != 0) {
|
---|
2039 | *_retval = PR_TRUE;
|
---|
2040 | }
|
---|
2041 | else {
|
---|
2042 | // Folders ending with ".app" are also considered to
|
---|
2043 | // be packages, even if the top-level folder doesn't have bundle set
|
---|
2044 | nsCAutoString name;
|
---|
2045 | if (NS_SUCCEEDED(rv = GetNativeLeafName(name))) {
|
---|
2046 | const char *extPtr = strrchr(name.get(), '.');
|
---|
2047 | if (extPtr) {
|
---|
2048 | if ((nsCRT::strcasecmp(extPtr, ".app") == 0))
|
---|
2049 | *_retval = PR_TRUE;
|
---|
2050 | }
|
---|
2051 | }
|
---|
2052 | }
|
---|
2053 | }
|
---|
2054 | return NS_OK;
|
---|
2055 | }
|
---|
2056 |
|
---|
2057 | NS_IMETHODIMP
|
---|
2058 | nsLocalFile::GetBundleDisplayName(nsAString& outBundleName)
|
---|
2059 | {
|
---|
2060 | PRBool isPackage = PR_FALSE;
|
---|
2061 | nsresult rv = IsPackage(&isPackage);
|
---|
2062 | if (NS_FAILED(rv) || !isPackage)
|
---|
2063 | return NS_ERROR_FAILURE;
|
---|
2064 |
|
---|
2065 | nsAutoString name;
|
---|
2066 | rv = GetLeafName(name);
|
---|
2067 | if (NS_FAILED(rv))
|
---|
2068 | return rv;
|
---|
2069 |
|
---|
2070 | PRInt32 length = name.Length();
|
---|
2071 | if (Substring(name, length - 4, length).EqualsLiteral(".app")) {
|
---|
2072 | // 4 characters in ".app"
|
---|
2073 | outBundleName = Substring(name, 0, length - 4);
|
---|
2074 | }
|
---|
2075 | else
|
---|
2076 | outBundleName = name;
|
---|
2077 |
|
---|
2078 | return NS_OK;
|
---|
2079 | }
|
---|
2080 |
|
---|
2081 | NS_IMETHODIMP
|
---|
2082 | nsLocalFile::GetBundleIdentifier(nsACString& outBundleIdentifier)
|
---|
2083 | {
|
---|
2084 | nsresult rv = NS_ERROR_FAILURE;
|
---|
2085 |
|
---|
2086 | CFURLRef urlRef;
|
---|
2087 | if (NS_SUCCEEDED(GetCFURL(&urlRef))) {
|
---|
2088 | CFBundleRef bundle = ::CFBundleCreate(NULL, urlRef);
|
---|
2089 | if (bundle) {
|
---|
2090 | CFStringRef bundleIdentifier = ::CFBundleGetIdentifier(bundle);
|
---|
2091 | if (bundleIdentifier)
|
---|
2092 | rv = CFStringReftoUTF8(bundleIdentifier, outBundleIdentifier);
|
---|
2093 |
|
---|
2094 | ::CFRelease(bundle);
|
---|
2095 | }
|
---|
2096 | ::CFRelease(urlRef);
|
---|
2097 | }
|
---|
2098 |
|
---|
2099 | return rv;
|
---|
2100 | }
|
---|
2101 |
|
---|
2102 |
|
---|
2103 | //*****************************************************************************
|
---|
2104 | // nsLocalFile Methods
|
---|
2105 | //*****************************************************************************
|
---|
2106 | #pragma mark -
|
---|
2107 | #pragma mark [Protected Methods]
|
---|
2108 |
|
---|
2109 | nsresult nsLocalFile::SetBaseRef(CFURLRef aCFURLRef)
|
---|
2110 | {
|
---|
2111 | NS_ENSURE_ARG(aCFURLRef);
|
---|
2112 |
|
---|
2113 | ::CFRetain(aCFURLRef);
|
---|
2114 | if (mBaseRef)
|
---|
2115 | ::CFRelease(mBaseRef);
|
---|
2116 | mBaseRef = aCFURLRef;
|
---|
2117 |
|
---|
2118 | mFollowLinksDirty = PR_TRUE;
|
---|
2119 | UpdateTargetRef();
|
---|
2120 | mCachedFSRefValid = PR_FALSE;
|
---|
2121 | return NS_OK;
|
---|
2122 | }
|
---|
2123 |
|
---|
2124 | nsresult nsLocalFile::UpdateTargetRef()
|
---|
2125 | {
|
---|
2126 | // Check we are correctly initialized.
|
---|
2127 | CHECK_mBaseRef();
|
---|
2128 |
|
---|
2129 | if (mFollowLinksDirty) {
|
---|
2130 | if (mTargetRef) {
|
---|
2131 | ::CFRelease(mTargetRef);
|
---|
2132 | mTargetRef = nsnull;
|
---|
2133 | }
|
---|
2134 | if (mFollowLinks) {
|
---|
2135 | mTargetRef = mBaseRef;
|
---|
2136 | ::CFRetain(mTargetRef);
|
---|
2137 |
|
---|
2138 | FSRef fsRef;
|
---|
2139 | if (::CFURLGetFSRef(mBaseRef, &fsRef)) {
|
---|
2140 | Boolean targetIsFolder, wasAliased;
|
---|
2141 | if (FSResolveAliasFile(&fsRef, true /*resolveAliasChains*/,
|
---|
2142 | &targetIsFolder, &wasAliased) == noErr && wasAliased) {
|
---|
2143 | ::CFRelease(mTargetRef);
|
---|
2144 | mTargetRef = CFURLCreateFromFSRef(NULL, &fsRef);
|
---|
2145 | if (!mTargetRef)
|
---|
2146 | return NS_ERROR_FAILURE;
|
---|
2147 | }
|
---|
2148 | }
|
---|
2149 | mFollowLinksDirty = PR_FALSE;
|
---|
2150 | }
|
---|
2151 | }
|
---|
2152 | return NS_OK;
|
---|
2153 | }
|
---|
2154 |
|
---|
2155 | nsresult nsLocalFile::GetFSRefInternal(FSRef& aFSRef, PRBool bForceUpdateCache)
|
---|
2156 | {
|
---|
2157 | if (bForceUpdateCache || !mCachedFSRefValid) {
|
---|
2158 | mCachedFSRefValid = PR_FALSE;
|
---|
2159 | CFURLRef whichURLRef = mFollowLinks ? mTargetRef : mBaseRef;
|
---|
2160 | NS_ENSURE_TRUE(whichURLRef, NS_ERROR_NULL_POINTER);
|
---|
2161 | if (::CFURLGetFSRef(whichURLRef, &mCachedFSRef))
|
---|
2162 | mCachedFSRefValid = PR_TRUE;
|
---|
2163 | }
|
---|
2164 | if (mCachedFSRefValid) {
|
---|
2165 | aFSRef = mCachedFSRef;
|
---|
2166 | return NS_OK;
|
---|
2167 | }
|
---|
2168 | // CFURLGetFSRef only returns a Boolean for success,
|
---|
2169 | // so we have to assume what the error was. This is
|
---|
2170 | // the only probable cause.
|
---|
2171 | return NS_ERROR_FILE_NOT_FOUND;
|
---|
2172 | }
|
---|
2173 |
|
---|
2174 | nsresult nsLocalFile::GetPathInternal(nsACString& path)
|
---|
2175 | {
|
---|
2176 | nsresult rv = NS_ERROR_FAILURE;
|
---|
2177 |
|
---|
2178 | CFURLRef whichURLRef = mFollowLinks ? mTargetRef : mBaseRef;
|
---|
2179 | NS_ENSURE_TRUE(whichURLRef, NS_ERROR_NULL_POINTER);
|
---|
2180 |
|
---|
2181 | CFStringRef pathStrRef = ::CFURLCopyFileSystemPath(whichURLRef, kCFURLPOSIXPathStyle);
|
---|
2182 | if (pathStrRef) {
|
---|
2183 | rv = CFStringReftoUTF8(pathStrRef, path);
|
---|
2184 | ::CFRelease(pathStrRef);
|
---|
2185 | }
|
---|
2186 | return rv;
|
---|
2187 | }
|
---|
2188 |
|
---|
2189 | nsresult nsLocalFile::CopyInternal(nsIFile* aParentDir,
|
---|
2190 | const nsAString& newName,
|
---|
2191 | PRBool followLinks)
|
---|
2192 | {
|
---|
2193 | // Check we are correctly initialized.
|
---|
2194 | CHECK_mBaseRef();
|
---|
2195 |
|
---|
2196 | StFollowLinksState srcFollowState(*this, followLinks);
|
---|
2197 |
|
---|
2198 | nsresult rv;
|
---|
2199 | OSErr err;
|
---|
2200 | FSRef srcFSRef, newFSRef;
|
---|
2201 |
|
---|
2202 | rv = GetFSRefInternal(srcFSRef);
|
---|
2203 | if (NS_FAILED(rv))
|
---|
2204 | return rv;
|
---|
2205 |
|
---|
2206 | nsCOMPtr<nsIFile> newParentDir = aParentDir;
|
---|
2207 |
|
---|
2208 | if (!newParentDir) {
|
---|
2209 | if (newName.IsEmpty())
|
---|
2210 | return NS_ERROR_INVALID_ARG;
|
---|
2211 | rv = GetParent(getter_AddRefs(newParentDir));
|
---|
2212 | if (NS_FAILED(rv))
|
---|
2213 | return rv;
|
---|
2214 | }
|
---|
2215 |
|
---|
2216 | // If newParentDir does not exist, create it
|
---|
2217 | PRBool exists;
|
---|
2218 | rv = newParentDir->Exists(&exists);
|
---|
2219 | if (NS_FAILED(rv))
|
---|
2220 | return rv;
|
---|
2221 | if (!exists) {
|
---|
2222 | rv = newParentDir->Create(nsIFile::DIRECTORY_TYPE, 0777);
|
---|
2223 | if (NS_FAILED(rv))
|
---|
2224 | return rv;
|
---|
2225 | }
|
---|
2226 |
|
---|
2227 | FSRef destFSRef;
|
---|
2228 | nsCOMPtr<nsILocalFileMac> newParentDirMac(do_QueryInterface(newParentDir));
|
---|
2229 | if (!newParentDirMac)
|
---|
2230 | return NS_ERROR_NO_INTERFACE;
|
---|
2231 | rv = newParentDirMac->GetFSRef(&destFSRef);
|
---|
2232 | if (NS_FAILED(rv))
|
---|
2233 | return rv;
|
---|
2234 |
|
---|
2235 | err =
|
---|
2236 | ::FSCopyObject(&srcFSRef, &destFSRef, newName.Length(),
|
---|
2237 | newName.Length() ? PromiseFlatString(newName).get() : NULL,
|
---|
2238 | 0, kFSCatInfoNone, false, false, NULL, NULL, &newFSRef);
|
---|
2239 |
|
---|
2240 | return MacErrorMapper(err);
|
---|
2241 | }
|
---|
2242 |
|
---|
2243 | const PRInt64 kMillisecsPerSec = 1000LL;
|
---|
2244 | const PRInt64 kUTCDateTimeFractionDivisor = 65535LL;
|
---|
2245 |
|
---|
2246 | PRInt64 nsLocalFile::HFSPlustoNSPRTime(const UTCDateTime& utcTime)
|
---|
2247 | {
|
---|
2248 | // Start with seconds since Jan. 1, 1904 GMT
|
---|
2249 | PRInt64 result = ((PRInt64)utcTime.highSeconds << 32) + (PRInt64)utcTime.lowSeconds;
|
---|
2250 | // Subtract to convert to NSPR epoch of 1970
|
---|
2251 | result -= kJanuaryFirst1970Seconds;
|
---|
2252 | // Convert to millisecs
|
---|
2253 | result *= kMillisecsPerSec;
|
---|
2254 | // Convert the fraction to millisecs and add it
|
---|
2255 | result += ((PRInt64)utcTime.fraction * kMillisecsPerSec) / kUTCDateTimeFractionDivisor;
|
---|
2256 |
|
---|
2257 | return result;
|
---|
2258 | }
|
---|
2259 |
|
---|
2260 | void nsLocalFile::NSPRtoHFSPlusTime(PRInt64 nsprTime, UTCDateTime& utcTime)
|
---|
2261 | {
|
---|
2262 | PRInt64 fraction = nsprTime % kMillisecsPerSec;
|
---|
2263 | PRInt64 seconds = (nsprTime / kMillisecsPerSec) + kJanuaryFirst1970Seconds;
|
---|
2264 | utcTime.highSeconds = (UInt16)((PRUint64)seconds >> 32);
|
---|
2265 | utcTime.lowSeconds = (UInt32)seconds;
|
---|
2266 | utcTime.fraction = (UInt16)((fraction * kUTCDateTimeFractionDivisor) / kMillisecsPerSec);
|
---|
2267 | }
|
---|
2268 |
|
---|
2269 | nsresult nsLocalFile::CFStringReftoUTF8(CFStringRef aInStrRef, nsACString& aOutStr)
|
---|
2270 | {
|
---|
2271 | nsresult rv = NS_ERROR_FAILURE;
|
---|
2272 | CFIndex usedBufLen, inStrLen = ::CFStringGetLength(aInStrRef);
|
---|
2273 | CFIndex charsConverted = ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen),
|
---|
2274 | kCFStringEncodingUTF8, 0, PR_FALSE, nsnull, 0, &usedBufLen);
|
---|
2275 | if (charsConverted == inStrLen) {
|
---|
2276 | #if 0 /* bird: too new? */
|
---|
2277 | aOutStr.SetLength(usedBufLen);
|
---|
2278 | if (aOutStr.Length() != usedBufLen)
|
---|
2279 | return NS_ERROR_OUT_OF_MEMORY;
|
---|
2280 | UInt8 *buffer = (UInt8*) aOutStr.BeginWriting();
|
---|
2281 |
|
---|
2282 | ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen),
|
---|
2283 | kCFStringEncodingUTF8, 0, false, buffer, usedBufLen, &usedBufLen);
|
---|
2284 | rv = NS_OK;
|
---|
2285 | #else
|
---|
2286 | nsAutoBuffer<UInt8, FILENAME_BUFFER_SIZE> buffer;
|
---|
2287 | if (buffer.EnsureElemCapacity(usedBufLen + 1)) {
|
---|
2288 | ::CFStringGetBytes(aInStrRef, CFRangeMake(0, inStrLen),
|
---|
2289 | kCFStringEncodingUTF8, 0, false, buffer.get(), usedBufLen, &usedBufLen);
|
---|
2290 | buffer.get()[usedBufLen] = '\0';
|
---|
2291 | aOutStr.Assign(nsDependentCString((char*)buffer.get()));
|
---|
2292 | rv = NS_OK;
|
---|
2293 | }
|
---|
2294 | #endif
|
---|
2295 | }
|
---|
2296 | return rv;
|
---|
2297 | }
|
---|
2298 |
|
---|
2299 | // nsIHashable
|
---|
2300 |
|
---|
2301 | NS_IMETHODIMP
|
---|
2302 | nsLocalFile::Equals(nsIHashable* aOther, PRBool *aResult)
|
---|
2303 | {
|
---|
2304 | return EqualsInternal(aOther, PR_FALSE, aResult);
|
---|
2305 | }
|
---|
2306 |
|
---|
2307 | NS_IMETHODIMP
|
---|
2308 | nsLocalFile::GetHashCode(PRUint32 *aResult)
|
---|
2309 | {
|
---|
2310 | CFStringRef pathStrRef = ::CFURLCopyFileSystemPath(mBaseRef, kCFURLPOSIXPathStyle);
|
---|
2311 | nsCAutoString path;
|
---|
2312 | CFStringReftoUTF8(pathStrRef, path);
|
---|
2313 | *aResult = HashString(path);
|
---|
2314 | return NS_OK;
|
---|
2315 | }
|
---|
2316 |
|
---|
2317 | //*****************************************************************************
|
---|
2318 | // Global Functions
|
---|
2319 | //*****************************************************************************
|
---|
2320 | #pragma mark -
|
---|
2321 | #pragma mark [Global Functions]
|
---|
2322 |
|
---|
2323 | void nsLocalFile::GlobalInit()
|
---|
2324 | {
|
---|
2325 | }
|
---|
2326 |
|
---|
2327 | void nsLocalFile::GlobalShutdown()
|
---|
2328 | {
|
---|
2329 | }
|
---|
2330 |
|
---|
2331 | nsresult NS_NewLocalFile(const nsAString& path, PRBool followLinks, nsILocalFile* *result)
|
---|
2332 | {
|
---|
2333 | nsLocalFile* file = new nsLocalFile;
|
---|
2334 | if (file == nsnull)
|
---|
2335 | return NS_ERROR_OUT_OF_MEMORY;
|
---|
2336 | NS_ADDREF(file);
|
---|
2337 |
|
---|
2338 | file->SetFollowLinks(followLinks);
|
---|
2339 |
|
---|
2340 | if (!path.IsEmpty()) {
|
---|
2341 | nsresult rv = file->InitWithPath(path);
|
---|
2342 | if (NS_FAILED(rv)) {
|
---|
2343 | NS_RELEASE(file);
|
---|
2344 | return rv;
|
---|
2345 | }
|
---|
2346 | }
|
---|
2347 | *result = file;
|
---|
2348 | return NS_OK;
|
---|
2349 | }
|
---|
2350 |
|
---|
2351 | nsresult NS_NewNativeLocalFile(const nsACString& path, PRBool followLinks, nsILocalFile **result)
|
---|
2352 | {
|
---|
2353 | return NS_NewLocalFile(NS_ConvertUTF8toUTF16(path), followLinks, result);
|
---|
2354 | }
|
---|
2355 |
|
---|
2356 | nsresult NS_NewLocalFileWithFSSpec(const FSSpec* inSpec, PRBool followLinks, nsILocalFileMac **result)
|
---|
2357 | {
|
---|
2358 | nsLocalFile* file = new nsLocalFile();
|
---|
2359 | if (file == nsnull)
|
---|
2360 | return NS_ERROR_OUT_OF_MEMORY;
|
---|
2361 | NS_ADDREF(file);
|
---|
2362 |
|
---|
2363 | file->SetFollowLinks(followLinks);
|
---|
2364 |
|
---|
2365 | nsresult rv = file->InitWithFSSpec(inSpec);
|
---|
2366 | if (NS_FAILED(rv)) {
|
---|
2367 | NS_RELEASE(file);
|
---|
2368 | return rv;
|
---|
2369 | }
|
---|
2370 | *result = file;
|
---|
2371 | return NS_OK;
|
---|
2372 | }
|
---|
2373 |
|
---|
2374 | nsresult NS_NewLocalFileWithFSRef(const FSRef* aFSRef, PRBool aFollowLinks, nsILocalFileMac** result)
|
---|
2375 | {
|
---|
2376 | nsLocalFile* file = new nsLocalFile();
|
---|
2377 | if (file == nsnull)
|
---|
2378 | return NS_ERROR_OUT_OF_MEMORY;
|
---|
2379 | NS_ADDREF(file);
|
---|
2380 |
|
---|
2381 | file->SetFollowLinks(aFollowLinks);
|
---|
2382 |
|
---|
2383 | nsresult rv = file->InitWithFSRef(aFSRef);
|
---|
2384 | if (NS_FAILED(rv)) {
|
---|
2385 | NS_RELEASE(file);
|
---|
2386 | return rv;
|
---|
2387 | }
|
---|
2388 | *result = file;
|
---|
2389 | return NS_OK;
|
---|
2390 | }
|
---|
2391 |
|
---|
2392 | //*****************************************************************************
|
---|
2393 | // Static Functions
|
---|
2394 | //*****************************************************************************
|
---|
2395 |
|
---|
2396 | static nsresult MacErrorMapper(OSErr inErr)
|
---|
2397 | {
|
---|
2398 | nsresult outErr;
|
---|
2399 |
|
---|
2400 | switch (inErr)
|
---|
2401 | {
|
---|
2402 | case noErr:
|
---|
2403 | outErr = NS_OK;
|
---|
2404 | break;
|
---|
2405 |
|
---|
2406 | case fnfErr:
|
---|
2407 | outErr = NS_ERROR_FILE_NOT_FOUND;
|
---|
2408 | break;
|
---|
2409 |
|
---|
2410 | case dupFNErr:
|
---|
2411 | outErr = NS_ERROR_FILE_ALREADY_EXISTS;
|
---|
2412 | break;
|
---|
2413 |
|
---|
2414 | case dskFulErr:
|
---|
2415 | outErr = NS_ERROR_FILE_DISK_FULL;
|
---|
2416 | break;
|
---|
2417 |
|
---|
2418 | case fLckdErr:
|
---|
2419 | outErr = NS_ERROR_FILE_IS_LOCKED;
|
---|
2420 | break;
|
---|
2421 |
|
---|
2422 | // Can't find good map for some
|
---|
2423 | case bdNamErr:
|
---|
2424 | outErr = NS_ERROR_FAILURE;
|
---|
2425 | break;
|
---|
2426 |
|
---|
2427 | default:
|
---|
2428 | outErr = NS_ERROR_FAILURE;
|
---|
2429 | break;
|
---|
2430 | }
|
---|
2431 | return outErr;
|
---|
2432 | }
|
---|
2433 |
|
---|
2434 | static OSErr FindRunningAppBySignature(OSType aAppSig, ProcessSerialNumber& outPsn)
|
---|
2435 | {
|
---|
2436 | ProcessInfoRec info;
|
---|
2437 | OSErr err = noErr;
|
---|
2438 |
|
---|
2439 | outPsn.highLongOfPSN = 0;
|
---|
2440 | outPsn.lowLongOfPSN = kNoProcess;
|
---|
2441 |
|
---|
2442 | while (PR_TRUE)
|
---|
2443 | {
|
---|
2444 | err = ::GetNextProcess(&outPsn);
|
---|
2445 | if (err == procNotFound)
|
---|
2446 | break;
|
---|
2447 | if (err != noErr)
|
---|
2448 | return err;
|
---|
2449 | info.processInfoLength = sizeof(ProcessInfoRec);
|
---|
2450 | info.processName = nil;
|
---|
2451 | info.processAppSpec = nil;
|
---|
2452 | err = ::GetProcessInformation(&outPsn, &info);
|
---|
2453 | if (err != noErr)
|
---|
2454 | return err;
|
---|
2455 |
|
---|
2456 | if (info.processSignature == aAppSig)
|
---|
2457 | return noErr;
|
---|
2458 | }
|
---|
2459 | return procNotFound;
|
---|
2460 | }
|
---|
2461 |
|
---|
2462 | // Convert a UTF-8 string to a UTF-16 string while normalizing to
|
---|
2463 | // Normalization Form C (composed Unicode). We need this because
|
---|
2464 | // Mac OS X file system uses NFD (Normalization Form D : decomposed Unicode)
|
---|
2465 | // while most other OS', server-side programs usually expect NFC.
|
---|
2466 |
|
---|
2467 | typedef void (*UnicodeNormalizer) (CFMutableStringRef, CFStringNormalizationForm);
|
---|
2468 | static void CopyUTF8toUTF16NFC(const nsACString& aSrc, nsAString& aResult)
|
---|
2469 | {
|
---|
2470 | static PRBool sChecked = PR_FALSE;
|
---|
2471 | static UnicodeNormalizer sUnicodeNormalizer = NULL;
|
---|
2472 |
|
---|
2473 | // CFStringNormalize was not introduced until Mac OS 10.2
|
---|
2474 | if (!sChecked) {
|
---|
2475 | CFBundleRef carbonBundle =
|
---|
2476 | CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Carbon"));
|
---|
2477 | if (carbonBundle)
|
---|
2478 | sUnicodeNormalizer = (UnicodeNormalizer)
|
---|
2479 | ::CFBundleGetFunctionPointerForName(carbonBundle,
|
---|
2480 | CFSTR("CFStringNormalize"));
|
---|
2481 | sChecked = PR_TRUE;
|
---|
2482 | }
|
---|
2483 |
|
---|
2484 | if (!sUnicodeNormalizer) { // OS X 10.2 or earlier
|
---|
2485 | CopyUTF8toUTF16(aSrc, aResult);
|
---|
2486 | return;
|
---|
2487 | }
|
---|
2488 |
|
---|
2489 | const nsAFlatCString &inFlatSrc = PromiseFlatCString(aSrc);
|
---|
2490 |
|
---|
2491 | // The number of 16bit code units in a UTF-16 string will never be
|
---|
2492 | // larger than the number of bytes in the corresponding UTF-8 string.
|
---|
2493 | CFMutableStringRef inStr =
|
---|
2494 | ::CFStringCreateMutable(NULL, inFlatSrc.Length());
|
---|
2495 |
|
---|
2496 | if (!inStr) {
|
---|
2497 | CopyUTF8toUTF16(aSrc, aResult);
|
---|
2498 | return;
|
---|
2499 | }
|
---|
2500 |
|
---|
2501 | ::CFStringAppendCString(inStr, inFlatSrc.get(), kCFStringEncodingUTF8);
|
---|
2502 |
|
---|
2503 | sUnicodeNormalizer(inStr, kCFStringNormalizationFormC);
|
---|
2504 |
|
---|
2505 | CFIndex length = CFStringGetLength(inStr);
|
---|
2506 | const UniChar* chars = CFStringGetCharactersPtr(inStr);
|
---|
2507 |
|
---|
2508 | if (chars)
|
---|
2509 | aResult.Assign(chars, length);
|
---|
2510 | else {
|
---|
2511 | nsAutoBuffer<UniChar, FILENAME_BUFFER_SIZE> buffer;
|
---|
2512 | if (!buffer.EnsureElemCapacity(length))
|
---|
2513 | CopyUTF8toUTF16(aSrc, aResult);
|
---|
2514 | else {
|
---|
2515 | CFStringGetCharacters(inStr, CFRangeMake(0, length), buffer.get());
|
---|
2516 | aResult.Assign(buffer.get(), length);
|
---|
2517 | }
|
---|
2518 | }
|
---|
2519 | CFRelease(inStr);
|
---|
2520 | }
|
---|