]> arthur.barton.de Git - netatalk.git/commitdiff
Rename cfrombstring to cfrombstr and msic
authorFrank Lahm <franklahm@googlemail.com>
Wed, 6 Oct 2010 15:11:51 +0000 (17:11 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Wed, 6 Oct 2010 15:11:51 +0000 (17:11 +0200)
24 files changed:
bin/Makefile.am
bin/ad/.gitignore [new file with mode: 0644]
bin/ad/Makefile.am [new file with mode: 0644]
bin/ad/ad.c [new file with mode: 0644]
bin/ad/ad.h [new file with mode: 0644]
bin/ad/ad_cp.c [new file with mode: 0644]
bin/ad/ad_ls.c [new file with mode: 0644]
bin/ad/ad_util.c [new file with mode: 0644]
bin/cnid/Makefile.am
bin/cnid/ad.c [deleted file]
bin/cnid/ad.h [deleted file]
bin/cnid/ad_cp.c [deleted file]
bin/cnid/ad_ls.c [deleted file]
bin/cnid/ad_util.c [deleted file]
configure.in
etc/afpd/appl.c
etc/afpd/catsearch.c
etc/afpd/dircache.c
etc/afpd/directory.c
etc/afpd/enumerate.c
etc/afpd/filedir.c
etc/afpd/mangle.c
etc/afpd/ofork.c
include/atalk/bstradd.h

index 5e36848600c1dab9d3fcdfafc4e860dc1b99a1c2..86978ace545e5df9d71d005a761e6222d35f4adb 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile.am for bin/
 
-SUBDIRS = adv1tov2 afile afppasswd cnid megatron uniconv misc
+SUBDIRS = ad adv1tov2 afile afppasswd cnid megatron uniconv misc
 
 if USE_APPLETALK
 SUBDIRS += aecho getzones nbp pap psorder
diff --git a/bin/ad/.gitignore b/bin/ad/.gitignore
new file mode 100644 (file)
index 0000000..28432ec
--- /dev/null
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+ad
+.deps
+.libs
+*.o
diff --git a/bin/ad/Makefile.am b/bin/ad/Makefile.am
new file mode 100644 (file)
index 0000000..20dec08
--- /dev/null
@@ -0,0 +1,19 @@
+# Makefile.am for bin/ad/
+
+noinst_HEADERS = ad.h
+
+if USE_BDB
+bin_PROGRAMS = ad
+
+ad_SOURCES = \
+       ad.c \
+       ad_util.c \
+       ad_ls.c \
+       ad_cp.c
+
+ad_LDADD = \
+       $(top_builddir)/libatalk/cnid/libcnid.la \
+       $(top_builddir)/libatalk/libatalk.la \
+       @ACL_LIBS@
+
+endif
diff --git a/bin/ad/ad.c b/bin/ad/ad.c
new file mode 100644 (file)
index 0000000..e272f5b
--- /dev/null
@@ -0,0 +1,61 @@
+/* 
+   Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
+   
+   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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+
+#include <atalk/cnid.h>
+#include <atalk/volinfo.h>
+#include <atalk/logger.h>
+#include "ad.h"
+
+static void usage_main(void)
+{
+/*
+    printf("Usage: ad ls|rm|cp|mv|set [file|dir, ...]\n");
+*/
+    printf("Usage: ad ls [file|dir, ...]\n");
+}
+
+int main(int argc, char **argv)
+{
+    setuplog("default log_note /dev/tty");
+
+    if (argc < 2) {
+        usage_main();
+        return 1;
+    }
+
+    if (STRCMP(argv[1], ==, "ls"))
+        return ad_ls(argc - 1, argv + 1);
+    else if (STRCMP(argv[1], ==, "cp"))
+        return ad_cp(argc - 1, argv + 1);
+    else {
+        usage_main();
+        return 1;
+    }
+
+    return 0;
+}
diff --git a/bin/ad/ad.h b/bin/ad/ad.h
new file mode 100644 (file)
index 0000000..e47c384
--- /dev/null
@@ -0,0 +1,87 @@
+/* 
+   Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
+   
+   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.
+*/
+
+#ifndef AD_H
+#define AD_H
+
+#define _XOPEN_SOURCE 600
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+#include <atalk/ftw.h>
+#include <atalk/volinfo.h>
+
+#define STRCMP(a,b,c) (strcmp(a,c) b 0)
+
+#define DIR_DOT_OR_DOTDOT(a) \
+        ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0))
+
+enum logtype {STD, DBG};
+
+#define SLOG(...)                             \
+    _log(STD, __VA_ARGS__)
+
+#define ERROR(...)                              \
+    do {                                        \
+        _log(STD, __VA_ARGS__);                 \
+        exit(1);                                \
+    } while (0)
+
+typedef struct {
+    struct volinfo volinfo;
+//    char *basename;
+} afpvol_t;
+
+extern int log_verbose;             /* Logging flag */
+extern void _log(enum logtype lt, char *fmt, ...);
+
+extern struct volinfo svolinfo, dvolinfo;
+extern struct vol svolume, dvolume;
+
+extern int ad_ls(int argc, char **argv);
+extern int ad_cp(int argc, char **argv);
+
+/* ad_util.c */
+extern int newvol(const char *path, afpvol_t *vol);
+extern void freevol(afpvol_t *vol);
+extern cnid_t cnid_for_path(const struct volinfo *vi, const struct vol *vol, const char *path);
+extern char *utompath(const struct volinfo *volinfo, char *upath);
+
+struct FTWELEM {
+    const struct FTW  *ftw;
+    const char        *ftw_path;
+    int               ftw_base_off;
+    int               ftw_tflag;
+    const struct stat *ftw_statp;
+};
+
+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 */
+} PATH_T;
+
+extern PATH_T to;
+extern int fflag, iflag, lflag, nflag, pflag, vflag;
+extern volatile sig_atomic_t info;
+
+extern int ftw_copy_file(const struct FTW *, const char *, const struct stat *, int);
+extern int copy_link(const struct FTW *, const char *, const struct stat *, int);
+extern int setfile(const struct stat *, int);
+extern int preserve_dir_acls(const struct stat *, char *, char *);
+extern int preserve_fd_acls(int, int);
+
+#endif /* AD_H */
diff --git a/bin/ad/ad_cp.c b/bin/ad/ad_cp.c
new file mode 100644 (file)
index 0000000..25a3654
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ * Copyright (c) 2010, Frank Lahm <franklahm@googlemail.com>
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * David Hitz of Auspex Systems Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Cp copies source files to target files.
+ *
+ * The global PATH_T structure "to" always contains the path to the
+ * current target file.  Since fts(3) does not change directories,
+ * this path can be either absolute or dot-relative.
+ *
+ * The basic algorithm is to initialize "to" and use fts(3) to traverse
+ * the file hierarchy rooted in the argument list.  A trivial case is the
+ * case of 'cp file1 file2'.  The more interesting case is the case of
+ * 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the
+ * path (relative to the root of the traversal) is appended to dir (stored
+ * in "to") to form the final target path.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atalk/ftw.h>
+#include <atalk/adouble.h>
+#include <atalk/vfs.h>
+#include <atalk/util.h>
+#include <atalk/unix.h>
+#include <atalk/volume.h>
+#include <atalk/volinfo.h>
+#include <atalk/bstrlib.h>
+#include <atalk/bstradd.h>
+#include <atalk/queue.h>
+
+#include "ad.h"
+
+#define STRIP_TRAILING_SLASH(p) {                                   \
+        while ((p).p_end > (p).p_path + 1 && (p).p_end[-1] == '/')  \
+            *--(p).p_end = 0;                                       \
+    }
+
+static char emptystring[] = "";
+
+PATH_T to = { to.p_path, emptystring, "" };
+
+int fflag, iflag, lflag, nflag, pflag, vflag;
+mode_t mask;
+struct volinfo svolinfo, dvolinfo;
+struct vol svolume, dvolume;
+cnid_t did = 0; /* current dir CNID */
+
+static enum op type;
+static int Rflag;
+volatile sig_atomic_t sigint;
+static int badcp, rval;
+static int ftw_options = FTW_MOUNT | FTW_PHYS | FTW_ACTIONRETVAL;
+static q_t *cnidq;              /* CNID dir stack */
+
+enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
+
+static char           *netatalk_dirs[] = {
+    ".AppleDouble",
+    ".AppleDB",
+    ".AppleDesktop",
+    NULL
+};
+
+static int copy(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf);
+static void siginfo(int _U_);
+
+/*
+  Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
+  Returns pointer to name or NULL.
+*/
+static const char *check_netatalk_dirs(const char *name)
+{
+    int c;
+
+    for (c=0; netatalk_dirs[c]; c++) {
+        if ((strcmp(name, netatalk_dirs[c])) == 0)
+            return netatalk_dirs[c];
+    }
+    return NULL;
+}
+
+
+static void usage_cp(void)
+{
+    printf(
+        "Usage: ad cp [-R [-P]] [-pvf] <source_file> <target_file>\n"
+        "Usage: ad cp [-R [-P]] [-pvfx] <source_file [source_file ...]> <target_directory>\n"
+        );
+    exit(EXIT_FAILURE);
+}
+
+static void upfunc(void)
+{
+    if (cnidq) {
+        cnid_t *cnid = dequeue(cnidq);
+        if (cnid) {
+            did = *cnid;
+            free(cnid);
+        }
+    }
+}
+
+int ad_cp(int argc, char *argv[])
+{
+    struct stat to_stat, tmp_stat;
+    int r, ch, have_trailing_slash;
+    char *target;
+#if 0
+    afpvol_t srcvol;
+    afpvol_t dstvol;
+#endif
+
+    while ((ch = getopt(argc, argv, "Rafilnpvx")) != -1)
+        switch (ch) {
+        case 'R':
+            Rflag = 1;
+            break;
+        case 'a':
+            pflag = 1;
+            Rflag = 1;
+            break;
+        case 'f':
+            fflag = 1;
+            iflag = nflag = 0;
+            break;
+        case 'i':
+            iflag = 1;
+            fflag = nflag = 0;
+            break;
+        case 'l':
+            lflag = 1;
+            break;
+        case 'n':
+            nflag = 1;
+            fflag = iflag = 0;
+            break;
+        case 'p':
+            pflag = 1;
+            break;
+        case 'v':
+            vflag = 1;
+            break;
+        case 'x':
+            ftw_options |= FTW_MOUNT;
+            break;
+        default:
+            usage_cp();
+            break;
+        }
+    argc -= optind;
+    argv += optind;
+
+    if (argc < 2)
+        usage_cp();
+
+    (void)signal(SIGINT, siginfo);
+
+    cnid_init();
+
+    /* Save the target base in "to". */
+    target = argv[--argc];
+    if ((strlcpy(to.p_path, target, PATH_MAX)) >= PATH_MAX)
+        ERROR("%s: name too long", target);
+
+    to.p_end = to.p_path + strlen(to.p_path);
+    if (to.p_path == to.p_end) {
+        *to.p_end++ = '.';
+        *to.p_end = 0;
+    }
+    have_trailing_slash = (to.p_end[-1] == '/');
+    if (have_trailing_slash)
+        STRIP_TRAILING_SLASH(to);
+    to.target_end = to.p_end;
+
+    /* Set end of argument list */
+    argv[argc] = NULL;
+
+    /*
+     * Cp has two distinct cases:
+     *
+     * cp [-R] source target
+     * cp [-R] source1 ... sourceN directory
+     *
+     * In both cases, source can be either a file or a directory.
+     *
+     * In (1), the target becomes a copy of the source. That is, if the
+     * source is a file, the target will be a file, and likewise for
+     * directories.
+     *
+     * In (2), the real target is not directory, but "directory/source".
+     */
+    r = stat(to.p_path, &to_stat);
+    if (r == -1 && errno != ENOENT)
+        ERROR("%s", to.p_path);
+    if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
+        /*
+         * Case (1).  Target is not a directory.
+         */
+        if (argc > 1)
+            ERROR("%s is not a directory", to.p_path);
+
+        /*
+         * Need to detect the case:
+         *cp -R dir foo
+         * Where dir is a directory and foo does not exist, where
+         * we want pathname concatenations turned on but not for
+         * the initial mkdir().
+         */
+        if (r == -1) {
+            lstat(*argv, &tmp_stat);
+
+            if (S_ISDIR(tmp_stat.st_mode) && Rflag)
+                type = DIR_TO_DNE;
+            else
+                type = FILE_TO_FILE;
+        } else
+            type = FILE_TO_FILE;
+
+        if (have_trailing_slash && type == FILE_TO_FILE) {
+            if (r == -1)
+                ERROR("directory %s does not exist", to.p_path);
+            else
+                ERROR("%s is not a directory", to.p_path);
+        }
+    } else
+        /*
+         * Case (2).  Target is a directory.
+         */
+        type = FILE_TO_DIR;
+
+    /*
+     * Keep an inverted copy of the umask, for use in correcting
+     * permissions on created directories when not using -p.
+     */
+    mask = ~umask(0777);
+    umask(~mask);
+
+#if 0
+    /* Inhereting perms in ad_mkdir etc requires this */
+    ad_setfuid(0);
+#endif
+
+    /* Load .volinfo file for destination*/
+    if (loadvolinfo(to.p_path, &dvolinfo) == 0) {
+        if (vol_load_charsets(&dvolinfo) == -1)
+            ERROR("Error loading charsets!");
+        /* Sanity checks to ensure we can touch this volume */
+        if (dvolinfo.v_vfs_ea != AFPVOL_EA_SYS)
+            ERROR("Unsupported Extended Attributes option: %u", dvolinfo.v_vfs_ea);
+
+        /* initialize sufficient struct vol and initialize CNID connection */
+        dvolume.v_adouble = AD_VERSION2;
+        dvolume.v_vfs_ea = AFPVOL_EA_SYS;
+        initvol_vfs(&dvolume);
+        int flags = 0;
+        if ((dvolinfo.v_flags & AFPVOL_NODEV))
+            flags |= CNID_FLAG_NODEV;
+
+        if ((dvolume.v_cdb = cnid_open(dvolinfo.v_path,
+                                       0000,
+                                       "dbd",
+                                       flags,
+                                       dvolinfo.v_dbd_host,
+                                       dvolinfo.v_dbd_port)) == NULL)
+            ERROR("Cant initialize CNID database connection for %s", dvolinfo.v_path);
+
+        /* setup a list for storing the CNID stack of dirs in destination path */
+        if ((cnidq = queue_init()) == NULL)
+            ERROR("Cant initialize CNID stack");
+    }
+
+    for (int i = 0; argv[i] != NULL; i++) { 
+        /* Load .volinfo file for source */
+        if (loadvolinfo(to.p_path, &svolinfo) == 0) {
+            if (vol_load_charsets(&svolinfo) == -1)
+                ERROR("Error loading charsets!");
+            /* Sanity checks to ensure we can touch this volume */
+            if (svolinfo.v_vfs_ea != AFPVOL_EA_SYS)
+                ERROR("Unsupported Extended Attributes option: %u", svolinfo.v_vfs_ea);
+
+            /* initialize sufficient struct vol and initialize CNID connection */
+            svolume.v_adouble = AD_VERSION2;
+            svolume.v_vfs_ea = AFPVOL_EA_SYS;
+            initvol_vfs(&svolume);
+            int flags = 0;
+            if ((svolinfo.v_flags & AFPVOL_NODEV))
+                flags |= CNID_FLAG_NODEV;
+
+            if ((svolume.v_cdb = cnid_open(svolinfo.v_path,
+                                           0000,
+                                           "dbd",
+                                           flags,
+                                           svolinfo.v_dbd_host,
+                                           svolinfo.v_dbd_port)) == NULL)
+                ERROR("Cant initialize CNID database connection for %s", svolinfo.v_path);
+        }
+
+        if (nftw(argv[i], copy, upfunc, 20, ftw_options) == -1) {
+            ERROR("%s: %s", argv[i], strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+
+        if (svolume.v_cdb)
+            cnid_close(svolume.v_cdb);
+        svolume.v_cdb = NULL;
+
+    }
+    return rval;
+}
+
+static int copy(const char *path,
+                const struct stat *statp,
+                int tflag,
+                struct FTW *ftw)
+{
+    struct stat to_stat;
+    int base = 0, dne;
+    size_t nlen;
+    const char *p;
+    char *target_mid;
+
+    const char *dir = strrchr(path, '/');
+    if (dir == NULL)
+        dir = path;
+    else
+        dir++;
+    if (check_netatalk_dirs(dir) != NULL) {
+        SLOG("Skipping Netatalk dir %s", path);
+        return FTW_SKIP_SIBLINGS;
+    }
+
+    /*
+     * If we are in case (2) above, we need to append the
+     * source name to the target name.
+     */
+    if (type != FILE_TO_FILE) {
+        /*
+         * Need to remember the roots of traversals to create
+         * correct pathnames.  If there's a directory being
+         * copied to a non-existent directory, e.g.
+         *     cp -R a/dir noexist
+         * the resulting path name should be noexist/foo, not
+         * noexist/dir/foo (where foo is a file in dir), which
+         * is the case where the target exists.
+         *
+         * Also, check for "..".  This is for correct path
+         * concatenation for paths ending in "..", e.g.
+         *     cp -R .. /tmp
+         * Paths ending in ".." are changed to ".".  This is
+         * tricky, but seems the easiest way to fix the problem.
+         *
+         * XXX
+         * Since the first level MUST be FTS_ROOTLEVEL, base
+         * is always initialized.
+         */
+        if (ftw->level == 0) {
+            if (type != DIR_TO_DNE) {
+                base = ftw->base;
+
+                if (strcmp(&path[base], "..") == 0)
+                    base += 1;
+            } else
+                base = strlen(path);
+        }
+
+        p = &path[base];
+        nlen = strlen(path) - base;
+        target_mid = to.target_end;
+        if (*p != '/' && target_mid[-1] != '/')
+            *target_mid++ = '/';
+        *target_mid = 0;
+        if (target_mid - to.p_path + nlen >= PATH_MAX) {
+            SLOG("%s%s: name too long (not copied)", to.p_path, p);
+            badcp = rval = 1;
+            return 0;
+        }
+        (void)strncat(target_mid, p, nlen);
+        to.p_end = target_mid + nlen;
+        *to.p_end = 0;
+        STRIP_TRAILING_SLASH(to);
+    }
+
+    /* Not an error but need to remember it happened */
+    if (stat(to.p_path, &to_stat) == -1)
+        dne = 1;
+    else {
+        if (to_stat.st_dev == statp->st_dev &&
+            to_stat.st_ino == statp->st_ino) {
+            SLOG("%s and %s are identical (not copied).",
+                to.p_path, path);
+            badcp = rval = 1;
+            if (S_ISDIR(statp->st_mode))
+                /* without using glibc extension FTW_ACTIONRETVAL cant handle this */
+                return -1;
+        }
+        if (!S_ISDIR(statp->st_mode) &&
+            S_ISDIR(to_stat.st_mode)) {
+            SLOG("cannot overwrite directory %s with "
+                "non-directory %s",
+                to.p_path, path);
+                badcp = rval = 1;
+                return 0;
+        }
+        dne = 0;
+    }
+
+    switch (statp->st_mode & S_IFMT) {
+    case S_IFLNK:
+        if (copy_link(ftw, path, statp, !dne))
+            badcp = rval = 1;
+        break;
+    case S_IFDIR:
+        if (!Rflag) {
+            SLOG("%s is a directory", path);
+            badcp = rval = 1;
+            return -1;
+        }
+        /*
+         * If the directory doesn't exist, create the new
+         * one with the from file mode plus owner RWX bits,
+         * modified by the umask.  Trade-off between being
+         * able to write the directory (if from directory is
+         * 555) and not causing a permissions race.  If the
+         * umask blocks owner writes, we fail..
+         */
+        if (dne) {
+            if (mkdir(to.p_path, statp->st_mode | S_IRWXU) < 0)
+                ERROR("%s", to.p_path);
+        } else if (!S_ISDIR(to_stat.st_mode)) {
+            errno = ENOTDIR;
+            ERROR("%s", to.p_path);
+        }
+
+        /* Create ad dir and copy ".Parent" */
+        if (svolinfo.v_path && svolinfo.v_adouble == AD_VERSION2 &&
+            dvolinfo.v_path && dvolinfo.v_adouble == AD_VERSION2) {
+            /* Create ".AppleDouble" dir */
+            mode_t omask = umask(0);
+            bstring addir = bfromcstr(to.p_path);
+            bcatcstr(addir, "/.AppleDouble");
+            mkdir(cfrombstr(addir), 02777);
+
+            /* copy ".Parent" file */
+            bcatcstr(addir, "/.Parent");
+            bstring sdir = bfromcstr(path);
+            bcatcstr(sdir, "/.AppleDouble/.Parent");
+            if (copy_file(-1, cfrombstr(sdir), cfrombstr(addir), 0666) != 0) {
+                SLOG("Error copying %s -> %s", cfrombstr(sdir), cfrombstr(addir));
+                badcp = rval = 1;
+                break;
+            }
+            umask(omask);
+
+            /* Get CNID of Parent and add new childir to CNID database */
+            did = cnid_for_path(&dvolinfo, &dvolume, to.p_path);
+        }
+
+        if (pflag) {
+            if (setfile(statp, -1))
+                rval = 1;
+#if 0
+            if (preserve_dir_acls(statp, curr->fts_accpath, to.p_path) != 0)
+                rval = 1;
+#endif
+        }
+        break;
+
+    case S_IFBLK:
+    case S_IFCHR:
+        SLOG("%s is a device file (not copied).", path);
+        break;
+    case S_IFSOCK:
+        SLOG("%s is a socket (not copied).", path);
+        break;
+    case S_IFIFO:
+        SLOG("%s is a FIFO (not copied).", path);
+        break;
+    default:
+        if (ftw_copy_file(ftw, path, statp, dne))
+            badcp = rval = 1;
+        break;
+    }
+    if (vflag && !badcp)
+        (void)printf("%s -> %s\n", path, to.p_path);
+
+    return 0;
+}
+
+static void siginfo(int sig _U_)
+{
+    sigint = 1;
+}
diff --git a/bin/ad/ad_ls.c b/bin/ad/ad_ls.c
new file mode 100644 (file)
index 0000000..87834d8
--- /dev/null
@@ -0,0 +1,635 @@
+/* 
+   Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
+   
+   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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+#include <time.h>
+
+#include <atalk/adouble.h>
+#include <atalk/cnid.h>
+#include <atalk/volinfo.h>
+#include "ad.h"
+
+#define ADv2_DIRNAME ".AppleDouble"
+
+#define DIR_DOT_OR_DOTDOT(a) \
+        ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0))
+
+/* ls options */
+static int ls_a;
+static int ls_l;
+static int ls_R;
+static int ls_d;
+static int ls_u;
+
+/* Used for pretty printing */
+static int first = 1;
+static int recursion;
+
+static char           *netatalk_dirs[] = {
+    ADv2_DIRNAME,
+    ".AppleDB",
+    ".AppleDesktop",
+    NULL
+};
+
+static char *labels[] = {
+    "---",
+    "gry",
+    "gre",
+    "vio",
+    "blu",
+    "yel",
+    "red",
+    "ora"
+};
+
+/*
+  Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
+  Returns pointer to name or NULL.
+*/
+static const char *check_netatalk_dirs(const char *name)
+{
+    int c;
+
+    for (c=0; netatalk_dirs[c]; c++) {
+        if ((strcmp(name, netatalk_dirs[c])) == 0)
+            return netatalk_dirs[c];
+    }
+    return NULL;
+}
+
+
+static void usage_ls(void)
+{
+    printf(
+        "Usage: ad ls [-dRl[u]] [file|dir, ...]\n\n"
+        "  -l Long Output [-u: unix info]:\n"
+        "     <unixinfo ...> <FinderFlags> <AFPAttributes> <Color> <Type> <Creator> <CNID from AppleDouble> <name>\n\n"
+        "     FinderFlags (valid for (f)ile and/or (d)irectory):\n"
+        "       d = On Desktop (f/d)\n"
+        "       e = Hidden extension (f/d)\n"
+        "       m = Shared (can run multiple times) (f)\n"
+        "       n = No INIT resources (f)\n"
+        "       i = Inited (f/d)\n"
+        "       c = Custom icon (f/d)\n"
+        "       t = Stationery (f)\n"
+        "       s = Name locked (f/d)\n"
+        "       b = Bundle (f/d)\n"
+        "       v = Invisible (f/d)\n"
+        "       a = Alias file (f/d)\n\n"
+        "     AFPAttributes:\n"
+        "       y = System (f/d)\n"
+        "       w = No write (f)\n"
+        "       p = Needs backup (f/d)\n"
+        "       r = No rename (f/d)\n"
+        "       l = No delete (f/d)\n"
+        "       o = No copy (f)\n\n"
+        "     Note: any letter appearing in uppercase means the flag is set\n"
+        "           but it's a directory for which the flag is not allowed.\n"
+        );
+}
+
+static void print_numlinks(const struct stat *statp)
+{
+    printf("%5ld", (long)statp->st_nlink);
+}
+
+static void print_owner(const struct stat *statp)
+{
+    struct passwd *pwd = getpwuid(statp->st_uid);
+
+    if (pwd == NULL)
+        printf(" %-8ld", (long)statp->st_uid);
+    else
+        printf(" %-8s", pwd->pw_name);
+}
+
+static void print_group(const struct stat *statp)
+{
+    struct group *grp = getgrgid(statp->st_gid);
+
+    if (grp == NULL)
+        printf(" %-8ld", (long)statp->st_gid);
+    else
+        printf(" %-8s", grp->gr_name);
+}
+
+static void print_size(const struct stat *statp)
+{
+    switch (statp->st_mode & S_IFMT) {
+    case S_IFCHR:
+    case S_IFBLK:
+        printf("%4u,%4u", (unsigned)(statp->st_rdev >> 8),
+               (unsigned)(statp->st_rdev & 0xFF));
+        break;
+    default:
+        printf("%9lu", (unsigned long)statp->st_size);
+    }
+}
+
+static void print_date(const struct stat *statp)
+{
+    time_t now;
+    double diff;
+    char buf[100], *fmt;
+
+    if (time(&now) == -1) {
+        printf(" ????????????");
+        return;
+    }
+    diff = difftime(now, statp->st_mtime);
+    if (diff < 0 || diff > 60 * 60 * 24 * 182.5)
+        fmt = "%b %e  %Y";
+    else
+        fmt = "%b %e %H:%M";
+    strftime(buf, sizeof(buf), fmt, localtime(&statp->st_mtime));
+    printf(" %s", buf);
+}
+
+static void print_flags(char *path, afpvol_t *vol, const struct stat *st)
+{
+    int adflags = 0;
+    struct adouble ad;
+    char *FinderInfo;
+    uint16_t FinderFlags;
+    uint16_t AFPattributes;
+    char type[5] = "----";
+    char creator[5] = "----";
+    int i;
+    uint32_t cnid;
+
+    if (S_ISDIR(st->st_mode))
+        adflags = ADFLAGS_DIR;
+
+    if (vol->volinfo.v_path == NULL)
+        return;
+
+    ad_init(&ad, vol->volinfo.v_adouble, vol->volinfo.v_ad_options);
+
+    if ( ad_metadata(path, adflags, &ad) < 0 )
+        return;
+
+    FinderInfo = ad_entry(&ad, ADEID_FINDERI);
+
+    memcpy(&FinderFlags, FinderInfo + 8, 2);
+    FinderFlags = ntohs(FinderFlags);
+
+    memcpy(type, FinderInfo, 4);
+    memcpy(creator, FinderInfo + 4, 4);
+
+    ad_getattr(&ad, &AFPattributes);
+    AFPattributes = ntohs(AFPattributes);
+
+    /*
+      Finder flags. Lowercase means valid, uppercase means invalid because
+      object is a dir and flag is only valid for files.
+    */
+    putchar(' ');
+    if (FinderFlags & FINDERINFO_ISONDESK)
+        putchar('d');
+    else
+        putchar('-');
+
+    if (FinderFlags & FINDERINFO_HIDEEXT)
+        putchar('e');
+    else
+        putchar('-');
+
+    if (FinderFlags & FINDERINFO_ISHARED) {
+        if (adflags & ADFLAGS_DIR)
+            putchar('M');
+        else
+            putchar('m');
+    } else
+        putchar('-');
+
+    if (FinderFlags & FINDERINFO_HASNOINITS) {
+        if (adflags & ADFLAGS_DIR)
+            putchar('N');
+        else
+            putchar('n');
+    } else
+        putchar('-');
+
+    if (FinderFlags & FINDERINFO_HASBEENINITED)
+        putchar('i');
+    else
+        putchar('-');
+
+    if (FinderFlags & FINDERINFO_HASCUSTOMICON)
+        putchar('c');
+    else
+        putchar('-');
+
+    if (FinderFlags & FINDERINFO_ISSTATIONNERY) {
+        if (adflags & ADFLAGS_DIR)
+            putchar('T');
+        else
+            putchar('t');
+    } else
+        putchar('-');
+
+    if (FinderFlags & FINDERINFO_NAMELOCKED)
+        putchar('s');
+    else
+        putchar('-');
+
+    if (FinderFlags & FINDERINFO_HASBUNDLE)
+        putchar('b');
+    else
+        putchar('-');
+
+    if (FinderFlags & FINDERINFO_INVISIBLE)
+        putchar('v');
+    else
+        putchar('-');
+
+    if (FinderFlags & FINDERINFO_ISALIAS)
+        putchar('a');
+    else
+        putchar('-');
+
+    putchar(' ');
+
+    /* AFP attributes */
+    if (AFPattributes & ATTRBIT_SYSTEM)
+        putchar('y');
+    else
+        putchar('-');
+
+    if (AFPattributes & ATTRBIT_NOWRITE) {
+        if (adflags & ADFLAGS_DIR)
+            putchar('W');
+        else
+            putchar('w');
+    } else
+        putchar('-');
+
+    if (AFPattributes & ATTRBIT_BACKUP)
+        putchar('p');
+    else
+        putchar('-');
+
+    if (AFPattributes & ATTRBIT_NORENAME)
+        putchar('r');
+    else
+        putchar('-');
+
+    if (AFPattributes & ATTRBIT_NODELETE)
+        putchar('l');
+    else
+        putchar('-');
+
+    if (AFPattributes & ATTRBIT_NOCOPY) {
+        if (adflags & ADFLAGS_DIR)
+            putchar('O');
+        else
+            putchar('o');                
+    } else
+        putchar('-');
+
+    /* Color */
+    printf(" %s ", labels[(FinderFlags & FINDERINFO_COLOR) >> 1]);
+
+    /* Type & Creator */
+    for(i=0; i<4; i++) {
+        if (isalnum(type[i]))
+            putchar(type[i]);
+        else
+            putchar('-');
+    }
+    putchar(' '); 
+    for(i=0; i<4; i++) {
+        if (isalnum(creator[i]))
+            putchar(creator[i]);
+        else
+            putchar('-');
+    }
+    putchar(' '); 
+
+    /* CNID */
+    cnid = ad_forcegetid(&ad);
+    if (cnid)
+        printf(" %10u ", ntohl(cnid));
+    else
+        printf(" !ADVOL_CACHE ");
+
+    ad_close_metadata(&ad);
+}
+
+#define TYPE(b) ((st->st_mode & (S_IFMT)) == (b))
+#define MODE(b) ((st->st_mode & (b)) == (b))
+
+static void print_mode(const struct stat *st)
+{
+    if (TYPE(S_IFBLK))
+        putchar('b');
+    else if (TYPE(S_IFCHR))
+        putchar('c');
+    else if (TYPE(S_IFDIR))
+        putchar('d');
+    else if (TYPE(S_IFIFO))
+        putchar('p');
+    else if (TYPE(S_IFREG))
+        putchar('-');
+    else if (TYPE(S_IFLNK))
+        putchar('l');
+    else if (TYPE(S_IFSOCK))
+        putchar('s');
+    else
+        putchar('?');
+    putchar(MODE(S_IRUSR) ? 'r' : '-');
+    putchar(MODE(S_IWUSR) ? 'w' : '-');
+    if (MODE(S_ISUID)) {
+        if (MODE(S_IXUSR))
+            putchar('s');
+        else
+            putchar('S');
+    }
+    else if (MODE(S_IXUSR))
+        putchar('x');
+    else
+        putchar('-');
+    putchar(MODE(S_IRGRP) ? 'r' : '-');
+    putchar(MODE(S_IWGRP) ? 'w' : '-');
+    if (MODE(S_ISGID)) {
+        if (MODE(S_IXGRP))
+            putchar('s');
+        else
+            putchar('S');
+    }
+    else if (MODE(S_IXGRP))
+        putchar('x');
+    else
+        putchar('-');
+    putchar(MODE(S_IROTH) ? 'r' : '-');
+    putchar(MODE(S_IWOTH) ? 'w' : '-');
+    if (MODE(S_IFDIR) && MODE(S_ISVTX)) {
+        if (MODE(S_IXOTH))
+            putchar('t');
+        else
+            putchar('T');
+    }
+    else if (MODE(S_IXOTH))
+        putchar('x');
+    else
+        putchar('-');
+}
+#undef TYPE
+#undef MODE
+
+static int ad_print(char *path, const struct stat *st, afpvol_t *vol)
+{
+    if ( ! ls_l) {
+        printf("%s  ", path);
+        if (ls_d)
+            printf("\n");
+        return 0;
+    }
+
+    /* Long output */
+    if (ls_u) {
+        print_mode(st);
+        print_numlinks(st);
+        print_owner(st);
+        print_group(st);
+        print_size(st);
+        print_date(st);
+    }
+    print_flags(path, vol, st);
+    printf("  %s\n", path);    
+
+
+    return 0;
+}
+
+static int ad_ls_r(char *path, afpvol_t *vol)
+{
+    int ret = 0, cwd, dirprinted = 0, dirempty;
+    const char *name;
+    char *tmp;
+    static char cwdpath[MAXPATHLEN+1];
+    DIR *dp;
+    struct dirent *ep;
+    static struct stat st;      /* Save some stack space */
+
+    if ( first)
+        cwdpath[0] = 0;
+    else
+        strcat(cwdpath, "/");
+
+    strcat(cwdpath, path);
+    first = 0;
+
+    if (lstat(path, &st) < 0) {
+        perror("Can't stat");
+        return -1;
+    }
+    /* If its a file or a dir with -d option call ad_print and return */
+    if (S_ISREG(st.st_mode) || ls_d)
+        return ad_print(path, &st, vol);
+
+    /* Its a dir: chdir to it remembering where we started */
+    if ((cwd = open(".", O_RDONLY)) == -1) {
+        perror("Cant open .");
+        return -1;
+    }
+    if (chdir(path) != 0) {
+        perror("Cant chdir");
+        close(cwd);
+        return -1;
+    }
+
+    if ((dp = opendir (".")) == NULL) {
+        perror("Couldn't opendir .");
+        return -1;
+    }
+
+    /* First run: print everything */
+    dirempty = 1;
+    while ((ep = readdir (dp))) {
+        /* Check if its "." or ".." */
+        if (DIR_DOT_OR_DOTDOT(ep->d_name))
+            continue;
+
+        /* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */
+        if ((name = check_netatalk_dirs(ep->d_name)) != NULL)
+            continue;
+
+        if ((ep->d_name[0] == '.') && ! ls_a)
+            continue;
+
+        dirempty = 0;
+
+        if (recursion && ! dirprinted) {
+            printf("\n%s:\n", cwdpath);
+            dirprinted = 1;
+        }
+
+        if (lstat(ep->d_name, &st) < 0) {
+            perror("Can't stat");
+            return -1;
+        }
+
+        ret = ad_print(ep->d_name, &st, vol);
+        if (ret != 0)
+            goto exit;
+    }
+
+    if (! ls_l && ! dirempty)
+        printf("\n");
+
+    /* Second run: recurse to dirs */
+    if (ls_R) {
+        rewinddir(dp);
+        while ((ep = readdir (dp))) {
+            /* Check if its "." or ".." */
+            if (DIR_DOT_OR_DOTDOT(ep->d_name))
+                continue;
+
+            /* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */
+            if ((name = check_netatalk_dirs(ep->d_name)) != NULL)
+                continue;
+
+            if ((ret = lstat(ep->d_name, &st)) < 0) {
+                perror("Can't stat");
+                goto exit;
+            }
+
+            /* Recursion */
+            if (S_ISDIR(st.st_mode)) {
+                recursion = 1;
+                ret = ad_ls_r(ep->d_name, vol);
+            }
+            if (ret != 0)
+                goto exit;
+        }
+    }
+
+exit:
+    closedir(dp);
+    fchdir(cwd);
+    close(cwd);
+
+    tmp = strrchr(cwdpath, '/');
+    if (tmp)
+        *tmp = 0;
+
+    return ret;
+}
+
+int ad_ls(int argc, char **argv)
+{
+    int c, firstarg;
+    afpvol_t vol;
+    struct stat st;
+
+    while ((c = getopt(argc, argv, ":adlRu")) != -1) {
+        switch(c) {
+        case 'a':
+            ls_a = 1;
+            break;
+        case 'd':
+            ls_d = 1;
+            break;
+        case 'l':
+            ls_l = 1;
+            break;
+        case 'R':
+            ls_R = 1;
+            break;
+        case 'u':
+            ls_u = 1;
+            break;
+        case ':':
+        case '?':
+            usage_ls();
+            return -1;
+            break;
+        }
+
+    }
+
+    if ((argc - optind) == 0) {
+        newvol(".", &vol);
+        ad_ls_r(".", &vol);
+        freevol(&vol);
+    }
+    else {
+        int havefile = 0;
+
+        firstarg = optind;
+
+        /* First run: only print files from argv paths */
+        while(optind < argc) {
+            if (stat(argv[optind], &st) != 0)
+                goto next;
+            if (S_ISDIR(st.st_mode))
+                goto next;
+
+            havefile = 1;
+            first = 1;
+            recursion = 0;
+
+            newvol(argv[optind], &vol);
+            ad_ls_r(argv[optind], &vol);
+            freevol(&vol);
+        next:
+            optind++;
+        }
+        if (havefile && (! ls_l))
+            printf("\n");
+
+        /* Second run: print dirs */
+        optind = firstarg;
+        while(optind < argc) {
+            if (stat(argv[optind], &st) != 0)
+                goto next2;
+            if ( ! S_ISDIR(st.st_mode))
+                goto next2;
+            if ((optind > firstarg) || havefile)
+                printf("\n%s:\n", argv[optind]);
+
+            first = 1;
+            recursion = 0;
+
+            newvol(argv[optind], &vol);
+            ad_ls_r(argv[optind], &vol);
+            freevol(&vol);
+
+        next2:
+            optind++;
+        }
+
+
+    }
+
+    return 0;
+}
diff --git a/bin/ad/ad_util.c b/bin/ad/ad_util.c
new file mode 100644 (file)
index 0000000..9f862a4
--- /dev/null
@@ -0,0 +1,618 @@
+/* 
+ * Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.   
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <sys/types.h>
+#include <sys/acl.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <atalk/cnid.h>
+#include <atalk/volinfo.h>
+#include <atalk/bstrlib.h>
+#include <atalk/bstradd.h>
+#include <atalk/util.h>
+#include "ad.h"
+
+#define cp_pct(x, y)((y == 0) ? 0 : (int)(100.0 * (x) / (y)))
+
+/* Memory strategy threshold, in pages: if physmem is larger then this, use a 
+ * large buffer */
+#define PHYSPAGES_THRESHOLD (32*1024)
+
+/* Maximum buffer size in bytes - do not allow it to grow larger than this */
+#define BUFSIZE_MAX (2*1024*1024)
+
+/* Small (default) buffer size in bytes. It's inefficient for this to be
+ * smaller than MAXPHYS */
+#define MAXPHYS (64 * 1024)
+#define BUFSIZE_SMALL (MAXPHYS)
+
+int log_verbose;             /* Logging flag */
+
+void _log(enum logtype lt, char *fmt, ...)
+{
+    int len;
+    static char logbuffer[1024];
+    va_list args;
+
+    if ( (lt == STD) || (log_verbose == 1)) {
+        va_start(args, fmt);
+        len = vsnprintf(logbuffer, 1023, fmt, args);
+        va_end(args);
+        logbuffer[1023] = 0;
+
+        printf("%s\n", logbuffer);
+    }
+}
+
+int newvol(const char *path, afpvol_t *vol)
+{
+    //    char *pathdup;
+    
+    memset(vol, 0, sizeof(afpvol_t));
+
+    //    pathdup = strdup(path);
+    //    vol->dirname = strdup(dirname(pathdup));
+    //    free(pathdup);
+    
+    //    pathdup = strdup(path);
+    //    vol->basename = strdup(basename(pathdup));
+    //    free(pathdup);
+
+    loadvolinfo((char *)path, &vol->volinfo);
+
+    return 0;
+}
+
+void freevol(afpvol_t *vol)
+{
+#if 0
+    if (vol->dirname) {
+        free(vol->dirname);
+        vol->dirname = NULL;
+    }
+    if (vol->basename) {
+        free(vol->basename);
+        vol->basename = NULL;
+    }
+#endif
+}
+
+/*
+  Taken form afpd/desktop.c
+*/
+char *utompath(const struct volinfo *volinfo, char *upath)
+{
+    static char  mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
+    char         *m, *u;
+    uint16_t     flags = CONV_IGNORE | CONV_UNESCAPEHEX;
+    size_t       outlen;
+
+    if (!upath)
+        return NULL;
+
+    m = mpath;
+    u = upath;
+    outlen = strlen(upath);
+
+    if ((volinfo->v_casefold & AFPVOL_UTOMUPPER))
+        flags |= CONV_TOUPPER;
+    else if ((volinfo->v_casefold & AFPVOL_UTOMLOWER))
+        flags |= CONV_TOLOWER;
+
+    if ((volinfo->v_flags & AFPVOL_EILSEQ)) {
+        flags |= CONV__EILSEQ;
+    }
+
+    /* convert charsets */
+    if ((size_t)-1 == ( outlen = convert_charset(volinfo->v_volcharset,
+                                                 CH_UTF8_MAC,
+                                                 volinfo->v_maccharset,
+                                                 u, outlen, mpath, MAXPATHLEN, &flags)) ) {
+        SLOG("Conversion from %s to %s for %s failed.",
+            volinfo->v_volcodepage, volinfo->v_maccodepage, u);
+        return NULL;
+    }
+
+    return(m);
+}
+
+/*
+ * path might be:
+ * (a) relative:
+ *     "dir/subdir" with cwd: "/afp_volume/topdir"
+ * (b) absolute:
+ *     "/afp_volume/dir/subdir"
+ */
+static const char *relative_path_for_volume(const char *path, const char *volpath)
+{
+    static char buf[MAXPATHLEN+1];
+    bstring fpath;
+
+    /* Make path absolute by concetanating for case (a) */
+    if (path[0] != '/') {
+        fpath = bfromcstr(getcwdpath());
+        if (fpath->data[fpath->slen - 1] != '/')
+            bcatcstr(fpath, "/");
+        bcatcstr(fpath, path);
+        if (fpath->data[fpath->slen - 1] == '/')
+            bdelete(fpath, fpath->slen - 1, 1);
+    } else {
+        fpath = bfromcstr(path);
+        if (fpath->data[fpath->slen - 1] == '/')
+            bdelete(fpath, fpath->slen - 1, 1);
+
+    }
+
+    return NULL;
+}
+
+/*!
+ * ResolvesCNID of a given paths
+ *
+ * path might be:
+ * (a) relative:
+ *     "dir/subdir" with cwd: "/afp_volume/topdir"
+ * (b) absolute:
+ *     "/afp_volume/dir/subdir"
+ *
+ * 1) in case a) concatenate both paths
+ * 3) strip volume root
+ * 4) start recursive CNID search with
+ *    a) DID:2, "topdir"
+ *    b) DID:2, "dir"
+ * 5) ...until we have the CNID for
+ *    a) "/afp_volume/topdir/dir"
+ *    b) "/afp_volume/dir" (no recursion required)
+ */
+cnid_t cnid_for_path(const struct volinfo *vi,
+                     const struct vol *vol,
+                     const char *path)
+{
+
+    return 0;
+}
+
+int ftw_copy_file(const struct FTW *entp,
+              const char *spath,
+              const struct stat *sp,
+              int dne)
+{
+    static char *buf = NULL;
+    static size_t bufsize;
+    ssize_t wcount;
+    size_t wresid;
+    off_t wtotal;
+    int ch, checkch, from_fd = 0, rcount, rval, to_fd = 0;
+    char *bufp;
+    char *p;
+
+    if ((from_fd = open(spath, O_RDONLY, 0)) == -1) {
+        SLOG("%s: %s", spath, strerror(errno));
+        return (1);
+    }
+
+    /*
+     * If the file exists and we're interactive, verify with the user.
+     * If the file DNE, set the mode to be the from file, minus setuid
+     * bits, modified by the umask; arguably wrong, but it makes copying
+     * executables work right and it's been that way forever.  (The
+     * other choice is 666 or'ed with the execute bits on the from file
+     * modified by the umask.)
+     */
+    if (!dne) {
+#define YESNO "(y/n [n]) "
+        if (nflag) {
+            if (vflag)
+                printf("%s not overwritten\n", to.p_path);
+            (void)close(from_fd);
+            return (0);
+        } else if (iflag) {
+            (void)fprintf(stderr, "overwrite %s? %s", 
+                          to.p_path, YESNO);
+            checkch = ch = getchar();
+            while (ch != '\n' && ch != EOF)
+                ch = getchar();
+            if (checkch != 'y' && checkch != 'Y') {
+                (void)close(from_fd);
+                (void)fprintf(stderr, "not overwritten\n");
+                return (1);
+            }
+        }
+        
+        if (fflag) {
+            /* remove existing destination file name, 
+             * create a new file  */
+            (void)unlink(to.p_path);
+            if (!lflag)
+                to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
+                             sp->st_mode & ~(S_ISUID | S_ISGID));
+        } else {
+            if (!lflag)
+                /* overwrite existing destination file name */
+                to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
+        }
+    } else {
+        if (!lflag)
+            to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
+                         sp->st_mode & ~(S_ISUID | S_ISGID));
+    }
+    
+    if (to_fd == -1) {
+        SLOG("%s: %s", to.p_path, strerror(errno));
+        (void)close(from_fd);
+        return (1);
+    }
+
+    rval = 0;
+
+    if (!lflag) {
+        /*
+         * Mmap and write if less than 8M (the limit is so we don't totally
+         * trash memory on big files.  This is really a minor hack, but it
+         * wins some CPU back.
+         * Some filesystems, such as smbnetfs, don't support mmap,
+         * so this is a best-effort attempt.
+         */
+
+        if (S_ISREG(sp->st_mode) && sp->st_size > 0 &&
+            sp->st_size <= 8 * 1024 * 1024 &&
+            (p = mmap(NULL, (size_t)sp->st_size, PROT_READ,
+                      MAP_SHARED, from_fd, (off_t)0)) != MAP_FAILED) {
+            wtotal = 0;
+            for (bufp = p, wresid = sp->st_size; ;
+                 bufp += wcount, wresid -= (size_t)wcount) {
+                wcount = write(to_fd, bufp, wresid);
+                if (wcount <= 0)
+                    break;
+                wtotal += wcount;
+                if (wcount >= (ssize_t)wresid)
+                    break;
+            }
+            if (wcount != (ssize_t)wresid) {
+                SLOG("%s: %s", to.p_path, strerror(errno));
+                rval = 1;
+            }
+            /* Some systems don't unmap on close(2). */
+            if (munmap(p, sp->st_size) < 0) {
+                SLOG("%s: %s", spath, strerror(errno));
+                rval = 1;
+            }
+        } else {
+            if (buf == NULL) {
+                /*
+                 * Note that buf and bufsize are static. If
+                 * malloc() fails, it will fail at the start
+                 * and not copy only some files. 
+                 */ 
+                if (sysconf(_SC_PHYS_PAGES) > 
+                    PHYSPAGES_THRESHOLD)
+                    bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
+                else
+                    bufsize = BUFSIZE_SMALL;
+                buf = malloc(bufsize);
+                if (buf == NULL)
+                    ERROR("Not enough memory");
+
+            }
+            wtotal = 0;
+            while ((rcount = read(from_fd, buf, bufsize)) > 0) {
+                for (bufp = buf, wresid = rcount; ;
+                     bufp += wcount, wresid -= wcount) {
+                    wcount = write(to_fd, bufp, wresid);
+                    if (wcount <= 0)
+                        break;
+                    wtotal += wcount;
+                    if (wcount >= (ssize_t)wresid)
+                        break;
+                }
+                if (wcount != (ssize_t)wresid) {
+                    SLOG("%s: %s", to.p_path, strerror(errno));
+                    rval = 1;
+                    break;
+                }
+            }
+            if (rcount < 0) {
+                SLOG("%s: %s", spath, strerror(errno));
+                rval = 1;
+            }
+        }
+    } else {
+        if (link(spath, to.p_path)) {
+            SLOG("%s", to.p_path);
+            rval = 1;
+        }
+    }
+    
+    /*
+     * Don't remove the target even after an error.  The target might
+     * not be a regular file, or its attributes might be important,
+     * or its contents might be irreplaceable.  It would only be safe
+     * to remove it if we created it and its length is 0.
+     */
+
+    if (!lflag) {
+        if (pflag && setfile(sp, to_fd))
+            rval = 1;
+        if (pflag && preserve_fd_acls(from_fd, to_fd) != 0)
+            rval = 1;
+        if (close(to_fd)) {
+            SLOG("%s: %s", to.p_path, strerror(errno));
+            rval = 1;
+        }
+    }
+
+    (void)close(from_fd);
+
+    return (rval);
+}
+
+int copy_link(const struct FTW *p,
+              const char *spath,
+              const struct stat *sstp,
+              int exists)
+{
+    int len;
+    char llink[PATH_MAX];
+
+    if ((len = readlink(spath, llink, sizeof(llink) - 1)) == -1) {
+        SLOG("readlink: %s: %s", spath, strerror(errno));
+        return (1);
+    }
+    llink[len] = '\0';
+    if (exists && unlink(to.p_path)) {
+        SLOG("unlink: %s: %s", to.p_path, strerror(errno));
+        return (1);
+    }
+    if (symlink(llink, to.p_path)) {
+        SLOG("symlink: %s: %s", llink, strerror(errno));
+        return (1);
+    }
+    return (pflag ? setfile(sstp, -1) : 0);
+}
+
+int setfile(const struct stat *fs, int fd)
+{
+    static struct timeval tv[2];
+    struct stat ts;
+    int rval, gotstat, islink, fdval;
+    mode_t mode;
+
+    rval = 0;
+    fdval = fd != -1;
+    islink = !fdval && S_ISLNK(fs->st_mode);
+    mode = fs->st_mode & (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO);
+
+    TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atim);
+    TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtim);
+    if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) {
+        SLOG("%sutimes: %s", islink ? "l" : "", to.p_path);
+        rval = 1;
+    }
+    if (fdval ? fstat(fd, &ts) :
+        (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts)))
+        gotstat = 0;
+    else {
+        gotstat = 1;
+        ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX |
+            S_IRWXU | S_IRWXG | S_IRWXO;
+    }
+    /*
+     * Changing the ownership probably won't succeed, unless we're root
+     * or POSIX_CHOWN_RESTRICTED is not set.  Set uid/gid before setting
+     * the mode; current BSD behavior is to remove all setuid bits on
+     * chown.  If chown fails, lose setuid/setgid bits.
+     */
+    if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid)
+        if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) :
+            (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) :
+             chown(to.p_path, fs->st_uid, fs->st_gid))) {
+            if (errno != EPERM) {
+                SLOG("chown: %s: %s", to.p_path, strerror(errno));
+                rval = 1;
+            }
+            mode &= ~(S_ISUID | S_ISGID);
+        }
+
+    if (!gotstat || mode != ts.st_mode)
+        if (fdval ? fchmod(fd, mode) : chmod(to.p_path, mode)) {
+            SLOG("chmod: %s: %s", to.p_path, strerror(errno));
+            rval = 1;
+        }
+
+#ifdef HAVE_ST_FLAGS
+    if (!gotstat || fs->st_flags != ts.st_flags)
+        if (fdval ?
+            fchflags(fd, fs->st_flags) :
+            (islink ? lchflags(to.p_path, fs->st_flags) :
+             chflags(to.p_path, fs->st_flags))) {
+            SLOG("chflags: %s: %s", to.p_path, strerror(errno));
+            rval = 1;
+        }
+#endif
+
+    return (rval);
+}
+
+int preserve_fd_acls(int source_fd, int dest_fd)
+{
+#if 0
+    acl_t acl;
+    acl_type_t acl_type;
+    int acl_supported = 0, ret, trivial;
+
+    ret = fpathconf(source_fd, _PC_ACL_NFS4);
+    if (ret > 0 ) {
+        acl_supported = 1;
+        acl_type = ACL_TYPE_NFS4;
+    } else if (ret < 0 && errno != EINVAL) {
+        warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", to.p_path);
+        return (1);
+    }
+    if (acl_supported == 0) {
+        ret = fpathconf(source_fd, _PC_ACL_EXTENDED);
+        if (ret > 0 ) {
+            acl_supported = 1;
+            acl_type = ACL_TYPE_ACCESS;
+        } else if (ret < 0 && errno != EINVAL) {
+            warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s",
+                 to.p_path);
+            return (1);
+        }
+    }
+    if (acl_supported == 0)
+        return (0);
+
+    acl = acl_get_fd_np(source_fd, acl_type);
+    if (acl == NULL) {
+        warn("failed to get acl entries while setting %s", to.p_path);
+        return (1);
+    }
+    if (acl_is_trivial_np(acl, &trivial)) {
+        warn("acl_is_trivial() failed for %s", to.p_path);
+        acl_free(acl);
+        return (1);
+    }
+    if (trivial) {
+        acl_free(acl);
+        return (0);
+    }
+    if (acl_set_fd_np(dest_fd, acl, acl_type) < 0) {
+        warn("failed to set acl entries for %s", to.p_path);
+        acl_free(acl);
+        return (1);
+    }
+    acl_free(acl);
+#endif
+    return (0);
+}
+
+int preserve_dir_acls(const struct stat *fs, char *source_dir, char *dest_dir)
+{
+#if 0
+    acl_t (*aclgetf)(const char *, acl_type_t);
+    int (*aclsetf)(const char *, acl_type_t, acl_t);
+    struct acl *aclp;
+    acl_t acl;
+    acl_type_t acl_type;
+    int acl_supported = 0, ret, trivial;
+
+    ret = pathconf(source_dir, _PC_ACL_NFS4);
+    if (ret > 0) {
+        acl_supported = 1;
+        acl_type = ACL_TYPE_NFS4;
+    } else if (ret < 0 && errno != EINVAL) {
+        warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", source_dir);
+        return (1);
+    }
+    if (acl_supported == 0) {
+        ret = pathconf(source_dir, _PC_ACL_EXTENDED);
+        if (ret > 0) {
+            acl_supported = 1;
+            acl_type = ACL_TYPE_ACCESS;
+        } else if (ret < 0 && errno != EINVAL) {
+            warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s",
+                 source_dir);
+            return (1);
+        }
+    }
+    if (acl_supported == 0)
+        return (0);
+
+    /*
+     * If the file is a link we will not follow it
+     */
+    if (S_ISLNK(fs->st_mode)) {
+        aclgetf = acl_get_link_np;
+        aclsetf = acl_set_link_np;
+    } else {
+        aclgetf = acl_get_file;
+        aclsetf = acl_set_file;
+    }
+    if (acl_type == ACL_TYPE_ACCESS) {
+        /*
+         * Even if there is no ACL_TYPE_DEFAULT entry here, a zero
+         * size ACL will be returned. So it is not safe to simply
+         * check the pointer to see if the default ACL is present.
+         */
+        acl = aclgetf(source_dir, ACL_TYPE_DEFAULT);
+        if (acl == NULL) {
+            warn("failed to get default acl entries on %s",
+                 source_dir);
+            return (1);
+        }
+        aclp = &acl->ats_acl;
+        if (aclp->acl_cnt != 0 && aclsetf(dest_dir,
+                                          ACL_TYPE_DEFAULT, acl) < 0) {
+            warn("failed to set default acl entries on %s",
+                 dest_dir);
+            acl_free(acl);
+            return (1);
+        }
+        acl_free(acl);
+    }
+    acl = aclgetf(source_dir, acl_type);
+    if (acl == NULL) {
+        warn("failed to get acl entries on %s", source_dir);
+        return (1);
+    }
+    if (acl_is_trivial_np(acl, &trivial)) {
+        warn("acl_is_trivial() failed on %s", source_dir);
+        acl_free(acl);
+        return (1);
+    }
+    if (trivial) {
+        acl_free(acl);
+        return (0);
+    }
+    if (aclsetf(dest_dir, acl_type, acl) < 0) {
+        warn("failed to set acl entries on %s", dest_dir);
+        acl_free(acl);
+        return (1);
+    }
+    acl_free(acl);
+#endif
+    return (0);
+}
index 0de86aa96e8a66623177c3fd94996ce60ad378e8..2ade6f5dfa4ddefda2d13e1017364967619e59eb 100644 (file)
@@ -1,19 +1,7 @@
 # Makefile.am for bin/cnid/
 
 EXTRA_DIST = cnid2_create.in
-noinst_HEADERS = ad.h
 
 if USE_BDB
-bin_PROGRAMS = ad
 bin_SCRIPTS = cnid2_create
-
-ad_SOURCES = ad.c ad_util.c \
-       ad_ls.c \
-       ad_cp.c
-
-ad_LDADD = \
-       $(top_builddir)/libatalk/cnid/libcnid.la \
-       $(top_builddir)/libatalk/libatalk.la \
-       @ACL_LIBS@
-
 endif
diff --git a/bin/cnid/ad.c b/bin/cnid/ad.c
deleted file mode 100644 (file)
index e272f5b..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* 
-   Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
-   
-   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.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <signal.h>
-#include <string.h>
-#include <errno.h>
-
-#include <atalk/cnid.h>
-#include <atalk/volinfo.h>
-#include <atalk/logger.h>
-#include "ad.h"
-
-static void usage_main(void)
-{
-/*
-    printf("Usage: ad ls|rm|cp|mv|set [file|dir, ...]\n");
-*/
-    printf("Usage: ad ls [file|dir, ...]\n");
-}
-
-int main(int argc, char **argv)
-{
-    setuplog("default log_note /dev/tty");
-
-    if (argc < 2) {
-        usage_main();
-        return 1;
-    }
-
-    if (STRCMP(argv[1], ==, "ls"))
-        return ad_ls(argc - 1, argv + 1);
-    else if (STRCMP(argv[1], ==, "cp"))
-        return ad_cp(argc - 1, argv + 1);
-    else {
-        usage_main();
-        return 1;
-    }
-
-    return 0;
-}
diff --git a/bin/cnid/ad.h b/bin/cnid/ad.h
deleted file mode 100644 (file)
index fe26bc5..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* 
-   Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
-   
-   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.
-*/
-
-#ifndef AD_H
-#define AD_H
-
-#define _XOPEN_SOURCE 600
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <signal.h>
-
-#include <atalk/ftw.h>
-#include <atalk/volinfo.h>
-
-#define STRCMP(a,b,c) (strcmp(a,c) b 0)
-
-#define DIR_DOT_OR_DOTDOT(a) \
-        ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0))
-
-enum logtype {STD, DBG};
-
-#define SLOG(...)                             \
-    _log(STD, __VA_ARGS__)
-
-#define ERROR(...)                              \
-    do {                                        \
-        _log(STD, __VA_ARGS__);                 \
-        exit(1);                                \
-    } while (0)
-
-typedef struct {
-    struct volinfo volinfo;
-//    char *basename;
-} afpvol_t;
-
-extern int log_verbose;             /* Logging flag */
-extern void _log(enum logtype lt, char *fmt, ...);
-
-extern struct volinfo svolinfo, dvolinfo;
-extern struct vol svolume, dvolume;
-
-extern int ad_ls(int argc, char **argv);
-extern int ad_cp(int argc, char **argv);
-
-/* ad_util.c */
-extern int newvol(const char *path, afpvol_t *vol);
-extern void freevol(afpvol_t *vol);
-extern cnid_t get_parent_cnid_for_path(const struct volinfo *vi, const struct vol *vol, const char *path);
-extern char *utompath(const struct volinfo *volinfo, char *upath);
-
-struct FTWELEM {
-    const struct FTW  *ftw;
-    const char        *ftw_path;
-    int               ftw_base_off;
-    int               ftw_tflag;
-    const struct stat *ftw_statp;
-};
-
-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 */
-} PATH_T;
-
-extern PATH_T to;
-extern int fflag, iflag, lflag, nflag, pflag, vflag;
-extern volatile sig_atomic_t info;
-
-extern int ftw_copy_file(const struct FTW *, const char *, const struct stat *, int);
-extern int copy_link(const struct FTW *, const char *, const struct stat *, int);
-extern int setfile(const struct stat *, int);
-extern int preserve_dir_acls(const struct stat *, char *, char *);
-extern int preserve_fd_acls(int, int);
-
-#endif /* AD_H */
diff --git a/bin/cnid/ad_cp.c b/bin/cnid/ad_cp.c
deleted file mode 100644 (file)
index 91cb762..0000000
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * Copyright (c) 2010, Frank Lahm <franklahm@googlemail.com>
- * Copyright (c) 1988, 1993, 1994
- * The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * David Hitz of Auspex Systems Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Cp copies source files to target files.
- *
- * The global PATH_T structure "to" always contains the path to the
- * current target file.  Since fts(3) does not change directories,
- * this path can be either absolute or dot-relative.
- *
- * The basic algorithm is to initialize "to" and use fts(3) to traverse
- * the file hierarchy rooted in the argument list.  A trivial case is the
- * case of 'cp file1 file2'.  The more interesting case is the case of
- * 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the
- * path (relative to the root of the traversal) is appended to dir (stored
- * in "to") to form the final target path.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <atalk/ftw.h>
-#include <atalk/adouble.h>
-#include <atalk/vfs.h>
-#include <atalk/util.h>
-#include <atalk/unix.h>
-#include <atalk/volume.h>
-#include <atalk/volinfo.h>
-#include <atalk/bstrlib.h>
-#include <atalk/bstradd.h>
-#include <atalk/queue.h>
-
-#include "ad.h"
-
-#define STRIP_TRAILING_SLASH(p) {                                   \
-        while ((p).p_end > (p).p_path + 1 && (p).p_end[-1] == '/')  \
-            *--(p).p_end = 0;                                       \
-    }
-
-static char emptystring[] = "";
-
-PATH_T to = { to.p_path, emptystring, "" };
-
-int fflag, iflag, lflag, nflag, pflag, vflag;
-mode_t mask;
-struct volinfo svolinfo, dvolinfo;
-struct vol svolume, dvolume;
-cnid_t did = 0; /* current dir CNID */
-
-static enum op type;
-static int Rflag;
-volatile sig_atomic_t sigint;
-static int badcp, rval;
-static int ftw_options = FTW_MOUNT | FTW_PHYS | FTW_ACTIONRETVAL;
-static q_t *cnidq;              /* CNID dir stack */
-
-enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
-
-static char           *netatalk_dirs[] = {
-    ".AppleDouble",
-    ".AppleDB",
-    ".AppleDesktop",
-    NULL
-};
-
-static int copy(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf);
-static void siginfo(int _U_);
-
-/*
-  Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
-  Returns pointer to name or NULL.
-*/
-static const char *check_netatalk_dirs(const char *name)
-{
-    int c;
-
-    for (c=0; netatalk_dirs[c]; c++) {
-        if ((strcmp(name, netatalk_dirs[c])) == 0)
-            return netatalk_dirs[c];
-    }
-    return NULL;
-}
-
-
-static void usage_cp(void)
-{
-    printf(
-        "Usage: ad cp [-R [-P]] [-pvf] <source_file> <target_file>\n"
-        "Usage: ad cp [-R [-P]] [-pvfx] <source_file [source_file ...]> <target_directory>\n"
-        );
-    exit(EXIT_FAILURE);
-}
-
-static void upfunc(void)
-{
-    if (cnidq) {
-        cnid_t *cnid = dequeue(cnidq);
-        if (cnid) {
-            did = *cnid;
-            free(cnid);
-        }
-    }
-}
-
-int ad_cp(int argc, char *argv[])
-{
-    struct stat to_stat, tmp_stat;
-    int r, ch, have_trailing_slash;
-    char *target;
-#if 0
-    afpvol_t srcvol;
-    afpvol_t dstvol;
-#endif
-
-    while ((ch = getopt(argc, argv, "Rafilnpvx")) != -1)
-        switch (ch) {
-        case 'R':
-            Rflag = 1;
-            break;
-        case 'a':
-            pflag = 1;
-            Rflag = 1;
-            break;
-        case 'f':
-            fflag = 1;
-            iflag = nflag = 0;
-            break;
-        case 'i':
-            iflag = 1;
-            fflag = nflag = 0;
-            break;
-        case 'l':
-            lflag = 1;
-            break;
-        case 'n':
-            nflag = 1;
-            fflag = iflag = 0;
-            break;
-        case 'p':
-            pflag = 1;
-            break;
-        case 'v':
-            vflag = 1;
-            break;
-        case 'x':
-            ftw_options |= FTW_MOUNT;
-            break;
-        default:
-            usage_cp();
-            break;
-        }
-    argc -= optind;
-    argv += optind;
-
-    if (argc < 2)
-        usage_cp();
-
-    (void)signal(SIGINT, siginfo);
-
-    cnid_init();
-
-    /* Save the target base in "to". */
-    target = argv[--argc];
-    if ((strlcpy(to.p_path, target, PATH_MAX)) >= PATH_MAX)
-        ERROR("%s: name too long", target);
-
-    to.p_end = to.p_path + strlen(to.p_path);
-    if (to.p_path == to.p_end) {
-        *to.p_end++ = '.';
-        *to.p_end = 0;
-    }
-    have_trailing_slash = (to.p_end[-1] == '/');
-    if (have_trailing_slash)
-        STRIP_TRAILING_SLASH(to);
-    to.target_end = to.p_end;
-
-    /* Set end of argument list */
-    argv[argc] = NULL;
-
-    /*
-     * Cp has two distinct cases:
-     *
-     * cp [-R] source target
-     * cp [-R] source1 ... sourceN directory
-     *
-     * In both cases, source can be either a file or a directory.
-     *
-     * In (1), the target becomes a copy of the source. That is, if the
-     * source is a file, the target will be a file, and likewise for
-     * directories.
-     *
-     * In (2), the real target is not directory, but "directory/source".
-     */
-    r = stat(to.p_path, &to_stat);
-    if (r == -1 && errno != ENOENT)
-        ERROR("%s", to.p_path);
-    if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
-        /*
-         * Case (1).  Target is not a directory.
-         */
-        if (argc > 1)
-            ERROR("%s is not a directory", to.p_path);
-
-        /*
-         * Need to detect the case:
-         *cp -R dir foo
-         * Where dir is a directory and foo does not exist, where
-         * we want pathname concatenations turned on but not for
-         * the initial mkdir().
-         */
-        if (r == -1) {
-            lstat(*argv, &tmp_stat);
-
-            if (S_ISDIR(tmp_stat.st_mode) && Rflag)
-                type = DIR_TO_DNE;
-            else
-                type = FILE_TO_FILE;
-        } else
-            type = FILE_TO_FILE;
-
-        if (have_trailing_slash && type == FILE_TO_FILE) {
-            if (r == -1)
-                ERROR("directory %s does not exist", to.p_path);
-            else
-                ERROR("%s is not a directory", to.p_path);
-        }
-    } else
-        /*
-         * Case (2).  Target is a directory.
-         */
-        type = FILE_TO_DIR;
-
-    /*
-     * Keep an inverted copy of the umask, for use in correcting
-     * permissions on created directories when not using -p.
-     */
-    mask = ~umask(0777);
-    umask(~mask);
-
-#if 0
-    /* Inhereting perms in ad_mkdir etc requires this */
-    ad_setfuid(0);
-#endif
-
-    /* Load .volinfo file for destination*/
-    if (loadvolinfo(to.p_path, &dvolinfo) == 0) {
-        if (vol_load_charsets(&dvolinfo) == -1)
-            ERROR("Error loading charsets!");
-        /* Sanity checks to ensure we can touch this volume */
-        if (dvolinfo.v_vfs_ea != AFPVOL_EA_SYS)
-            ERROR("Unsupported Extended Attributes option: %u", dvolinfo.v_vfs_ea);
-
-        /* initialize sufficient struct vol and initialize CNID connection */
-        dvolume.v_adouble = AD_VERSION2;
-        dvolume.v_vfs_ea = AFPVOL_EA_SYS;
-        initvol_vfs(&dvolume);
-        int flags = 0;
-        if ((dvolinfo.v_flags & AFPVOL_NODEV))
-            flags |= CNID_FLAG_NODEV;
-
-        if ((dvolume.v_cdb = cnid_open(dvolinfo.v_path,
-                                       0000,
-                                       "dbd",
-                                       flags,
-                                       dvolinfo.v_dbd_host,
-                                       dvolinfo.v_dbd_port)) == NULL)
-            ERROR("Cant initialize CNID database connection for %s", dvolinfo.v_path);
-
-        /* setup a list for storing the CNID stack of dirs in destination path */
-        if ((cnidq = queue_init()) == NULL)
-            ERROR("Cant initialize CNID stack");
-    }
-
-    for (int i = 0; argv[i] != NULL; i++) { 
-        /* Load .volinfo file for source */
-        if (loadvolinfo(to.p_path, &svolinfo) == 0) {
-            if (vol_load_charsets(&svolinfo) == -1)
-                ERROR("Error loading charsets!");
-            /* Sanity checks to ensure we can touch this volume */
-            if (svolinfo.v_vfs_ea != AFPVOL_EA_SYS)
-                ERROR("Unsupported Extended Attributes option: %u", svolinfo.v_vfs_ea);
-
-            /* initialize sufficient struct vol and initialize CNID connection */
-            svolume.v_adouble = AD_VERSION2;
-            svolume.v_vfs_ea = AFPVOL_EA_SYS;
-            initvol_vfs(&svolume);
-            int flags = 0;
-            if ((svolinfo.v_flags & AFPVOL_NODEV))
-                flags |= CNID_FLAG_NODEV;
-
-            if ((svolume.v_cdb = cnid_open(svolinfo.v_path,
-                                           0000,
-                                           "dbd",
-                                           flags,
-                                           svolinfo.v_dbd_host,
-                                           svolinfo.v_dbd_port)) == NULL)
-                ERROR("Cant initialize CNID database connection for %s", svolinfo.v_path);
-        }
-
-        if (nftw(argv[i], copy, upfunc, 20, ftw_options) == -1) {
-            ERROR("%s: %s", argv[i], strerror(errno));
-            exit(EXIT_FAILURE);
-        }
-
-        if (svolume.v_cdb)
-            cnid_close(svolume.v_cdb);
-        svolume.v_cdb = NULL;
-
-    }
-    return rval;
-}
-
-static int copy(const char *path,
-                const struct stat *statp,
-                int tflag,
-                struct FTW *ftw)
-{
-    struct stat to_stat;
-    int base = 0, dne;
-    size_t nlen;
-    const char *p;
-    char *target_mid;
-
-    const char *dir = strrchr(path, '/');
-    if (dir == NULL)
-        dir = path;
-    else
-        dir++;
-    if (check_netatalk_dirs(dir) != NULL) {
-        SLOG("Skipping Netatalk dir %s", path);
-        return FTW_SKIP_SIBLINGS;
-    }
-
-    /*
-     * If we are in case (2) above, we need to append the
-     * source name to the target name.
-     */
-    if (type != FILE_TO_FILE) {
-        /*
-         * Need to remember the roots of traversals to create
-         * correct pathnames.  If there's a directory being
-         * copied to a non-existent directory, e.g.
-         *     cp -R a/dir noexist
-         * the resulting path name should be noexist/foo, not
-         * noexist/dir/foo (where foo is a file in dir), which
-         * is the case where the target exists.
-         *
-         * Also, check for "..".  This is for correct path
-         * concatenation for paths ending in "..", e.g.
-         *     cp -R .. /tmp
-         * Paths ending in ".." are changed to ".".  This is
-         * tricky, but seems the easiest way to fix the problem.
-         *
-         * XXX
-         * Since the first level MUST be FTS_ROOTLEVEL, base
-         * is always initialized.
-         */
-        if (ftw->level == 0) {
-            if (type != DIR_TO_DNE) {
-                base = ftw->base;
-
-                if (strcmp(&path[base], "..") == 0)
-                    base += 1;
-            } else
-                base = strlen(path);
-        }
-
-        p = &path[base];
-        nlen = strlen(path) - base;
-        target_mid = to.target_end;
-        if (*p != '/' && target_mid[-1] != '/')
-            *target_mid++ = '/';
-        *target_mid = 0;
-        if (target_mid - to.p_path + nlen >= PATH_MAX) {
-            SLOG("%s%s: name too long (not copied)", to.p_path, p);
-            badcp = rval = 1;
-            return 0;
-        }
-        (void)strncat(target_mid, p, nlen);
-        to.p_end = target_mid + nlen;
-        *to.p_end = 0;
-        STRIP_TRAILING_SLASH(to);
-    }
-
-    /* Not an error but need to remember it happened */
-    if (stat(to.p_path, &to_stat) == -1)
-        dne = 1;
-    else {
-        if (to_stat.st_dev == statp->st_dev &&
-            to_stat.st_ino == statp->st_ino) {
-            SLOG("%s and %s are identical (not copied).",
-                to.p_path, path);
-            badcp = rval = 1;
-            if (S_ISDIR(statp->st_mode))
-                /* without using glibc extension FTW_ACTIONRETVAL cant handle this */
-                return -1;
-        }
-        if (!S_ISDIR(statp->st_mode) &&
-            S_ISDIR(to_stat.st_mode)) {
-            SLOG("cannot overwrite directory %s with "
-                "non-directory %s",
-                to.p_path, path);
-                badcp = rval = 1;
-                return 0;
-        }
-        dne = 0;
-    }
-
-    switch (statp->st_mode & S_IFMT) {
-    case S_IFLNK:
-        if (copy_link(ftw, path, statp, !dne))
-            badcp = rval = 1;
-        break;
-    case S_IFDIR:
-        if (!Rflag) {
-            SLOG("%s is a directory", path);
-            badcp = rval = 1;
-            return -1;
-        }
-        /*
-         * If the directory doesn't exist, create the new
-         * one with the from file mode plus owner RWX bits,
-         * modified by the umask.  Trade-off between being
-         * able to write the directory (if from directory is
-         * 555) and not causing a permissions race.  If the
-         * umask blocks owner writes, we fail..
-         */
-        if (dne) {
-            if (mkdir(to.p_path, statp->st_mode | S_IRWXU) < 0)
-                ERROR("%s", to.p_path);
-        } else if (!S_ISDIR(to_stat.st_mode)) {
-            errno = ENOTDIR;
-            ERROR("%s", to.p_path);
-        }
-
-        /* Create ad dir and copy ".Parent" */
-        if (svolinfo.v_path && svolinfo.v_adouble == AD_VERSION2 &&
-            dvolinfo.v_path && dvolinfo.v_adouble == AD_VERSION2) {
-            /* Create ".AppleDouble" dir */
-            mode_t omask = umask(0);
-            bstring addir = bfromcstr(to.p_path);
-            bcatcstr(addir, "/.AppleDouble");
-            mkdir(cfrombstring(addir), 02777);
-
-            /* copy ".Parent" file */
-            bcatcstr(addir, "/.Parent");
-            bstring sdir = bfromcstr(path);
-            bcatcstr(sdir, "/.AppleDouble/.Parent");
-            if (copy_file(-1, cfrombstring(sdir), cfrombstring(addir), 0666) != 0) {
-                SLOG("Error copying %s -> %s", cfrombstring(sdir), cfrombstring(addir));
-                badcp = rval = 1;
-                break;
-            }
-            umask(omask);
-
-            /* Get CNID of Parent and add new childir to CNID database */
-            did = get_parent_cnid_for_path(&dvolinfo, &dvolume, to.p_path);
-        }
-
-        if (pflag) {
-            if (setfile(statp, -1))
-                rval = 1;
-#if 0
-            if (preserve_dir_acls(statp, curr->fts_accpath, to.p_path) != 0)
-                rval = 1;
-#endif
-        }
-        break;
-
-    case S_IFBLK:
-    case S_IFCHR:
-        SLOG("%s is a device file (not copied).", path);
-        break;
-    case S_IFSOCK:
-        SLOG("%s is a socket (not copied).", path);
-        break;
-    case S_IFIFO:
-        SLOG("%s is a FIFO (not copied).", path);
-        break;
-    default:
-        if (ftw_copy_file(ftw, path, statp, dne))
-            badcp = rval = 1;
-        break;
-    }
-    if (vflag && !badcp)
-        (void)printf("%s -> %s\n", path, to.p_path);
-
-    return 0;
-}
-
-static void siginfo(int sig _U_)
-{
-    sigint = 1;
-}
diff --git a/bin/cnid/ad_ls.c b/bin/cnid/ad_ls.c
deleted file mode 100644 (file)
index 87834d8..0000000
+++ /dev/null
@@ -1,635 +0,0 @@
-/* 
-   Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
-   
-   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.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <string.h>
-#include <errno.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <pwd.h>
-#include <grp.h>
-#include <time.h>
-
-#include <atalk/adouble.h>
-#include <atalk/cnid.h>
-#include <atalk/volinfo.h>
-#include "ad.h"
-
-#define ADv2_DIRNAME ".AppleDouble"
-
-#define DIR_DOT_OR_DOTDOT(a) \
-        ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0))
-
-/* ls options */
-static int ls_a;
-static int ls_l;
-static int ls_R;
-static int ls_d;
-static int ls_u;
-
-/* Used for pretty printing */
-static int first = 1;
-static int recursion;
-
-static char           *netatalk_dirs[] = {
-    ADv2_DIRNAME,
-    ".AppleDB",
-    ".AppleDesktop",
-    NULL
-};
-
-static char *labels[] = {
-    "---",
-    "gry",
-    "gre",
-    "vio",
-    "blu",
-    "yel",
-    "red",
-    "ora"
-};
-
-/*
-  Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
-  Returns pointer to name or NULL.
-*/
-static const char *check_netatalk_dirs(const char *name)
-{
-    int c;
-
-    for (c=0; netatalk_dirs[c]; c++) {
-        if ((strcmp(name, netatalk_dirs[c])) == 0)
-            return netatalk_dirs[c];
-    }
-    return NULL;
-}
-
-
-static void usage_ls(void)
-{
-    printf(
-        "Usage: ad ls [-dRl[u]] [file|dir, ...]\n\n"
-        "  -l Long Output [-u: unix info]:\n"
-        "     <unixinfo ...> <FinderFlags> <AFPAttributes> <Color> <Type> <Creator> <CNID from AppleDouble> <name>\n\n"
-        "     FinderFlags (valid for (f)ile and/or (d)irectory):\n"
-        "       d = On Desktop (f/d)\n"
-        "       e = Hidden extension (f/d)\n"
-        "       m = Shared (can run multiple times) (f)\n"
-        "       n = No INIT resources (f)\n"
-        "       i = Inited (f/d)\n"
-        "       c = Custom icon (f/d)\n"
-        "       t = Stationery (f)\n"
-        "       s = Name locked (f/d)\n"
-        "       b = Bundle (f/d)\n"
-        "       v = Invisible (f/d)\n"
-        "       a = Alias file (f/d)\n\n"
-        "     AFPAttributes:\n"
-        "       y = System (f/d)\n"
-        "       w = No write (f)\n"
-        "       p = Needs backup (f/d)\n"
-        "       r = No rename (f/d)\n"
-        "       l = No delete (f/d)\n"
-        "       o = No copy (f)\n\n"
-        "     Note: any letter appearing in uppercase means the flag is set\n"
-        "           but it's a directory for which the flag is not allowed.\n"
-        );
-}
-
-static void print_numlinks(const struct stat *statp)
-{
-    printf("%5ld", (long)statp->st_nlink);
-}
-
-static void print_owner(const struct stat *statp)
-{
-    struct passwd *pwd = getpwuid(statp->st_uid);
-
-    if (pwd == NULL)
-        printf(" %-8ld", (long)statp->st_uid);
-    else
-        printf(" %-8s", pwd->pw_name);
-}
-
-static void print_group(const struct stat *statp)
-{
-    struct group *grp = getgrgid(statp->st_gid);
-
-    if (grp == NULL)
-        printf(" %-8ld", (long)statp->st_gid);
-    else
-        printf(" %-8s", grp->gr_name);
-}
-
-static void print_size(const struct stat *statp)
-{
-    switch (statp->st_mode & S_IFMT) {
-    case S_IFCHR:
-    case S_IFBLK:
-        printf("%4u,%4u", (unsigned)(statp->st_rdev >> 8),
-               (unsigned)(statp->st_rdev & 0xFF));
-        break;
-    default:
-        printf("%9lu", (unsigned long)statp->st_size);
-    }
-}
-
-static void print_date(const struct stat *statp)
-{
-    time_t now;
-    double diff;
-    char buf[100], *fmt;
-
-    if (time(&now) == -1) {
-        printf(" ????????????");
-        return;
-    }
-    diff = difftime(now, statp->st_mtime);
-    if (diff < 0 || diff > 60 * 60 * 24 * 182.5)
-        fmt = "%b %e  %Y";
-    else
-        fmt = "%b %e %H:%M";
-    strftime(buf, sizeof(buf), fmt, localtime(&statp->st_mtime));
-    printf(" %s", buf);
-}
-
-static void print_flags(char *path, afpvol_t *vol, const struct stat *st)
-{
-    int adflags = 0;
-    struct adouble ad;
-    char *FinderInfo;
-    uint16_t FinderFlags;
-    uint16_t AFPattributes;
-    char type[5] = "----";
-    char creator[5] = "----";
-    int i;
-    uint32_t cnid;
-
-    if (S_ISDIR(st->st_mode))
-        adflags = ADFLAGS_DIR;
-
-    if (vol->volinfo.v_path == NULL)
-        return;
-
-    ad_init(&ad, vol->volinfo.v_adouble, vol->volinfo.v_ad_options);
-
-    if ( ad_metadata(path, adflags, &ad) < 0 )
-        return;
-
-    FinderInfo = ad_entry(&ad, ADEID_FINDERI);
-
-    memcpy(&FinderFlags, FinderInfo + 8, 2);
-    FinderFlags = ntohs(FinderFlags);
-
-    memcpy(type, FinderInfo, 4);
-    memcpy(creator, FinderInfo + 4, 4);
-
-    ad_getattr(&ad, &AFPattributes);
-    AFPattributes = ntohs(AFPattributes);
-
-    /*
-      Finder flags. Lowercase means valid, uppercase means invalid because
-      object is a dir and flag is only valid for files.
-    */
-    putchar(' ');
-    if (FinderFlags & FINDERINFO_ISONDESK)
-        putchar('d');
-    else
-        putchar('-');
-
-    if (FinderFlags & FINDERINFO_HIDEEXT)
-        putchar('e');
-    else
-        putchar('-');
-
-    if (FinderFlags & FINDERINFO_ISHARED) {
-        if (adflags & ADFLAGS_DIR)
-            putchar('M');
-        else
-            putchar('m');
-    } else
-        putchar('-');
-
-    if (FinderFlags & FINDERINFO_HASNOINITS) {
-        if (adflags & ADFLAGS_DIR)
-            putchar('N');
-        else
-            putchar('n');
-    } else
-        putchar('-');
-
-    if (FinderFlags & FINDERINFO_HASBEENINITED)
-        putchar('i');
-    else
-        putchar('-');
-
-    if (FinderFlags & FINDERINFO_HASCUSTOMICON)
-        putchar('c');
-    else
-        putchar('-');
-
-    if (FinderFlags & FINDERINFO_ISSTATIONNERY) {
-        if (adflags & ADFLAGS_DIR)
-            putchar('T');
-        else
-            putchar('t');
-    } else
-        putchar('-');
-
-    if (FinderFlags & FINDERINFO_NAMELOCKED)
-        putchar('s');
-    else
-        putchar('-');
-
-    if (FinderFlags & FINDERINFO_HASBUNDLE)
-        putchar('b');
-    else
-        putchar('-');
-
-    if (FinderFlags & FINDERINFO_INVISIBLE)
-        putchar('v');
-    else
-        putchar('-');
-
-    if (FinderFlags & FINDERINFO_ISALIAS)
-        putchar('a');
-    else
-        putchar('-');
-
-    putchar(' ');
-
-    /* AFP attributes */
-    if (AFPattributes & ATTRBIT_SYSTEM)
-        putchar('y');
-    else
-        putchar('-');
-
-    if (AFPattributes & ATTRBIT_NOWRITE) {
-        if (adflags & ADFLAGS_DIR)
-            putchar('W');
-        else
-            putchar('w');
-    } else
-        putchar('-');
-
-    if (AFPattributes & ATTRBIT_BACKUP)
-        putchar('p');
-    else
-        putchar('-');
-
-    if (AFPattributes & ATTRBIT_NORENAME)
-        putchar('r');
-    else
-        putchar('-');
-
-    if (AFPattributes & ATTRBIT_NODELETE)
-        putchar('l');
-    else
-        putchar('-');
-
-    if (AFPattributes & ATTRBIT_NOCOPY) {
-        if (adflags & ADFLAGS_DIR)
-            putchar('O');
-        else
-            putchar('o');                
-    } else
-        putchar('-');
-
-    /* Color */
-    printf(" %s ", labels[(FinderFlags & FINDERINFO_COLOR) >> 1]);
-
-    /* Type & Creator */
-    for(i=0; i<4; i++) {
-        if (isalnum(type[i]))
-            putchar(type[i]);
-        else
-            putchar('-');
-    }
-    putchar(' '); 
-    for(i=0; i<4; i++) {
-        if (isalnum(creator[i]))
-            putchar(creator[i]);
-        else
-            putchar('-');
-    }
-    putchar(' '); 
-
-    /* CNID */
-    cnid = ad_forcegetid(&ad);
-    if (cnid)
-        printf(" %10u ", ntohl(cnid));
-    else
-        printf(" !ADVOL_CACHE ");
-
-    ad_close_metadata(&ad);
-}
-
-#define TYPE(b) ((st->st_mode & (S_IFMT)) == (b))
-#define MODE(b) ((st->st_mode & (b)) == (b))
-
-static void print_mode(const struct stat *st)
-{
-    if (TYPE(S_IFBLK))
-        putchar('b');
-    else if (TYPE(S_IFCHR))
-        putchar('c');
-    else if (TYPE(S_IFDIR))
-        putchar('d');
-    else if (TYPE(S_IFIFO))
-        putchar('p');
-    else if (TYPE(S_IFREG))
-        putchar('-');
-    else if (TYPE(S_IFLNK))
-        putchar('l');
-    else if (TYPE(S_IFSOCK))
-        putchar('s');
-    else
-        putchar('?');
-    putchar(MODE(S_IRUSR) ? 'r' : '-');
-    putchar(MODE(S_IWUSR) ? 'w' : '-');
-    if (MODE(S_ISUID)) {
-        if (MODE(S_IXUSR))
-            putchar('s');
-        else
-            putchar('S');
-    }
-    else if (MODE(S_IXUSR))
-        putchar('x');
-    else
-        putchar('-');
-    putchar(MODE(S_IRGRP) ? 'r' : '-');
-    putchar(MODE(S_IWGRP) ? 'w' : '-');
-    if (MODE(S_ISGID)) {
-        if (MODE(S_IXGRP))
-            putchar('s');
-        else
-            putchar('S');
-    }
-    else if (MODE(S_IXGRP))
-        putchar('x');
-    else
-        putchar('-');
-    putchar(MODE(S_IROTH) ? 'r' : '-');
-    putchar(MODE(S_IWOTH) ? 'w' : '-');
-    if (MODE(S_IFDIR) && MODE(S_ISVTX)) {
-        if (MODE(S_IXOTH))
-            putchar('t');
-        else
-            putchar('T');
-    }
-    else if (MODE(S_IXOTH))
-        putchar('x');
-    else
-        putchar('-');
-}
-#undef TYPE
-#undef MODE
-
-static int ad_print(char *path, const struct stat *st, afpvol_t *vol)
-{
-    if ( ! ls_l) {
-        printf("%s  ", path);
-        if (ls_d)
-            printf("\n");
-        return 0;
-    }
-
-    /* Long output */
-    if (ls_u) {
-        print_mode(st);
-        print_numlinks(st);
-        print_owner(st);
-        print_group(st);
-        print_size(st);
-        print_date(st);
-    }
-    print_flags(path, vol, st);
-    printf("  %s\n", path);    
-
-
-    return 0;
-}
-
-static int ad_ls_r(char *path, afpvol_t *vol)
-{
-    int ret = 0, cwd, dirprinted = 0, dirempty;
-    const char *name;
-    char *tmp;
-    static char cwdpath[MAXPATHLEN+1];
-    DIR *dp;
-    struct dirent *ep;
-    static struct stat st;      /* Save some stack space */
-
-    if ( first)
-        cwdpath[0] = 0;
-    else
-        strcat(cwdpath, "/");
-
-    strcat(cwdpath, path);
-    first = 0;
-
-    if (lstat(path, &st) < 0) {
-        perror("Can't stat");
-        return -1;
-    }
-    /* If its a file or a dir with -d option call ad_print and return */
-    if (S_ISREG(st.st_mode) || ls_d)
-        return ad_print(path, &st, vol);
-
-    /* Its a dir: chdir to it remembering where we started */
-    if ((cwd = open(".", O_RDONLY)) == -1) {
-        perror("Cant open .");
-        return -1;
-    }
-    if (chdir(path) != 0) {
-        perror("Cant chdir");
-        close(cwd);
-        return -1;
-    }
-
-    if ((dp = opendir (".")) == NULL) {
-        perror("Couldn't opendir .");
-        return -1;
-    }
-
-    /* First run: print everything */
-    dirempty = 1;
-    while ((ep = readdir (dp))) {
-        /* Check if its "." or ".." */
-        if (DIR_DOT_OR_DOTDOT(ep->d_name))
-            continue;
-
-        /* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */
-        if ((name = check_netatalk_dirs(ep->d_name)) != NULL)
-            continue;
-
-        if ((ep->d_name[0] == '.') && ! ls_a)
-            continue;
-
-        dirempty = 0;
-
-        if (recursion && ! dirprinted) {
-            printf("\n%s:\n", cwdpath);
-            dirprinted = 1;
-        }
-
-        if (lstat(ep->d_name, &st) < 0) {
-            perror("Can't stat");
-            return -1;
-        }
-
-        ret = ad_print(ep->d_name, &st, vol);
-        if (ret != 0)
-            goto exit;
-    }
-
-    if (! ls_l && ! dirempty)
-        printf("\n");
-
-    /* Second run: recurse to dirs */
-    if (ls_R) {
-        rewinddir(dp);
-        while ((ep = readdir (dp))) {
-            /* Check if its "." or ".." */
-            if (DIR_DOT_OR_DOTDOT(ep->d_name))
-                continue;
-
-            /* Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop" */
-            if ((name = check_netatalk_dirs(ep->d_name)) != NULL)
-                continue;
-
-            if ((ret = lstat(ep->d_name, &st)) < 0) {
-                perror("Can't stat");
-                goto exit;
-            }
-
-            /* Recursion */
-            if (S_ISDIR(st.st_mode)) {
-                recursion = 1;
-                ret = ad_ls_r(ep->d_name, vol);
-            }
-            if (ret != 0)
-                goto exit;
-        }
-    }
-
-exit:
-    closedir(dp);
-    fchdir(cwd);
-    close(cwd);
-
-    tmp = strrchr(cwdpath, '/');
-    if (tmp)
-        *tmp = 0;
-
-    return ret;
-}
-
-int ad_ls(int argc, char **argv)
-{
-    int c, firstarg;
-    afpvol_t vol;
-    struct stat st;
-
-    while ((c = getopt(argc, argv, ":adlRu")) != -1) {
-        switch(c) {
-        case 'a':
-            ls_a = 1;
-            break;
-        case 'd':
-            ls_d = 1;
-            break;
-        case 'l':
-            ls_l = 1;
-            break;
-        case 'R':
-            ls_R = 1;
-            break;
-        case 'u':
-            ls_u = 1;
-            break;
-        case ':':
-        case '?':
-            usage_ls();
-            return -1;
-            break;
-        }
-
-    }
-
-    if ((argc - optind) == 0) {
-        newvol(".", &vol);
-        ad_ls_r(".", &vol);
-        freevol(&vol);
-    }
-    else {
-        int havefile = 0;
-
-        firstarg = optind;
-
-        /* First run: only print files from argv paths */
-        while(optind < argc) {
-            if (stat(argv[optind], &st) != 0)
-                goto next;
-            if (S_ISDIR(st.st_mode))
-                goto next;
-
-            havefile = 1;
-            first = 1;
-            recursion = 0;
-
-            newvol(argv[optind], &vol);
-            ad_ls_r(argv[optind], &vol);
-            freevol(&vol);
-        next:
-            optind++;
-        }
-        if (havefile && (! ls_l))
-            printf("\n");
-
-        /* Second run: print dirs */
-        optind = firstarg;
-        while(optind < argc) {
-            if (stat(argv[optind], &st) != 0)
-                goto next2;
-            if ( ! S_ISDIR(st.st_mode))
-                goto next2;
-            if ((optind > firstarg) || havefile)
-                printf("\n%s:\n", argv[optind]);
-
-            first = 1;
-            recursion = 0;
-
-            newvol(argv[optind], &vol);
-            ad_ls_r(argv[optind], &vol);
-            freevol(&vol);
-
-        next2:
-            optind++;
-        }
-
-
-    }
-
-    return 0;
-}
diff --git a/bin/cnid/ad_util.c b/bin/cnid/ad_util.c
deleted file mode 100644 (file)
index 1814ae7..0000000
+++ /dev/null
@@ -1,586 +0,0 @@
-/* 
- * Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.   
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include <sys/types.h>
-#include <sys/acl.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sysexits.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include <atalk/cnid.h>
-#include <atalk/volinfo.h>
-#include "ad.h"
-
-#define cp_pct(x, y)((y == 0) ? 0 : (int)(100.0 * (x) / (y)))
-
-/* Memory strategy threshold, in pages: if physmem is larger then this, use a 
- * large buffer */
-#define PHYSPAGES_THRESHOLD (32*1024)
-
-/* Maximum buffer size in bytes - do not allow it to grow larger than this */
-#define BUFSIZE_MAX (2*1024*1024)
-
-/* Small (default) buffer size in bytes. It's inefficient for this to be
- * smaller than MAXPHYS */
-#define MAXPHYS (64 * 1024)
-#define BUFSIZE_SMALL (MAXPHYS)
-
-int log_verbose;             /* Logging flag */
-
-void _log(enum logtype lt, char *fmt, ...)
-{
-    int len;
-    static char logbuffer[1024];
-    va_list args;
-
-    if ( (lt == STD) || (log_verbose == 1)) {
-        va_start(args, fmt);
-        len = vsnprintf(logbuffer, 1023, fmt, args);
-        va_end(args);
-        logbuffer[1023] = 0;
-
-        printf("%s\n", logbuffer);
-    }
-}
-
-int newvol(const char *path, afpvol_t *vol)
-{
-    //    char *pathdup;
-    
-    memset(vol, 0, sizeof(afpvol_t));
-
-    //    pathdup = strdup(path);
-    //    vol->dirname = strdup(dirname(pathdup));
-    //    free(pathdup);
-    
-    //    pathdup = strdup(path);
-    //    vol->basename = strdup(basename(pathdup));
-    //    free(pathdup);
-
-    loadvolinfo((char *)path, &vol->volinfo);
-
-    return 0;
-}
-
-void freevol(afpvol_t *vol)
-{
-#if 0
-    if (vol->dirname) {
-        free(vol->dirname);
-        vol->dirname = NULL;
-    }
-    if (vol->basename) {
-        free(vol->basename);
-        vol->basename = NULL;
-    }
-#endif
-}
-
-/*
-  Taken form afpd/desktop.c
-*/
-char *utompath(const struct volinfo *volinfo, char *upath)
-{
-    static char  mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
-    char         *m, *u;
-    uint16_t     flags = CONV_IGNORE | CONV_UNESCAPEHEX;
-    size_t       outlen;
-
-    if (!upath)
-        return NULL;
-
-    m = mpath;
-    u = upath;
-    outlen = strlen(upath);
-
-    if ((volinfo->v_casefold & AFPVOL_UTOMUPPER))
-        flags |= CONV_TOUPPER;
-    else if ((volinfo->v_casefold & AFPVOL_UTOMLOWER))
-        flags |= CONV_TOLOWER;
-
-    if ((volinfo->v_flags & AFPVOL_EILSEQ)) {
-        flags |= CONV__EILSEQ;
-    }
-
-    /* convert charsets */
-    if ((size_t)-1 == ( outlen = convert_charset(volinfo->v_volcharset,
-                                                 CH_UTF8_MAC,
-                                                 volinfo->v_maccharset,
-                                                 u, outlen, mpath, MAXPATHLEN, &flags)) ) {
-        SLOG("Conversion from %s to %s for %s failed.",
-            volinfo->v_volcodepage, volinfo->v_maccodepage, u);
-        return NULL;
-    }
-
-    return(m);
-}
-
-/*!
- * Resolves CNID of a given paths parent directory
- *
- * path might be:
- * (a) relative:
- *     "dir/subdir" with cwd: "/afp_volume/topdir"
- * (b) absolute:
- *     "/afp_volume/dir/subdir"
- *
- * 1) in case a) concatenate both paths
- * 2) strip last element
- * 3) strip volume root
- * 4) start recursive CNID search with
- *    a) DID:2, "topdir"
- *    b) DID:2, "dir"
- * 5) ...until we have the CNID for
- *    a) "/afp_volume/topdir/dir"
- *    b) "/afp_volume/dir" (no recursion required)
- */
-cnid_t get_parent_cnid_for_path(const struct volinfo *vi,
-                                const struct vol *vol,
-                                const char *path)
-{
-
-    return 0;
-}
-
-int ftw_copy_file(const struct FTW *entp,
-              const char *spath,
-              const struct stat *sp,
-              int dne)
-{
-    static char *buf = NULL;
-    static size_t bufsize;
-    ssize_t wcount;
-    size_t wresid;
-    off_t wtotal;
-    int ch, checkch, from_fd = 0, rcount, rval, to_fd = 0;
-    char *bufp;
-    char *p;
-
-    if ((from_fd = open(spath, O_RDONLY, 0)) == -1) {
-        SLOG("%s: %s", spath, strerror(errno));
-        return (1);
-    }
-
-    /*
-     * If the file exists and we're interactive, verify with the user.
-     * If the file DNE, set the mode to be the from file, minus setuid
-     * bits, modified by the umask; arguably wrong, but it makes copying
-     * executables work right and it's been that way forever.  (The
-     * other choice is 666 or'ed with the execute bits on the from file
-     * modified by the umask.)
-     */
-    if (!dne) {
-#define YESNO "(y/n [n]) "
-        if (nflag) {
-            if (vflag)
-                printf("%s not overwritten\n", to.p_path);
-            (void)close(from_fd);
-            return (0);
-        } else if (iflag) {
-            (void)fprintf(stderr, "overwrite %s? %s", 
-                          to.p_path, YESNO);
-            checkch = ch = getchar();
-            while (ch != '\n' && ch != EOF)
-                ch = getchar();
-            if (checkch != 'y' && checkch != 'Y') {
-                (void)close(from_fd);
-                (void)fprintf(stderr, "not overwritten\n");
-                return (1);
-            }
-        }
-        
-        if (fflag) {
-            /* remove existing destination file name, 
-             * create a new file  */
-            (void)unlink(to.p_path);
-            if (!lflag)
-                to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
-                             sp->st_mode & ~(S_ISUID | S_ISGID));
-        } else {
-            if (!lflag)
-                /* overwrite existing destination file name */
-                to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
-        }
-    } else {
-        if (!lflag)
-            to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
-                         sp->st_mode & ~(S_ISUID | S_ISGID));
-    }
-    
-    if (to_fd == -1) {
-        SLOG("%s: %s", to.p_path, strerror(errno));
-        (void)close(from_fd);
-        return (1);
-    }
-
-    rval = 0;
-
-    if (!lflag) {
-        /*
-         * Mmap and write if less than 8M (the limit is so we don't totally
-         * trash memory on big files.  This is really a minor hack, but it
-         * wins some CPU back.
-         * Some filesystems, such as smbnetfs, don't support mmap,
-         * so this is a best-effort attempt.
-         */
-
-        if (S_ISREG(sp->st_mode) && sp->st_size > 0 &&
-            sp->st_size <= 8 * 1024 * 1024 &&
-            (p = mmap(NULL, (size_t)sp->st_size, PROT_READ,
-                      MAP_SHARED, from_fd, (off_t)0)) != MAP_FAILED) {
-            wtotal = 0;
-            for (bufp = p, wresid = sp->st_size; ;
-                 bufp += wcount, wresid -= (size_t)wcount) {
-                wcount = write(to_fd, bufp, wresid);
-                if (wcount <= 0)
-                    break;
-                wtotal += wcount;
-                if (wcount >= (ssize_t)wresid)
-                    break;
-            }
-            if (wcount != (ssize_t)wresid) {
-                SLOG("%s: %s", to.p_path, strerror(errno));
-                rval = 1;
-            }
-            /* Some systems don't unmap on close(2). */
-            if (munmap(p, sp->st_size) < 0) {
-                SLOG("%s: %s", spath, strerror(errno));
-                rval = 1;
-            }
-        } else {
-            if (buf == NULL) {
-                /*
-                 * Note that buf and bufsize are static. If
-                 * malloc() fails, it will fail at the start
-                 * and not copy only some files. 
-                 */ 
-                if (sysconf(_SC_PHYS_PAGES) > 
-                    PHYSPAGES_THRESHOLD)
-                    bufsize = MIN(BUFSIZE_MAX, MAXPHYS * 8);
-                else
-                    bufsize = BUFSIZE_SMALL;
-                buf = malloc(bufsize);
-                if (buf == NULL)
-                    ERROR("Not enough memory");
-
-            }
-            wtotal = 0;
-            while ((rcount = read(from_fd, buf, bufsize)) > 0) {
-                for (bufp = buf, wresid = rcount; ;
-                     bufp += wcount, wresid -= wcount) {
-                    wcount = write(to_fd, bufp, wresid);
-                    if (wcount <= 0)
-                        break;
-                    wtotal += wcount;
-                    if (wcount >= (ssize_t)wresid)
-                        break;
-                }
-                if (wcount != (ssize_t)wresid) {
-                    SLOG("%s: %s", to.p_path, strerror(errno));
-                    rval = 1;
-                    break;
-                }
-            }
-            if (rcount < 0) {
-                SLOG("%s: %s", spath, strerror(errno));
-                rval = 1;
-            }
-        }
-    } else {
-        if (link(spath, to.p_path)) {
-            SLOG("%s", to.p_path);
-            rval = 1;
-        }
-    }
-    
-    /*
-     * Don't remove the target even after an error.  The target might
-     * not be a regular file, or its attributes might be important,
-     * or its contents might be irreplaceable.  It would only be safe
-     * to remove it if we created it and its length is 0.
-     */
-
-    if (!lflag) {
-        if (pflag && setfile(sp, to_fd))
-            rval = 1;
-        if (pflag && preserve_fd_acls(from_fd, to_fd) != 0)
-            rval = 1;
-        if (close(to_fd)) {
-            SLOG("%s: %s", to.p_path, strerror(errno));
-            rval = 1;
-        }
-    }
-
-    (void)close(from_fd);
-
-    return (rval);
-}
-
-int copy_link(const struct FTW *p,
-              const char *spath,
-              const struct stat *sstp,
-              int exists)
-{
-    int len;
-    char llink[PATH_MAX];
-
-    if ((len = readlink(spath, llink, sizeof(llink) - 1)) == -1) {
-        SLOG("readlink: %s: %s", spath, strerror(errno));
-        return (1);
-    }
-    llink[len] = '\0';
-    if (exists && unlink(to.p_path)) {
-        SLOG("unlink: %s: %s", to.p_path, strerror(errno));
-        return (1);
-    }
-    if (symlink(llink, to.p_path)) {
-        SLOG("symlink: %s: %s", llink, strerror(errno));
-        return (1);
-    }
-    return (pflag ? setfile(sstp, -1) : 0);
-}
-
-int setfile(const struct stat *fs, int fd)
-{
-    static struct timeval tv[2];
-    struct stat ts;
-    int rval, gotstat, islink, fdval;
-    mode_t mode;
-
-    rval = 0;
-    fdval = fd != -1;
-    islink = !fdval && S_ISLNK(fs->st_mode);
-    mode = fs->st_mode & (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO);
-
-    TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atim);
-    TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtim);
-    if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) {
-        SLOG("%sutimes: %s", islink ? "l" : "", to.p_path);
-        rval = 1;
-    }
-    if (fdval ? fstat(fd, &ts) :
-        (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts)))
-        gotstat = 0;
-    else {
-        gotstat = 1;
-        ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX |
-            S_IRWXU | S_IRWXG | S_IRWXO;
-    }
-    /*
-     * Changing the ownership probably won't succeed, unless we're root
-     * or POSIX_CHOWN_RESTRICTED is not set.  Set uid/gid before setting
-     * the mode; current BSD behavior is to remove all setuid bits on
-     * chown.  If chown fails, lose setuid/setgid bits.
-     */
-    if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid)
-        if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) :
-            (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) :
-             chown(to.p_path, fs->st_uid, fs->st_gid))) {
-            if (errno != EPERM) {
-                SLOG("chown: %s: %s", to.p_path, strerror(errno));
-                rval = 1;
-            }
-            mode &= ~(S_ISUID | S_ISGID);
-        }
-
-    if (!gotstat || mode != ts.st_mode)
-        if (fdval ? fchmod(fd, mode) : chmod(to.p_path, mode)) {
-            SLOG("chmod: %s: %s", to.p_path, strerror(errno));
-            rval = 1;
-        }
-
-#ifdef HAVE_ST_FLAGS
-    if (!gotstat || fs->st_flags != ts.st_flags)
-        if (fdval ?
-            fchflags(fd, fs->st_flags) :
-            (islink ? lchflags(to.p_path, fs->st_flags) :
-             chflags(to.p_path, fs->st_flags))) {
-            SLOG("chflags: %s: %s", to.p_path, strerror(errno));
-            rval = 1;
-        }
-#endif
-
-    return (rval);
-}
-
-int preserve_fd_acls(int source_fd, int dest_fd)
-{
-#if 0
-    acl_t acl;
-    acl_type_t acl_type;
-    int acl_supported = 0, ret, trivial;
-
-    ret = fpathconf(source_fd, _PC_ACL_NFS4);
-    if (ret > 0 ) {
-        acl_supported = 1;
-        acl_type = ACL_TYPE_NFS4;
-    } else if (ret < 0 && errno != EINVAL) {
-        warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", to.p_path);
-        return (1);
-    }
-    if (acl_supported == 0) {
-        ret = fpathconf(source_fd, _PC_ACL_EXTENDED);
-        if (ret > 0 ) {
-            acl_supported = 1;
-            acl_type = ACL_TYPE_ACCESS;
-        } else if (ret < 0 && errno != EINVAL) {
-            warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s",
-                 to.p_path);
-            return (1);
-        }
-    }
-    if (acl_supported == 0)
-        return (0);
-
-    acl = acl_get_fd_np(source_fd, acl_type);
-    if (acl == NULL) {
-        warn("failed to get acl entries while setting %s", to.p_path);
-        return (1);
-    }
-    if (acl_is_trivial_np(acl, &trivial)) {
-        warn("acl_is_trivial() failed for %s", to.p_path);
-        acl_free(acl);
-        return (1);
-    }
-    if (trivial) {
-        acl_free(acl);
-        return (0);
-    }
-    if (acl_set_fd_np(dest_fd, acl, acl_type) < 0) {
-        warn("failed to set acl entries for %s", to.p_path);
-        acl_free(acl);
-        return (1);
-    }
-    acl_free(acl);
-#endif
-    return (0);
-}
-
-int preserve_dir_acls(const struct stat *fs, char *source_dir, char *dest_dir)
-{
-#if 0
-    acl_t (*aclgetf)(const char *, acl_type_t);
-    int (*aclsetf)(const char *, acl_type_t, acl_t);
-    struct acl *aclp;
-    acl_t acl;
-    acl_type_t acl_type;
-    int acl_supported = 0, ret, trivial;
-
-    ret = pathconf(source_dir, _PC_ACL_NFS4);
-    if (ret > 0) {
-        acl_supported = 1;
-        acl_type = ACL_TYPE_NFS4;
-    } else if (ret < 0 && errno != EINVAL) {
-        warn("fpathconf(..., _PC_ACL_NFS4) failed for %s", source_dir);
-        return (1);
-    }
-    if (acl_supported == 0) {
-        ret = pathconf(source_dir, _PC_ACL_EXTENDED);
-        if (ret > 0) {
-            acl_supported = 1;
-            acl_type = ACL_TYPE_ACCESS;
-        } else if (ret < 0 && errno != EINVAL) {
-            warn("fpathconf(..., _PC_ACL_EXTENDED) failed for %s",
-                 source_dir);
-            return (1);
-        }
-    }
-    if (acl_supported == 0)
-        return (0);
-
-    /*
-     * If the file is a link we will not follow it
-     */
-    if (S_ISLNK(fs->st_mode)) {
-        aclgetf = acl_get_link_np;
-        aclsetf = acl_set_link_np;
-    } else {
-        aclgetf = acl_get_file;
-        aclsetf = acl_set_file;
-    }
-    if (acl_type == ACL_TYPE_ACCESS) {
-        /*
-         * Even if there is no ACL_TYPE_DEFAULT entry here, a zero
-         * size ACL will be returned. So it is not safe to simply
-         * check the pointer to see if the default ACL is present.
-         */
-        acl = aclgetf(source_dir, ACL_TYPE_DEFAULT);
-        if (acl == NULL) {
-            warn("failed to get default acl entries on %s",
-                 source_dir);
-            return (1);
-        }
-        aclp = &acl->ats_acl;
-        if (aclp->acl_cnt != 0 && aclsetf(dest_dir,
-                                          ACL_TYPE_DEFAULT, acl) < 0) {
-            warn("failed to set default acl entries on %s",
-                 dest_dir);
-            acl_free(acl);
-            return (1);
-        }
-        acl_free(acl);
-    }
-    acl = aclgetf(source_dir, acl_type);
-    if (acl == NULL) {
-        warn("failed to get acl entries on %s", source_dir);
-        return (1);
-    }
-    if (acl_is_trivial_np(acl, &trivial)) {
-        warn("acl_is_trivial() failed on %s", source_dir);
-        acl_free(acl);
-        return (1);
-    }
-    if (trivial) {
-        acl_free(acl);
-        return (0);
-    }
-    if (aclsetf(dest_dir, acl_type, acl) < 0) {
-        warn("failed to set acl entries on %s", dest_dir);
-        acl_free(acl);
-        return (1);
-    }
-    acl_free(acl);
-#endif
-    return (0);
-}
index 20d613ca5f250f7ee47f2901a5a4b1befa1ebe58..75162bd6c133f79746b3d4be857420282e8ed626 100644 (file)
@@ -1275,6 +1275,7 @@ dnl --------------------- generate files
 
 AC_OUTPUT([Makefile
        bin/Makefile
+       bin/ad/Makefile
        bin/adv1tov2/Makefile
        bin/aecho/Makefile
        bin/afile/Makefile
index d7e72f2395a5e78c9821d83160342eb11fde090b..fe9ff250336214d410a32bee946578865d490fd2 100644 (file)
@@ -138,7 +138,7 @@ makemacpath(const struct vol *vol, char *mpath, int mpathlen, struct dir *dir, c
             /* FIXME: pathname too long */
             return NULL;
         }
-        memcpy(p, cfrombstring(dir->d_m_name), blength(dir->d_m_name) + 1);
+        memcpy(p, cfrombstr(dir->d_m_name), blength(dir->d_m_name) + 1);
         if ((dir = dirlookup(vol, dir->d_pdid)) == NULL)
             return NULL;
     }
index b266348ca0ca6a15073c1dfb003b70d90a426901..3aa043497b37c40e17702ef51b3248cb97914eaa 100644 (file)
@@ -608,7 +608,7 @@ static int catsearch(struct vol *vol, struct dir *dir,
                                                goto catsearch_end;
                                        }
                 }
-                path.m_name = cfrombstring(path.d_dir->d_m_name);
+                path.m_name = cfrombstr(path.d_dir->d_m_name);
                        
                                if (addstack(path.u_name, path.d_dir, cidx) == -1) {
                                        result = AFPERR_MISC;
index c641f249f4a85d361d580bdb8f97371aa33d2447..323a7371c9f958107fd0c09ebe53e1e6e7af4e92 100644 (file)
@@ -285,7 +285,7 @@ struct dir *dircache_search_by_did(const struct vol *vol, cnid_t did)
 
     if (cdir)
         LOG(log_debug, logtype_afpd, "dircache(did:%u): {cached: path:'%s'}",
-            ntohl(did), cfrombstring(cdir->d_u_name));
+            ntohl(did), cfrombstr(cdir->d_u_name));
     else
         LOG(log_debug, logtype_afpd, "dircache(did:%u): {not in cache}", ntohl(did));
 
@@ -380,7 +380,7 @@ int dircache_add(struct dir *dir)
     }
 
     LOG(log_debug, logtype_afpd, "dircache(did:%u,'%s'): {added}",
-        ntohl(dir->d_did), cfrombstring(dir->d_u_name));
+        ntohl(dir->d_did), cfrombstr(dir->d_u_name));
 
    AFP_ASSERT(queue_count == index_didname->hash_nodecount 
            && queue_count == dircache->hash_nodecount);
@@ -413,7 +413,7 @@ void dircache_remove(const struct vol *vol _U_, struct dir *dir, int flags)
     if (flags & DIDNAME_INDEX) {
         if ((hn = hash_lookup(index_didname, dir)) == NULL) {
             LOG(log_error, logtype_default, "dircache_remove(%u,\"%s\"): not in didname index", 
-                ntohl(dir->d_did), cfrombstring(dir->d_u_name));
+                ntohl(dir->d_did), cfrombstr(dir->d_u_name));
             dircache_dump();
             AFP_PANIC("dircache_remove");
         }
@@ -423,7 +423,7 @@ void dircache_remove(const struct vol *vol _U_, struct dir *dir, int flags)
     if (flags & DIRCACHE) {
         if ((hn = hash_lookup(dircache, dir)) == NULL) {
             LOG(log_error, logtype_default, "dircache_remove(%u,\"%s\"): not in dircache", 
-                ntohl(dir->d_did), cfrombstring(dir->d_u_name));
+                ntohl(dir->d_did), cfrombstr(dir->d_u_name));
             dircache_dump();
             AFP_PANIC("dircache_remove");
         }
@@ -431,7 +431,7 @@ void dircache_remove(const struct vol *vol _U_, struct dir *dir, int flags)
     }
 
     LOG(log_debug, logtype_afpd, "dircache(did:%u,\"%s\"): {removed}",
-        ntohl(dir->d_did), cfrombstring(dir->d_u_name));
+        ntohl(dir->d_did), cfrombstr(dir->d_u_name));
 
    AFP_ASSERT(queue_count == index_didname->hash_nodecount 
            && queue_count == dircache->hash_nodecount);
@@ -524,7 +524,7 @@ void dircache_dump(void)
                 dir->d_fullpath ? "d" : "f",
                 (dir->d_flags & DIRF_CACHELOCK) ? "l" : "-",
                 dir->d_ofork ? "o" : "-",
-                cfrombstring(dir->d_u_name));
+                cfrombstr(dir->d_u_name));
     }
 
     fprintf(dump, "\nSecondary DID/name index:\n");
@@ -542,7 +542,7 @@ void dircache_dump(void)
                 dir->d_fullpath ? "d" : "f",
                 (dir->d_flags & DIRF_CACHELOCK) ? "l" : "-",
                 dir->d_ofork ? "o" : "-",
-                cfrombstring(dir->d_u_name));
+                cfrombstr(dir->d_u_name));
     }
 
     fprintf(dump, "\nLRU Queue:\n");
@@ -561,7 +561,7 @@ void dircache_dump(void)
                 dir->d_fullpath ? "d" : "f",
                 (dir->d_flags & DIRF_CACHELOCK) ? "l" : "-",
                 dir->d_ofork ? "o" : "-",
-                cfrombstring(dir->d_u_name));
+                cfrombstr(dir->d_u_name));
         n = n->next;
     }
 
index ad76bd090f8dae8e6c25f4d33dfb5a617520ab7e..cadcdb025b168366920c02a986a2570154da763d 100644 (file)
@@ -369,19 +369,19 @@ static struct path *path_from_dir(struct vol *vol, struct dir *dir, struct path
         if (movecwd( vol, dirlookup(vol, dir->d_pdid)) < 0 ) /* 1 */
             return NULL;
 
-        memcpy(ret->m_name, cfrombstring(dir->d_m_name), blength(dir->d_m_name) + 1); /* 3 */
+        memcpy(ret->m_name, cfrombstr(dir->d_m_name), blength(dir->d_m_name) + 1); /* 3 */
         if (dir->d_m_name == dir->d_u_name) {
             ret->u_name = ret->m_name;
         } else {
             ret->u_name =  ret->m_name + blength(dir->d_m_name) + 1;
-            memcpy(ret->u_name, cfrombstring(dir->d_u_name), blength(dir->d_u_name) + 1);
+            memcpy(ret->u_name, cfrombstr(dir->d_u_name), blength(dir->d_u_name) + 1);
         }
 
         ret->d_dir = dir;
 
         LOG(log_debug, logtype_afpd, "cname('%s') {path-from-dir: AFPERR_ACCESS. curdir:'%s', path:'%s'}",
-            cfrombstring(dir->d_fullpath),
-            cfrombstring(curdir->d_fullpath),
+            cfrombstr(dir->d_fullpath),
+            cfrombstr(curdir->d_fullpath),
             ret->u_name);
 
         return ret;
@@ -390,12 +390,12 @@ static struct path *path_from_dir(struct vol *vol, struct dir *dir, struct path
         if (movecwd(vol, dirlookup(vol, dir->d_pdid)) < 0 ) /* 1 */
             return NULL;
 
-        memcpy(ret->m_name, cfrombstring(dir->d_m_name), blength(dir->d_m_name) + 1);
+        memcpy(ret->m_name, cfrombstr(dir->d_m_name), blength(dir->d_m_name) + 1);
         if (dir->d_m_name == dir->d_u_name) {
             ret->u_name = ret->m_name;
         } else {
             ret->u_name =  ret->m_name + blength(dir->d_m_name) + 1;
-            memcpy(ret->u_name, cfrombstring(dir->d_u_name), blength(dir->d_u_name) + 1);
+            memcpy(ret->u_name, cfrombstr(dir->d_u_name), blength(dir->d_u_name) + 1);
         }
 
         ret->d_dir = NULL;      /* 4 */
@@ -475,7 +475,7 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
             afp_errno = AFPERR_BADTYPE;
             return NULL;
         }
-        if (lstat(cfrombstring(ret->d_fullpath), &st) != 0) {
+        if (lstat(cfrombstr(ret->d_fullpath), &st) != 0) {
             LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {lstat: %s}", ntohl(did), strerror(errno));
             switch (errno) {
             case ENOENT:
@@ -526,9 +526,9 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
     }
 
     /* stat it and check if it's a dir */
-    LOG(log_debug, logtype_afpd, "dirlookup: {stating %s}", cfrombstring(fullpath));
+    LOG(log_debug, logtype_afpd, "dirlookup: {stating %s}", cfrombstr(fullpath));
 
-    if (stat(cfrombstring(fullpath), &st) != 0) { /* 5a */
+    if (stat(cfrombstr(fullpath), &st) != 0) { /* 5a */
         switch (errno) {
         case ENOENT:
             afp_errno = AFPERR_NOOBJ;
@@ -572,7 +572,7 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
     }
 
     LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {end: did:%u, path:'%s'}",
-        ntohl(did), ntohl(pdid), cfrombstring(ret->d_fullpath));
+        ntohl(did), ntohl(pdid), cfrombstr(ret->d_fullpath));
 
 exit:
     if (err) {
@@ -783,8 +783,8 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i
     if ((cdir = dircache_search_by_name(vol, dir, path->u_name, strlen(path->u_name))) != NULL) {
         /* there's a stray entry in the dircache */
         LOG(log_debug, logtype_afpd, "dir_add(did:%u,'%s/%s'): {stray cache entry: did:%u,'%s', removing}",
-            ntohl(dir->d_did), cfrombstring(dir->d_fullpath), path->u_name,
-            ntohl(cdir->d_did), cfrombstring(dir->d_fullpath));
+            ntohl(dir->d_did), cfrombstr(dir->d_fullpath), path->u_name,
+            ntohl(cdir->d_did), cfrombstr(dir->d_fullpath));
         if (dir_remove(vol, cdir) != 0) {
             dircache_dump();
             AFP_PANIC("dir_add");
@@ -829,14 +829,14 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i
     }
 
     if ((dircache_add(cdir)) != 0) { /* 4 */
-        LOG(log_error, logtype_afpd, "dir_add: fatal dircache error: %s", cfrombstring(fullpath));
+        LOG(log_error, logtype_afpd, "dir_add: fatal dircache error: %s", cfrombstr(fullpath));
         exit(EXITERR_SYS);
     }
 
 exit:
     if (err != 0) {
         LOG(log_debug, logtype_afpd, "dir_add('%s/%s'): error: %u",
-            cfrombstring(dir->d_u_name), path->u_name, err);
+            cfrombstr(dir->d_u_name), path->u_name, err);
 
         if (adp)
             ad_close_metadata(adp);
@@ -848,8 +848,8 @@ exit:
     } else {
         /* no error */
         LOG(log_debug, logtype_afpd, "dir_add(did:%u,'%s/%s'): {cached: %u,'%s'}",
-            ntohl(dir->d_did), cfrombstring(dir->d_fullpath), path->u_name,
-            ntohl(cdir->d_did), cfrombstring(cdir->d_fullpath));
+            ntohl(dir->d_did), cfrombstr(dir->d_fullpath), path->u_name,
+            ntohl(cdir->d_did), cfrombstr(cdir->d_fullpath));
     }
 
     return(cdir);
@@ -876,7 +876,7 @@ int dir_remove(const struct vol *vol, struct dir *dir)
 
     if (dir->d_flags & DIRF_CACHELOCK || dir->d_ofork) { /* 1 */
         LOG(log_warning, logtype_afpd, "dir_remove(did:%u,'%s'): dir is locked or has opened forks",
-            ntohl(dir->d_did), cfrombstring(dir->d_fullpath));
+            ntohl(dir->d_did), cfrombstr(dir->d_fullpath));
         return 0;
     }
 
@@ -887,7 +887,7 @@ int dir_remove(const struct vol *vol, struct dir *dir)
     }
 
     LOG(log_debug, logtype_afpd, "dir_remove(did:%u,'%s'): {removing}",
-        ntohl(dir->d_did), cfrombstring(dir->d_fullpath));
+        ntohl(dir->d_did), cfrombstr(dir->d_fullpath));
 
     dircache_remove(vol, dir, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); /* 3 */
     dir_free(dir);              /* 4 */
@@ -1013,7 +1013,7 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath)
     int         size = 0;
     int         toUTF8 = 0;
 
-    LOG(log_maxdebug, logtype_afpd, "came('%s'): {start}", cfrombstring(dir->d_fullpath));
+    LOG(log_maxdebug, logtype_afpd, "came('%s'): {start}", cfrombstr(dir->d_fullpath));
 
     data = *cpath;
     afp_errno = AFPERR_NOOBJ;
@@ -1054,7 +1054,7 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath)
 
     if (movecwd(vol, dir) < 0 ) {
         LOG(log_debug, logtype_afpd, "cname(did:%u): failed to chdir to '%s'",
-            ntohl(dir->d_did), cfrombstring(dir->d_fullpath));
+            ntohl(dir->d_did), cfrombstr(dir->d_fullpath));
         if (len == 0)
             return path_from_dir(vol, dir, &ret);
         else
@@ -1095,7 +1095,7 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath)
             return NULL;
         }
 
-        LOG(log_maxdebug, logtype_afpd, "came('%s'): {node: '%s}", cfrombstring(dir->d_fullpath), ret.u_name);
+        LOG(log_maxdebug, logtype_afpd, "came('%s'): {node: '%s}", cfrombstr(dir->d_fullpath), ret.u_name);
 
         /* Prevent access to our special folders like .AppleDouble */
         if (check_name(vol, ret.u_name)) {
@@ -1111,7 +1111,7 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath)
              * root parent (did 1) has one child: the volume. Requests for did=1 with
              * some <name> must check against the volume name.
              */
-            if ((strcmp(cfrombstring(vol->v_root->d_m_name), ret.m_name)) == 0)
+            if ((strcmp(cfrombstr(vol->v_root->d_m_name), ret.m_name)) == 0)
                 cdir = vol->v_root;
             else
                 return NULL;
@@ -1138,13 +1138,15 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath)
                  * this will terminate clean in while (1) because len == 0,
                  * probably afp_createfile|dir
                  */
-                LOG(log_maxdebug, logtype_afpd, "came('%s'): {leave-cnode ENOENT (possile create request): '%s'}", cfrombstring(dir->d_fullpath), ret.u_name);
+                LOG(log_maxdebug, logtype_afpd, "came('%s'): {leave-cnode ENOENT (possile create request): '%s'}",
+                    cfrombstr(dir->d_fullpath), ret.u_name);
                 continue; /* 10 */
             }
 
             switch (ret.st.st_mode & S_IFMT) {
             case S_IFREG: /* 11 */
-                LOG(log_debug, logtype_afpd, "came('%s'): {file: '%s'}", cfrombstring(dir->d_fullpath), ret.u_name);
+                LOG(log_debug, logtype_afpd, "came('%s'): {file: '%s'}",
+                    cfrombstr(dir->d_fullpath), ret.u_name);
                 if (len > 0) {
                     /* it wasn't the last part, so we have a bogus path request */
                     afp_errno = AFPERR_PARAM;
@@ -1152,9 +1154,11 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath)
                 }
                 continue; /* continues while loop */
             case S_IFLNK: /* 12 */
-                LOG(log_debug, logtype_afpd, "came('%s'): {link: '%s'}", cfrombstring(dir->d_fullpath), ret.u_name);
+                LOG(log_debug, logtype_afpd, "came('%s'): {link: '%s'}",
+                    cfrombstr(dir->d_fullpath), ret.u_name);
                 if (len > 0) {
-                    LOG(log_warning, logtype_afpd, "came('%s'): {symlinked dir: '%s'}", cfrombstring(dir->d_fullpath), ret.u_name);
+                    LOG(log_warning, logtype_afpd, "came('%s'): {symlinked dir: '%s'}",
+                        cfrombstr(dir->d_fullpath), ret.u_name);
                     afp_errno = AFPERR_PARAM;
                     return NULL;
                 }
@@ -1183,7 +1187,7 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath)
         /* Now chdir to the evaluated dir */
         if (movecwd( vol, cdir ) < 0 ) { /* 16 */
             LOG(log_debug, logtype_afpd, "cname(cwd:'%s'): failed to chdir to new subdir '%s': %s",
-                cfrombstring(curdir->d_fullpath), cfrombstring(cdir->d_fullpath), strerror(errno));
+                cfrombstr(curdir->d_fullpath), cfrombstr(cdir->d_fullpath), strerror(errno));
             if (len == 0)
                 return path_from_dir(vol, cdir, &ret);
             else
@@ -1205,8 +1209,8 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath)
     }
 
     LOG(log_debug, logtype_afpd, "came('%s') {end: curdir:'%s', path:'%s'}",
-        cfrombstring(dir->d_fullpath),
-        cfrombstring(curdir->d_fullpath),
+        cfrombstr(dir->d_fullpath),
+        cfrombstr(curdir->d_fullpath),
         ret.u_name);
 
     return &ret;
@@ -1228,7 +1232,7 @@ int movecwd(const struct vol *vol, struct dir *dir)
     AFP_ASSERT(dir);
 
     LOG(log_maxdebug, logtype_afpd, "movecwd(curdir:'%s', cwd:'%s')",
-        cfrombstring(curdir->d_fullpath), getcwdpath());
+        cfrombstr(curdir->d_fullpath), getcwdpath());
 
     if ( dir == curdir)
         return( 0 );
@@ -1237,11 +1241,12 @@ int movecwd(const struct vol *vol, struct dir *dir)
         return 0;
     }
 
-    LOG(log_debug, logtype_afpd, "movecwd(did:%u, '%s')", ntohl(dir->d_did), cfrombstring(dir->d_fullpath));
+    LOG(log_debug, logtype_afpd, "movecwd(did:%u, '%s')",
+        ntohl(dir->d_did), cfrombstr(dir->d_fullpath));
 
-    if ((ret = lchdir(cfrombstring(dir->d_fullpath))) != 0 ) {
+    if ((ret = lchdir(cfrombstr(dir->d_fullpath))) != 0 ) {
         LOG(log_debug, logtype_afpd, "movecwd('%s'): ret: %u, %s",
-            cfrombstring(dir->d_fullpath), ret, strerror(errno));
+            cfrombstr(dir->d_fullpath), ret, strerror(errno));
         if (ret == 1) {
             /* p is a symlink or getcwd failed */
             afp_errno = AFPERR_BADTYPE;
@@ -1384,7 +1389,7 @@ int getdirparams(const struct vol *vol,
         case DIRPBIT_ATTR :
             if ( isad ) {
                 ad_getattr(&ad, &ashort);
-            } else if (invisible_dots(vol, cfrombstring(dir->d_u_name))) {
+            } else if (invisible_dots(vol, cfrombstr(dir->d_u_name))) {
                 ashort = htons(ATTRBIT_INVISIBLE);
             } else
                 ashort = 0;
@@ -1430,7 +1435,7 @@ int getdirparams(const struct vol *vol,
                 memcpy(data + FINDERINFO_FRVIEWOFF, &ashort, sizeof(ashort));
 
                 /* dot files are by default visible */
-                if (invisible_dots(vol, cfrombstring(dir->d_u_name))) {
+                if (invisible_dots(vol, cfrombstr(dir->d_u_name))) {
                     ashort = htons(FINDERINFO_INVISIBLE);
                     memcpy(data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
                 }
@@ -1553,12 +1558,12 @@ int getdirparams(const struct vol *vol,
     if ( l_nameoff ) {
         ashort = htons( data - buf );
         memcpy( l_nameoff, &ashort, sizeof( ashort ));
-        data = set_name(vol, data, pdid, cfrombstring(dir->d_m_name), dir->d_did, 0);
+        data = set_name(vol, data, pdid, cfrombstr(dir->d_m_name), dir->d_did, 0);
     }
     if ( utf_nameoff ) {
         ashort = htons( data - buf );
         memcpy( utf_nameoff, &ashort, sizeof( ashort ));
-        data = set_name(vol, data, pdid, cfrombstring(dir->d_m_name), dir->d_did, utf8);
+        data = set_name(vol, data, pdid, cfrombstr(dir->d_m_name), dir->d_did, utf8);
     }
     if ( isad ) {
         ad_close_metadata( &ad );
@@ -1795,7 +1800,7 @@ int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *b
          * to set our name, etc.
          */
         if ( (ad_get_HF_flags( &ad ) & O_CREAT)) {
-            ad_setname(&ad, cfrombstring(curdir->d_m_name));
+            ad_setname(&ad, cfrombstr(curdir->d_m_name));
         }
     }
 
@@ -2057,7 +2062,7 @@ int afp_syncdir(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_,
 
         if ( fsync(dfd) < 0 )
             LOG(log_error, logtype_afpd, "afp_syncdir(%s): %s",
-                vol->ad_path(cfrombstring(dir->d_u_name), ADFLAGS_DIR), strerror(errno) );
+                vol->ad_path(cfrombstr(dir->d_u_name), ADFLAGS_DIR), strerror(errno) );
         close(dfd);
     }
 
@@ -2262,7 +2267,7 @@ int deletecurdir(struct vol *vol)
         goto delete_done;
     }
 
-    err = netatalk_rmdir_all_errors(-1, cfrombstring(fdir->d_u_name));
+    err = netatalk_rmdir_all_errors(-1, cfrombstr(fdir->d_u_name));
     if ( err ==  AFP_OK || err == AFPERR_NOOBJ) {
         cnid_delete(vol->v_cdb, fdir->d_did);
         dir_remove( vol, fdir );
index b8a403bd4fd958a9b5de04d9c6cca5ccb3ea5bc2..49625bdc2f0586d598ffe22715bc09e044bbf331 100644 (file)
@@ -270,7 +270,7 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,
 
     LOG(log_debug, logtype_afpd, "enumerate(vid:%u, did:%u, cwddid:%u, cwd:'%s', name:'%s', f/d:%04x/%04x, rc:%u, i:%u, max:%u)",
         ntohs(vid), ntohl(did), ntohl(curdir->d_did),
-        cfrombstring(curdir->d_fullpath), o_path->u_name,
+        cfrombstr(curdir->d_fullpath), o_path->u_name,
         fbitmap, dbitmap, reqcnt, sindex, maxsz);
 
     data = rbuf + 3 * sizeof( u_int16_t );
index 095189ce2b84a0605d34e18f5b99c402ac6ae67c..46c0bf309fbc4bb6152c8ce26e169c64231b007c 100644 (file)
@@ -176,7 +176,7 @@ int afp_getfildirparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *r
 
     LOG(log_debug, logtype_afpd, "getfildirparams(vid:%u, did:%u, f/d:%04x/%04x) {cwdid:%u, cwd: %s, name:'%s'}",
         ntohs(vid), ntohl(dir->d_did), fbitmap, dbitmap,
-        ntohl(curdir->d_did), cfrombstring(curdir->d_fullpath), s_path->u_name);
+        ntohl(curdir->d_did), cfrombstr(curdir->d_fullpath), s_path->u_name);
 
     st   = &s_path->st;
     if (!s_path->st_valid) {
@@ -523,7 +523,7 @@ int afp_rename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size
         if ( movecwd( vol, dirlookup(vol, sdir->d_pdid) ) < 0 ) {
             return afp_errno;
         }
-        memcpy(oldname, cfrombstring(sdir->d_m_name), blength(sdir->d_m_name) +1);
+        memcpy(oldname, cfrombstr(sdir->d_m_name), blength(sdir->d_m_name) +1);
     }
 
     /* another place where we know about the path type */
@@ -596,7 +596,7 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size
             rc = deletefile(vol, -1, upath, 1);
 
             struct dir *cachedfile;
-            if (cachedfile = dircache_search_by_name(vol, dir, upath, strlen(upath))) {
+            if ((cachedfile = dircache_search_by_name(vol, dir, upath, strlen(upath)))) {
                 dircache_remove(vol, cachedfile, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX);
                 dir_free(cachedfile);
             }
@@ -627,9 +627,9 @@ char *absupath(const struct vol *vol, struct dir *dir, char *u)
     if (path->slen > MAXPATHLEN)
         return NULL;
 
-    LOG(log_debug, logtype_afpd, "absupath: %s", cfrombstring(path));
+    LOG(log_debug, logtype_afpd, "absupath: %s", cfrombstr(path));
 
-    strncpy(pathbuf, cfrombstring(path), blength(path) + 1);
+    strncpy(pathbuf, cfrombstr(path), blength(path) + 1);
     bdestroy(path);
 
     return(pathbuf);
@@ -699,7 +699,7 @@ int afp_moveandrename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U
         }
         strcpy(oldname, path->m_name); /* an extra copy for of_rename */
     } else {
-        memcpy(oldname, cfrombstring(sdir->d_m_name), blength(sdir->d_m_name) + 1);
+        memcpy(oldname, cfrombstr(sdir->d_m_name), blength(sdir->d_m_name) + 1);
     }
 
 #ifdef HAVE_RENAMEAT
index 7769542df4a4fe8e9df8a8f94043bbab57b42866..91533e619a674d9748b5c1cc6f365c6d58952aae 100644 (file)
@@ -182,11 +182,11 @@ private_demangle(const struct vol *vol, char *mfilename, cnid_t did, cnid_t *osx
         }
         if (!osx) {
             /* it's not from cname so mfilename and dir must be the same */
-            if (strcmp(cfrombstring(dir->d_m_name), mfilename) == 0) {
-                return cfrombstring(dir->d_u_name);
+            if (strcmp(cfrombstr(dir->d_m_name), mfilename) == 0) {
+                return cfrombstr(dir->d_u_name);
             }
         } else {
-            return demangle_checks(vol, cfrombstring(dir->d_u_name), mfilename, prefix, t);
+            return demangle_checks(vol, cfrombstr(dir->d_u_name), mfilename, prefix, t);
         }
     }
     else if (NULL != (u_name = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) {
index a6359ad29329373e5db2fdb7b673cfbf3fee6241..b82eabcb2f24405130b0b04782259b8642b61a38 100644 (file)
@@ -290,7 +290,7 @@ int of_stat(struct path *path)
 
     if ((ret = lstat(path->u_name, &path->st)) < 0) {
         LOG(log_debug, logtype_afpd, "of_stat('%s/%s': %s)",
-            cfrombstring(curdir->d_fullpath), path->u_name, strerror(errno));
+            cfrombstr(curdir->d_fullpath), path->u_name, strerror(errno));
        path->st_errno = errno;
     }
 
@@ -335,7 +335,7 @@ int of_statdir(struct vol *vol, struct path *path)
     len = blength(path->d_dir->d_u_name);
     if (len > (MAXPATHLEN - 3))
         len = MAXPATHLEN - 3;
-    strncpy(pathname + 3, cfrombstring(path->d_dir->d_u_name), len + 1);
+    strncpy(pathname + 3, cfrombstr(path->d_dir->d_u_name), len + 1);
 
     LOG(log_debug, logtype_afpd, "of_statdir: stating: '%s'", pathname);
 
@@ -350,7 +350,7 @@ int of_statdir(struct vol *vol, struct path *path)
            return -1;
        path->st_errno = 0;
 
-       if ((ret = lstat(cfrombstring(path->d_dir->d_u_name), &path->st)) < 0) 
+       if ((ret = lstat(cfrombstr(path->d_dir->d_u_name), &path->st)) < 0) 
            path->st_errno = errno;
     }
 
index a402339accf4a2aa6f904ada7397e4e04e969ab2..df8262ca0cc019cedf221e098f3fb76d4aa752ef 100644 (file)
 
 #include <atalk/bstrlib.h>
 
-#define cfrombstring(b) ((char *)((b)->data))
+#define cfrombstr(b) ((char *)((b)->data))
+
+/* strip slashes from end of a bstring */
+#define BSTRING_STRIP_SLASH(a)                      \
+    do {                                            \
+        while ((a)->data[(a)->slen - 1] == '/')     \
+            bdelete((a), (a)->slen - 1, 1);         \
+    } while (0);
 
 typedef struct tagbstring static_bstring;