]> arthur.barton.de Git - netatalk.git/blob - libatalk/dsi/dsi_write.c
59f8e387191e7eb0fe5abdc18177b2eea846014c
[netatalk.git] / libatalk / dsi / dsi_write.c
1 /*
2  * $Id: dsi_write.c,v 1.4 2005-04-28 20:50:02 bfernhomberg Exp $
3  *
4  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
5  * All rights reserved. See COPYRIGHT.
6  *
7  * 7 Oct 1997 added checks for 0 data.
8  */
9
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif /* HAVE_CONFIG_H */
13
14 /* this streams writes */
15 #include <stdio.h>
16 #ifdef HAVE_UNISTD_H
17 #include <unistd.h>
18 #endif /* HAVE_UNISTD_H */
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/time.h>
22 #ifdef HAVE_FCNTL_H
23 #include <fcntl.h>
24 #endif /* HAVE_FCNTL_H */
25 #include <string.h>
26
27 #include <atalk/dsi.h>
28 #include <netatalk/endian.h>
29
30 #ifndef MIN
31 #define MIN(a,b)     ((a) < (b) ? (a) : (b))
32 #endif /* ! MIN */
33
34 /* initialize relevant things for dsi_write. this returns the amount
35  * of data in the data buffer. the interface has been reworked to allow
36  * for arbitrary buffers. */
37 size_t dsi_writeinit(DSI *dsi, void *buf, const size_t buflen _U_)
38 {
39 #ifdef TIMER_ON_READ
40   const struct itimerval none = {{0, 0}, {0, 0}};
41 #endif  
42   size_t len, header;
43
44   /* figure out how much data we have. do a couple checks for 0 
45    * data */
46   header = ntohl(dsi->header.dsi_code);
47   dsi->datasize = header ? ntohl(dsi->header.dsi_len) - header : 0;
48   if (dsi->datasize > 0) {
49     len = MIN(sizeof(dsi->commands) - header, dsi->datasize);
50     
51     /* write last part of command buffer into buf */
52     memcpy(buf, dsi->commands + header, len);
53     
54     /* recalculate remaining data */
55     dsi->datasize -= len;
56   } else
57     len = 0;
58
59 #ifdef TIMER_ON_READ
60   /* deal with signals. i'm doing it this way to ensure that we don't
61    * get confused if a writeflush on zero remaining data is, for some
62    * reason, needed. */
63   sigprocmask(SIG_BLOCK, &dsi->sigblockset, &dsi->oldset);
64   dsi->sigblocked = 1;
65   setitimer(ITIMER_REAL, &none, &dsi->savetimer);
66 #endif  
67   return len;
68 }
69
70 /* fill up buf and then return. this should be called repeatedly
71  * until all the data has been read. i block alarm processing 
72  * during the transfer to avoid sending unnecessary tickles. */
73 size_t dsi_write(DSI *dsi, void *buf, const size_t buflen)
74 {
75   size_t length;
76
77   if (((length = MIN(buflen, dsi->datasize)) > 0) &&
78       ((length = dsi_stream_read(dsi, buf, length)) > 0)) {
79     dsi->datasize -= length;
80     return length;
81   }
82 #ifdef TIMER_ON_READ
83   setitimer(ITIMER_REAL, &dsi->savetimer, NULL);
84   sigprocmask(SIG_SETMASK, &dsi->oldset, NULL);
85 #endif
86   return 0;
87 }
88
89 /* flush any unread buffers. */
90 void dsi_writeflush(DSI *dsi)
91 {
92   size_t length;
93
94   while (dsi->datasize > 0) { 
95     length = dsi_stream_read(dsi, dsi->data,
96                              MIN(sizeof(dsi->data), dsi->datasize));
97     if (length > 0)
98       dsi->datasize -= length;
99     else
100       break;
101   }
102 #ifdef TIMER_ON_READ
103   setitimer(ITIMER_REAL, &dsi->savetimer, NULL);
104   sigprocmask(SIG_SETMASK, &dsi->oldset, NULL);
105 #endif  
106 }