//---------------------------------------------------------------------------------------- nsresult nsFileSpec::Rename(const char* inNewName) //---------------------------------------------------------------------------------------- { NS_ASSERTION(inNewName, "Attempt to Rename with a null string"); // This function should not be used to move a file on disk. if (mPath.IsEmpty() || strchr(inNewName, '/')) return NS_FILE_FAILURE; char* oldPath = nsCRT::strdup(mPath); SetLeafName(inNewName); if (PR_Rename(oldPath, mPath) != NS_OK) { // Could not rename, set back to the original. mPath = oldPath; nsCRT::free(oldPath); return NS_FILE_FAILURE; } nsCRT::free(oldPath); return NS_OK; } // nsFileSpec::Rename
//---------------------------------------------------------------------------------------- void nsFileSpec::MakeUnique() //---------------------------------------------------------------------------------------- { if (!Exists()) return; char* leafName = GetLeafName(); if (!leafName) return; char* lastDot = strrchr(leafName, '.'); char* suffix = ""; if (lastDot) { suffix = nsCRT::strdup(lastDot); // include '.' *lastDot = '\0'; // strip suffix and dot. } const int kMaxRootLength = nsFileSpecHelpers::kMaxCoreLeafNameLength - strlen(suffix) - 1; if ((int)strlen(leafName) > (int)kMaxRootLength) leafName[kMaxRootLength] = '\0'; for (short indx = 1; indx < 1000 && Exists(); indx++) { // start with "Picture-1.jpg" after "Picture.jpg" exists char newName[nsFileSpecHelpers::kMaxFilenameLength + 1]; sprintf(newName, "%s-%d%s", leafName, indx, suffix); SetLeafName(newName); } if (*suffix) nsCRT::free(suffix); nsCRT::free(leafName); } // nsFileSpec::MakeUnique
//---------------------------------------------------------------------------------------- nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased) //---------------------------------------------------------------------------------------- { wasAliased = PR_FALSE; char resolvedPath[MAXPATHLEN]; int charCount = readlink(mPath, (char*)&resolvedPath, MAXPATHLEN); if (0 < charCount) { if (MAXPATHLEN > charCount) resolvedPath[charCount] = '\0'; wasAliased = PR_TRUE; /* if it's not an absolute path, replace the leaf with what got resolved */ if (resolvedPath[0] != '/') { SetLeafName(resolvedPath); } else { mPath = (char*)&resolvedPath; } char* canonicalPath = realpath((const char *)mPath, resolvedPath); NS_ASSERTION(canonicalPath, "realpath failed"); if (canonicalPath) { mPath = (char*)&resolvedPath; } else { return NS_ERROR_FAILURE; } } return NS_OK; } // nsFileSpec::ResolveSymlink
//---------------------------------------------------------------------------------------- void nsFileSpec::MakeUnique(const char* inSuggestedLeafName) //---------------------------------------------------------------------------------------- { if (inSuggestedLeafName && *inSuggestedLeafName) SetLeafName(inSuggestedLeafName); MakeUnique(); } // nsFileSpec::MakeUnique
//---------------------------------------------------------------------------------------- void nsFileSpec::operator += (const char* inRelativePath) //---------------------------------------------------------------------------------------- { if (!inRelativePath || mPath.IsEmpty()) return; char endChar = mPath[(int)(strlen(mPath) - 1)]; if (endChar == '/') mPath += "x"; else mPath += "/x"; SetLeafName(inRelativePath); } // nsFileSpec::operator +=
//---------------------------------------------------------------------------------------- void nsFileSpec::operator += (const char* inRelativePath) //---------------------------------------------------------------------------------------- { NS_ASSERTION(inRelativePath, "Attempt to do += with a null string"); if (!inRelativePath || mPath.IsEmpty()) return; char endChar = mPath[(int)(strlen(mPath) - 1)]; if (endChar == '/') mPath += "x"; else mPath += "/x"; SetLeafName(inRelativePath); } // nsFileSpec::operator +=
//---------------------------------------------------------------------------------------- void nsFileSpec::operator += (const char* inRelativePath) //---------------------------------------------------------------------------------------- { NS_ASSERTION(inRelativePath, "Attempt to do += with a null string"); if (!inRelativePath || mPath.IsEmpty()) return; if (mPath[mPath.Length() - 1] == '\\') mPath += "x"; else mPath += "\\x"; // If it's a (unix) relative path, make it native nsSimpleCharString dosPath = inRelativePath; nsFileSpecHelpers::UnixToNative(dosPath); SetLeafName(dosPath); } // nsFileSpec::operator +=
//---------------------------------------------------------------------------------------- nsresult nsFileSpec::ResolveSymlink(PRBool& wasAliased) //---------------------------------------------------------------------------------------- { wasAliased = PR_FALSE; char resolvedPath[MAXPATHLEN]; int charCount = readlink(mPath, (char*)&resolvedPath, MAXPATHLEN); if (0 < charCount) { if (MAXPATHLEN > charCount) resolvedPath[charCount] = '\0'; wasAliased = PR_TRUE; /* if it's not an absolute path, replace the leaf with what got resolved */ if (resolvedPath[0] != '/') { SetLeafName(resolvedPath); } else { mPath = (char*)resolvedPath; } BEntry e((const char *)mPath, true); // traverse symlink BPath p; status_t err; err = e.GetPath(&p); NS_ASSERTION(err == B_OK, "realpath failed"); const char* canonicalPath = p.Path(); if(err == B_OK) mPath = (char*)canonicalPath; else return NS_ERROR_FAILURE; } return NS_OK; } // nsFileSpec::ResolveSymlink
NS_IMETHODIMP nsLocalFile::CreateUnique(uint32_t aType, uint32_t aAttributes) { nsresult rv; bool longName; #ifdef XP_WIN nsAutoString pathName, leafName, rootName, suffix; rv = GetPath(pathName); #else nsAutoCString pathName, leafName, rootName, suffix; rv = GetNativePath(pathName); #endif if (NS_FAILED(rv)) { return rv; } longName = (pathName.Length() + kMaxSequenceNumberLength > kMaxFilenameLength); if (!longName) { rv = Create(aType, aAttributes); if (rv != NS_ERROR_FILE_ALREADY_EXISTS) { return rv; } } #ifdef XP_WIN rv = GetLeafName(leafName); if (NS_FAILED(rv)) { return rv; } const int32_t lastDot = leafName.RFindChar(char16_t('.')); #else rv = GetNativeLeafName(leafName); if (NS_FAILED(rv)) { return rv; } const int32_t lastDot = leafName.RFindChar('.'); #endif if (lastDot == kNotFound) { rootName = leafName; } else { suffix = Substring(leafName, lastDot); // include '.' rootName = Substring(leafName, 0, lastDot); // strip suffix and dot } if (longName) { int32_t maxRootLength = (kMaxFilenameLength - (pathName.Length() - leafName.Length()) - suffix.Length() - kMaxSequenceNumberLength); // We cannot create an item inside a directory whose name is too long. // Also, ensure that at least one character remains after we truncate // the root name, as we don't want to end up with an empty leaf name. if (maxRootLength < 2) { return NS_ERROR_FILE_UNRECOGNIZED_PATH; } #ifdef XP_WIN // ensure that we don't cut the name in mid-UTF16-character rootName.SetLength(NS_IS_LOW_SURROGATE(rootName[maxRootLength]) ? maxRootLength - 1 : maxRootLength); SetLeafName(rootName + suffix); #else if (NS_IsNativeUTF8()) { // ensure that we don't cut the name in mid-UTF8-character // (assume the name is valid UTF8 to begin with) while (UTF8traits::isInSeq(rootName[maxRootLength])) { --maxRootLength; } // Another check to avoid ending up with an empty leaf name. if (maxRootLength == 0 && suffix.IsEmpty()) { return NS_ERROR_FILE_UNRECOGNIZED_PATH; } } rootName.SetLength(maxRootLength); SetNativeLeafName(rootName + suffix); #endif nsresult rv = Create(aType, aAttributes); if (rv != NS_ERROR_FILE_ALREADY_EXISTS) { return rv; } } 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) { return rv; } } // The disk is full, sort of return NS_ERROR_FILE_TOO_BIG; }