]> arthur.barton.de Git - netatalk.git/commitdiff
Start working on ad_set
authorFrank Lahm <franklahm@googlemail.com>
Tue, 3 Apr 2012 08:07:12 +0000 (10:07 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Tue, 3 Apr 2012 08:07:12 +0000 (10:07 +0200)
bin/ad/Makefile.am
bin/ad/ad.c
bin/ad/ad_set.c [new file with mode: 0644]

index 7e6fe922b911db850841a15d3e7e72eb6d3cf491..5c3f47b67f918c634dc9247d97d3c70e42896f5c 100644 (file)
@@ -12,7 +12,8 @@ ad_SOURCES = \
        ad_ls.c \
        ad_cp.c \
        ad_mv.c \
-       ad_rm.c
+       ad_rm.c \
+       ad_set.c
 
 ad_CFLAGS = -D_PATH_AD=\"$(bindir)/ad\"
 
index 6115c2f2fb3c21b73e07d70793785fe82aae4417..078989fca081f8ac2a793ee666ecf3b15b75b5c8 100644 (file)
@@ -35,7 +35,7 @@
 
 static void usage_main(void)
 {
-    printf("Usage: ad ls|cp|rm|mv|find [file|dir, ...]\n");
+    printf("Usage: ad ls|cp|rm|mv|set|find [file|dir, ...]\n");
     printf("       ad -v|--version\n");
 }
 
@@ -69,6 +69,8 @@ int main(int argc, char **argv)
         return ad_rm(argc - 1, argv + 1, &obj);
     else if (STRCMP(argv[1], ==, "mv"))
         return ad_mv(argc, argv, &obj);
+    else if (STRCMP(argv[1], ==, "set"))
+        return ad_set(argc, argv, &obj);
     else if (STRCMP(argv[1], ==, "find"))
         return ad_find(argc, argv, &obj);
     else if (STRCMP(argv[1], ==, "-v")) {
diff --git a/bin/ad/ad_set.c b/bin/ad/ad_set.c
new file mode 100644 (file)
index 0000000..1a2cac8
--- /dev/null
@@ -0,0 +1,417 @@
+/* 
+   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 "ad.h"
+
+#define ADv2_DIRNAME ".AppleDouble"
+
+#define DIR_DOT_OR_DOTDOT(a) \
+        ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0))
+
+static volatile sig_atomic_t alarmed;
+
+/* 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"
+};
+
+/*
+  SIGNAL handling:
+  catch SIGINT and SIGTERM which cause clean exit. Ignore anything else.
+*/
+
+static void sig_handler(int signo)
+{
+    alarmed = 1;
+    return;
+}
+
+static void set_signal(void)
+{
+    struct sigaction sv;
+
+    sv.sa_handler = sig_handler;
+    sv.sa_flags = SA_RESTART;
+    sigemptyset(&sv.sa_mask);
+    if (sigaction(SIGTERM, &sv, NULL) < 0)
+        ERROR("error in sigaction(SIGTERM): %s", strerror(errno));
+
+    if (sigaction(SIGINT, &sv, NULL) < 0)
+        ERROR("error in sigaction(SIGINT): %s", strerror(errno));
+
+    memset(&sv, 0, sizeof(struct sigaction));
+    sv.sa_handler = SIG_IGN;
+    sigemptyset(&sv.sa_mask);
+
+    if (sigaction(SIGABRT, &sv, NULL) < 0)
+        ERROR("error in sigaction(SIGABRT): %s", strerror(errno));
+
+    if (sigaction(SIGHUP, &sv, NULL) < 0)
+        ERROR("error in sigaction(SIGHUP): %s", strerror(errno));
+
+    if (sigaction(SIGQUIT, &sv, NULL) < 0)
+        ERROR("error in sigaction(SIGQUIT): %s", strerror(errno));
+}
+
+/*
+  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_set(void)
+{
+    printf(
+        "Usage: ad set file|dir [-t TYPE] [-c CREATOR] [-l label] [-f flags]\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_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->vol->v_path == NULL)
+        return;
+
+    ad_init(&ad, vol->vol);
+
+    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(&ad, ADFLAGS_HF);
+}
+
+int ad_ls(int argc, char **argv, AFPObj *obj)
+{
+    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;
+        }
+
+    }
+
+    set_signal();
+    cnid_init();
+
+    if ((argc - optind) == 0) {
+        openvol(obj, ".", &vol);
+        ad_ls_r(".", &vol);
+        closevol(&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;
+
+            openvol(obj, argv[optind], &vol);
+            ad_ls_r(argv[optind], &vol);
+            closevol(&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;
+
+            openvol(obj, argv[optind], &vol);
+            ad_ls_r(argv[optind], &vol);
+            closevol(&vol);
+
+        next2:
+            optind++;
+        }
+
+
+    }
+
+    return 0;
+}