Fix directory creation to use low level methods which consider the presence

of an existing directory to be an error, rather than the NSFileManager methods
that consider it a success.  The logic of distributed locking requires us to
fail if a directory already exists.
This commit is contained in:
Richard Frith-Macdonald 2017-06-17 06:52:05 +01:00
parent a5a2e85423
commit ed721bf4da
4 changed files with 80 additions and 29 deletions

View file

@ -41,6 +41,14 @@
# include <fcntl.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
static NSFileManager *mgr = nil;
@ -230,37 +238,36 @@ static NSFileManager *mgr = nil;
attributesToSet = [NSMutableDictionary dictionaryWithCapacity: 1];
[attributesToSet setObject: [NSNumber numberWithUnsignedInt: 0755]
forKey: NSFilePosixPermissions];
locked = [mgr createDirectoryAtPath: _lockPath
withIntermediateDirectories: YES
attributes: attributesToSet
error: NULL];
/* We must not use the NSFileManager directory creation methods,
* since they consider the presence of an existing directory a
* success, and we need to know if we can actually create a new
* directory.
*/
#if defined(_WIN32)
{
const unichar *lpath;
lpath = [mgr fileSystemRepresentationWithPath: _lockPath];
locked = (CreateDirectoryW(lpath, 0) != FALSE) ? YES : NO;
}
#else
{
const char *lpath;
lpath = [mgr fileSystemRepresentationWithPath: _lockPath];
locked = (mkdir(lpath, 0777) == 0) ? YES : NO;
}
#endif
if (NO == locked)
{
NSLog(@"Failed to create lock directory '%@' - %@",
_lockPath, [NSError _last]);
}
else
{
BOOL dir;
/* We expect the directory creation to have failed because
* it already exists as another processes lock.
* If the directory doesn't exist, then either the other
* process has removed it's lock (and we can retry)
* or we have a severe problem!
*/
if ([mgr fileExistsAtPath: _lockPath isDirectory: &dir] == NO)
{
locked = [mgr createDirectoryAtPath: _lockPath
withIntermediateDirectories: YES
attributes: attributesToSet
error: NULL];
if (NO == locked)
{
NSLog(@"Failed to create lock directory '%@' - %@",
_lockPath, [NSError _last]);
}
}
}
if (YES == locked)
{
[mgr changeFileAttributes: attributesToSet atPath: _lockPath];
attributes = [mgr fileAttributesAtPath: _lockPath
traverseLink: YES];
if (attributes == nil)