DARWIN: Convert prefpane write ops to privhelper

Convert the prefpane logic for writing to config files to use
privhelper, so it can work with macOS 10.8+. With this commit, the
"CellServDB Editor" and "Parameter" tabs in the prefpane should now
work.

Specifically, define the privhelper task "write". Define a new variant
to TaskUtil's executePrivTask() called executePrivTaskWrite() to use the
new task type, and convert the prefpane code to use it.

Most files are straightforward, but converting writeAfsdOption() is a
little awkward due to the repeated checking of useAfsdConfVersion. Just
remove the writeAfsdOption() method and make the caller choose between
writeNewAfsdOption() and writeOldAfsdOption().

The new "write" task takes a new argument (data) to indicate what data
to write to the config file in question. Like the "backup" task, it also
takes a "filename" argument that is checked against our list of config
files.

Change-Id: Ib93da5a75a92e3507c15f9ee03eb8f7fbad7d088
Reviewed-on: https://gerrit.openafs.org/15960
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Michael Meffie <mmeffie@sinenomine.net>
Reviewed-by: Cheyenne Wills <cwills@sinenomine.net>
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
This commit is contained in:
Marcio Barbosa 2024-11-23 05:30:37 -08:00 committed by Andrew Deason
parent 75da4edd3c
commit 14777a2db4
5 changed files with 125 additions and 114 deletions

View File

@ -258,10 +258,9 @@
/*! /*!
@function writeCacheInfo @function writeCacheInfo
@abstract Write the cache info down the file @abstract Write the cache info down the file
@param filePath where to write the CacheInfo
@result return the execution error @result return the execution error
*/ */
-(int) writeCacheInfo:(NSString*)filePath; -(int) writeCacheInfo;
/*! /*!
@function readAfsdOption @function readAfsdOption
@ -292,14 +291,6 @@
@param filePath path of the new file with afs.conf file format @param filePath path of the new file with afs.conf file format
*/ */
-(int) readNewAfsdOption:(NSString*)filePath; -(int) readNewAfsdOption:(NSString*)filePath;
/*!
@function writeAfsdOption
@abstract <#(description)#>
@discussion <#(description)#>
@param <#(name) (description)#>
@result <#(description)#>
*/
-(int) writeAfsdOption:(NSString*)filePath;
/*! /*!
@function writeOldAfsdOption @function writeOldAfsdOption
@abstract Write the cache manager parameter to file @abstract Write the cache manager parameter to file
@ -307,13 +298,12 @@
@param filePath file path for file to write into @param filePath file path for file to write into
@result <#(description)#> @result <#(description)#>
*/ */
-(int) writeOldAfsdOption:(NSString*)filePath; -(int) writeOldAfsdOption;
/*! /*!
@function writeNewAfsdOption @function writeNewAfsdOption
@abstract Write the cache parameter to a file with the new format @abstract Write the cache parameter to a file with the new format
@param filePath file path where write into
*/ */
-(int) writeNewAfsdOption:(NSString*)filePath; -(int) writeNewAfsdOption;
/*! /*!
@function getAfsVersion @function getAfsVersion
@abstract Return the string representing the afs version @abstract Return the string representing the afs version

View File

@ -402,7 +402,7 @@
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
// writeCacheInfo: // writeCacheInfo:
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
-(int) writeCacheInfo:(NSString*)filePath -(int) writeCacheInfo
{ {
NSNumber *tmpNum = nil; NSNumber *tmpNum = nil;
NSMutableString *cacheInfoContent = [[NSMutableString alloc] init]; NSMutableString *cacheInfoContent = [[NSMutableString alloc] init];
@ -427,10 +427,7 @@
userInfo:nil]; userInfo:nil];
[cacheInfoContent appendString:[tmpNum stringValue]]; [cacheInfoContent appendString:[tmpNum stringValue]];
[cacheInfoContent writeToFile: [filePath stringByExpandingTildeInPath] [TaskUtil executePrivTaskWrite:@"/etc/cacheinfo" data:cacheInfoContent];
atomically: YES
encoding: NSASCIIStringEncoding
error: nil];
[cacheInfoContent release]; [cacheInfoContent release];
return noErr; return noErr;
@ -580,31 +577,10 @@
} }
// -------------------------------------------------------------------------------
// writeCacheInfo:
// -------------------------------------------------------------------------------
-(int) writeAfsdOption:(NSString*)filePath
{
int result = 0;
@try{
if(useAfsdConfVersion) {
result = [self writeNewAfsdOption:filePath];
} else {
result = [self writeOldAfsdOption:filePath];
}
}@catch(NSException *e){
@throw e;
}@finally{
}
return result;
}
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
// writeOldAfsdOption: // writeOldAfsdOption:
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
-(int) writeOldAfsdOption:(NSString*)filePath; -(int) writeOldAfsdOption
{ {
NSMutableString *oldConfFileContent = [[[NSMutableString alloc] init] autorelease]; NSMutableString *oldConfFileContent = [[[NSMutableString alloc] init] autorelease];
//add afsd param //add afsd param
@ -614,12 +590,9 @@
[oldConfFileContent appendString:@"\n"]; [oldConfFileContent appendString:@"\n"];
//write content on file //write content on file
[oldConfFileContent writeToFile: [filePath stringByExpandingTildeInPath] [TaskUtil executePrivTaskWrite:AFSD_OLD_PREFERENCE_FILE data:oldConfFileContent];
atomically: YES
encoding: NSASCIIStringEncoding
error: nil];
return noErr; return noErr;
} }
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -629,7 +602,7 @@
// AFS_POST_INIT=afs_server_prefs // AFS_POST_INIT=afs_server_prefs
// AFS_PRE_SHUTDOWN= // AFS_PRE_SHUTDOWN=
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
-(int) writeNewAfsdOption:(NSString*)filePath -(int) writeNewAfsdOption
{ {
NSMutableString *newConfFileContent = [[[NSMutableString alloc] init] autorelease]; NSMutableString *newConfFileContent = [[[NSMutableString alloc] init] autorelease];
@ -652,10 +625,8 @@
[newConfFileContent appendString:@"\n"]; [newConfFileContent appendString:@"\n"];
//Write to file //Write to file
[newConfFileContent writeToFile: [filePath stringByExpandingTildeInPath] [TaskUtil executePrivTaskWrite:AFSD_NEW_PREFERENCE_FILE data:newConfFileContent];
atomically: YES
encoding: NSASCIIStringEncoding
error: nil];
return noErr; return noErr;
} }
@ -1108,8 +1079,6 @@
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
-(void) saveConfigurationFiles:(BOOL) makeBackup -(void) saveConfigurationFiles:(BOOL) makeBackup
{ {
NSError *err;
NSMutableString *filePath = [[NSMutableString alloc] initWithCapacity:256];
NSMutableString *cellServDBString = [[NSMutableString alloc] initWithCapacity:256]; NSMutableString *cellServDBString = [[NSMutableString alloc] initWithCapacity:256];
NSMutableString *theseCellString = [[NSMutableString alloc] initWithCapacity:256]; NSMutableString *theseCellString = [[NSMutableString alloc] initWithCapacity:256];
DBCellElement *cellElement = nil; DBCellElement *cellElement = nil;
@ -1118,14 +1087,6 @@
@try{ @try{
[self exceptionOnInvalidPath]; [self exceptionOnInvalidPath];
// ThisCell
[filePath setString: @"/tmp/ThisCell"];
[cellName writeToFile: [filePath stringByExpandingTildeInPath]
atomically:YES
encoding: NSASCIIStringEncoding
error:nil];
// CellServDB
for(int idx = 0; idx < [cellList count]; idx++){ for(int idx = 0; idx < [cellList count]; idx++){
cellElement = [cellList objectAtIndex:idx]; cellElement = [cellList objectAtIndex:idx];
[cellServDBString appendString:[cellElement description]]; [cellServDBString appendString:[cellElement description]];
@ -1135,45 +1096,18 @@
} }
} }
[filePath setString: @"/tmp/CellServDB"];
[cellServDBString writeToFile: [filePath stringByExpandingTildeInPath]
atomically:YES
encoding: NSUTF8StringEncoding
error:&err];
[filePath setString: @"/tmp/TheseCells"];
[theseCellString writeToFile: [filePath stringByExpandingTildeInPath]
atomically:YES
encoding: NSUTF8StringEncoding
error:&err];
if(makeBackup) [self backupConfigurationFiles]; if(makeBackup) [self backupConfigurationFiles];
// install ThisCell [TaskUtil executePrivTaskWrite:@"/etc/ThisCell" data:cellName];
[filePath setString: installationPath]; [TaskUtil executePrivTaskWrite:@"/etc/CellServDB" data:cellServDBString];
[filePath appendString: @"/etc/ThisCell"]; [TaskUtil executePrivTaskWrite:@"/etc/TheseCells" data:theseCellString];
[self installConfigurationFile:@"/tmp/ThisCell"
destPath:filePath];
// install CellServDB
[filePath setString: installationPath];
[filePath appendString: @"/etc/CellServDB"];
[self installConfigurationFile:@"/tmp/CellServDB"
destPath:filePath];
// install CellServDB
[filePath setString: installationPath];
[filePath appendString: @"/etc/TheseCells"];
[self installConfigurationFile:@"/tmp/TheseCells"
destPath:filePath];
} @catch (NSException *e) { } @catch (NSException *e) {
@throw e; @throw e;
}@finally { }@finally {
// dispose all variable used // dispose all variable used
if(filePath) [filePath release];
if(cellServDBString) [cellServDBString release]; if(cellServDBString) [cellServDBString release];
if(theseCellString) [theseCellString release];
} }
} }
@ -1188,12 +1122,6 @@
@try{ @try{
[self exceptionOnInvalidPath]; [self exceptionOnInvalidPath];
// cacheinfo file creation
[self writeCacheInfo:@"/tmp/cacheinfo"];
//afsd.option or afs.conf file creation
[self writeAfsdOption:useAfsdConfVersion?AFSD_TMP_NEW_PREFERENCE_FILE:AFSD_TMP_OLD_PREFERENCE_FILE];
// backup original file // backup original file
if(makeBackup) { if(makeBackup) {
//cacheinfo //cacheinfo
@ -1206,18 +1134,17 @@
[TaskUtil executePrivTaskBackup:AFSD_OLD_PREFERENCE_FILE]; [TaskUtil executePrivTaskBackup:AFSD_OLD_PREFERENCE_FILE];
} }
} }
// cacheinfo
[self writeCacheInfo];
// install cacheinfo if (useAfsdConfVersion) {
[filePath setString:installationPath]; // afs.conf
[filePath appendString: @"/etc/cacheinfo"]; [self writeNewAfsdOption];
[self installConfigurationFile:@"/tmp/cacheinfo" } else {
destPath:filePath]; // afsd.options
[self writeOldAfsdOption];
// install afsd.conf or afs.conf configuration file }
[filePath setString: installationPath];
[filePath appendString: useAfsdConfVersion?AFSD_NEW_PREFERENCE_FILE:AFSD_OLD_PREFERENCE_FILE];
[self installConfigurationFile:useAfsdConfVersion?AFSD_TMP_NEW_PREFERENCE_FILE:AFSD_TMP_OLD_PREFERENCE_FILE
destPath:filePath];
} @catch (NSException *e) { } @catch (NSException *e) {
@throw e; @throw e;

View File

@ -17,7 +17,8 @@
+(NSString*) searchExecutablePath:(NSString*)unixCommand; +(NSString*) searchExecutablePath:(NSString*)unixCommand;
+(NSString*) executeTaskSearchingPath:(NSString*)unixCommand args:(NSArray*)args; +(NSString*) executeTaskSearchingPath:(NSString*)unixCommand args:(NSArray*)args;
+(NSString*) executeTask:(NSString*) taskName arguments:(NSArray *)args; +(NSString*) executeTask:(NSString*) taskName arguments:(NSArray *)args;
+(int) executePrivTask:(const char *)task filename:(char *)filename; +(int) executePrivTask:(const char *)task filename:(char *)filename data:(char *)data;
+(int) executePrivTask:(const char *)task; +(int) executePrivTask:(const char *)task;
+(int) executePrivTaskBackup:(NSString *)filename; +(int) executePrivTaskBackup:(NSString *)filename;
+(int) executePrivTaskWrite:(NSString *)filename data:(NSString *)data;
@end @end

View File

@ -85,8 +85,11 @@
* *
* @param[in] task The name of the task to perform (e.g. "startup_enable"). * @param[in] task The name of the task to perform (e.g. "startup_enable").
* See privhelper.c:ProcessRequest for what tasks we define. * See privhelper.c:ProcessRequest for what tasks we define.
* @param[in] filename Used for the "backup" task. Don't specify this with * @param[in] filename Used for the "backup"/"write" tasks. Don't specify this with
* executePrivTask; use executePrivTaskBackup instead. * executePrivTask; use executePrivTaskBackup or
* executePrivTaskWrite instead.
* @param[in] data Used for the "write" task. Don't specify this with
* executePrivTask; use executePrivTaskWrite instead.
* *
* @returns Return status of the task * @returns Return status of the task
* @retval 0 success * @retval 0 success
@ -94,7 +97,7 @@
* @retval nonzero The return value of system() of a failed command for the * @retval nonzero The return value of system() of a failed command for the
* task. * task.
*/ */
+(int) executePrivTask:(const char *)task filename:(char *)filename { +(int) executePrivTask:(const char *)task filename:(char *)filename data:(char *)data {
int status = -1; int status = -1;
OSErr autherr = [[AuthUtil shared] autorize]; OSErr autherr = [[AuthUtil shared] autorize];
@ -140,6 +143,9 @@
if (filename != NULL) { if (filename != NULL) {
xpc_dictionary_set_string(msg, "filename", filename); xpc_dictionary_set_string(msg, "filename", filename);
} }
if (data != NULL) {
xpc_dictionary_set_string(msg, "data", data);
}
xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, msg); xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, msg);
if (reply == NULL) { if (reply == NULL) {
@ -166,10 +172,14 @@
} }
+(int) executePrivTask:(const char *)task { +(int) executePrivTask:(const char *)task {
return [self executePrivTask:task filename:NULL]; return [self executePrivTask:task filename:NULL data:NULL];
} }
+(int) executePrivTaskBackup:(NSString *)filename { +(int) executePrivTaskBackup:(NSString *)filename {
return [self executePrivTask:"backup" filename:[filename UTF8String]]; return [self executePrivTask:"backup" filename:[filename UTF8String] data:NULL];
}
+(int) executePrivTaskWrite:(NSString *)filename data:(NSString *)data {
return [self executePrivTask:"write" filename:[filename UTF8String] data:[data UTF8String]];
} }
@end @end

View File

@ -293,6 +293,68 @@ BackupFile(const char *filename)
return code; return code;
} }
/*
* Writes the given "data" into "filename".
*/
static int
WriteFile(const char *filename, const char *data)
{
int code;
char *path = NULL;
char *tmp_path = NULL;
FILE *fh = NULL;
path = GetFullPath("write", filename);
if (path == NULL) {
goto error;
}
code = asprintf(&tmp_path, "%s.tmp", path);
if (code < 0) {
tmp_path = NULL;
mem_error();
goto error;
}
fh = fopen(tmp_path, "w");
if (fh == NULL) {
code = errno;
syslog(LOG_WARNING, "%s: Cannot open %s for writing, errno %d",
PRIVHELPER_ID, tmp_path, code);
goto error;
}
if (fputs(data, fh) == EOF) {
syslog(LOG_ERR, "%s: Error writing to %s", PRIVHELPER_ID, tmp_path);
goto error;
}
if (fclose(fh) == EOF) {
syslog(LOG_ERR, "%s: Error closing %s", PRIVHELPER_ID, tmp_path);
goto error;
}
fh = NULL;
code = RunCommand(1, "/usr/sbin/chown", "root:wheel", tmp_path, NULL);
if (code != 0) {
goto done;
}
code = RunCommand(1, "/bin/mv", "-f", tmp_path, path);
done:
free(path);
free(tmp_path);
if (fh != NULL) {
fclose(fh);
}
return code;
error:
code = -1;
goto done;
}
/** /**
* Run the requested privileged task. * Run the requested privileged task.
* *
@ -314,6 +376,9 @@ BackupFile(const char *filename)
* - backup: Make a backup copy of the configuration file named in the argument * - backup: Make a backup copy of the configuration file named in the argument
* "filename". This copies file "X" to "X.afscommander_bk". * "filename". This copies file "X" to "X.afscommander_bk".
* *
* - write: Write data to a given file. The filename is given in the argument
* "filename"; the data to write is in the argument "data".
*
* @param[in] task The name of the requested task. * @param[in] task The name of the requested task.
* @param[in] event The XPC dictionary containing other task-specific * @param[in] event The XPC dictionary containing other task-specific
* arguments. * arguments.
@ -349,6 +414,24 @@ ProcessRequest(const char *task, xpc_object_t event)
return -1; return -1;
} }
return BackupFile(filename); return BackupFile(filename);
} else if (strcmp(task, "write") == 0) {
const char *filename;
const char *data;
filename = xpc_dictionary_get_string(event, "filename");
if (filename == NULL) {
syslog(LOG_WARNING, "%s: Task 'write' missing filename", PRIVHELPER_ID);
return -1;
}
data = xpc_dictionary_get_string(event, "data");
if (data == NULL) {
syslog(LOG_WARNING, "%s: Task 'write' missing data", PRIVHELPER_ID);
return -1;
}
return WriteFile(filename, data);
} }
syslog(LOG_WARNING, "%s: Received unknown task '%s'", PRIVHELPER_ID, task); syslog(LOG_WARNING, "%s: Received unknown task '%s'", PRIVHELPER_ID, task);