X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libatalk%2Fadouble%2Fad_flush.c;h=5d99227a6fec5b6835319dc2bf81544c08756816;hb=296eb8dfd48fb30bbc4b2371c3e1dabefe9d833d;hp=c92daddffeee738a3b58013957f048975ddf2ed8;hpb=ecfc96169ab669b578e53fa8e13592934fe37788;p=netatalk.git diff --git a/libatalk/adouble/ad_flush.c b/libatalk/adouble/ad_flush.c index c92daddf..5d99227a 100644 --- a/libatalk/adouble/ad_flush.c +++ b/libatalk/adouble/ad_flush.c @@ -1,5 +1,5 @@ /* - * $Id: ad_flush.c,v 1.7 2005-04-28 20:49:52 bfernhomberg Exp $ + * $Id: ad_flush.c,v 1.14 2010-03-30 12:55:26 franklahm Exp $ * * Copyright (c) 1990,1991 Regents of The University of Michigan. * All Rights Reserved. @@ -14,50 +14,52 @@ * permission. This software is supplied as is without expressed or * implied warranties of any kind. * - * Research Systems Unix Group - * The University of Michigan - * c/o Mike Clark - * 535 W. William Street - * Ann Arbor, Michigan - * +1-313-763-0525 - * netatalk@itd.umich.edu + * Research Systems Unix Group + * The University of Michigan + * c/o Mike Clark + * 535 W. William Street + * Ann Arbor, Michigan + * +1-313-763-0525 + * netatalk@itd.umich.edu */ #ifdef HAVE_CONFIG_H #include #endif /* HAVE_CONFIG_H */ +#include #include #include #include -#include #include #include "ad_private.h" -#if AD_VERSION == AD_VERSION1 +#if AD_VERSION == AD_VERSION1 #define EID_DISK(a) (a) #else static const u_int32_t set_eid[] = { -0,1,2,3,4,5,6,7,8, -9,10,11,12,13,14,15, -AD_DEV, AD_INO, AD_SYN, AD_ID + 0,1,2,3,4,5,6,7,8, + 9,10,11,12,13,14,15, + AD_DEV, AD_INO, AD_SYN, AD_ID }; #define EID_DISK(a) (set_eid[a]) #endif -/* rebuild the header */ -void ad_rebuild_header(struct adouble *ad) +/* rebuild the adouble header + * XXX should be in a separate file ? + */ +int ad_rebuild_adouble_header(struct adouble *ad) { - u_int32_t eid; - u_int32_t temp; - - u_int16_t nent; - char *buf, *nentp; + u_int32_t eid; + u_int32_t temp; + + u_int16_t nent; + char *buf, *nentp; /* * Rebuild any header information that might have changed. @@ -67,90 +69,178 @@ void ad_rebuild_header(struct adouble *ad) temp = htonl( ad->ad_magic ); memcpy(buf, &temp, sizeof( temp )); buf += sizeof( temp ); - + temp = htonl( ad->ad_version ); memcpy(buf, &temp, sizeof( temp )); buf += sizeof( temp ); memcpy(buf, ad->ad_filler, sizeof( ad->ad_filler )); buf += sizeof( ad->ad_filler ); - + nentp = buf; buf += sizeof( nent ); for ( eid = 0, nent = 0; eid < ADEID_MAX; eid++ ) { - if ( ad->ad_eid[ eid ].ade_off == 0 ) { - continue; - } - temp = htonl( EID_DISK(eid) ); - memcpy(buf, &temp, sizeof( temp )); - buf += sizeof( temp ); - - temp = htonl( ad->ad_eid[ eid ].ade_off ); - memcpy(buf, &temp, sizeof( temp )); - buf += sizeof( temp ); - - temp = htonl( ad->ad_eid[ eid ].ade_len ); - memcpy(buf, &temp, sizeof( temp )); - buf += sizeof( temp ); - nent++; + if ( ad->ad_eid[ eid ].ade_off == 0 ) { + continue; + } + temp = htonl( EID_DISK(eid) ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + temp = htonl( ad->ad_eid[ eid ].ade_off ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + + temp = htonl( ad->ad_eid[ eid ].ade_len ); + memcpy(buf, &temp, sizeof( temp )); + buf += sizeof( temp ); + nent++; } nent = htons( nent ); memcpy(nentp, &nent, sizeof( nent )); + return ad_getentryoff(ad, ADEID_RFORK); } +/* ------------------- + * XXX copy only header with same size or comment + * doesn't work well for adouble with different version. + * + */ +int ad_copy_header(struct adouble *add, struct adouble *ads) +{ + u_int32_t eid; + u_int32_t len; + + for ( eid = 0; eid < ADEID_MAX; eid++ ) { + if ( ads->ad_eid[ eid ].ade_off == 0 ) { + continue; + } + + if ( add->ad_eid[ eid ].ade_off == 0 ) { + continue; + } + + len = ads->ad_eid[ eid ].ade_len; + if (!len) { + continue; + } -int ad_flush( ad, adflags ) - struct adouble *ad; - int adflags; + if (eid != ADEID_COMMENT && add->ad_eid[ eid ].ade_len != len ) { + continue; + } + + ad_setentrylen( add, eid, len ); + memcpy( ad_entry( add, eid ), ad_entry( ads, eid ), len ); + } + add->ad_rlen = ads->ad_rlen; + return 0; +} + +/* ------------------- */ +int ad_rebuild_sfm_header(struct adouble *ad) +{ + u_int32_t temp; + + u_int16_t attr; + char *buf; + + /* + * Rebuild any header information that might have changed. + */ + buf = ad->ad_data; + /* FIXME */ +/* temp = htonl( ad->ad_magic ); */ + temp = ad->ad_magic; + memcpy(buf, &temp, sizeof( temp )); + +/* temp = htonl( ad->ad_version ); */ + temp = ad->ad_version; + memcpy(buf +4, &temp, sizeof( temp )); + + /* need to save attrib */ + if (!ad_getattr(ad, &attr)) { + attr &= ~htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN); + + memcpy(buf +48 +4, &attr, sizeof(attr)); + + } + return AD_SFM_LEN; +} + + +int ad_flush( struct adouble *ad) { int len; - if (( adflags & ADFLAGS_HF ) && ( ad->ad_hf.adf_flags & O_RDWR )) { - /* sync our header */ + if (( ad->ad_md->adf_flags & O_RDWR )) { + /* sync our header */ if (ad->ad_rlen > 0xffffffff) { ad_setentrylen(ad, ADEID_RFORK, 0xffffffff); } else { ad_setentrylen(ad, ADEID_RFORK, ad->ad_rlen); } - ad_rebuild_header(ad); - len = ad_getentryoff(ad, ADEID_RFORK); - /* now flush it out */ - if (adf_pwrite(&ad->ad_hf, ad->ad_data, len, 0) != len) { - if ( errno == 0 ) { - errno = EIO; - } - return( -1 ); - } + len = ad->ad_ops->ad_rebuild_header(ad); + + if (adf_pwrite(ad->ad_md, ad->ad_data, len, 0) != len) { + if ( errno == 0 ) { + errno = EIO; + } + return( -1 ); + } } return( 0 ); } /* use refcounts so that we don't have to re-establish fcntl locks. */ -int ad_close( ad, adflags ) - struct adouble *ad; - int adflags; +int ad_close( struct adouble *ad, int adflags) { - int err = 0; - - if (( adflags & ADFLAGS_DF ) && ad->ad_df.adf_fd != -1 && - !(--ad->ad_df.adf_refcount)) { - if ( close( ad->ad_df.adf_fd ) < 0 ) { - err = -1; - } - ad->ad_df.adf_fd = -1; - adf_lock_free(&ad->ad_df); + int err = 0; + + if ((adflags & ADFLAGS_DF) + && ad_data_fileno(ad) >= 0 + && --ad->ad_data_fork.adf_refcount == 0) { + if (ad->ad_data_fork.adf_syml !=0) { + free(ad->ad_data_fork.adf_syml); + ad->ad_data_fork.adf_syml = 0; + } else { + if ( close( ad_data_fileno(ad) ) < 0 ) + err = -1; + } + ad_data_fileno(ad) = -1; + adf_lock_free(&ad->ad_data_fork); + } + + if (!( adflags & ADFLAGS_HF )) { + return err; + } + + /* meta /resource fork */ + + if ( ad_meta_fileno(ad) != -1 && !(--ad->ad_md->adf_refcount)) { + if ( close( ad_meta_fileno(ad) ) < 0 ) { + err = -1; + } + ad_meta_fileno(ad) = -1; + adf_lock_free(ad->ad_md); + } + + if (ad->ad_flags != AD_VERSION1_SFM) { + return err; } - if (( adflags & ADFLAGS_HF ) && ad->ad_hf.adf_fd != -1 && - !(--ad->ad_hf.adf_refcount)) { - if ( close( ad->ad_hf.adf_fd ) < 0 ) { - err = -1; - } - ad->ad_hf.adf_fd = -1; - adf_lock_free(&ad->ad_hf); + if ((adflags & ADFLAGS_DIR)) { + return err; + } + + if ( ad_reso_fileno(ad) != -1 && !(--ad->ad_resource_fork.adf_refcount)) { + if ( close( ad_reso_fileno(ad) ) < 0 ) { + err = -1; + } + ad_reso_fileno(ad) = -1; + adf_lock_free(&ad->ad_resource_fork); } - return( err ); + return err; }