]> arthur.barton.de Git - netatalk.git/blob - bin/ad/ad_set.c
1a2cac887c189d76d20624322f6911b2d4d4adbf
[netatalk.git] / bin / ad / ad_set.c
1 /* 
2    Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
3    
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8  
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 */
14
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif /* HAVE_CONFIG_H */
18
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <limits.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <dirent.h>
28 #include <fcntl.h>
29 #include <ctype.h>
30 #include <pwd.h>
31 #include <grp.h>
32 #include <time.h>
33
34 #include <atalk/adouble.h>
35 #include <atalk/cnid.h>
36 #include "ad.h"
37
38 #define ADv2_DIRNAME ".AppleDouble"
39
40 #define DIR_DOT_OR_DOTDOT(a) \
41         ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0))
42
43 static volatile sig_atomic_t alarmed;
44
45 /* ls options */
46 static int ls_a;
47 static int ls_l;
48 static int ls_R;
49 static int ls_d;
50 static int ls_u;
51
52 /* Used for pretty printing */
53 static int first = 1;
54 static int recursion;
55
56 static char           *netatalk_dirs[] = {
57     ADv2_DIRNAME,
58     ".AppleDB",
59     ".AppleDesktop",
60     NULL
61 };
62
63 static char *labels[] = {
64     "---",
65     "gry",
66     "gre",
67     "vio",
68     "blu",
69     "yel",
70     "red",
71     "ora"
72 };
73
74 /*
75   SIGNAL handling:
76   catch SIGINT and SIGTERM which cause clean exit. Ignore anything else.
77 */
78
79 static void sig_handler(int signo)
80 {
81     alarmed = 1;
82     return;
83 }
84
85 static void set_signal(void)
86 {
87     struct sigaction sv;
88
89     sv.sa_handler = sig_handler;
90     sv.sa_flags = SA_RESTART;
91     sigemptyset(&sv.sa_mask);
92     if (sigaction(SIGTERM, &sv, NULL) < 0)
93         ERROR("error in sigaction(SIGTERM): %s", strerror(errno));
94
95     if (sigaction(SIGINT, &sv, NULL) < 0)
96         ERROR("error in sigaction(SIGINT): %s", strerror(errno));
97
98     memset(&sv, 0, sizeof(struct sigaction));
99     sv.sa_handler = SIG_IGN;
100     sigemptyset(&sv.sa_mask);
101
102     if (sigaction(SIGABRT, &sv, NULL) < 0)
103         ERROR("error in sigaction(SIGABRT): %s", strerror(errno));
104
105     if (sigaction(SIGHUP, &sv, NULL) < 0)
106         ERROR("error in sigaction(SIGHUP): %s", strerror(errno));
107
108     if (sigaction(SIGQUIT, &sv, NULL) < 0)
109         ERROR("error in sigaction(SIGQUIT): %s", strerror(errno));
110 }
111
112 /*
113   Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
114   Returns pointer to name or NULL.
115 */
116 static const char *check_netatalk_dirs(const char *name)
117 {
118     int c;
119
120     for (c=0; netatalk_dirs[c]; c++) {
121         if ((strcmp(name, netatalk_dirs[c])) == 0)
122             return netatalk_dirs[c];
123     }
124     return NULL;
125 }
126
127
128 static void usage_set(void)
129 {
130     printf(
131         "Usage: ad set file|dir [-t TYPE] [-c CREATOR] [-l label] [-f flags]\n\n"
132         "     FinderFlags (valid for (f)ile and/or (d)irectory):\n"
133         "       d = On Desktop (f/d)\n"
134         "       e = Hidden extension (f/d)\n"
135         "       m = Shared (can run multiple times) (f)\n"
136         "       n = No INIT resources (f)\n"
137         "       i = Inited (f/d)\n"
138         "       c = Custom icon (f/d)\n"
139         "       t = Stationery (f)\n"
140         "       s = Name locked (f/d)\n"
141         "       b = Bundle (f/d)\n"
142         "       v = Invisible (f/d)\n"
143         "       a = Alias file (f/d)\n\n"
144         "     AFPAttributes:\n"
145         "       y = System (f/d)\n"
146         "       w = No write (f)\n"
147         "       p = Needs backup (f/d)\n"
148         "       r = No rename (f/d)\n"
149         "       l = No delete (f/d)\n"
150         "       o = No copy (f)\n\n"
151         "     Note: any letter appearing in uppercase means the flag is set\n"
152         "           but it's a directory for which the flag is not allowed.\n"
153         );
154 }
155
156 static void print_flags(char *path, afpvol_t *vol, const struct stat *st)
157 {
158     int adflags = 0;
159     struct adouble ad;
160     char *FinderInfo;
161     uint16_t FinderFlags;
162     uint16_t AFPattributes;
163     char type[5] = "----";
164     char creator[5] = "----";
165     int i;
166     uint32_t cnid;
167
168     if (S_ISDIR(st->st_mode))
169         adflags = ADFLAGS_DIR;
170
171     if (vol->vol->v_path == NULL)
172         return;
173
174     ad_init(&ad, vol->vol);
175
176     if ( ad_metadata(path, adflags, &ad) < 0 )
177         return;
178
179     FinderInfo = ad_entry(&ad, ADEID_FINDERI);
180
181     memcpy(&FinderFlags, FinderInfo + 8, 2);
182     FinderFlags = ntohs(FinderFlags);
183
184     memcpy(type, FinderInfo, 4);
185     memcpy(creator, FinderInfo + 4, 4);
186
187     ad_getattr(&ad, &AFPattributes);
188     AFPattributes = ntohs(AFPattributes);
189
190     /*
191       Finder flags. Lowercase means valid, uppercase means invalid because
192       object is a dir and flag is only valid for files.
193     */
194     putchar(' ');
195     if (FinderFlags & FINDERINFO_ISONDESK)
196         putchar('d');
197     else
198         putchar('-');
199
200     if (FinderFlags & FINDERINFO_HIDEEXT)
201         putchar('e');
202     else
203         putchar('-');
204
205     if (FinderFlags & FINDERINFO_ISHARED) {
206         if (adflags & ADFLAGS_DIR)
207             putchar('M');
208         else
209             putchar('m');
210     } else
211         putchar('-');
212
213     if (FinderFlags & FINDERINFO_HASNOINITS) {
214         if (adflags & ADFLAGS_DIR)
215             putchar('N');
216         else
217             putchar('n');
218     } else
219         putchar('-');
220
221     if (FinderFlags & FINDERINFO_HASBEENINITED)
222         putchar('i');
223     else
224         putchar('-');
225
226     if (FinderFlags & FINDERINFO_HASCUSTOMICON)
227         putchar('c');
228     else
229         putchar('-');
230
231     if (FinderFlags & FINDERINFO_ISSTATIONNERY) {
232         if (adflags & ADFLAGS_DIR)
233             putchar('T');
234         else
235             putchar('t');
236     } else
237         putchar('-');
238
239     if (FinderFlags & FINDERINFO_NAMELOCKED)
240         putchar('s');
241     else
242         putchar('-');
243
244     if (FinderFlags & FINDERINFO_HASBUNDLE)
245         putchar('b');
246     else
247         putchar('-');
248
249     if (FinderFlags & FINDERINFO_INVISIBLE)
250         putchar('v');
251     else
252         putchar('-');
253
254     if (FinderFlags & FINDERINFO_ISALIAS)
255         putchar('a');
256     else
257         putchar('-');
258
259     putchar(' ');
260
261     /* AFP attributes */
262     if (AFPattributes & ATTRBIT_SYSTEM)
263         putchar('y');
264     else
265         putchar('-');
266
267     if (AFPattributes & ATTRBIT_NOWRITE) {
268         if (adflags & ADFLAGS_DIR)
269             putchar('W');
270         else
271             putchar('w');
272     } else
273         putchar('-');
274
275     if (AFPattributes & ATTRBIT_BACKUP)
276         putchar('p');
277     else
278         putchar('-');
279
280     if (AFPattributes & ATTRBIT_NORENAME)
281         putchar('r');
282     else
283         putchar('-');
284
285     if (AFPattributes & ATTRBIT_NODELETE)
286         putchar('l');
287     else
288         putchar('-');
289
290     if (AFPattributes & ATTRBIT_NOCOPY) {
291         if (adflags & ADFLAGS_DIR)
292             putchar('O');
293         else
294             putchar('o');                
295     } else
296         putchar('-');
297
298     /* Color */
299     printf(" %s ", labels[(FinderFlags & FINDERINFO_COLOR) >> 1]);
300
301     /* Type & Creator */
302     for(i=0; i<4; i++) {
303         if (isalnum(type[i]))
304             putchar(type[i]);
305         else
306             putchar('-');
307     }
308     putchar(' '); 
309     for(i=0; i<4; i++) {
310         if (isalnum(creator[i]))
311             putchar(creator[i]);
312         else
313             putchar('-');
314     }
315     putchar(' '); 
316
317     /* CNID */
318     cnid = ad_forcegetid(&ad);
319     if (cnid)
320         printf(" %10u ", ntohl(cnid));
321     else
322         printf(" !ADVOL_CACHE ");
323
324     ad_close(&ad, ADFLAGS_HF);
325 }
326
327 int ad_ls(int argc, char **argv, AFPObj *obj)
328 {
329     int c, firstarg;
330     afpvol_t vol;
331     struct stat st;
332
333     while ((c = getopt(argc, argv, ":adlRu")) != -1) {
334         switch(c) {
335         case 'a':
336             ls_a = 1;
337             break;
338         case 'd':
339             ls_d = 1;
340             break;
341         case 'l':
342             ls_l = 1;
343             break;
344         case 'R':
345             ls_R = 1;
346             break;
347         case 'u':
348             ls_u = 1;
349             break;
350         case ':':
351         case '?':
352             usage_ls();
353             return -1;
354             break;
355         }
356
357     }
358
359     set_signal();
360     cnid_init();
361
362     if ((argc - optind) == 0) {
363         openvol(obj, ".", &vol);
364         ad_ls_r(".", &vol);
365         closevol(&vol);
366     }
367     else {
368         int havefile = 0;
369
370         firstarg = optind;
371
372         /* First run: only print files from argv paths */
373         while(optind < argc) {
374             if (stat(argv[optind], &st) != 0)
375                 goto next;
376             if (S_ISDIR(st.st_mode))
377                 goto next;
378
379             havefile = 1;
380             first = 1;
381             recursion = 0;
382
383             openvol(obj, argv[optind], &vol);
384             ad_ls_r(argv[optind], &vol);
385             closevol(&vol);
386         next:
387             optind++;
388         }
389         if (havefile && (! ls_l))
390             printf("\n");
391
392         /* Second run: print dirs */
393         optind = firstarg;
394         while(optind < argc) {
395             if (stat(argv[optind], &st) != 0)
396                 goto next2;
397             if ( ! S_ISDIR(st.st_mode))
398                 goto next2;
399             if ((optind > firstarg) || havefile)
400                 printf("\n%s:\n", argv[optind]);
401
402             first = 1;
403             recursion = 0;
404
405             openvol(obj, argv[optind], &vol);
406             ad_ls_r(argv[optind], &vol);
407             closevol(&vol);
408
409         next2:
410             optind++;
411         }
412
413
414     }
415
416     return 0;
417 }