openat(2)

Nicolas Thery nthery at gmail.com
Wed Jul 22 15:21:27 PDT 2009


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(fstatvfs_args), (sy_call_t *)sys_fstatvfs },       /* 501
= fstatvfs */
       { AS(fhstatvfs_args), (sy_call_t *)sys_fhstatvfs },     /* 502
= fhstatvfs */
       { AS(getvfsstat_args), (sy_call_t *)sys_getvfsstat },   /* 503
= getvfsstat */
+       { AS(openat_args), (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_path[0] != '/' && 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;
 };





More information about the Submit mailing list