Reputation: 4462
Assuming Linux, or more generally a sufficiently POSIX compliant system, is there a ready made method of checking if opening a file with a given name would succeed? Most optimistically I am seeking an implementation of a function with the same prototype as open(2)
int test_open(const char *pathname, int flags);
which would return result according to anticipated success or failure of open(2)
system call with the same parameters, but without actually creating or opening any file. It should be suitably licensed (reusable in proprietary software project) open source.
The open(2)
manual page lists many reasons for open(2)
failing. One errno
value can decode multiple reasons, and the errno
is different between Linux and POSIX. But nevertheless roughly speaking:
errno
are most relevant: EACCESS
, EEXIST
, ENOENT
, EISDIR
, ENOTDIR
(both POSIX and Linux).ELOOP
, EMFILE
, ENFILE
, ENAMETOOLONG
, ENODEV
, ENXIO
, EOVERFLOW
, EPERM
, EROFS
, ETXTBSY
, EWOULDBLOCK
(POSIX adds EAGAIN
).ENOMEM
, EINTR
, ENOSPC
(POSIX adds EIO
, ENOSR
).(I am now unable to quickly find online POSIX manual page for open()
, I am personally referring to POSIX manual pages installed in my Linux machine - I will edit the question when I find online link.)
Background and Expectations: My application/system configuration architecture mandates that an input value need to be validated before storing it permanently. Only after the validation and storage steps are performed, is the file going to be used for writing. Accepting bad values would be huge inconvenience (also trying to actually change to use bad file path would disturb the operation). I cannot or do not want to make exception for this special case (it is just one of over a hundred of configuration values).
I would prefer to not introduce side effects for the validation by creating a file (the flags for open()
include O_CREAT
). It is obvious that the check I am seeking for cannot be implemented 100% reliably in the most general case, which is the underlying reason for my categorizing the possible error conditions into three groups. We could have a very educated guess by analyzing the directory permissions, existence of directories, and whether there is already something with the same name which hinders opening the file, and whether the file name makes sense (my group 1 conditions). (Group 2 checks for number of symbolic links, file descriptor limits, name length limit, O_NOATIME
permission, writability of the file system, and maybe EWOULDBLOCK
and POSIX EAGAIN
cases could be done but they are more cumbersome and probably less portable to do, and are expected to be less likely to happen unless evil input, which were the reasons for categorizing them less important).
P.S. I added tag c
which is my programming language now, but the language is not very relevant.
Upvotes: 0
Views: 1055
Reputation: 1
There is no fail-proof way to do that, because (as Jite commented) some other process could have changed the environment (e.g. removed the parent directory, or filled up the filesystem, exceeded the disk quota, ....) between your test_open
and the further open
or creat
syscall. Or the disk (or the media containing the filesystem, e.g. some USB stick) could have burned or have been unplugged.
The good practice is to check the result of open
and use errno
when it has failed.
You could use access
to check a few things before. But since there is no fail-proof way, why bother?
You might validate the directory part of your file path using the realpath(3) function .... But even that is useless, some other process could have created or deleted the directory between your test_open
and the real open
Upvotes: 3