Back to index

lightning-sunbird  0.9+nobinonly
nsFileSpecWin.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Masayuki Nakano <masayuki@d-toybox.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 //     This file is included by nsFileSpec.cp, and includes the Windows-specific
00040 //     implementations.
00041 
00042 #include <sys/stat.h>
00043 #include <direct.h>
00044 #include <limits.h>
00045 #include <stdlib.h>
00046 #include "prio.h"
00047 #include "nsError.h"
00048 
00049 #include <windows.h>
00050 #include <mbstring.h>
00051 
00052 #if (_MSC_VER == 1100) || defined(__GNUC__)
00053 #define INITGUID
00054 #include <objbase.h>
00055 DEFINE_OLEGUID(IID_IPersistFile, 0x0000010BL, 0, 0);
00056 #endif
00057 
00058 #include <shlobj.h>
00059 #include <shellapi.h>
00060 #include <shlguid.h>
00061 
00062 #ifndef WINCE
00063 #ifdef UNICODE
00064 #define CreateDirectoryW  CreateDirectory
00065 #else
00066 #define CreateDirectoryA  CreateDirectory
00067 #endif 
00068 #endif
00069 
00070 //----------------------------------------------------------------------------------------
00071 void nsFileSpecHelpers::Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs)
00072 // Canonify, make absolute, and check whether directories exist. This
00073 // takes a (possibly relative) native path and converts it into a
00074 // fully qualified native path.
00075 //----------------------------------------------------------------------------------------
00076 {
00077     if (ioPath.IsEmpty())
00078         return;
00079   
00080     NS_ASSERTION(strchr((const char*)ioPath, '/') == 0,
00081               "This smells like a Unix path. Native path expected! "
00082               "Please fix.");
00083        if (inMakeDirs)
00084     {
00085         const int mode = 0755;
00086         nsSimpleCharString unixStylePath = ioPath;
00087         nsFileSpecHelpers::NativeToUnix(unixStylePath);
00088         nsFileSpecHelpers::MakeAllDirectories((const char*)unixStylePath, mode);
00089     }
00090     char buffer[_MAX_PATH];
00091     errno = 0;
00092     *buffer = '\0';
00093     char* canonicalPath = _fullpath(buffer, ioPath, _MAX_PATH);
00094 
00095        if (canonicalPath)
00096        {
00097               NS_ASSERTION( canonicalPath[0] != '\0', "Uh oh...couldn't convert" );
00098               if (canonicalPath[0] == '\0')
00099                      return;
00100        }
00101     ioPath = canonicalPath;
00102 } // nsFileSpecHelpers::Canonify
00103 
00104 //----------------------------------------------------------------------------------------
00105 void nsFileSpecHelpers::UnixToNative(nsSimpleCharString& ioPath)
00106 // This just does string manipulation.  It doesn't check reality, or canonify, or
00107 // anything
00108 //----------------------------------------------------------------------------------------
00109 {
00110        // Allow for relative or absolute.  We can do this in place, because the
00111        // native path is never longer.
00112        
00113        if (ioPath.IsEmpty())
00114               return;
00115               
00116   // Strip initial slash for an absolute path
00117        char* src = (char*)ioPath;
00118   if (*src == '/') {
00119     if (!src[1]) {
00120       // allocate new string by copying from ioPath[1]
00121       nsSimpleCharString temp = src + 1;
00122       ioPath = temp;
00123       return;
00124     }
00125          // Since it was an absolute path, check for the drive letter
00126               char* colonPointer = src + 2;
00127               if (strstr(src, "|/") == colonPointer)
00128            *colonPointer = ':';
00129          // allocate new string by copying from ioPath[1]
00130          nsSimpleCharString temp = src + 1;
00131          ioPath = temp;
00132        }
00133 
00134     // Convert '/' to '\'. (Must check EVERY character: consider UNC path
00135     // case.)
00136     for (src = (char*)ioPath; *src; ++src)
00137     {
00138         if (*src == '/')
00139             *src = '\\';
00140     }
00141 
00142 } // nsFileSpecHelpers::UnixToNative
00143 
00144 //----------------------------------------------------------------------------------------
00145 void nsFileSpecHelpers::NativeToUnix(nsSimpleCharString& ioPath)
00146 // This just does string manipulation.  It doesn't check reality, or canonify, or
00147 // anything.  The unix path is longer, so we can't do it in place.
00148 //----------------------------------------------------------------------------------------
00149 {
00150        if (ioPath.IsEmpty())
00151               return;
00152               
00153        // Convert the drive-letter separator, if present
00154        nsSimpleCharString temp("/");
00155 
00156        char* cp = (char*)ioPath + 1;
00157        if (strstr(cp, ":\\") == cp)
00158               *cp = '|';    // absolute path
00159     else
00160       if (cp[0] == '\\')    // unc path
00161         cp--;
00162         else
00163         temp[0] = '\0'; // relative path
00164        
00165        // Convert '\' to '/'
00166        for (; *cp; cp++)
00167     {
00168       if(IsDBCSLeadByte(*cp) && *(cp+1) != nsnull)
00169       {
00170          cp++;
00171          continue;
00172       }
00173       if (*cp == '\\')
00174         *cp = '/';
00175     }
00176        // Add the slash in front.
00177        temp += ioPath;
00178        ioPath = temp;
00179 }
00180 
00181 //----------------------------------------------------------------------------------------
00182 nsFileSpec::nsFileSpec(const nsFilePath& inPath)
00183 //----------------------------------------------------------------------------------------
00184 {
00185 //    NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
00186        *this = inPath;
00187 }
00188 
00189 //----------------------------------------------------------------------------------------
00190 void nsFileSpec::operator = (const nsFilePath& inPath)
00191 //----------------------------------------------------------------------------------------
00192 {
00193        mPath = (const char*)inPath;
00194        nsFileSpecHelpers::UnixToNative(mPath);
00195        mError = NS_OK;
00196 } // nsFileSpec::operator =
00197 
00198 //----------------------------------------------------------------------------------------
00199 nsFilePath::nsFilePath(const nsFileSpec& inSpec)
00200 //----------------------------------------------------------------------------------------
00201 {
00202        *this = inSpec;
00203 } // nsFilePath::nsFilePath
00204 
00205 //----------------------------------------------------------------------------------------
00206 void nsFilePath::operator = (const nsFileSpec& inSpec)
00207 //----------------------------------------------------------------------------------------
00208 {
00209        mPath = inSpec.mPath;
00210        nsFileSpecHelpers::NativeToUnix(mPath);
00211 } // nsFilePath::operator =
00212 
00213 //----------------------------------------------------------------------------------------
00214 void nsFileSpec::SetLeafName(const char* inLeafName)
00215 //----------------------------------------------------------------------------------------
00216 {
00217        NS_ASSERTION(inLeafName, "Attempt to SetLeafName with a null string");
00218        mPath.LeafReplace('\\', inLeafName);
00219 } // nsFileSpec::SetLeafName
00220 
00221 //----------------------------------------------------------------------------------------
00222 char* nsFileSpec::GetLeafName() const
00223 //----------------------------------------------------------------------------------------
00224 {
00225     return mPath.GetLeaf('\\');
00226 } // nsFileSpec::GetLeafName
00227 
00228 //----------------------------------------------------------------------------------------
00229 PRBool nsFileSpec::Exists() const
00230 //----------------------------------------------------------------------------------------
00231 {
00232        struct stat st;
00233        return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st); 
00234 } // nsFileSpec::Exists
00235 
00236 //----------------------------------------------------------------------------------------
00237 void nsFileSpec::GetModDate(TimeStamp& outStamp) const
00238 //----------------------------------------------------------------------------------------
00239 {
00240        struct stat st;
00241     if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0) 
00242         outStamp = st.st_mtime; 
00243     else
00244         outStamp = 0;
00245 } // nsFileSpec::GetModDate
00246 
00247 //----------------------------------------------------------------------------------------
00248 PRUint32 nsFileSpec::GetFileSize() const
00249 //----------------------------------------------------------------------------------------
00250 {
00251        struct stat st;
00252     if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0) 
00253         return (PRUint32)st.st_size; 
00254     return 0;
00255 } // nsFileSpec::GetFileSize
00256 
00257 //----------------------------------------------------------------------------------------
00258 PRBool nsFileSpec::IsFile() const
00259 //----------------------------------------------------------------------------------------
00260 {
00261   struct stat st;
00262   return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFREG & st.st_mode);
00263 } // nsFileSpec::IsFile
00264 
00265 //----------------------------------------------------------------------------------------
00266 PRBool nsFileSpec::IsDirectory() const
00267 //----------------------------------------------------------------------------------------
00268 {
00269        struct stat st;
00270        return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFDIR & st.st_mode);
00271 } // nsFileSpec::IsDirectory
00272 
00273 //----------------------------------------------------------------------------------------
00274 PRBool nsFileSpec::IsHidden() const
00275 //----------------------------------------------------------------------------------------
00276 {
00277     PRBool hidden = PR_FALSE;
00278     if (!mPath.IsEmpty())
00279     {
00280         DWORD attr = GetFileAttributes(mPath);
00281         if (FILE_ATTRIBUTE_HIDDEN & attr)
00282             hidden = PR_TRUE;
00283     }
00284     return hidden;
00285 }
00286 // nsFileSpec::IsHidden
00287 
00288 //----------------------------------------------------------------------------------------
00289 PRBool nsFileSpec::IsSymlink() const
00290 //----------------------------------------------------------------------------------------
00291 {
00292     HRESULT hres; 
00293     IShellLink* psl; 
00294     
00295     PRBool isSymlink = PR_FALSE;
00296 #ifndef WINCE
00297     CoInitialize(NULL);
00298     // Get a pointer to the IShellLink interface. 
00299     hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); 
00300     if (SUCCEEDED(hres)) 
00301     { 
00302         IPersistFile* ppf; 
00303         
00304         // Get a pointer to the IPersistFile interface. 
00305         hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); 
00306         
00307         if (SUCCEEDED(hres)) 
00308         {
00309             WCHAR wsz[MAX_PATH]; 
00310             // Ensure that the string is Unicode. 
00311             MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH); 
00312  
00313             // Load the shortcut. 
00314             hres = ppf->Load(wsz, STGM_READ); 
00315             if (SUCCEEDED(hres)) 
00316             {
00317                 isSymlink = PR_TRUE;
00318             }
00319             
00320             // Release the pointer to the IPersistFile interface. 
00321             ppf->Release(); 
00322         }
00323         
00324         // Release the pointer to the IShellLink interface. 
00325         psl->Release();
00326     }
00327 
00328     CoUninitialize();
00329 #endif
00330     return isSymlink;
00331 }
00332 
00333 
00334 //----------------------------------------------------------------------------------------
00335 nsresult nsFileSpec::ResolveSymlink(PRBool& wasSymlink)
00336 //----------------------------------------------------------------------------------------
00337 {
00338     wasSymlink = PR_FALSE;  // assume failure
00339 #ifndef WINCE
00340        if (Exists())
00341               return NS_OK;
00342 
00343 
00344     HRESULT hres; 
00345     IShellLink* psl; 
00346 
00347     CoInitialize(NULL);
00348 
00349     // Get a pointer to the IShellLink interface. 
00350     hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); 
00351     if (SUCCEEDED(hres)) 
00352     { 
00353         IPersistFile* ppf; 
00354         
00355         // Get a pointer to the IPersistFile interface. 
00356         hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); 
00357         
00358         if (SUCCEEDED(hres)) 
00359         {
00360             WCHAR wsz[MAX_PATH]; 
00361             // Ensure that the string is Unicode. 
00362             MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH); 
00363  
00364             // Load the shortcut. 
00365             hres = ppf->Load(wsz, STGM_READ); 
00366             if (SUCCEEDED(hres)) 
00367             {
00368                 wasSymlink = PR_TRUE;
00369 
00370                 // Resolve the link. 
00371                 hres = psl->Resolve(nsnull, SLR_NO_UI ); 
00372                 if (SUCCEEDED(hres)) 
00373                 { 
00374                     char szGotPath[MAX_PATH]; 
00375                     WIN32_FIND_DATA wfd; 
00376 
00377                     // Get the path to the link target. 
00378                     hres = psl->GetPath( szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY ); 
00379 
00380                     if (SUCCEEDED(hres))
00381                     {
00382                         // Here we modify the nsFileSpec;
00383                         mPath = szGotPath;
00384                         mError = NS_OK;
00385                     }
00386                 } 
00387             }
00388             else {
00389                 // It wasn't a shortcut. Oh well. Leave it like it was.
00390                 hres = 0;
00391             }
00392 
00393             // Release the pointer to the IPersistFile interface. 
00394             ppf->Release(); 
00395         }
00396         // Release the pointer to the IShellLink interface. 
00397         psl->Release();
00398     }
00399 
00400     CoUninitialize();
00401 
00402     if (SUCCEEDED(hres))
00403         return NS_OK;
00404 
00405     return NS_FILE_FAILURE;
00406 #else
00407     return NS_OK;
00408 #endif //WINCE
00409 }
00410 
00411 
00412 
00413 //----------------------------------------------------------------------------------------
00414 void nsFileSpec::GetParent(nsFileSpec& outSpec) const
00415 //----------------------------------------------------------------------------------------
00416 {
00417   outSpec.mPath = mPath;
00418   char* chars = (char*)outSpec.mPath;
00419   chars[outSpec.mPath.Length() - 1] = '\0'; // avoid trailing separator, if any
00420   unsigned char* cp = _mbsrchr((unsigned char*)chars, '\\');
00421   if (cp++)
00422     outSpec.mPath.SetLength(cp - (unsigned char*)chars); // truncate.
00423 } // nsFileSpec::GetParent
00424 
00425 //----------------------------------------------------------------------------------------
00426 void nsFileSpec::operator += (const char* inRelativePath)
00427 //----------------------------------------------------------------------------------------
00428 {
00429        NS_ASSERTION(inRelativePath, "Attempt to do += with a null string");
00430 
00431        if (!inRelativePath || mPath.IsEmpty())
00432               return;
00433        
00434        if (mPath[mPath.Length() - 1] == '\\')
00435               mPath += "x";
00436        else
00437               mPath += "\\x";
00438        
00439        // If it's a (unix) relative path, make it native
00440        nsSimpleCharString dosPath = inRelativePath;
00441        nsFileSpecHelpers::UnixToNative(dosPath);
00442        SetLeafName(dosPath);
00443 } // nsFileSpec::operator +=
00444 
00445 //----------------------------------------------------------------------------------------
00446 void nsFileSpec::CreateDirectory(int /*mode*/)
00447 //----------------------------------------------------------------------------------------
00448 {
00449        // Note that mPath is canonical!
00450        if (!mPath.IsEmpty())
00451            mkdir(nsNSPRPath(*this));
00452 } // nsFileSpec::CreateDirectory
00453 
00454 //----------------------------------------------------------------------------------------
00455 void nsFileSpec::Delete(PRBool inRecursive) const
00456 //----------------------------------------------------------------------------------------
00457 {
00458     if (IsDirectory())
00459     {
00460            if (inRecursive)
00461         {
00462             for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
00463                 {
00464                     nsFileSpec& child = (nsFileSpec&)i;
00465                     child.Delete(inRecursive);
00466                 }           
00467         }
00468            rmdir(nsNSPRPath(*this));
00469     }
00470        else if (!mPath.IsEmpty())
00471     {
00472         remove(nsNSPRPath(*this));
00473     }
00474 } // nsFileSpec::Delete
00475 
00476 
00477 //----------------------------------------------------------------------------------------
00478 void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
00479 //----------------------------------------------------------------------------------------
00480 {
00481     if (IsDirectory())
00482     {
00483               if (!(newDir.Exists()))
00484               {
00485                      newDir.CreateDirectory();
00486               }
00487 
00488               for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
00489               {
00490                      nsFileSpec& child = (nsFileSpec&)i;
00491 
00492                      if (child.IsDirectory())
00493                      {
00494                             nsFileSpec tmpDirSpec(newDir);
00495 
00496                             char *leafname = child.GetLeafName();
00497                             tmpDirSpec += leafname;
00498                             nsCRT::free(leafname);
00499 
00500                             child.RecursiveCopy(tmpDirSpec);
00501                      }
00502                      else
00503                      {
00504                             child.RecursiveCopy(newDir);
00505                      }
00506               }
00507     }
00508     else if (!mPath.IsEmpty())
00509     {
00510               nsFileSpec& filePath = (nsFileSpec&) *this;
00511 
00512               if (!(newDir.Exists()))
00513               {
00514                      newDir.CreateDirectory();
00515               }
00516 
00517         filePath.CopyToDir(newDir);
00518     }
00519 } // nsFileSpec::RecursiveCopy
00520 
00521 //----------------------------------------------------------------------------------------
00522 nsresult
00523 nsFileSpec::Truncate(PRInt32 aNewFileLength) const
00524 //----------------------------------------------------------------------------------------
00525 {
00526     DWORD status;
00527     HANDLE hFile;
00528 
00529     // Leave it to Microsoft to open an existing file with a function
00530     // named "CreateFile".
00531     hFile = CreateFile(mPath,
00532                        GENERIC_WRITE, 
00533                        FILE_SHARE_READ, 
00534                        NULL, 
00535                        OPEN_EXISTING, 
00536                        FILE_ATTRIBUTE_NORMAL, 
00537                        NULL); 
00538     if (hFile == INVALID_HANDLE_VALUE)
00539         return NS_FILE_FAILURE;
00540 
00541     // Seek to new, desired end of file
00542     status = SetFilePointer(hFile, aNewFileLength, NULL, FILE_BEGIN);
00543     if (status == 0xffffffff)
00544         goto error;
00545 
00546     // Truncate file at current cursor position
00547     if (!SetEndOfFile(hFile))
00548         goto error;
00549 
00550     if (!CloseHandle(hFile))
00551         return NS_FILE_FAILURE;
00552 
00553     return NS_OK;
00554 
00555  error:
00556     CloseHandle(hFile);
00557     return NS_FILE_FAILURE;
00558 
00559 } // nsFileSpec::Truncate
00560 
00561 //----------------------------------------------------------------------------------------
00562 nsresult nsFileSpec::Rename(const char* inNewName)
00563 //----------------------------------------------------------------------------------------
00564 {
00565        NS_ASSERTION(inNewName, "Attempt to Rename with a null string");
00566 
00567     // This function should not be used to move a file on disk. 
00568     if (strchr(inNewName, '/')) 
00569         return NS_FILE_FAILURE;
00570 
00571     char* oldPath = nsCRT::strdup(mPath);
00572     
00573     SetLeafName(inNewName);        
00574 
00575     if (PR_Rename(oldPath, mPath) != NS_OK)
00576     {
00577         // Could not rename, set back to the original.
00578         mPath = oldPath;
00579         return NS_FILE_FAILURE;
00580     }
00581     
00582     nsCRT::free(oldPath);
00583     
00584     return NS_OK;
00585 } // nsFileSpec::Rename
00586 
00587 //----------------------------------------------------------------------------------------
00588 nsresult nsFileSpec::CopyToDir(const nsFileSpec& inParentDirectory) const
00589 //----------------------------------------------------------------------------------------
00590 {
00591     // We can only copy into a directory, and (for now) can not copy entire directories
00592     if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
00593     {
00594         char *leafname = GetLeafName();
00595         nsSimpleCharString destPath(inParentDirectory.GetCString());
00596         destPath += "\\";
00597         destPath += leafname;
00598         nsCRT::free(leafname);
00599         
00600         // CopyFile returns non-zero if succeeds
00601         int copyOK = CopyFile(GetCString(), destPath, PR_TRUE);
00602         if (copyOK)
00603             return NS_OK;
00604     }
00605     return NS_FILE_FAILURE;
00606 } // nsFileSpec::CopyToDir
00607 
00608 //----------------------------------------------------------------------------------------
00609 nsresult nsFileSpec::MoveToDir(const nsFileSpec& inNewParentDirectory)
00610 //----------------------------------------------------------------------------------------
00611 {
00612     // We can only copy into a directory, and (for now) can not copy entire directories
00613     if (inNewParentDirectory.IsDirectory() && (! IsDirectory() ) )
00614     {
00615         char *leafname = GetLeafName();
00616         nsSimpleCharString destPath(inNewParentDirectory.GetCString());
00617         destPath += "\\";
00618         destPath += leafname;
00619         nsCRT::free(leafname);
00620 
00621         // MoveFile returns non-zero if succeeds
00622         int copyOK = MoveFile(GetCString(), destPath);
00623 
00624         if (copyOK)
00625         {
00626             *this = inNewParentDirectory + GetLeafName(); 
00627             return NS_OK;
00628         }
00629         
00630     }
00631     return NS_FILE_FAILURE;
00632 } // nsFileSpec::MoveToDir
00633 
00634 //----------------------------------------------------------------------------------------
00635 nsresult nsFileSpec::Execute(const char* inArgs ) const
00636 //----------------------------------------------------------------------------------------
00637 {    
00638 #ifndef WINCE
00639     if (!IsDirectory())
00640     {
00641         nsSimpleCharString fileNameWithArgs = "\"";
00642         fileNameWithArgs += mPath + "\" " + inArgs;
00643         int execResult = WinExec( fileNameWithArgs, SW_NORMAL );     
00644         if (execResult > 31)
00645             return NS_OK;
00646     }
00647 #endif
00648     return NS_FILE_FAILURE;
00649 } // nsFileSpec::Execute
00650 
00651 
00652 //----------------------------------------------------------------------------------------
00653 PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
00654 //----------------------------------------------------------------------------------------
00655 {
00656 #ifndef WINCE
00657     PRInt64 int64;
00658     
00659     LL_I2L(int64 , LONG_MAX);
00660 
00661     char aDrive[_MAX_DRIVE + 2];
00662        _splitpath( (const char*)mPath, aDrive, NULL, NULL, NULL);
00663 
00664        if (aDrive[0] == '\0')
00665        {
00666         // The back end is always trying to pass us paths that look
00667         //   like /c|/netscape/mail.  See if we've got one of them
00668         if (mPath.Length() > 2 && mPath[0] == '/' && mPath[2] == '|')
00669         {
00670             aDrive[0] = mPath[1];
00671             aDrive[1] = ':';
00672             aDrive[2] = '\0';
00673         }
00674         else
00675         {
00676             // Return bogus large number and hope for the best
00677             return int64; 
00678         }
00679     }
00680 
00681        strcat(aDrive, "\\");
00682 
00683     // Check disk space
00684     DWORD dwSecPerClus, dwBytesPerSec, dwFreeClus, dwTotalClus;
00685     ULARGE_INTEGER liFreeBytesAvailableToCaller, liTotalNumberOfBytes, liTotalNumberOfFreeBytes;
00686     double nBytes = 0;
00687 
00688     BOOL (WINAPI* getDiskFreeSpaceExA)(LPCTSTR lpDirectoryName, 
00689                                        PULARGE_INTEGER lpFreeBytesAvailableToCaller,
00690                                        PULARGE_INTEGER lpTotalNumberOfBytes,    
00691                                        PULARGE_INTEGER lpTotalNumberOfFreeBytes) = NULL;
00692 
00693     HINSTANCE hInst = LoadLibrary("KERNEL32.DLL");
00694     NS_ASSERTION(hInst != NULL, "COULD NOT LOAD KERNEL32.DLL");
00695     if (hInst != NULL)
00696     {
00697         getDiskFreeSpaceExA =  (BOOL (WINAPI*)(LPCTSTR lpDirectoryName, 
00698                                                PULARGE_INTEGER lpFreeBytesAvailableToCaller,
00699                                                PULARGE_INTEGER lpTotalNumberOfBytes,    
00700                                                PULARGE_INTEGER lpTotalNumberOfFreeBytes)) 
00701         GetProcAddress(hInst, "GetDiskFreeSpaceExA");
00702         FreeLibrary(hInst);
00703     }
00704 
00705     if (getDiskFreeSpaceExA && (*getDiskFreeSpaceExA)(aDrive,
00706                                                       &liFreeBytesAvailableToCaller, 
00707                                                       &liTotalNumberOfBytes,  
00708                                                       &liTotalNumberOfFreeBytes))
00709     {
00710         nBytes = (double)(signed __int64)liFreeBytesAvailableToCaller.QuadPart;
00711     }
00712     else if ( GetDiskFreeSpace(aDrive, &dwSecPerClus, &dwBytesPerSec, &dwFreeClus, &dwTotalClus))
00713     {
00714         nBytes = (double)dwFreeClus*(double)dwSecPerClus*(double) dwBytesPerSec;
00715     }
00716     return (PRInt64)nBytes;
00717 #else
00718     return (PRInt64)0;
00719 #endif
00720 }
00721 
00722 
00723 
00724 //========================================================================================
00725 //                                                      nsDirectoryIterator
00726 //========================================================================================
00727 
00728 //----------------------------------------------------------------------------------------
00729 nsDirectoryIterator::nsDirectoryIterator(const nsFileSpec& inDirectory, PRBool resolveSymlink)
00730 //----------------------------------------------------------------------------------------
00731        : mCurrent(inDirectory)
00732        , mDir(nsnull)
00733     , mStarting(inDirectory)
00734        , mExists(PR_FALSE)
00735     , mResoveSymLinks(resolveSymlink)
00736 {
00737     mDir = PR_OpenDir(inDirectory);
00738        mCurrent += "dummy";
00739     mStarting += "dummy";
00740     ++(*this);
00741 } // nsDirectoryIterator::nsDirectoryIterator
00742 
00743 //----------------------------------------------------------------------------------------
00744 nsDirectoryIterator::~nsDirectoryIterator()
00745 //----------------------------------------------------------------------------------------
00746 {
00747     if (mDir)
00748            PR_CloseDir(mDir);
00749 } // nsDirectoryIterator::nsDirectoryIterator
00750 
00751 //----------------------------------------------------------------------------------------
00752 nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
00753 //----------------------------------------------------------------------------------------
00754 {
00755        mExists = PR_FALSE;
00756        if (!mDir)
00757               return *this;
00758     PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH); // Ignore '.' && '..'
00759        if (entry)
00760     {
00761       mExists = PR_TRUE;
00762       mCurrent = mStarting;
00763       mCurrent.SetLeafName(entry->name);
00764       if (mResoveSymLinks)
00765       {   
00766           PRBool ignore;
00767           mCurrent.ResolveSymlink(ignore);
00768       }
00769     }
00770        return *this;
00771 } // nsDirectoryIterator::operator ++
00772 
00773 //----------------------------------------------------------------------------------------
00774 nsDirectoryIterator& nsDirectoryIterator::operator -- ()
00775 //----------------------------------------------------------------------------------------
00776 {
00777        return ++(*this); // can't do it backwards.
00778 } // nsDirectoryIterator::operator --
00779