]> arthur.barton.de Git - netatalk.git/commitdiff
Automatic unescaping of CAP hexencoded '/' and '.'
authorFrank Lahm <franklahm@googlemail.com>
Thu, 29 Mar 2012 16:58:59 +0000 (18:58 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Thu, 29 Mar 2012 16:58:59 +0000 (18:58 +0200)
- when accessed from AFP client in enumerat()
- also updates CNID db
BUGS:
- dbd not working

etc/afpd/enumerate.c
etc/afpd/volume.c
etc/cnid_dbd/cmd_dbd_scanvol.c
include/atalk/adouble.h
include/atalk/directory.h
libatalk/adouble/Makefile.am
libatalk/adouble/ad_conv.c [new file with mode: 0644]
libatalk/adouble/ad_open.c

index 80759a439cf61bfed6f088b0641bf5e4c48a907a..021862e76a87e974ef54d399eff5f14527886c4a 100644 (file)
@@ -347,13 +347,16 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,
             continue;
         }
         memset(&s_path, 0, sizeof(s_path));
+
+        /* conversions on the fly */
+        const char *convname;
         s_path.u_name = sd.sd_last;
-        if (of_stat( &s_path) < 0 ) {
-            /*
-             * Somebody else plays with the dir, well it can be us with 
-            * "Empty Trash..."
-            */
+        if (ad_convert(sd.sd_last, &s_path.st, vol, &convname) == 0 && convname) {
+            s_path.u_name = (char *)convname;
+            s_path.unconverted_name = sd.sd_last; /* Needed for CNID fixup */
+        }
 
+        if (of_stat( &s_path) < 0 ) {
             /* so the next time it won't try to stat it again
              * another solution would be to invalidate the cache with 
              * sd.sd_did = 0 but if it's not ENOENT error it will start again
@@ -364,12 +367,18 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,
             continue;
         }
 
+        /* Fixup CNID db if ad_convert resulted in a rename (then convname != NULL) */
+        if (convname) {
+            s_path.id = cnid_lookup(vol->v_cdb, &s_path.st, curdir->d_did, sd.sd_last, strlen(sd.sd_last));
+            if (s_path.id != CNID_INVALID) {
+                if (cnid_update(vol->v_cdb, s_path.id, &s_path.st, curdir->d_did, convname, strlen(convname)) != 0)
+                    LOG(log_error, logtype_afpd, "enumerate: error updating CNID of \"%s\"", fullpathname(convname));
+            }
+        }
+
         sd.sd_last += len + 1;
         s_path.m_name = NULL;
 
-        /* Convert adouble:v2 to adouble:ea on the fly */
-        (void)ad_convert(s_path.u_name, &s_path.st, vol);
-
         /*
          * If a fil/dir is not a dir, it's a file. This is slightly
          * inaccurate, since that means /dev/null is a file, /dev/printer
index 1d4081e29212e9dcd851e8e39efbaccfc7fe3273..61d744ca70cdc980d21b98734a06b25682e3e1d9 100644 (file)
@@ -321,7 +321,7 @@ static int getvolparams(const AFPObj *obj, uint16_t bitmap, struct vol *vol, str
      * .Parent file here if it doesn't exist. */
 
     /* Convert adouble:v2 to adouble:ea on the fly */
-    (void)ad_convert(vol->v_path, st, vol);
+    (void)ad_convert(vol->v_path, st, vol, NULL);
 
     ad_init(&ad, vol);
     if (ad_open(&ad, vol->v_path, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0 ) {
index 9685c3d219c341a81aa48de436abd2e3f3bb4ca0..4baea635cadc5bcdf033f70e63b0476a59e599dd 100644 (file)
@@ -221,7 +221,7 @@ static int check_adfile(const char *fname, const struct stat *st)
     if (myvol->v_adouble == AD_VERSION_EA) {
         if (!(dbd_flags & DBD_FLAGS_V2TOEA))
             return 0;
-        if (ad_convert(fname, st, myvol) != 0) {
+        if (ad_convert(fname, st, myvol, NULL) != 0) {
             switch (errno) {
             case ENOENT:
                 break;
@@ -1002,7 +1002,7 @@ static int scanvol(struct vol *vol, dbd_flags_t flags)
     if ((myvol->v_adouble == AD_VERSION_EA) && (dbd_flags & DBD_FLAGS_V2TOEA)) {
         if (lstat(".", &st) != 0)
             return -1;
-        if (ad_convert(".", &st, vol) != 0) {
+        if (ad_convert(".", &st, vol, NULL) != 0) {
             switch (errno) {
             case ENOENT:
                 break;
index 5b276a5a27a2e8255266eb5bbf810e3c0b19c2b8..f95279d7aa7779ada385ea7642799aad682b832e 100644 (file)
@@ -403,8 +403,11 @@ extern int ad_stat        (const char *, struct stat *);
 extern int ad_metadata    (const char *, int, struct adouble *);
 extern int ad_metadataat  (int, const char *, int, struct adouble *);
 extern mode_t ad_hf_mode(mode_t mode);
-extern int ad_convert(const char *path, const struct stat *sp, const struct vol *vol);
 extern int ad_valid_header_osx(const char *path);
+
+/* ad_conv.c */
+extern int ad_convert(const char *path, const struct stat *sp, const struct vol *vol, const char **newpath);
+
 /* ad_read.c/ad_write.c */
 extern int     sys_ftruncate(int fd, off_t length);
 extern ssize_t ad_read(struct adouble *, uint32_t, off_t, char *, size_t);
index a2759aa18ca1cb455d73b0c1c6c3479a3c941882..06a56ac9736b3c81d6d7c942bd89f97b9bbced93 100644 (file)
@@ -83,6 +83,7 @@ struct path {
     int         m_type;             /* mac name type (long name, unicode */
     char        *m_name;            /* mac name */
     char        *u_name;            /* unix name */
+    char        *unconverted_name;  /* NULL or u_name before ad_convert() conversion */
     cnid_t      id;                 /* file id (only for getmetadata) */
     struct dir  *d_dir;             /* */
     int         st_valid;           /* does st_errno and st set */
index 6602926b6328986453cb395bbb9c476bdf582aca..49144a2aa62831042f33efff428316378d724b60 100644 (file)
@@ -2,7 +2,17 @@
 
 noinst_LTLIBRARIES = libadouble.la
 
-libadouble_la_SOURCES = ad_open.c ad_flush.c ad_read.c ad_write.c ad_size.c \
-       ad_mmap.c ad_lock.c ad_date.c ad_attr.c ad_sendfile.c
+libadouble_la_SOURCES = \
+       ad_attr.c \
+       ad_conv.c \
+       ad_date.c \
+       ad_flush.c \
+       ad_lock.c \
+       ad_mmap.c \
+       ad_open.c \
+       ad_read.c \
+       ad_sendfile.c \
+       ad_size.c \
+       ad_write.c
 
 noinst_HEADERS = ad_lock.h
diff --git a/libatalk/adouble/ad_conv.c b/libatalk/adouble/ad_conv.c
new file mode 100644 (file)
index 0000000..10284db
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2012 Frank Lahm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*!
+ * @file
+ * Part of Netatalk's AppleDouble implementatation
+ * @sa include/atalk/adouble.h
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <errno.h>
+#include <sys/param.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <arpa/inet.h>
+
+#include <atalk/logger.h>
+#include <atalk/adouble.h>
+#include <atalk/util.h>
+#include <atalk/unix.h>
+#include <atalk/ea.h>
+#include <atalk/bstrlib.h>
+#include <atalk/bstradd.h>
+#include <atalk/compat.h>
+#include <atalk/errchk.h>
+#include <atalk/volume.h>
+
+#include "ad_lock.h"
+
+static char emptyfilad[32] = {0,0,0,0,0,0,0,0,
+                              0,0,0,0,0,0,0,0,
+                              0,0,0,0,0,0,0,0,
+                              0,0,0,0,0,0,0,0};
+
+static char emptydirad[32] = {0,0,0,0,0,0,0,0,
+                              0,0,0,0,0,0,1,0,
+                              0,0,0,0,0,0,0,0,
+                              0,0,0,0,0,0,0,0};
+
+static int ad_conv_v22ea_hf(const char *path, const struct stat *sp, const struct vol *vol)
+{
+    EC_INIT;
+    struct adouble adv2;
+    struct adouble adea;
+    const char *adpath;
+    int adflags;
+    uint32_t ctime, mtime, afpinfo = 0;
+    char *emptyad;
+
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): BEGIN", fullpathname(path));
+
+    ad_init(&adea, vol);
+    ad_init_old(&adv2, AD_VERSION2, adea.ad_options);
+    adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
+
+    /* Open and lock adouble:v2 file */
+    EC_ZERO( ad_open(&adv2, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR) );
+
+    EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) );
+    EC_NEG1_LOG( adv2.ad_ops->ad_header_read(path, &adv2, sp) );
+
+    /* Check if it's a non-empty header */
+    if (S_ISREG(sp->st_mode))
+        emptyad = &emptyfilad[0];
+    else
+        emptyad = &emptydirad[0];
+
+    if (ad_getentrylen(&adv2, ADEID_COMMENT) != 0)
+        goto copy;
+    if (ad_getentryoff(&adv2, ADEID_FINDERI)
+        && (ad_getentrylen(&adv2, ADEID_FINDERI) == ADEDLEN_FINDERI)
+        && (memcmp(ad_entry(&adv2, ADEID_FINDERI), emptyad, ADEDLEN_FINDERI) != 0))
+        goto copy;
+    if (ad_getentryoff(&adv2, ADEID_FILEDATESI)) {
+        EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_CREATE | AD_DATE_UNIX, &ctime) );
+        EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_MODIFY | AD_DATE_UNIX, &mtime) );
+        if ((ctime != mtime) || (mtime != sp->st_mtime))
+            goto copy;
+    }
+    if (ad_getentryoff(&adv2, ADEID_AFPFILEI)) {
+        if (memcmp(ad_entry(&adv2, ADEID_AFPFILEI), &afpinfo, ADEDLEN_AFPFILEI) != 0)
+            goto copy;
+    }
+
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): default adouble", fullpathname(path), ret);
+    goto EC_CLEANUP;
+
+copy:
+    /* Create a adouble:ea meta EA */
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): copying adouble", fullpathname(path), ret);
+    EC_ZERO_LOG( ad_open(&adea, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE) );
+    EC_ZERO_LOG( ad_copy_header(&adea, &adv2) );
+    ad_flush(&adea);
+
+EC_CLEANUP:
+    EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_SETSHRMD) );
+    EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_SETSHRMD) );
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): END: %d", fullpathname(path), ret);
+    EC_EXIT;
+}
+
+static int ad_conv_v22ea_rf(const char *path, const struct stat *sp, const struct vol *vol)
+{
+    EC_INIT;
+    struct adouble adv2;
+    struct adouble adea;
+
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): BEGIN", fullpathname(path));
+
+    if (S_ISDIR(sp->st_mode))
+        return 0;
+
+    ad_init(&adea, vol);
+    ad_init_old(&adv2, AD_VERSION2, adea.ad_options);
+
+    /* Open and lock adouble:v2 file */
+    EC_ZERO( ad_open(&adv2, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR) );
+
+    if (adv2.ad_rlen > 0) {
+        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( copy_fork(ADEID_RFORK, &adea, &adv2) );
+        adea.ad_rlen = adv2.ad_rlen;
+        ad_flush(&adea);
+    }
+
+EC_CLEANUP:
+    EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_RF) );
+    EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_RF) );
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): END: %d", fullpathname(path), ret);
+    EC_EXIT;
+}
+
+static int ad_conv_v22ea(const char *path, const struct stat *sp, const struct vol *vol)
+{
+    EC_INIT;
+    const char *adpath;
+    int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
+
+    EC_ZERO( ad_conv_v22ea_hf(path, sp, vol) );
+    EC_ZERO( ad_conv_v22ea_rf(path, sp, vol) );
+
+    EC_NULL( adpath = ad_path(path, adflags) );
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): deleting adouble:v2 file: \"%s\"",
+        path, fullpathname(adpath));
+
+    become_root();
+    EC_ZERO_LOG( unlink(adpath) );
+    unbecome_root();
+
+EC_CLEANUP:
+    if (errno == ENOENT)
+        EC_STATUS(0);
+    EC_EXIT;
+}
+
+/*!
+ * Remove hexencoded dots and slashes (":2e" and ":2f")
+ */
+static int ad_conv_dehex(const char *path, const struct stat *sp, const struct vol *vol, const char **newpathp)
+{
+    EC_INIT;
+    static char buf[MAXPATHLEN];
+    const char *adpath, *p;
+    int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
+    bstring newpath = NULL;
+
+    LOG(log_debug, logtype_default,"ad_conv_dehex(\"%s\"): BEGIN", fullpathname(path));
+
+    *newpathp = NULL;
+
+    if ((p = strchr(path, ':')) == NULL)
+        goto EC_CLEANUP;
+
+    EC_NULL( newpath = bfromcstr(path) );
+
+    EC_ZERO( bfindreplace(newpath, bfromcstr(":2e"), bfromcstr("."), 0) );
+    EC_ZERO( bfindreplace(newpath, bfromcstr(":2f"), bfromcstr(":"), 0) );
+    
+    become_root();
+    if (adflags != ADFLAGS_DIR)
+        rename(vol->ad_path(path, 0), vol->ad_path(bdata(newpath), 0));
+    rename(path, bdata(newpath));
+    unbecome_root();
+
+    strlcpy(buf, bdata(newpath), sizeof(buf));
+    *newpathp = buf;
+
+EC_CLEANUP:
+    if (newpath)
+        bdestroy(newpath);
+    EC_EXIT;
+}
+
+/*!
+ * AppleDouble and encoding conversion on the fly
+ *
+ * @param path      (r) path to file or directory
+ * @param sp        (r) stat(path)
+ * @param vol       (r) volume handle
+ * @param newpath   (w) if encoding changed, new name. Can be NULL.
+ *
+ * @returns         -1 on internal error, otherwise 0. newpath is NULL if no character conversion was done,
+ *                  otherwise newpath points to a static string with the converted name
+ */
+int ad_convert(const char *path, const struct stat *sp, const struct vol *vol, const char **newpath)
+{
+    EC_INIT;
+    const char *p;
+
+    LOG(log_debug, logtype_default,"ad_convert(\"%s\"): BEGIN", fullpathname(path));
+
+    if (newpath)
+        *newpath = NULL;
+
+    if ((vol->v_adouble == AD_VERSION_EA) && !(vol->v_flags & AFPVOL_NOV2TOEACONV))
+        EC_ZERO( ad_conv_v22ea(path, sp, vol) );
+
+    if (vol->v_adouble == AD_VERSION_EA) {
+        EC_ZERO( ad_conv_dehex(path, sp, vol, &p) );
+        if (p && newpath)
+            *newpath = p;
+    }
+
+EC_CLEANUP:
+    LOG(log_debug, logtype_default,"ad_convert(\"%s\"): END: %d", fullpathname(path), ret);
+    EC_EXIT;
+}
+
index 196053ee31ab288601b4c365f56da42600c00263..79016b5feac43e1d6fed2110e2d5e320610470e9 100644 (file)
@@ -809,111 +809,6 @@ static int ad2openflags(const struct adouble *ad, int adfile, int adflags)
     return oflags;
 }
 
-static char emptyfilad[32] = {0,0,0,0,0,0,0,0,
-                              0,0,0,0,0,0,0,0,
-                              0,0,0,0,0,0,0,0,
-                              0,0,0,0,0,0,0,0};
-
-static char emptydirad[32] = {0,0,0,0,0,0,0,0,
-                              0,0,0,0,0,0,1,0,
-                              0,0,0,0,0,0,0,0,
-                              0,0,0,0,0,0,0,0};
-
-static int ad_conv_v22ea_hf(const char *path, const struct stat *sp, const struct vol *vol)
-{
-    EC_INIT;
-    struct adouble adv2;
-    struct adouble adea;
-    const char *adpath;
-    int adflags;
-    uint32_t ctime, mtime, afpinfo = 0;
-    char *emptyad;
-
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): BEGIN", fullpathname(path));
-
-    ad_init(&adea, vol);
-    ad_init_old(&adv2, AD_VERSION2, adea.ad_options);
-    adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
-
-    /* Open and lock adouble:v2 file */
-    EC_ZERO( ad_open(&adv2, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR) );
-    EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) );
-    EC_NEG1_LOG( adv2.ad_ops->ad_header_read(path, &adv2, sp) );
-
-    /* Check if it's a non-empty header */
-    if (S_ISREG(sp->st_mode))
-        emptyad = &emptyfilad[0];
-    else
-        emptyad = &emptydirad[0];
-
-    if (ad_getentrylen(&adv2, ADEID_COMMENT) != 0)
-        goto copy;
-    if (ad_getentryoff(&adv2, ADEID_FINDERI)
-        && (ad_getentrylen(&adv2, ADEID_FINDERI) == ADEDLEN_FINDERI)
-        && (memcmp(ad_entry(&adv2, ADEID_FINDERI), emptyad, ADEDLEN_FINDERI) != 0))
-        goto copy;
-    if (ad_getentryoff(&adv2, ADEID_FILEDATESI)) {
-        EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_CREATE | AD_DATE_UNIX, &ctime) );
-        EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_MODIFY | AD_DATE_UNIX, &mtime) );
-        if ((ctime != mtime) || (mtime != sp->st_mtime))
-            goto copy;
-    }
-    if (ad_getentryoff(&adv2, ADEID_AFPFILEI)) {
-        if (memcmp(ad_entry(&adv2, ADEID_AFPFILEI), &afpinfo, ADEDLEN_AFPFILEI) != 0)
-            goto copy;
-    }
-
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): default adouble", fullpathname(path), ret);
-    goto EC_CLEANUP;
-
-copy:
-    /* Create a adouble:ea meta EA */
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): copying adouble", fullpathname(path), ret);
-    EC_ZERO_LOG( ad_open(&adea, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE) );
-    EC_ZERO_LOG( ad_copy_header(&adea, &adv2) );
-    ad_flush(&adea);
-
-EC_CLEANUP:
-    EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_SETSHRMD) );
-    EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_SETSHRMD) );
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): END: %d", fullpathname(path), ret);
-    EC_EXIT;
-}
-
-static int ad_conv_v22ea_rf(const char *path, const struct stat *sp, const struct vol *vol)
-{
-    EC_INIT;
-    struct adouble adv2;
-    struct adouble adea;
-
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): BEGIN", fullpathname(path));
-
-    if (S_ISDIR(sp->st_mode))
-        return 0;
-
-    ad_init(&adea, vol);
-    ad_init_old(&adv2, AD_VERSION2, adea.ad_options);
-
-    /* Open and lock adouble:v2 file */
-    EC_ZERO( ad_open(&adv2, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR) );
-    if (adv2.ad_rlen > 0) {
-        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( copy_fork(ADEID_RFORK, &adea, &adv2) );
-        adea.ad_rlen = adv2.ad_rlen;
-        ad_flush(&adea);
-    }
-
-EC_CLEANUP:
-    EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_RF) );
-    EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_RF) );
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): END: %d", fullpathname(path), ret);
-    EC_EXIT;
-}
-
 static int ad_open_df(const char *path, int adflags, mode_t mode, struct adouble *ad)
 {
     EC_INIT;
@@ -1929,33 +1824,6 @@ EC_CLEANUP:
     return ret;
 }
 
-int ad_convert(const char *path, const struct stat *sp, const struct vol *vol)
-{
-    EC_INIT;
-    const char *adpath;
-    int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
-
-    LOG(log_debug, logtype_default,"ad_convert(\"%s\"): BEGIN", fullpathname(path));
-
-    if (!(vol->v_adouble == AD_VERSION_EA) || (vol->v_flags & AFPVOL_NOV2TOEACONV))
-        goto EC_CLEANUP;
-
-    EC_ZERO( ad_conv_v22ea_hf(path, sp, vol) );
-    EC_ZERO( ad_conv_v22ea_rf(path, sp, vol) );
-
-    EC_NULL( adpath = ad_path(path, adflags) );
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): deleting adouble:v2 file: \"%s\"",
-        path, fullpathname(adpath));
-
-    become_root();
-    EC_ZERO_LOG( unlink(adpath) );
-    unbecome_root();
-
-EC_CLEANUP:
-    LOG(log_debug, logtype_default,"ad_convert(\"%s\"): END: %d", fullpathname(path), ret);
-    EC_EXIT;
-}
-
 /* build a resource fork mode from the data fork mode:
  * remove X mode and extend header to RW if R or W (W if R for locking),
  */