2 * $Id: ad_flush.c,v 1.12 2009-10-13 22:55:37 didg Exp $
4 * Copyright (c) 1990,1991 Regents of The University of Michigan.
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.
17 * Research Systems Unix Group
18 * The University of Michigan
20 * 535 W. William Street
23 * netatalk@itd.umich.edu
28 #endif /* HAVE_CONFIG_H */
31 #include <atalk/adouble.h>
37 #include "ad_private.h"
38 #if AD_VERSION == AD_VERSION1
40 #define EID_DISK(a) (a)
44 static const u_int32_t set_eid[] = {
47 AD_DEV, AD_INO, AD_SYN, AD_ID
50 #define EID_DISK(a) (set_eid[a])
53 /* rebuild the adouble header
54 * XXX should be in a separate file ?
56 int ad_rebuild_adouble_header(struct adouble *ad)
65 * Rebuild any header information that might have changed.
69 temp = htonl( ad->ad_magic );
70 memcpy(buf, &temp, sizeof( temp ));
71 buf += sizeof( temp );
73 temp = htonl( ad->ad_version );
74 memcpy(buf, &temp, sizeof( temp ));
75 buf += sizeof( temp );
77 memcpy(buf, ad->ad_filler, sizeof( ad->ad_filler ));
78 buf += sizeof( ad->ad_filler );
81 buf += sizeof( nent );
82 for ( eid = 0, nent = 0; eid < ADEID_MAX; eid++ ) {
83 if ( ad->ad_eid[ eid ].ade_off == 0 ) {
86 temp = htonl( EID_DISK(eid) );
87 memcpy(buf, &temp, sizeof( temp ));
88 buf += sizeof( temp );
90 temp = htonl( ad->ad_eid[ eid ].ade_off );
91 memcpy(buf, &temp, sizeof( temp ));
92 buf += sizeof( temp );
94 temp = htonl( ad->ad_eid[ eid ].ade_len );
95 memcpy(buf, &temp, sizeof( temp ));
96 buf += sizeof( temp );
100 memcpy(nentp, &nent, sizeof( nent ));
101 return ad_getentryoff(ad, ADEID_RFORK);
104 /* -------------------
105 * XXX copy only header with same size or comment
106 * doesn't work well for adouble with different version.
109 int ad_copy_header(struct adouble *add, struct adouble *ads)
114 for ( eid = 0; eid < ADEID_MAX; eid++ ) {
115 if ( ads->ad_eid[ eid ].ade_off == 0 ) {
119 if ( add->ad_eid[ eid ].ade_off == 0 ) {
123 len = ads->ad_eid[ eid ].ade_len;
128 if (eid != ADEID_COMMENT && add->ad_eid[ eid ].ade_len != len ) {
132 ad_setentrylen( add, eid, len );
133 memcpy( ad_entry( add, eid ), ad_entry( ads, eid ), len );
135 add->ad_rlen = ads->ad_rlen;
139 /* ------------------- */
140 int ad_rebuild_sfm_header(struct adouble *ad)
148 * Rebuild any header information that might have changed.
152 /* temp = htonl( ad->ad_magic ); */
154 memcpy(buf, &temp, sizeof( temp ));
156 /* temp = htonl( ad->ad_version ); */
157 temp = ad->ad_version;
158 memcpy(buf +4, &temp, sizeof( temp ));
160 /* need to save attrib */
161 if (!ad_getattr(ad, &attr)) {
162 attr &= ~htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN);
164 memcpy(buf +48 +4, &attr, sizeof(attr));
171 int ad_flush( struct adouble *ad)
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);
181 ad_setentrylen(ad, ADEID_RFORK, ad->ad_rlen);
183 len = ad->ad_ops->ad_rebuild_header(ad);
185 if (adf_pwrite(ad->ad_md, ad->ad_data, len, 0) != len) {
196 /* use refcounts so that we don't have to re-establish fcntl locks. */
197 int ad_close( struct adouble *ad, int adflags)
201 if (( adflags & ADFLAGS_DF ) && ad_data_fileno(ad) != -1 &&
202 !(--ad->ad_data_fork.adf_refcount)) {
203 if ( close( ad_data_fileno(ad) ) < 0 ) {
206 ad_data_fileno(ad) = -1;
207 adf_lock_free(&ad->ad_data_fork);
210 if (!( adflags & ADFLAGS_HF )) {
214 /* meta /resource fork */
216 if ( ad_meta_fileno(ad) != -1 && !(--ad->ad_md->adf_refcount)) {
217 if ( close( ad_meta_fileno(ad) ) < 0 ) {
220 ad_meta_fileno(ad) = -1;
221 adf_lock_free(ad->ad_md);
224 if (ad->ad_flags != AD_VERSION1_SFM) {
228 if ((adflags & ADFLAGS_DIR)) {
232 if ( ad_reso_fileno(ad) != -1 && !(--ad->ad_resource_fork.adf_refcount)) {
233 if ( close( ad_reso_fileno(ad) ) < 0 ) {
236 ad_reso_fileno(ad) = -1;
237 adf_lock_free(&ad->ad_resource_fork);