Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl: Testing that a file is actually writable as opposed to checking file permissions

Say I have a file /var/tmp/filename.

In Perl, I write the following snippet:

#!/usr/bin/env perl
use strict;
use warnings;

if (-W /var/tmp/filename)
{
...
}

exit;

Will the -W and -w functions (http://perldoc.perl.org/functions/-X.html) check that the file can actually be written to, or only check that the file permissions allow writing?

The reason I ask is that I am writing a script which gets a cookie from a server.

This script needs to be able to write the cookie file to the filesystem, but if the filesystem path to the cookie file is read only, the permissions on the file won't matter. So I want to test if the cookiefile is actually writable as opposed to just checking its permissions.

like image 377
Speeddymon Avatar asked Dec 25 '16 22:12

Speeddymon


2 Answers

In general, the -X operators only test the file modes, not whether the file is actually writeable. So you are going to have to test actually performing the operation, and catch any failure.

From http://perldoc.perl.org/functions/-X.html :

The interpretation of the file permission operators -r , -R , -w , -W , -x , and -X is by default based solely on the mode of the file and the uids and gids of the user. There may be other reasons you can't actually read, write, or execute the file: for example network filesystem access controls, ACLs (access control lists), read-only filesystems, and unrecognized executable formats. Note that the use of these six specific operators to verify if some operation is possible is usually a mistake, because it may be open to race conditions.

I have just verified this with a read-only loopback mount of a filesystem-in-a-file on my test system (Ubuntu 16.04) and the -W flag does indeed incorrectly report that the file can be written to.

You could use the touch command:

$ touch /media/MountPoint/testfile
touch: cannot touch '/media/MountPoint/testfile': Read-only file system

This returns a zero-length string on success when run using backtics:

unless (length `touch $filename`) 
{
    print "Can write\n";
}
like image 64
nickcrabtree Avatar answered Oct 10 '22 01:10

nickcrabtree


If your concern is the filesystem, you can check whether it is mounted read-only. If so, its line in /proc/mounts will have ro, so open the file and grep for lines with ro and your filesystem.

This will work only on filesystems that use /proc but yours do.

Note that querying with mount is less reliable.

A sure-fire way is to attempt to write a file, and I'd use File::Temp for that.

like image 36
zdim Avatar answered Oct 10 '22 02:10

zdim