Write file to etc directory in mac os x
I am trying to write file into /etc folder on Mac OS X.
[[textView string] writeToFile:@"/etc/info.txt" atomically:YES encoding:NSUnicodeStringEncoding error:&error];
It throws error that I don't have permission to write there ( naturally ), but I d开发者_运维问答on't understand how to get permission to be able to write into the System folders.
Also can somebody provide simple example?
Please help. Thank you.
The claim "you should never write to /etc/" -folder is not valid.
There certainly are many many good reasons to write to system folders - if writing enterprise software that sets up things for users so that user's don't need to do that manually. This is required by many corporations to even approve Macs as work computers in the first place. This is typically done with shell scripting or high level languages (such as Python or Ruby), but for end user usability it would be necessary that also UI apps are able to read and write changes to system folders (such as the folder owned by configuration management system).
I am writing professionally software that must write to system folders, change contents of configuration files etc. in folders which require root privileges - all the time. I have had not 100% success in doing that since MacOSX has been made too much unfriendly for this (enterprise software for corporate internal use) use case and the approach I use seems to fail to work sometimes. I ended up popping up admin password request dialog by using Apple Script object. It sucks, but worked for my main use case:
NSString *shellCommand = [[NSString alloc] initWithFormat:@"do shell script \"/bin/bash /usr/bin/nameoftheshellscriptgoeshere.sh\" with administrator privileges"];
NSAppleScript *script;
script = [[NSAppleScript alloc] initWithSource:shellCommand];
NSDictionary* errDict = NULL;
[script executeAndReturnError:&errDict];
If your installer placed nameoftheshellscriptgoeshere.sh (or whatever name you give for it) shell script to /usr/bin, you are able to do your magic in the shell script.
This approach only works if the administrative thing can be done with a shell script. There is a workaround, but is really not very beautiful: Needing to write configuration files to a system directory with Objective-C application, using this causes a really tedious roundtrip: you create a modified configuration file to a folder that is writable by the Cocoa application and then this app executes Apple Script which executes a one liner shell script that copies this temporary configuration file to its correct location in the system folder requiring root privileges. This is very unoptimal and clumsy and introduces dependency on the said shell script - in other words, the UI app will malfunction if the shell script is not installed on the system. And lots of unnecessary separated parts to maintain just for one single reason: raising privileges of Cocoa app is hard or impossible and corporate software has not apparently been a design point in designing the OSX.
Writing to /etc/ will require root level access. You will have to ask the user for their password and then run an appropriate helper tool, etc, to do the actual writing for you.
See the Authorization Services Tasks documentation.
In general, you should never write to /etc/ for any reason. That is a system owned and controlled directory. Certainly, given the unix underpinnings of the OS, there are things that can be done by doing so, but only as a means of last resort.
For anyone else who comes across this while Googling for answers:
If you just use the "sudo nano directory/file.name" command it will open the nano text editor and then you can write files to the /etc/ directory (or whichever directory you want) so what I did was:
'sudo nano /etc/krb5.conf'
which opened the nano text editor and simultaneously created the file 'krb5.conf' in the etc directory then all I needed to do was input the code and write the file. Took about 30s.
Okay, after researching quite a bit I believe I found a more/less simple method. First check out the link: Cocoa - Gaining Root Access for NSFileManager
They suggest using already made class "BLAuthentication" - which takes care of lots of authentication coding for you. Google it to download, add to the project and use in your code. Here is a example of how simple that is:
id blTmp = [BLAuthentication sharedInstance];
NSString *myCommand = [[NSString alloc] initWithString:@"/bin/cp"];
NSArray *para = [[NSArray alloc] initWithObjects:fileName, @"/etc/", nil];
[blTmp authenticate:myCommand];
if([blTmp isAuthenticated:myCommand] == true) {
NSLog(@"Authenticated");
[blTmp executeCommandSynced:myCommand withArgs:para];
} else { NSLog(@"Not Authenticated"); }
[fileName release];
[myCommand release];
[para release];
Naturally above approach doesn't exactly answers my own question, since with above example you don't directly write to "/etc". Instead first I have to write file to "/tmp" (or other directory of your choice) and then using "cp" command in unix, copy it over to "/etc" (using "BLAuthentication" for authentication).
This is the simplest to do it, that I managed to find.
*Note: This method might not work in Lion (Mac os 10.7) since "BLAuthentication" uses deprecated function "AuthorizationExecuteWithPrivileges". Also I would suggest watching WWDC 2011 where they talk about security and proper ways of accomplishing the task. However if you need to prototype and/or play around, "BLAuthentication" should do the trick.
How to create a /logs directory you can write to:
- Disable SIP (recovery mode,
csrutil disable
) - Open Recovery mode by pressing
command + R
, until u see Apple Logo - Restart
- Open a terminal
echo 'logs' | sudo tee -a /etc/synthetic.conf
- Reboot
- Or you can manually create a File /etc/synthetic.conf
- synthetic.conf
#create an empty directory named "logs" at / which may be mounted over
logs
- Then Reboot the system
- Make sure
**/etc/synthetic.conf**
has the following permissions:- root: read, write
- wheel: read
- everyone: read
精彩评论