]> arthur.barton.de Git - netatalk.git/blob - bin/ad/ad_find.c
Redesign ad_open API to only use one arg for all flags, fix locking for adouble:v2
[netatalk.git] / bin / ad / ad_find.c
1 /* 
2    Copyright (c) 2010 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
28 #include <atalk/adouble.h>
29 #include <atalk/cnid.h>
30 #include <atalk/cnid_dbd_private.h>
31 #include <atalk/volinfo.h>
32 #include <atalk/bstrlib.h>
33 #include <atalk/bstradd.h>
34 #include <atalk/directory.h>
35 #include <atalk/util.h>
36 #include <atalk/unicode.h>
37 #include "ad.h"
38
39 static volatile sig_atomic_t alarmed;
40
41 /*
42   SIGNAL handling:
43   catch SIGINT and SIGTERM which cause clean exit. Ignore anything else.
44 */
45
46 static void sig_handler(int signo)
47 {
48     alarmed = 1;
49     return;
50 }
51
52 static void set_signal(void)
53 {
54     struct sigaction sv;
55
56     sv.sa_handler = sig_handler;
57     sv.sa_flags = SA_RESTART;
58     sigemptyset(&sv.sa_mask);
59     if (sigaction(SIGTERM, &sv, NULL) < 0)
60         ERROR("error in sigaction(SIGTERM): %s", strerror(errno));
61
62     if (sigaction(SIGINT, &sv, NULL) < 0)
63         ERROR("error in sigaction(SIGINT): %s", strerror(errno));
64
65     memset(&sv, 0, sizeof(struct sigaction));
66     sv.sa_handler = SIG_IGN;
67     sigemptyset(&sv.sa_mask);
68
69     if (sigaction(SIGABRT, &sv, NULL) < 0)
70         ERROR("error in sigaction(SIGABRT): %s", strerror(errno));
71
72     if (sigaction(SIGHUP, &sv, NULL) < 0)
73         ERROR("error in sigaction(SIGHUP): %s", strerror(errno));
74
75     if (sigaction(SIGQUIT, &sv, NULL) < 0)
76         ERROR("error in sigaction(SIGQUIT): %s", strerror(errno));
77 }
78
79 static void usage_find(void)
80 {
81     printf(
82         "Usage: ad find [-v VOLUME_PATH] NAME\n"
83         );
84 }
85
86 int ad_find(int argc, char **argv)
87 {
88     int c, ret;
89     afpvol_t vol;
90     const char *srchvol = getcwdpath();
91
92     while ((c = getopt(argc-1, &argv[1], ":v:")) != -1) {
93         switch(c) {
94         case 'v':
95             srchvol = strdup(optarg);
96             break;
97         case ':':
98         case '?':
99             usage_find();
100             return -1;
101             break;
102         }
103
104     }
105     optind++;
106
107     if ((argc - optind) != 1) {
108         usage_find();
109         exit(1);
110     }
111
112     set_signal();
113     cnid_init();
114
115     if (openvol(srchvol, &vol) != 0)
116         ERROR("Cant open volume \"%s\"", srchvol);
117
118     uint16_t flags = CONV_TOLOWER;
119     char namebuf[MAXPATHLEN + 1];
120     if (convert_charset(vol.volinfo.v_volcharset,
121                         vol.volinfo.v_volcharset,
122                         vol.volinfo.v_maccharset,
123                         argv[optind],
124                         strlen(argv[optind]),
125                         namebuf,
126                         MAXPATHLEN,
127                         &flags) == (size_t)-1) {
128         ERROR("conversion error");
129     }
130
131     int count;
132     char resbuf[DBD_MAX_SRCH_RSLTS * sizeof(cnid_t)];
133     if ((count = cnid_find(vol.volume.v_cdb,
134                            namebuf,
135                            strlen(namebuf),
136                            resbuf,
137                            sizeof(resbuf))) < 1) {
138         ret = 1;
139     } else {
140         ret = 0;
141         cnid_t cnid;
142         char *bufp = resbuf;
143         bstring sep = bfromcstr("/");
144         while (count--) {
145             memcpy(&cnid, bufp, sizeof(cnid_t));
146             bufp += sizeof(cnid_t);
147
148             bstring path = NULL;
149             bstring volpath = bfromcstr(vol.volinfo.v_path);
150             BSTRING_STRIP_SLASH(volpath);
151             char buffer[12 + MAXPATHLEN + 1];
152             int buflen = 12 + MAXPATHLEN + 1;
153             char *name;
154             cnid_t did = cnid;
155             struct bstrList *pathlist = bstrListCreateMin(32);
156
157             while (did != DIRDID_ROOT) {
158                 if ((name = cnid_resolve(vol.volume.v_cdb, &did, buffer, buflen)) == NULL)
159                     goto next;
160                 bstrListPush(pathlist, bfromcstr(name));
161             }
162             bstrListPush(pathlist, volpath);
163             path = bjoinInv(pathlist, sep);
164             
165             printf("%s\n", cfrombstr(path));
166
167         next:
168             bstrListDestroy(pathlist);
169             bdestroy(path);
170         }
171         bdestroy(sep);
172     }
173
174     closevol(&vol);
175
176     return ret;
177 }