From 3839498e720151ecc8d623ffc7f87906aa274a8b Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 12 Jun 2014 22:40:23 +0200 Subject: [PATCH] Delete 0 byte size resource fork ._ files Signed-off-by: Ralph Boehme Change-Id: ef5f88f5f2cefa75cf20d0ee447b4e20579a2f12 --- NEWS | 1 + etc/afpd/ofork.c | 33 +++++++++++++++++++++++++++++++++ libatalk/adouble/ad_write.c | 23 ++++++++++++++--------- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/NEWS b/NEWS index f305674b..138ff03a 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,7 @@ Changes in 3.1.3 * FIX: afpd: Unarchiving certain ZIP archives fails, bug #569 * UPD: Update Unicode support to version 7.0.0 * FIX: Memory overflow caused by 'basedir regex', bug #567 +* NEW: afpd: delete empty resource forks, from FR #94 Changes in 3.1.2 ================ diff --git a/etc/afpd/ofork.c b/etc/afpd/ofork.c index 8a04efb9..9d389bb2 100644 --- a/etc/afpd/ofork.c +++ b/etc/afpd/ofork.c @@ -23,10 +23,12 @@ #include #include #include +#include #include "volume.h" #include "directory.h" #include "fork.h" +#include "desktop.h" /* we need to have a hashed list of oforks (by dev inode) */ #define OFORK_HASHSIZE 64 @@ -435,6 +437,37 @@ int of_closefork(const AFPObj *obj, struct ofork *ofork) #endif ret = 0; + + /* + * Check for 0 byte size resource forks, delete them. + * Here's the deal: + * (1) the size must be 0 + * (2) the fork must refer to a resource fork + * (3) the refcount must be 1 which means this fork has the last + * reference to the adouble struct and the subsequent + * ad_close() will close the assoiciated fd. + * (4) nobody else has the resource fork open + * + * We only do this for ._ AppleDouble resource forks, not for + * xattr resource forks, because the test-suite then fails several + * tests on Solaris, the reason for that still needs to be + * determined. + */ + if ((ofork->of_ad->ad_rlen == 0) + && (ofork->of_flags & AFPFORK_RSRC) + && (ofork->of_ad->ad_rfp->adf_refcount == 1) + && (ad_openforks(ofork->of_ad, ATTRBIT_DOPEN) == 0)) { + +#ifndef HAVE_EAFD + (void)unlink(ofork->of_ad->ad_ops->ad_path( + mtoupath(ofork->of_vol, + of_name(ofork), + ofork->of_did, + utf8_encoding(obj)), + 0)); +#endif + } + if ( ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD) < 0 ) { ret = -1; } diff --git a/libatalk/adouble/ad_write.c b/libatalk/adouble/ad_write.c index 5cd3742d..4ae1cf60 100644 --- a/libatalk/adouble/ad_write.c +++ b/libatalk/adouble/ad_write.c @@ -161,17 +161,22 @@ int ad_rtruncate(struct adouble *ad, const char *uname, const off_t size) { EC_INIT; -#ifndef HAVE_EAFD - if (ad->ad_vers == AD_VERSION_EA && size == 0) - EC_NEG1( unlink(ad->ad_ops->ad_path(uname, 0)) ); - else -#endif - EC_NEG1( sys_ftruncate(ad_reso_fileno(ad), size + ad->ad_eid[ ADEID_RFORK ].ade_off) ); + /* + * We can't delete 0 byte size resource forks either, because a + * fork may reference the adouble handle with an open fd for the + * file, which means we would only delete the directory entry, not + * the file. Subsequently all code that works with fork handles + * finds the fork open, so eg flushing a fork (ad_flush()) will + * recreate ._ files. The correct place to delete 0 byte sized + * resource forks is in of_closefork(). + */ + + EC_NEG1( sys_ftruncate(ad_reso_fileno(ad), size + ad->ad_eid[ ADEID_RFORK ].ade_off) ); + + ad->ad_rlen = size; EC_CLEANUP: - if (ret == 0) - ad->ad_rlen = size; - else + if (ret != 0) LOG(log_error, logtype_ad, "ad_rtruncate(\"%s\"): %s", fullpathname(uname), strerror(errno)); EC_EXIT; -- 2.39.2