implement linkat
authorAlex Hornung <alex@alexhornung.com>
Mon, 30 Jul 2012 11:21:53 +0000 (11:21 +0000)
committerAlex Hornung <alex@alexhornung.com>
Mon, 30 Jul 2012 15:31:27 +0000 (15:31 +0000)
include/unistd.h
sys/kern/init_sysent.c
sys/kern/syscalls.c
sys/kern/syscalls.master
sys/kern/vfs_syscalls.c
sys/sys/fcntl.h
sys/sys/syscall-hide.h
sys/sys/syscall.h
sys/sys/syscall.mk
sys/sys/sysproto.h
sys/sys/sysunion.h

index b9efb52..b8dbf46 100644 (file)
@@ -425,8 +425,8 @@ int faccessat(int, const char *, int, int);
 int    fchownat(int, const char *, uid_t, gid_t, int);
 #if 0
 int    fexecve(int, char *const [], char *const []);
-int    linkat(int, const char *, int, const char *, int);
 #endif
+int    linkat(int, const char *, int, const char *, int);
 ssize_t        readlinkat(int, const char * __restrict, char * __restrict, size_t);
 int    symlinkat(const char *, int, const char *);
 int    unlinkat(int, const char *, int);
index 3c0762b..b96207f 100644 (file)
@@ -564,4 +564,5 @@ struct sysent sysent[] = {
        { AS(symlinkat_args), (sy_call_t *)sys_symlinkat },     /* 528 = symlinkat */
        { AS(swapoff_args), (sy_call_t *)sys_swapoff }, /* 529 = swapoff */
        { AS(vquotactl_args), (sy_call_t *)sys_vquotactl },     /* 530 = vquotactl */
+       { AS(linkat_args), (sy_call_t *)sys_linkat },   /* 531 = linkat */
 };
index 0c8e3f0..013a338 100644 (file)
@@ -538,4 +538,5 @@ const char *syscallnames[] = {
        "symlinkat",                    /* 528 = symlinkat */
        "swapoff",                      /* 529 = swapoff */
        "vquotactl",                    /* 530 = vquotactl */
+       "linkat",                       /* 531 = linkat */
 };
index 843f90e..8a5a793 100644 (file)
 529    STD     BSD     { int swapoff(char *name); }
 530    STD     BSD     { int vquotactl(const char *path, \
                            struct plistref *pref); }
+531    STD     POSIX   { int linkat(int fd1, char *path1, int fd2, \
+                               char *path2, int flags); }
index 11c66a8..4e9fe49 100644 (file)
@@ -2287,6 +2287,33 @@ sys_link(struct link_args *uap)
        return (error);
 }
 
+/*
+ * linkat_args(int fd1, char *path1, int fd2, char *path2, int flags)
+ *
+ * Make a hard file link. The path1 argument is relative to the directory
+ * associated with fd1, and similarly the path2 argument is relative to
+ * the directory associated with fd2.
+ */
+int
+sys_linkat(struct linkat_args *uap)
+{
+       struct nlookupdata nd, linknd;
+       struct file *fp1, *fp2;
+       int error;
+
+       error = nlookup_init_at(&nd, &fp1, uap->fd1, uap->path1, UIO_USERSPACE,
+           (uap->flags & AT_SYMLINK_FOLLOW) ? NLC_FOLLOW : 0);
+       if (error == 0) {
+               error = nlookup_init_at(&linknd, &fp2, uap->fd2,
+                   uap->path2, UIO_USERSPACE, 0);
+               if (error == 0)
+                       error = kern_link(&nd, &linknd);
+               nlookup_done_at(&linknd, fp2);
+       }
+       nlookup_done_at(&nd, fp1);
+       return (error);
+}
+
 int
 kern_symlink(struct nlookupdata *nd, char *path, int mode)
 {
index 489f0b6..03e657b 100644 (file)
 #define AT_SYMLINK_NOFOLLOW    1
 #define AT_REMOVEDIR           2
 #define AT_EACCESS             4
+#define AT_SYMLINK_FOLLOW      8
 
 /*
  * Constants used for fcntl(2)
index 8d1e086..e0310e1 100644 (file)
@@ -361,3 +361,4 @@ HIDE_POSIX(readlinkat)
 HIDE_POSIX(symlinkat)
 HIDE_BSD(swapoff)
 HIDE_BSD(vquotactl)
+HIDE_POSIX(linkat)
index a97cb28..ed049b4 100644 (file)
 #define        SYS_symlinkat   528
 #define        SYS_swapoff     529
 #define        SYS_vquotactl   530
-#define        SYS_MAXSYSCALL  531
+#define        SYS_linkat      531
+#define        SYS_MAXSYSCALL  532
index 5a8f8d8..10a711d 100644 (file)
@@ -309,4 +309,5 @@ MIASM =  \
        readlinkat.o \
        symlinkat.o \
        swapoff.o \
-       vquotactl.o
+       vquotactl.o \
+       linkat.o
index e02fa51..d334469 100644 (file)
@@ -2365,6 +2365,16 @@ struct   vquotactl_args {
        const char *    path;   char path_[PAD_(const char *)];
        struct plistref *       pref;   char pref_[PAD_(struct plistref *)];
 };
+struct linkat_args {
+#ifdef _KERNEL
+       struct sysmsg sysmsg;
+#endif
+       int     fd1;    char fd1_[PAD_(int)];
+       char *  path1;  char path1_[PAD_(char *)];
+       int     fd2;    char fd2_[PAD_(int)];
+       char *  path2;  char path2_[PAD_(char *)];
+       int     flags;  char flags_[PAD_(int)];
+};
 
 #ifdef COMPAT_43
 
@@ -2982,6 +2992,7 @@ int       sys_readlinkat (struct readlinkat_args *);
 int    sys_symlinkat (struct symlinkat_args *);
 int    sys_swapoff (struct swapoff_args *);
 int    sys_vquotactl (struct vquotactl_args *);
+int    sys_linkat (struct linkat_args *);
 
 #endif /* !_SYS_SYSPROTO_H_ */
 #undef PAD_
index 6006e90..b18ba48 100644 (file)
@@ -417,4 +417,5 @@ union sysunion {
        struct  symlinkat_args symlinkat;
        struct  swapoff_args swapoff;
        struct  vquotactl_args vquotactl;
+       struct  linkat_args linkat;
 };