bugGNUstep - Bugs: bug #35671, Wrong error from -[NSFileManager...

 
 
Show feedback again

You are not allowed to post comments on this tracker with your current authentification level.

bug #35671: Wrong error from -[NSFileManager createDirectoryAtPath:...]

Submitted by:  Jens Alfke <snej>
Submitted on:  Wed 29 Feb 2012 08:07:47 PM UTC  
 
Category: NoneSeverity: 3 - Normal
Item Group: NoneStatus: None
Privacy: PublicAssigned to: None
Open/Closed: Open

Mon 29 Apr 2013 03:51:36 PM UTC, comment #1:

I don't know how precise compatibility with Mac OS X/Cocoa should be for this bug, but the behaviour proposed in the patch doesn't match it:

'Wrong error Error Domain=NSCocoaErrorDomain Code=516 "The file “foobar” couldn’t be saved in the folder “tmp” because a file with the same name already exists." UserInfo=0x7f85d940ab80 {NSFilePath=/tmp/foobar, NSUnderlyingError=0x7f85d940a9d0 "The operation couldn’t be completed. File exists"}'

but error code 516 is not EEXIST and the error is in the Cocoa error domain. The underlying error is in NSPOSIXErrorDomain and has code 17 (EEXIST). The matching Foundation error (from Foundation/FoundationErrors.h) is this:

NSFileWriteFileExistsError NS_ENUM_AVAILABLE(10_7, 5_0) = 516, // Write error (file exists)

which is what NSFileManager returns in Foundation. I think it'd be reasonable for GNUstep-base to follow that example.

Graham Lee <leeg>
Wed 29 Feb 2012 08:07:47 PM UTC, original submission:

Calling -[NSFileManager createDirectoryAtPath: withIntermediateDirectories: attributes: error:] with an already-existing directory whose path is (at least?) two levels deep, returns the wrong error code. The output NSError has code 2 (ENOENT), when it should be EEXIST. (It may be possible for other incorrect error codes to be returned too.)

STEPS TO REPRODUCE

$ mkdir /tmp/foobar

NSError* error = nil;
[[NSFIleManager defaultManager] createDirectoryAtPath: @"/tmp/foobar" withIntermediateDirectories: NO attributes: nil error: &error];
NSAssert(error.code == EEXIST, @"Wrong error %@", error);

DIAGNOSIS
The above method calls the older method -createDirectoryAtPath:attributes:, and if that fails it calls -[NSError _lastError] to generate the NSError to be returned. This assumes the relevant error code is contained in errno.

However, in the case where the directory already exists, the older method returns NO after a successful stat() call, so errno never actually gets set to EEXIST. Instead the value from the previous error (whatever that was) is left behind.

The best fix appears to be to manually set errno=EEXIST in this situation. (See patch below.)

There may be other code paths in that method that have similar issues; I haven't checked.

CONFIGURATION
URL: http://svn.gna.org/svn/gnustep/libs/base/trunk/Source
Repository Root: http://svn.gna.org/svn/gnustep
Repository UUID: 72102866-910b-0410-8b05-ffd578937521
Revision: 34837
My OS is Ubuntu 11 (current according to software update).
I'm compiling with Clang 3.1 (trunk 151546).

PATCH

Index: NSFileManager.m
===================================================================
--- NSFileManager.m (revision 34837)
+++ NSFileManager.m (working copy)
@@ -854,6 +854,7 @@
{
ASSIGN(_lastError,
@"Could not create directory - already exists");
+ errno = EEXIST;
return NO;
}
}

Jens Alfke <snej>

 

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -unavailable- added by leeg (Posted a comment)
  • -unavailable- added by snej (Submitted the item)
  •  

    Do you think this task is very important?
    If so, you can click here to add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.

     

    Please enter the title of George Orwell's famous dystopian book (it's a date):

     

     

    No Changes Have Been Made to This Item
    Show feedback again

    Back to the top


    Powered by Savane 3.1-cleanup