~ubuntu-branches/debian/wheezy/netatalk/wheezy

« back to all changes in this revision

Viewing changes to libatalk/dsi/dsi_stream.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2011-06-05 21:04:21 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20110605210421-19gag2srevj0ocxh
Tags: 2.2~beta4-1
* New upstream release.
  + Fixes "Internal Error" after ad_open on sparc.
    Closes: bug#606005. Thanks to Alfredo Sola.
* Adjust references to unofficial packages in README.Debian.
* Use dversionmangle (not uversionmangle) in watch file. Fix add
  leading dash (-) to upstream version in mangling.
* Update patches:
  + Drop patches 107 and 294 (Zeroconf support): Implemented
    (differently) upstream now.
  + Drop patches 109 and 112 (avoid broken XFS linkage) obsolete.
  + Drop patch 200 (hostname resolving): adopted upstream.
  + Refresh patch 205.
* Rewrite copyright file using draft 174 of DEP-5 format.
* Build-depend on and recommend unversioned (i.e. default) BerkeleyDB
  packages.
  Closes: bug#621413. Thanks to Ondřej Surý.
  Simplify suggestions on older versioned BerkeleyDB packages.
* Stop installing some documentation dropped upstream, and let CDBS
  automagically handle some of the remains.
* Update control file:
  + Bump policy compliance to standards-version 3.9.2.
  + Shorten Vcs-* URLs.
* Add patches 115 and (for automade file) 214 to avoid installing
  unneeded /default dir.
  Closes: bug#628119. Thanks to Russell Muetzelfeldt and Luk Claes.
* Don't ship .la files. Closes: bug#621849. Thanks to Andreas Metzler
  and Luk Claes.
* Stop renaming afile and achfile, dropped upstream.
* Explicitly enable DDP (AppleTalk), now disabled by default.
* Enable Zeroconf, should be stable now.
* Simplify package relations:
  + Drop (build-)dependency fallback unneeded even for oldstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * $Id: dsi_stream.c,v 1.20 2009-10-26 12:35:56 franklahm Exp $
3
 
 *
4
2
 * Copyright (c) 1998 Adrian Sun (asun@zoology.washington.edu)
5
3
 * All rights reserved. See COPYRIGHT.
6
4
 *
15
13
#include "config.h"
16
14
#endif /* HAVE_CONFIG_H */
17
15
 
18
 
#define USE_WRITEV
19
 
 
20
16
#include <stdio.h>
21
17
#include <stdlib.h>
22
18
 
28
24
#include <errno.h>
29
25
#include <sys/types.h>
30
26
#include <sys/socket.h>
31
 
 
32
 
#ifdef USE_WRITEV
33
27
#include <sys/uio.h>
34
 
#endif
35
28
 
36
29
#include <atalk/logger.h>
37
30
#include <atalk/dsi.h>
48
41
#define MSG_DONTWAIT 0x40
49
42
#endif
50
43
 
51
 
/* ------------------------- 
52
 
 * we don't use a circular buffer.
53
 
*/
54
 
static void dsi_init_buffer(DSI *dsi)
55
 
{
56
 
    if (!dsi->buffer) {
57
 
        /* XXX config options */
58
 
        dsi->maxsize = 6 * dsi->server_quantum;
59
 
        if (!dsi->maxsize)
60
 
            dsi->maxsize = 6 * DSI_SERVQUANT_DEF;
61
 
        dsi->buffer = malloc(dsi->maxsize);
62
 
        if (!dsi->buffer) {
63
 
            return;
64
 
        }
65
 
        dsi->start = dsi->buffer;
66
 
        dsi->eof = dsi->buffer;
67
 
        dsi->end = dsi->buffer + dsi->maxsize;
68
 
    }
69
 
}
70
 
 
71
 
/* ---------------------- 
72
 
   afpd is sleeping too much while trying to send something.
73
 
   May be there's no reader or the reader is also sleeping in write,
74
 
   look if there's some data for us to read, hopefully it will wake up
75
 
   the reader so we can write again.
76
 
*/
 
44
/*
 
45
 * afpd is sleeping too much while trying to send something.
 
46
 * May be there's no reader or the reader is also sleeping in write,
 
47
 * look if there's some data for us to read, hopefully it will wake up
 
48
 * the reader so we can write again.
 
49
 *
 
50
 * @returns 0 when is possible to send again, -1 on error
 
51
 */
77
52
static int dsi_peek(DSI *dsi)
78
53
{
 
54
    static int warned = 0;
79
55
    fd_set readfds, writefds;
80
56
    int    len;
81
57
    int    maxfd;
82
58
    int    ret;
83
59
 
84
 
    FD_ZERO(&readfds);
85
 
    FD_ZERO(&writefds);
86
 
    FD_SET( dsi->socket, &readfds);
87
 
    FD_SET( dsi->socket, &writefds);
88
 
    maxfd = dsi->socket +1;
 
60
    LOG(log_debug, logtype_dsi, "dsi_peek");
 
61
 
 
62
    maxfd = dsi->socket + 1;
89
63
 
90
64
    while (1) {
91
 
        FD_SET( dsi->socket, &readfds);
 
65
        FD_ZERO(&readfds);
 
66
        FD_ZERO(&writefds);
 
67
 
 
68
        if (dsi->eof < dsi->end) {
 
69
            /* space in read buffer */
 
70
            FD_SET( dsi->socket, &readfds);
 
71
        } else {
 
72
            if (!warned) {
 
73
                warned = 1;
 
74
                LOG(log_note, logtype_dsi, "dsi_peek: readahead buffer is full, possibly increase -dsireadbuf option");
 
75
                LOG(log_note, logtype_dsi, "dsi_peek: dsireadbuf: %d, DSI quantum: %d, effective buffer size: %d",
 
76
                    dsi->dsireadbuf,
 
77
                    dsi->server_quantum ? dsi->server_quantum : DSI_SERVQUANT_DEF,
 
78
                    dsi->end - dsi->buffer);
 
79
            }
 
80
        }
 
81
 
92
82
        FD_SET( dsi->socket, &writefds);
93
83
 
94
84
        /* No timeout: if there's nothing to read nor nothing to write,
98
88
                /* we might have been interrupted by out timer, so restart select */
99
89
                continue;
100
90
            /* give up */
 
91
            LOG(log_error, logtype_dsi, "dsi_peek: unexpected select return: %d %s",
 
92
                ret, ret < 0 ? strerror(errno) : "");
 
93
            return -1;
 
94
        }
 
95
 
 
96
        if (FD_ISSET(dsi->socket, &writefds)) {
 
97
            /* we can write again */
 
98
            LOG(log_debug, logtype_dsi, "dsi_peek: can write again");
101
99
            break;
102
100
        }
103
101
 
104
102
        /* Check if there's sth to read, hopefully reading that will unblock the client */
105
103
        if (FD_ISSET(dsi->socket, &readfds)) {
106
 
            dsi_init_buffer(dsi);
107
 
            len = dsi->end - dsi->eof;
 
104
            len = dsi->end - dsi->eof; /* it's ensured above that there's space */
108
105
 
109
 
            if (len <= 0) {
110
 
                /* ouch, our buffer is full ! fall back to blocking IO 
111
 
                 * could block and disconnect but it's better than a cpu hog */
112
 
                break;
 
106
            if ((len = read(dsi->socket, dsi->eof, len)) <= 0) {
 
107
                if (len == 0) {
 
108
                    LOG(log_error, logtype_dsi, "dsi_peek: EOF");
 
109
                    return -1;
 
110
                }
 
111
                LOG(log_error, logtype_dsi, "dsi_peek: read: %s", strerror(errno));
 
112
                if (errno == EAGAIN)
 
113
                    continue;
 
114
                return -1;
113
115
            }
 
116
            LOG(log_debug, logtype_dsi, "dsi_peek: read %d bytes", len);
114
117
 
115
 
            len = read(dsi->socket, dsi->eof, len);
116
 
            if (len <= 0)
117
 
                break;
118
118
            dsi->eof += len;
119
119
        }
120
 
 
121
 
        if (FD_ISSET(dsi->socket, &writefds))
122
 
            /* we can write again at last */
123
 
            break;
124
120
    }
125
121
 
126
122
    return 0;
141
137
 
142
138
  LOG(log_maxdebug, logtype_dsi, "dsi_stream_write: sending %u bytes", length);
143
139
 
144
 
  /* non blocking mode */
145
 
  if (setnonblock(dsi->socket, 1) < 0) {
146
 
      LOG(log_error, logtype_dsi, "dsi_stream_write: setnonblock: %s", strerror(errno));
147
 
      return -1;
148
 
  }
149
 
 
150
140
  while (written < length) {
151
141
      len = send(dsi->socket, (u_int8_t *) data + written, length - written, flags);
152
142
      if (len >= 0) {
158
148
          continue;
159
149
 
160
150
      if (errno == EAGAIN || errno == EWOULDBLOCK) {
 
151
          LOG(log_debug, logtype_dsi, "dsi_stream_write: send: %s", strerror(errno));
 
152
 
161
153
          if (mode == DSI_NOWAIT && written == 0) {
162
154
              /* DSI_NOWAIT is used by attention give up in this case. */
163
155
              written = -1;
181
173
  dsi->write_count += written;
182
174
 
183
175
exit:
184
 
  if (setnonblock(dsi->socket, 0) < 0) {
185
 
      LOG(log_error, logtype_dsi, "dsi_stream_write: setnonblock: %s", strerror(errno));
186
 
      written = -1;
187
 
  }
188
 
 
189
176
  dsi->in_write--;
190
177
  return written;
191
178
}
199
186
  size_t written;
200
187
  ssize_t len;
201
188
 
 
189
  LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: sending %u bytes", length);
 
190
 
202
191
  dsi->in_write++;
203
192
  written = 0;
204
193
 
205
 
  /* non blocking mode */
206
 
  if (setnonblock(dsi->socket, 1) < 0) {
207
 
      LOG(log_error, logtype_dsi, "dsi_stream_read_file: setnonblock: %s", strerror(errno));
208
 
      return -1;
209
 
  }
210
 
 
211
194
  while (written < length) {
212
195
    len = sys_sendfile(dsi->socket, fromfd, &offset, length - written);
213
196
        
226
209
          }
227
210
          continue;
228
211
      }
229
 
      LOG(log_error, logtype_dsi, "dsi_stream_write: %s", strerror(errno));
 
212
      LOG(log_error, logtype_dsi, "dsi_stream_read_file: %s", strerror(errno));
230
213
      break;
231
214
    }
232
215
    else if (!len) {
238
221
        written += len;
239
222
  }
240
223
 
241
 
  if (setnonblock(dsi->socket, 0) < 0) {
242
 
      LOG(log_error, logtype_dsi, "dsi_stream_read_file: setnonblock: %s", strerror(errno));
243
 
      return -1;
244
 
  }
245
 
 
246
224
  dsi->write_count += written;
247
225
  dsi->in_write--;
248
226
  return written;
255
233
static size_t from_buf(DSI *dsi, u_int8_t *buf, size_t count)
256
234
{
257
235
    size_t nbe = 0;
 
236
 
 
237
    if (dsi->buffer == NULL)
 
238
        /* afpd master has no DSI buffering */
 
239
        return 0;
 
240
 
 
241
    LOG(log_maxdebug, logtype_dsi, "from_buf: %u bytes", count);
258
242
    
259
 
    if (dsi->start) {        
260
 
        nbe = dsi->eof - dsi->start;
261
 
 
262
 
        if (nbe > 0) {
263
 
           nbe = min((size_t)nbe, count);
264
 
           memcpy(buf, dsi->start, nbe);
265
 
           dsi->start += nbe;
266
 
 
267
 
           if (dsi->eof == dsi->start) 
268
 
               dsi->start = dsi->eof = dsi->buffer;
269
 
 
270
 
        }
 
243
    nbe = dsi->eof - dsi->start;
 
244
 
 
245
    if (nbe > 0) {
 
246
        nbe = min((size_t)nbe, count);
 
247
        memcpy(buf, dsi->start, nbe);
 
248
        dsi->start += nbe;
 
249
 
 
250
        if (dsi->eof == dsi->start)
 
251
            dsi->start = dsi->eof = dsi->buffer;
271
252
    }
 
253
 
 
254
    LOG(log_debug, logtype_dsi, "from_buf(read: %u, unread:%u , space left: %u): returning %u",
 
255
        dsi->start - dsi->buffer, dsi->eof - dsi->start, dsi->end - dsi->eof, nbe);
 
256
 
272
257
    return nbe;
273
258
}
274
259
 
282
267
 */
283
268
static ssize_t buf_read(DSI *dsi, u_int8_t *buf, size_t count)
284
269
{
285
 
    ssize_t nbe;
286
 
    
 
270
    ssize_t len;
 
271
 
 
272
    LOG(log_maxdebug, logtype_dsi, "buf_read(%u bytes)", count);
 
273
 
287
274
    if (!count)
288
275
        return 0;
289
276
 
290
 
    nbe = from_buf(dsi, buf, count); /* 1. */
291
 
    if (nbe)
292
 
        return nbe;             /* 2. */
 
277
    len = from_buf(dsi, buf, count); /* 1. */
 
278
    if (len)
 
279
        return len;             /* 2. */
293
280
  
294
 
    return read(dsi->socket, buf, count); /* 3. */
 
281
    len = readt(dsi->socket, buf, count, 0, 1); /* 3. */
 
282
 
 
283
    LOG(log_maxdebug, logtype_dsi, "buf_read(%u bytes): got: %d", count, len);
 
284
 
 
285
    return len;
295
286
}
296
287
 
297
288
/*
298
289
 * Essentially a loop around buf_read() to ensure "length" bytes are read
299
290
 * from dsi->buffer and/or the socket.
 
291
 *
 
292
 * @returns length on success, some value smaller then length indicates an error
300
293
 */
301
294
size_t dsi_stream_read(DSI *dsi, void *data, const size_t length)
302
295
{
303
296
  size_t stored;
304
297
  ssize_t len;
305
 
  
 
298
 
 
299
  LOG(log_maxdebug, logtype_dsi, "dsi_stream_read(%u bytes)", length);
 
300
 
306
301
  stored = 0;
307
302
  while (stored < length) {
308
 
    len = buf_read(dsi, (u_int8_t *) data + stored, length - stored);
309
 
    if (len == -1 && errno == EINTR)
310
 
      continue;
311
 
    else if (len > 0)
312
 
      stored += len;
313
 
    else { /* eof or error */
314
 
      /* don't log EOF error if it's just after connect (OSX 10.3 probe) */
315
 
      if (len || stored || dsi->read_count) {
316
 
          LOG(log_error, logtype_dsi, "dsi_stream_read(%d): %s", len, (len < 0)?strerror(errno):"unexpected EOF");
 
303
      len = buf_read(dsi, (u_int8_t *) data + stored, length - stored);
 
304
      if (len == -1 && (errno == EINTR || errno == EAGAIN)) {
 
305
          LOG(log_debug, logtype_dsi, "dsi_stream_read: select read loop");
 
306
          continue;
 
307
      } else if (len > 0) {
 
308
          stored += len;
 
309
      } else { /* eof or error */
 
310
          /* don't log EOF error if it's just after connect (OSX 10.3 probe) */
 
311
          if (len || stored || dsi->read_count) {
 
312
              if (! (dsi->flags & DSI_DISCONNECTED)) {
 
313
                  LOG(log_error, logtype_dsi, "dsi_stream_read: len:%d, %s",
 
314
                      len, (len < 0) ? strerror(errno) : "unexpected EOF");
 
315
              }
 
316
              return 0;
 
317
          }
 
318
          break;
317
319
      }
318
 
      break;
319
 
    }
320
320
  }
321
321
 
322
322
  dsi->read_count += stored;
 
323
 
 
324
  LOG(log_maxdebug, logtype_dsi, "dsi_stream_read(%u bytes): got: %u", length, stored);
323
325
  return stored;
324
326
}
325
327
 
331
333
{
332
334
  size_t len;
333
335
  size_t buflen;
 
336
 
 
337
  LOG(log_maxdebug, logtype_dsi, "dsi_buffered_stream_read: %u bytes", length);
334
338
  
335
 
  dsi_init_buffer(dsi);
336
339
  len = from_buf(dsi, data, length); /* read from buffer dsi->buffer */
337
340
  dsi->read_count += len;
338
341
  if (len == length) {          /* got enough bytes from there ? */
355
358
 
356
359
/* ---------------------------------------
357
360
*/
358
 
void dsi_sleep(DSI *dsi, const int state)
359
 
{
360
 
    dsi->asleep = state;
361
 
}
362
 
 
363
 
/* ---------------------------------------
364
 
*/
365
361
static void block_sig(DSI *dsi)
366
362
{
367
363
  dsi->in_write++;
381
377
int dsi_stream_send(DSI *dsi, void *buf, size_t length)
382
378
{
383
379
  char block[DSI_BLOCKSIZ];
384
 
#ifdef USE_WRITEV
385
380
  struct iovec iov[2];
386
381
  size_t towrite;
387
382
  ssize_t len;
388
 
#endif /* USE_WRITEV */
 
383
 
 
384
  LOG(log_maxdebug, logtype_dsi, "dsi_stream_send: %u bytes",
 
385
      length ? length : sizeof(block));
389
386
 
390
387
  block[0] = dsi->header.dsi_flags;
391
388
  block[1] = dsi->header.dsi_command;
403
400
  
404
401
  /* block signals */
405
402
  block_sig(dsi);
406
 
#ifdef USE_WRITEV
407
403
  iov[0].iov_base = block;
408
404
  iov[0].iov_len = sizeof(block);
409
405
  iov[1].iov_base = buf;
412
408
  towrite = sizeof(block) + length;
413
409
  dsi->write_count += towrite;
414
410
  while (towrite > 0) {
415
 
    if (((len = writev(dsi->socket, iov, 2)) == -1 && errno == EINTR) || 
416
 
        !len)
417
 
      continue;
418
 
    
419
 
    if ((size_t)len == towrite) /* wrote everything out */
420
 
      break;
421
 
    else if (len < 0) { /* error */
422
 
      if (errno == EAGAIN || errno == EWOULDBLOCK) {
423
 
          if (!dsi_peek(dsi)) {
424
 
              continue;
425
 
          }
426
 
      }
427
 
      LOG(log_error, logtype_dsi, "dsi_stream_send: %s", strerror(errno));
428
 
      unblock_sig(dsi);
429
 
      return 0;
430
 
    }
431
 
    
432
 
    towrite -= len;
433
 
    if (towrite > length) { /* skip part of header */
434
 
      iov[0].iov_base = (char *) iov[0].iov_base + len;
435
 
      iov[0].iov_len -= len;
436
 
    } else { /* skip to data */
437
 
      if (iov[0].iov_len) {
438
 
        len -= iov[0].iov_len;
439
 
        iov[0].iov_len = 0;
440
 
      }
441
 
      iov[1].iov_base = (char *) iov[1].iov_base + len;
442
 
      iov[1].iov_len -= len;
443
 
    }
 
411
      if (((len = writev(dsi->socket, iov, 2)) == -1 && errno == EINTR) || (len == 0))
 
412
          continue;
 
413
    
 
414
      if ((size_t)len == towrite) /* wrote everything out */
 
415
          break;
 
416
      else if (len < 0) { /* error */
 
417
          if (errno == EAGAIN || errno == EWOULDBLOCK) {
 
418
              if (!dsi_peek(dsi)) {
 
419
                  continue;
 
420
              }
 
421
          }
 
422
          LOG(log_error, logtype_dsi, "dsi_stream_send: %s", strerror(errno));
 
423
          unblock_sig(dsi);
 
424
          return 0;
 
425
      }
 
426
    
 
427
      towrite -= len;
 
428
      if (towrite > length) { /* skip part of header */
 
429
          iov[0].iov_base = (char *) iov[0].iov_base + len;
 
430
          iov[0].iov_len -= len;
 
431
      } else { /* skip to data */
 
432
          if (iov[0].iov_len) {
 
433
              len -= iov[0].iov_len;
 
434
              iov[0].iov_len = 0;
 
435
          }
 
436
          iov[1].iov_base = (char *) iov[1].iov_base + len;
 
437
          iov[1].iov_len -= len;
 
438
      }
444
439
  }
445
440
  
446
 
#else /* USE_WRITEV */
447
 
  /* write the header then data */
448
 
  if ((dsi_stream_write(dsi, block, sizeof(block), 1) != sizeof(block)) ||
449
 
            (dsi_stream_write(dsi, buf, length, 0) != length)) {
450
 
      unblock_sig(dsi);
451
 
      return 0;
452
 
  }
453
 
#endif /* USE_WRITEV */
454
 
 
455
441
  unblock_sig(dsi);
456
442
  return 1;
457
443
}
466
452
{
467
453
  char block[DSI_BLOCKSIZ];
468
454
 
 
455
  LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: %u bytes", ilength);
 
456
 
469
457
  /* read in the header */
470
458
  if (dsi_buffered_stream_read(dsi, (u_int8_t *)block, sizeof(block)) != sizeof(block)) 
471
459
    return 0;