~ubuntu-branches/ubuntu/utopic/nss-pam-ldapd/utopic-proposed

« back to all changes in this revision

Viewing changes to common/tio.c

  • Committer: Package Import Robot
  • Author(s): Arthur de Jong
  • Date: 2012-10-14 23:00:00 UTC
  • Revision ID: package-import@ubuntu.com-20121014230000-tn63bv35wlebv45a
Tags: 0.8.10-3
* fix a problem in sed logic for commenting out disabled options
  (closes: #689296)
* support "EXTERNAL" SASL mechanism in debconf configuration (LP: #1063923)
  (the debconf template has been postponed to avoid having to update all
  translations for a relatively minor change)
* 01-use-poll-instead-of-select.patch: use poll() instead of select()
  for checking file descriptor activity to also correctly work if more
  than FD_SETSIZE files are already open (closes: #690319)

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#include <signal.h>
36
36
#include <stdio.h>
37
37
#include <limits.h>
 
38
#include <poll.h>
38
39
 
39
40
#include "tio.h"
40
41
 
63
64
  int fd;
64
65
  struct tio_buffer readbuffer;
65
66
  struct tio_buffer writebuffer;
66
 
  struct timeval readtimeout;
67
 
  struct timeval writetimeout;
 
67
  int readtimeout;
 
68
  int writetimeout;
68
69
  int read_resettable; /* whether the tio_reset() function can be called */
69
70
#ifdef DEBUG_TIO_STATS
70
71
  /* this is used to collect statistics on the use of the streams
74
75
#endif /* DEBUG_TIO_STATS */
75
76
};
76
77
 
77
 
/* add the second timeval to the first modifing the first */
78
 
static inline void tio_tv_add(struct timeval *tv1, const struct timeval *tv2)
79
 
{
80
 
  /* BUG: we hope that this does not overflow */
81
 
  tv1->tv_usec+=tv2->tv_usec;
82
 
  if (tv1->tv_usec>=1000000)
83
 
  {
84
 
    tv1->tv_usec-=1000000;
85
 
    tv1->tv_sec+=1;
86
 
  }
87
 
  tv1->tv_sec+=tv2->tv_sec;
88
 
}
89
 
 
90
78
/* build a timeval for comparison to when the operation should be finished */
91
 
static inline void tio_tv_prepare(struct timeval *deadline, const struct timeval *timeout)
 
79
static inline void tio_get_deadline(struct timeval *deadline,int timeout)
92
80
{
93
81
  if (gettimeofday(deadline,NULL))
94
82
  {
97
85
    deadline->tv_usec=0;
98
86
    return;
99
87
  }
100
 
  tio_tv_add(deadline,timeout);
 
88
  deadline->tv_sec+=timeout/1000;
 
89
  deadline->tv_sec+=(timeout%1000)*1000;
101
90
}
102
91
 
103
 
/* update the timeval to the value that is remaining before deadline
 
92
/* update the timeout to the value that is remaining before deadline
104
93
   returns non-zero if there is no more time before the deadline */
105
 
static inline int tio_tv_remaining(struct timeval *tv, const struct timeval *deadline)
 
94
static inline int tio_time_remaining(const struct timeval *deadline)
106
95
{
 
96
  struct timeval tv;
107
97
  /* get the current time */
108
 
  if (gettimeofday(tv,NULL))
 
98
  if (gettimeofday(&tv,NULL))
109
99
  {
110
100
    /* 1 second default if gettimeofday() is broken */
111
 
    tv->tv_sec=1;
112
 
    tv->tv_usec=0;
113
 
    return 0;
114
 
  }
115
 
  /* check if we're too late */
116
 
  if ( (tv->tv_sec>deadline->tv_sec) ||
117
 
       ( (tv->tv_sec==deadline->tv_sec) && (tv->tv_usec>deadline->tv_usec) ) )
118
 
    return -1;
119
 
  /* update tv */
120
 
  tv->tv_sec=deadline->tv_sec-tv->tv_sec;
121
 
  if (tv->tv_usec<=deadline->tv_usec)
122
 
    tv->tv_usec=deadline->tv_usec-tv->tv_usec;
123
 
  else
124
 
  {
125
 
    tv->tv_sec--;
126
 
    tv->tv_usec=1000000+deadline->tv_usec-tv->tv_usec;
127
 
  }
128
 
  return 0;
 
101
    return 1000;
 
102
  }
 
103
  /* calculate time remaining in miliseconds */
 
104
  return (deadline->tv_sec-tv.tv_sec)*1000 + (deadline->tv_usec-tv.tv_usec)/1000;
129
105
}
130
106
 
131
107
/* open a new TFILE based on the file descriptor */
132
 
TFILE *tio_fdopen(int fd,struct timeval *readtimeout,struct timeval *writetimeout,
 
108
TFILE *tio_fdopen(int fd,int readtimeout,int writetimeout,
133
109
                  size_t initreadsize,size_t maxreadsize,
134
110
                  size_t initwritesize,size_t maxwritesize)
135
111
{
162
138
  fp->writebuffer.start=0;
163
139
  fp->writebuffer.len=0;
164
140
  /* initialize other attributes */
165
 
  fp->readtimeout.tv_sec=readtimeout->tv_sec;
166
 
  fp->readtimeout.tv_usec=readtimeout->tv_usec;
167
 
  fp->writetimeout.tv_sec=writetimeout->tv_sec;
168
 
  fp->writetimeout.tv_usec=writetimeout->tv_usec;
 
141
  fp->readtimeout=readtimeout;
 
142
  fp->writetimeout=writetimeout;
169
143
  fp->read_resettable=0;
170
144
#ifdef DEBUG_TIO_STATS
171
145
  fp->byteswritten=0;
176
150
 
177
151
/* wait for any activity on the specified file descriptor using
178
152
   the specified deadline */
179
 
static int tio_select(TFILE *fp, int readfd, const struct timeval *deadline)
 
153
static int tio_wait(TFILE *fp,int readfd,const struct timeval *deadline)
180
154
{
181
 
  struct timeval tv;
182
 
  fd_set fdset;
 
155
  int timeout;
 
156
  struct pollfd fds[1];
183
157
  int rv;
184
158
  while (1)
185
159
  {
186
 
    /* prepare our filedescriptorset */
187
 
    FD_ZERO(&fdset);
188
 
    FD_SET(fp->fd,&fdset);
189
160
    /* figure out the time we need to wait */
190
 
    if (tio_tv_remaining(&tv,deadline))
 
161
    if ((timeout=tio_time_remaining(deadline))<0)
191
162
    {
192
163
      errno=ETIME;
193
164
      return -1;
195
166
    /* wait for activity */
196
167
    if (readfd)
197
168
    {
 
169
      fds[0].fd=fp->fd;
 
170
      fds[0].events=POLLIN;
198
171
      /* santiy check for moving clock */
199
 
      if (tv.tv_sec>fp->readtimeout.tv_sec)
200
 
        tv.tv_sec=fp->readtimeout.tv_sec;
201
 
      rv=select(FD_SETSIZE,&fdset,NULL,NULL,&tv);
 
172
      if (timeout>fp->readtimeout)
 
173
        timeout=fp->readtimeout;
202
174
    }
203
175
    else
204
176
    {
 
177
      fds[0].fd=fp->fd;
 
178
      fds[0].events=POLLOUT;
205
179
      /* santiy check for moving clock */
206
 
      if (tv.tv_sec>fp->writetimeout.tv_sec)
207
 
        tv.tv_sec=fp->writetimeout.tv_sec;
208
 
      rv=select(FD_SETSIZE,NULL,&fdset,NULL,&tv);
 
180
      if (timeout>fp->writetimeout)
 
181
        timeout=fp->writetimeout;
209
182
    }
 
183
    rv=poll(fds,1,timeout);
210
184
    if (rv>0)
211
185
      return 0; /* we have activity */
212
186
    else if (rv==0)
234
208
  /* have a more convenient storage type for the buffer */
235
209
  uint8_t *ptr=(uint8_t *)buf;
236
210
  /* build a time by which we should be finished */
237
 
  tio_tv_prepare(&deadline,&(fp->readtimeout));
 
211
  tio_get_deadline(&deadline,fp->readtimeout);
238
212
  /* loop until we have returned all the needed data */
239
213
  while (1)
240
214
  {
292
266
      }
293
267
    }
294
268
    /* wait until we have input */
295
 
    if (tio_select(fp,1,&deadline))
 
269
    if (tio_wait(fp,1,&deadline))
296
270
      return -1;
297
271
    /* read the input in the buffer */
298
272
    len=fp->readbuffer.size-fp->readbuffer.start;
326
300
/* Read all available data from the stream and empty the read buffer. */
327
301
int tio_skipall(TFILE *fp)
328
302
{
329
 
  struct timeval tv;
330
 
  fd_set fdset;
 
303
  struct pollfd fds[1];
331
304
  int rv;
332
305
  size_t len;
333
306
  /* clear the read buffer */
342
315
#endif /* SSIZE_MAX */
343
316
  while (1)
344
317
  {
345
 
    /* prepare our file descriptor set */
346
 
    FD_ZERO(&fdset);
347
 
    FD_SET(fp->fd,&fdset);
348
 
    /* prepare the time to wait */
349
 
    tv.tv_sec=0;
350
 
    tv.tv_usec=0;
351
318
    /* see if any data is available */
352
 
    rv=select(FD_SETSIZE,&fdset,NULL,NULL,&tv);
 
319
    fds[0].fd=fp->fd;
 
320
    fds[0].events=POLLIN;
 
321
    rv=poll(fds,1,0);
 
322
    /* check the poll() result */
353
323
    if (rv==0)
354
324
      return 0; /* no file descriptor ready */
355
325
    if ((rv<0)&&((errno==EINTR)||(errno==EAGAIN)))
424
394
{
425
395
  struct timeval deadline;
426
396
  /* build a time by which we should be finished */
427
 
  tio_tv_prepare(&deadline,&(fp->writetimeout));
 
397
  tio_get_deadline(&deadline,fp->writetimeout);
428
398
  /* loop until we have written our buffer */
429
399
  while (fp->writebuffer.len > 0)
430
400
  {
431
401
    /* wait until we can write */
432
 
    if (tio_select(fp,0,&deadline))
 
402
    if (tio_wait(fp,0,&deadline))
433
403
      return -1;
434
404
    /* write one block */
435
405
    if (tio_writebuf(fp))
442
412
   will accept data */
443
413
static int tio_flush_nonblock(TFILE *fp)
444
414
{
445
 
  struct timeval tv;
446
 
  fd_set fdset;
 
415
  struct pollfd fds[1];
447
416
  int rv;
448
 
  /* prepare our filedescriptorset */
449
 
  FD_ZERO(&fdset);
450
 
  FD_SET(fp->fd,&fdset);
451
 
  /* set the timeout to 0 to poll */
452
 
  tv.tv_sec=0;
453
 
  tv.tv_usec=0;
454
417
  /* wait for activity */
455
 
  rv=select(FD_SETSIZE,NULL,&fdset,NULL,&tv);
 
418
  fds[0].fd=fp->fd;
 
419
  fds[0].events=POLLOUT;
 
420
  rv=poll(fds,1,0);
456
421
  /* check if any file descriptors were ready (timeout) or we were
457
422
     interrupted */
458
423
  if ((rv==0)||((rv<0)&&(errno==EINTR)))