diff options
author | John McCutchan <ttb@tentacle.dhs.org> | 2005-12-12 03:37:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-12-12 11:57:43 -0500 |
commit | 8140a5005bc6f1c9d0fa103460d50d472e6e3426 (patch) | |
tree | 9c5ae431bf1db43e3a1e7a4cceb472c76077ac18 | |
parent | b4788f6d55548e587ced330ece711456f40ec8f1 (diff) |
[PATCH] inotify: add two inotify_add_watch flags
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>
-rw-r--r-- | fs/inotify.c | 13 | ||||
-rw-r--r-- | include/linux/inotify.h | 2 |
2 files changed, 12 insertions, 3 deletions
diff --git a/fs/inotify.c b/fs/inotify.c index bf7ce1d2412b..2fecb7af4a77 100644 --- a/fs/inotify.c +++ b/fs/inotify.c | |||
@@ -364,11 +364,12 @@ static int inotify_dev_get_wd(struct inotify_device *dev, | |||
364 | /* | 364 | /* |
365 | * find_inode - resolve a user-given path to a specific inode and return a nd | 365 | * find_inode - resolve a user-given path to a specific inode and return a nd |
366 | */ | 366 | */ |
367 | static int find_inode(const char __user *dirname, struct nameidata *nd) | 367 | static int find_inode(const char __user *dirname, struct nameidata *nd, |
368 | unsigned flags) | ||
368 | { | 369 | { |
369 | int error; | 370 | int error; |
370 | 371 | ||
371 | error = __user_walk(dirname, LOOKUP_FOLLOW, nd); | 372 | error = __user_walk(dirname, flags, nd); |
372 | if (error) | 373 | if (error) |
373 | return error; | 374 | return error; |
374 | /* you can only watch an inode if you have read permissions on it */ | 375 | /* 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) | |||
933 | struct file *filp; | 934 | struct file *filp; |
934 | int ret, fput_needed; | 935 | int ret, fput_needed; |
935 | int mask_add = 0; | 936 | int mask_add = 0; |
937 | unsigned flags = 0; | ||
936 | 938 | ||
937 | filp = fget_light(fd, &fput_needed); | 939 | filp = fget_light(fd, &fput_needed); |
938 | if (unlikely(!filp)) | 940 | if (unlikely(!filp)) |
@@ -944,7 +946,12 @@ asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) | |||
944 | goto fput_and_out; | 946 | goto fput_and_out; |
945 | } | 947 | } |
946 | 948 | ||
947 | ret = find_inode(path, &nd); | 949 | if (!(mask & IN_DONT_FOLLOW)) |
950 | flags |= LOOKUP_FOLLOW; | ||
951 | if (mask & IN_ONLYDIR) | ||
952 | flags |= LOOKUP_DIRECTORY; | ||
953 | |||
954 | ret = find_inode(path, &nd, flags); | ||
948 | if (unlikely(ret)) | 955 | if (unlikely(ret)) |
949 | goto fput_and_out; | 956 | goto fput_and_out; |
950 | 957 | ||
diff --git a/include/linux/inotify.h b/include/linux/inotify.h index ee5b239092ed..267c88b5f742 100644 --- a/include/linux/inotify.h +++ b/include/linux/inotify.h | |||
@@ -47,6 +47,8 @@ struct inotify_event { | |||
47 | #define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* moves */ | 47 | #define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* moves */ |
48 | 48 | ||
49 | /* special flags */ | 49 | /* special flags */ |
50 | #define IN_ONLYDIR 0x01000000 /* only watch the path if it is a directory */ | ||
51 | #define IN_DONT_FOLLOW 0x02000000 /* don't follow a sym link */ | ||
50 | #define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */ | 52 | #define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */ |
51 | #define IN_ISDIR 0x40000000 /* event occurred against dir */ | 53 | #define IN_ISDIR 0x40000000 /* event occurred against dir */ |
52 | #define IN_ONESHOT 0x80000000 /* only send event once */ | 54 | #define IN_ONESHOT 0x80000000 /* only send event once */ |