forked from jerrykrinock/CategoriesObjC
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNSFileManager+SyncServFaker.m
160 lines (139 loc) · 4.62 KB
/
NSFileManager+SyncServFaker.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#import "NSFileManager+SyncServFaker.h"
#include <unistd.h>
@implementation NSFileManager (SyncServFaker)
- (NSString*)syncServicesLockPathForPath:(NSString*)path {
return [[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"lock"] ;
}
- (NSString*)syncServicesDetailsPathForPath:(NSString*)path {
return [[self syncServicesLockPathForPath:path] stringByAppendingPathComponent:@"details.plist"] ;
}
- (BOOL)syncServicesHasLockedPath:(NSString*)path {
NSString* lockPath = [self syncServicesDetailsPathForPath:path] ;
BOOL isDirectory ;
BOOL exists = [self fileExistsAtPath:lockPath
isDirectory:&isDirectory] ;
NSData* data = [NSData dataWithContentsOfFile:lockPath] ;
NSDictionary* lockDic = [NSPropertyListSerialization propertyListFromData:data
mutabilityOption:0
format:NULL
errorDescription:NULL] ;
if (!lockDic) {
// Bad lock file. Ignore it.
return NO ;
}
else {
NSNumber* lockPid = [lockDic objectForKey:@"LockFileProcessID"] ;
if (!lockPid) {
// Bad lock file. Ignore it.
return NO ;
}
int pid = [lockPid intValue] ;
struct ProcessSerialNumber psn = {0, 0};
GetProcessForPID (pid, &psn) ;
if ((psn.highLongOfPSN == 0) && (psn.lowLongOfPSN == 0)){
NSLog(@"Ignoring lock file set by terminated process with pid %d", pid) ;
NSError* error = nil ;
BOOL ok = [self removeItemAtPath:lockPath
error:&error] ;
if (ok) {
NSLog(@"and removed lock file") ;
}
else {
NSLog(@"but could not remove lock file because %@", error) ;
}
return NO ;
}
NSDate* lockDate = [lockDic objectForKey:@"LockFileDate"] ;
if (!lockDate) {
// Bad lock file. Ignore it.
return NO ;
}
NSTimeInterval timeSinceLock = -[lockDate timeIntervalSinceNow] ;
if (timeSinceLock > 60.0) {
NSLog(@"Ignoring lock file %@ since it has been locked for %f seconds, too long!", lockPath, timeSinceLock) ;
return NO ;
}
}
return (exists && isDirectory) ;
}
- (BOOL)blockUntilSafeToWritePath:(NSString*)path
timeout:(NSTimeInterval)timeout {
NSDate* startDate = [NSDate date] ;
while (YES) {
BOOL ok = ![self syncServicesHasLockedPath:path] ;
if (ok) {
return YES ;
}
else if ([startDate timeIntervalSinceNow] < -timeout) {
return NO ;
}
usleep(500000) ;
}
}
- (BOOL)acquireSyncServicesLockPath:(NSString*)path
timeout:(NSTimeInterval)timeout {
if (![self blockUntilSafeToWritePath:path
timeout:timeout]) {
return NO ;
}
NSDictionary* lockDic = [NSDictionary dictionaryWithObjectsAndKeys:
[NSDate date], @"LockFileDate",
@"localhost", @"LockFileHostname",
[NSNumber numberWithInt:[[NSProcessInfo processInfo] processIdentifier]], @"LockFileProcessID",
[[[[NSProcessInfo processInfo] arguments] objectAtIndex:0] lastPathComponent], @"LockFileProcessName",
NSFullUserName(), @"LockFileUsername",
nil] ;
NSString* lockPath = [self syncServicesLockPathForPath:path] ;
NSError* error = nil ;
/*
If you are developing with the 10.5 SDK, MAC_OS_X_VERSION_MAX_ALLOWED = 1050, MAC_OS_X_VERSION_10_5 = 1050 and the following #if will be true.
If you are developing with the 10.6 SDK, MAC_OS_X_VERSION_MAX_ALLOWED = 1060, MAC_OS_X_VERSION_10_5 = 1050 and the following #if will be false.
*/
#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
[self createDirectoryAtPath:lockPath
attributes:nil] ;
#else
[self createDirectoryAtPath:lockPath
withIntermediateDirectories:YES
attributes:nil
error:&error] ;
#endif
if (error) {
NSLog(@"Internal Error 248-0938 %@", error) ;
}
NSString* detailsPath = [self syncServicesDetailsPathForPath:path] ;
NSData* data = [NSPropertyListSerialization dataFromPropertyList:lockDic
format:NSPropertyListXMLFormat_v1_0
errorDescription:NULL] ;
[data writeToFile:detailsPath
atomically:YES] ;
return YES ;
}
- (void)relinquishSyncServicesLockPath:(NSString*)path {
NSString* removePath ;
removePath = [self syncServicesDetailsPathForPath:path] ;
#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
[self removeFileAtPath:removePath
handler:nil] ;
#else
NSError* error = nil ;
[self removeItemAtPath:removePath
error:&error] ;
if (error) {
NSLog(@"Internal Error 345-9678 %@", error) ;
}
error = nil ;
#endif
removePath = [self syncServicesLockPathForPath:path] ;
#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
[self removeFileAtPath:removePath
handler:nil] ;
#else
[self removeItemAtPath:removePath
error:&error] ;
if (error) {
NSLog(@"Internal Error 194-8497 %@", error) ;
}
#endif
}
@end