'How to check if file created using `open` is newly created?

When opening a file with O_CREAT set, the file in question will be created if it does not already exist. I want special action to be taken only if the file is newly created. Is there a reliable way to check if this the case?

Currently I first attempt to open the file without O_CREAT and O_EXCL. If this fails, I then attempt to open with both of these set, and on success perform the special action. However, this is not atomic and fails if the file comes into existence between the two open attempts.



Solution 1:[1]

You can do something like this.

int open_or_create(char const* path, int flags, bool* was_created) {
    int fd;
    while (true) {
        // Try to open existing file.
        fd = open(path, flags & ~(O_CREAT | O_EXCL));
        // If this succeeds, of fails for any reason other than that
        // it doesn't exist, return.
        if (fd != -1 || errno != ENOENT) {
            if (fd != -1) {
                *was_created = false;
            }
            return fd;
        }
        // Otherwise, it failed because the file doesn't exist.
        // Try to create it.
        fd = open(path, flags | O_CREAT | O_EXCL);
        // If this succeeds or fails for any reason other than that
        // the file already exists, return.
        if (fd != -1 || errno != EEXIST) {
            if (fd != -1) {
                *was_created = true;
            }
            return fd;
        }
        // Otherwise, it failed because the file already exists. Retry.
    }
}

The two cases can be freely swapped if it's more likely that the file doesn't exist than that it already exists.

There is a theoretical failure mode where another process repeatedly creates and deletes the file just before we try create it and just before we try to open it respectively. In practice this is extremely unlikely to be an issue.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1