【发布时间】:2020-06-10 11:21:24
【问题描述】:
我想以原子方式更改文件的某些属性。 (背景:这是针对用户空间 NFS 实现,其中 SETATTR 调用在文件上设置多个属性)。
我未能解决的问题是以原子方式进行更新。即,stat()s 或rename()s 文件的不同进程不应看到部分更新的属性。
不同的简化(即没有错误检查和符号链接处理)方法及其缺点是:
-
使用传统函数:
int setattr(char *path, attributes attrs) { lchown(path, attr.owner, attr.group); chmod(path, attr.mode) utime(path, ...) return 0 }这不是原子的(并且无法在符号链接上正常工作)。
-
使用
fchown()等人。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; }这有点原子,但如果文件的模式不允许打开,或者文件是符号链接(在这种情况下应该修改符号链接的属性而不是目标的属性),则会失败。将
O_PATH添加到open()调用在这里也无济于事,因为fchown()和fchmod()然后会失败。 -
使用
fchownat()等人。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; }这看起来最有希望,但这又不是原子的。
我是否遗漏了什么或者没有一种方法可以满足我的需求?
【问题讨论】:
-
O_WRONLY不会清除文件的内容吗? -
@MarcoBonelli 它没有。这就是
O_TRUNC的语义。
标签: c unix system-calls