Bug 1443651: Don't return failure for access denied from createUnique() if file exists. r=Mossop
authorKris Maglione <maglione.k@gmail.com>
Tue, 06 Mar 2018 14:32:40 -0800
changeset 462431 e957efe5d14c0a7a79483b477e9a6c9a8e7ddb3f
parent 462430 686b970032b4eff9d6513bbe3c2652b75a5378d8
child 462432 eaa25a9925006447cc24717554e567d77965ac21
push id1683
push usersfraser@mozilla.com
push dateThu, 26 Apr 2018 16:43:40 +0000
treeherdermozilla-release@5af6cb21869d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMossop
bugs1443651
milestone60.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1443651: Don't return failure for access denied from createUnique() if file exists. r=Mossop There are ways for Create() to return access denied for files which already exist, particularly in the case of locked files. When it does, createUnique() should check whether the file exists before considering the attempt a failure. MozReview-Commit-ID: FyJTghk04jH
xpcom/io/nsLocalFileCommon.cpp
--- a/xpcom/io/nsLocalFileCommon.cpp
+++ b/xpcom/io/nsLocalFileCommon.cpp
@@ -56,21 +56,29 @@ nsLocalFile::CreateUnique(uint32_t aType
 #else
   nsAutoCString pathName, leafName, rootName, suffix;
   rv = GetNativePath(pathName);
 #endif
   if (NS_FAILED(rv)) {
     return rv;
   }
 
+  auto FailedBecauseExists = [&] (nsresult aRv) {
+    if (aRv == NS_ERROR_FILE_ACCESS_DENIED) {
+      bool exists;
+      return NS_SUCCEEDED(Exists(&exists)) && exists;
+    }
+    return aRv == NS_ERROR_FILE_ALREADY_EXISTS;
+  };
+
   longName = (pathName.Length() + kMaxSequenceNumberLength >
               kMaxFilenameLength);
   if (!longName) {
     rv = Create(aType, aAttributes);
-    if (rv != NS_ERROR_FILE_ALREADY_EXISTS) {
+    if (!FailedBecauseExists(rv)) {
       return rv;
     }
   }
 
 #ifdef XP_WIN
   rv = GetLeafName(leafName);
   if (NS_FAILED(rv)) {
     return rv;
@@ -123,32 +131,32 @@ nsLocalFile::CreateUnique(uint32_t aType
         return NS_ERROR_FILE_UNRECOGNIZED_PATH;
       }
     }
 
     rootName.SetLength(maxRootLength);
     SetNativeLeafName(rootName + suffix);
 #endif
     nsresult rvCreate = Create(aType, aAttributes);
-    if (rvCreate != NS_ERROR_FILE_ALREADY_EXISTS) {
+    if (!FailedBecauseExists(rvCreate)) {
       return rvCreate;
     }
   }
 
   for (int indx = 1; indx < 10000; ++indx) {
     // start with "Picture-1.jpg" after "Picture.jpg" exists
 #ifdef XP_WIN
     SetLeafName(rootName +
                 NS_ConvertASCIItoUTF16(nsPrintfCString("-%d", indx)) +
                 suffix);
 #else
     SetNativeLeafName(rootName + nsPrintfCString("-%d", indx) + suffix);
 #endif
     rv = Create(aType, aAttributes);
-    if (NS_SUCCEEDED(rv) || rv != NS_ERROR_FILE_ALREADY_EXISTS) {
+    if (NS_SUCCEEDED(rv) || !FailedBecauseExists(rv)) {
       return rv;
     }
   }
 
   // The disk is full, sort of
   return NS_ERROR_FILE_TOO_BIG;
 }