The attached patch implements the inotify syscalls. inotify.c is a test program.
Example: $ arm-linux-gcc inotify.c -o test -static $ qemu-arm test file & [4] 13882 wd = 1 $ echo aaa > file Event on 1 mask 2(IN_MODIFY) Event on 1 mask 20(IN_OPEN) Event on 1 mask 8(IN_CLOSE_WRITE) Event on 1 mask 20(IN_OPEN) Event on 1 mask 1(IN_ACCESS) Event on 1 mask 10(IN_CLOSE_NOWRITE) $ chmod a+rwx file Event on 1 mask 4(IN_ATTRIB) Lauro Ramos Venancio OpenBossa Labs Instituto Nokia de Tecnologia Recife - Brazil
#include <stdio.h> #include <stdlib.h> #include <sys/inotify.h> #include <linux/kernel.h> #include <sys/poll.h> #include <string.h> #include <errno.h> void print_event(uint32_t event) { if (event & IN_ACCESS) printf("IN_ACCESS"); else if (event & IN_ATTRIB) printf("IN_ATTRIB"); else if (event & IN_CLOSE_WRITE) printf("IN_CLOSE_WRITE"); else if (event & IN_CLOSE_NOWRITE) printf("IN_CLOSE_NOWRITE"); else if (event & IN_CREATE) printf("IN_CREATE"); else if (event & IN_DELETE) printf("IN_DELETE"); else if (event & IN_DELETE_SELF) printf("IN_DELETE_SELF"); else if (event & IN_MODIFY) printf("IN_MODIFY"); else if (event & IN_MOVE_SELF) printf("IN_MOVE_SELF"); else if (event & IN_MOVED_FROM) printf("IN_MOVED_FROM"); else if (event & IN_MOVED_TO) printf("IN_MOVED_TO"); else if (event & IN_OPEN) printf("IN_OPEN"); } int main(int argc, char *argv[]) { int fd, wd, bytes_read; struct pollfd pfd; struct inotify_event event; if(0 > (fd = inotify_init())) { printf("Error on notify init: %d\n", fd); exit(-1); } if(argc < 2) { printf("Usage: %s <file>\n", argv[0]); exit(-1); } if(0 > (wd = inotify_add_watch(fd, argv[1], IN_ALL_EVENTS))) { printf("Error on add watch: %d\n", wd); exit(-1); } printf("wd = %d\n", wd); pfd.fd = fd; pfd.events = POLLIN | POLLERR | POLLNVAL; while(1) { if(0 > poll(&pfd, 1, -1)) { printf("Error on poll: %s\n", strerror(errno)); exit(-1); } if(pfd.revents & POLLIN) { bytes_read = read(fd, &event, sizeof(struct inotify_event)); if(bytes_read < 0) { printf("Error reading some bytes and stuff:" "%s\n", strerror(bytes_read)); } else { printf("Event on %ld mask %lx(", event.wd, event.mask); print_event(event.mask); printf(")\n"); } } } }
Index: linux-user/syscall.c =================================================================== RCS file: /sources/qemu/qemu/linux-user/syscall.c,v retrieving revision 1.121 diff -u -r1.121 syscall.c --- linux-user/syscall.c 17 Sep 2007 08:09:50 -0000 1.121 +++ linux-user/syscall.c 21 Sep 2007 19:18:25 -0000 @@ -47,6 +47,7 @@ #include <sys/shm.h> #include <sys/sem.h> #include <sys/statfs.h> +#include <sys/inotify.h> #include <utime.h> #include <sys/sysinfo.h> //#include <sys/user.h> @@ -4652,7 +4653,23 @@ case TARGET_NR_set_robust_list: goto unimplemented_nowarn; #endif - +#ifdef TARGET_NR_inotify_init + case TARGET_NR_inotify_init: + ret = get_errno(inotify_init()); + break; +#endif +#ifdef TARGET_NR_inotify_add_watch + case TARGET_NR_inotify_add_watch: + p = lock_user_string(arg2); + ret = get_errno(inotify_add_watch(arg1, path(p), arg3)); + unlock_user(p, arg2, 0); + break; +#endif +#ifdef TARGET_NR_inotify_rm_watch + case TARGET_NR_inotify_rm_watch: + ret = get_errno(inotify_rm_watch(arg1, arg2)); + break; +#endif default: unimplemented: gemu_log("qemu: Unsupported syscall: %d\n", num);