Lines 21-62
Link Here
|
21 |
static char qfile_rcsid[] = "$Id: qfile.c,v 1.29 2006/05/14 21:37:11 vapier Exp $"; |
21 |
static char qfile_rcsid[] = "$Id: qfile.c,v 1.29 2006/05/14 21:37:11 vapier Exp $"; |
22 |
#define qfile_usage(ret) usage(ret, QFILE_FLAGS, qfile_long_opts, qfile_opts_help, lookup_applet_idx("qfile")) |
22 |
#define qfile_usage(ret) usage(ret, QFILE_FLAGS, qfile_long_opts, qfile_opts_help, lookup_applet_idx("qfile")) |
23 |
|
23 |
|
24 |
void qfile(char *path, char *fullname); |
24 |
void qfile(char *path, char *base_name, char *dir_name, char *real_dir_name); |
25 |
void qfile(char *path, char *fullname) |
25 |
void qfile(char *path, char *base_name, char *dir_name, char *real_dir_name) |
26 |
{ |
26 |
{ |
27 |
FILE *fp; |
27 |
FILE *fp; |
28 |
DIR *dir; |
28 |
DIR *dir; |
29 |
struct dirent *dentry; |
29 |
struct dirent *dentry; |
30 |
char *p; |
30 |
char *p; |
31 |
size_t flen; |
31 |
char *q; |
32 |
int base = 0; |
32 |
size_t bnlen; |
33 |
char fname[_Q_PATH_MAX]; |
33 |
size_t dnlen = 0; |
|
|
34 |
size_t rdnlen = 0; |
34 |
char buf[1024]; |
35 |
char buf[1024]; |
35 |
char pkg[126]; |
36 |
char pkg[126]; |
36 |
depend_atom *atom; |
37 |
depend_atom *atom; |
37 |
|
38 |
|
38 |
strncpy(fname, fullname, sizeof(fname)); |
39 |
bnlen = strlen(base_name); |
39 |
|
40 |
if (dir_name != NULL) |
40 |
if ((fname[0] == '.') && ((p = getenv("PWD")) != NULL)) { |
41 |
dnlen = strlen(dir_name); |
41 |
char tmp[_Q_PATH_MAX]; |
42 |
if (real_dir_name != NULL) |
42 |
snprintf(tmp, sizeof(fname), "%s/%s", p, fullname); |
43 |
rdnlen = strlen(real_dir_name); |
43 |
/* Don't check the return value here as it is ok if |
|
|
44 |
* the function fails. Think of the case where fname |
45 |
* is '...somefile', we don't want to abort then as |
46 |
* the value in fname will be unchanged. */ |
47 |
realpath(tmp, fname); |
48 |
} |
49 |
|
50 |
flen = strlen(fname); |
51 |
|
44 |
|
52 |
if (chdir(path) != 0 || (dir = opendir(".")) == NULL) |
45 |
if (chdir(path) != 0 || (dir = opendir(".")) == NULL) |
53 |
return; |
46 |
return; |
54 |
|
47 |
|
55 |
if (!strchr(fname, '/')) |
|
|
56 |
base = 1; |
57 |
else |
58 |
base = 0; |
59 |
|
60 |
while ((dentry = readdir(dir))) { |
48 |
while ((dentry = readdir(dir))) { |
61 |
if (dentry->d_name[0] == '.') |
49 |
if (dentry->d_name[0] == '.') |
62 |
continue; |
50 |
continue; |
Lines 70-89
Link Here
|
70 |
snprintf(pkg, sizeof(pkg), "%s/%s", basename(path), dentry->d_name); |
58 |
snprintf(pkg, sizeof(pkg), "%s/%s", basename(path), dentry->d_name); |
71 |
while ((fgets(buf, sizeof(buf), fp)) != NULL) { |
59 |
while ((fgets(buf, sizeof(buf), fp)) != NULL) { |
72 |
contents_entry *e; |
60 |
contents_entry *e; |
|
|
61 |
int path_ok = 0; |
62 |
if (dir_name == NULL && real_dir_name == NULL) |
63 |
path_ok = 1; |
73 |
|
64 |
|
74 |
e = contents_parse_line(buf); |
65 |
e = contents_parse_line(buf); |
75 |
if (!e) |
66 |
if (!e) |
76 |
continue; |
67 |
continue; |
77 |
|
68 |
|
78 |
p = xstrdup(e->name); |
69 |
p = xstrdup(e->name); |
79 |
if (strncmp(base ? basename(p) : p, fname, flen) != 0 |
70 |
q = basename(p); |
80 |
|| strlen(base ? basename(p) : p) != flen) { |
71 |
if (strncmp(q, base_name, bnlen) != 0 |
|
|
72 |
|| strlen(q) != bnlen) { |
81 |
free(p); |
73 |
free(p); |
82 |
continue; |
74 |
continue; |
83 |
} |
75 |
} |
|
|
76 |
free(p); |
77 |
|
78 |
if (!path_ok) { |
79 |
// check the full filepath... |
80 |
p = xstrdup(e->name); |
81 |
q = xstrdup(dirname(p)); |
82 |
free(p); |
83 |
if (dnlen == strlen(q) |
84 |
&& strncmp(q, dir_name, dnlen) == 0) |
85 |
// dir_name == dirname(CONTENTS) |
86 |
path_ok = 1; |
87 |
else if (rdnlen == strlen(q) |
88 |
&& strncmp(q, real_dir_name, rdnlen) == 0) |
89 |
// real_dir_name == dirname(CONTENTS) |
90 |
path_ok = 1; |
91 |
else { |
92 |
char rpath[_Q_PATH_MAX]; |
93 |
errno = 0; |
94 |
realpath(q, rpath); |
95 |
if (errno != 0) { |
96 |
if (verbose) { |
97 |
warn("Could not read real path of \"%s\": %s", q, strerror(errno)); |
98 |
warn("We'll never know whether it was a result for your query..."); |
99 |
} |
100 |
} else if (dnlen == strlen(rpath) |
101 |
&& strncmp(rpath, dir_name, dnlen) == 0) |
102 |
// dir_name == realpath(dirname(CONTENTS)) |
103 |
path_ok = 1; |
104 |
else if (rdnlen == strlen(rpath) |
105 |
&& strncmp(rpath, real_dir_name, rdnlen) == 0) |
106 |
// real_dir_name == realpath(dirname(CONTENTS)) |
107 |
path_ok = 1; |
108 |
} |
109 |
free(q); |
110 |
} |
111 |
if (!path_ok) |
112 |
continue; |
113 |
|
84 |
if ((atom = atom_explode(pkg)) == NULL) { |
114 |
if ((atom = atom_explode(pkg)) == NULL) { |
85 |
warn("invalid atom %s", pkg); |
115 |
warn("invalid atom %s", pkg); |
86 |
free(p); |
|
|
87 |
continue; |
116 |
continue; |
88 |
} |
117 |
} |
89 |
printf("%s%s/%s%s%s", BOLD, atom->CATEGORY, BLUE, |
118 |
printf("%s%s/%s%s%s", BOLD, atom->CATEGORY, BLUE, |
Lines 92-101
Link Here
|
92 |
if (quiet) |
121 |
if (quiet) |
93 |
puts(""); |
122 |
puts(""); |
94 |
else |
123 |
else |
95 |
printf(" (%s)\n", p); |
124 |
printf(" (%s)\n", e->name); |
96 |
|
125 |
|
97 |
atom_implode(atom); |
126 |
atom_implode(atom); |
98 |
free(p); |
|
|
99 |
found++; |
127 |
found++; |
100 |
} |
128 |
} |
101 |
fclose(fp); |
129 |
fclose(fp); |
Lines 110-115
Link Here
|
110 |
struct dirent *dentry; |
138 |
struct dirent *dentry; |
111 |
int i; |
139 |
int i; |
112 |
char *p; |
140 |
char *p; |
|
|
141 |
char ** basenames; |
142 |
char ** dirnames; |
143 |
char ** realdirnames; |
144 |
char * pwd; |
113 |
|
145 |
|
114 |
DBG("argc=%d argv[0]=%s argv[1]=%s", |
146 |
DBG("argc=%d argv[0]=%s argv[1]=%s", |
115 |
argc, argv[0], argc > 1 ? argv[1] : "NULL?"); |
147 |
argc, argv[0], argc > 1 ? argv[1] : "NULL?"); |
Lines 130-150
Link Here
|
130 |
if (chdir(portvdb) != 0 || (dir = opendir(".")) == NULL) |
162 |
if (chdir(portvdb) != 0 || (dir = opendir(".")) == NULL) |
131 |
return EXIT_FAILURE; |
163 |
return EXIT_FAILURE; |
132 |
|
164 |
|
133 |
/* CONTENTS stores dir names w/out trailing / so clean up input */ |
165 |
// For each argument, we store its basename, its dirname, |
134 |
for (i = optind; i < argc; ++i) { |
166 |
// and the realpath of its dirname. |
135 |
p = argv[i] + strlen(argv[i]) - 1; |
167 |
basenames = malloc((argc-optind) * sizeof(char*)); |
136 |
if (*p == '/') |
168 |
dirnames = malloc((argc-optind) * sizeof(char*)); |
137 |
*p = '\0'; |
169 |
realdirnames = malloc((argc-optind) * sizeof(char*)); |
|
|
170 |
if ((pwd = getenv("PWD")) != NULL) { |
171 |
int pwdlen = strlen(pwd); |
172 |
if ((pwdlen > 0) && (pwd[pwdlen-1] == '/')) |
173 |
pwd[pwdlen-1] = '\0'; |
174 |
} |
175 |
for (i = 0; i < (argc-optind); ++i) { |
176 |
char tmppath[_Q_PATH_MAX]; |
177 |
char abspath[_Q_PATH_MAX]; |
178 |
|
179 |
basenames[i] = NULL; |
180 |
dirnames[i] = NULL; |
181 |
realdirnames[i] = NULL; |
182 |
|
183 |
// Record basename, but if it is "." or ".." |
184 |
strncpy(tmppath, basename(argv[i+optind]), _Q_PATH_MAX); |
185 |
if ((strlen(tmppath) > 2) || strncmp(tmppath, "..", strlen(tmppath))) { |
186 |
basenames[i] = xstrdup(tmppath); |
187 |
// If there is no "/" in the argument, then it's over. |
188 |
// (we are searching a simple file name) |
189 |
if (strchr(argv[i+optind], '/') == NULL) |
190 |
continue; |
191 |
} |
192 |
|
193 |
// Make sure we have an absolute path available |
194 |
if (argv[i+optind][0] == '/') |
195 |
strncpy(abspath, argv[i+optind], _Q_PATH_MAX); |
196 |
else if (pwd != NULL) |
197 |
snprintf(abspath, _Q_PATH_MAX, "%s/%s", pwd, argv[i+optind]); |
198 |
else { |
199 |
err("$PWD not found in environment."); |
200 |
err("Skipping query item \"%s\".", argv[i+optind]); |
201 |
continue; |
202 |
} |
203 |
|
204 |
if (basenames[i] != NULL) { |
205 |
// Get both the dirname and its realpath |
206 |
dirnames[i] = xstrdup(dirname(abspath)); |
207 |
errno = 0; |
208 |
realpath(dirnames[i], tmppath); |
209 |
if (errno != 0) { |
210 |
if (verbose) { |
211 |
warn("Could not read real path of \"%s\": %s", dirnames[i], strerror(errno)); |
212 |
warn("Results for query item \"%s\" may not be accurate.", argv[i+optind]); |
213 |
} |
214 |
} else if (strcmp(dirnames[i], tmppath)) |
215 |
realdirnames[i] = xstrdup(tmppath); |
216 |
} else { |
217 |
// No basename means we are looking for something like "/foo/bar/.." |
218 |
// Dirname is meaningless here, we can only get realpath of the full |
219 |
// path and then split it. |
220 |
errno = 0; |
221 |
realpath(tmppath, abspath); |
222 |
if (errno != 0) { |
223 |
err("Could not read real path of \"%s\": %s", tmppath, strerror(errno)); |
224 |
err("Skipping query item \"%s\".", argv[i+optind]); |
225 |
continue; |
226 |
} |
227 |
basenames[i] = xstrdup(basename(tmppath)); |
228 |
realdirnames[i] = xstrdup(dirname(tmppath)); |
229 |
} |
138 |
} |
230 |
} |
139 |
|
231 |
|
140 |
/* open /var/db/pkg */ |
232 |
/* open /var/db/pkg */ |
141 |
while ((dentry = q_vdb_get_next_dir(dir))) { |
233 |
while ((dentry = q_vdb_get_next_dir(dir))) { |
142 |
xasprintf(&p, "%s%s/%s", portroot, portvdb, dentry->d_name); |
234 |
xasprintf(&p, "%s%s/%s", portroot, portvdb, dentry->d_name); |
143 |
for (i = optind; i < argc; ++i) |
235 |
for (i = 0; i < (argc-optind); ++i) { |
144 |
qfile(p, argv[i]); |
236 |
if (basenames[i] != NULL) |
|
|
237 |
qfile(p, basenames[i], dirnames[i], realdirnames[i]); |
238 |
} |
145 |
free(p); |
239 |
free(p); |
146 |
} |
240 |
} |
147 |
|
241 |
|
|
|
242 |
for (i = 0; i < (argc-optind); ++i) { |
243 |
if (basenames[i] != NULL) free(basenames[i]); |
244 |
if (dirnames[i] != NULL) free(dirnames[i]); |
245 |
if (realdirnames[i] != NULL) free(realdirnames[i]); |
246 |
} |
247 |
free(basenames); free(dirnames); free(realdirnames); |
248 |
|
148 |
return (found ? EXIT_SUCCESS : EXIT_FAILURE); |
249 |
return (found ? EXIT_SUCCESS : EXIT_FAILURE); |
149 |
} |
250 |
} |
150 |
|
251 |
|