1 | /* |
---|
2 | * The contents of this file are subject to the Mozilla Public License |
---|
3 | * Version 1.1 (the "License"); you may not use this file except in |
---|
4 | * compliance with the License. You may obtain a copy of the License at |
---|
5 | * http://www.mozilla.org/MPL/ |
---|
6 | * |
---|
7 | * Software distributed under the License is distributed on an "AS IS" |
---|
8 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
---|
9 | * License for the specific language governing rights and limitations |
---|
10 | * under the License. |
---|
11 | * |
---|
12 | * The Original Code is the Mozilla OS/2 libraries. |
---|
13 | * |
---|
14 | * The Initial Developer of the Original Code is John Fairhurst, |
---|
15 | * <john_fairhurst@iname.com>. Portions created by John Fairhurst are |
---|
16 | * Copyright (C) 1998 John Fairhurst. All Rights Reserved. |
---|
17 | * |
---|
18 | * Contributor(s): Henry Sobotka <sobotka@axess.com> |
---|
19 | * 00/01/06: general review and update against Win/Unix versions; |
---|
20 | * replaced nsFileSpec::Execute implementation with system() call |
---|
21 | * which properly launches OS/2 PM|VIO, WinOS2 and DOS programs |
---|
22 | * |
---|
23 | * This Original Code has been modified by IBM Corporation. |
---|
24 | * Modifications made by IBM described herein are |
---|
25 | * Copyright (c) International Business Machines |
---|
26 | * Corporation, 2000 |
---|
27 | * |
---|
28 | * Modifications to Mozilla code or documentation |
---|
29 | * identified per MPL Section 3.3 |
---|
30 | * |
---|
31 | * Date Modified by Description of modification |
---|
32 | * 03/23/2000 IBM Corp. Fixed bug where 2 char or less profile names treated as drive letters. |
---|
33 | * 06/20/2000 IBM Corp. Make it more like Windows version. |
---|
34 | */ |
---|
35 | |
---|
36 | #define INCL_DOSERRORS |
---|
37 | #define INCL_DOS |
---|
38 | #define INCL_WINWORKPLACE |
---|
39 | #include <os2.h> |
---|
40 | |
---|
41 | #ifdef XP_OS2_VACPP |
---|
42 | #include <direct.h> |
---|
43 | #endif |
---|
44 | |
---|
45 | #include <sys/types.h> |
---|
46 | #include <sys/stat.h> |
---|
47 | #include <limits.h> |
---|
48 | #include <ctype.h> |
---|
49 | #include <io.h> |
---|
50 | |
---|
51 | //---------------------------------------------------------------------------------------- |
---|
52 | void nsFileSpecHelpers::Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs) |
---|
53 | // Canonify, make absolute, and check whether directories exist. This |
---|
54 | // takes a (possibly relative) native path and converts it into a |
---|
55 | // fully qualified native path. |
---|
56 | //---------------------------------------------------------------------------------------- |
---|
57 | { |
---|
58 | if (ioPath.IsEmpty()) |
---|
59 | return; |
---|
60 | |
---|
61 | NS_ASSERTION(strchr((const char*)ioPath, '/') == 0, |
---|
62 | "This smells like a Unix path. Native path expected! " |
---|
63 | "Please fix."); |
---|
64 | if (inMakeDirs) |
---|
65 | { |
---|
66 | const int mode = 0700; |
---|
67 | nsSimpleCharString unixStylePath = ioPath; |
---|
68 | nsFileSpecHelpers::NativeToUnix(unixStylePath); |
---|
69 | nsFileSpecHelpers::MakeAllDirectories((const char*)unixStylePath, mode); |
---|
70 | } |
---|
71 | char buffer[_MAX_PATH]; |
---|
72 | errno = 0; |
---|
73 | *buffer = '\0'; |
---|
74 | #ifdef XP_OS2 |
---|
75 | PRBool removedBackslash = PR_FALSE; |
---|
76 | PRUint32 lenstr = ioPath.Length(); |
---|
77 | char &lastchar = ioPath[lenstr -1]; |
---|
78 | |
---|
79 | // Strip off any trailing backslash UNLESS it's the backslash that |
---|
80 | // comes after "X:". Note also that "\" is valid. Sheesh. |
---|
81 | // |
---|
82 | if( lastchar == '\\' && (lenstr != 3 || ioPath[1] != ':') && lenstr != 1) |
---|
83 | { |
---|
84 | lastchar = '\0'; |
---|
85 | removedBackslash = PR_TRUE; |
---|
86 | } |
---|
87 | |
---|
88 | char canonicalPath[CCHMAXPATH] = ""; |
---|
89 | |
---|
90 | DosQueryPathInfo( (char*) ioPath, |
---|
91 | FIL_QUERYFULLNAME, |
---|
92 | canonicalPath, |
---|
93 | CCHMAXPATH); |
---|
94 | #else |
---|
95 | char* canonicalPath = _fullpath(buffer, ioPath, _MAX_PATH); |
---|
96 | #endif |
---|
97 | |
---|
98 | if (canonicalPath) |
---|
99 | { |
---|
100 | NS_ASSERTION( canonicalPath[0] != '\0', "Uh oh...couldn't convert" ); |
---|
101 | if (canonicalPath[0] == '\0') |
---|
102 | return; |
---|
103 | #ifdef XP_OS2 |
---|
104 | // If we removed that backslash, add it back onto the fullpath |
---|
105 | if (removedBackslash) |
---|
106 | strcat( canonicalPath, "\\"); |
---|
107 | #endif |
---|
108 | } |
---|
109 | ioPath = canonicalPath; |
---|
110 | } // nsFileSpecHelpers::Canonify |
---|
111 | |
---|
112 | //---------------------------------------------------------------------------------------- |
---|
113 | void nsFileSpecHelpers::UnixToNative(nsSimpleCharString& ioPath) |
---|
114 | // This just does string manipulation. It doesn't check reality, or canonify, or |
---|
115 | // anything |
---|
116 | //---------------------------------------------------------------------------------------- |
---|
117 | { |
---|
118 | // Allow for relative or absolute. We can do this in place, because the |
---|
119 | // native path is never longer. |
---|
120 | |
---|
121 | if (ioPath.IsEmpty()) |
---|
122 | return; |
---|
123 | |
---|
124 | // Strip initial slash for an absolute path |
---|
125 | char* src = (char*)ioPath; |
---|
126 | if (*src == '/') { |
---|
127 | if (!src[1]) { |
---|
128 | // allocate new string by copying from ioPath[1] |
---|
129 | nsSimpleCharString temp = src + 1; |
---|
130 | ioPath = temp; |
---|
131 | return; |
---|
132 | } |
---|
133 | // Since it was an absolute path, check for the drive letter |
---|
134 | char* colonPointer = src + 2; |
---|
135 | if (strstr(src, "|/") == colonPointer) |
---|
136 | *colonPointer = ':'; |
---|
137 | // allocate new string by copying from ioPath[1] |
---|
138 | nsSimpleCharString temp = src + 1; |
---|
139 | ioPath = temp; |
---|
140 | } |
---|
141 | |
---|
142 | src = (char*)ioPath; |
---|
143 | |
---|
144 | if (*src) { |
---|
145 | // Convert '/' to '\'. |
---|
146 | while (*++src) |
---|
147 | { |
---|
148 | if (*src == '/') |
---|
149 | *src = '\\'; |
---|
150 | } |
---|
151 | } |
---|
152 | } // nsFileSpecHelpers::UnixToNative |
---|
153 | |
---|
154 | //---------------------------------------------------------------------------------------- |
---|
155 | void nsFileSpecHelpers::NativeToUnix(nsSimpleCharString& ioPath) |
---|
156 | // This just does string manipulation. It doesn't check reality, or canonify, or |
---|
157 | // anything. The unix path is longer, so we can't do it in place. |
---|
158 | //---------------------------------------------------------------------------------------- |
---|
159 | { |
---|
160 | if (ioPath.IsEmpty()) |
---|
161 | return; |
---|
162 | |
---|
163 | // Convert the drive-letter separator, if present |
---|
164 | nsSimpleCharString temp("/"); |
---|
165 | |
---|
166 | char* cp = (char*)ioPath + 1; |
---|
167 | if (strstr(cp, ":\\") == cp) |
---|
168 | *cp = '|'; // absolute path |
---|
169 | else |
---|
170 | temp[0] = '\0'; // relative path |
---|
171 | |
---|
172 | // Convert '\' to '/' |
---|
173 | for (; *cp; cp++) |
---|
174 | { |
---|
175 | #ifdef XP_OS2 |
---|
176 | // OS2TODO - implement equivalent of IsDBCSLeadByte |
---|
177 | #else |
---|
178 | if(IsDBCSLeadByte(*cp) && *(cp+1) != nsnull) |
---|
179 | { |
---|
180 | cp++; |
---|
181 | continue; |
---|
182 | } |
---|
183 | #endif |
---|
184 | if (*cp == '\\') |
---|
185 | *cp = '/'; |
---|
186 | } |
---|
187 | // Add the slash in front. |
---|
188 | temp += ioPath; |
---|
189 | ioPath = temp; |
---|
190 | } |
---|
191 | |
---|
192 | //---------------------------------------------------------------------------------------- |
---|
193 | nsFileSpec::nsFileSpec(const nsFilePath& inPath) |
---|
194 | //---------------------------------------------------------------------------------------- |
---|
195 | { |
---|
196 | // NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!"); |
---|
197 | *this = inPath; |
---|
198 | } |
---|
199 | |
---|
200 | //---------------------------------------------------------------------------------------- |
---|
201 | void nsFileSpec::operator = (const nsFilePath& inPath) |
---|
202 | //---------------------------------------------------------------------------------------- |
---|
203 | { |
---|
204 | mPath = (const char*)inPath; |
---|
205 | nsFileSpecHelpers::UnixToNative(mPath); |
---|
206 | mError = NS_OK; |
---|
207 | } // nsFileSpec::operator = |
---|
208 | |
---|
209 | //---------------------------------------------------------------------------------------- |
---|
210 | nsFilePath::nsFilePath(const nsFileSpec& inSpec) |
---|
211 | //---------------------------------------------------------------------------------------- |
---|
212 | { |
---|
213 | *this = inSpec; |
---|
214 | } // nsFilePath::nsFilePath |
---|
215 | |
---|
216 | //---------------------------------------------------------------------------------------- |
---|
217 | void nsFilePath::operator = (const nsFileSpec& inSpec) |
---|
218 | //---------------------------------------------------------------------------------------- |
---|
219 | { |
---|
220 | mPath = inSpec.mPath; |
---|
221 | nsFileSpecHelpers::NativeToUnix(mPath); |
---|
222 | } // nsFilePath::operator = |
---|
223 | |
---|
224 | //---------------------------------------------------------------------------------------- |
---|
225 | void nsFileSpec::SetLeafName(const char* inLeafName) |
---|
226 | //---------------------------------------------------------------------------------------- |
---|
227 | { |
---|
228 | NS_ASSERTION(inLeafName, "Attempt to SetLeafName with a null string"); |
---|
229 | mPath.LeafReplace('\\', inLeafName); |
---|
230 | } // nsFileSpec::SetLeafName |
---|
231 | |
---|
232 | //---------------------------------------------------------------------------------------- |
---|
233 | char* nsFileSpec::GetLeafName() const |
---|
234 | //---------------------------------------------------------------------------------------- |
---|
235 | { |
---|
236 | return mPath.GetLeaf('\\'); |
---|
237 | } // nsFileSpec::GetLeafName |
---|
238 | |
---|
239 | //---------------------------------------------------------------------------------------- |
---|
240 | PRBool nsFileSpec::Exists() const |
---|
241 | //---------------------------------------------------------------------------------------- |
---|
242 | { |
---|
243 | struct stat st; |
---|
244 | return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st); |
---|
245 | } // nsFileSpec::Exists |
---|
246 | |
---|
247 | //---------------------------------------------------------------------------------------- |
---|
248 | void nsFileSpec::GetModDate(TimeStamp& outStamp) const |
---|
249 | //---------------------------------------------------------------------------------------- |
---|
250 | { |
---|
251 | struct stat st; |
---|
252 | if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0) |
---|
253 | outStamp = st.st_mtime; |
---|
254 | else |
---|
255 | outStamp = 0; |
---|
256 | } // nsFileSpec::GetModDate |
---|
257 | |
---|
258 | //---------------------------------------------------------------------------------------- |
---|
259 | PRUint32 nsFileSpec::GetFileSize() const |
---|
260 | //---------------------------------------------------------------------------------------- |
---|
261 | { |
---|
262 | struct stat st; |
---|
263 | if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0) |
---|
264 | return (PRUint32)st.st_size; |
---|
265 | return 0; |
---|
266 | } // nsFileSpec::GetFileSize |
---|
267 | |
---|
268 | //---------------------------------------------------------------------------------------- |
---|
269 | PRBool nsFileSpec::IsFile() const |
---|
270 | //---------------------------------------------------------------------------------------- |
---|
271 | { |
---|
272 | struct stat st; |
---|
273 | #ifdef XP_OS2 |
---|
274 | return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && ( S_IFREG & st.st_mode); |
---|
275 | #else |
---|
276 | return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFREG & st.st_mode); |
---|
277 | #endif |
---|
278 | } // nsFileSpec::IsFile |
---|
279 | |
---|
280 | //---------------------------------------------------------------------------------------- |
---|
281 | PRBool nsFileSpec::IsDirectory() const |
---|
282 | //---------------------------------------------------------------------------------------- |
---|
283 | { |
---|
284 | struct stat st; |
---|
285 | #ifdef XP_OS2 |
---|
286 | return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && ( S_IFDIR & st.st_mode); |
---|
287 | #else |
---|
288 | return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFDIR & st.st_mode); |
---|
289 | #endif |
---|
290 | } // nsFileSpec::IsDirectory |
---|
291 | |
---|
292 | //---------------------------------------------------------------------------------------- |
---|
293 | PRBool nsFileSpec::IsHidden() const |
---|
294 | //---------------------------------------------------------------------------------------- |
---|
295 | { |
---|
296 | PRBool hidden = PR_FALSE; |
---|
297 | if (!mPath.IsEmpty()) |
---|
298 | { |
---|
299 | #ifdef XP_OS2 |
---|
300 | FILESTATUS3 fs3; |
---|
301 | APIRET rc; |
---|
302 | |
---|
303 | rc = DosQueryPathInfo( mPath, |
---|
304 | FIL_STANDARD, |
---|
305 | &fs3, |
---|
306 | sizeof fs3); |
---|
307 | if(!rc) |
---|
308 | hidden = fs3.attrFile & FILE_HIDDEN ? PR_TRUE : PR_FALSE; |
---|
309 | #else |
---|
310 | DWORD attr = GetFileAttributes(mPath); |
---|
311 | if (FILE_ATTRIBUTE_HIDDEN & attr) |
---|
312 | hidden = PR_TRUE; |
---|
313 | #endif |
---|
314 | } |
---|
315 | return hidden; |
---|
316 | } |
---|
317 | // nsFileSpec::IsHidden |
---|
318 | |
---|
319 | //---------------------------------------------------------------------------------------- |
---|
320 | PRBool nsFileSpec::IsSymlink() const |
---|
321 | //---------------------------------------------------------------------------------------- |
---|
322 | { |
---|
323 | #ifdef XP_OS2 |
---|
324 | return PR_FALSE; // No symlinks on OS/2 |
---|
325 | #else |
---|
326 | HRESULT hres; |
---|
327 | IShellLink* psl; |
---|
328 | |
---|
329 | PRBool isSymlink = PR_FALSE; |
---|
330 | |
---|
331 | CoInitialize(NULL); |
---|
332 | // Get a pointer to the IShellLink interface. |
---|
333 | hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); |
---|
334 | if (SUCCEEDED(hres)) |
---|
335 | { |
---|
336 | IPersistFile* ppf; |
---|
337 | |
---|
338 | // Get a pointer to the IPersistFile interface. |
---|
339 | hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); |
---|
340 | |
---|
341 | if (SUCCEEDED(hres)) |
---|
342 | { |
---|
343 | WORD wsz[MAX_PATH]; |
---|
344 | // Ensure that the string is Unicode. |
---|
345 | MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH); |
---|
346 | |
---|
347 | // Load the shortcut. |
---|
348 | hres = ppf->Load(wsz, STGM_READ); |
---|
349 | if (SUCCEEDED(hres)) |
---|
350 | { |
---|
351 | isSymlink = PR_TRUE; |
---|
352 | } |
---|
353 | |
---|
354 | // Release the pointer to the IPersistFile interface. |
---|
355 | ppf->Release(); |
---|
356 | } |
---|
357 | |
---|
358 | // Release the pointer to the IShellLink interface. |
---|
359 | psl->Release(); |
---|
360 | } |
---|
361 | |
---|
362 | CoUninitialize(); |
---|
363 | |
---|
364 | return isSymlink; |
---|
365 | #endif |
---|
366 | } |
---|
367 | |
---|
368 | |
---|
369 | //---------------------------------------------------------------------------------------- |
---|
370 | nsresult nsFileSpec::ResolveSymlink(PRBool& wasSymlink) |
---|
371 | //---------------------------------------------------------------------------------------- |
---|
372 | { |
---|
373 | #ifdef XP_OS2 |
---|
374 | return NS_OK; // no symlinks on OS/2 |
---|
375 | #else |
---|
376 | wasSymlink = PR_FALSE; // assume failure |
---|
377 | |
---|
378 | if (Exists()) |
---|
379 | return NS_OK; |
---|
380 | |
---|
381 | |
---|
382 | HRESULT hres; |
---|
383 | IShellLink* psl; |
---|
384 | |
---|
385 | CoInitialize(NULL); |
---|
386 | |
---|
387 | // Get a pointer to the IShellLink interface. |
---|
388 | hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); |
---|
389 | if (SUCCEEDED(hres)) |
---|
390 | { |
---|
391 | IPersistFile* ppf; |
---|
392 | |
---|
393 | // Get a pointer to the IPersistFile interface. |
---|
394 | hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); |
---|
395 | |
---|
396 | if (SUCCEEDED(hres)) |
---|
397 | { |
---|
398 | WORD wsz[MAX_PATH]; |
---|
399 | // Ensure that the string is Unicode. |
---|
400 | MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH); |
---|
401 | |
---|
402 | // Load the shortcut. |
---|
403 | hres = ppf->Load(wsz, STGM_READ); |
---|
404 | if (SUCCEEDED(hres)) |
---|
405 | { |
---|
406 | wasSymlink = PR_TRUE; |
---|
407 | |
---|
408 | // Resolve the link. |
---|
409 | hres = psl->Resolve(nsnull, SLR_NO_UI ); |
---|
410 | if (SUCCEEDED(hres)) |
---|
411 | { |
---|
412 | char szGotPath[MAX_PATH]; |
---|
413 | WIN32_FIND_DATA wfd; |
---|
414 | |
---|
415 | // Get the path to the link target. |
---|
416 | hres = psl->GetPath( szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY ); |
---|
417 | |
---|
418 | if (SUCCEEDED(hres)) |
---|
419 | { |
---|
420 | // Here we modify the nsFileSpec; |
---|
421 | mPath = szGotPath; |
---|
422 | mError = NS_OK; |
---|
423 | } |
---|
424 | } |
---|
425 | } |
---|
426 | else { |
---|
427 | // It wasn't a shortcut. Oh well. Leave it like it was. |
---|
428 | hres = 0; |
---|
429 | } |
---|
430 | |
---|
431 | // Release the pointer to the IPersistFile interface. |
---|
432 | ppf->Release(); |
---|
433 | } |
---|
434 | // Release the pointer to the IShellLink interface. |
---|
435 | psl->Release(); |
---|
436 | } |
---|
437 | |
---|
438 | CoUninitialize(); |
---|
439 | |
---|
440 | if (SUCCEEDED(hres)) |
---|
441 | return NS_OK; |
---|
442 | |
---|
443 | return NS_FILE_FAILURE; |
---|
444 | #endif |
---|
445 | } |
---|
446 | |
---|
447 | |
---|
448 | |
---|
449 | //---------------------------------------------------------------------------------------- |
---|
450 | void nsFileSpec::GetParent(nsFileSpec& outSpec) const |
---|
451 | //---------------------------------------------------------------------------------------- |
---|
452 | { |
---|
453 | outSpec.mPath = mPath; |
---|
454 | char* chars = (char*)outSpec.mPath; |
---|
455 | chars[outSpec.mPath.Length() - 1] = '\0'; // avoid trailing separator, if any |
---|
456 | char* cp = strrchr(chars, '\\'); |
---|
457 | if (cp++) |
---|
458 | outSpec.mPath.SetLength(cp - chars); // truncate. |
---|
459 | } // nsFileSpec::GetParent |
---|
460 | |
---|
461 | //---------------------------------------------------------------------------------------- |
---|
462 | void nsFileSpec::operator += (const char* inRelativePath) |
---|
463 | //---------------------------------------------------------------------------------------- |
---|
464 | { |
---|
465 | NS_ASSERTION(inRelativePath, "Attempt to do += with a null string"); |
---|
466 | |
---|
467 | if (!inRelativePath || mPath.IsEmpty()) |
---|
468 | return; |
---|
469 | |
---|
470 | if (mPath[mPath.Length() - 1] == '\\') |
---|
471 | mPath += "x"; |
---|
472 | else |
---|
473 | mPath += "\\x"; |
---|
474 | |
---|
475 | // If it's a (unix) relative path, make it native |
---|
476 | nsSimpleCharString dosPath = inRelativePath; |
---|
477 | nsFileSpecHelpers::UnixToNative(dosPath); |
---|
478 | SetLeafName(dosPath); |
---|
479 | } // nsFileSpec::operator += |
---|
480 | |
---|
481 | //---------------------------------------------------------------------------------------- |
---|
482 | void nsFileSpec::CreateDirectory(int /*mode*/) |
---|
483 | //---------------------------------------------------------------------------------------- |
---|
484 | { |
---|
485 | // Note that mPath is canonical! |
---|
486 | if (!mPath.IsEmpty()) |
---|
487 | #ifdef XP_OS2 |
---|
488 | // OS2TODO - vacpp complains about mkdir but PR_MkDir should be ok? |
---|
489 | PR_MkDir(nsNSPRPath(*this), PR_CREATE_FILE); |
---|
490 | #else |
---|
491 | mkdir(nsNSPRPath(*this)); |
---|
492 | #endif |
---|
493 | } // nsFileSpec::CreateDirectory |
---|
494 | |
---|
495 | //---------------------------------------------------------------------------------------- |
---|
496 | void nsFileSpec::Delete(PRBool inRecursive) const |
---|
497 | //---------------------------------------------------------------------------------------- |
---|
498 | { |
---|
499 | if (IsDirectory()) |
---|
500 | { |
---|
501 | if (inRecursive) |
---|
502 | { |
---|
503 | for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++) |
---|
504 | { |
---|
505 | nsFileSpec& child = i.Spec(); |
---|
506 | child.Delete(inRecursive); |
---|
507 | } |
---|
508 | } |
---|
509 | #ifdef XP_OS2 |
---|
510 | // OS2TODO - vacpp complains if use rmdir but PR_RmDir should be ok? |
---|
511 | PR_RmDir(nsNSPRPath(*this)); |
---|
512 | #else |
---|
513 | rmdir(nsNSPRPath(*this)); |
---|
514 | #endif |
---|
515 | } |
---|
516 | else if (!mPath.IsEmpty()) |
---|
517 | { |
---|
518 | remove(nsNSPRPath(*this)); |
---|
519 | } |
---|
520 | } // nsFileSpec::Delete |
---|
521 | |
---|
522 | |
---|
523 | //---------------------------------------------------------------------------------------- |
---|
524 | void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const |
---|
525 | //---------------------------------------------------------------------------------------- |
---|
526 | { |
---|
527 | if (IsDirectory()) |
---|
528 | { |
---|
529 | if (!(newDir.Exists())) |
---|
530 | { |
---|
531 | newDir.CreateDirectory(); |
---|
532 | } |
---|
533 | |
---|
534 | for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++) |
---|
535 | { |
---|
536 | nsFileSpec& child = i.Spec(); |
---|
537 | |
---|
538 | if (child.IsDirectory()) |
---|
539 | { |
---|
540 | nsFileSpec tmpDirSpec(newDir); |
---|
541 | |
---|
542 | char *leafname = child.GetLeafName(); |
---|
543 | tmpDirSpec += leafname; |
---|
544 | nsCRT::free(leafname); |
---|
545 | |
---|
546 | child.RecursiveCopy(tmpDirSpec); |
---|
547 | } |
---|
548 | else |
---|
549 | { |
---|
550 | child.RecursiveCopy(newDir); |
---|
551 | } |
---|
552 | } |
---|
553 | } |
---|
554 | else if (!mPath.IsEmpty()) |
---|
555 | { |
---|
556 | nsFileSpec& filePath = (nsFileSpec&) *this; |
---|
557 | |
---|
558 | if (!(newDir.Exists())) |
---|
559 | { |
---|
560 | newDir.CreateDirectory(); |
---|
561 | } |
---|
562 | |
---|
563 | filePath.CopyToDir(newDir); |
---|
564 | } |
---|
565 | } // nsFileSpec::RecursiveCopy |
---|
566 | |
---|
567 | //---------------------------------------------------------------------------------------- |
---|
568 | nsresult |
---|
569 | nsFileSpec::Truncate(PRInt32 aNewFileLength) const |
---|
570 | //---------------------------------------------------------------------------------------- |
---|
571 | { |
---|
572 | #ifdef XP_OS2 |
---|
573 | APIRET rc; |
---|
574 | HFILE hFile; |
---|
575 | ULONG actionTaken; |
---|
576 | |
---|
577 | rc = DosOpen(mPath, |
---|
578 | &hFile, |
---|
579 | &actionTaken, |
---|
580 | 0, |
---|
581 | FILE_NORMAL, |
---|
582 | OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS, |
---|
583 | OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_READWRITE, |
---|
584 | NULL); |
---|
585 | |
---|
586 | if (rc != NO_ERROR) |
---|
587 | return NS_FILE_FAILURE; |
---|
588 | |
---|
589 | rc = DosSetFileSize(hFile, aNewFileLength); |
---|
590 | |
---|
591 | if (rc == NO_ERROR) |
---|
592 | DosClose(hFile); |
---|
593 | else |
---|
594 | goto error; |
---|
595 | #else |
---|
596 | DWORD status; |
---|
597 | HANDLE hFile; |
---|
598 | |
---|
599 | // Leave it to Microsoft to open an existing file with a function |
---|
600 | // named "CreateFile". |
---|
601 | hFile = CreateFile(mPath, |
---|
602 | GENERIC_WRITE, |
---|
603 | FILE_SHARE_READ, |
---|
604 | NULL, |
---|
605 | OPEN_EXISTING, |
---|
606 | FILE_ATTRIBUTE_NORMAL, |
---|
607 | NULL); |
---|
608 | if (hFile == INVALID_HANDLE_VALUE) |
---|
609 | return NS_FILE_FAILURE; |
---|
610 | |
---|
611 | // Seek to new, desired end of file |
---|
612 | status = SetFilePointer(hFile, aNewFileLength, NULL, FILE_BEGIN); |
---|
613 | if (status == 0xffffffff) |
---|
614 | goto error; |
---|
615 | |
---|
616 | // Truncate file at current cursor position |
---|
617 | if (!SetEndOfFile(hFile)) |
---|
618 | goto error; |
---|
619 | |
---|
620 | if (!CloseHandle(hFile)) |
---|
621 | return NS_FILE_FAILURE; |
---|
622 | #endif |
---|
623 | |
---|
624 | return NS_OK; |
---|
625 | |
---|
626 | error: |
---|
627 | #ifdef XP_OS2 |
---|
628 | DosClose(hFile); |
---|
629 | #else |
---|
630 | CloseHandle(hFile); |
---|
631 | #endif |
---|
632 | return NS_FILE_FAILURE; |
---|
633 | |
---|
634 | } // nsFileSpec::Truncate |
---|
635 | |
---|
636 | //---------------------------------------------------------------------------------------- |
---|
637 | nsresult nsFileSpec::Rename(const char* inNewName) |
---|
638 | //---------------------------------------------------------------------------------------- |
---|
639 | { |
---|
640 | NS_ASSERTION(inNewName, "Attempt to Rename with a null string"); |
---|
641 | |
---|
642 | // This function should not be used to move a file on disk. |
---|
643 | if (strchr(inNewName, '/')) |
---|
644 | return NS_FILE_FAILURE; |
---|
645 | |
---|
646 | char* oldPath = nsCRT::strdup(mPath); |
---|
647 | |
---|
648 | SetLeafName(inNewName); |
---|
649 | |
---|
650 | if (PR_Rename(oldPath, mPath) != NS_OK) |
---|
651 | { |
---|
652 | // Could not rename, set back to the original. |
---|
653 | mPath = oldPath; |
---|
654 | return NS_FILE_FAILURE; |
---|
655 | } |
---|
656 | |
---|
657 | nsCRT::free(oldPath); |
---|
658 | |
---|
659 | return NS_OK; |
---|
660 | } // nsFileSpec::Rename |
---|
661 | |
---|
662 | //---------------------------------------------------------------------------------------- |
---|
663 | nsresult nsFileSpec::CopyToDir(const nsFileSpec& inParentDirectory) const |
---|
664 | //---------------------------------------------------------------------------------------- |
---|
665 | { |
---|
666 | // We can only copy into a directory, and (for now) can not copy entire directories |
---|
667 | if (inParentDirectory.IsDirectory() && (! IsDirectory() ) ) |
---|
668 | { |
---|
669 | char *leafname = GetLeafName(); |
---|
670 | nsSimpleCharString destPath(inParentDirectory.GetCString()); |
---|
671 | destPath += "\\"; |
---|
672 | destPath += leafname; |
---|
673 | nsCRT::free(leafname); |
---|
674 | |
---|
675 | // CopyFile returns non-zero if succeeds |
---|
676 | #ifdef XP_OS2 |
---|
677 | APIRET rc; |
---|
678 | PRBool copyOK; |
---|
679 | |
---|
680 | rc = DosCopy(GetCString(), (PSZ)destPath, DCPY_EXISTING); |
---|
681 | |
---|
682 | if (rc == NO_ERROR) |
---|
683 | copyOK = PR_TRUE; |
---|
684 | else |
---|
685 | copyOK = PR_FALSE; |
---|
686 | #else |
---|
687 | int copyOK = CopyFile(GetCString(), destPath, PR_TRUE); |
---|
688 | #endif |
---|
689 | if (copyOK) |
---|
690 | return NS_OK; |
---|
691 | } |
---|
692 | return NS_FILE_FAILURE; |
---|
693 | } // nsFileSpec::CopyToDir |
---|
694 | |
---|
695 | //---------------------------------------------------------------------------------------- |
---|
696 | nsresult nsFileSpec::MoveToDir(const nsFileSpec& inNewParentDirectory) |
---|
697 | //---------------------------------------------------------------------------------------- |
---|
698 | { |
---|
699 | // We can only copy into a directory, and (for now) can not copy entire directories |
---|
700 | if (inNewParentDirectory.IsDirectory() && (! IsDirectory() ) ) |
---|
701 | { |
---|
702 | char *leafname = GetLeafName(); |
---|
703 | nsSimpleCharString destPath(inNewParentDirectory.GetCString()); |
---|
704 | destPath += "\\"; |
---|
705 | destPath += leafname; |
---|
706 | nsCRT::free(leafname); |
---|
707 | |
---|
708 | if (DosMove(GetCString(), destPath) == NO_ERROR) |
---|
709 | { |
---|
710 | *this = inNewParentDirectory + GetLeafName(); |
---|
711 | return NS_OK; |
---|
712 | } |
---|
713 | |
---|
714 | } |
---|
715 | return NS_FILE_FAILURE; |
---|
716 | } // nsFileSpec::MoveToDir |
---|
717 | |
---|
718 | //---------------------------------------------------------------------------------------- |
---|
719 | nsresult nsFileSpec::Execute(const char* inArgs ) const |
---|
720 | //---------------------------------------------------------------------------------------- |
---|
721 | { |
---|
722 | if (!IsDirectory()) |
---|
723 | { |
---|
724 | #ifdef XP_OS2 |
---|
725 | nsresult result = NS_FILE_FAILURE; |
---|
726 | |
---|
727 | if (!mPath.IsEmpty()) |
---|
728 | { |
---|
729 | nsSimpleCharString fileNameWithArgs = mPath + " " + inArgs; |
---|
730 | result = NS_FILE_RESULT(system(fileNameWithArgs)); |
---|
731 | } |
---|
732 | return result; |
---|
733 | #else |
---|
734 | nsSimpleCharString fileNameWithArgs = "\""; |
---|
735 | fileNameWithArgs += mPath + "\" " + inArgs; |
---|
736 | int execResult = WinExec( fileNameWithArgs, SW_NORMAL ); |
---|
737 | if (execResult > 31) |
---|
738 | return NS_OK; |
---|
739 | #endif |
---|
740 | } |
---|
741 | return NS_FILE_FAILURE; |
---|
742 | } // nsFileSpec::Execute |
---|
743 | |
---|
744 | |
---|
745 | //---------------------------------------------------------------------------------------- |
---|
746 | PRInt64 nsFileSpec::GetDiskSpaceAvailable() const |
---|
747 | //---------------------------------------------------------------------------------------- |
---|
748 | { |
---|
749 | PRInt64 nBytes = 0; |
---|
750 | ULONG ulDriveNo = toupper(mPath[0]) + 1 - 'A'; |
---|
751 | FSALLOCATE fsAllocate; |
---|
752 | APIRET rc = DosQueryFSInfo(ulDriveNo, |
---|
753 | FSIL_ALLOC, |
---|
754 | &fsAllocate, |
---|
755 | sizeof(fsAllocate)); |
---|
756 | |
---|
757 | if (rc == NO_ERROR) { |
---|
758 | nBytes = fsAllocate.cUnitAvail; |
---|
759 | nBytes *= fsAllocate.cSectorUnit; |
---|
760 | nBytes *= fsAllocate.cbSector; |
---|
761 | } |
---|
762 | |
---|
763 | return nBytes; |
---|
764 | } |
---|
765 | |
---|
766 | |
---|
767 | |
---|
768 | //======================================================================================== |
---|
769 | // nsDirectoryIterator |
---|
770 | //======================================================================================== |
---|
771 | |
---|
772 | //---------------------------------------------------------------------------------------- |
---|
773 | nsDirectoryIterator::nsDirectoryIterator(const nsFileSpec& inDirectory, PRBool resolveSymlink) |
---|
774 | //---------------------------------------------------------------------------------------- |
---|
775 | : mCurrent(inDirectory) |
---|
776 | , mDir(nsnull) |
---|
777 | , mStarting(inDirectory) |
---|
778 | , mExists(PR_FALSE) |
---|
779 | , mResoveSymLinks(resolveSymlink) |
---|
780 | { |
---|
781 | mDir = PR_OpenDir(inDirectory); |
---|
782 | mCurrent += "dummy"; |
---|
783 | mStarting += "dummy"; |
---|
784 | ++(*this); |
---|
785 | } // nsDirectoryIterator::nsDirectoryIterator |
---|
786 | |
---|
787 | //---------------------------------------------------------------------------------------- |
---|
788 | nsDirectoryIterator::~nsDirectoryIterator() |
---|
789 | //---------------------------------------------------------------------------------------- |
---|
790 | { |
---|
791 | if (mDir) |
---|
792 | PR_CloseDir(mDir); |
---|
793 | } // nsDirectoryIterator::nsDirectoryIterator |
---|
794 | |
---|
795 | //---------------------------------------------------------------------------------------- |
---|
796 | nsDirectoryIterator& nsDirectoryIterator::operator ++ () |
---|
797 | //---------------------------------------------------------------------------------------- |
---|
798 | { |
---|
799 | mExists = PR_FALSE; |
---|
800 | if (!mDir) |
---|
801 | return *this; |
---|
802 | PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH); // Ignore '.' && '..' |
---|
803 | if (entry) |
---|
804 | { |
---|
805 | mExists = PR_TRUE; |
---|
806 | mCurrent = mStarting; |
---|
807 | mCurrent.SetLeafName(entry->name); |
---|
808 | if (mResoveSymLinks) |
---|
809 | { |
---|
810 | PRBool ignore; |
---|
811 | mCurrent.ResolveSymlink(ignore); |
---|
812 | } |
---|
813 | } |
---|
814 | return *this; |
---|
815 | } // nsDirectoryIterator::operator ++ |
---|
816 | |
---|
817 | //---------------------------------------------------------------------------------------- |
---|
818 | nsDirectoryIterator& nsDirectoryIterator::operator -- () |
---|
819 | //---------------------------------------------------------------------------------------- |
---|
820 | { |
---|
821 | return ++(*this); // can't do it backwards. |
---|
822 | } // nsDirectoryIterator::operator -- |
---|
823 | |
---|