]> arthur.barton.de Git - netatalk.git/blob - libatalk/adouble/ad_flush.c
Symlink patch from Anton Starikov
[netatalk.git] / libatalk / adouble / ad_flush.c
1 /*
2  * $Id: ad_flush.c,v 1.12.2.1 2010-01-02 10:22:33 franklahm 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     u_int32_t       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       temp;
143
144     u_int16_t       attr;
145     char        *buf;
146
147     /*
148      * Rebuild any header information that might have changed.
149      */
150     buf = ad->ad_data;
151     /* FIXME */
152 /*    temp = htonl( ad->ad_magic ); */
153     temp = ad->ad_magic;
154     memcpy(buf, &temp, sizeof( temp ));
155
156 /*    temp = htonl( ad->ad_version ); */
157     temp = ad->ad_version;
158     memcpy(buf +4, &temp, sizeof( temp ));
159
160     /* need to save attrib */
161     if (!ad_getattr(ad, &attr)) {
162         attr &= ~htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN);
163
164         memcpy(buf +48 +4, &attr, sizeof(attr));
165
166     }
167     return AD_SFM_LEN;
168 }
169
170
171 int ad_flush( struct adouble *ad)
172 {
173     int len;
174
175     if (( ad->ad_md->adf_flags & O_RDWR )) {
176         /* sync our header */
177         if (ad->ad_rlen > 0xffffffff) {
178             ad_setentrylen(ad, ADEID_RFORK, 0xffffffff);
179         }
180         else {
181             ad_setentrylen(ad, ADEID_RFORK, ad->ad_rlen);
182         }
183         len = ad->ad_ops->ad_rebuild_header(ad);
184
185         if (adf_pwrite(ad->ad_md, ad->ad_data, len, 0) != len) {
186             if ( errno == 0 ) {
187                 errno = EIO;
188             }
189             return( -1 );
190         }
191     }
192
193     return( 0 );
194 }
195
196 /* use refcounts so that we don't have to re-establish fcntl locks. */
197 int ad_close( struct adouble *ad, int adflags)
198 {
199     int         err = 0;
200
201     if (( adflags & ADFLAGS_DF ) && ad_data_fileno(ad) != -1 &&
202         !(--ad->ad_data_fork.adf_refcount)) {
203         if (ad->ad_data_fork.adf_syml!=0){
204             free(ad->ad_data_fork.adf_syml);
205             ad->ad_data_fork.adf_syml=0;
206         }else{     
207         if ( close( ad_data_fileno(ad) ) < 0 ) {
208             err = -1;
209         }
210         }
211         ad_data_fileno(ad) = -1;
212         adf_lock_free(&ad->ad_data_fork);
213     }
214
215     if (!( adflags & ADFLAGS_HF )) {
216         return err;
217     }
218
219     /* meta /resource fork */
220
221     if ( ad_meta_fileno(ad) != -1 && !(--ad->ad_md->adf_refcount)) {
222         if ( close( ad_meta_fileno(ad) ) < 0 ) {
223             err = -1;
224         }
225         ad_meta_fileno(ad) = -1;
226         adf_lock_free(ad->ad_md);
227     }
228
229     if (ad->ad_flags != AD_VERSION1_SFM) {
230         return err;
231     }
232
233     if ((adflags & ADFLAGS_DIR)) {
234         return err;
235     }
236
237     if ( ad_reso_fileno(ad) != -1 && !(--ad->ad_resource_fork.adf_refcount)) {
238         if ( close( ad_reso_fileno(ad) ) < 0 ) {
239             err = -1;
240         }
241         ad_reso_fileno(ad) = -1;
242         adf_lock_free(&ad->ad_resource_fork);
243     }
244
245     return err;
246 }