Bug #1435
closedopenat(2)
0%
Description
Hello,
I'm implementing the openat(2) system call. Here is a patch
containing the kernel-side part. If there is no objection, I'll
commit it in a couple of days alongside the userland wrappers and man
page.
Cheers,
Nicolas
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
index 20b33f6..d66ef2f 100644
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c@ -537,4 +537,5
@ struct sysent sysent[] = {
{ AS, (sy_call_t )sys_fstatvfs }, / 501
= fstatvfs */
{ AS, (sy_call_t )sys_fhstatvfs }, / 502
= fhstatvfs */
{ AS, (sy_call_t )sys_getvfsstat }, / 503
= getvfsstat /
+ { AS, (sy_call_t *)sys_openat }, / 504 = openat /
};
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
index 817e44b..5664413 100644
--- a/sys/kern/syscalls.c
++ b/sys/kern/syscalls.c@ -511,4 +511,5
@ char *syscallnames[] = {
"fstatvfs", / 501 = fstatvfs /
"fhstatvfs", / 502 = fhstatvfs /
"getvfsstat", / 503 = getvfsstat /
"openat", / 504 = openat */
};
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 3b2672e..8527373 100644
--- a/sys/kern/syscalls.master
++ b/sys/kern/syscalls.master@ -688,3 +688,7
@
502 STD BSD { int fhstatvfs(const struct fhandle *u_fhp, struct
statvfs *buf); }
503 STD BSD { int getvfsstat(struct statfs *buf, \
struct statvfs *vbuf, long vbufsize, int flags); }
+504 STD BSD { int openat(int fd, char *path, int flags, int mode); }
; XXX should be { int openat(int fd, const char *path,
int flags, ...);}
; but we're not ready for `const' or varargs.
; XXX man page says `mode_t mode'.
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 27b766c..8a87f33 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c@ -1837,6 +1837,48
@ sys_open(struct open_args *uap)
return (error);
}
/*
* openat_args(int fd, char path, int flags, int mode)
+ */
int
+sys_openat(struct openat_args *uap)
{
+ struct thread *td = curthread;
+ struct proc *p = td->td_proc;
+ struct file fp = NULL;
+ struct vnode vp;
+ struct nlookupdata nd;
+ int error;
error = nlookup_init(&nd, uap->path, UIO_USERSPACE, 0);
+ if (error != 0)
+ goto cleanup;
if (nd.nl_path0 != '/' && uap->fd != AT_FDCWD) {
+ /
+ * Use dir pointed to by fd as lookup starting point instead
+ * of current dir.
+ /
+ if ((error = holdvnode(p->p_fd, uap->fd, &fp)) != 0)
+ goto cleanup;
+ vp = (struct vnode)fp->f_data;
+ if (vp->v_type != VDIR || fp->f_nchandle.ncp == NULL) {
+ error = ENOTDIR;
+ goto cleanup;
+ }
+ cache_drop(&nd.nl_nch);
+ cache_copy(&fp->f_nchandle, &nd.nl_nch);
+ }
error = kern_open(&nd, uap->flags, uap->mode, &uap->sysmsg_result);
+cleanup:
if (fp != NULL)
+ fdrop(fp);
+ nlookup_done(&nd);
+ return (error);
}
int
kern_mknod(struct nlookupdata *nd, int mode, int rmajor, int rminor)
{
diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h
index 7593dbb..df1db82 100644
--- a/sys/sys/fcntl.h
+++ b/sys/sys/fcntl.h@ -197,6 +197,8
@
#define F_NOEND 0x080 /* l_len = 0, internally used */
#endif
#define AT_FDCWD 0xFFFAFDCD /* see openat(2) /
/
* Advisory file segment locking data type -
* information passed to system by user@ -233,6 +235,7
@ union fcntl_dat {
_BEGIN_DECLS
int open (const char *, int, ...);
int openat (int, const char *, int, ...);
int creat (const char *, mode_t);
int fcntl (int, int, ...);
#ifndef _POSIX_SOURCE
diff --git a/sys/sys/syscall-hide.h b/sys/sys/syscall-hide.h
index 0e57ae0..6ef21fc 100644
--- a/sys/sys/syscall-hide.h
++ b/sys/sys/syscall-hide.h
@ -334,3 +334,4
@ HIDE_BSD(statvfs)
HIDE_BSD(fstatvfs)
HIDE_BSD(fhstatvfs)
HIDE_BSD(getvfsstat)
HIDE_BSD(openat)
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
index 38f0fc1..3f5d863 100644
--- a/sys/sys/syscall.h
++ b/sys/sys/syscall.h
@ -345,4 +345,5
@
#define SYS_fstatvfs 501
#define SYS_fhstatvfs 502
#define SYS_getvfsstat 503
#define SYS_MAXSYSCALL 504
#define SYS_openat 504
#define SYS_MAXSYSCALL 505
diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
index c1598a8..4fa37c8 100644
-- a/sys/sys/syscall.mk
++ b/sys/sys/syscall.mk
@ -285,4 +285,5
@ MIASM = \
statvfs.o \
fstatvfs.o \
fhstatvfs.o \
- getvfsstat.o
getvfsstat.o \
+ openat.o
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
index 6d72e28..7395548 100644
--- a/sys/sys/sysproto.h
++ b/sys/sys/sysproto.h
@ -2159,6 +2159,15
@ struct getvfsstat_args {
long vbufsize; char vbufsize[PAD_(long)];
int flags; char flags_[PAD_(int)];
};
+struct openat_args {
#ifdef KERNEL
+ struct sysmsg sysmsg;
#endif
int fd; char fd[PAD_(int)];
+ char * path; char path_[PAD_(char *)];
+ int flags; char flags_[PAD_(int)];
+ int mode; char mode_[PAD_(int)];
+};
#ifdef COMPAT_43
@ -2745,6 +2754,7
@ int sys_statvfs (struct statvfs_args *);
int sys_fstatvfs (struct fstatvfs_args *);
int sys_fhstatvfs (struct fhstatvfs_args *);
int sys_getvfsstat (struct getvfsstat_args *);
+int sys_openat (struct openat_args *);
#endif /* !_SYS_SYSPROTO_H_ */
#undef PAD_
diff --git a/sys/sys/sysunion.h b/sys/sys/sysunion.h
index 2aaa1d8..fe50bbd 100644
--- a/sys/sys/sysunion.h
++ b/sys/sys/sysunion.h
@ -390,4 +390,5
@ union sysunion {
struct fstatvfs_args fstatvfs;
struct fhstatvfs_args fhstatvfs;
struct getvfsstat_args getvfsstat;
struct openat_args openat;
};