]> arthur.barton.de Git - netatalk.git/blob - libatalk/adouble/ad_flush.c
add a SFM compatible format for adouble
[netatalk.git] / libatalk / adouble / ad_flush.c
1 /*
2  * $Id: ad_flush.c,v 1.8 2006-09-29 09:39:16 didg Exp $
3  *
4  * Copyright (c) 1990,1991 Regents of The University of Michigan.
5  * All Rights Reserved.
6  *
7  * Permission to use, copy, modify, and distribute this software and
8  * its documentation for any purpose and without fee is hereby granted,
9  * provided that the above copyright notice appears in all copies and
10  * that both that copyright notice and this permission notice appear
11  * in supporting documentation, and that the name of The University
12  * of Michigan not be used in advertising or publicity pertaining to
13  * distribution of the software without specific, written prior
14  * permission. This software is supplied as is without expressed or
15  * implied warranties of any kind.
16  *
17  *      Research Systems Unix Group
18  *      The University of Michigan
19  *      c/o Mike Clark
20  *      535 W. William Street
21  *      Ann Arbor, Michigan
22  *      +1-313-763-0525
23  *      netatalk@itd.umich.edu
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif /* HAVE_CONFIG_H */
29
30 #include <string.h>
31 #include <atalk/adouble.h>
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <errno.h>
36
37 #include "ad_private.h"
38 #if AD_VERSION == AD_VERSION1 
39
40 #define EID_DISK(a) (a)
41
42 #else
43
44 static const u_int32_t set_eid[] = {
45 0,1,2,3,4,5,6,7,8,
46 9,10,11,12,13,14,15,
47 AD_DEV, AD_INO, AD_SYN, AD_ID
48 };
49
50 #define EID_DISK(a) (set_eid[a])
51 #endif
52
53 /* rebuild the adouble header 
54  * XXX should be in a separate file ?
55 */
56 int  ad_rebuild_adouble_header(struct adouble *ad)
57 {
58     u_int32_t           eid;
59     u_int32_t           temp;
60     
61     u_int16_t           nent;
62     char                *buf, *nentp;
63
64     /*
65      * Rebuild any header information that might have changed.
66      */
67     buf = ad->ad_data;
68
69     temp = htonl( ad->ad_magic );
70     memcpy(buf, &temp, sizeof( temp ));
71     buf += sizeof( temp );
72     
73     temp = htonl( ad->ad_version );
74     memcpy(buf, &temp, sizeof( temp ));
75     buf += sizeof( temp );
76
77     memcpy(buf, ad->ad_filler, sizeof( ad->ad_filler ));
78     buf += sizeof( ad->ad_filler );
79     
80     nentp = buf;
81     buf += sizeof( nent );
82     for ( eid = 0, nent = 0; eid < ADEID_MAX; eid++ ) {
83       if ( ad->ad_eid[ eid ].ade_off == 0 ) {
84         continue;
85       }
86       temp = htonl( EID_DISK(eid) );
87       memcpy(buf, &temp, sizeof( temp ));
88       buf += sizeof( temp );
89
90       temp = htonl( ad->ad_eid[ eid ].ade_off );
91       memcpy(buf, &temp, sizeof( temp ));
92       buf += sizeof( temp );
93
94       temp = htonl( ad->ad_eid[ eid ].ade_len );
95       memcpy(buf, &temp, sizeof( temp ));
96       buf += sizeof( temp );
97       nent++;
98     }
99     nent = htons( nent );
100     memcpy(nentp, &nent, sizeof( nent ));
101     return ad_getentryoff(ad, ADEID_RFORK);
102 }
103
104 /* ------------------- 
105  * XXX copy only header with same size or comment
106  * doesn't work well for adouble with different version.
107  * 
108 */
109 int ad_copy_header(struct adouble *add, struct adouble *ads)
110 {
111     u_int32_t           eid;
112     int                 len;
113
114     for ( eid = 0; eid < ADEID_MAX; eid++ ) {
115       if ( ads->ad_eid[ eid ].ade_off == 0 ) {
116         continue;
117       }
118
119       if ( add->ad_eid[ eid ].ade_off == 0 ) {
120         continue;
121       }
122
123       len = ads->ad_eid[ eid ].ade_len;
124       if (!len) {
125         continue;
126       }
127       
128       if (eid != ADEID_COMMENT && add->ad_eid[ eid ].ade_len != len ) {
129         continue;      
130       }
131       
132       ad_setentrylen( add, eid, len );
133       memcpy( ad_entry( add, eid ), ad_entry( ads, eid ), len );
134     }
135     add->ad_rlen = ads->ad_rlen;
136     return 0;
137 }
138
139 /* ------------------- */
140 int  ad_rebuild_sfm_header(struct adouble *ad)
141 {
142     u_int32_t           eid;
143     u_int32_t           temp;
144     
145     u_int16_t           attr;
146     char                *buf, *nentp;
147
148     /*
149      * Rebuild any header information that might have changed.
150      */
151     buf = ad->ad_data;
152     /* FIXME */
153 //    temp = htonl( ad->ad_magic );
154     temp = ad->ad_magic;
155     memcpy(buf, &temp, sizeof( temp ));
156     
157 //    temp = htonl( ad->ad_version );
158     temp = ad->ad_version;
159     memcpy(buf +4, &temp, sizeof( temp ));
160
161     /* need to save attrib */
162     if (!ad_getattr(ad, &attr)) {
163         attr &= ~htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN);
164
165         memcpy(buf +48 +4, &attr, sizeof(attr));
166         
167     }
168     return AD_SFM_LEN;
169 }
170
171
172 int ad_flush( ad )
173     struct adouble      *ad;
174 {
175     int len;
176
177     if (( ad->ad_md->adf_flags & O_RDWR )) {
178         /* sync our header */
179         if (ad->ad_rlen > 0xffffffff) {
180             ad_setentrylen(ad, ADEID_RFORK, 0xffffffff);
181         }
182         else {
183             ad_setentrylen(ad, ADEID_RFORK, ad->ad_rlen);
184         }
185         len = ad->ad_ops->ad_rebuild_header(ad);
186
187         if (adf_pwrite(ad->ad_md, ad->ad_data, len, 0) != len) {
188             if ( errno == 0 ) {
189                 errno = EIO;
190             }
191             return( -1 );
192         }
193     }
194
195     return( 0 );
196 }
197
198 /* use refcounts so that we don't have to re-establish fcntl locks. */
199 int ad_close( ad, adflags )
200     struct adouble      *ad;
201     int                 adflags;
202 {
203     int                 err = 0;
204
205     if (( adflags & ADFLAGS_DF ) && ad_data_fileno(ad) != -1 &&
206             !(--ad->ad_data_fork.adf_refcount)) {
207         if ( close( ad_data_fileno(ad) ) < 0 ) {
208             err = -1;
209         }
210         ad_data_fileno(ad) = -1;
211         adf_lock_free(&ad->ad_data_fork);
212     }
213
214     if (!( adflags & ADFLAGS_HF )) {
215         return err;
216     }
217     
218     /* meta /resource fork */
219
220     if ( ad_meta_fileno(ad) != -1 && !(--ad->ad_md->adf_refcount)) {
221         if ( close( ad_meta_fileno(ad) ) < 0 ) {
222             err = -1;
223         }
224         ad_meta_fileno(ad) = -1;
225         adf_lock_free(ad->ad_md);
226     }
227
228     if (ad->ad_flags != AD_VERSION1_SFM) {
229         return err;
230     }
231
232     if ((adflags & ADFLAGS_DIR)) {
233         return err;
234     }
235
236     if ( ad_reso_fileno(ad) != -1 && !(--ad->ad_resource_fork.adf_refcount)) {
237         if ( close( ad_reso_fileno(ad) ) < 0 ) {
238             err = -1;
239         }
240         ad_reso_fileno(ad) = -1;
241         adf_lock_free(&ad->ad_resource_fork);
242     }
243     
244     return err;
245 }