Back to index

lightning-sunbird  0.9+nobinonly
nsFileSpecOS2.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Mozilla OS/2 libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * John Fairhurst, <john_fairhurst@iname.com>.
00018  * Portions created by the Initial Developer are Copyright (C) 1998
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Henry Sobotka <sobotka@axess.com>
00023  *   00/01/06: general review and update against Win/Unix versions;
00024  *   replaced nsFileSpec::Execute implementation with system() call
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK *****
00039  * 
00040  * This Original Code has been modified by IBM Corporation.
00041  * Modifications made by IBM described herein are
00042  * Copyright (c) International Business Machines
00043  * Corporation, 2000
00044  *
00045  * Modifications to Mozilla code or documentation
00046  * identified per MPL Section 3.3
00047  *
00048  * Date             Modified by     Description of modification
00049  * 03/23/2000       IBM Corp.      Fixed bug where 2 char or less profile names treated as drive letters.
00050  * 06/20/2000       IBM Corp.      Make it more like Windows version.
00051  */
00052 
00053 #define INCL_DOSERRORS
00054 #define INCL_DOS
00055 #define INCL_WINWORKPLACE
00056 #include <os2.h>
00057 
00058 #ifdef XP_OS2_VACPP
00059 #include <direct.h>
00060 #endif
00061 
00062 #include <sys/types.h>
00063 #include <sys/stat.h>
00064 #include <limits.h>
00065 #include <ctype.h>
00066 #include <io.h>
00067 
00068 //----------------------------------------------------------------------------------------
00069 void nsFileSpecHelpers::Canonify(nsSimpleCharString& ioPath, PRBool inMakeDirs)
00070 // Canonify, make absolute, and check whether directories exist. This
00071 // takes a (possibly relative) native path and converts it into a
00072 // fully qualified native path.
00073 //----------------------------------------------------------------------------------------
00074 {
00075     if (ioPath.IsEmpty())
00076         return;
00077   
00078     NS_ASSERTION(strchr((const char*)ioPath, '/') == 0,
00079               "This smells like a Unix path. Native path expected! "
00080               "Please fix.");
00081        if (inMakeDirs)
00082     {
00083         const int mode = 0700;
00084         nsSimpleCharString unixStylePath = ioPath;
00085         nsFileSpecHelpers::NativeToUnix(unixStylePath);
00086         nsFileSpecHelpers::MakeAllDirectories((const char*)unixStylePath, mode);
00087     }
00088     char buffer[_MAX_PATH];
00089     errno = 0;
00090     *buffer = '\0';
00091 #ifdef XP_OS2
00092     PRBool removedBackslash = PR_FALSE;
00093     PRUint32 lenstr = ioPath.Length();
00094     char &lastchar = ioPath[lenstr -1];
00095 
00096     // Strip off any trailing backslash UNLESS it's the backslash that
00097     // comes after "X:".  Note also that "\" is valid.  Sheesh.
00098     //
00099     if( lastchar == '\\' && (lenstr != 3 || ioPath[1] != ':') && lenstr != 1)
00100     {
00101        lastchar = '\0';
00102        removedBackslash = PR_TRUE;
00103     }
00104 
00105     char canonicalPath[CCHMAXPATH] = "";
00106 
00107     DosQueryPathInfo( (char*) ioPath, 
00108                                           FIL_QUERYFULLNAME,
00109                                           canonicalPath, 
00110                                           CCHMAXPATH);
00111 #else
00112     char* canonicalPath = _fullpath(buffer, ioPath, _MAX_PATH);
00113 #endif
00114 
00115        if (canonicalPath)
00116        {
00117               NS_ASSERTION( canonicalPath[0] != '\0', "Uh oh...couldn't convert" );
00118               if (canonicalPath[0] == '\0')
00119                      return;
00120 #ifdef XP_OS2
00121                 // If we removed that backslash, add it back onto the fullpath
00122                 if (removedBackslash)
00123                    strcat( canonicalPath, "\\");
00124 #endif
00125        }
00126     ioPath = canonicalPath;
00127 } // nsFileSpecHelpers::Canonify
00128 
00129 //----------------------------------------------------------------------------------------
00130 void nsFileSpecHelpers::UnixToNative(nsSimpleCharString& ioPath)
00131 // This just does string manipulation.  It doesn't check reality, or canonify, or
00132 // anything
00133 //----------------------------------------------------------------------------------------
00134 {
00135        // Allow for relative or absolute.  We can do this in place, because the
00136        // native path is never longer.
00137        
00138        if (ioPath.IsEmpty())
00139               return;
00140               
00141   // Strip initial slash for an absolute path
00142        char* src = (char*)ioPath;
00143   if (*src == '/') {
00144     if (!src[1]) {
00145       // allocate new string by copying from ioPath[1]
00146       nsSimpleCharString temp = src + 1;
00147       ioPath = temp;
00148       return;
00149     }
00150          // Since it was an absolute path, check for the drive letter
00151               char* colonPointer = src + 2;
00152               if (strstr(src, "|/") == colonPointer)
00153            *colonPointer = ':';
00154          // allocate new string by copying from ioPath[1]
00155          nsSimpleCharString temp = src + 1;
00156          ioPath = temp;
00157        }
00158 
00159        src = (char*)ioPath;
00160               
00161     if (*src) {
00162            // Convert '/' to '\'.
00163            while (*++src)
00164         {
00165             if (*src == '/')
00166                 *src = '\\';
00167         }
00168     }
00169 } // nsFileSpecHelpers::UnixToNative
00170 
00171 //----------------------------------------------------------------------------------------
00172 void nsFileSpecHelpers::NativeToUnix(nsSimpleCharString& ioPath)
00173 // This just does string manipulation.  It doesn't check reality, or canonify, or
00174 // anything.  The unix path is longer, so we can't do it in place.
00175 //----------------------------------------------------------------------------------------
00176 {
00177        if (ioPath.IsEmpty())
00178               return;
00179               
00180        // Convert the drive-letter separator, if present
00181        nsSimpleCharString temp("/");
00182 
00183        char* cp = (char*)ioPath + 1;
00184        if (strstr(cp, ":\\") == cp)
00185               *cp = '|';    // absolute path
00186     else
00187         temp[0] = '\0'; // relative path
00188        
00189        // Convert '\' to '/'
00190        for (; *cp; cp++)
00191     {
00192 #ifdef XP_OS2
00193       // OS2TODO - implement equivalent of IsDBCSLeadByte
00194 #else
00195       if(IsDBCSLeadByte(*cp) && *(cp+1) != nsnull)
00196       {
00197          cp++;
00198          continue;
00199       }
00200 #endif
00201       if (*cp == '\\')
00202         *cp = '/';
00203     }
00204        // Add the slash in front.
00205        temp += ioPath;
00206        ioPath = temp;
00207 }
00208 
00209 //----------------------------------------------------------------------------------------
00210 nsFileSpec::nsFileSpec(const nsFilePath& inPath)
00211 //----------------------------------------------------------------------------------------
00212 {
00213 //    NS_ASSERTION(0, "nsFileSpec is unsupported - use nsIFile!");
00214        *this = inPath;
00215 }
00216 
00217 //----------------------------------------------------------------------------------------
00218 void nsFileSpec::operator = (const nsFilePath& inPath)
00219 //----------------------------------------------------------------------------------------
00220 {
00221        mPath = (const char*)inPath;
00222        nsFileSpecHelpers::UnixToNative(mPath);
00223        mError = NS_OK;
00224 } // nsFileSpec::operator =
00225 
00226 //----------------------------------------------------------------------------------------
00227 nsFilePath::nsFilePath(const nsFileSpec& inSpec)
00228 //----------------------------------------------------------------------------------------
00229 {
00230        *this = inSpec;
00231 } // nsFilePath::nsFilePath
00232 
00233 //----------------------------------------------------------------------------------------
00234 void nsFilePath::operator = (const nsFileSpec& inSpec)
00235 //----------------------------------------------------------------------------------------
00236 {
00237        mPath = inSpec.mPath;
00238        nsFileSpecHelpers::NativeToUnix(mPath);
00239 } // nsFilePath::operator =
00240 
00241 //----------------------------------------------------------------------------------------
00242 void nsFileSpec::SetLeafName(const char* inLeafName)
00243 //----------------------------------------------------------------------------------------
00244 {
00245        NS_ASSERTION(inLeafName, "Attempt to SetLeafName with a null string");
00246        mPath.LeafReplace('\\', inLeafName);
00247 } // nsFileSpec::SetLeafName
00248 
00249 //----------------------------------------------------------------------------------------
00250 char* nsFileSpec::GetLeafName() const
00251 //----------------------------------------------------------------------------------------
00252 {
00253     return mPath.GetLeaf('\\');
00254 } // nsFileSpec::GetLeafName
00255 
00256 //----------------------------------------------------------------------------------------
00257 PRBool nsFileSpec::Exists() const
00258 //----------------------------------------------------------------------------------------
00259 {
00260        struct stat st;
00261        return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st); 
00262 } // nsFileSpec::Exists
00263 
00264 //----------------------------------------------------------------------------------------
00265 void nsFileSpec::GetModDate(TimeStamp& outStamp) const
00266 //----------------------------------------------------------------------------------------
00267 {
00268        struct stat st;
00269     if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0) 
00270         outStamp = st.st_mtime; 
00271     else
00272         outStamp = 0;
00273 } // nsFileSpec::GetModDate
00274 
00275 //----------------------------------------------------------------------------------------
00276 PRUint32 nsFileSpec::GetFileSize() const
00277 //----------------------------------------------------------------------------------------
00278 {
00279        struct stat st;
00280     if (!mPath.IsEmpty() && stat(nsNSPRPath(*this), &st) == 0) 
00281         return (PRUint32)st.st_size; 
00282     return 0;
00283 } // nsFileSpec::GetFileSize
00284 
00285 //----------------------------------------------------------------------------------------
00286 PRBool nsFileSpec::IsFile() const
00287 //----------------------------------------------------------------------------------------
00288 {
00289   struct stat st;
00290 #ifdef XP_OS2
00291   return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (  S_IFREG & st.st_mode);
00292 #else
00293   return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFREG & st.st_mode);
00294 #endif
00295 } // nsFileSpec::IsFile
00296 
00297 //----------------------------------------------------------------------------------------
00298 PRBool nsFileSpec::IsDirectory() const
00299 //----------------------------------------------------------------------------------------
00300 {
00301        struct stat st;
00302 #ifdef XP_OS2
00303         return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (  S_IFDIR & st.st_mode);
00304 #else
00305        return !mPath.IsEmpty() && 0 == stat(nsNSPRPath(*this), &st) && (_S_IFDIR & st.st_mode);
00306 #endif
00307 } // nsFileSpec::IsDirectory
00308 
00309 //----------------------------------------------------------------------------------------
00310 PRBool nsFileSpec::IsHidden() const
00311 //----------------------------------------------------------------------------------------
00312 {
00313     PRBool hidden = PR_FALSE;
00314     if (!mPath.IsEmpty())
00315     {
00316 #ifdef XP_OS2
00317         FILESTATUS3 fs3;
00318         APIRET rc;
00319 
00320         rc = DosQueryPathInfo( mPath,
00321                                          FIL_STANDARD, 
00322                                          &fs3,
00323                                          sizeof fs3);
00324         if(!rc)
00325           hidden = fs3.attrFile & FILE_HIDDEN ? PR_TRUE : PR_FALSE;
00326 #else
00327         DWORD attr = GetFileAttributes(mPath);
00328         if (FILE_ATTRIBUTE_HIDDEN & attr)
00329             hidden = PR_TRUE;
00330 #endif
00331     }
00332     return hidden;
00333 }
00334 // nsFileSpec::IsHidden
00335 
00336 //----------------------------------------------------------------------------------------
00337 PRBool nsFileSpec::IsSymlink() const
00338 //----------------------------------------------------------------------------------------
00339 {
00340 #ifdef XP_OS2
00341     return PR_FALSE;                // No symlinks on OS/2
00342 #else
00343     HRESULT hres; 
00344     IShellLink* psl; 
00345     
00346     PRBool isSymlink = PR_FALSE;
00347     
00348     CoInitialize(NULL);
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             WORD 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                 isSymlink = PR_TRUE;
00369             }
00370             
00371             // Release the pointer to the IPersistFile interface. 
00372             ppf->Release(); 
00373         }
00374         
00375         // Release the pointer to the IShellLink interface. 
00376         psl->Release();
00377     }
00378 
00379     CoUninitialize();
00380 
00381     return isSymlink;
00382 #endif
00383 }
00384 
00385 
00386 //----------------------------------------------------------------------------------------
00387 nsresult nsFileSpec::ResolveSymlink(PRBool& wasSymlink)
00388 //----------------------------------------------------------------------------------------
00389 {
00390 #ifdef XP_OS2
00391     return NS_OK;           // no symlinks on OS/2
00392 #else
00393     wasSymlink = PR_FALSE;  // assume failure
00394 
00395        if (Exists())
00396               return NS_OK;
00397 
00398 
00399     HRESULT hres; 
00400     IShellLink* psl; 
00401 
00402     CoInitialize(NULL);
00403 
00404     // Get a pointer to the IShellLink interface. 
00405     hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); 
00406     if (SUCCEEDED(hres)) 
00407     { 
00408         IPersistFile* ppf; 
00409         
00410         // Get a pointer to the IPersistFile interface. 
00411         hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); 
00412         
00413         if (SUCCEEDED(hres)) 
00414         {
00415             WORD wsz[MAX_PATH]; 
00416             // Ensure that the string is Unicode. 
00417             MultiByteToWideChar(CP_ACP, 0, mPath, -1, wsz, MAX_PATH); 
00418  
00419             // Load the shortcut. 
00420             hres = ppf->Load(wsz, STGM_READ); 
00421             if (SUCCEEDED(hres)) 
00422             {
00423                 wasSymlink = PR_TRUE;
00424 
00425                 // Resolve the link. 
00426                 hres = psl->Resolve(nsnull, SLR_NO_UI ); 
00427                 if (SUCCEEDED(hres)) 
00428                 { 
00429                     char szGotPath[MAX_PATH]; 
00430                     WIN32_FIND_DATA wfd; 
00431 
00432                     // Get the path to the link target. 
00433                     hres = psl->GetPath( szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY ); 
00434 
00435                     if (SUCCEEDED(hres))
00436                     {
00437                         // Here we modify the nsFileSpec;
00438                         mPath = szGotPath;
00439                         mError = NS_OK;
00440                     }
00441                 } 
00442             }
00443             else {
00444                 // It wasn't a shortcut. Oh well. Leave it like it was.
00445                 hres = 0;
00446             }
00447 
00448             // Release the pointer to the IPersistFile interface. 
00449             ppf->Release(); 
00450         }
00451         // Release the pointer to the IShellLink interface. 
00452         psl->Release();
00453     }
00454 
00455     CoUninitialize();
00456 
00457     if (SUCCEEDED(hres))
00458         return NS_OK;
00459 
00460     return NS_FILE_FAILURE;
00461 #endif
00462 }
00463 
00464 
00465 
00466 //----------------------------------------------------------------------------------------
00467 void nsFileSpec::GetParent(nsFileSpec& outSpec) const
00468 //----------------------------------------------------------------------------------------
00469 {
00470        outSpec.mPath = mPath;
00471        char* chars = (char*)outSpec.mPath;
00472        chars[outSpec.mPath.Length() - 1] = '\0'; // avoid trailing separator, if any
00473     char* cp = strrchr(chars, '\\');
00474     if (cp++)
00475            outSpec.mPath.SetLength(cp - chars); // truncate.
00476 } // nsFileSpec::GetParent
00477 
00478 //----------------------------------------------------------------------------------------
00479 void nsFileSpec::operator += (const char* inRelativePath)
00480 //----------------------------------------------------------------------------------------
00481 {
00482        NS_ASSERTION(inRelativePath, "Attempt to do += with a null string");
00483 
00484        if (!inRelativePath || mPath.IsEmpty())
00485               return;
00486        
00487        if (mPath[mPath.Length() - 1] == '\\')
00488               mPath += "x";
00489        else
00490               mPath += "\\x";
00491        
00492        // If it's a (unix) relative path, make it native
00493        nsSimpleCharString dosPath = inRelativePath;
00494        nsFileSpecHelpers::UnixToNative(dosPath);
00495        SetLeafName(dosPath);
00496 } // nsFileSpec::operator +=
00497 
00498 //----------------------------------------------------------------------------------------
00499 void nsFileSpec::CreateDirectory(int /*mode*/)
00500 //----------------------------------------------------------------------------------------
00501 {
00502        // Note that mPath is canonical!
00503        if (!mPath.IsEmpty())
00504 #ifdef XP_OS2
00505            // OS2TODO - vacpp complains about mkdir but PR_MkDir should be ok?
00506             PR_MkDir(nsNSPRPath(*this), PR_CREATE_FILE);
00507 #else
00508            mkdir(nsNSPRPath(*this));
00509 #endif
00510 } // nsFileSpec::CreateDirectory
00511 
00512 //----------------------------------------------------------------------------------------
00513 void nsFileSpec::Delete(PRBool inRecursive) const
00514 //----------------------------------------------------------------------------------------
00515 {
00516     if (IsDirectory())
00517     {
00518            if (inRecursive)
00519         {
00520             for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
00521                 {
00522                     nsFileSpec& child = i.Spec();
00523                     child.Delete(inRecursive);
00524                 }           
00525         }
00526 #ifdef XP_OS2
00527             // OS2TODO - vacpp complains if use rmdir but PR_RmDir should be ok?
00528             PR_RmDir(nsNSPRPath(*this));
00529 #else
00530            rmdir(nsNSPRPath(*this));
00531 #endif
00532     }
00533        else if (!mPath.IsEmpty())
00534     {
00535         remove(nsNSPRPath(*this));
00536     }
00537 } // nsFileSpec::Delete
00538 
00539 
00540 //----------------------------------------------------------------------------------------
00541 void nsFileSpec::RecursiveCopy(nsFileSpec newDir) const
00542 //----------------------------------------------------------------------------------------
00543 {
00544     if (IsDirectory())
00545     {
00546               if (!(newDir.Exists()))
00547               {
00548                      newDir.CreateDirectory();
00549               }
00550 
00551               for (nsDirectoryIterator i(*this, PR_FALSE); i.Exists(); i++)
00552               {
00553                      nsFileSpec& child = i.Spec();
00554 
00555                      if (child.IsDirectory())
00556                      {
00557                             nsFileSpec tmpDirSpec(newDir);
00558 
00559                             char *leafname = child.GetLeafName();
00560                             tmpDirSpec += leafname;
00561                             nsCRT::free(leafname);
00562 
00563                             child.RecursiveCopy(tmpDirSpec);
00564                      }
00565                      else
00566                      {
00567                             child.RecursiveCopy(newDir);
00568                      }
00569               }
00570     }
00571     else if (!mPath.IsEmpty())
00572     {
00573               nsFileSpec& filePath = (nsFileSpec&) *this;
00574 
00575               if (!(newDir.Exists()))
00576               {
00577                      newDir.CreateDirectory();
00578               }
00579 
00580         filePath.CopyToDir(newDir);
00581     }
00582 } // nsFileSpec::RecursiveCopy
00583 
00584 //----------------------------------------------------------------------------------------
00585 nsresult
00586 nsFileSpec::Truncate(PRInt32 aNewFileLength) const
00587 //----------------------------------------------------------------------------------------
00588 {
00589 #ifdef XP_OS2
00590     APIRET rc;
00591     HFILE hFile;
00592     ULONG actionTaken;
00593 
00594     rc = DosOpen(mPath,
00595                  &hFile,
00596                  &actionTaken,
00597                  0,                 
00598                  FILE_NORMAL,
00599                  OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS,
00600                  OPEN_SHARE_DENYWRITE | OPEN_ACCESS_WRITEONLY,
00601                  NULL);
00602                                  
00603     if (rc != NO_ERROR)
00604         return NS_FILE_FAILURE;
00605 
00606     rc = DosSetFileSize(hFile, aNewFileLength);
00607 
00608     if (rc == NO_ERROR) 
00609         DosClose(hFile);
00610     else
00611         goto error; 
00612 #else
00613     DWORD status;
00614     HANDLE hFile;
00615 
00616     // Leave it to Microsoft to open an existing file with a function
00617     // named "CreateFile".
00618     hFile = CreateFile(mPath,
00619                        GENERIC_WRITE, 
00620                        FILE_SHARE_READ, 
00621                        NULL, 
00622                        OPEN_EXISTING, 
00623                        FILE_ATTRIBUTE_NORMAL, 
00624                        NULL); 
00625     if (hFile == INVALID_HANDLE_VALUE)
00626         return NS_FILE_FAILURE;
00627 
00628     // Seek to new, desired end of file
00629     status = SetFilePointer(hFile, aNewFileLength, NULL, FILE_BEGIN);
00630     if (status == 0xffffffff)
00631         goto error;
00632 
00633     // Truncate file at current cursor position
00634     if (!SetEndOfFile(hFile))
00635         goto error;
00636 
00637     if (!CloseHandle(hFile))
00638         return NS_FILE_FAILURE;
00639 #endif
00640 
00641     return NS_OK;
00642 
00643  error:
00644 #ifdef XP_OS2
00645     DosClose(hFile);
00646 #else
00647     CloseHandle(hFile);
00648 #endif
00649     return NS_FILE_FAILURE;
00650 
00651 } // nsFileSpec::Truncate
00652 
00653 //----------------------------------------------------------------------------------------
00654 nsresult nsFileSpec::Rename(const char* inNewName)
00655 //----------------------------------------------------------------------------------------
00656 {
00657        NS_ASSERTION(inNewName, "Attempt to Rename with a null string");
00658 
00659     // This function should not be used to move a file on disk. 
00660     if (strchr(inNewName, '/')) 
00661         return NS_FILE_FAILURE;
00662 
00663     char* oldPath = nsCRT::strdup(mPath);
00664     
00665     SetLeafName(inNewName);        
00666 
00667     if (PR_Rename(oldPath, mPath) != NS_OK)
00668     {
00669         // Could not rename, set back to the original.
00670         mPath = oldPath;
00671         return NS_FILE_FAILURE;
00672     }
00673     
00674     nsCRT::free(oldPath);
00675     
00676     return NS_OK;
00677 } // nsFileSpec::Rename
00678 
00679 //----------------------------------------------------------------------------------------
00680 nsresult nsFileSpec::CopyToDir(const nsFileSpec& inParentDirectory) const
00681 //----------------------------------------------------------------------------------------
00682 {
00683     // We can only copy into a directory, and (for now) can not copy entire directories
00684     if (inParentDirectory.IsDirectory() && (! IsDirectory() ) )
00685     {
00686         char *leafname = GetLeafName();
00687         nsSimpleCharString destPath(inParentDirectory.GetCString());
00688         destPath += "\\";
00689         destPath += leafname;
00690         nsCRT::free(leafname);
00691         
00692         // CopyFile returns non-zero if succeeds
00693 #ifdef XP_OS2
00694         APIRET rc;
00695         PRBool copyOK;
00696 
00697         rc = DosCopy(GetCString(), (PSZ)destPath, DCPY_EXISTING);
00698 
00699         if (rc == NO_ERROR)
00700             copyOK = PR_TRUE;
00701         else
00702             copyOK = PR_FALSE;
00703 #else
00704         int copyOK = CopyFile(GetCString(), destPath, PR_TRUE);
00705 #endif
00706         if (copyOK)
00707             return NS_OK;
00708     }
00709     return NS_FILE_FAILURE;
00710 } // nsFileSpec::CopyToDir
00711 
00712 //----------------------------------------------------------------------------------------
00713 nsresult nsFileSpec::MoveToDir(const nsFileSpec& inNewParentDirectory)
00714 //----------------------------------------------------------------------------------------
00715 {
00716     // We can only copy into a directory, and (for now) can not copy entire directories
00717     if (inNewParentDirectory.IsDirectory() && (! IsDirectory() ) )
00718     {
00719         char *leafname = GetLeafName();
00720         nsSimpleCharString destPath(inNewParentDirectory.GetCString());
00721         destPath += "\\";
00722         destPath += leafname;
00723         nsCRT::free(leafname);
00724 
00725         if (DosMove(GetCString(), destPath) == NO_ERROR)
00726         {
00727             *this = inNewParentDirectory + GetLeafName(); 
00728             return NS_OK;
00729         }
00730         
00731     }
00732     return NS_FILE_FAILURE;
00733 } // nsFileSpec::MoveToDir
00734 
00735 //----------------------------------------------------------------------------------------
00736 nsresult nsFileSpec::Execute(const char* inArgs ) const
00737 //----------------------------------------------------------------------------------------
00738 {    
00739     if (!IsDirectory())
00740     {
00741 #ifdef XP_OS2
00742         nsresult result = NS_FILE_FAILURE;
00743     
00744         if (!mPath.IsEmpty())
00745         {
00746             nsSimpleCharString fileNameWithArgs = mPath + " " + inArgs;   
00747             result = NS_FILE_RESULT(system(fileNameWithArgs));
00748         } 
00749         return result;
00750 #else
00751         nsSimpleCharString fileNameWithArgs = "\"";
00752         fileNameWithArgs += mPath + "\" " + inArgs;
00753         int execResult = WinExec( fileNameWithArgs, SW_NORMAL );     
00754         if (execResult > 31)
00755             return NS_OK;
00756 #endif
00757     }
00758     return NS_FILE_FAILURE;
00759 } // nsFileSpec::Execute
00760 
00761 
00762 //----------------------------------------------------------------------------------------
00763 PRInt64 nsFileSpec::GetDiskSpaceAvailable() const
00764 //----------------------------------------------------------------------------------------
00765 {
00766     PRInt64 nBytes = 0;
00767     ULONG ulDriveNo = toupper(mPath[0]) + 1 - 'A';
00768     FSALLOCATE fsAllocate;
00769     APIRET rc = DosQueryFSInfo(ulDriveNo,
00770                                FSIL_ALLOC,
00771                                &fsAllocate,
00772                                sizeof(fsAllocate));
00773 
00774     if (rc == NO_ERROR) {
00775        nBytes = fsAllocate.cUnitAvail;
00776        nBytes *= fsAllocate.cSectorUnit;
00777        nBytes *= fsAllocate.cbSector;
00778     }
00779 
00780     return nBytes;
00781 }
00782 
00783 
00784 
00785 //========================================================================================
00786 //                                                      nsDirectoryIterator
00787 //========================================================================================
00788 
00789 //----------------------------------------------------------------------------------------
00790 nsDirectoryIterator::nsDirectoryIterator(const nsFileSpec& inDirectory, PRBool resolveSymlink)
00791 //----------------------------------------------------------------------------------------
00792        : mCurrent(inDirectory)
00793        , mDir(nsnull)
00794     , mStarting(inDirectory)
00795        , mExists(PR_FALSE)
00796     , mResoveSymLinks(resolveSymlink)
00797 {
00798     mDir = PR_OpenDir(inDirectory);
00799        mCurrent += "dummy";
00800     mStarting += "dummy";
00801     ++(*this);
00802 } // nsDirectoryIterator::nsDirectoryIterator
00803 
00804 //----------------------------------------------------------------------------------------
00805 nsDirectoryIterator::~nsDirectoryIterator()
00806 //----------------------------------------------------------------------------------------
00807 {
00808     if (mDir)
00809            PR_CloseDir(mDir);
00810 } // nsDirectoryIterator::nsDirectoryIterator
00811 
00812 //----------------------------------------------------------------------------------------
00813 nsDirectoryIterator& nsDirectoryIterator::operator ++ ()
00814 //----------------------------------------------------------------------------------------
00815 {
00816        mExists = PR_FALSE;
00817        if (!mDir)
00818               return *this;
00819     PRDirEntry* entry = PR_ReadDir(mDir, PR_SKIP_BOTH); // Ignore '.' && '..'
00820        if (entry)
00821     {
00822       mExists = PR_TRUE;
00823       mCurrent = mStarting;
00824       mCurrent.SetLeafName(entry->name);
00825       if (mResoveSymLinks)
00826       {   
00827           PRBool ignore;
00828           mCurrent.ResolveSymlink(ignore);
00829       }
00830     }
00831        return *this;
00832 } // nsDirectoryIterator::operator ++
00833 
00834 //----------------------------------------------------------------------------------------
00835 nsDirectoryIterator& nsDirectoryIterator::operator -- ()
00836 //----------------------------------------------------------------------------------------
00837 {
00838        return ++(*this); // can't do it backwards.
00839 } // nsDirectoryIterator::operator --
00840