版本

namedat()已在内核2.6.16中添加到Linux;库支持已添加到版本2.4中的glibc。

namedat2()已在内核3.15中添加到Linux;库支持在glibc 2.28中添加。

错误说明

EACCES
对包含oldpath或newpath的目录的写许可权被拒绝,或者对oldpath或newpath的路径前缀中的目录之一的搜索许可被拒绝,或者oldpath是目录并且不允许写许可权(需要更新..条目)。 (另请参见path_resolution(7)。)
EBUSY
重命名失败是因为oldpath或newpath是某个进程正在使用的目录(可能是当前工作目录或根目录,或者因为它已打开供读取)或系统正在使用(例如,作为挂载点) ),而系统认为这是一个错误。 (请注意,在这种情况下不需要返回EBUSY - -无论如何进行重命名都没有错- -但是如果系统无法处理这种情况,则允许返回EBUSY。)
EDQUOT
用户在文件系统上的磁盘块配额已用尽。
EFAULT
oldpath或newpath指向您可访问的地址空间之外的位置。
EINVAL
新的路径名包含旧的路径前缀,或更普遍地,尝试将目录设为其自身的子目录。
EISDIR
newpath是现有目录,而oldpath不是目录。
ELOOP
解决oldpath或newpath时遇到太多符号链接。
EMLINK
oldpath已经具有最大数量的链接,或者它是一个目录,而包含newpath的目录具有最大数量的链接。
ENAMETOOLONG
oldpath或newpath太长。
ENOENT
由oldpath命名的链接不存在;或者,newpath中的目录组件不存在;或者或者,oldpath或newpath是一个空字符串。
ENOMEM
内核内存不足。
ENOSPC
包含文件的设备没有空间容纳新目录条目。
ENOTDIR
实际上,在oldpath或newpath中用作目录的组件不是目录。或者,oldpath是目录,而newpath存在,但不是目录。
ENOTEMPTYor EEXIST
newpath是一个非空目录,即包含""以外的条目。和" .."。
EPERMor EACCES
包含oldpath的目录设置了粘滞位(S_ISVTX),并且该进程的有效用户ID既不是要删除文件的用户ID,也不是包含该目录的目录的用户ID,并且该进程没有特权(Linux:没有CAP_FOWNER功能);或newpath是现有文件,并且包含该文件的目录设置了粘滞位,并且该进程的有效用户ID既不是要替换文件的用户ID,也不是包含该文件的目录的用户ID,并且该进程没有特权(Linux:不具备CAP_FOWNER功能);或包含路径名的文件系统不支持重命名所请求的类型。
EROFS
该文件位于只读文件系统上。
EXDEV
oldpath和newpath不在同一挂载的文件系统上。 (Linux允许将文件系统挂载到多个点,但是即使在两个挂载点上都挂载了相同的文件系统,rename()也无法跨不同的挂载点工作。)

对于renameat()和renameat2(),可能会发生以下其他错误:

EBADF
olddirfd或newdirfd不是有效的文件描述符。
ENOTDIR
oldpath是相对的,而olddirfd是引用目录以外的文件的文件描述符;或类似的newpath和newdirfd

对于renameat2(),可能会发生以下其他错误:

EEXIST
标志包含RENAME_NOREPLACE,并且newpath已经存在。
EINVAL
在标志中指定了无效的标志。
EINVAL
RENAME_NOREPLACE和RENAME_EXCHANGE均在标志中指定。
EINVAL
RENAME_WHITEOUT和RENAME_EXCHANGE均在标志中指定。
EINVAL
文件系统不支持标志中的标志之一。
ENOENT
标志包含RENAME_EXCHANGE,并且newpath不存在。
EPERM
在标志中指定了RENAME_WHITEOUT,但是调用者没有CAP_MKNOD功能。

遵循规范

重命名():4.3BSD,C89,C99,POSIX.1-2001,POSIX.1-2008。

namedat():POSIX.1-2008。

namedat2()是特定于Linux的。

语法

#include <stdio.h>

int rename(const char *oldpath, const char *newpath);

#include <fcntl.h>           /* Definition of AT_* constants */
#include <stdio.h>

int renameat(int olddirfd, const char *oldpath,
             int newdirfd, const char *newpath);

int renameat2(int olddirfd, const char *oldpath,
              int newdirfd, const char *newpath, unsigned int flags);

glibc的功能测试宏要求(请参阅feature_test_macros(7)):

namedat():

Since glibc 2.10:
_POSIX_C_SOURCE>= 200809L
Before glibc 2.10:
_ATFILE_SOURCE

namedat2():

_GNU_SOURCE

返回值

成功时,返回零。如果出错,则返回-1,并正确设置errno。

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/

另外参见

mv(1),重命名(1),chmod(2),link(2),symlink(2),unlink(2),path_resolution(7),symlink(7)

名称

rename, renameat, renameat2-更改文件的名称或位置

备注

Glibc notes

在较旧的内核(其中namenameat()不可用)上,glibc包装器功能会退回到使用named()。当oldpath和newpath是相对路径名时,glibc基于/ proc / self / fd中与olddirfd和newdirfd参数相对应的符号链接构造路径名。

BUGS

在NFS文件系统上,您不能假定如果操作失败,则不会重命名该文件。如果服务器执行重命名操作然后崩溃,则重新传输的RPC将在服务器再次启动时进行处理,从而导致失败。该应用程序有望处理此问题。有关类似问题,请参见link(2)。

说明

named()重命名文件,并根据需要在目录之间移动文件。到该文件的任何其他硬链接(使用link(2)创建的)均不受影响。 oldpath的打开文件描述符也不受影响。

各种限制决定了重命名操作是否成功:请参见下面的错误。

如果newpath已经存在,它将被原子替换,这样,尝试访问newpath的另一个进程将找不到它。但是,可能会有一个窗口,其中oldpath和newpath都引用要重命名的文件。

如果oldpath和newpath是引用同一文件的现有硬链接,则named()不执行任何操作,并返回成功状态。

如果存在newpath但操作由于某种原因而失败,rename()保证将newpath的实例保留在原处。

oldpath可以指定目录。在这种情况下,newpath要么不存在,要么必须指定一个空目录。

如果oldpath引用符号链接,则该链接将重命名;否则,将重新命名该链接。如果newpath引用符号链接,则该链接将被覆盖。

renameat()

除了这里描述的区别外,系统重命名()系统调用的操作与重命名()完全相同。

如果oldpath中给定的路径名​​是相对路径名,则将其相对于文件描述符olddirfd所引用的目录进行解释(而不是相对于调用进程的当前工作目录,如相对路径名的named()所做的那样) 。

如果oldpath是相对的,而olddirfd是特殊值AT_FDCWD,则将oldpath相对于调用进程的当前工作目录(如rename())进行解释。

如果oldpath是绝对路径,则将忽略olddirfd。

对newpath的解释与对oldpath的解释相同,只是相对路径名是相对于文件描述符newdirfd引用的目录进行解释的。

请参阅openat(2)以获取对namedat()的需求的解释。

renameat2()

namedat2()还有一个额外的flags参数。带有零标志参数的renameat2()调用等效于renameat()。

flags参数是由零个或多个以下标志组成的位掩码:

RENAME_EXCHANGE
以原子方式交换oldpath和newpath。这两个路径名都必须存在,但可以具有不同的类型(例如,一个可以是非空目录,另一个可以是符号链接)。
RENAME_NOREPLACE
不要覆盖重命名的newpath。如果newpath已经存在,则返回错误。
RENAME_NOREPLACE不能与RENAME_EXCHANGE一起使用。
RENAME_NOREPLACE

requires support from the underlying filesystem.
Support for various filesystems was added as follows:

*
ext4(Linux 3.15);
*
btrfs,shmem和cifs(Linux 3.17);
*
xfs(Linux 4.0);
*
Linux 4.9中增加了对许多其他文件系统的支持,包括ext2,minix,reiserfs,jfs,vfat和bpf。
RENAME_WHITEOUT(since Linux 3.18)
该操作仅对覆盖/联合文件系统实现有意义。
指定RENAME_WHITEOUT会在执行重命名的同时在重命名源处创建一个" whiteout"对象。整个操作是原子的,因此,如果重命名成功,则还将创建白电。
"中断"是在联合/覆盖文件系统构造中具有特殊含义的对象。在这些构造中,存在多个层,并且仅顶层被修改。较高层上的变白将有效地将匹配文件隐藏在较低层中,使其看起来好像文件不存在。
重命名位于较低层上的文件后,首先将其复制(如果尚未位于较高层上),然后在较高的可读写层上重命名。同时,需要对源文件进行" whiteouted"处理(以便使较低层中的源文件版本不可见)。整个操作需要原子完成。
当不是联合/覆盖的一部分时,变白显示为带有{0,0}设备编号的字符设备。 (请注意,其他联合/覆盖实现可能会采用不同的方法来存储掉电条目;特别是,BSD联合安装使用了单独的inode类型DT_WHT,在Linux可用的某些文件系统(例如CODA和XFS)支持的情况下,该类型会被忽略。内核的中断支持代码,至少从Linux 4.19开始。)
RENAME_WHITEOUT需要与创建设备节点相同的特权(即CAP_MKNOD功能)。
RENAME_WHITEOUT不能与RENAME_EXCHANGE一起使用。
RENAME_WHITEOUT需要基础文件系统的支持。提供支持的文件系统包括tmpfs(自Linux 3.18起),ext4(自Linux 3.18起),XFS(自Linux 4.1起),f2fs(自Linux 4.2起),btrfs(自Linux 4.7起)和ubifs(自Linux 4.9起)。 。
RENAME - Linux手册页

Linux程序员手册 第2部分
更新日期: 2020-06-09

日期:2019-08-20 17:59:15 来源:oir作者:oir