LCOV - code coverage report
Current view: directory - xpcom/io - nsLocalFileCommon.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 129 114 88.4 %
Date: 2012-06-02 Functions: 7 7 100.0 %

       1                 : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1999
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Doug Turner <dougt@netscape.com>
      24                 :  *
      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.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : #include "nsIServiceManager.h"
      39                 : 
      40                 : #include "nsLocalFile.h" // includes platform-specific headers
      41                 : 
      42                 : #include "nsString.h"
      43                 : #include "nsCOMPtr.h"
      44                 : #include "nsReadableUtils.h"
      45                 : #include "nsPrintfCString.h"
      46                 : #include "nsCRT.h"
      47                 : #include "nsNativeCharsetUtils.h"
      48                 : #include "nsUTF8Utils.h"
      49                 : 
      50                 : #ifdef XP_WIN
      51                 : #include <string.h>
      52                 : #endif
      53                 : 
      54                 : 
      55            1419 : void NS_StartupLocalFile()
      56                 : {
      57            1419 :     nsLocalFile::GlobalInit();
      58            1419 : }
      59                 : 
      60            1419 : void NS_ShutdownLocalFile()
      61                 : {
      62            1419 :     nsLocalFile::GlobalShutdown();
      63            1419 : }
      64                 : 
      65                 : #if !defined(MOZ_WIDGET_COCOA) && !defined(XP_WIN)
      66                 : NS_IMETHODIMP
      67             940 : nsLocalFile::InitWithFile(nsILocalFile *aFile)
      68                 : {
      69             940 :     NS_ENSURE_ARG(aFile);
      70                 :     
      71            1880 :     nsCAutoString path;
      72             940 :     aFile->GetNativePath(path);
      73             940 :     if (path.IsEmpty())
      74               0 :         return NS_ERROR_INVALID_ARG;
      75             940 :     return InitWithNativePath(path); 
      76                 : }
      77                 : #endif
      78                 : 
      79                 : #define kMaxFilenameLength 255
      80                 : #define kMaxExtensionLength 100
      81                 : #define kMaxSequenceNumberLength 5 // "-9999"
      82                 : // requirement: kMaxExtensionLength < kMaxFilenameLength - kMaxSequenceNumberLength
      83                 : 
      84                 : NS_IMETHODIMP
      85            1231 : nsLocalFile::CreateUnique(PRUint32 type, PRUint32 attributes)
      86                 : {
      87                 :     nsresult rv;
      88                 :     bool longName;
      89                 : 
      90                 : #ifdef XP_WIN
      91                 :     nsAutoString pathName, leafName, rootName, suffix;
      92                 :     rv = GetPath(pathName);
      93                 : #else
      94            2462 :     nsCAutoString pathName, leafName, rootName, suffix; 
      95            1231 :     rv = GetNativePath(pathName);
      96                 : #endif
      97            1231 :     if (NS_FAILED(rv))
      98               0 :         return rv;
      99                 : 
     100            1231 :     longName = (pathName.Length() + kMaxSequenceNumberLength >
     101            1231 :                 kMaxFilenameLength);
     102            1231 :     if (!longName)
     103                 :     {
     104            1228 :         rv = Create(type, attributes);
     105            1228 :         if (rv != NS_ERROR_FILE_ALREADY_EXISTS)
     106             405 :             return rv;
     107                 :     }
     108                 : 
     109                 : #ifdef XP_WIN
     110                 :     rv = GetLeafName(leafName);
     111                 :     if (NS_FAILED(rv))
     112                 :         return rv;
     113                 : 
     114                 :     const PRInt32 lastDot = leafName.RFindChar(PRUnichar('.'));
     115                 : #else
     116             826 :     rv = GetNativeLeafName(leafName);
     117             826 :     if (NS_FAILED(rv))
     118               0 :         return rv;
     119                 : 
     120             826 :     const PRInt32 lastDot = leafName.RFindChar('.');
     121                 : #endif
     122                 : 
     123             826 :     if (lastDot == kNotFound)
     124                 :     {
     125              12 :         rootName = leafName;
     126                 :     } 
     127                 :     else
     128                 :     {
     129             814 :         suffix = Substring(leafName, lastDot);      // include '.'
     130             814 :         rootName = Substring(leafName, 0, lastDot); // strip suffix and dot
     131                 :     }
     132                 : 
     133             826 :     if (longName)
     134                 :     {
     135                 :         PRInt32 maxRootLength = (kMaxFilenameLength -
     136               3 :                                  (pathName.Length() - leafName.Length()) -
     137               3 :                                  suffix.Length() - kMaxSequenceNumberLength);
     138                 : 
     139                 :         // We cannot create an item inside a directory whose name is too long.
     140                 :         // Also, ensure that at least one character remains after we truncate
     141                 :         // the root name, as we don't want to end up with an empty leaf name.
     142               3 :         if (maxRootLength < 2)
     143               2 :             return NS_ERROR_FILE_UNRECOGNIZED_PATH;
     144                 : 
     145                 : #ifdef XP_WIN
     146                 :         // ensure that we don't cut the name in mid-UTF16-character
     147                 :         rootName.SetLength(NS_IS_LOW_SURROGATE(rootName[maxRootLength]) ?
     148                 :                            maxRootLength - 1 : maxRootLength);
     149                 :         SetLeafName(rootName + suffix);
     150                 : #else
     151               1 :         if (NS_IsNativeUTF8())
     152                 :         {
     153                 :             // ensure that we don't cut the name in mid-UTF8-character
     154                 :             // (assume the name is valid UTF8 to begin with)
     155               2 :             while (UTF8traits::isInSeq(rootName[maxRootLength]))
     156               0 :                 --maxRootLength;
     157                 : 
     158                 :             // Another check to avoid ending up with an empty leaf name.
     159               1 :             if (maxRootLength == 0 && suffix.IsEmpty())
     160               0 :                 return NS_ERROR_FILE_UNRECOGNIZED_PATH;
     161                 :         }
     162                 : 
     163               1 :         rootName.SetLength(maxRootLength);
     164               1 :         SetNativeLeafName(rootName + suffix);
     165                 : #endif
     166               1 :         nsresult rv = Create(type, attributes);
     167               1 :         if (rv != NS_ERROR_FILE_ALREADY_EXISTS)
     168               1 :             return rv;
     169                 :     }
     170                 : 
     171            1549 :     for (int indx = 1; indx < 10000; indx++)
     172                 :     {
     173                 :         // start with "Picture-1.jpg" after "Picture.jpg" exists
     174                 : #ifdef XP_WIN
     175                 :         SetLeafName(rootName +
     176                 :                     NS_ConvertASCIItoUTF16(nsPrintfCString("-%d", indx)) +
     177                 :                     suffix);
     178                 : #else
     179            1549 :         SetNativeLeafName(rootName + nsPrintfCString("-%d", indx) + suffix);
     180                 : #endif
     181            1549 :         rv = Create(type, attributes);
     182            1549 :         if (NS_SUCCEEDED(rv) || rv != NS_ERROR_FILE_ALREADY_EXISTS) 
     183             823 :             return rv;
     184                 :     }
     185                 :  
     186                 :     // The disk is full, sort of
     187               0 :     return NS_ERROR_FILE_TOO_BIG;
     188                 : }
     189                 : 
     190                 : #if defined(XP_WIN) || defined(XP_OS2)
     191                 : static const PRUnichar kPathSeparatorChar       = '\\';
     192                 : #elif defined(XP_UNIX)
     193                 : static const PRUnichar kPathSeparatorChar       = '/';
     194                 : #else
     195                 : #error Need to define file path separator for your platform
     196                 : #endif
     197                 : 
     198               2 : static PRInt32 SplitPath(PRUnichar *path, PRUnichar **nodeArray, PRInt32 arrayLen)
     199                 : {
     200               2 :     if (*path == 0)
     201               0 :       return 0;
     202                 : 
     203               2 :     PRUnichar **nodePtr = nodeArray;
     204               2 :     if (*path == kPathSeparatorChar)
     205               2 :       path++;    
     206               2 :     *nodePtr++ = path;
     207                 :     
     208              66 :     for (PRUnichar *cp = path; *cp != 0; cp++) {
     209              64 :       if (*cp == kPathSeparatorChar) {
     210               5 :         *cp++ = 0;
     211               5 :         if (*cp == 0)
     212               0 :           break;
     213               5 :         if (nodePtr - nodeArray >= arrayLen)
     214               0 :           return -1;
     215               5 :         *nodePtr++ = cp;
     216                 :       }
     217                 :     }
     218               2 :     return nodePtr - nodeArray;
     219                 : }
     220                 : 
     221                 :  
     222                 : NS_IMETHODIMP
     223               1 : nsLocalFile::GetRelativeDescriptor(nsILocalFile *fromFile, nsACString& _retval)
     224                 : {
     225               1 :     NS_ENSURE_ARG_POINTER(fromFile);
     226               1 :     const PRInt32 kMaxNodesInPath = 32;
     227                 : 
     228                 :     //
     229                 :     // _retval will be UTF-8 encoded
     230                 :     // 
     231                 :         
     232                 :     nsresult rv;
     233               1 :     _retval.Truncate(0);
     234                 : 
     235               2 :     nsAutoString thisPath, fromPath;
     236                 :     PRUnichar *thisNodes[kMaxNodesInPath], *fromNodes[kMaxNodesInPath];
     237                 :     PRInt32  thisNodeCnt, fromNodeCnt, nodeIndex;
     238                 :     
     239               1 :     rv = GetPath(thisPath);
     240               1 :     if (NS_FAILED(rv))
     241               0 :         return rv;
     242               1 :     rv = fromFile->GetPath(fromPath);
     243               1 :     if (NS_FAILED(rv))
     244               0 :         return rv;
     245                 : 
     246                 :     // get raw pointer to mutable string buffer
     247               1 :     PRUnichar *thisPathPtr; thisPath.BeginWriting(thisPathPtr);
     248               1 :     PRUnichar *fromPathPtr; fromPath.BeginWriting(fromPathPtr);
     249                 :     
     250               1 :     thisNodeCnt = SplitPath(thisPathPtr, thisNodes, kMaxNodesInPath);
     251               1 :     fromNodeCnt = SplitPath(fromPathPtr, fromNodes, kMaxNodesInPath);
     252               1 :     if (thisNodeCnt < 0 || fromNodeCnt < 0)
     253               0 :       return NS_ERROR_FAILURE;
     254                 :     
     255               3 :     for (nodeIndex = 0; nodeIndex < thisNodeCnt && nodeIndex < fromNodeCnt; ++nodeIndex) {
     256                 : #ifdef XP_WIN
     257                 :       if (_wcsicmp(thisNodes[nodeIndex], fromNodes[nodeIndex]))
     258                 :         break;
     259                 : #else
     260               3 :       if (nsCRT::strcmp(thisNodes[nodeIndex], fromNodes[nodeIndex]))
     261               1 :         break;
     262                 : #endif
     263                 :     }
     264                 :     
     265               1 :     PRInt32 branchIndex = nodeIndex;
     266               2 :     for (nodeIndex = branchIndex; nodeIndex < fromNodeCnt; nodeIndex++) 
     267               1 :       _retval.AppendLiteral("../");
     268               3 :     for (nodeIndex = branchIndex; nodeIndex < thisNodeCnt; nodeIndex++) {
     269               4 :       NS_ConvertUTF16toUTF8 nodeStr(thisNodes[nodeIndex]);
     270               2 :       _retval.Append(nodeStr);
     271               2 :       if (nodeIndex + 1 < thisNodeCnt)
     272               1 :         _retval.Append('/');
     273                 :     }
     274                 :         
     275               1 :     return NS_OK;
     276                 : }
     277                 : 
     278                 : NS_IMETHODIMP
     279               1 : nsLocalFile::SetRelativeDescriptor(nsILocalFile *fromFile, const nsACString& relativeDesc)
     280                 : {
     281               2 :     NS_NAMED_LITERAL_CSTRING(kParentDirStr, "../");
     282                 :  
     283               2 :     nsCOMPtr<nsIFile> targetFile;
     284               1 :     nsresult rv = fromFile->Clone(getter_AddRefs(targetFile));
     285               1 :     if (NS_FAILED(rv))
     286               0 :         return rv;
     287                 : 
     288                 :     //
     289                 :     // relativeDesc is UTF-8 encoded
     290                 :     // 
     291                 : 
     292               1 :     nsCString::const_iterator strBegin, strEnd;
     293               1 :     relativeDesc.BeginReading(strBegin);
     294               1 :     relativeDesc.EndReading(strEnd);
     295                 :     
     296               1 :     nsCString::const_iterator nodeBegin(strBegin), nodeEnd(strEnd);
     297               1 :     nsCString::const_iterator pos(strBegin);
     298                 :     
     299               2 :     nsCOMPtr<nsIFile> parentDir;
     300               3 :     while (FindInReadable(kParentDirStr, nodeBegin, nodeEnd)) {
     301               1 :         rv = targetFile->GetParent(getter_AddRefs(parentDir));
     302               1 :         if (NS_FAILED(rv))
     303               0 :             return rv;
     304               1 :         if (!parentDir)
     305               0 :             return NS_ERROR_FILE_UNRECOGNIZED_PATH;
     306               1 :         targetFile = parentDir;
     307                 : 
     308               1 :         nodeBegin = nodeEnd;
     309               1 :         pos = nodeEnd;
     310               1 :         nodeEnd = strEnd;
     311                 :     }
     312                 : 
     313               1 :     nodeBegin = nodeEnd = pos;
     314               4 :     while (nodeEnd != strEnd) {
     315               2 :       FindCharInReadable('/', nodeEnd, strEnd);
     316               2 :       targetFile->Append(NS_ConvertUTF8toUTF16(Substring(nodeBegin, nodeEnd)));
     317               2 :       if (nodeEnd != strEnd) // If there's more left in the string, inc over the '/' nodeEnd is on.
     318               1 :         ++nodeEnd;
     319               2 :       nodeBegin = nodeEnd;
     320                 :     }
     321                 : 
     322               2 :     nsCOMPtr<nsILocalFile> targetLocalFile(do_QueryInterface(targetFile));
     323               1 :     return InitWithFile(targetLocalFile);
     324                 : }

Generated by: LCOV version 1.7