+.SH 例
+The following program demonstrates the usage of the inotify API. It marks
+the directories passed as a command\-line arguments and waits for events of
+type \fBIN_OPEN\fP, \fBIN_CLOSE_NOWRITE\fP and \fBIN_CLOSE_WRITE\fP.
+.PP
+The following output was recorded while editing the file
+\fI/home/user/temp/foo\fP and listing directory \fI/tmp\fP. Before the file and
+the directory were opened, \fBIN_OPEN\fP events occurred. After the file was
+closed, an \fBIN_CLOSE_WRITE\fP event occurred. After the directory was
+closed, an \fBIN_CLOSE_NOWRITE\fP event occurred. Execution of the program
+ended when the user pressed the ENTER key.
+.SS 出力例
+.in +4n
+.nf
+$ \fB./a.out /tmp /home/user/temp\fP
+Press enter key to terminate.
+Listening for events.
+IN_OPEN: /home/user/temp/foo [file]
+IN_CLOSE_WRITE: /home/user/temp/foo [file]
+IN_OPEN: /tmp/ [directory]
+IN_CLOSE_NOWRITE: /tmp/ [directory]
+
+Listening for events stopped.
+.fi
+.in
+.SS プログラムソース
+.nf
+#include <errno.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/inotify.h>
+#include <unistd.h>
+
+/* Read all available inotify events from the file descriptor 'fd'.
+ wd is the table of watch descriptors for the directories in argv.
+ argc is the length of wd and argv.
+ argv is the list of watched directories.
+ Entry 0 of wd and argv is unused. */
+
+static void
+handle_events(int fd, int *wd, int argc, char* argv[])
+{
+ /* Some systems cannot read integer variables if they are not
+ properly aligned. On other systems, incorrect alignment may
+ decrease performance. Hence, the buffer used for reading from
+ the inotify file descriptor should have the same alignment as
+ struct inotify_event. */
+
+ char buf[4096]
+ __attribute__ ((aligned(__alignof__(struct inotify_event))));
+ const struct inotify_event *event;
+ int i;
+ ssize_t len;
+ char *ptr;
+
+ /* Loop while events can be read from inotify file descriptor. */
+
+ for (;;) {
+
+ /* Read some events. */
+
+ len = read(fd, buf, sizeof buf);
+ if (len == \-1 && errno != EAGAIN) {
+ perror("read");
+ exit(EXIT_FAILURE);
+ }
+
+ /* If the nonblocking read() found no events to read, then
+ it returns \-1 with errno set to EAGAIN. In that case,
+ we exit the loop. */
+
+ if (len <= 0)
+ break;
+
+ /* Loop over all events in the buffer */
+
+ for (ptr = buf; ptr < buf + len;
+ ptr += sizeof(struct inotify_event) + event\->len) {
+
+ event = (const struct inotify_event *) ptr;
+
+ /* Print event type */
+
+ if (event\->mask & IN_OPEN)
+ printf("IN_OPEN: ");
+ if (event\->mask & IN_CLOSE_NOWRITE)
+ printf("IN_CLOSE_NOWRITE: ");
+ if (event\->mask & IN_CLOSE_WRITE)
+ printf("IN_CLOSE_WRITE: ");
+
+ /* Print the name of the watched directory */
+
+ for (i = 1; i < argc; ++i) {
+ if (wd[i] == event\->wd) {
+ printf("%s/", argv[i]);
+ break;
+ }
+ }
+
+ /* Print the name of the file */
+
+ if (event\->len)
+ printf("%s", event\->name);
+
+ /* Print type of filesystem object */
+
+ if (event\->mask & IN_ISDIR)
+ printf(" [directory]\en");
+ else
+ printf(" [file]\en");
+ }
+ }
+}
+
+int
+main(int argc, char* argv[])
+{
+ char buf;
+ int fd, i, poll_num;
+ int *wd;
+ nfds_t nfds;
+ struct pollfd fds[2];
+
+ if (argc < 2) {
+ printf("Usage: %s PATH [PATH ...]\en", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Press ENTER key to terminate.\en");
+
+ /* Create the file descriptor for accessing the inotify API */
+
+ fd = inotify_init1(IN_NONBLOCK);
+ if (fd == \-1) {
+ perror("inotify_init1");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Allocate memory for watch descriptors */
+
+ wd = calloc(argc, sizeof(int));
+ if (wd == NULL) {
+ perror("calloc");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Mark directories for events
+ \- file was opened
+ \- file was closed */
+
+ for (i = 1; i < argc; i++) {
+ wd[i] = inotify_add_watch(fd, argv[i],
+ IN_OPEN | IN_CLOSE);
+ if (wd[i] == \-1) {
+ fprintf(stderr, "Cannot watch '%s'\en", argv[i]);
+ perror("inotify_add_watch");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Prepare for polling */
+
+ nfds = 2;
+
+ /* Console input */
+
+ fds[0].fd = STDIN_FILENO;
+ fds[0].events = POLLIN;
+
+ /* Inotify input */
+
+ fds[1].fd = fd;
+ fds[1].events = POLLIN;
+
+ /* Wait for events and/or terminal input */
+
+ printf("Listening for events.\en");
+ while (1) {
+ poll_num = poll(fds, nfds, \-1);
+ if (poll_num == \-1) {
+ if (errno == EINTR)
+ continue;
+ perror("poll");
+ exit(EXIT_FAILURE);
+ }
+
+ if (poll_num > 0) {
+
+ if (fds[0].revents & POLLIN) {
+
+ /* Console input is available. Empty stdin and quit */
+
+ while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\en')
+ continue;
+ break;
+ }
+
+ if (fds[1].revents & POLLIN) {
+
+ /* Inotify events are available */
+
+ handle_events(fd, wd, argc, argv);
+ }
+ }
+ }
+
+ printf("Listening for events stopped.\en");
+
+ /* Close inotify file descriptor */
+
+ close(fd);
+
+ free(wd);
+ exit(EXIT_SUCCESS);
+}
+.fi