看板 DFBSD_submit 關於我們 聯絡資訊
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; };