]> arthur.barton.de Git - netatalk.git/blob - libatalk/adouble/ad_write.c
0d37ebf6cfff342ac95b1ba511d6f96fe1500a63
[netatalk.git] / libatalk / adouble / ad_write.c
1 /*
2  * Copyright (c) 1990,1995 Regents of The University of Michigan.
3  * All Rights Reserved.  See COPYRIGHT.
4  */
5
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #include <string.h>
11 #include <sys/types.h>
12 #include <sys/param.h>
13 #include <sys/stat.h>
14 #include <unistd.h>
15 #include <fcntl.h>
16 #include <errno.h>
17
18 #include <atalk/adouble.h>
19
20 #ifndef MIN
21 #define MIN(a,b)        ((a)<(b)?(a):(b))
22 #endif
23
24 /* XXX: this would benefit from pwrite. 
25  *      locking has to be checked before each stream of consecutive
26  *      ad_writes to prevent a lock in the middle from causing problems. 
27  */
28 ssize_t ad_write( ad, eid, off, end, buf, buflen )
29     struct adouble      *ad;
30     const u_int32_t     eid;
31     off_t               off;
32     const int           end;
33     const char          *buf;
34     const size_t        buflen;
35 {
36     struct stat         st;
37     ssize_t             cc;
38
39     if ( eid == ADEID_DFORK ) {
40         if ( end ) {
41             if ( fstat( ad->ad_df.adf_fd, &st ) < 0 ) {
42                 return( -1 );
43             }
44             off = st.st_size - off;
45         }
46
47         if ( ad->ad_df.adf_off != off ) {
48             if ( lseek( ad->ad_df.adf_fd, (off_t) off, SEEK_SET ) < 0 ) {
49                 return( -1 );
50             }
51             ad->ad_df.adf_off = off;
52         }
53         cc = write( ad->ad_df.adf_fd, buf, buflen );
54         if ( cc < 0 ) {
55             return( -1 );
56         }
57         ad->ad_df.adf_off += cc;
58     } else {
59         if ( end ) {
60             off = ad->ad_eid[ eid ].ade_len - off;
61         }
62         cc = ad->ad_eid[eid].ade_off + off;
63
64 #ifdef USE_MMAPPED_HEADERS
65         if (eid != ADEID_RFORK) {
66           memcpy(ad->ad_data + cc, buf, buflen);
67           cc = buflen;
68           goto ad_write_done;
69         }         
70 #endif
71
72         if ( ad->ad_hf.adf_off != cc ) {
73           if ( lseek( ad->ad_hf.adf_fd, (off_t) cc, SEEK_SET ) < 0 ) {
74               return( -1 );
75           }
76           ad->ad_hf.adf_off = cc;
77         }
78           
79         if ((cc = write( ad->ad_hf.adf_fd, buf, buflen )) < 0)
80           return( -1 );
81         ad->ad_hf.adf_off += cc;
82         
83 #ifndef USE_MMAPPED_HEADERS
84         /* sync up our internal buffer */
85         if (ad->ad_hf.adf_off < ad_getentryoff(ad, ADEID_RFORK))
86           memcpy(ad->ad_data + ad->ad_hf.adf_off, buf,
87                  MIN(sizeof(ad->ad_data) - ad->ad_hf.adf_off, cc));
88 #else     
89 ad_write_done:
90 #endif
91           if ( ad->ad_eid[ eid ].ade_len < off + cc ) {
92             ad->ad_eid[ eid ].ade_len = off + cc;
93           }
94     }
95
96     return( cc );
97 }
98
99 /* set locks here */
100 int ad_rtruncate( ad, size )
101     struct adouble      *ad;
102     const size_t        size;
103 {
104     int err;
105
106     if (ad_tmplock(ad, ADEID_RFORK, ADLOCK_WR, 0, 0) < 0)
107       return -2;
108
109     if ( ftruncate( ad->ad_hf.adf_fd,
110             size + ad->ad_eid[ ADEID_RFORK ].ade_off ) < 0 ) {
111         err = errno;
112         ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0);
113         errno = err;
114         return( -1 );
115     }
116
117     ad->ad_eid[ ADEID_RFORK ].ade_len = size;
118     if ( lseek( ad->ad_hf.adf_fd, ad->ad_eid[ADEID_RFORK].ade_off, 
119                 SEEK_SET ) < 0 ) {
120         err = errno;
121         ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0);
122         errno = err;
123         return( -1 );
124     }
125
126     ad->ad_hf.adf_off = ad->ad_eid[ADEID_RFORK].ade_off;
127     ad_tmplock(ad, ADEID_RFORK, ADLOCK_CLR, 0, 0);
128     return( 0 );
129 }
130
131 int ad_dtruncate(ad, size)
132     struct adouble      *ad;
133     const size_t        size;
134 {
135     int err;
136
137     if (ad_tmplock(ad, ADEID_DFORK, ADLOCK_WR, 0, 0) < 0)
138       return -2;
139
140     if (ftruncate(ad->ad_df.adf_fd, size) < 0) {
141       err = errno;
142       ad_tmplock(ad, ADEID_DFORK, ADLOCK_CLR, 0, 0);
143       errno = err;
144     } else 
145       ad_tmplock(ad, ADEID_DFORK, ADLOCK_CLR, 0, 0);
146
147     return 0;
148 }