Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F146034008
D55539.id172803.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D55539.id172803.diff
View Options
diff --git a/include/stdio.h b/include/stdio.h
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -398,6 +398,7 @@
char *fgetln(FILE *, size_t *);
const char *fmtcheck(const char *, const char *) __format_arg(2);
int fpurge(FILE *);
+int renameat2(int, const char *, int, const char *, unsigned int);
void setbuffer(FILE *, char *, int);
int setlinebuf(FILE *);
int vasprintf(char **, const char *, __va_list)
diff --git a/lib/libsys/Makefile.sys b/lib/libsys/Makefile.sys
--- a/lib/libsys/Makefile.sys
+++ b/lib/libsys/Makefile.sys
@@ -513,7 +513,8 @@
MLINKS+=recv.2 recvfrom.2 \
recv.2 recvmmsg.2 \
recv.2 recvmsg.2
-MLINKS+=rename.2 renameat.2
+MLINKS+=rename.2 renameat.2 \
+ rename.2 renameat2.2
MLINKS+=rtprio.2 rtprio_thread.2
MLINKS+=sched_get_priority_max.2 sched_get_priority_min.2 \
sched_get_priority_max.2 sched_rr_get_interval.2
diff --git a/lib/libsys/Symbol.sys.map b/lib/libsys/Symbol.sys.map
--- a/lib/libsys/Symbol.sys.map
+++ b/lib/libsys/Symbol.sys.map
@@ -393,6 +393,7 @@
FBSD_1.9 {
pdrfork;
pdrfork_thread;
+ renameat2;
};
FBSDprivate_1.0 {
diff --git a/lib/libsys/_libsys.h b/lib/libsys/_libsys.h
--- a/lib/libsys/_libsys.h
+++ b/lib/libsys/_libsys.h
@@ -474,6 +474,7 @@
typedef int (__sys_kexec_load_t)(uint64_t, u_long, struct kexec_segment *, u_long);
typedef int (__sys_pdrfork_t)(int *, int, int);
typedef int (__sys_pdwait_t)(int, int *, int, struct __wrusage *, struct __siginfo *);
+typedef int (__sys_renameat2_t)(int, const char *, int, const char *, int);
_Noreturn void __sys__exit(int rval);
int __sys_fork(void);
@@ -883,6 +884,7 @@
int __sys_kexec_load(uint64_t entry, u_long nseg, struct kexec_segment * segments, u_long flags);
int __sys_pdrfork(int * fdp, int pdflags, int rfflags);
int __sys_pdwait(int fd, int * status, int options, struct __wrusage * wrusage, struct __siginfo * info);
+int __sys_renameat2(int oldfd, const char * old, int newfd, const char * new, int flags);
__END_DECLS
#endif /* __LIBSYS_H_ */
diff --git a/lib/libsys/rename.2 b/lib/libsys/rename.2
--- a/lib/libsys/rename.2
+++ b/lib/libsys/rename.2
@@ -39,6 +39,16 @@
.Fn rename "const char *from" "const char *to"
.Ft int
.Fn renameat "int fromfd" "const char *from" "int tofd" "const char *to"
+.In sys/fcntl.h
+.In stdio.h
+.Ft int
+.Fo renameat2
+.Fa "int fromfd"
+.Fa "const char *from"
+.Fa "int tofd"
+.Fa "const char *to"
+.Fa "unsigned int flags"
+.Fc
.Sh DESCRIPTION
The
.Fn rename
@@ -112,32 +122,28 @@
.Fa tofd
parameter, the current working directory is used in the determination
of the file for the respective path parameter.
-.\".Sh CAVEAT
-.\"The system can deadlock if a loop in the file system graph is present.
-.\"This loop takes the form of an entry in directory
-.\".Pa a ,
-.\"say
-.\".Pa a/foo ,
-.\"being a hard link to directory
-.\".Pa b ,
-.\"and an entry in
-.\"directory
-.\".Pa b ,
-.\"say
-.\".Pa b/bar ,
-.\"being a hard link
-.\"to directory
-.\".Pa a .
-.\"When such a loop exists and two separate processes attempt to
-.\"perform
-.\".Ql rename a/foo b/bar
-.\"and
-.\".Ql rename b/bar a/foo ,
-.\"respectively,
-.\"the system may deadlock attempting to lock
-.\"both directories for modification.
-.\"Hard links to directories should be
-.\"replaced by symbolic links by the system administrator.
+.Pp
+The
+.Fn renameat2
+system call takes additional
+.Fa flags
+argument.
+If
+.Fa flags
+is zero, the
+.Fn renameat2
+call operates same as
+.Fn renameat .
+Additionally, the following flags can be specified:
+.Bl -tag -width AT_RENAME_NOREPLACE
+.It Dv AT_RENAME_NOREPLACE
+If the path specified by
+.Fa tofd
+and
+.Fa to
+exists, the request fails with the error
+.Er EEXIST .
+.El
.Sh RETURN VALUES
.Rv -std rename
.Sh ERRORS
@@ -324,6 +330,18 @@
.Dv CAP_RENAMEAT_TARGET
right.
.El
+.Pp
+In addition to the errors returned by the
+.Fn renameat ,
+the
+.Fn renameat2
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EEXIST
+The path specified as the
+.Fa to
+already exists.
+.El
.Sh SEE ALSO
.Xr chflags 2 ,
.Xr open 2 ,
@@ -341,3 +359,7 @@
.Fn renameat
system call appeared in
.Fx 8.0 .
+The
+.Fn renameat2
+system call appeared in
+.Fx 16.0 .
diff --git a/lib/libsys/syscalls.map b/lib/libsys/syscalls.map
--- a/lib/libsys/syscalls.map
+++ b/lib/libsys/syscalls.map
@@ -823,4 +823,6 @@
__sys_pdrfork;
_pdwait;
__sys_pdwait;
+ _renameat2;
+ __sys_renameat2;
};
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -519,4 +519,5 @@
#define FREEBSD32_SYS_jail_remove_jd 598
#define FREEBSD32_SYS_pdrfork 600
#define FREEBSD32_SYS_freebsd32_pdwait 601
-#define FREEBSD32_SYS_MAXSYSCALL 602
+#define FREEBSD32_SYS_renameat2 602
+#define FREEBSD32_SYS_MAXSYSCALL 603
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -607,4 +607,5 @@
"#599", /* 599 = kexec_load */
"pdrfork", /* 600 = pdrfork */
"freebsd32_pdwait", /* 601 = freebsd32_pdwait */
+ "renameat2", /* 602 = renameat2 */
};
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -669,4 +669,5 @@
{ .sy_narg = 0, .sy_call = (sy_call_t *)nosys, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_ABSENT }, /* 599 = freebsd32_kexec_load */
{ .sy_narg = AS(pdrfork_args), .sy_call = (sy_call_t *)sys_pdrfork, .sy_auevent = AUE_PDRFORK, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 600 = pdrfork */
{ .sy_narg = AS(freebsd32_pdwait_args), .sy_call = (sy_call_t *)freebsd32_pdwait, .sy_auevent = AUE_PDWAIT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 601 = freebsd32_pdwait */
+ { .sy_narg = AS(renameat2_args), .sy_call = (sy_call_t *)sys_renameat2, .sy_auevent = AUE_RENAMEAT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 602 = renameat2 */
};
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
--- a/sys/compat/freebsd32/freebsd32_systrace_args.c
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -3447,6 +3447,17 @@
*n_args = 5;
break;
}
+ /* renameat2 */
+ case 602: {
+ struct renameat2_args *p = params;
+ iarg[a++] = p->oldfd; /* int */
+ uarg[a++] = (intptr_t)p->old; /* const char * */
+ iarg[a++] = p->newfd; /* int */
+ uarg[a++] = (intptr_t)p->new; /* const char * */
+ iarg[a++] = p->flags; /* int */
+ *n_args = 5;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9314,6 +9325,28 @@
break;
};
break;
+ /* renameat2 */
+ case 602:
+ switch (ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "userland const char *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "userland const char *";
+ break;
+ case 4:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11242,6 +11275,11 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* renameat2 */
+ case 602:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -811,7 +811,7 @@
{
return (kern_renameat(td, AT_FDCWD, args->from, AT_FDCWD,
- args->to, UIO_USERSPACE));
+ args->to, UIO_USERSPACE, 0));
}
#endif
@@ -833,7 +833,9 @@
linux_renameat2(struct thread *td, struct linux_renameat2_args *args)
{
int olddfd, newdfd;
+ u_int atflags;
+ atflags = 0;
if (args->flags != 0) {
if (args->flags & ~(LINUX_RENAME_EXCHANGE |
LINUX_RENAME_NOREPLACE | LINUX_RENAME_WHITEOUT))
@@ -842,6 +844,10 @@
args->flags & (LINUX_RENAME_NOREPLACE |
LINUX_RENAME_WHITEOUT))
return (EINVAL);
+ if ((args->flags & LINUX_RENAME_NOREPLACE) != 0) {
+ args->flags &= ~LINUX_RENAME_NOREPLACE;
+ atflags |= AT_RENAME_NOREPLACE;
+ }
#if 0
/*
* This spams the console on Ubuntu Focal.
@@ -849,8 +855,10 @@
* What's needed here is a general mechanism to let users know
* about missing features without hogging the system.
*/
- linux_msg(td, "renameat2 unsupported flags 0x%x",
- args->flags);
+ if (args->flags != 0) {
+ linux_msg(td, "renameat2 unsupported flags 0x%x",
+ args->flags);
+ }
#endif
return (EINVAL);
}
@@ -858,7 +866,7 @@
olddfd = (args->olddfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->olddfd;
newdfd = (args->newdfd == LINUX_AT_FDCWD) ? AT_FDCWD : args->newdfd;
return (kern_renameat(td, olddfd, args->oldname, newdfd,
- args->newname, UIO_USERSPACE));
+ args->newname, UIO_USERSPACE, atflags));
}
#ifdef LINUX_LEGACY_SYSCALLS
diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
--- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
+++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c
@@ -5527,6 +5527,11 @@
}
#endif
+ if (error == 0) {
+ if (ap->a_flags != 0)
+ error = EOPNOTSUPP;
+ }
+
if (error == 0)
error = zfs_do_rename(fdvp, &fvp, ap->a_fcnp, tdvp, &tvp,
ap->a_tcnp, ap->a_fcnp->cn_cred);
diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c
--- a/sys/fs/fuse/fuse_vnops.c
+++ b/sys/fs/fuse/fuse_vnops.c
@@ -2254,6 +2254,10 @@
err = EXTERROR(EXDEV, "Cross-device rename");
goto out;
}
+ if (ap->a_flags != 0) {
+ err = EOPNOTSUPP;
+ goto out;
+ }
cache_purge(fvp);
/*
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -49,12 +49,12 @@
* October 1992
*/
-#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/clock.h>
#include <sys/dirent.h>
+#include <sys/fcntl.h>
#include <sys/lock.h>
#include <sys/lockf.h>
#include <sys/malloc.h>
@@ -970,6 +970,11 @@
goto abortit;
}
+ if ((ap->a_flags & ~(AT_RENAME_NOREPLACE)) != 0) {
+ error = EOPNOTSUPP;
+ goto abortit;
+ }
+
/*
* If source and dest are the same, do nothing.
*/
@@ -1036,6 +1041,11 @@
vrele(tvp);
tvp = NULL;
}
+ if (error == 0 && tvp != NULL &&
+ (ap->a_flags & AT_RENAME_NOREPLACE) != 0) {
+ error = EEXIST;
+ goto unlock;
+ }
if (error == 0) {
nip = NULL;
error = deget(pmp, scn, blkoff, LK_EXCLUSIVE | LK_NOWAIT,
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -2196,6 +2196,12 @@
error = EXDEV;
goto out;
}
+
+ if (ap->a_flags != 0) {
+ error = EOPNOTSUPP;
+ goto out;
+ }
+
nmp = VFSTONFS(fvp->v_mount);
if (fvp == tvp) {
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -1715,7 +1715,7 @@
if (error == 0) {
error = VOP_RENAME(fromndp->ni_dvp, fromndp->ni_vp,
&fromndp->ni_cnd, tondp->ni_dvp, tondp->ni_vp,
- &tondp->ni_cnd);
+ &tondp->ni_cnd, 0);
lockmgr(&mp->mnt_renamelock, LK_RELEASE, 0);
vfs_rel(mp);
} else {
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -741,7 +741,8 @@
ltvp = NULL;
}
- error = VOP_RENAME(lfdvp, lfvp, ap->a_fcnp, ltdvp, ltvp, ap->a_tcnp);
+ error = VOP_RENAME(lfdvp, lfvp, ap->a_fcnp, ltdvp, ltvp, ap->a_tcnp,
+ ap->a_flags);
vrele(fdvp);
vrele(fvp);
vrele(tdvp);
diff --git a/sys/fs/p9fs/p9fs_vnops.c b/sys/fs/p9fs/p9fs_vnops.c
--- a/sys/fs/p9fs/p9fs_vnops.c
+++ b/sys/fs/p9fs/p9fs_vnops.c
@@ -2084,6 +2084,11 @@
goto out;
}
+ if (ap->a_flags != 0) {
+ error = EOPNOTSUPP;
+ goto out;
+ }
+
/* warning if you are renaming to the same name */
if (fvp == tvp)
error = 0;
diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c
--- a/sys/fs/smbfs/smbfs_vnops.c
+++ b/sys/fs/smbfs/smbfs_vnops.c
@@ -577,6 +577,11 @@
goto out;
}
+ if (ap->a_flags != 0) {
+ error = EOPNOTSUPP;
+ goto out;
+ }
+
if (tvp && vrefcnt(tvp) > 1) {
error = EBUSY;
goto out;
diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -993,6 +993,11 @@
goto out;
}
+ if ((v->a_flags & ~(AT_RENAME_NOREPLACE)) != 0) {
+ error = EOPNOTSUPP;
+ goto out;
+ }
+
/* If source and target are the same file, there is nothing to do. */
if (fvp == tvp) {
error = 0;
@@ -1013,9 +1018,14 @@
"tmpfs_rename: fdvp not locked");
ASSERT_VOP_ELOCKED(tdvp,
"tmpfs_rename: tdvp not locked");
- if (tvp != NULL)
+ if (tvp != NULL) {
ASSERT_VOP_ELOCKED(tvp,
"tmpfs_rename: tvp not locked");
+ if ((v->a_flags & ~(AT_RENAME_NOREPLACE)) != 0) {
+ error = EEXIST;
+ goto out_locked;
+ }
+ }
if (fvp == tvp) {
error = 0;
goto out_locked;
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c
--- a/sys/fs/unionfs/union_vnops.c
+++ b/sys/fs/unionfs/union_vnops.c
@@ -1413,6 +1413,11 @@
goto unionfs_rename_abort;
}
+ if (ap->a_flags != 0) {
+ error = EOPNOTSUPP;
+ goto unionfs_rename_abort;
+ }
+
/* Renaming a file to itself has no effect. */
if (fvp == tvp)
goto unionfs_rename_abort;
@@ -1581,7 +1586,7 @@
if (rfvp == rtvp)
goto unionfs_rename_abort;
- error = VOP_RENAME(rfdvp, rfvp, fcnp, rtdvp, rtvp, tcnp);
+ error = VOP_RENAME(rfdvp, rfvp, fcnp, rtdvp, rtvp, tcnp, ap->a_flags);
if (error == 0) {
if (rtvp != NULL && rtvp->v_type == VDIR)
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -668,4 +668,5 @@
{ .sy_narg = AS(kexec_load_args), .sy_call = (sy_call_t *)sys_kexec_load, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 599 = kexec_load */
{ .sy_narg = AS(pdrfork_args), .sy_call = (sy_call_t *)sys_pdrfork, .sy_auevent = AUE_PDRFORK, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 600 = pdrfork */
{ .sy_narg = AS(pdwait_args), .sy_call = (sy_call_t *)sys_pdwait, .sy_auevent = AUE_PDWAIT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 601 = pdwait */
+ { .sy_narg = AS(renameat2_args), .sy_call = (sy_call_t *)sys_renameat2, .sy_auevent = AUE_RENAMEAT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 602 = renameat2 */
};
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -607,4 +607,5 @@
"kexec_load", /* 599 = kexec_load */
"pdrfork", /* 600 = pdrfork */
"pdwait", /* 601 = pdwait */
+ "renameat2", /* 602 = renameat2 */
};
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3420,5 +3420,13 @@
_Out_opt_ _Contains_long_ptr_ struct __siginfo *info
);
}
-
+602 AUE_RENAMEAT STD|CAPENABLED {
+ int renameat2(
+ int oldfd,
+ _In_z_ const char *old,
+ int newfd,
+ _In_z_ const char *new,
+ int flags
+ );
+ }
; vim: syntax=off
diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c
--- a/sys/kern/systrace_args.c
+++ b/sys/kern/systrace_args.c
@@ -3544,6 +3544,17 @@
*n_args = 5;
break;
}
+ /* renameat2 */
+ case 602: {
+ struct renameat2_args *p = params;
+ iarg[a++] = p->oldfd; /* int */
+ uarg[a++] = (intptr_t)p->old; /* const char * */
+ iarg[a++] = p->newfd; /* int */
+ uarg[a++] = (intptr_t)p->new; /* const char * */
+ iarg[a++] = p->flags; /* int */
+ *n_args = 5;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9488,6 +9499,28 @@
break;
};
break;
+ /* renameat2 */
+ case 602:
+ switch (ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "userland const char *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ case 3:
+ p = "userland const char *";
+ break;
+ case 4:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11511,6 +11544,11 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* renameat2 */
+ case 602:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -3720,7 +3720,7 @@
{
return (kern_renameat(td, AT_FDCWD, uap->from, AT_FDCWD,
- uap->to, UIO_USERSPACE));
+ uap->to, UIO_USERSPACE, 0));
}
#ifndef _SYS_SYSPROTO_H_
@@ -3736,7 +3736,15 @@
{
return (kern_renameat(td, uap->oldfd, uap->old, uap->newfd, uap->new,
- UIO_USERSPACE));
+ UIO_USERSPACE, 0));
+}
+
+int
+sys_renameat2(struct thread *td, struct renameat2_args *uap)
+{
+
+ return (kern_renameat(td, uap->oldfd, uap->old, uap->newfd, uap->new,
+ UIO_USERSPACE, uap->flags));
}
#ifdef MAC
@@ -3766,7 +3774,7 @@
int
kern_renameat(struct thread *td, int oldfd, const char *old, int newfd,
- const char *new, enum uio_seg pathseg)
+ const char *new, enum uio_seg pathseg, u_int flags)
{
struct mount *mp, *tmp;
struct vnode *tvp, *fvp, *tdvp;
@@ -3775,6 +3783,8 @@
int error;
short irflag;
+ if ((flags & ~(AT_RENAME_NOREPLACE)) != 0)
+ return (EINVAL);
again:
tmp = mp = NULL;
bwillwrite();
@@ -3810,6 +3820,10 @@
}
tdvp = tond.ni_dvp;
tvp = tond.ni_vp;
+ if (tvp != NULL && (flags & AT_RENAME_NOREPLACE) != 0) {
+ error = EEXIST;
+ goto out;
+ }
error = vn_start_write(fvp, &mp, V_NOWAIT);
if (error != 0) {
again1:
@@ -3887,7 +3901,7 @@
out:
if (error == 0) {
error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
- tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
+ tond.ni_dvp, tond.ni_vp, &tond.ni_cnd, flags);
NDFREE_PNBUF(&fromnd);
NDFREE_PNBUF(&tond);
} else {
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -336,6 +336,7 @@
IN WILLRELE struct vnode *tdvp;
IN WILLRELE struct vnode *tvp;
IN struct componentname *tcnp;
+ IN u_int flags;
};
diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h
--- a/sys/sys/fcntl.h
+++ b/sys/sys/fcntl.h
@@ -245,6 +245,9 @@
#define AT_RESOLVE_BENEATH 0x2000 /* Do not allow name resolution
to walk out of dirfd */
#define AT_EMPTY_PATH 0x4000 /* Operate on dirfd if path is empty */
+
+#define AT_RENAME_NOREPLACE 0x0001
+#define RENAME_NOREPLACE AT_RENAME_NOREPLACE
#endif /* __BSD_VISIBLE */
/*
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
--- a/sys/sys/syscall.h
+++ b/sys/sys/syscall.h
@@ -540,4 +540,5 @@
#define SYS_kexec_load 599
#define SYS_pdrfork 600
#define SYS_pdwait 601
-#define SYS_MAXSYSCALL 602
+#define SYS_renameat2 602
+#define SYS_MAXSYSCALL 603
diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
--- a/sys/sys/syscall.mk
+++ b/sys/sys/syscall.mk
@@ -443,4 +443,5 @@
jail_remove_jd.o \
kexec_load.o \
pdrfork.o \
- pdwait.o
+ pdwait.o \
+ renameat2.o
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -305,7 +305,7 @@
int kern_recvit(struct thread *td, int s, struct msghdr *mp,
enum uio_seg fromseg, struct mbuf **controlp);
int kern_renameat(struct thread *td, int oldfd, const char *old, int newfd,
- const char *new, enum uio_seg pathseg);
+ const char *new, enum uio_seg pathseg, u_int flags);
int kern_sched_getparam(struct thread *td, struct thread *targettd,
struct sched_param *param);
int kern_sched_getscheduler(struct thread *td, struct thread *targettd,
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
--- a/sys/sys/sysproto.h
+++ b/sys/sys/sysproto.h
@@ -1925,6 +1925,13 @@
char wrusage_l_[PADL_(struct __wrusage *)]; struct __wrusage * wrusage; char wrusage_r_[PADR_(struct __wrusage *)];
char info_l_[PADL_(struct __siginfo *)]; struct __siginfo * info; char info_r_[PADR_(struct __siginfo *)];
};
+struct renameat2_args {
+ char oldfd_l_[PADL_(int)]; int oldfd; char oldfd_r_[PADR_(int)];
+ char old_l_[PADL_(const char *)]; const char * old; char old_r_[PADR_(const char *)];
+ char newfd_l_[PADL_(int)]; int newfd; char newfd_r_[PADR_(int)];
+ char new_l_[PADL_(const char *)]; const char * new; char new_r_[PADR_(const char *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
int sys__exit(struct thread *, struct _exit_args *);
int sys_fork(struct thread *, struct fork_args *);
int sys_read(struct thread *, struct read_args *);
@@ -2334,6 +2341,7 @@
int sys_kexec_load(struct thread *, struct kexec_load_args *);
int sys_pdrfork(struct thread *, struct pdrfork_args *);
int sys_pdwait(struct thread *, struct pdwait_args *);
+int sys_renameat2(struct thread *, struct renameat2_args *);
#ifdef COMPAT_43
@@ -3335,6 +3343,7 @@
#define SYS_AUE_kexec_load AUE_NULL
#define SYS_AUE_pdrfork AUE_PDRFORK
#define SYS_AUE_pdwait AUE_PDWAIT
+#define SYS_AUE_renameat2 AUE_RENAMEAT
#undef PAD_
#undef PADL_
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -1255,6 +1255,7 @@
struct vnode *a_tdvp;
struct vnode *a_tvp;
struct componentname *a_tcnp;
+ u_int a_flags;
} */ *ap)
{
struct vnode *tvp = ap->a_tvp;
@@ -1293,6 +1294,12 @@
goto releout;
}
+ if ((ap->a_flags & ~(AT_RENAME_NOREPLACE)) != 0) {
+ error = EOPNOTSUPP;
+ mp = NULL;
+ goto releout;
+ }
+
fdvp_s = fvp_s = tdvp_s = tvp_s = SEQC_MOD;
relock:
/*
@@ -1387,6 +1394,11 @@
}
}
+ if (tvp != NULL && (ap->a_flags & AT_RENAME_NOREPLACE) != 0) {
+ error = EEXIST;
+ goto unlockout;
+ }
+
if (DOINGSUJ(fdvp) &&
(seqc_in_modify(fdvp_s) || !vn_seqc_consistent(fdvp, fdvp_s) ||
seqc_in_modify(fvp_s) || !vn_seqc_consistent(fvp, fvp_s) ||
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Feb 28, 5:45 AM (13 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29054970
Default Alt Text
D55539.id172803.diff (21 KB)
Attached To
Mode
D55539: Add renameat(2) and AT_RENAME_NOREPLACE flag for it
Attached
Detach File
Event Timeline
Log In to Comment