]> arthur.barton.de Git - netatalk.git/commitdiff
New utility: ad
authorfranklahm <franklahm>
Tue, 1 Sep 2009 14:28:07 +0000 (14:28 +0000)
committerfranklahm <franklahm>
Tue, 1 Sep 2009 14:28:07 +0000 (14:28 +0000)
bin/cnid/.cvsignore
bin/cnid/Makefile.am
bin/cnid/ad.c [new file with mode: 0644]
bin/cnid/ad.h [new file with mode: 0644]
bin/cnid/ad_cp.c [new file with mode: 0644]
bin/cnid/ad_ls.c [new file with mode: 0644]
bin/cnid/ad_util.c [new file with mode: 0644]
include/atalk/adouble.h
include/atalk/volinfo.h
libatalk/util/volinfo.c

index 8834f14d3d78f223547e9e04920d284276f19fcb..4857ef88d269b7631c939e6d7ff2dd1ec941cf9a 100644 (file)
@@ -1,5 +1,6 @@
 Makefile
 Makefile.in
+ad
 cnid2_create
 cnid_maint
 cnid_index
index 16b5bfac38f2fd879f52cfb621a1eaccaa4f19dd..09acab9f341b3fb2722d0ce9d8017a02a6c632e7 100644 (file)
@@ -1,9 +1,15 @@
 # Makefile.am for bin/cnid/
 
 EXTRA_DIST = cnid_maint.in cnid2_create.in
+noinst_HEADERS = ad.h
 
 if USE_BDB
+bin_PROGRAMS = ad
 bin_SCRIPTS = cnid_maint cnid2_create
-else
-#bin_SCRIPTS = 
+
+ad_SOURCES = ad.c ad_util.c \
+       ad_ls.c \
+       ad_cp.c
+
+ad_LDADD = $(top_builddir)/libatalk/libatalk.la
 endif
diff --git a/bin/cnid/ad.c b/bin/cnid/ad.c
new file mode 100644 (file)
index 0000000..a569659
--- /dev/null
@@ -0,0 +1,60 @@
+/* 
+   $Id: ad.c,v 1.1 2009-09-01 14:28:07 franklahm Exp $
+
+   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 "ad.h"
+
+static void usage_main()
+{
+/*
+    printf("Usage: ad ls|rm|cp|mv|set [file|dir, ...]\n");
+*/
+    printf("Usage: ad ls [file|dir, ...]\n");
+}
+
+int main(int argc, char **argv)
+{
+    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
new file mode 100644 (file)
index 0000000..bb08085
--- /dev/null
@@ -0,0 +1,41 @@
+/* 
+   $Id: ad.h,v 1.1 2009-09-01 14:28:07 franklahm Exp $
+
+   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
+
+#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))
+
+typedef struct {
+    struct volinfo volinfo;
+//    char *dirname;
+//    char *basename;
+//    int adflags;                /* file:0, dir:ADFLAGS_DIR */
+} afpvol_t;
+
+
+extern int newvol(const char *path, afpvol_t *vol);
+extern void freevol(afpvol_t *vol);
+
+extern int ad_ls(int argc, char **argv);
+extern int ad_cp(int argc, char **argv);
+
+#endif /* AD_H */
diff --git a/bin/cnid/ad_cp.c b/bin/cnid/ad_cp.c
new file mode 100644 (file)
index 0000000..e2f2472
--- /dev/null
@@ -0,0 +1,303 @@
+/* 
+   $Id: ad_cp.c,v 1.1 2009-09-01 14:28:07 franklahm Exp $
+
+   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 <libgen.h>
+
+#include <atalk/adouble.h>
+#include <atalk/cnid.h>
+#include <atalk/volinfo.h>
+#include <atalk/util.h>
+#include "ad.h"
+
+#define ADv2_DIRNAME ".AppleDouble"
+
+/* options */
+static int cp_R;
+static int cp_L;
+static int cp_P;
+static int cp_n;
+static int cp_p;
+static int cp_v;
+
+static char           *netatalk_dirs[] = {
+    ADv2_DIRNAME,
+    ".AppleDB",
+    ".AppleDesktop",
+    NULL
+};
+
+/*
+  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()
+{
+    printf(
+        "Usage: ad cp [-R [-L | -P]] [-pv] <source_file> <target_file>\n"
+        "Usage: ad cp [-R [-L | -P]] [-pv] <source_file [source_file ...]> <target_directory>\n"
+        );
+}
+
+static int ad_cp_copy(const afpvol_t *srcvol, const afpvol_t *dstvol,
+                      char *srcfile, char *dstfile, struct stat *st)
+{
+    printf("copy: '%s' -> '%s'\n", srcfile, dstfile);
+    return 0;
+}
+
+static int ad_cp_r(const afpvol_t *srcvol, const afpvol_t *dstvol, char *srcdir, char *dstdir)
+{
+    int ret = 0, cwd, dirprinted = 0, dirempty;
+    static char srcpath[MAXPATHLEN+1];
+    static char dstpath[MAXPATHLEN+1];
+    char *tmp;
+    DIR *dp;
+    struct dirent *ep;
+    static struct stat st;      /* Save some stack space */
+
+    strlcat(srcpath, srcdir, sizeof(srcpath));
+    strlcat(dstpath, dstdir, sizeof(dstpath));
+
+    if ((dp = opendir (srcdir)) == NULL) {
+        perror("Couldn't opendir .");
+        return -1;
+    }
+
+    /* First run: copy files */
+    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 ((check_netatalk_dirs(ep->d_name)) != NULL)
+            continue;
+
+        if (lstat(ep->d_name, &st) < 0) {
+            perror("Can't stat");
+            return -1;
+        }
+
+        /* Build paths, copy, strip name */
+        strlcat(srcpath, "/", sizeof(srcpath));
+        strlcat(dstpath, "/", sizeof(dstpath));
+        strlcat(srcpath, ep->d_name, sizeof(srcpath));
+        strlcat(dstpath, ep->d_name, sizeof(dstpath));
+
+        ret = ad_cp_copy(srcvol, dstvol, srcpath, dstpath, &st);
+
+        if ((tmp = strrchr(srcpath, '/')))
+            *tmp = 0;
+        if ((tmp = strrchr(dstpath, '/')))
+            *tmp = 0;
+
+        if (ret != 0)
+            goto exit;
+    }
+
+    /* Second run: recurse to dirs */
+    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 (check_netatalk_dirs(ep->d_name) != NULL)
+            continue;
+        
+        if (lstat(ep->d_name, &st) < 0) {
+            perror("Can't stat");
+            return -1;
+        }
+        
+        /* Recursion */
+        if (S_ISDIR(st.st_mode)) {
+            strlcat(srcpath, "/", sizeof(srcpath));
+            strlcat(dstpath, "/", sizeof(dstpath));
+            ret = ad_cp_r(srcvol, dstvol, ep->d_name, ep->d_name);
+        }
+        if (ret != 0)
+            goto exit;
+    }
+
+exit:
+    closedir(dp);
+    fchdir(cwd);
+    close(cwd);
+
+    if ((tmp = strrchr(srcpath, '/')))
+        *tmp = 0;
+    if ((tmp = strrchr(dstpath, '/')))
+        *tmp = 0;
+
+    return ret;
+}
+
+int ad_cp(int argc, char **argv)
+{
+    int c, numpaths;
+    afpvol_t srcvvol;
+    struct stat sst;
+    struct stat dst;
+    afpvol_t srcvol;
+    afpvol_t dstvol;
+    char *srcfile = NULL;
+    char *srcdir = NULL;    
+    char *dstfile = NULL;
+    char *dstdir = NULL;
+    char path[MAXPATHLEN+1];
+    char *basenametmp;
+
+    while ((c = getopt(argc, argv, ":npvLPR")) != -1) {
+        switch(c) {
+        case 'n':
+            cp_n = 1;
+            break;
+        case 'p':
+            cp_p = 1;
+            break;
+        case 'v':
+            cp_v = 1;
+            break;
+        case 'L':
+            cp_L = 1;
+            break;
+        case 'P':
+            cp_P = 1;
+            break;
+        case 'R':
+            cp_R = 1;
+            break;
+        case ':':
+        case '?':
+            usage_cp();
+            return -1;
+            break;
+        }
+    }
+
+    /* How many pathnames do we have */
+    numpaths = argc - optind;
+    printf("Number of paths: %u\n", numpaths);
+    if (numpaths < 2) {
+        usage_cp();
+        exit(EXIT_FAILURE);
+    }
+
+    while ( argv[argc-1][(strlen(argv[argc-1]) - 1)] == '/')
+        argv[argc-1][(strlen(argv[argc-1]) - 1)] = 0;
+    printf("Destination is: %s\n", argv[argc-1]);
+
+    /* Create vol for destination */
+    newvol(argv[argc-1], &dstvol);
+
+    if (numpaths == 2) {
+        /* Case 1: 2 paths */
+        if (stat(argv[optind], &sst) != 0)
+            goto next;
+        if (S_ISREG(sst.st_mode)) {
+            /* Either file to file or file to dir copy */
+            newvol(argv[optind], &srcvol);
+            ad_cp_copy(&srcvol, &dstvol, srcfile, path, &sst);
+            freevol(&srcvol);
+            freevol(&dstvol);
+            
+        } else if (S_ISDIR(sst.st_mode)) {
+            /* dir to dir copy. Check if -R is requested */
+            if (!cp_R) {
+                usage_cp();
+                exit(EXIT_FAILURE);
+            }
+        }
+
+    } else {
+        /* Case 2: >2 paths */
+        while (optind < (argc-1)) {
+            printf("Source is: %s\n", argv[optind]);
+            newvol(argv[optind], &srcvol);
+            if (stat(argv[optind], &sst) != 0)
+                goto next;
+            if (S_ISDIR(sst.st_mode)) {
+                /* Source is a directory */
+                if (!cp_R) {
+                    printf("Source %s is a directory\n", argv[optind]);
+                    goto next;
+                }
+                srcdir = argv[optind];
+                dstdir = argv[argc-1];
+                
+                ad_cp_r(&srcvol, &dstvol, srcdir, dstdir);
+                freevol(&srcvol);
+            } else {
+                /* Source is a file */
+                srcfile = argv[optind];
+                if (numpaths != 2 && !dstdir) {
+                    usage_cp();
+                    exit(EXIT_FAILURE);
+                }
+                path[0] = 0;
+                strlcat(path, dstdir, sizeof(path));
+                basenametmp = strdup(srcfile);
+                strlcat(path, basename(basenametmp), sizeof(path));
+                free(basenametmp);
+                printf("%s %s\n", srcfile, path);
+                if (ad_cp_copy(&srcvol, &dstvol, srcfile, path, &sst) != 0) {
+                    freevol(&srcvol);
+                    freevol(&dstvol);
+                    exit(EXIT_FAILURE);
+                }
+            } /* else */
+        next:
+            optind++;
+        } /* while */
+    } /* else (numpath>2) */
+
+    freevol(&dstvol);
+
+    return 0;
+
+}
diff --git a/bin/cnid/ad_ls.c b/bin/cnid/ad_ls.c
new file mode 100644 (file)
index 0000000..58ab5d9
--- /dev/null
@@ -0,0 +1,635 @@
+/* 
+   $Id: ad_ls.c,v 1.1 2009-09-01 14:28:07 franklahm Exp $
+
+   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()
+{
+    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] = "----";
+
+    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 */
+    int i;
+    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 */
+    uint32_t 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
+
+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;
+}
+
+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 (lstat(ep->d_name, &st) < 0) {
+                perror("Can't stat");
+                return -1;
+            }
+
+            /* 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 {
+        firstarg = optind;
+
+        /* First run: only print files from argv paths */
+        int havefile = 0;
+        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
new file mode 100644 (file)
index 0000000..0624b5a
--- /dev/null
@@ -0,0 +1,66 @@
+/* 
+   $Id: ad_util.c,v 1.1 2009-09-01 14:28:07 franklahm Exp $
+
+   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 <string.h>
+#include <errno.h>
+#include <libgen.h>
+
+#include <atalk/cnid.h>
+#include <atalk/volinfo.h>
+#include "ad.h"
+
+
+int newvol(const char *path, afpvol_t *vol)
+{
+//    char *pathdup;
+
+    memset(vol, sizeof(afpvol_t), 0);
+
+//    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
+}
index 1e3680a21fb2aeabde7aef8da6320bb97a87f75b..fb10fbad30da81a30eacd153d468ad9e4eef897b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: adouble.h,v 1.39 2009-07-21 13:41:16 didg Exp $
+ * $Id: adouble.h,v 1.40 2009-09-01 14:28:07 franklahm Exp $
  * Copyright (c) 1990,1991 Regents of The University of Michigan.
  * All Rights Reserved.
  *
@@ -375,18 +375,19 @@ struct adouble_fops {
 #define FINDERINFO_FRCREATOFF  4
 #define FINDERINFO_FRFLAGOFF   8
 
-/* finderinfo flags */
-#define FINDERINFO_ISONDESK      (1)     /* "d" */
+/* FinderInfo Flags, char in `ad ls`, valid for files|dirs */
+#define FINDERINFO_ISONDESK      (1)     /* "d", fd */
 #define FINDERINFO_COLOR         (0x0e)
-#define FINDERINFO_ISHARED       (1<<6)  /* "m" */
-#define FINDERINFO_HASNOINITS    (1<<7)  /* "n" */
-#define FINDERINFO_HASBEENINITED (1<<8)  /* "i" */
-#define FINDERINFO_HASCUSTOMICON (1<<10) /* "c" */
-#define FINDERINFO_ISSTATIONNERY (1<<11) /* "t" */
-#define FINDERINFO_NAMELOCKED    (1<<12) /* "s" */
-#define FINDERINFO_HASBUNDLE     (1<<13) /* "b" */
-#define FINDERINFO_INVISIBLE     (1<<14) /* "v" */
-#define FINDERINFO_ISALIAS       (1<<15) /* "a" */
+#define FINDERINFO_HIDEEXT       (1<<4)  /* "e", fd */
+#define FINDERINFO_ISHARED       (1<<6)  /* "m", f  */
+#define FINDERINFO_HASNOINITS    (1<<7)  /* "n", f  */
+#define FINDERINFO_HASBEENINITED (1<<8)  /* "i", fd */
+#define FINDERINFO_HASCUSTOMICON (1<<10) /* "c", fd */
+#define FINDERINFO_ISSTATIONNERY (1<<11) /* "t", f  */
+#define FINDERINFO_NAMELOCKED    (1<<12) /* "s", fd */
+#define FINDERINFO_HASBUNDLE     (1<<13) /* "b", fd */
+#define FINDERINFO_INVISIBLE     (1<<14) /* "v", fd */
+#define FINDERINFO_ISALIAS       (1<<15) /* "a", fd */
 
 #define FINDERINFO_FRVIEWOFF  14 
 #define FINDERINFO_CUSTOMICON 0x4
@@ -398,23 +399,24 @@ struct adouble_fops {
    <https://sourceforge.net/tracker/?func=detail&aid=2802236&group_id=8642&atid=108642>
  */
 
-/* AFP attributes for files and dirs. (d) = only these are valid for directories */
-#define ATTRBIT_INVISIBLE (1<<0)  /* (d) */
-#define ATTRBIT_MULTIUSER (1<<1)
-#define ATTRBIT_SYSTEM    (1<<2)  /* "y" (d) */
-#define ATTRBIT_DOPEN     (1<<3)  /* data fork already open */
-#define ATTRBIT_ROPEN     (1<<4)  /* resource fork already open */
-#define ATTRBIT_NOWRITE   (1<<5)  /* "w" write inhibit(v2)/read-only(v1) bit ("") */
-#define ATTRBIT_BACKUP    (1<<6)  /* "b" (d) */
-#define ATTRBIT_NORENAME  (1<<7)  /* "r" (d) */
-#define ATTRBIT_NODELETE  (1<<8)  /* "d" (d) */
-#define ATTRBIT_NOCOPY    (1<<10) /* "c" */
-#define ATTRBIT_SETCLR    (1<<15) /* set/clear bits (d) */
-
-/* AFP attributes for dirs */
-#define ATTRBIT_EXPFLDR   (1<<1)  /* Folder is a sharepoint ("p") */
-#define ATTRBIT_MOUNTED   (1<<3)  /* Directory is mounted by a user ("") */
-#define ATTRBIT_SHARED    (1<<4)  /* shared area, called IsExpFolder in spec ("") */
+/* AFP attributes, char in `ad ls`, valid for files|dirs */
+#define ATTRBIT_INVISIBLE (1<<0)  /* opaque from FinderInfo */
+#define ATTRBIT_MULTIUSER (1<<1)  /* file: opaque, dir: see below */
+#define ATTRBIT_SYSTEM    (1<<2)  /* "y", fd */
+#define ATTRBIT_DOPEN     (1<<3)  /* data fork already open. Not stored, computed on the fly */
+#define ATTRBIT_ROPEN     (1<<4)  /* resource fork already open. Not stored, computed on the fly */
+#define ATTRBIT_NOWRITE   (1<<5)  /* "w", f, write inhibit(v2)/read-only(v1) bit */
+#define ATTRBIT_BACKUP    (1<<6)  /* "p", fd */
+#define ATTRBIT_NORENAME  (1<<7)  /* "r", fd */
+#define ATTRBIT_NODELETE  (1<<8)  /* "l", fd */
+#define ATTRBIT_NOCOPY    (1<<10) /* "o", f */
+#define ATTRBIT_SETCLR    (1<<15) /* set/clear bit (d) */
+
+/* AFP attributes for dirs. These should probably be computed on the fly.
+ * We don't do that, nor does e.g. OS S X 10.5 Server */
+#define ATTRBIT_EXPFLDR   (1<<1)  /* Folder is a sharepoint */
+#define ATTRBIT_MOUNTED   (1<<3)  /* Directory is mounted by a user */
+#define ATTRBIT_SHARED    (1<<4)  /* Shared area, called IsExpFolder in spec */
  
 /* private AFPFileInfo bits */
 #define AD_AFPFILEI_OWNER       (1 << 0) /* any owner */
index 0caa94ab7eecf3d564600994acac479fa8590d6b..fcf3a48d9ad2e8918877209b79c64209ed58c1f7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: volinfo.h,v 1.5 2009-05-14 13:46:08 franklahm Exp $
+ * $Id: volinfo.h,v 1.6 2009-09-01 14:28:07 franklahm Exp $
  */
 
 #ifndef _ATALK_VOLINFO_H
@@ -46,6 +46,7 @@
 #define AFPVOL_ULOWERMUPPER    (AFPVOL_MTOULOWER | AFPVOL_UTOMUPPER)
 
 /* volinfo for shell utilities */
+#define VOLINFODIR  ".AppleDesktop"
 #define VOLINFOFILE ".volinfo"
 
 struct volinfo {
index 0c06c120298c649f5082da346bc10affaaac9f4f..8ba6b00a8795c5f038b2baae6b49827bf5c1766d 100644 (file)
@@ -149,8 +149,9 @@ static char * make_path_absolute(char *path, size_t bufsize)
 
     if (!S_ISDIR(st.st_mode)) {
         if (NULL == (p=strrchr(abspath, '/')) )
-            return NULL;
-        *p = '\0';
+            strcpy(abspath, ".");
+        else
+            *p = '\0';
     }
 
     if (!getcwd(savecwd, sizeof(savecwd)) || chdir(abspath) < 0)       
@@ -158,13 +159,11 @@ static char * make_path_absolute(char *path, size_t bufsize)
 
     if (!getcwd(abspath, sizeof(abspath)) || chdir (savecwd) < 0)
         return NULL;
-        
     
     if (strlen(abspath) > bufsize)
         return NULL;
 
     strlcpy(path, abspath, bufsize);
-
     return path;
 }