[PATCH] inotify: add two inotify_add_watch flags
authorJohn McCutchan <ttb@tentacle.dhs.org>
Mon, 12 Dec 2005 08:37:14 +0000 (00:37 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 12 Dec 2005 16:57:43 +0000 (08:57 -0800)
The below patch lets userspace have more control over the inodes that
inotify will watch.  It introduces two new flags.

        IN_ONLYDIR -- only watch the inode if it is a directory.
        This is needed to avoid the race that can occur when we want to be
        sure that we are watching a directory.

        IN_DONT_FOLLOW -- don't follow a symlink.  In combination
        with IN_ONLYDIR we can make sure that we don't watch the target of
        symlinks.

The issues the flags fix came up when writing the gnome-vfs inotify
backend.  Default behaviour is unchanged.

Signed-off-by: John McCutchan <ttb@tentacle.dhs.org>
Acked-by: Robert Love <rml@novell.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/inotify.c
include/linux/inotify.h

index bf7ce1d2412bb43928b908527287668eb59fb90d..2fecb7af4a77d6316171f0e25a40fd9027a71647 100644 (file)
@@ -364,11 +364,12 @@ static int inotify_dev_get_wd(struct inotify_device *dev,
 /*
  * find_inode - resolve a user-given path to a specific inode and return a nd
  */
-static int find_inode(const char __user *dirname, struct nameidata *nd)
+static int find_inode(const char __user *dirname, struct nameidata *nd,
+                     unsigned flags)
 {
        int error;
 
-       error = __user_walk(dirname, LOOKUP_FOLLOW, nd);
+       error = __user_walk(dirname, flags, nd);
        if (error)
                return error;
        /* you can only watch an inode if you have read permissions on it */
@@ -933,6 +934,7 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
        struct file *filp;
        int ret, fput_needed;
        int mask_add = 0;
+       unsigned flags = 0;
 
        filp = fget_light(fd, &fput_needed);
        if (unlikely(!filp))
@@ -944,7 +946,12 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
                goto fput_and_out;
        }
 
-       ret = find_inode(path, &nd);
+       if (!(mask & IN_DONT_FOLLOW))
+               flags |= LOOKUP_FOLLOW;
+       if (mask & IN_ONLYDIR)
+               flags |= LOOKUP_DIRECTORY;
+
+       ret = find_inode(path, &nd, flags);
        if (unlikely(ret))
                goto fput_and_out;
 
index ee5b239092edbb03dee1765dd7919246bf4a2400..267c88b5f742592b69dabf70bfcdfb2c471ec706 100644 (file)
@@ -47,6 +47,8 @@ struct inotify_event {
 #define IN_MOVE                        (IN_MOVED_FROM | IN_MOVED_TO) /* moves */
 
 /* special flags */
+#define IN_ONLYDIR             0x01000000      /* only watch the path if it is a directory */
+#define IN_DONT_FOLLOW         0x02000000      /* don't follow a sym link */
 #define IN_MASK_ADD            0x20000000      /* add to the mask of an already existing watch */
 #define IN_ISDIR               0x40000000      /* event occurred against dir */
 #define IN_ONESHOT             0x80000000      /* only send event once */