1 #ifndef _LINUX_FS_NOTIFY_H 2 #define _LINUX_FS_NOTIFY_H 3 4 /* 5 * include/linux/fsnotify.h - generic hooks for filesystem notification, to 6 * reduce in-source duplication from both dnotify and inotify. 7 * 8 * We don't compile any of this away in some complicated menagerie of ifdefs. 9 * Instead, we rely on the code inside to optimize away as needed. 10 * 11 * (C) Copyright 2005 Robert Love 12 */ 13 14 #include <linux/fsnotify_backend.h> 15 #include <linux/audit.h> 16 #include <linux/slab.h> 17 #include <linux/bug.h> 18 19 /* Notify this dentry's parent about a child's events. */ 20 static inline int fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) 21 { 22 if (!dentry) 23 dentry = path->dentry; 24 25 return __fsnotify_parent(path, dentry, mask); 26 } 27 28 /* simple call site for access decisions */ 29 static inline int fsnotify_perm(struct file *file, int mask) 30 { 31 struct path *path = &file->f_path; 32 struct inode *inode = file_inode(file); 33 __u32 fsnotify_mask = 0; 34 int ret; 35 36 if (file->f_mode & FMODE_NONOTIFY) 37 return 0; 38 if (!(mask & (MAY_READ | MAY_OPEN))) 39 return 0; 40 if (mask & MAY_OPEN) 41 fsnotify_mask = FS_OPEN_PERM; 42 else if (mask & MAY_READ) 43 fsnotify_mask = FS_ACCESS_PERM; 44 else 45 BUG(); 46 47 ret = fsnotify_parent(path, NULL, fsnotify_mask); 48 if (ret) 49 return ret; 50 51 return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); 52 } 53 54 /* 55 * fsnotify_link_count - inode's link count changed 56 */ 57 static inline void fsnotify_link_count(struct inode *inode) 58 { 59 fsnotify(inode, FS_ATTRIB, inode, FSNOTIFY_EVENT_INODE, NULL, 0); 60 } 61 62 /* 63 * fsnotify_move - file old_name at old_dir was moved to new_name at new_dir 64 */ 65 static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, 66 const unsigned char *old_name, 67 int isdir, struct inode *target, struct dentry *moved) 68 { 69 struct inode *source = moved->d_inode; 70 u32 fs_cookie = fsnotify_get_cookie(); 71 __u32 old_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_FROM); 72 __u32 new_dir_mask = (FS_EVENT_ON_CHILD | FS_MOVED_TO); 73 const unsigned char *new_name = moved->d_name.name; 74 75 if (old_dir == new_dir) 76 old_dir_mask |= FS_DN_RENAME; 77 78 if (isdir) { 79 old_dir_mask |= FS_ISDIR; 80 new_dir_mask |= FS_ISDIR; 81 } 82 83 fsnotify(old_dir, old_dir_mask, source, FSNOTIFY_EVENT_INODE, old_name, 84 fs_cookie); 85 fsnotify(new_dir, new_dir_mask, source, FSNOTIFY_EVENT_INODE, new_name, 86 fs_cookie); 87 88 if (target) 89 fsnotify_link_count(target); 90 91 if (source) 92 fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0); 93 audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE); 94 } 95 96 /* 97 * fsnotify_inode_delete - and inode is being evicted from cache, clean up is needed 98 */ 99 static inline void fsnotify_inode_delete(struct inode *inode) 100 { 101 __fsnotify_inode_delete(inode); 102 } 103 104 /* 105 * fsnotify_vfsmount_delete - a vfsmount is being destroyed, clean up is needed 106 */ 107 static inline void fsnotify_vfsmount_delete(struct vfsmount *mnt) 108 { 109 __fsnotify_vfsmount_delete(mnt); 110 } 111 112 /* 113 * fsnotify_nameremove - a filename was removed from a directory 114 */ 115 static inline void fsnotify_nameremove(struct dentry *dentry, int isdir) 116 { 117 __u32 mask = FS_DELETE; 118 119 if (isdir) 120 mask |= FS_ISDIR; 121 122 fsnotify_parent(NULL, dentry, mask); 123 } 124 125 /* 126 * fsnotify_inoderemove - an inode is going away 127 */ 128 static inline void fsnotify_inoderemove(struct inode *inode) 129 { 130 fsnotify(inode, FS_DELETE_SELF, inode, FSNOTIFY_EVENT_INODE, NULL, 0); 131 __fsnotify_inode_delete(inode); 132 } 133 134 /* 135 * fsnotify_create - 'name' was linked in 136 */ 137 static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) 138 { 139 audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE); 140 141 fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); 142 } 143 144 /* 145 * fsnotify_link - new hardlink in 'inode' directory 146 * Note: We have to pass also the linked inode ptr as some filesystems leave 147 * new_dentry->d_inode NULL and instantiate inode pointer later 148 */ 149 static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry) 150 { 151 fsnotify_link_count(inode); 152 audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE); 153 154 fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0); 155 } 156 157 /* 158 * fsnotify_mkdir - directory 'name' was created 159 */ 160 static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) 161 { 162 __u32 mask = (FS_CREATE | FS_ISDIR); 163 struct inode *d_inode = dentry->d_inode; 164 165 audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE); 166 167 fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); 168 } 169 170 /* 171 * fsnotify_access - file was read 172 */ 173 static inline void fsnotify_access(struct file *file) 174 { 175 struct path *path = &file->f_path; 176 struct inode *inode = file_inode(file); 177 __u32 mask = FS_ACCESS; 178 179 if (S_ISDIR(inode->i_mode)) 180 mask |= FS_ISDIR; 181 182 if (!(file->f_mode & FMODE_NONOTIFY)) { 183 fsnotify_parent(path, NULL, mask); 184 fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); 185 } 186 } 187 188 /* 189 * fsnotify_modify - file was modified 190 */ 191 static inline void fsnotify_modify(struct file *file) 192 { 193 struct path *path = &file->f_path; 194 struct inode *inode = file_inode(file); 195 __u32 mask = FS_MODIFY; 196 197 if (S_ISDIR(inode->i_mode)) 198 mask |= FS_ISDIR; 199 200 if (!(file->f_mode & FMODE_NONOTIFY)) { 201 fsnotify_parent(path, NULL, mask); 202 fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); 203 } 204 } 205 206 /* 207 * fsnotify_open - file was opened 208 */ 209 static inline void fsnotify_open(struct file *file) 210 { 211 struct path *path = &file->f_path; 212 struct inode *inode = file_inode(file); 213 __u32 mask = FS_OPEN; 214 215 if (S_ISDIR(inode->i_mode)) 216 mask |= FS_ISDIR; 217 218 fsnotify_parent(path, NULL, mask); 219 fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); 220 } 221 222 /* 223 * fsnotify_close - file was closed 224 */ 225 static inline void fsnotify_close(struct file *file) 226 { 227 struct path *path = &file->f_path; 228 struct inode *inode = file_inode(file); 229 fmode_t mode = file->f_mode; 230 __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE; 231 232 if (S_ISDIR(inode->i_mode)) 233 mask |= FS_ISDIR; 234 235 if (!(file->f_mode & FMODE_NONOTIFY)) { 236 fsnotify_parent(path, NULL, mask); 237 fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0); 238 } 239 } 240 241 /* 242 * fsnotify_xattr - extended attributes were changed 243 */ 244 static inline void fsnotify_xattr(struct dentry *dentry) 245 { 246 struct inode *inode = dentry->d_inode; 247 __u32 mask = FS_ATTRIB; 248 249 if (S_ISDIR(inode->i_mode)) 250 mask |= FS_ISDIR; 251 252 fsnotify_parent(NULL, dentry, mask); 253 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); 254 } 255 256 /* 257 * fsnotify_change - notify_change event. file was modified and/or metadata 258 * was changed. 259 */ 260 static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid) 261 { 262 struct inode *inode = dentry->d_inode; 263 __u32 mask = 0; 264 265 if (ia_valid & ATTR_UID) 266 mask |= FS_ATTRIB; 267 if (ia_valid & ATTR_GID) 268 mask |= FS_ATTRIB; 269 if (ia_valid & ATTR_SIZE) 270 mask |= FS_MODIFY; 271 272 /* both times implies a utime(s) call */ 273 if ((ia_valid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) 274 mask |= FS_ATTRIB; 275 else if (ia_valid & ATTR_ATIME) 276 mask |= FS_ACCESS; 277 else if (ia_valid & ATTR_MTIME) 278 mask |= FS_MODIFY; 279 280 if (ia_valid & ATTR_MODE) 281 mask |= FS_ATTRIB; 282 283 if (mask) { 284 if (S_ISDIR(inode->i_mode)) 285 mask |= FS_ISDIR; 286 287 fsnotify_parent(NULL, dentry, mask); 288 fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0); 289 } 290 } 291 292 #if defined(CONFIG_FSNOTIFY) /* notify helpers */ 293 294 /* 295 * fsnotify_oldname_init - save off the old filename before we change it 296 */ 297 static inline const unsigned char *fsnotify_oldname_init(const unsigned char *name) 298 { 299 return kstrdup(name, GFP_KERNEL); 300 } 301 302 /* 303 * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init 304 */ 305 static inline void fsnotify_oldname_free(const unsigned char *old_name) 306 { 307 kfree(old_name); 308 } 309 310 #else /* CONFIG_FSNOTIFY */ 311 312 static inline const char *fsnotify_oldname_init(const unsigned char *name) 313 { 314 return NULL; 315 } 316 317 static inline void fsnotify_oldname_free(const unsigned char *old_name) 318 { 319 } 320 321 #endif /* CONFIG_FSNOTIFY */ 322 323 #endif /* _LINUX_FS_NOTIFY_H */ 324