From: Ralph Boehme Date: Tue, 13 Aug 2013 14:19:25 +0000 (+0200) Subject: FPExchangeFiles must only switch data file, not metadata X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=commitdiff_plain;h=cd9c05184ff9bb779034c2dc9cd63a975dac059e FPExchangeFiles must only switch data file, not metadata In Netatalk 3, afp_exchangefiles() moves the metadata EAs togehter with the files, so we must copy the metadata EAs back at then end. Fixes bug #521. --- diff --git a/NEWS b/NEWS index d567d530..98e2d2b5 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,8 @@ Changes in 3.0.5 set to yes, then Netatalk will attempt to recursively delete any vetoed files and directories. FR #82. * UPD: systemd unit dir is /usr/lib/systemd/system . +* FIX: Saving files from application like MS Word may result in the file + loosing metadata like the Finder label. Bug #521. Changes in 3.0.4 ================ diff --git a/etc/afpd/file.c b/etc/afpd/file.c index daaa84a5..f639c49b 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -2208,6 +2208,42 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U } goto err_temp_to_dest; } + + if (AD_META_OPEN(adsp) || AD_META_OPEN(addp)) { + struct adouble adtmp; + bool opened_ads, opened_add; + + ad_init(&adtmp, vol); + ad_init_offsets(&adtmp); + + if (!AD_META_OPEN(adsp)) { + if (ad_open(adsp, p, ADFLAGS_HF) != 0) + return -1; + opened_ads = true; + } + + if (!AD_META_OPEN(addp)) { + if (ad_open(addp, upath, ADFLAGS_HF) != 0) + return -1; + opened_add = true; + } + + if (ad_copy_header(&adtmp, adsp) != 0) + goto err_temp_to_dest; + if (ad_copy_header(adsp, addp) != 0) + goto err_temp_to_dest; + if (ad_copy_header(addp, &adtmp) != 0) + goto err_temp_to_dest; + ad_flush(adsp); + ad_flush(addp); + + if (opened_ads) + ad_close(adsp, ADFLAGS_HF); + if (opened_add) + ad_close(addp, ADFLAGS_HF); + } + + /* FIXME: we should switch ressource fork too */ /* here we need to reopen if crossdev */ if (sid && ad_setid(addp, destst.st_dev, destst.st_ino, sid, sdir->d_did, vol->v_stamp)) diff --git a/include/atalk/adouble.h b/include/atalk/adouble.h index c0f4098d..3b764a76 100644 --- a/include/atalk/adouble.h +++ b/include/atalk/adouble.h @@ -402,6 +402,7 @@ extern int ad_mkdir (const char *, mode_t); struct vol; extern void ad_init (struct adouble *, const struct vol * restrict); extern void ad_init_old (struct adouble *ad, int flags, int options); +extern int ad_init_offsets(struct adouble *ad); extern int ad_open (struct adouble *ad, const char *path, int adflags, ...); extern int ad_openat (struct adouble *, int dirfd, const char *path, int adflags, ...); extern int ad_refresh (const char *path, struct adouble *); diff --git a/libatalk/adouble/ad_open.c b/libatalk/adouble/ad_open.c index 6915cbb1..06c3c71e 100644 --- a/libatalk/adouble/ad_open.c +++ b/libatalk/adouble/ad_open.c @@ -311,19 +311,16 @@ static uint32_t get_eid(uint32_t eid) return 0; } -/* ----------------------------------- */ -static int new_ad_header(struct adouble *ad, const char *path, struct stat *stp, int adflags) + +/** + * Initialize offset pointers + */ +int ad_init_offsets(struct adouble *ad) { const struct entry *eid; - uint16_t ashort; - struct stat st; - LOG(log_debug, logtype_ad, "new_ad_header(\"%s\")", path); - - if (ad->ad_magic == AD_MAGIC) { - LOG(log_debug, logtype_ad, "new_ad_header(\"%s\"): already initialized", path); + if (ad->ad_magic == AD_MAGIC) return 0; - } ad->ad_magic = AD_MAGIC; ad->ad_version = ad->ad_vers & 0x0f0000; @@ -346,6 +343,21 @@ static int new_ad_header(struct adouble *ad, const char *path, struct stat *stp, eid++; } + return 0; +} + +/* ----------------------------------- */ +static int new_ad_header(struct adouble *ad, const char *path, struct stat *stp, int adflags) +{ + const struct entry *eid; + uint16_t ashort; + struct stat st; + + LOG(log_debug, logtype_ad, "new_ad_header(\"%s\")", path); + + if (ad_init_offsets(ad) != 0) + return -1; + /* set default creator/type fields */ memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRTYPEOFF,"\0\0\0\0", 4); memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRCREATOFF,"\0\0\0\0", 4);