Bug 485328: nsLocalFileUnix::GetNativeTarget() is broken for symlinks and (dangling) symlinks. r=neil, sr=bsmedberg

This commit is contained in:
Peter Annema 2009-04-07 04:38:41 -07:00
parent 633a7c9dfd
commit c2228f83ec
2 changed files with 39 additions and 60 deletions

View File

@ -1476,16 +1476,13 @@ nsLocalFile::GetNativeTarget(nsACString &_retval)
_retval.Truncate();
struct stat symStat;
lstat(mPath.get(), &symStat);
if (lstat(mPath.get(), &symStat) == -1)
return NSRESULT_FOR_ERRNO();
if (!S_ISLNK(symStat.st_mode))
return NS_ERROR_FILE_INVALID_PATH;
PRInt64 targetSize64;
if (NS_FAILED(GetFileSizeOfLink(&targetSize64)))
return NS_ERROR_FAILURE;
PRInt32 size;
LL_L2I(size, targetSize64);
PRInt32 size = (PRInt32)symStat.st_size;
char *target = (char *)nsMemory::Alloc(size + 1);
if (!target)
return NS_ERROR_OUT_OF_MEMORY;
@ -1496,14 +1493,19 @@ nsLocalFile::GetNativeTarget(nsACString &_retval)
}
target[size] = '\0';
nsresult rv;
PRBool isSymlink;
nsresult rv = NS_OK;
nsCOMPtr<nsIFile> self(this);
nsCOMPtr<nsIFile> parent;
while (NS_SUCCEEDED(rv = self->GetParent(getter_AddRefs(parent)))) {
NS_ASSERTION(parent != nsnull, "no parent?!");
PRInt32 maxLinks = 40;
while (PR_TRUE) {
if (maxLinks-- == 0) {
rv = NS_ERROR_FILE_UNRESOLVABLE_SYMLINK;
break;
}
if (target[0] != '/') {
nsCOMPtr<nsIFile> parent;
if (NS_FAILED(rv = self->GetParent(getter_AddRefs(parent))))
break;
nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(parent, &rv));
if (NS_FAILED(rv))
break;
@ -1511,45 +1513,39 @@ nsLocalFile::GetNativeTarget(nsACString &_retval)
break;
if (NS_FAILED(rv = localFile->GetNativePath(_retval)))
break;
if (NS_FAILED(rv = parent->IsSymlink(&isSymlink)))
break;
self = parent;
} else {
nsCOMPtr<nsILocalFile> localFile;
rv = NS_NewNativeLocalFile(nsDependentCString(target), PR_TRUE,
getter_AddRefs(localFile));
if (NS_FAILED(rv))
break;
if (NS_FAILED(rv = localFile->IsSymlink(&isSymlink)))
break;
_retval = target; // XXX can we avoid this buffer copy?
self = do_QueryInterface(localFile);
_retval = target;
}
if (NS_FAILED(rv) || !isSymlink)
break;
const nsPromiseFlatCString &flatRetval = PromiseFlatCString(_retval);
// strip off any and all trailing '/'
PRInt32 len = strlen(target);
while (target[len-1] == '/' && len > 1)
target[--len] = '\0';
if (lstat(flatRetval.get(), &symStat) < 0) {
rv = NSRESULT_FOR_ERRNO();
// Any failure in testing the current target we'll just interpret
// as having reached our destiny.
if (lstat(flatRetval.get(), &symStat) == -1)
break;
}
if (!S_ISLNK(symStat.st_mode)) {
rv = NS_ERROR_FILE_INVALID_PATH;
break;
}
size = symStat.st_size;
if (readlink(flatRetval.get(), target, size) < 0) {
rv = NSRESULT_FOR_ERRNO();
break;
}
target[size] = '\0';
_retval.Truncate();
// And of course we're done if it isn't a symlink.
if (!S_ISLNK(symStat.st_mode))
break;
PRInt32 newSize = (PRInt32)symStat.st_size;
if (newSize > size) {
char *newTarget = (char *)nsMemory::Realloc(target, newSize + 1);
if (!newTarget) {
rv = NS_ERROR_OUT_OF_MEMORY;
break;
}
target = newTarget;
size = newSize;
}
PRInt32 linkLen = readlink(flatRetval.get(), target, size);
if (linkLen == -1) {
rv = NSRESULT_FOR_ERRNO();
break;
}
target[linkLen] = '\0';
}
nsMemory::Free(target);

View File

@ -56,20 +56,6 @@ function makeSymLink(from, toName, relative) {
print("---");
print(from.path);
print(to.path);
if (isUnix && (from.leafName == DOES_NOT_EXIST || from.isSymlink())) {
// Bug 485328: nsLocalFileUnix::GetTarget() is broken for dangling symlinks
if (from.leafName != DOES_NOT_EXIST) {
let fromN = from.clone();
fromN.normalize();
let toN = to.clone();
toN.normalize();
do_check_eq(fromN.path, toN.path);
}
return to;
}
print(to.target);
if (isMac) {
@ -128,9 +114,6 @@ function setupTestDir(testDir, relative) {
makeSymLink(imaginary, DANGLING_LINK, relative);
if (isUnix) // Will be fixed in bug 485328
return;
try {
makeSymLink(loop, LOOP_LINK, relative);
do_check_true(false);