OSX AFSBackgrounder fix minor bug
[openafs.git] / src / platform / DARWIN / AFSPreference / PListManager.m
1 //
2 //  PListManager.m
3 //  OpenAFS
4 //
5 //  Created by Claudio Bisegni on 25/04/08.
6 //  Copyright 2008 Infn. All rights reserved.
7 //
8
9 #import "PListManager.h"
10 #import "FileUtil.h"
11 #import "TaskUtil.h"
12
13 #define BACKGROUNDER_AGENT_NAME                                 @"AFSBackgrounder.app/Contents/MacOS/AFSBackgrounder"
14
15 @implementation PListManager
16 // -------------------------------------------------------------------------------
17 //  krb5TiketAtLoginTime:
18 // -------------------------------------------------------------------------------
19 +(void) krb5TiketAtLoginTime:(BOOL)enable{
20         NSData                                  *plistData = nil;
21         NSString                                *error = nil;
22         NSString                                *toRemove = nil;
23         NSString                                *toAdd = nil;
24         NSPropertyListFormat    format;
25         NSMutableDictionary             *plist = nil;
26         SInt32                                  osxMJVers = 0;
27         SInt32                                  osxMnVers = 0;
28         FileUtil                                *futil = nil;
29         
30         //check system 
31         if (Gestalt(gestaltSystemVersionMajor, &osxMJVers) != noErr || Gestalt(gestaltSystemVersionMinor, &osxMnVers) != noErr) @throw [NSException exceptionWithName:@"PListManager:krb5TiketAtLoginTime" 
32                                                                                                                                                                                                                                                                                                                    reason:@"Error getting system version"
33                                                                                                                                                                                                                                                                                                                  userInfo:nil];
34         //get auth plist file
35         plistData = [NSData dataWithContentsOfFile:AUTH_FILE];
36         
37         //Get plist for updating with NSPropertyListMutableContainersAndLeaves
38         plist = [NSPropertyListSerialization propertyListFromData:plistData
39                                                                                          mutabilityOption:NSPropertyListMutableContainersAndLeaves
40                                                                                                            format:&format
41                                                                                          errorDescription:&error];
42         if(!plist) {
43                 @throw [NSException exceptionWithName:@"PListManager:krb5TiketAtLoginTime" 
44                                                                            reason:error
45                                                                          userInfo:nil];
46                 
47         }
48         
49         //Get "rights" dic
50         NSMutableDictionary *rightsDic = [plist objectForKey:@"rights"];
51         
52         //Get "system.login.console" dic
53         NSMutableDictionary *loginConsoleDic = [rightsDic objectForKey:@"system.login.console"];
54         
55         //Get "mechanisms" dic
56         NSMutableArray *mechanismsArray = [loginConsoleDic objectForKey:@"mechanisms"];
57         switch(osxMnVers){
58                 case 4:
59                         if(enable){
60                                 //remove
61                                 toRemove = DELETE_IN_10_4;
62                                 toAdd = ADD_IN_PLIST;
63                         } else {
64                                 toRemove = ADD_IN_PLIST;
65                                 toAdd = DELETE_IN_10_4;
66                         }
67                         break;
68                         
69                 case 5:
70                         if(enable){
71                                 //remove
72                                 toRemove = DELETE_IN_10_5;
73                                 toAdd = ADD_IN_PLIST;
74                         } else {
75                                 toRemove = ADD_IN_PLIST;
76                                 toAdd = DELETE_IN_10_5;
77                         }
78                         
79                         break;
80         }
81         
82         //Make change
83         [mechanismsArray removeObject:toRemove];
84         [mechanismsArray addObject:toAdd];
85         //write plist
86         plistData  = [NSPropertyListSerialization dataFromPropertyList:plist
87                                                                                                                         format:NSPropertyListXMLFormat_v1_0
88                                                                                                   errorDescription:&error];
89         if(!plistData) {
90                 @throw [NSException exceptionWithName:@"PListManager:krb5TiketAtLoginTime" 
91                                                                            reason:error
92                                                                          userInfo:nil];
93                 
94         }
95         if(![plistData writeToFile:TMP_FILE atomically:NO]) {
96                 @throw [NSException exceptionWithName:@"PListManager:krb5TiketAtLoginTime" 
97                                                                            reason:@"Temp file write error"
98                                                                          userInfo:nil];
99                 
100         }
101         
102         //now we can move the file
103         futil = [[FileUtil alloc] init];
104         if([futil startAutorization] == noErr) {
105                 if(![[NSFileManager defaultManager] fileExistsAtPath:AUTH_FILE_BK]) {
106                         //bk file doesn't exist so make it
107                         [futil autorizedCopy:AUTH_FILE toPath:AUTH_FILE_BK];
108                 }
109                 // chmod on tmp file
110                 [futil autorizedChown:TMP_FILE owner:@"root" group:@"wheel"];
111                 //mov ethe file 
112                 [futil autorizedMoveFile:TMP_FILE toPath:AUTH_FILE_DIR];
113         }
114         [futil release];
115 }
116
117 // -------------------------------------------------------------------------------
118 //  checkAklogAtLoginTimeLaunchdEnable:
119 // -------------------------------------------------------------------------------
120 +(BOOL) checkKrb5AtLoginTimeLaunchdEnable {
121         BOOL result = false;
122         NSString *authFileContent = nil;
123         authFileContent = [NSString stringWithContentsOfFile:AUTH_FILE];
124         if(authFileContent) {
125                 result = [authFileContent rangeOfString:ADD_IN_PLIST].location != NSNotFound;   
126         }
127         return result;
128 }
129
130         
131 // -------------------------------------------------------------------------------
132 //  installLaunchdFile:
133 // -------------------------------------------------------------------------------
134 +(void) installBackgrounderLaunchdFile:(BOOL)install resourcePath:(NSString*) rsrcPath {
135         NSData                          *plistData = nil;
136         NSMutableDictionary *launchdDic = nil;  
137         NSMutableDictionary *keepAliveDic = nil;
138         NSString                        *error = nil;
139         NSString                        *backgrounderPath = [[rsrcPath stringByAppendingString:@"/"] stringByAppendingString:BACKGROUNDER_AGENT_NAME];
140         
141         
142         if(![[NSFileManager defaultManager] fileExistsAtPath:[HOME_LAUNCHD_AGENT_FOLDER stringByExpandingTildeInPath]]) {
143                 @throw [NSException exceptionWithName:@"PListManager:installLaunchdFile" 
144                                                                            reason:@"The folder ~/Library/LaunchAgent doesn't exist!"
145                                                                          userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] 
146                                                                                                                                                   forKey:@"agent_folder_error"]];
147         }
148         
149         if(install) {
150                 if(![[NSFileManager defaultManager] fileExistsAtPath:[BACKGROUNDER_LAUNCHD_CONTROL_FILE stringByExpandingTildeInPath]]) {
151                         launchdDic = [[[NSMutableDictionary alloc] init] autorelease];
152                         keepAliveDic = [[[NSMutableDictionary alloc] init] autorelease];
153                         
154                         [launchdDic setObject:@"it.infn.lnf.network.AFSBackgrounder" 
155                                                    forKey:@"Label"];
156                         
157                         [keepAliveDic setObject:[NSNumber numberWithBool:NO]
158                                                          forKey:@"SuccessfulExit"];
159                         
160                         [launchdDic setObject:keepAliveDic 
161                                                    forKey:@"KeepAlive"];
162                         
163                         [launchdDic setObject:@"Aqua"
164                                                    forKey:@"LimitLoadToSessionType"];
165                         
166                         [launchdDic setObject:[NSArray arrayWithObject:backgrounderPath]
167                                                    forKey:@"ProgramArguments"];
168                         
169                         [launchdDic setObject:[NSNumber numberWithBool:YES] 
170                                                    forKey:@"RunAtLoad"];
171                         
172                         plistData  = [NSPropertyListSerialization dataFromPropertyList:launchdDic
173                                                                                                                                         format:NSPropertyListXMLFormat_v1_0
174                                                                                                                   errorDescription:&error];
175                         
176                         if(!plistData) {
177                                 @throw [NSException exceptionWithName:@"PListManager:installLaunchdFile" 
178                                                                                            reason:error
179                                                                                          userInfo:nil];
180                                 
181                         }
182                         
183                         if(![plistData writeToFile:BACKGROUNDER_LAUNCHD_TMP_CONTROL_FILE atomically:NO]) {
184                                 @throw [NSException exceptionWithName:@"PListManager:installLaunchdFile" 
185                                                                                            reason:@"Temp file write error"
186                                                                                          userInfo:nil];
187                                 
188                         }
189                         
190                         //now we can move the file
191                         [TaskUtil executeTaskSearchingPath:@"mv" args:[NSArray arrayWithObjects:BACKGROUNDER_LAUNCHD_TMP_CONTROL_FILE, [BACKGROUNDER_LAUNCHD_CONTROL_FILE stringByExpandingTildeInPath], nil]];
192                 }
193         } else {
194                 // delete launchd configuration file
195                 [TaskUtil executeTaskSearchingPath:@"rm" args:[NSArray arrayWithObjects:[BACKGROUNDER_LAUNCHD_CONTROL_FILE stringByExpandingTildeInPath], nil]];
196         }
197         
198 }
199
200 // -------------------------------------------------------------------------------
201 //  checkAklogAtLoginTimeLaunchdEnable:
202 // -------------------------------------------------------------------------------
203 +(BOOL) checkLoginTimeLaunchdBackgrounder {
204         BOOL result = [[NSFileManager defaultManager] fileExistsAtPath:[BACKGROUNDER_LAUNCHD_CONTROL_FILE stringByExpandingTildeInPath]];
205         return result;
206 }
207
208 // -------------------------------------------------------------------------------
209 //  installAfsStartupLaunchdFile:
210 // -------------------------------------------------------------------------------
211 +(void) manageAfsStartupLaunchdFile:(BOOL)enable 
212                                    afsStartupScript:(NSString*)afsStartupScript 
213                                                 afsBasePath:(NSString*)afsBasePath 
214                                                    afsdPath:(NSString*)afsdPath {
215         NSData                          *plistData = nil;
216         NSMutableDictionary *launchdDic = nil;
217         NSString                        *error = nil;
218         OSErr                           status = noErr;
219         
220         
221         if(![[NSFileManager defaultManager] fileExistsAtPath:[LAUNCHD_DAEMON_FOLDER stringByExpandingTildeInPath]]) {
222                 @throw [NSException exceptionWithName:@"PListManager:installAfsStartupLaunchdFile" 
223                                                                            reason:@"The folder /Library/LaunchDaemon doesn't exist!"
224                                                                          userInfo:nil];
225         }
226         
227         status = [[AuthUtil shared] autorize];
228         if(status != noErr)@throw [NSException exceptionWithName:@"PListManager:installAfsStartupLaunchdFile" 
229                                                                                                           reason:@"Autorization Error"
230                                                                                                         userInfo:nil];
231         
232         if(enable) {
233                 //Check first if the launchd configuration file for startup is present
234                 if(![[NSFileManager defaultManager] fileExistsAtPath:[AFS_STARTUP_CONTROL_FILE stringByExpandingTildeInPath]]) {
235                         launchdDic = [[[NSMutableDictionary alloc] init] autorelease];
236                         //argDic = [[NSMutableArray alloc] init];
237                         
238                         [launchdDic setObject:@"it.infn.lnf.afsstartup" 
239                                                    forKey:@"Label"];
240                         
241                         
242                         [launchdDic setObject:[NSArray arrayWithObjects:afsStartupScript, afsBasePath, afsdPath, nil]
243                                                    forKey:@"ProgramArguments"];
244                         
245                         [launchdDic setObject:[NSNumber numberWithBool:YES] 
246                                                    forKey:@"RunAtLoad"];
247                         
248                         plistData  = [NSPropertyListSerialization dataFromPropertyList:launchdDic
249                                                                                                                                         format:NSPropertyListXMLFormat_v1_0
250                                                                                                                   errorDescription:&error];
251                         
252                         if(!plistData) {
253                                 @throw [NSException exceptionWithName:@"PListManager:installLaunchdFile" 
254                                                                                            reason:error
255                                                                                          userInfo:nil];
256                                 
257                         }
258                         
259                         if(![plistData writeToFile:AFS_STARTUP_TMP_CONTROL_FILE atomically:NO]) {
260                                 @throw [NSException exceptionWithName:@"PListManager:installLaunchdFile" 
261                                                                                            reason:@"Temp file write error"
262                                                                                          userInfo:nil];
263                                 
264                         }
265                         
266                         //now we can move the file
267                         [TaskUtil executeTaskSearchingPath:@"mv" args:[NSArray arrayWithObjects:AFS_STARTUP_TMP_CONTROL_FILE, [LAUNCHD_DAEMON_FOLDER stringByExpandingTildeInPath], nil]];
268                 }
269         }
270         
271 }
272
273 // -------------------------------------------------------------------------------
274 //  launchctlCommand:
275 // -------------------------------------------------------------------------------
276 +(void) launchctlCommand:(BOOL)enable
277                           userDomain:(BOOL)userDomain
278                                            option:(NSArray*)option 
279                                         plistName:(NSString*)plistName {
280         NSMutableArray *argument = [NSMutableArray array];
281         NSMutableString *commandPath = [NSMutableString stringWithCapacity:0];
282         NSUInteger searchDomain = userDomain?NSUserDomainMask:NSSystemDomainMask;
283         //
284         NSArray *libraryPath = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, searchDomain,  YES);
285         //set the load unload
286         [argument addObject:enable?@"load":@"unload"];
287
288         //if there are load the user custo option
289         if(option) [argument addObjectsFromArray:option];
290                 
291         //construct the path
292         [commandPath appendString:[libraryPath objectAtIndex:0]];
293         [commandPath appendFormat:@"/LaunchAgents/%@", plistName];
294         
295         [argument addObject:commandPath];
296         //exec the command
297         [TaskUtil executeTaskSearchingPath:@"launchctl"  
298                                                                   args:argument];
299 }
300
301 // -------------------------------------------------------------------------------
302 //  launchdJobState:
303 // -------------------------------------------------------------------------------
304 +(BOOL) launchdJobState:(NSString*)jobName {
305         NSMutableArray *argument = [NSMutableArray array];
306         
307         //set the load unload
308         [argument addObject:@"list"];
309         [argument addObject:jobName];
310         //exec the command
311         NSString *taskResult =[TaskUtil executeTaskSearchingPath:@"launchctl"  
312                                                                                                                 args:argument];
313         return taskResult && [taskResult rangeOfString:jobName].location != NSNotFound;
314 }
315 @end