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);

Reply via email to