]> arthur.barton.de Git - netatalk.git/blob - libatalk/adouble/ad_flush.c
Convert all u_int to ISO uint
[netatalk.git] / libatalk / adouble / ad_flush.c
1 /*
2  * Copyright (c) 1990,1991 Regents of The University of Michigan.
3  * Copyright (c) 2010      Frank Lahm
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software and
7  * its documentation for any purpose and without fee is hereby granted,
8  * provided that the above copyright notice appears in all copies and
9  * that both that copyright notice and this permission notice appear
10  * in supporting documentation, and that the name of The University
11  * of Michigan not be used in advertising or publicity pertaining to
12  * distribution of the software without specific, written prior
13  * permission. This software is supplied as is without expressed or
14  * implied warranties of any kind.
15  *
16  *  Research Systems Unix Group
17  *  The University of Michigan
18  *  c/o Mike Clark
19  *  535 W. William Street
20  *  Ann Arbor, Michigan
21  *  +1-313-763-0525
22  *  netatalk@itd.umich.edu
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif /* HAVE_CONFIG_H */
28
29 #include <string.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <arpa/inet.h>
34
35 #include <atalk/adouble.h>
36 #include <atalk/ea.h>
37 #include <atalk/logger.h>
38 #include <atalk/bstrlib.h>
39 #include <atalk/bstradd.h>
40
41 #include "ad_lock.h"
42
43 static const uint32_t set_eid[] = {
44     0,1,2,3,4,5,6,7,8,
45     9,10,11,12,13,14,15,
46     AD_DEV, AD_INO, AD_SYN, AD_ID
47 };
48
49 #define EID_DISK(a) (set_eid[a])
50
51 /*
52  * Rebuild any header information that might have changed.
53  */
54 int  ad_rebuild_adouble_header(struct adouble *ad)
55 {
56     uint32_t       eid;
57     uint32_t       temp;
58     uint16_t       nent;
59     char        *buf, *nentp;
60     int             len;
61
62     buf = ad->ad_data;
63
64     temp = htonl( ad->ad_magic );
65     memcpy(buf, &temp, sizeof( temp ));
66     buf += sizeof( temp );
67
68     temp = htonl( ad->ad_version );
69     memcpy(buf, &temp, sizeof( temp ));
70     buf += sizeof( temp );
71
72     buf += sizeof( ad->ad_filler );
73
74     nentp = buf;
75     buf += sizeof( nent );
76     for ( eid = 0, nent = 0; eid < ADEID_MAX; eid++ ) {
77         if ( ad->ad_eid[ eid ].ade_off == 0 ) {
78             continue;
79         }
80         temp = htonl( EID_DISK(eid) );
81         memcpy(buf, &temp, sizeof( temp ));
82         buf += sizeof( temp );
83
84         temp = htonl( ad->ad_eid[ eid ].ade_off );
85         memcpy(buf, &temp, sizeof( temp ));
86         buf += sizeof( temp );
87
88         temp = htonl( ad->ad_eid[ eid ].ade_len );
89         memcpy(buf, &temp, sizeof( temp ));
90         buf += sizeof( temp );
91         nent++;
92     }
93     nent = htons( nent );
94     memcpy(nentp, &nent, sizeof( nent ));
95
96     switch (ad->ad_flags) {
97     case AD_VERSION2:
98         len = ad_getentryoff(ad, ADEID_RFORK);
99         break;
100     case AD_VERSION_EA:
101         len = AD_DATASZ_EA;
102         break;
103     default:
104         LOG(log_error, logtype_afpd, "Unexpected adouble version");
105         len = 0;
106         break;
107     }
108
109     return len;
110 }
111
112 /* -------------------
113  * XXX copy only header with same size or comment
114  * doesn't work well for adouble with different version.
115  *
116  */
117 int ad_copy_header(struct adouble *add, struct adouble *ads)
118 {
119     uint32_t       eid;
120     uint32_t       len;
121
122     for ( eid = 0; eid < ADEID_MAX; eid++ ) {
123         if ( ads->ad_eid[ eid ].ade_off == 0 ) {
124             continue;
125         }
126
127         if ( add->ad_eid[ eid ].ade_off == 0 ) {
128             continue;
129         }
130
131         len = ads->ad_eid[ eid ].ade_len;
132         if (!len) {
133             continue;
134         }
135
136         if (eid != ADEID_COMMENT && add->ad_eid[ eid ].ade_len != len ) {
137             continue;
138         }
139
140         ad_setentrylen( add, eid, len );
141         memcpy( ad_entry( add, eid ), ad_entry( ads, eid ), len );
142     }
143     add->ad_rlen = ads->ad_rlen;
144     return 0;
145 }
146
147 int ad_flush(struct adouble *ad)
148 {
149     int len;
150
151     if (( ad->ad_md->adf_flags & O_RDWR )) {
152         if (ad_getentryoff(ad, ADEID_RFORK)) {
153             if (ad->ad_rlen > 0xffffffff)
154                 ad_setentrylen(ad, ADEID_RFORK, 0xffffffff);
155             else
156                 ad_setentrylen(ad, ADEID_RFORK, ad->ad_rlen);
157         }
158         len = ad->ad_ops->ad_rebuild_header(ad);
159
160         switch (ad->ad_flags) {
161         case AD_VERSION2:
162             if (adf_pwrite(ad->ad_md, ad->ad_data, len, 0) != len) {
163                 if (errno == 0)
164                     errno = EIO;
165                 return( -1 );
166             }
167             break;
168         case AD_VERSION_EA:
169             if (sys_lsetxattr(cfrombstr(ad->ad_fullpath), AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0) != 0) {
170                 LOG(log_error, logtype_afpd, "ad_flush: sys_fsetxattr error: %s",
171                     strerror(errno));
172                 return -1;
173             }
174             break;
175         default:
176             LOG(log_error, logtype_afpd, "ad_flush: unexpected adouble version");
177             return -1;
178         }
179     }
180
181     return( 0 );
182 }
183
184 /*!
185  * Close a struct adouble freeing all resources
186  *
187  * This close the whole thing, regardless of what you pass in adflags!
188  * When open forks are using this struct adouble (ad_refcount>0) the close
189  * request is ignored.
190  */
191 int ad_close( struct adouble *ad, int adflags)
192 {
193     int err = 0;
194
195     if (ad == NULL)
196         return 0;
197
198     LOG(log_debug, logtype_default, "ad_close(\"%s\", %s)",
199         cfrombstr(ad->ad_fullpath),
200         adflags2logstr(adflags));
201
202     if (ad->ad_refcount) {
203         LOG(log_debug, logtype_default, "ad_close(\"%s\"): adouble in use by fork, not closing",
204             cfrombstr(ad->ad_fullpath));
205         return 0;
206     }
207
208     if (ad_data_fileno(ad) != -1) {
209         if ((ad_data_fileno(ad) == -2) && (ad->ad_data_fork.adf_syml != NULL)) {
210             free(ad->ad_data_fork.adf_syml);
211             ad->ad_data_fork.adf_syml = NULL;
212         } else {
213             if ( close( ad_data_fileno(ad) ) < 0 )
214                 err = -1;
215         }
216         ad_data_fileno(ad) = -1;
217         adf_lock_free(&ad->ad_data_fork);
218         ad->ad_adflags &= ~ADFLAGS_DF;
219     }
220
221     if (ad_meta_fileno(ad) != -1) {
222         if ( close( ad_meta_fileno(ad) ) < 0 )
223             err = -1;
224         ad_meta_fileno(ad) = -1;
225         adf_lock_free(ad->ad_md);
226         ad->ad_adflags &= ~ADFLAGS_HF;
227     }
228
229     if (ad->ad_resforkbuf) {
230         free(ad->ad_resforkbuf);
231         ad->ad_resforkbuf = NULL;
232         ad->ad_adflags &= ~ADFLAGS_RF;
233     }
234
235     if (ad->ad_fullpath) {
236         bdestroy(ad->ad_fullpath);
237         ad->ad_fullpath = NULL;
238     }
239
240     return err;
241 }