Back out bug 459443 for now, until the patch in bug 474389 gets reviewed
[mozilla-central.git] / xpcom / obsolete / nsFileSpecWin.cpp
blob7489fbd5ef1b2eb310cdfec798a4883fd53a60f2
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
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/
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.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Masayuki Nakano <masayuki@d-toybox.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 // This file is included by nsFileSpec.cp, and includes the Windows-specific
40 // implementations.
42 #include <sys/stat.h>
43 #include <direct.h>
44 #include <limits.h>
45 #include <stdlib.h>
46 #include "prio.h"
47 #include "nsError.h"
49 #include <windows.h>
50 #include <mbstring.h>
52 #if (_MSC_VER == 1100) || defined(__GNUC__)
53 #define INITGUID
54 #include <objbase.h>
55 DEFINE_OLEGUID(IID_IPersistFile, 0x0000010BL, 0, 0);
56 #endif
58 #include <shlobj.h>
59 #include <shellapi.h>
60 #include <shlguid.h>
62 #ifndef WINCE
63 #ifdef UNICODE
64 #define CreateDirectoryW CreateDirectory
65 #else
66 #define CreateDirectoryA CreateDirectory
67 #endif
68 #endif
70 //----------------------------------------------------------------------------------------
71 void nsFileSpecHelpers::Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs)
72 // Canonify, make absolute, and check whether directories exist. This
73 // takes a (possibly relative) native path and converts it into a
74 // fully qualified native path.
75 //----------------------------------------------------------------------------------------
77 if (ioPath.IsEmpty())
78 return;
80 NS_ASSERTION(strchr((const char*)ioPath, '/') == 0,
81 "This smells like a Unix path. Native path expected! "
82 "Please fix.");
83 if (inMakeDirs)
85 const int mode = 0755;
86 nsSimpleCharString unixStylePath = ioPath;
87 nsFileSpecHelpers::NativeToUnix(unixStylePath);
88 nsFileSpecHelpers::MakeAllDirectories((const char*)unixStylePath, mode);
90 char buffer[_MAX_PATH];
91 errno = 0;
92 *buffer = '\0';
93 char* canonicalPath = _fullpath(buffer, ioPath, _MAX_PATH);
95 if (canonicalPath)
97 NS_ASSERTION( canonicalPath[0] != '\0', "Uh oh...couldn't convert" );
98 if (canonicalPath[0] == '\0')
99 return;
101 ioPath = canonicalPath;
102 } // nsFileSpecHelpers::Canonify
104 //----------------------------------------------------------------------------------------
105 void nsFileSpecHelpers::UnixToNative(nsSimpleCharString& ioPath)
106 // This just does string manipulation. It doesn't check reality, or canonify, or
107 // anything
108 //----------------------------------------------------------------------------------------
110 // Allow for relative or absolute. We can do this in place, because the
111 // native path is never longer.
113 if (ioPath.IsEmpty())
114 return;
116 // Strip initial slash for an absolute path
117 char* src = (char*)ioPath;
118 if (*src == '/') {
119 if (!src[1]) {
120 // allocate new string by copying from ioPath[1]
121 nsSimpleCharString temp = src + 1;
122 ioPath = temp;
123 return;
125 // Since it was an absolute path, check for the drive letter
126 char* colonPointer = src + 2;
127 if (strstr(src, "|/") == colonPointer)
128 *colonPointer = ':';
129 // allocate new string by copying from ioPath[1]
130 nsSimpleCharString temp = src + 1;
131 ioPath = temp;
134 // Convert '/' to '\'. (Must check EVERY character: consider UNC path
135 // case.)
136 for (src = (char*)ioPath; *src; ++src)
138 if (*src == '/')
139 *src = '\\';
142 } // nsFileSpecHelpers::UnixToNative
144 //----------------------------------------------------------------------------------------
145 void nsFileSpecHelpers::NativeToUnix(nsSimpleCharString& ioPath)
146 // This just does string manipulation. It doesn't check reality, or canonify, or
147 // anything. The unix path is longer, so we can't do it in place.
148 //----------------------------------------------------------------------------------------
150 if (ioPath.IsEmpty())
151 return;
153 // Convert the drive-letter separator, if present
154 nsSimpleCharString temp("/");
156 char* cp = (char*)ioPath + 1;
157 if (strstr(cp, ":\\") == cp)
158 *cp = '|'; // absolute path
159 else
160 if (cp[0] == '\\') // unc path
161 cp--;
162 else
163 temp[0] = '\0'; // relative path
165 // Convert '\' to '/'
166 for (; *cp; cp++)
168 if(IsDBCSLeadByte(*cp) && *(cp+1) != nsnull)
170 cp++;
171 continue;
173 if (*cp == '\\')
174 *cp = '/';
176 // Add the slash in front.
177 temp += ioPath;
178 ioPath = temp;
181 //----------------------------------------------------------------------------------------
182 nsFileSpec::nsFileSpec(const nsFilePath& inPath)
183 //----------------------------------------------------------------------------------------
185 // NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
186 *this = inPath;
189 //----------------------------------------------------------------------------------------
190 void nsFileSpec::operator = (const nsFilePath& inPath)
191 //----------------------------------------------------------------------------------------
193 mPath = (const char*)inPath;
194 nsFileSpecHelpers::UnixToNative(mPath);
195 mError = NS_OK;
196 } // nsFileSpec::operator =
198 //----------------------------------------------------------------------------------------
199 nsFilePath::nsFilePath(const nsFileSpec& inSpec)
200 //----------------------------------------------------------------------------------------
202 *this = inSpec;
203 } // nsFilePath::nsFilePath
205 //----------------------------------------------------------------------------------------
206 void nsFilePath::operator = (const nsFileSpec& inSpec)
207 //----------------------------------------------------------------------------------------
209 mPath = inSpec.mPath;
210 nsFileSpecHelpers::NativeToUnix(mPath);
211 } // nsFilePath::operator =
213 //----------------------------------------------------------------------------------------
214 void nsFileSpec::SetLeafName(const char* inLeafName)
215 //----------------------------------------------------------------------------------------
217 NS_ASSERTION(inLeafName, "Attempt to SetLeafName with a null string");
218 mPath.LeafReplace('\\', inLeafName);
219 } // nsFileSpec::SetLeafName
221 //----------------------------------------------------------------------------------------
222 char* nsFileSpec::GetLeafName() const
223 //----------------------------------------------------------------------------------------
225 return mPath.GetLeaf('\\');
226 } // nsFileSpec::GetLeafName
228 //----------------------------------------------------------------------------------------
229 PRBool nsFileSpec::Exists() const
230 //----------------------------------------------------------------------------------------
232 struct stat st;
233 return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st);
234 } // nsFileSpec::Exists
236 //----------------------------------------------------------------------------------------
237 void nsFileSpec::GetModDate(TimeStamp& outStamp) const
238 //----------------------------------------------------------------------------------------
240 struct stat st;
241 if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0)
242 outStamp = st.st_mtime;
243 else
244 outStamp = 0;
245 } // nsFileSpec::GetModDate
247 //----------------------------------------------------------------------------------------
248 PRUint32 nsFileSpec::GetFileSize() const
249 //----------------------------------------------------------------------------------------
251 struct stat st;
252 if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0)
253 return (PRUint32)st.st_size;
254 return 0;
255 } // nsFileSpec::GetFileSize
257 //----------------------------------------------------------------------------------------
258 PRBool nsFileSpec::IsFile() const
259 //----------------------------------------------------------------------------------------
261 struct stat st;
262 return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFREG & st.st_mode);
263 } // nsFileSpec::IsFile
265 //----------------------------------------------------------------------------------------
266 PRBool nsFileSpec::IsDirectory() const
267 //----------------------------------------------------------------------------------------
269 struct stat st;
270 return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFDIR & st.st_mode);
271 } // nsFileSpec::IsDirectory
273 //----------------------------------------------------------------------------------------
274 PRBool nsFileSpec::IsHidden() const
275 //----------------------------------------------------------------------------------------
277 PRBool hidden = PR_FALSE;
278 if (!mPath.IsEmpty())
280 DWORD attr = GetFileAttributes(mPath);
281 if (FILE_ATTRIBUTE_HIDDEN & attr)
282 hidden = PR_TRUE;
284 return hidden;
286 // nsFileSpec::IsHidden
288 //----------------------------------------------------------------------------------------
289 PRBool nsFileSpec::IsSymlink() const
290 //----------------------------------------------------------------------------------------
292 HRESULT hres;
293 IShellLink* psl;
295 PRBool isSymlink = PR_FALSE;
296 #ifndef WINCE
297 CoInitialize(NULL);
298 // Get a pointer to the IShellLink interface.
299 hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
300 if (SUCCEEDED(hres))
302 IPersistFile* ppf;
304 // Get a pointer to the IPersistFile interface.
305 hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
307 if (SUCCEEDED(hres))
309 WCHAR wsz[MAX_PATH];
310 // Ensure that the string is Unicode.
311 MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH);
313 // Load the shortcut.
314 hres = ppf->Load(wsz, STGM_READ);
315 if (SUCCEEDED(hres))
317 isSymlink = PR_TRUE;
320 // Release the pointer to the IPersistFile interface.
321 ppf->Release();
324 // Release the pointer to the IShellLink interface.
325 psl->Release();
328 CoUninitialize();
329 #endif
330 return isSymlink;
334 //----------------------------------------------------------------------------------------
335 nsresult nsFileSpec::ResolveSymlink(PRBool& wasSymlink)
336 //----------------------------------------------------------------------------------------
338 wasSymlink = PR_FALSE; // assume failure
339 #ifndef WINCE
340 if (Exists())
341 return NS_OK;
344 HRESULT hres;
345 IShellLink* psl;
347 CoInitialize(NULL);
349 // Get a pointer to the IShellLink interface.
350 hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
351 if (SUCCEEDED(hres))
353 IPersistFile* ppf;
355 // Get a pointer to the IPersistFile interface.
356 hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
358 if (SUCCEEDED(hres))
360 WCHAR wsz[MAX_PATH];
361 // Ensure that the string is Unicode.
362 MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH);
364 // Load the shortcut.
365 hres = ppf->Load(wsz, STGM_READ);
366 if (SUCCEEDED(hres))
368 wasSymlink = PR_TRUE;
370 // Resolve the link.
371 hres = psl->Resolve(nsnull, SLR_NO_UI );
372 if (SUCCEEDED(hres))
374 char szGotPath[MAX_PATH];
375 WIN32_FIND_DATA wfd;
377 // Get the path to the link target.
378 hres = psl->GetPath( szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY );
380 if (SUCCEEDED(hres))
382 // Here we modify the nsFileSpec;
383 mPath = szGotPath;
384 mError = NS_OK;
388 else {
389 // It wasn't a shortcut. Oh well. Leave it like it was.
390 hres = 0;
393 // Release the pointer to the IPersistFile interface.
394 ppf->Release();
396 // Release the pointer to the IShellLink interface.
397 psl->Release();
400 CoUninitialize();
402 if (SUCCEEDED(hres))
403 return NS_OK;
405 return NS_FILE_FAILURE;
406 #else
407 return NS_OK;
408 #endif //WINCE
413 //----------------------------------------------------------------------------------------
414 void nsFileSpec::GetParent(nsFileSpec& outSpec) const
415 //----------------------------------------------------------------------------------------
417 outSpec.mPath = mPath;
418 char* chars = (char*)outSpec.mPath;
419 chars[outSpec.mPath.Length() - 1] = '\0'; // avoid trailing separator, if any
420 unsigned char* cp = _mbsrchr((unsigned char*)chars, '\\');
421 if (cp++)
422 outSpec.mPath.SetLength(cp - (unsigned char*)chars); // truncate.
423 } // nsFileSpec::GetParent
425 //----------------------------------------------------------------------------------------
426 void nsFileSpec::operator += (const char* inRelativePath)
427 //----------------------------------------------------------------------------------------
429 NS_ASSERTION(inRelativePath, "Attempt to do += with a null string");
431 if (!inRelativePath || mPath.IsEmpty())
432 return;
434 if (mPath[mPath.Length() - 1] == '\\')
435 mPath += "x";
436 else
437 mPath += "\\x";
439 // If it's a (unix) relative path, make it native
440 nsSimpleCharString dosPath = inRelativePath;
441 nsFileSpecHelpers::UnixToNative(dosPath);
442 SetLeafName(dosPath);
443 } // nsFileSpec::operator +=
445 //----------------------------------------------------------------------------------------
446 void nsFileSpec::CreateDirectory(int /*mode*/)
447 //----------------------------------------------------------------------------------------
449 // Note that mPath is canonical!
450 if (!mPath.IsEmpty())
451 mkdir(nsNSPRPath(*this));
452 } // nsFileSpec::CreateDirectory
454 //----------------------------------------------------------------------------------------
455 void nsFileSpec::Delete(PRBool inRecursive) const
456 //----------------------------------------------------------------------------------------
458 if (IsDirectory())
460 if (inRecursive)
462 for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
464 nsFileSpec& child = (nsFileSpec&)i;
465 child.Delete(inRecursive);
468 rmdir(nsNSPRPath(*this));
470 else if (!mPath.IsEmpty())
472 remove(nsNSPRPath(*this));
474 } // nsFileSpec::Delete
477 //----------------------------------------------------------------------------------------
478 void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
479 //----------------------------------------------------------------------------------------
481 if (IsDirectory())
483 if (!(newDir.Exists()))
485 newDir.CreateDirectory();
488 for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
490 nsFileSpec& child = (nsFileSpec&)i;
492 if (child.IsDirectory())
494 nsFileSpec tmpDirSpec(newDir);
496 char *leafname = child.GetLeafName();
497 tmpDirSpec += leafname;
498 nsCRT::free(leafname);
500 child.RecursiveCopy(tmpDirSpec);
502 else
504 child.RecursiveCopy(newDir);
508 else if (!mPath.IsEmpty())
510 nsFileSpec& filePath = (nsFileSpec&) *this;
512 if (!(newDir.Exists()))
514 newDir.CreateDirectory();
517 filePath.CopyToDir(newDir);
519 } // nsFileSpec::RecursiveCopy
521 //----------------------------------------------------------------------------------------
522 nsresult
523 nsFileSpec::Truncate(PRInt32 aNewFileLength) const
524 //----------------------------------------------------------------------------------------
526 DWORD status;
527 HANDLE hFile;
529 // Leave it to Microsoft to open an existing file with a function
530 // named "CreateFile".
531 hFile = CreateFile(mPath,
532 GENERIC_WRITE,
533 FILE_SHARE_READ,
534 NULL,
535 OPEN_EXISTING,
536 FILE_ATTRIBUTE_NORMAL,
537 NULL);
538 if (hFile == INVALID_HANDLE_VALUE)
539 return NS_FILE_FAILURE;
541 // Seek to new, desired end of file
542 status = SetFilePointer(hFile, aNewFileLength, NULL, FILE_BEGIN);
543 if (status == 0xffffffff)
544 goto error;
546 // Truncate file at current cursor position
547 if (!SetEndOfFile(hFile))
548 goto error;
550 if (!CloseHandle(hFile))
551 return NS_FILE_FAILURE;
553 return NS_OK;
555 error:
556 CloseHandle(hFile);
557 return NS_FILE_FAILURE;
559 } // nsFileSpec::Truncate
561 //----------------------------------------------------------------------------------------
562 nsresult nsFileSpec::Rename(const char* inNewName)
563 //----------------------------------------------------------------------------------------
565 NS_ASSERTION(inNewName, "Attempt to Rename with a null string");
567 // This function should not be used to move a file on disk.
568 if (strchr(inNewName, '/'))
569 return NS_FILE_FAILURE;
571 char* oldPath = nsCRT::strdup(mPath);
573 SetLeafName(inNewName);
575 if (PR_Rename(oldPath, mPath) != NS_OK)
577 // Could not rename, set back to the original.
578 mPath = oldPath;
579 return NS_FILE_FAILURE;
582 nsCRT::free(oldPath);
584 return NS_OK;
585 } // nsFileSpec::Rename
587 //----------------------------------------------------------------------------------------
588 nsresult nsFileSpec::CopyToDir(const nsFileSpec& inParentDirectory) const
589 //----------------------------------------------------------------------------------------
591 // We can only copy into a directory, and (for now) can not copy entire directories
592 if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
594 char *leafname = GetLeafName();
595 nsSimpleCharString destPath(inParentDirectory.GetCString());
596 destPath += "\\";
597 destPath += leafname;
598 nsCRT::free(leafname);
600 // CopyFile returns non-zero if succeeds
601 int copyOK = CopyFile(GetCString(), destPath, PR_TRUE);
602 if (copyOK)
603 return NS_OK;
605 return NS_FILE_FAILURE;
606 } // nsFileSpec::CopyToDir
608 //----------------------------------------------------------------------------------------
609 nsresult nsFileSpec::MoveToDir(const nsFileSpec& inNewParentDirectory)
610 //----------------------------------------------------------------------------------------
612 // We can only copy into a directory, and (for now) can not copy entire directories
613 if (inNewParentDirectory.IsDirectory() && (! IsDirectory() ) )
615 char *leafname = GetLeafName();
616 nsSimpleCharString destPath(inNewParentDirectory.GetCString());
617 destPath += "\\";
618 destPath += leafname;
619 nsCRT::free(leafname);
621 // MoveFile returns non-zero if succeeds
622 int copyOK = MoveFile(GetCString(), destPath);
624 if (copyOK)
626 *this = inNewParentDirectory + GetLeafName();
627 return NS_OK;
631 return NS_FILE_FAILURE;
632 } // nsFileSpec::MoveToDir
634 //----------------------------------------------------------------------------------------
635 nsresult nsFileSpec::Execute(const char* inArgs ) const
636 //----------------------------------------------------------------------------------------
638 #ifndef WINCE
639 if (!IsDirectory())
641 nsSimpleCharString fileNameWithArgs = "\"";
642 fileNameWithArgs += mPath + "\" " + inArgs;
643 int execResult = WinExec( fileNameWithArgs, SW_NORMAL );
644 if (execResult > 31)
645 return NS_OK;
647 #endif
648 return NS_FILE_FAILURE;
649 } // nsFileSpec::Execute
652 //----------------------------------------------------------------------------------------
653 PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
654 //----------------------------------------------------------------------------------------
656 #ifndef WINCE
657 PRInt64 int64;
659 LL_I2L(int64 , LONG_MAX);
661 char aDrive[_MAX_DRIVE + 2];
662 _splitpath( (const char*)mPath, aDrive, NULL, NULL, NULL);
664 if (aDrive[0] == '\0')
666 // The back end is always trying to pass us paths that look
667 // like /c|/netscape/mail. See if we've got one of them
668 if (mPath.Length() > 2 && mPath[0] == '/' && mPath[2] == '|')
670 aDrive[0] = mPath[1];
671 aDrive[1] = ':';
672 aDrive[2] = '\0';
674 else
676 // Return bogus large number and hope for the best
677 return int64;
681 strcat(aDrive, "\\");
683 // Check disk space
684 DWORD dwSecPerClus, dwBytesPerSec, dwFreeClus, dwTotalClus;
685 ULARGE_INTEGER liFreeBytesAvailableToCaller, liTotalNumberOfBytes, liTotalNumberOfFreeBytes;
686 double nBytes = 0;
688 BOOL (WINAPI* getDiskFreeSpaceExA)(LPCTSTR lpDirectoryName,
689 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
690 PULARGE_INTEGER lpTotalNumberOfBytes,
691 PULARGE_INTEGER lpTotalNumberOfFreeBytes) = NULL;
693 HINSTANCE hInst = LoadLibrary("KERNEL32.DLL");
694 NS_ASSERTION(hInst != NULL, "COULD NOT LOAD KERNEL32.DLL");
695 if (hInst != NULL)
697 getDiskFreeSpaceExA = (BOOL (WINAPI*)(LPCTSTR lpDirectoryName,
698 PULARGE_INTEGER lpFreeBytesAvailableToCaller,
699 PULARGE_INTEGER lpTotalNumberOfBytes,
700 PULARGE_INTEGER lpTotalNumberOfFreeBytes))
701 GetProcAddress(hInst, "GetDiskFreeSpaceExA");
702 FreeLibrary(hInst);
705 if (getDiskFreeSpaceExA && (*getDiskFreeSpaceExA)(aDrive,
706 &liFreeBytesAvailableToCaller,
707 &liTotalNumberOfBytes,
708 &liTotalNumberOfFreeBytes))
710 nBytes = (double)(signed __int64)liFreeBytesAvailableToCaller.QuadPart;
712 else if ( GetDiskFreeSpace(aDrive, &dwSecPerClus, &dwBytesPerSec, &dwFreeClus, &dwTotalClus))
714 nBytes = (double)dwFreeClus*(double)dwSecPerClus*(double) dwBytesPerSec;
716 return (PRInt64)nBytes;
717 #else
718 return (PRInt64)0;
719 #endif
724 //========================================================================================
725 // nsDirectoryIterator
726 //========================================================================================
728 //----------------------------------------------------------------------------------------
729 nsDirectoryIterator::nsDirectoryIterator(const nsFileSpec& inDirectory, PRBool resolveSymlink)
730 //----------------------------------------------------------------------------------------
731 : mCurrent(inDirectory)
732 , mDir(nsnull)
733 , mStarting(inDirectory)
734 , mExists(PR_FALSE)
735 , mResoveSymLinks(resolveSymlink)
737 mDir = PR_OpenDir(inDirectory);
738 mCurrent += "dummy";
739 mStarting += "dummy";
740 ++(*this);
741 } // nsDirectoryIterator::nsDirectoryIterator
743 //----------------------------------------------------------------------------------------
744 nsDirectoryIterator::~nsDirectoryIterator()
745 //----------------------------------------------------------------------------------------
747 if (mDir)
748 PR_CloseDir(mDir);
749 } // nsDirectoryIterator::nsDirectoryIterator
751 //----------------------------------------------------------------------------------------
752 nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
753 //----------------------------------------------------------------------------------------
755 mExists = PR_FALSE;
756 if (!mDir)
757 return *this;
758 PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH); // Ignore '.' && '..'
759 if (entry)
761 mExists = PR_TRUE;
762 mCurrent = mStarting;
763 mCurrent.SetLeafName(entry->name);
764 if (mResoveSymLinks)
766 PRBool ignore;
767 mCurrent.ResolveSymlink(ignore);
770 return *this;
771 } // nsDirectoryIterator::operator ++
773 //----------------------------------------------------------------------------------------
774 nsDirectoryIterator& nsDirectoryIterator::operator -- ()
775 //----------------------------------------------------------------------------------------
777 return ++(*this); // can't do it backwards.
778 } // nsDirectoryIterator::operator --