Burak Özdemir
Burak Özdemir

Reputation: 560

open() function parameters

If you look at this code block below by taking into consideration the last parameter "0", Does write line work properly ?

filename = argv[1];
string = "Example string";
if (stat(argv[1], &buf) != 0)
{
    fd = open(filename, O_WRONLY | O_CREAT, 0);
    if (fd < 0)
    {
        perror(filename);
        exit(1);
    }
    write(fd, string, strlen(string));
    close(fd);
}
else
{
    print("%s file exists\n", filename);
}

Upvotes: 2

Views: 6421

Answers (3)

Art
Art

Reputation: 20392

Interesting question. POSIX says:

The argument following the oflag argument does not affect whether the file is open for reading, writing, or for both.

Which means that since you're handling the error return from open, if you reach the write line the behavior is well defined.

To expand a bit why this works. On most filesystems on unix-like systems, the meta-data related to a file should not affect already open file descriptors. You can for example remove a file that you have opened. This is in fact done quite commonly with temporary files, so that you don't need to remember to delete them on exit. The same applies to permissions or even ownership of the file. In fact, you can chroot while holding a file open and you can still write to it without actually being able to see it. You can even use file descriptor passing to give an open file descriptor to another process that wouldn't be allowed to open that file. This is quite commonly used for privilege separation. The permissions you had when creating a file descriptor are valid regardless of the changes to permissions later. So your question is a very interesting edge case because it asks if the filesystem permissions of the file are set before or after we create a file descriptor for it and POSIX seems to be clear on that.

I can only think of two exceptions to that right now. First is when someone forcibly remounts a filesystem to read-only in that case the kernel will go through horrifying gymnastics to invalidate your file descriptor which will make all its operations fail. Second one is AFS where your permissions are actually checked when you close the file (or, when the last user of the file on your local system closes it which sends it to the server), which leads to hilarious problems where your time-limited access tokens were valid when you opened a file but aren't valid any longer when you close it. This is also why close returns errors (but that's another rant).

This is why I mentioned error handling above. Even though POSIX says that it should not have an effect, I could see AFS or certain other file systems refusing to open such a file.

Upvotes: 2

DevSolar
DevSolar

Reputation: 70263

From the manpage:

mode specifies the permissions to use in case a new file is created. This argument must be supplied when O_CREAT is specified in flags; if O_CREAT is not specified, then mode is ignored. The effective permissions are modified by the process's umask in the usual way: The permissions of the created file are (mode & ~umask). Note that this mode applies only to future accesses of the newly created file; the open() call that creates a read-only file may well return a read/write file descriptor.

The following symbolic constants are provided for mode:

S_IRWXU  00700 user (file owner) has read, write and execute permission
S_IRUSR  00400 user has read permission
S_IWUSR  00200 user has write permission
S_IXUSR  00100 user has execute permission
S_IRWXG  00070 group has read, write and execute permission
S_IRGRP  00040 group has read permission
S_IWGRP  00020 group has write permission
S_IXGRP  00010 group has execute permission
S_IRWXO  00007 others have read, write and execute permission
S_IROTH  00004 others have read permission
S_IWOTH  00002 others have write permission
S_IXOTH  00001 others have execute permission

So, specifying a mode of zero, you will create a file with the permissions of 0 & ~umask, i.e. a file without any permissions.

What exactly the filesystem makes of this is not in the domain of the open() or write() functions.

Upvotes: 2

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53006

It is valid,

This is from open(2) Linux manual pages

The mode argument specifies the file mode bits be applied when a new file is created. This argument must be supplied when O_CREAT or O_TMPFILE is specified in flags; if neither O_CREAT nor O_TMPFILE is specified, then mode is ignored. The effective mode is modified by the process's umask in the usual way: in the absence of a default ACL, the mode of the created file is (mode & ~umask). Note that this mode applies only to future accesses of the newly created file; the open() call that creates a read-only file may well return a read/write file descriptor.

In theory then, your access to the file will be valid until you call close() as I understand the part I highlighted in the above excerpt.

Upvotes: 2

Related Questions