[PATCH] Add new syscall \`inotify_add_watch_fd'.

From: Giuseppe Scrivano
Date: Tue Sep 08 2009 - 17:40:03 EST


It makes possible to register a file to be watched by inotify using
its file descriptor instead of its path.
---
arch/x86/kernel/syscall_table_32.S | 1 +
fs/notify/inotify/inotify_user.c | 54 ++++++++++++++++++++++++++++++++++--
include/linux/syscalls.h | 3 ++
3 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index d51321d..46eb4ac 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -336,3 +336,4 @@ ENTRY(sys_call_table)
.long sys_pwritev
.long sys_rt_tgsigqueueinfo /* 335 */
.long sys_perf_counter_open
+ .long sys_inotify_add_watch_fd
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index dcd2040..53f3c41 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -747,16 +747,64 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,

/* create/update an inode mark */
ret = inotify_update_watch(group, inode, mask);
- if (unlikely(ret))
- goto path_put_and_out;

-path_put_and_out:
path_put(&path);
fput_and_out:
fput_light(filp, fput_needed);
return ret;
}

+SYSCALL_DEFINE3(inotify_add_watch_fd, int, wd, int, fd, u32, mask)
+{
+ struct fsnotify_group *group;
+ struct inode *inode;
+ struct path path;
+ struct file *filp;
+ struct file *filp2;
+ int ret, fput_needed, fput2_needed;
+ unsigned flags = 0;
+
+ filp = fget_light(wd, &fput_needed);
+ if (unlikely(!filp))
+ return -EBADF;
+
+ /* verify that this is indeed an inotify instance */
+ if (unlikely(filp->f_op != &inotify_fops)) {
+ ret = -EINVAL;
+ goto fput_and_out;
+ }
+
+ if (!(mask & IN_DONT_FOLLOW))
+ flags |= LOOKUP_FOLLOW;
+ if (mask & IN_ONLYDIR)
+ flags |= LOOKUP_DIRECTORY;
+
+ filp2 = fget_light(fd, &fput2_needed);
+
+ if (unlikely(!filp2)){
+ ret = -EBADF;
+ goto fput_and_out;
+ }
+
+ /* you can only watch an inode if you have read permissions on it */
+ ret = inode_permission(filp2->f_path.dentry->d_inode, MAY_READ);
+ if (ret)
+ goto fput2_and_out;
+
+ /* inode held in place by reference to path; group by fget on fd */
+ inode = filp2->f_path.dentry->d_inode;
+ group = filp->private_data;
+
+ /* create/update an inode mark */
+ ret = inotify_update_watch(group, inode, mask);
+
+fput2_and_out:
+ fput_light(filp2, fput2_needed);
+fput_and_out:
+ fput_light(filp, fput_needed);
+ return ret;
+}
+
SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd)
{
struct fsnotify_group *group;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 80de700..0833b1d 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -761,4 +761,7 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[]);
asmlinkage long sys_perf_counter_open(
struct perf_counter_attr __user *attr_uptr,
pid_t pid, int cpu, int group_fd, unsigned long flags);
+
+
+asmlinkage long sys_inotify_add_watch_fd(int wd, int fd, u32 mask);
#endif
--
1.6.3.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/