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
sig_handler(int signo)45 static void sig_handler(int signo)
46 {
47 alarmed = 1;
48 return;
49 }
50
set_signal(void)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
usage_find(void)78 static void usage_find(void)
79 {
80 printf(
81 "Usage: ad find [-v VOLUME_PATH] NAME\n"
82 );
83 }
84
ad_find(int argc,char ** argv,AFPObj * obj)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 }
177