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