comparison src/lib/ioloop-notify-dn.c @ 1729:5bf22d6bb65e HEAD

Added IO_DIR_NOTIFY and IO_FILE_NOTIFY conditions to io_add(). IO_DIR_NOTIFY is now implemented for Linux dnotify.
author Timo Sirainen <tss@iki.fi>
date Sun, 24 Aug 2003 15:43:53 +0300
parents
children 69f1ba731c84
comparison
equal deleted inserted replaced
1728:d1a6d9d24bd9 1729:5bf22d6bb65e
1 /* Copyright (C) 2003 Timo Sirainen */
2
3 /* Logic is pretty much based on dnotify by Oskar Liljeblad. */
4
5 #define _GNU_SOURCE
6 #include "lib.h"
7
8 #ifdef IOLOOP_NOTIFY_DNOTIFY
9
10 #include "ioloop-internal.h"
11 #include "write-full.h"
12
13 #include <signal.h>
14 #include <unistd.h>
15 #include <fcntl.h>
16
17 static int event_pipe[2] = { -1, -1 };
18
19 static void sigrt_handler(int signo __attr_unused__, siginfo_t *si,
20 void *data __attr_unused__)
21 {
22 if (write_full(event_pipe[1], &si->si_fd, sizeof(int)) < 0)
23 i_fatal("write_full(event_pipe) failed: %m");
24 }
25
26 static void event_callback(void *context)
27 {
28 struct ioloop *ioloop = context;
29 struct io *io;
30 int fd, ret;
31
32 ret = read(event_pipe[0], &fd, sizeof(fd));
33 if (ret < 0)
34 i_fatal("read(event_pipe) failed: %m");
35 if (ret != sizeof(fd))
36 i_fatal("read(event_pipe) returned %d != %d", ret, sizeof(fd));
37
38 if (gettimeofday(&ioloop_timeval, &ioloop_timezone) < 0)
39 i_fatal("gettimeofday(): %m");
40 ioloop_time = ioloop_timeval.tv_sec;
41
42 for (io = ioloop->notifys; io != NULL; io = io->next) {
43 if (io->fd == fd) {
44 io->callback(io->context);
45 break;
46 }
47 }
48 }
49
50 static int dn_init(void)
51 {
52 struct sigaction act;
53
54 if (pipe(event_pipe) < 0) {
55 i_error("pipe() failed: %m");
56 return FALSE;
57 }
58
59 act.sa_sigaction = sigrt_handler;
60 sigemptyset(&act.sa_mask);
61 act.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;
62
63 if (sigaction(SIGRTMIN, &act, NULL) < 0) {
64 i_error("sigaction(SIGRTMIN) failed: %m");
65 close(event_pipe[0]);
66 close(event_pipe[1]);
67 return FALSE;
68 }
69
70 return TRUE;
71 }
72
73 struct io *io_loop_notify_add(struct ioloop *ioloop, int fd,
74 enum io_condition condition,
75 io_callback_t *callback, void *context)
76 {
77 struct io *io;
78
79 if ((condition & IO_FILE_NOTIFY) != 0)
80 return NULL;
81
82 if (event_pipe[0] == -1) {
83 if (!dn_init())
84 return NULL;
85 }
86 if (ioloop->event_io == NULL) {
87 ioloop->event_io =
88 io_add(event_pipe[0], IO_READ, event_callback, ioloop);
89 }
90
91 if (fcntl(fd, F_SETSIG, SIGRTMIN) < 0) {
92 i_error("fcntl(F_SETSIG) failed: %m");
93 return FALSE;
94 }
95 if (fcntl(fd, F_NOTIFY, DN_CREATE | DN_DELETE | DN_RENAME |
96 DN_MULTISHOT) < 0) {
97 i_error("fcntl(F_NOTIFY) failed: %m");
98 (void)fcntl(fd, F_SETSIG, 0);
99 return FALSE;
100 }
101
102 io = p_new(ioloop->pool, struct io, 1);
103 io->fd = fd;
104 io->condition = condition;
105
106 io->callback = callback;
107 io->context = context;
108
109 io->next = ioloop->notifys;
110 ioloop->notifys = io;
111 return io;
112 }
113
114 void io_loop_notify_remove(struct ioloop *ioloop, struct io *io)
115 {
116 struct io **io_p;
117
118 for (io_p = &ioloop->notifys; *io_p != NULL; io_p = &(*io_p)->next) {
119 if (*io_p == io) {
120 *io_p = io->next;
121 break;
122 }
123 }
124
125 if (fcntl(io->fd, F_SETSIG, 0) < 0)
126 i_error("fcntl(F_SETSIG, 0) failed: %m");
127 if (fcntl(io->fd, F_NOTIFY, 0) < 0)
128 i_error("fcntl(F_NOTIFY, 0) failed: %m");
129
130 p_free(ioloop->pool, io);
131
132 if (ioloop->notifys == NULL) {
133 io_remove(ioloop->event_io);
134 ioloop->event_io = NULL;
135 }
136 }
137
138 #endif