2 * Copyright (c) 1990,1991 Regents of The University of Michigan.
5 * Permission to use, copy, modify, and distribute this software and
6 * its documentation for any purpose and without fee is hereby granted,
7 * provided that the above copyright notice appears in all copies and
8 * that both that copyright notice and this permission notice appear
9 * in supporting documentation, and that the name of The University
10 * of Michigan not be used in advertising or publicity pertaining to
11 * distribution of the software without specific, written prior
12 * permission. This software is supplied as is without expressed or
13 * implied warranties of any kind.
15 * Research Systems Unix Group
16 * The University of Michigan
18 * 535 W. William Street
21 * netatalk@itd.umich.edu
26 #endif /* HAVE_CONFIG_H */
29 #include <atalk/adouble.h>
35 #include "ad_private.h"
36 #if AD_VERSION == AD_VERSION1
38 #define EID_DISK(a) (a)
42 static const u_int32_t set_eid[] = {
45 AD_DEV, AD_INO, AD_SYN, AD_ID
48 #define EID_DISK(a) (set_eid[a])
51 /* rebuild the adouble header
52 * XXX should be in a separate file ?
54 int ad_rebuild_adouble_header(struct adouble *ad)
63 * Rebuild any header information that might have changed.
67 temp = htonl( ad->ad_magic );
68 memcpy(buf, &temp, sizeof( temp ));
69 buf += sizeof( temp );
71 temp = htonl( ad->ad_version );
72 memcpy(buf, &temp, sizeof( temp ));
73 buf += sizeof( temp );
75 memcpy(buf, ad->ad_filler, sizeof( ad->ad_filler ));
76 buf += sizeof( ad->ad_filler );
79 buf += sizeof( nent );
80 for ( eid = 0, nent = 0; eid < ADEID_MAX; eid++ ) {
81 if ( ad->ad_eid[ eid ].ade_off == 0 ) {
84 temp = htonl( EID_DISK(eid) );
85 memcpy(buf, &temp, sizeof( temp ));
86 buf += sizeof( temp );
88 temp = htonl( ad->ad_eid[ eid ].ade_off );
89 memcpy(buf, &temp, sizeof( temp ));
90 buf += sizeof( temp );
92 temp = htonl( ad->ad_eid[ eid ].ade_len );
93 memcpy(buf, &temp, sizeof( temp ));
94 buf += sizeof( temp );
98 memcpy(nentp, &nent, sizeof( nent ));
99 return ad_getentryoff(ad, ADEID_RFORK);
102 /* -------------------
103 * XXX copy only header with same size or comment
104 * doesn't work well for adouble with different version.
107 int ad_copy_header(struct adouble *add, struct adouble *ads)
112 for ( eid = 0; eid < ADEID_MAX; eid++ ) {
113 if ( ads->ad_eid[ eid ].ade_off == 0 ) {
117 if ( add->ad_eid[ eid ].ade_off == 0 ) {
121 len = ads->ad_eid[ eid ].ade_len;
126 if (eid != ADEID_COMMENT && add->ad_eid[ eid ].ade_len != len ) {
130 ad_setentrylen( add, eid, len );
131 memcpy( ad_entry( add, eid ), ad_entry( ads, eid ), len );
133 add->ad_rlen = ads->ad_rlen;
137 /* ------------------- */
138 int ad_rebuild_sfm_header(struct adouble *ad)
146 * Rebuild any header information that might have changed.
150 /* temp = htonl( ad->ad_magic ); */
152 memcpy(buf, &temp, sizeof( temp ));
154 /* temp = htonl( ad->ad_version ); */
155 temp = ad->ad_version;
156 memcpy(buf +4, &temp, sizeof( temp ));
158 /* need to save attrib */
159 if (!ad_getattr(ad, &attr)) {
160 attr &= ~htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN);
162 memcpy(buf +48 +4, &attr, sizeof(attr));
169 int ad_flush( struct adouble *ad)
173 if (( ad->ad_md->adf_flags & O_RDWR )) {
174 /* sync our header */
175 if (ad->ad_rlen > 0xffffffff) {
176 ad_setentrylen(ad, ADEID_RFORK, 0xffffffff);
179 ad_setentrylen(ad, ADEID_RFORK, ad->ad_rlen);
181 len = ad->ad_ops->ad_rebuild_header(ad);
183 if (adf_pwrite(ad->ad_md, ad->ad_data, len, 0) != len) {
194 /* use refcounts so that we don't have to re-establish fcntl locks. */
195 int ad_close( struct adouble *ad, int adflags)
199 if ((adflags & ADFLAGS_DF)
200 && (ad_data_fileno(ad) >= 0 || ad_data_fileno(ad) == -2) /* -2 means symlink */
201 && --ad->ad_data_fork.adf_refcount == 0) {
202 if (ad->ad_data_fork.adf_syml != NULL) {
203 free(ad->ad_data_fork.adf_syml);
204 ad->ad_data_fork.adf_syml = 0;
206 if ( close( ad_data_fileno(ad) ) < 0 )
209 ad_data_fileno(ad) = -1;
210 adf_lock_free(&ad->ad_data_fork);
213 if (!( adflags & ADFLAGS_HF )) {
217 /* meta /resource fork */
219 if ( ad_meta_fileno(ad) != -1 && !(--ad->ad_md->adf_refcount)) {
220 if ( close( ad_meta_fileno(ad) ) < 0 ) {
223 ad_meta_fileno(ad) = -1;
224 adf_lock_free(ad->ad_md);
227 if (ad->ad_flags != AD_VERSION1_SFM) {
231 if ((adflags & ADFLAGS_DIR)) {
235 if ( ad_reso_fileno(ad) != -1 && !(--ad->ad_resource_fork.adf_refcount)) {
236 if ( close( ad_reso_fileno(ad) ) < 0 ) {
239 ad_reso_fileno(ad) = -1;
240 adf_lock_free(&ad->ad_resource_fork);