--- linux-2.5/arch/i386/kernel/entry.S-flink 2003-03-21 23:09:32.000000000 -0800 +++ linux-2.5/arch/i386/kernel/entry.S 2003-04-06 10:32:27.000000000 -0700 @@ -852,6 +852,7 @@ ENTRY(sys_call_table) .long sys_clock_gettime /* 265 */ .long sys_clock_getres .long sys_clock_nanosleep + .long sys_flink nr_syscalls=(.-sys_call_table)/4 --- linux-2.5/fs/namei.c-flink 2003-04-03 10:04:03.000000000 -0800 +++ linux-2.5/fs/namei.c 2003-04-06 11:20:41.000000000 -0700 @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -1796,10 +1797,10 @@ int vfs_link(struct dentry *old_dentry, * with linux 2.0, and to avoid hard-linking to directories * and other special files. --ADM */ -asmlinkage long sys_link(const char * oldname, const char * newname) +static long link_common(struct vfsmount *old_mnt, struct dentry *old_dentry, const char *newname) { struct dentry *new_dentry; - struct nameidata nd, old_nd; + struct nameidata nd; int error; char * to; @@ -1807,32 +1808,53 @@ asmlinkage long sys_link(const char * ol if (IS_ERR(to)) return PTR_ERR(to); - error = __user_walk(oldname, 0, &old_nd); - if (error) - goto exit; error = path_lookup(to, LOOKUP_PARENT, &nd); if (error) - goto out; + goto exit; error = -EXDEV; - if (old_nd.mnt != nd.mnt) + if (old_mnt != nd.mnt) goto out_release; new_dentry = lookup_create(&nd, 0); error = PTR_ERR(new_dentry); if (!IS_ERR(new_dentry)) { - error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); + error = vfs_link(old_dentry, nd.dentry->d_inode, new_dentry); dput(new_dentry); } up(&nd.dentry->d_inode->i_sem); out_release: path_release(&nd); -out: - path_release(&old_nd); exit: putname(to); return error; } +asmlinkage long sys_link(const char *oldname, const char *newname) +{ + struct nameidata old_nd; + int error; + + error = __user_walk(oldname, 0, &old_nd); + if (!error) { + error = link_common(old_nd.mnt, old_nd.dentry, newname); + path_release(&old_nd); + } + return error; +} + +asmlinkage long sys_flink(unsigned int fd, const char *newname) +{ + struct file *file; + int error = -EBADF; + + file = fget(fd); + if (file) { + error = link_common(file->f_vfsmnt, file->f_dentry, newname); + fput(file); + } + return error; +} + /* * The worst of all namespace operations - renaming directory. "Perverted" * doesn't even start to describe it. Somebody in UCB had a heck of a trip... --- linux-2.5/include/asm-i386/unistd.h-flink 2003-02-19 21:41:59.000000000 -0800 +++ linux-2.5/include/asm-i386/unistd.h 2003-04-06 10:30:08.000000000 -0700 @@ -273,8 +273,9 @@ #define __NR_clock_gettime (__NR_timer_create+6) #define __NR_clock_getres (__NR_timer_create+7) #define __NR_clock_nanosleep (__NR_timer_create+8) +#define __NR_flink 268 -#define NR_syscalls 268 +#define NR_syscalls 269 /* user-visible error numbers are in the range -1 - -124: see */