]> arthur.barton.de Git - netatalk.git/blob - bin/ad/ad_set.c
Support for using $u username variable in AFP volume definitions
[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 const char *labels[] = {
44     "none",
45     "grey",
46     "green",
47     "violet",
48     "blue",
49     "yellow",
50     "red",
51     "orange",
52     NULL
53 };
54
55 static char *new_label;
56 static char *new_type;
57 static char *new_creator;
58 static char *new_flags;
59 static char *new_attributes;
60
61 static void usage_set(void)
62 {
63     printf(
64         "Usage: ad set [-t TYPE] [-c CREATOR] [-l label] [-f flags] [-a attributes] file|dir \n\n"
65         "     Color Label:\n"
66         "       none | grey | green | violet | blue | yellow | red | orange\n\n"
67         "     FinderFlags:\n"
68         "       d = On Desktop (f/d)\n"
69         "       e = Hidden extension (f/d)\n"
70         "       m = Shared (can run multiple times) (f)\n"
71         "       n = No INIT resources (f)\n"
72         "       i = Inited (f/d)\n"
73         "       c = Custom icon (f/d)\n"
74         "       t = Stationery (f)\n"
75         "       s = Name locked (f/d)\n"
76         "       b = Bundle (f/d)\n"
77         "       v = Invisible (f/d)\n"
78         "       a = Alias file (f/d)\n\n"
79         "     AFPAttributes:\n"
80         "       y = System (f/d)\n"
81         "       w = No write (f)\n"
82         "       p = Needs backup (f/d)\n"
83         "       r = No rename (f/d)\n"
84         "       l = No delete (f/d)\n"
85         "       o = No copy (f)\n\n"
86         "     Uppercase letter sets the flag, lowercase removes the flag\n"
87         "     f = valid for files\n"
88         "     d = valid for directories\n"
89
90         );
91 }
92
93 static void change_type(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_type)
94 {
95     char *FinderInfo;
96
97     if ((FinderInfo = ad_entry(ad, ADEID_FINDERI)))
98         memcpy(FinderInfo, new_type, 4);
99 }
100
101 static void change_creator(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_creator)
102 {
103     char *FinderInfo;
104
105     if ((FinderInfo = ad_entry(ad, ADEID_FINDERI)))
106         memcpy(FinderInfo + 4, new_creator, 4);
107
108 }
109
110 static void change_label(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_label)
111 {
112     char *FinderInfo;
113     const char **color = &labels[0];
114     uint16_t FinderFlags;
115     unsigned char color_count = 0;
116
117     if ((FinderInfo = ad_entry(ad, ADEID_FINDERI)) == NULL)
118         return;
119
120     while (*color) {
121         if (strcasecmp(*color, new_label) == 0) {
122             /* get flags */
123             memcpy(&FinderFlags, FinderInfo + 8, 2);
124             FinderFlags = ntohs(FinderFlags);
125
126             /* change value */
127             FinderFlags &= ~FINDERINFO_COLOR;
128             FinderFlags |= color_count << 1;
129
130             /* copy it back */
131             FinderFlags = ntohs(FinderFlags);
132             memcpy(FinderInfo + 8, &FinderFlags, 2);
133
134             break;
135         }
136         color++;
137         color_count++;
138     }
139 }
140
141 static void change_attributes(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_attributes)
142 {
143     uint16_t AFPattributes;
144
145     ad_getattr(ad, &AFPattributes);
146     AFPattributes = ntohs(AFPattributes);
147
148     if (S_ISREG(st->st_mode)) {
149         if (strchr(new_attributes, 'W'))
150             AFPattributes |= ATTRBIT_NOWRITE;
151         if (strchr(new_attributes, 'w'))
152             AFPattributes &= ~ATTRBIT_NOWRITE;
153
154         if (strchr(new_attributes, 'O'))
155             AFPattributes |= ATTRBIT_NOCOPY;
156         if (strchr(new_attributes, 'o'))
157             AFPattributes &= ~ATTRBIT_NOCOPY;
158     }
159
160     if (strchr(new_attributes, 'Y'))
161         AFPattributes |= ATTRBIT_SYSTEM;
162     if (strchr(new_attributes, 'y'))
163         AFPattributes &= ~ATTRBIT_SYSTEM;
164
165     if (strchr(new_attributes, 'P'))
166         AFPattributes |= ATTRBIT_BACKUP;
167     if (strchr(new_attributes, 'p'))
168         AFPattributes &= ~ATTRBIT_BACKUP;
169
170     if (strchr(new_attributes, 'R'))
171         AFPattributes |= ATTRBIT_NORENAME;
172     if (strchr(new_attributes, 'r'))
173         AFPattributes &= ~ATTRBIT_NORENAME;
174
175     if (strchr(new_attributes, 'L'))
176         AFPattributes |= ATTRBIT_NODELETE;
177     if (strchr(new_attributes, 'l'))
178         AFPattributes &= ~ATTRBIT_NODELETE;
179
180     AFPattributes = ntohs(AFPattributes);
181     ad_setattr(ad, AFPattributes);
182 }
183
184 static void change_flags(char *path, afpvol_t *vol, const struct stat *st, struct adouble *ad, char *new_flags)
185 {
186     char *FinderInfo;
187     uint16_t FinderFlags;
188
189     if ((FinderInfo = ad_entry(ad, ADEID_FINDERI)) == NULL)
190         return;
191
192     memcpy(&FinderFlags, FinderInfo + 8, 2);
193     FinderFlags = ntohs(FinderFlags);
194
195     if (S_ISREG(st->st_mode)) {
196         if (strchr(new_flags, 'M'))
197             FinderFlags |= FINDERINFO_ISHARED;
198         if (strchr(new_flags, 'm'))
199             FinderFlags &= ~FINDERINFO_ISHARED;
200
201         if (strchr(new_flags, 'N'))
202             FinderFlags |= FINDERINFO_HASNOINITS;
203         if (strchr(new_flags, 'n'))
204             FinderFlags &= ~FINDERINFO_HASNOINITS;
205
206         if (strchr(new_flags, 'T'))
207             FinderFlags |= FINDERINFO_ISSTATIONNERY;
208         if (strchr(new_flags, 't'))
209             FinderFlags &= ~FINDERINFO_ISSTATIONNERY;
210     }
211
212     if (strchr(new_flags, 'D'))
213         FinderFlags |= FINDERINFO_ISONDESK;
214     if (strchr(new_flags, 'd'))
215         FinderFlags &= ~FINDERINFO_ISONDESK;
216
217     if (strchr(new_flags, 'E'))
218         FinderFlags |= FINDERINFO_HIDEEXT;
219     if (strchr(new_flags, 'e'))
220         FinderFlags &= ~FINDERINFO_HIDEEXT;
221
222     if (strchr(new_flags, 'I'))
223         FinderFlags |= FINDERINFO_HASBEENINITED;
224     if (strchr(new_flags, 'i'))
225         FinderFlags &= ~FINDERINFO_HASBEENINITED;
226
227     if (strchr(new_flags, 'C'))
228         FinderFlags |= FINDERINFO_HASCUSTOMICON;
229     if (strchr(new_flags, 'c'))
230         FinderFlags &= ~FINDERINFO_HASCUSTOMICON;
231
232     if (strchr(new_flags, 'S'))
233         FinderFlags |= FINDERINFO_NAMELOCKED;
234     if (strchr(new_flags, 's'))
235         FinderFlags &= ~FINDERINFO_NAMELOCKED;
236
237     if (strchr(new_flags, 'B'))
238         FinderFlags |= FINDERINFO_HASBUNDLE;
239     if (strchr(new_flags, 'b'))
240         FinderFlags &= ~FINDERINFO_HASBUNDLE;
241
242     if (strchr(new_flags, 'V'))
243         FinderFlags |= FINDERINFO_INVISIBLE;
244     if (strchr(new_flags, 'v'))
245         FinderFlags &= ~FINDERINFO_INVISIBLE;
246
247     if (strchr(new_flags, 'A'))
248         FinderFlags |= FINDERINFO_ISALIAS;
249     if (strchr(new_flags, 'a'))
250         FinderFlags &= ~FINDERINFO_ISALIAS;
251
252     FinderFlags = ntohs(FinderFlags);
253     memcpy(FinderInfo + 8, &FinderFlags, 2);
254 }
255
256 int ad_set(int argc, char **argv, AFPObj *obj)
257 {
258     int c;
259     afpvol_t vol;
260     struct stat st;
261     int adflags = 0;
262     struct adouble ad;
263
264     while ((c = getopt(argc, argv, ":l:t:c:f:a:")) != -1) {
265         switch(c) {
266         case 'l':
267             new_label = strdup(optarg);
268             break;
269         case 't':
270             new_type = strdup(optarg);
271             break;
272         case 'c':
273             new_creator = strdup(optarg);
274             break;
275         case 'f':
276             new_flags = strdup(optarg);
277             break;
278         case 'a':
279             new_attributes = strdup(optarg);
280             break;
281         case ':':
282         case '?':
283             usage_set();
284             return -1;
285             break;
286         }
287
288     }
289
290     if (argc <= optind)
291         exit(1);
292
293     cnid_init();
294
295     openvol(obj, argv[optind], &vol);
296     if (vol.vol->v_path == NULL)
297         exit(1);
298
299     if (stat(argv[optind], &st) != 0) {
300         perror("stat");
301         exit(1);
302     }
303
304     if (S_ISDIR(st.st_mode))
305         adflags = ADFLAGS_DIR;
306
307     ad_init(&ad, vol.vol);
308
309     if (ad_open(&ad, argv[optind], adflags | ADFLAGS_HF | ADFLAGS_CREATE | ADFLAGS_RDWR, 0666) < 0)
310         goto exit;
311
312     if (new_label)
313         change_label(argv[optind], &vol, &st, &ad, new_label);
314     if (new_type)
315         change_type(argv[optind], &vol, &st, &ad, new_type);
316     if (new_creator)
317         change_creator(argv[optind], &vol, &st, &ad, new_creator);
318     if (new_flags)
319         change_flags(argv[optind], &vol, &st, &ad, new_flags);
320     if (new_attributes)
321         change_attributes(argv[optind], &vol, &st, &ad, new_attributes);
322
323     ad_flush(&ad);
324     ad_close(&ad, ADFLAGS_HF);
325
326 exit:
327     closevol(&vol);
328
329     return 0;
330 }