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;
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;
#include <atalk/util.h>
#include <atalk/logger.h>
#include <atalk/errchk.h>
+#include <atalk/unicode.h>
+
#include "ad.h"
int log_verbose; /* Logging flag */
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
*
#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
*****************************************************************/
extern const char *getcwdpath(void);
+extern char *stripped_slashes_basename(char *p);
extern int lchdir(const char *dir);
#endif /* _ATALK_UTIL_H */
/*
- $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
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
*
char *dup1 = NULL;
char *dup2 = NULL;
char *dup3 = NULL;
+ char *dup4 = NULL;
const char *name = NULL;
const char *dir = NULL;
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));
}
if (dup1) free(dup1);
if (dup2) free(dup2);
if (dup3) free(dup3);
+ if (dup4) free(dup4);
EC_EXIT;
}