Mercurial > dovecot > original-hg > dovecot-1.2
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 |