Reputation: 97
I have a read-only file that I can write to If I answer ok to a prompt that confirms that I want to write. I accept the prompt manually.
Can I do the same using my Perl script ?I try to do the following but end up getting an error " Permission denied for write"
my $directory= "a/b/c/d.sv";
open (my $sh, '>',"${directory}");
while($sh){
print"I am here" if(/#HERE/);
}
close $sh;
Can I override this error?
Upvotes: 0
Views: 816
Reputation: 132858
There's another way to go about this that avoids some timing problems.
First, completely create the file in a temporary file. This leaves the original in place until you are completely done. This also has the security benefit that you have not temporarily unprotected the file to deal with it ("race condition"). And, nothing that uses this file has the chance to get an incomplete
Once you are completely done creating the replacement, set its mode to the same as the target file. That is, the target file will never have a different mode. Once you've done that, rename the temporary file to original (which is not controlled by file permissions but directory permissions):
use File::Temp qw(tempfile);
my( $fh, $filename ) = tempfile();
print { $fh } "Hello";
close $fh;
my $target_file = $ARGV[0];
my $mode = (stat($target_file))[2];
chmod $mode, $filename;
rename $filename => $target_file;
Here's a small shell script to demonstrate that:
TARGET_FILE=sv.txt
rm -f ${TARGET_FILE}
touch ${TARGET_FILE}
chmod 0400 ${TARGET_FILE}
ls -l ${TARGET_FILE}
perl replace.pl ${TARGET_FILE};
ls -l ${TARGET_FILE}
It's output:
$ ./sv.sh
-r-------- 1 brian staff 0 Mar 31 04:14 sv.txt
-r-------- 1 brian staff 5 Mar 31 04:14 sv.txt
Upvotes: 3
Reputation: 1520
This is the short version of how to write to readonly files, for the full answer to your question, see Roberts answer
#read the current permissions (and other file data if you want)
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);
#temporary make the file writable
my $writablemode = 0644;
chmod($writablemode, $filename);
#do some write actions
open(my $fh, ">", $filename);
print($fh, "somedata");
close $fh;
#restore the permissions
chmod($mode, $filename);
Upvotes: 1
Reputation: 8663
You can use chmod to change the file permissions and make the file writable.
The number argument for the permissions is explained in the chmod man page, but in short you set the execute (1), write (2), and read (4) bits and you do this for owner, group, and rest of the world. So you get a 3-digit number where the first digit is for the owner, the 2nd for the group, and the last for the rest of the world. 0 removes all access, 6 is read and write access (2 for writing + 4 for reading).
my $directory= "a/b/c/d.sv";
chmod 0600, $directory;
open (my $sh, '>',"${directory}");
(BTW, $directory
is a poor name for a file.)
If you want to restore the file's permissions to what they were before, you'll first have to store them, using stat, which returns a bunch of file meta information:
my $directory= "a/b/c/d.sv";
my $oldperms = (stat($directory))[2];
printf "Old perms were %04o\n", $oldperms & 07777;
chmod 0600, $directory;
open (my $sh, '>',"${directory}");
# write the file
close $sh;
# restore old permissions
chmod $oldperms, $directory;
Upvotes: 2