I want to atomically change some attributes of a file. (Background: This is for a userspace NFS implementation where the SETATTR call sets several attributes on a file).
The problem I fail to solve is to make the update in an atomic way. That is, a different process that stat()s or rename()s the file should not see partially updated attributes.
Different simplified (i.e. no error checking and symlink handling) approaches with their downsides are:
using traditional functions:
int setattr(char *path, attributes attrs) { lchown(path, attr.owner, attr.group); chmod(path, attr.mode) utime(path, ...) return 0 }This is not atomic (and fails to work properly on symlinks).
using
fchown()et al.int setattr(char *path, attributes attrs) { int fd = open(path, O_WRONLY); fchown(fd, attr.owner, attr.group); fchmod(fd, attr.mode); futimens(fd, ...); return 0; }This is somewhat atomic, but fails if the file's mode doesn't allow opening, or the file is a symlink (in which case the symlink's attributes should be modified instead of the target's). Adding
O_PATHto theopen()call doesn't help here either, asfchown()andfchmod()then fail.using
fchownat()et al.int setattr(char *path, attributes attrs) { int fd = open(dirname(path), O_WRONLY | O_PATH); fchownat(fd, basename(path), attr.owner, attr.group, AT_SYMLINK_NOFOLLOW); fchmodat(fd, basename(path), attr.mode, 0); utimensat(fd, basename(path), ..., AT_SYMLINK_NOFOLLOW); return 0; }This looks most promising, but again this isn't atomic.
Am I missing something or isn't there an approach that does what I want?