From 1fd316930fbb61d754cf7df36e584348bb95cfc3 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Sun, 15 Jun 2014 06:07:10 +0200 Subject: [PATCH] Resource fork conversion from AppleDouble v2 broken, bug #568 Converting from AppleDouble v2 to ea may corrupt the resource fork. In some circumstances an offset calculation is wrong resulting in corrupt resource forks after the conversion. Ensure the resource fork AppleDouble entry offset is always set up and we don't rely on the manual offset calculation. Skip ADEID_RFORK in ad_copy_header() and allow copying of AppleDouble entry that have an initial zero size in the destination adouble. Signed-off-by: Ralph Boehme --- NEWS | 4 ++++ libatalk/adouble/ad_conv.c | 2 +- libatalk/adouble/ad_flush.c | 7 ++----- libatalk/adouble/ad_open.c | 22 ++++++++++++++++++++++ 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index eb10cf61..9299f4f2 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,10 @@ Changes in 3.1.3 * NEW: afpd: delete empty resource forks, from FR #92 * FIX: afpd: fix a crash when accessing ._ AppleDouble files created by OS X via SMB, bug #564 +* FIX: afpd and dbd: Converting from AppleDouble v2 to ea may corrupt + the resource fork. In some circumstances an offset calculation + is wrong resulting in corrupt resource forks after the + conversion. Bug #568. Changes in 3.1.2 ================ diff --git a/libatalk/adouble/ad_conv.c b/libatalk/adouble/ad_conv.c index 2a75ec62..43f4332b 100644 --- a/libatalk/adouble/ad_conv.c +++ b/libatalk/adouble/ad_conv.c @@ -152,7 +152,7 @@ static int ad_conv_v22ea_rf(const char *path, const struct stat *sp, const struc EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) ); /* Create a adouble:ea resource fork */ - EC_ZERO_LOG( ad_open(&adea, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) ); + EC_ZERO_LOG( ad_open(&adea, path, ADFLAGS_RF|ADFLAGS_RDWR|ADFLAGS_CREATE|ADFLAGS_SETSHRMD, 0666) ); EC_ZERO_LOG( copy_fork(ADEID_RFORK, &adea, &adv2) ); adea.ad_rlen = adv2.ad_rlen; diff --git a/libatalk/adouble/ad_flush.c b/libatalk/adouble/ad_flush.c index 6e214863..6a1900c7 100644 --- a/libatalk/adouble/ad_flush.c +++ b/libatalk/adouble/ad_flush.c @@ -217,15 +217,12 @@ int ad_copy_header(struct adouble *add, struct adouble *ads) continue; len = ads->ad_eid[ eid ].ade_len; - if (!len || len != add->ad_eid[ eid ].ade_len) + if (len == 0) continue; switch (eid) { case ADEID_COMMENT: - case ADEID_PRIVDEV: - case ADEID_PRIVINO: - case ADEID_PRIVSYN: - case ADEID_PRIVID: + case ADEID_RFORK: continue; default: ad_setentrylen( add, eid, len ); diff --git a/libatalk/adouble/ad_open.c b/libatalk/adouble/ad_open.c index 14f2caa4..53ec4eb9 100644 --- a/libatalk/adouble/ad_open.c +++ b/libatalk/adouble/ad_open.c @@ -343,6 +343,14 @@ int ad_init_offsets(struct adouble *ad) eid++; } + /* + * Ensure the resource fork offset is always set + */ +#ifndef HAVE_EAFD + if (ad->ad_vers == AD_VERSION_EA) + ad_setentryoff(ad, ADEID_RFORK, ADEDOFF_RFORK_OSX); +#endif + return 0; } @@ -795,6 +803,14 @@ static int ad_header_read_ea(const char *path, struct adouble *ad, const struct EC_FAIL; } + /* + * Ensure the resource fork offset is always set + */ +#ifndef HAVE_EAFD + if (ad->ad_vers == AD_VERSION_EA) + ad_setentryoff(ad, ADEID_RFORK, ADEDOFF_RFORK_OSX); +#endif + EC_CLEANUP: if (ret != 0 && errno == EINVAL) { become_root(); @@ -1809,6 +1825,12 @@ void ad_init(struct adouble *ad, const struct vol * restrict vol) * - we remember open fds for files because me must avoid a single close releasing fcntl locks for other * fds of the same file * + * BUGS: + * + * * on Solaris (HAVE_EAFD) ADFLAGS_RF doesn't work without + * ADFLAGS_HF, because it checks whether ad_meta_fileno() is already + * openend. As a workaround pass ADFLAGS_SETSHRMD. + * * @returns 0 on success, any other value indicates an error */ int ad_open(struct adouble *ad, const char *path, int adflags, ...) -- 2.39.2