RENAME - Linux手册页
Linux程序员手册 第2部分
更新日期: 2020-06-09
名称
rename, renameat, renameat2-更改文件的名称或位置
语法
#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
说明
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起)。 。
返回值
成功时,返回零。如果出错,则返回-1,并正确设置errno。
错误说明
- 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功能。
版本
namedat()已在内核2.6.16中添加到Linux;库支持已添加到版本2.4中的glibc。
namedat2()已在内核3.15中添加到Linux;库支持在glibc 2.28中添加。
遵循规范
重命名():4.3BSD,C89,C99,POSIX.1-2001,POSIX.1-2008。
namedat():POSIX.1-2008。
namedat2()是特定于Linux的。
备注
Glibc notes
在较旧的内核(其中namenameat()不可用)上,glibc包装器函数会退回到使用named()。当oldpath和newpath是相对路径名时,glibc基于/ proc / self / fd中与olddirfd和newdirfd参数相对应的符号链接构造路径名。
BUGS
在NFS文件系统上,您不能假定如果操作失败,则不会重命名该文件。如果服务器执行重命名操作然后崩溃,则重新传输的RPC将在服务器再次启动时进行处理,从而导致失败。该应用程序有望处理此问题。有关类似问题,请参见link(2)。
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。