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