]> arthur.barton.de Git - netatalk.git/commitdiff
Convert name of objects
authorFrank Lahm <franklahm@googlemail.com>
Sun, 10 Oct 2010 13:40:02 +0000 (15:40 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Sun, 10 Oct 2010 13:40:02 +0000 (15:40 +0200)
bin/ad/ad.h
bin/ad/ad_cp.c
bin/ad/ad_util.c
include/atalk/util.h
libatalk/util/unix.c
libatalk/vfs/vfs.c

index 964f316400fe790d9f64d900354f80b529836aad..85cdbda38a54d69dae44a40cbfaffad662f3dc67 100644 (file)
@@ -61,19 +61,12 @@ extern cnid_t cnid_for_path(const struct volinfo *vi,
                             const char *path,
                             cnid_t *did);
 extern char *utompath(const struct volinfo *volinfo, const char *upath);
-
-struct FTWELEM {
-    const struct FTW  *ftw;
-    const char        *ftw_path;
-    int               ftw_base_off;
-    int               ftw_tflag;
-    const struct stat *ftw_statp;
-};
+extern int convert_dots_encoding(const afpvol_t *svol, const afpvol_t *dvol, char *path, size_t buflen);
 
 typedef struct {
     char *p_end;/* pointer to NULL at end of path */
     char *target_end;/* pointer to end of target base */
-    char p_path[PATH_MAX];/* pointer to the start of a path */
+    char p_path[MAXPATHLEN + 2];/* pointer to the start of a path */
 } PATH_T;
 
 extern PATH_T to;
index dfb2b7362d788010ea3bff61871ab10b5d8fd8b7..c198e22885f3eb12adcbebb21703d71949f21ccf 100644 (file)
@@ -492,6 +492,14 @@ static int copy(const char *path,
         SLOG("%s is a FIFO (not copied).", path);
         break;
     default:
+        if (dvolume.volinfo.v_path) {
+            if ((convert_dots_encoding(&svolume, &dvolume, to.p_path, MAXPATHLEN)) == -1) {
+                SLOG("Error converting name for %s", to.p_path);
+                badcp = rval = 1;
+                break;
+            }
+        }
+
         if (ftw_copy_file(ftw, path, statp, dne))
             badcp = rval = 1;
 
index ac05fc0a8807d09b360330da0d9e6aeef0a12ee0..f951d25e9826698a9a89b65cef056b7163497d14 100644 (file)
@@ -55,6 +55,8 @@
 #include <atalk/util.h>
 #include <atalk/logger.h>
 #include <atalk/errchk.h>
+#include <atalk/unicode.h>
+
 #include "ad.h"
 
 int log_verbose;             /* Logging flag */
@@ -223,6 +225,59 @@ EC_CLEANUP:
     return NULL;
 }
 
+/*!
+ * Convert dot encoding of basename _in place_
+ *
+ * path arg can be "[/][dir/ | ...]filename". It will be converted in place
+ * possible encoding ".file" as ":2efile" which means the result will be
+ * longer then the original which means provide a big enough buffer.
+ *
+ * @param svol   (r)  source volume
+ * @param dvol   (r)  destinatio volume
+ * @param path   (rw) path to convert _in place_
+ * @param buflen (r)  size of path buffer (max strlen == buflen -1)
+ *
+ * @returns 0 on sucess, -1 on error
+ */
+int convert_dots_encoding(const afpvol_t *svol, const afpvol_t *dvol, char *path, size_t buflen)
+{
+    static charset_t from = (charset_t) -1;
+    static char buf[MAXPATHLEN+2];
+    char *bname = stripped_slashes_basename(path);
+    int pos = bname - path;
+    uint16_t flags = 0;
+
+    if ( ! svol->volinfo.v_path) {
+        /* no source volume: escape special chars (eg ':') */
+        from = dvol->volinfo.v_volcharset; /* src = dst charset */
+        flags |= CONV_ESCAPEHEX;
+    } else {
+        from = svol->volinfo.v_volcharset;
+    }
+
+    if ( (svol->volinfo.v_path)
+         && ! (svol->volinfo.v_flags & AFPVOL_USEDOTS)
+         && (dvol->volinfo.v_flags & AFPVOL_USEDOTS)) {
+        /* source is without dots, destination is with */
+        flags |= CONV_UNESCAPEHEX;
+    } else if (! (dvol->volinfo.v_flags & AFPVOL_USEDOTS)) {
+        flags |= CONV_ESCAPEDOTS;
+    }
+
+    int len = convert_charset(from,
+                              dvol->volinfo.v_volcharset,
+                              dvol->volinfo.v_maccharset,
+                              bname, strlen(bname),
+                              buf, MAXPATHLEN,
+                              &flags);
+    if (len == -1)
+        return -1;
+
+    if (strlcpy(bname, buf, MAXPATHLEN - pos) > MAXPATHLEN - pos)
+        return -1;
+    return 0;
+}
+
 /*!
  * ResolvesCNID of a given paths
  *
index 3f10132121a62f7ca79f734477f191e9032b739f..ad917cd3062a219e7a8bf350f12a4266b5c03b41 100644 (file)
@@ -47,6 +47,7 @@
 #define AFP_ASSERT(b)
 #endif /* NDEBUG */
 
+
 #ifdef WITH_SENDFILE
 extern ssize_t sys_sendfile (int __out_fd, int __in_fd, off_t *__offset,size_t __count);
 #endif
@@ -139,6 +140,7 @@ extern int compare_ip(const struct sockaddr *sa1, const struct sockaddr *sa2);
  *****************************************************************/
 
 extern const char *getcwdpath(void);
+extern char *stripped_slashes_basename(char *p);
 extern int lchdir(const char *dir);
 
 #endif  /* _ATALK_UTIL_H */
index 6231a03782c538809dd632593c0796bd9e57fc9a..1c131ad507c9712a4de3a18f8648795b89c950ef 100644 (file)
@@ -1,5 +1,4 @@
 /*
-  $Id: unix.c,v 1.6 2010-02-28 22:29:16 didg Exp $
   Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
 
   This program is free software; you can redistribute it and/or modify
@@ -56,6 +55,26 @@ const char *getcwdpath(void)
         return strerror(errno);
 }
 
+/*!
+ * Takes a buffer with a path, strips slashs, returns basename
+ *
+ * @param p (rw) path
+ *        path may be
+ *          "[/][dir/[...]]file"
+ *        or
+ *          "[/][dir/[...]]dir/[/]"
+ *        Result is "file" or "dir" 
+ *
+ * @returns pointer to basename in path buffer, buffer is possibly modified
+ */
+char *stripped_slashes_basename(char *p)
+{
+    int i = strlen(p) - 1;
+    while (i > 0 && p[i] == '/')
+        p[i--] = 0;
+    return (strrchr(p, '/') ? strrchr(p, '/') + 1 : p);
+}
+
 /*!
  * @brief symlink safe chdir replacement
  *
index 8213dbe24af65d4b7f5ccac3f672cd2b3e9e343e..2431144ce7137112364478f1f29924f2b7640160 100644 (file)
@@ -335,6 +335,7 @@ static int RF_copyfile_adouble(VFS_FUNC_ARGS_COPYFILE)
     char *dup1 = NULL;
     char *dup2 = NULL;
     char *dup3 = NULL;
+    char *dup4 = NULL;
     const char *name = NULL;
     const char *dir = NULL;
 
@@ -351,22 +352,25 @@ static int RF_copyfile_adouble(VFS_FUNC_ARGS_COPYFILE)
         EC_ZERO(bcatcstr(d, "/.AppleDouble/.Parent"));
     } else {
         /* get basename */
-        EC_NULL(dup1 = strdup(dst));
-        EC_NULL(name = basename(strdup(dup1)));
 
         /* build src path to AppleDouble file*/
+        EC_NULL(dup1 = strdup(src));
+        EC_NULL(name = basename(strdup(dup1)));
+
         EC_NULL(dup2 = strdup(src));
         EC_NULL(dir = dirname(dup2));
         EC_NULL(s = bfromcstr(dir));
+        EC_ZERO(bcatcstr(s, "/.AppleDouble/"));
+        EC_ZERO(bcatcstr(s, name));
 
         /* build dst path to AppleDouble file*/
+        EC_NULL(dup4 = strdup(dst));
+        EC_NULL(name = basename(strdup(dup4)));
+
         EC_NULL(dup3 = strdup(dst));
         EC_NULL(dir = dirname(dup3));
         EC_NULL(d = bfromcstr(dir));
-
-        EC_ZERO(bcatcstr(s, "/.AppleDouble/"));
         EC_ZERO(bcatcstr(d, "/.AppleDouble/"));
-        EC_ZERO(bcatcstr(s, name));
         EC_ZERO(bcatcstr(d, name));
     }
 
@@ -378,6 +382,7 @@ EC_CLEANUP:
     if (dup1) free(dup1);
     if (dup2) free(dup2);
     if (dup3) free(dup3);
+    if (dup4) free(dup4);
 
     EC_EXIT;
 }