~lefteris-nikoltsios/+junk/samba-lp1016895

« back to all changes in this revision

Viewing changes to source3/lib/events.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
*/
20
20
 
21
21
#include "includes.h"
22
 
#include <tevent_internal.h>
23
 
 
24
 
void event_fd_set_writeable(struct tevent_fd *fde)
25
 
{
26
 
        TEVENT_FD_WRITEABLE(fde);
27
 
}
28
 
 
29
 
void event_fd_set_not_writeable(struct tevent_fd *fde)
30
 
{
31
 
        TEVENT_FD_NOT_WRITEABLE(fde);
32
 
}
33
 
 
34
 
void event_fd_set_readable(struct tevent_fd *fde)
35
 
{
36
 
        TEVENT_FD_READABLE(fde);
37
 
}
38
 
 
39
 
void event_fd_set_not_readable(struct tevent_fd *fde)
40
 
{
41
 
        TEVENT_FD_NOT_READABLE(fde);
42
 
}
43
 
 
44
 
/*
45
 
 * Return if there's something in the queue
46
 
 */
47
 
 
48
 
bool event_add_to_select_args(struct tevent_context *ev,
49
 
                              const struct timeval *now,
50
 
                              fd_set *read_fds, fd_set *write_fds,
51
 
                              struct timeval *timeout, int *maxfd)
52
 
{
53
 
        struct tevent_fd *fde;
54
 
        struct timeval diff;
55
 
        bool ret = false;
 
22
#include "lib/tevent/tevent_internal.h"
 
23
#include "../lib/util/select.h"
 
24
#include "system/select.h"
 
25
 
 
26
struct tevent_poll_private {
 
27
        /*
 
28
         * Index from file descriptor into the pollfd array
 
29
         */
 
30
        int *pollfd_idx;
 
31
 
 
32
        /*
 
33
         * Cache for s3_event_loop_once to avoid reallocs
 
34
         */
 
35
        struct pollfd *pfds;
 
36
};
 
37
 
 
38
static struct tevent_poll_private *tevent_get_poll_private(
 
39
        struct tevent_context *ev)
 
40
{
 
41
        struct tevent_poll_private *state;
 
42
 
 
43
        state = (struct tevent_poll_private *)ev->additional_data;
 
44
        if (state == NULL) {
 
45
                state = TALLOC_ZERO_P(ev, struct tevent_poll_private);
 
46
                ev->additional_data = (void *)state;
 
47
                if (state == NULL) {
 
48
                        DEBUG(10, ("talloc failed\n"));
 
49
                }
 
50
        }
 
51
        return state;
 
52
}
 
53
 
 
54
static void count_fds(struct tevent_context *ev,
 
55
                      int *pnum_fds, int *pmax_fd)
 
56
{
 
57
        struct tevent_fd *fde;
 
58
        int num_fds = 0;
 
59
        int max_fd = 0;
 
60
 
 
61
        for (fde = ev->fd_events; fde != NULL; fde = fde->next) {
 
62
                if (fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE)) {
 
63
                        num_fds += 1;
 
64
                        if (fde->fd > max_fd) {
 
65
                                max_fd = fde->fd;
 
66
                        }
 
67
                }
 
68
        }
 
69
        *pnum_fds = num_fds;
 
70
        *pmax_fd = max_fd;
 
71
}
 
72
 
 
73
bool event_add_to_poll_args(struct tevent_context *ev, TALLOC_CTX *mem_ctx,
 
74
                            struct pollfd **pfds, int *pnum_pfds,
 
75
                            int *ptimeout)
 
76
{
 
77
        struct tevent_poll_private *state;
 
78
        struct tevent_fd *fde;
 
79
        int i, num_fds, max_fd, num_pollfds, idx_len;
 
80
        struct pollfd *fds;
 
81
        struct timeval now, diff;
 
82
        int timeout;
 
83
 
 
84
        state = tevent_get_poll_private(ev);
 
85
        if (state == NULL) {
 
86
                return false;
 
87
        }
 
88
        count_fds(ev, &num_fds, &max_fd);
 
89
 
 
90
        idx_len = max_fd+1;
 
91
 
 
92
        if (talloc_array_length(state->pollfd_idx) < idx_len) {
 
93
                state->pollfd_idx = TALLOC_REALLOC_ARRAY(
 
94
                        state, state->pollfd_idx, int, idx_len);
 
95
                if (state->pollfd_idx == NULL) {
 
96
                        DEBUG(10, ("talloc_realloc failed\n"));
 
97
                        return false;
 
98
                }
 
99
        }
 
100
 
 
101
        fds = *pfds;
 
102
        num_pollfds = *pnum_pfds;
 
103
 
 
104
        /*
 
105
         * The +1 is for the sys_poll calling convention. It expects
 
106
         * an array 1 longer for the signal pipe
 
107
         */
 
108
 
 
109
        if (talloc_array_length(fds) < num_pollfds + num_fds + 1) {
 
110
                fds = TALLOC_REALLOC_ARRAY(mem_ctx, fds, struct pollfd,
 
111
                                           num_pollfds + num_fds + 1);
 
112
                if (fds == NULL) {
 
113
                        DEBUG(10, ("talloc_realloc failed\n"));
 
114
                        return false;
 
115
                }
 
116
        }
 
117
 
 
118
        memset(&fds[num_pollfds], 0, sizeof(struct pollfd) * num_fds);
 
119
 
 
120
        /*
 
121
         * This needs tuning. We need to cope with multiple fde's for a file
 
122
         * descriptor. The problem is that we need to re-use pollfd_idx across
 
123
         * calls for efficiency. One way would be a direct bitmask that might
 
124
         * be initialized quicker, but our bitmap_init implementation is
 
125
         * pretty heavy-weight as well.
 
126
         */
 
127
        for (i=0; i<idx_len; i++) {
 
128
                state->pollfd_idx[i] = -1;
 
129
        }
56
130
 
57
131
        for (fde = ev->fd_events; fde; fde = fde->next) {
58
 
                if (fde->fd < 0 || fde->fd >= FD_SETSIZE) {
59
 
                        /* We ignore here, as it shouldn't be
60
 
                           possible to add an invalid fde->fd
61
 
                           but we don't want FD_SET to see an
62
 
                           invalid fd. */
 
132
                struct pollfd *pfd;
 
133
 
 
134
                if ((fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE)) == 0) {
63
135
                        continue;
64
136
                }
65
137
 
 
138
                if (state->pollfd_idx[fde->fd] == -1) {
 
139
                        /*
 
140
                         * We haven't seen this fd yet. Allocate a new pollfd.
 
141
                         */
 
142
                        state->pollfd_idx[fde->fd] = num_pollfds;
 
143
                        pfd = &fds[num_pollfds];
 
144
                        num_pollfds += 1;
 
145
                } else {
 
146
                        /*
 
147
                         * We have already seen this fd. OR in the flags.
 
148
                         */
 
149
                        pfd = &fds[state->pollfd_idx[fde->fd]];
 
150
                }
 
151
 
 
152
                pfd->fd = fde->fd;
 
153
 
66
154
                if (fde->flags & EVENT_FD_READ) {
67
 
                        FD_SET(fde->fd, read_fds);
68
 
                        ret = true;
 
155
                        pfd->events |= (POLLIN|POLLHUP);
69
156
                }
70
157
                if (fde->flags & EVENT_FD_WRITE) {
71
 
                        FD_SET(fde->fd, write_fds);
72
 
                        ret = true;
73
 
                }
74
 
 
75
 
                if ((fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE))
76
 
                    && (fde->fd > *maxfd)) {
77
 
                        *maxfd = fde->fd;
 
158
                        pfd->events |= POLLOUT;
78
159
                }
79
160
        }
 
161
        *pfds = fds;
 
162
        *pnum_pfds = num_pollfds;
80
163
 
81
164
        if (ev->immediate_events != NULL) {
82
 
                *timeout = timeval_zero();
 
165
                *ptimeout = 0;
83
166
                return true;
84
167
        }
85
 
 
86
168
        if (ev->timer_events == NULL) {
87
 
                return ret;
88
 
        }
89
 
 
90
 
        diff = timeval_until(now, &ev->timer_events->next_event);
91
 
        *timeout = timeval_min(timeout, &diff);
 
169
                *ptimeout = MIN(*ptimeout, INT_MAX);
 
170
                return true;
 
171
        }
 
172
 
 
173
        now = timeval_current();
 
174
        diff = timeval_until(&now, &ev->timer_events->next_event);
 
175
        timeout = timeval_to_msec(diff);
 
176
 
 
177
        if (timeout < *ptimeout) {
 
178
                *ptimeout = timeout;
 
179
        }
92
180
 
93
181
        return true;
94
182
}
95
183
 
96
 
bool run_events(struct tevent_context *ev,
97
 
                int selrtn, fd_set *read_fds, fd_set *write_fds)
 
184
bool run_events_poll(struct tevent_context *ev, int pollrtn,
 
185
                     struct pollfd *pfds, int num_pfds)
98
186
{
 
187
        struct tevent_poll_private *state;
 
188
        int *pollfd_idx;
99
189
        struct tevent_fd *fde;
100
190
        struct timeval now;
101
191
 
139
229
                return true;
140
230
        }
141
231
 
142
 
        if (selrtn <= 0) {
 
232
        if (pollrtn <= 0) {
143
233
                /*
144
234
                 * No fd ready
145
235
                 */
146
236
                return false;
147
237
        }
148
238
 
 
239
        state = (struct tevent_poll_private *)ev->additional_data;
 
240
        pollfd_idx = state->pollfd_idx;
 
241
 
149
242
        for (fde = ev->fd_events; fde; fde = fde->next) {
 
243
                struct pollfd *pfd;
150
244
                uint16 flags = 0;
151
245
 
152
 
                if (FD_ISSET(fde->fd, read_fds)) flags |= EVENT_FD_READ;
153
 
                if (FD_ISSET(fde->fd, write_fds)) flags |= EVENT_FD_WRITE;
154
 
 
 
246
                if ((fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE)) == 0) {
 
247
                        continue;
 
248
                }
 
249
 
 
250
                if (pollfd_idx[fde->fd] >= num_pfds) {
 
251
                        DEBUG(1, ("internal error: pollfd_idx[fde->fd] (%d) "
 
252
                                  ">= num_pfds (%d)\n", pollfd_idx[fde->fd],
 
253
                                  num_pfds));
 
254
                        return false;
 
255
                }
 
256
                pfd = &pfds[pollfd_idx[fde->fd]];
 
257
 
 
258
                if (pfd->fd != fde->fd) {
 
259
                        DEBUG(1, ("internal error: pfd->fd (%d) "
 
260
                                  "!= fde->fd (%d)\n", pollfd_idx[fde->fd],
 
261
                                  num_pfds));
 
262
                        return false;
 
263
                }
 
264
 
 
265
                if (pfd->revents & (POLLHUP|POLLERR)) {
 
266
                        /* If we only wait for EVENT_FD_WRITE, we
 
267
                           should not tell the event handler about it,
 
268
                           and remove the writable flag, as we only
 
269
                           report errors when waiting for read events
 
270
                           to match the select behavior. */
 
271
                        if (!(fde->flags & EVENT_FD_READ)) {
 
272
                                EVENT_FD_NOT_WRITEABLE(fde);
 
273
                                continue;
 
274
                        }
 
275
                        flags |= EVENT_FD_READ;
 
276
                }
 
277
 
 
278
                if (pfd->revents & POLLIN) {
 
279
                        flags |= EVENT_FD_READ;
 
280
                }
 
281
                if (pfd->revents & POLLOUT) {
 
282
                        flags |= EVENT_FD_WRITE;
 
283
                }
155
284
                if (flags & fde->flags) {
156
 
                        DLIST_DEMOTE(ev->fd_events, fde, struct tevent_fd *);
 
285
                        DLIST_DEMOTE(ev->fd_events, fde, struct tevent_fd);
157
286
                        fde->handler(ev, fde, flags, fde->private_data);
158
287
                        return true;
159
288
                }
162
291
        return false;
163
292
}
164
293
 
165
 
 
166
294
struct timeval *get_timed_events_timeout(struct tevent_context *ev,
167
295
                                         struct timeval *to_ret)
168
296
{
187
315
 
188
316
static int s3_event_loop_once(struct tevent_context *ev, const char *location)
189
317
{
190
 
        struct timeval now, to;
191
 
        fd_set r_fds, w_fds;
192
 
        int maxfd = 0;
 
318
        struct tevent_poll_private *state;
 
319
        int timeout;
 
320
        int num_pfds;
193
321
        int ret;
194
322
 
195
 
        FD_ZERO(&r_fds);
196
 
        FD_ZERO(&w_fds);
197
 
 
198
 
        to.tv_sec = 9999;       /* Max timeout */
199
 
        to.tv_usec = 0;
200
 
 
201
 
        if (run_events(ev, 0, NULL, NULL)) {
 
323
        timeout = INT_MAX;
 
324
 
 
325
        state = tevent_get_poll_private(ev);
 
326
        if (state == NULL) {
 
327
                errno = ENOMEM;
 
328
                return -1;
 
329
        }
 
330
 
 
331
        if (run_events_poll(ev, 0, NULL, 0)) {
202
332
                return 0;
203
333
        }
204
334
 
205
 
        GetTimeOfDay(&now);
206
 
 
207
 
        if (!event_add_to_select_args(ev, &now, &r_fds, &w_fds, &to, &maxfd)) {
 
335
        num_pfds = 0;
 
336
        if (!event_add_to_poll_args(ev, state,
 
337
                                    &state->pfds, &num_pfds, &timeout)) {
208
338
                return -1;
209
339
        }
210
340
 
211
 
        ret = sys_select(maxfd+1, &r_fds, &w_fds, NULL, &to);
212
 
 
 
341
        ret = sys_poll(state->pfds, num_pfds, timeout);
213
342
        if (ret == -1 && errno != EINTR) {
214
343
                tevent_debug(ev, TEVENT_DEBUG_FATAL,
215
 
                             "sys_select() failed: %d:%s\n",
 
344
                             "poll() failed: %d:%s\n",
216
345
                             errno, strerror(errno));
217
346
                return -1;
218
347
        }
219
348
 
220
 
        run_events(ev, ret, &r_fds, &w_fds);
 
349
        run_events_poll(ev, ret, state->pfds, num_pfds);
221
350
        return 0;
222
351
}
223
352
 
224
 
void event_context_reinit(struct tevent_context *ev)
225
 
{
226
 
        tevent_common_context_destructor(ev);
227
 
        return;
228
 
}
229
 
 
230
353
static int s3_event_context_init(struct tevent_context *ev)
231
354
{
232
355
        return 0;