Setting chmod

J

John

$sec=open(TEKST,">test.txt");
chmod 0600,$sec;
binmode(TEKST);
print TEKST ""hello world";
close TEKST;


Why is the test.txt not chmodded to 0600 but to 0755
 
J

Joost Diepenmaat

John said:
Why is the test.txt not chmodded to 0600 but to 0755

Because $sec is not a file name or a file handle. It's a good idea to
check if any file operation succeeded:

open(TEKST,">test.txt") or die $!;
chmod 0600,*TEKST or die $!;
binmode(TEKST);
print TEKST "hello world";
close TEKST;
 
G

Gunnar Hjalmarsson

Joost said:
Because $sec is not a file name or a file handle. It's a good idea to
check if any file operation succeeded:

open(TEKST,">test.txt") or die $!;
chmod 0600,*TEKST or die $!;

With sysopen() you can do it in one step:

sysopen TEKST, 'test.txt', O_WRONLY|O_CREAT, 0600 or die $!;
 
J

John

Joost Diepenmaat said:
Because $sec is not a file name or a file handle. It's a good idea to
check if any file operation succeeded:

open(TEKST,">test.txt") or die $!;
chmod 0600,*TEKST or die $!;
binmode(TEKST);
print TEKST "hello world";
close TEKST;

I still got different result. This time I've got 0644
 
J

Joost Diepenmaat

John said:
I still got different result. This time I've got 0644

That's strange. With that code you should only get permissions of 0600
or less (when umask is set to something other than 0).

What are the owners and permissions of text.txt and its containing
directory prior to running the command?

What operating system & perl version are you using?
 
G

Gunnar Hjalmarsson

John said:
I still got different result. This time I've got 0644

Did you check the return value from chmod() as suggested? When I run the
code as above, I got a "No such file or directory" error message. Then I
tried

chmod 0600, 'test.txt' or die $!;

which worked.

Please also see my other message in this thread.
 
J

Joost Diepenmaat

[ ... ]
Did you check the return value from chmod() as suggested? When I run
the code as above, I got a "No such file or directory" error
message.

AFAIK the code as posted above should work in systems that support
fchmod() - basically any recent Unix - and should generate a fatal error
at line 2 on systems that don't.

Whatever it does it should never give a "No such file or directory
error". At least not at line 2.
 
G

Gunnar Hjalmarsson

Joost said:
[ ... ]
Did you check the return value from chmod() as suggested? When I run
the code as above, I got a "No such file or directory" error
message.

AFAIK the code as posted above should work in systems that support
fchmod() - basically any recent Unix - and should generate a fatal error
at line 2 on systems that don't.

Whatever it does it should never give a "No such file or directory
error". At least not at line 2.

$ cat test.pl
print "$^O\n";
open(TEKST,">test.txt") or die $!;
chmod 0600,*TEKST or die $!;
$ perl test.pl
linux
No such file or directory at test.pl line 3.
$ ls -l test.txt
-rw-rw-r-- 1 gunnarh gunnarh 0 Mar 9 18:42 test.txt
$
 
J

Joost Diepenmaat

Gunnar Hjalmarsson said:
$ cat test.pl
print "$^O\n";
open(TEKST,">test.txt") or die $!;
chmod 0600,*TEKST or die $!;
$ perl test.pl
linux
No such file or directory at test.pl line 3.
$ ls -l test.txt
-rw-rw-r-- 1 gunnarh gunnarh 0 Mar 9 18:42 test.txt
$

Agh. I just checked and this code only runs as I described in perl 5.8.8
and higher. Older perls don't accept file handles as arguments to chmod.
 
B

Ben Morrow

Quoth Joost Diepenmaat said:
Because $sec is not a file name or a file handle. It's a good idea to
check if any file operation succeeded:

open(TEKST,">test.txt") or die $!;
chmod 0600,*TEKST or die $!;

Don't use bare globs unless you really have to. They're very magic, and
it's always safer to use a globref when you can:

chmod 0600, \*TEKST or die $!;

Of course, a lexical filehandle would be better again.

Ben
 
G

Gunnar Hjalmarsson

Joost said:
Agh. I just checked and this code only runs as I described in perl 5.8.8
and higher. Older perls don't accept file handles as arguments to chmod.

That explains it; I'm using v5.8.1.
 
J

John

Gunnar Hjalmarsson said:
That explains it; I'm using v5.8.1.

I am confused.
So what should the chmod line have if I have Perl 5?
Some say it should be *TEKST, others something else.
 
J

Joost Diepenmaat

John said:
I am confused.
So what should the chmod line have if I have Perl 5?
Some say it should be *TEKST, others something else.

perl 5.8 and 5.10 are also perl 5s, but if you want to be compatible
with older perls, it's probably best to use the optional PERMS argument
to sysopen instead of combining open and chmod:

use Fctnl qw(O_WRONLY);
sysopen TEXT,"myfile.txt",O_WRONLY,0600 or die $!;

or, possibly, use the umask() function to change the default permissions
and then use open().

and only use chmod() if you want to change the permissions of files
you're not otherwise writing to.

See perldoc -f umask and perldoc -f sysopen
 
J

John

Joost Diepenmaat said:
perl 5.8 and 5.10 are also perl 5s, but if you want to be compatible
with older perls, it's probably best to use the optional PERMS argument
to sysopen instead of combining open and chmod:

use Fctnl qw(O_WRONLY);
sysopen TEXT,"myfile.txt",O_WRONLY,0600 or die $!;

or, possibly, use the umask() function to change the default permissions
and then use open().

and only use chmod() if you want to change the permissions of files
you're not otherwise writing to.

See perldoc -f umask and perldoc -f sysopen


OK I finally found what really works without using external library:

$sec=open(TEKST,">test.txt");
chmod 0600,"test.txt";
binmode(TEKST);
print TEKST ""hello world";
close TEKST;

0600 everytime.
 
J

Joost Diepenmaat

John said:
OK I finally found what really works without using external library:

$sec=open(TEKST,">test.txt");
chmod 0600,"test.txt";
binmode(TEKST);
print TEKST ""hello world";
close TEKST;

0600 everytime.

Well, almost everytime: if someone else unlinks, overwrites, or moves
the file (possibly replacing it with another) between the open() and
chmod() call this won't do what you expect. Which is why using sysopen()
or umask() and open() (or using perl5.8.8+'s chmod HANDLE) is better if
you're working in a multi-tasking environment.
 
J

Joost Diepenmaat

John said:
$sec=open(TEKST,">test.txt");
chmod 0600,"test.txt";

Addendum:

You *really* should check the return values of those calls.

canonically:

open(TEXT,">test.txt") or die "Can't open test.txt for writing: $!";
chmod 0600,"test.txt" or die "Can't chmod test.txt: $!";
 
J

Joost Diepenmaat

Abigail said:
Well, if someone else unlinks, overwrites or moves the file, the program
most likely doesn't do what you expect, regardless whether this happens
before, or after the chmod. And your program doesn't magically do what
you expect under such conditions if you use sysopen.

You're right, of course. It's just one of the things to
consider. Another is that in this case, the file is supposed to be
unreadable for anyone but the user writing it, but using
chmod($filename) after an open() leaves a short time window during which
someone else could possibly open the file for reading (or maybe even
read+write), which would give them access to the contents of the file as
long as they keep the handle.

Just saying, /if/ you need to specify restrictive permissions, you
probably want to do that it reliably as possible.
 
J

Joost Diepenmaat

Abigail said:
I really, really dislike the attitude of many Perl people to respond
to question with suggestions of changing the code that have nothing
at all to do with the question; and all for hypothetical situations
which may not at all be relevant for the OP. To make matter worse,
those hypothetical are usually only revealed after someone asks the
reasons behind the suggestion.

Which is why I said that "John"'s code would work "almost everytime" and
provided examples of some situations were it wouldn't. Since the poster
indicated he's new to perl he might also be new to these kinds of
potential problems.

I do appreciate you calling me on the above post, by the way: it made me
think a bit harder about the security implications of the race
condition.
 
P

Peter J. Holzer

Well, almost everytime: if someone else unlinks, overwrites, or moves
the file (possibly replacing it with another) between the open() and
chmod() call this won't do what you expect.

If that's a problem you shouldn't use open to open the file for writing
in the first place. Another user could create a symlink named "test.txt"
and you end up overwriting a completely different file.

Use sysopen with the O_EXCL flag instead. Or, if it's a temporary file
(the most common case where this is a problem) use the File::Temp
module.

hp
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,189
Latest member
CryptoTaxSoftware

Latest Threads

Top