Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 142217 | Differences between
and this patch

Collapse All | Expand All

(-)qfile.c.orig (-54 / +169 lines)
Lines 9-30 Link Here
9
9
10
#ifdef APPLET_qfile
10
#ifdef APPLET_qfile
11
11
12
#define QFILE_FLAGS "eo" COMMON_FLAGS
12
#define QFILE_FLAGS "eoR" COMMON_FLAGS
13
static struct option const qfile_long_opts[] = {
13
static struct option const qfile_long_opts[] = {
14
	{"exact",       no_argument, NULL, 'e'},
14
	{"exact",       no_argument, NULL, 'e'},
15
	{"orphans",     no_argument, NULL, 'o'},
15
	{"orphans",     no_argument, NULL, 'o'},
16
	{"root-prefix", no_argument, NULL, 'R'},
16
	COMMON_LONG_OPTS
17
	COMMON_LONG_OPTS
17
};
18
};
18
static const char *qfile_opts_help[] = {
19
static const char *qfile_opts_help[] = {
19
	"Exact match",
20
	"Exact match",
20
	"List orphan files",
21
	"List orphan files",
22
	"Assume arguments are already prefixed by $ROOT",
21
	COMMON_OPTS_HELP
23
	COMMON_OPTS_HELP
22
};
24
};
23
static char qfile_rcsid[] = "$Id: qfile.c,v 1.34 2006/07/19 16:20:41 solar Exp $";
25
static char qfile_rcsid[] = "$Id: qfile.c,v 1.34 2006/07/19 16:20:41 solar Exp $";
24
#define qfile_usage(ret) usage(ret, QFILE_FLAGS, qfile_long_opts, qfile_opts_help, lookup_applet_idx("qfile"))
26
#define qfile_usage(ret) usage(ret, QFILE_FLAGS, qfile_long_opts, qfile_opts_help, lookup_applet_idx("qfile"))
25
27
26
void qfile(char *path, int argc, char **base_names, char **dir_names, char **real_dir_names, short * non_orphans);
28
static inline short qfile_is_prefix(const char* path, const char* prefix, int prefix_length) {
27
void qfile(char *path, int argc, char **base_names, char **dir_names, char **real_dir_names, short * non_orphans)
29
	return !prefix_length 
30
		|| (strlen(path) >= prefix_length
31
			&& (path[prefix_length] == '/' || path[prefix_length] == '\0')
32
			&& !strncmp(path, prefix, prefix_length));
33
}
34
35
void qfile(char *path, int argc, char* root, char* real_root, char* bn_firstchars,
36
		char **base_names, char **dir_names, char **real_dir_names, short * non_orphans);
37
void qfile(char *path, int argc, char* root, char* real_root, char* bn_firstchars,
38
		char **base_names, char **dir_names, char **real_dir_names, short * non_orphans)
28
{
39
{
29
	FILE *fp;
40
	FILE *fp;
30
	DIR *dir;
41
	DIR *dir;
Lines 36-41 Link Here
36
	char pkg[126];
47
	char pkg[126];
37
	depend_atom *atom;
48
	depend_atom *atom;
38
	int i, path_ok;
49
	int i, path_ok;
50
	char bn_firstchar;
39
51
40
	if (chdir(path) != 0 || (dir = opendir(".")) == NULL)
52
	if (chdir(path) != 0 || (dir = opendir(".")) == NULL)
41
		return;
53
		return;
Lines 62-67 Link Here
62
				continue;
74
				continue;
63
			entry_basename++;
75
			entry_basename++;
64
76
77
			// used to cut the number of strcmp() calls
78
			bn_firstchar = entry_basename[0];
79
			
65
			for(i = 0; i < argc; i++) {
80
			for(i = 0; i < argc; i++) {
66
				if (base_names[i] == NULL)
81
				if (base_names[i] == NULL)
67
					continue;
82
					continue;
Lines 69-75 Link Here
69
					continue;
84
					continue;
70
				path_ok = (dir_names[i] == NULL && real_dir_names[i] == NULL);
85
				path_ok = (dir_names[i] == NULL && real_dir_names[i] == NULL);
71
86
72
				if (strcmp(entry_basename, base_names[i]) != 0)
87
				if (bn_firstchar != bn_firstchars[i]
88
						|| strcmp(entry_basename, base_names[i]))
73
					continue;
89
					continue;
74
90
75
				if (!path_ok) {
91
				if (!path_ok) {
Lines 93-114 Link Here
93
						// real_dir_name == dirname(CONTENTS)
109
						// real_dir_name == dirname(CONTENTS)
94
						path_ok = 1;
110
						path_ok = 1;
95
					else {
111
					else {
96
						char rpath[_Q_PATH_MAX];
112
						char rpath[_Q_PATH_MAX+1];
113
						char * fullpath = entry_dirname;
97
						errno = 0;
114
						errno = 0;
98
						realpath(entry_dirname, rpath);
115
						if (real_root != NULL && real_root[0] != '\0')
116
							xasprintf(&fullpath, "%s%s", real_root, entry_dirname);
117
						realpath(fullpath, rpath);
99
						if (errno != 0) {
118
						if (errno != 0) {
100
							if (verbose) {
119
							if (verbose) {
101
								warn("Could not read real path of \"%s\": %s", p, strerror(errno));
120
								warn("Could not read real path of \"%s\" (from %s): %s", 
102
								warn("We'll never know whether it was a result for your query...");
121
										fullpath, pkg, strerror(errno));
122
								warn("We'll never know whether \"%s/%s\" was a result for your query...", 
123
										entry_dirname, entry_basename);
103
							}
124
							}
125
						} else if (!qfile_is_prefix(rpath, real_root, strlen(real_root))) {
126
							if (verbose)
127
								warn("Real path of \"%s\" is not under ROOT: %s", fullpath, rpath);
104
						} else if (dir_names[i] != NULL && 
128
						} else if (dir_names[i] != NULL && 
105
								strcmp(rpath, dir_names[i]) == 0)
129
								strcmp(rpath + strlen(real_root), dir_names[i]) == 0)
106
							// dir_name == realpath(dirname(CONTENTS))
130
							// dir_name == realpath(dirname(CONTENTS))
107
							path_ok = 1;
131
							path_ok = 1;
108
						else if (real_dir_names[i] != NULL && 
132
						else if (real_dir_names[i] != NULL && 
109
								strcmp(rpath, real_dir_names[i]) == 0)
133
								strcmp(rpath + strlen(real_root), real_dir_names[i]) == 0)
110
							// real_dir_name == realpath(dirname(CONTENTS))
134
							// real_dir_name == realpath(dirname(CONTENTS))
111
							path_ok = 1;
135
							path_ok = 1;
136
						if (fullpath != entry_dirname)
137
							free(fullpath);
112
					}
138
					}
113
					free(entry_dirname);
139
					free(entry_dirname);
114
				}
140
				}
Lines 125-130 Link Here
125
						(exact ? dentry->d_name : atom->PN), NORM);
151
						(exact ? dentry->d_name : atom->PN), NORM);
126
					if (quiet)
152
					if (quiet)
127
						puts("");
153
						puts("");
154
					else if (root != NULL)
155
						printf(" (%s%s)\n", root, e->name);
128
					else
156
					else
129
						printf(" (%s)\n", e->name);
157
						printf(" (%s)\n", e->name);
130
	
158
	
Lines 146-159 Link Here
146
{
174
{
147
	DIR *dir;
175
	DIR *dir;
148
	struct dirent *dentry;
176
	struct dirent *dentry;
149
	int i;
177
	int i, nb_of_queries;
150
	char *p;
178
	char *p;
151
	char ** basenames;
179
	char ** basenames;
152
	char ** dirnames;
180
	char ** dirnames;
153
	char ** realdirnames;
181
	char ** realdirnames;
154
	char * pwd;
182
	char * basenames_firstchars;
183
	char * pwd = NULL;
155
	short * non_orphans = NULL;
184
	short * non_orphans = NULL;
156
	short search_orphans = 0;
185
	short search_orphans = 0;
186
	short assume_root_prefix = 0;
187
	char * root_prefix;
188
	char * real_root;
189
	int real_root_length;
190
	char tmppath[_Q_PATH_MAX+1];
191
	char abspath[_Q_PATH_MAX+1];
157
192
158
	DBG("argc=%d argv[0]=%s argv[1]=%s",
193
	DBG("argc=%d argv[0]=%s argv[1]=%s",
159
	    argc, argv[0], argc > 1 ? argv[1] : "NULL?");
194
	    argc, argv[0], argc > 1 ? argv[1] : "NULL?");
Lines 163-254 Link Here
163
			COMMON_GETOPTS_CASES(qfile)
198
			COMMON_GETOPTS_CASES(qfile)
164
			case 'e': exact = 1; break;
199
			case 'e': exact = 1; break;
165
			case 'o': search_orphans = 1; break;
200
			case 'o': search_orphans = 1; break;
201
			case 'R': assume_root_prefix = 1; break;
166
		}
202
		}
167
	}
203
	}
168
	if (!exact && verbose) exact++;
204
	if (!exact && verbose) exact++;
169
	if (argc == optind)
205
	if (argc == optind)
170
		qfile_usage(EXIT_FAILURE);
206
		qfile_usage(EXIT_FAILURE);
207
	nb_of_queries = argc - optind;
171
208
172
	if (chdir(portroot))
209
	if (chdir(portroot))
173
		errp("could not chdir(%s) for ROOT", portroot);
210
		errp("could not chdir(%s) for ROOT", portroot);
174
211
175
	if (chdir(portvdb) != 0 || (dir = opendir(".")) == NULL)
212
	if (chdir(portvdb) != 0 || (dir = opendir(".")) == NULL)
176
		return EXIT_FAILURE;
213
		errp("could not chdir(ROOT/%s) for installed packages database", portvdb);
177
178
	if (search_orphans)
179
		non_orphans = xmalloc((argc-optind) * sizeof(short));
180
214
181
	// For each argument, we store its basename, its dirname,
215
	// Try to get $PWD.  Must be absolute, with no trailing slash
182
	// and the realpath of its dirname.
216
	if ((pwd = getenv("PWD")) != NULL && pwd[0] == '/') {
217
		pwd = xstrdup(pwd);
218
		if ((pwd[strlen(pwd) - 1] == '/'))
219
			pwd[strlen(pwd) - 1] = '\0';
220
	} else
221
		pwd = NULL;
222
223
	// Get realpath of $ROOT, with no trailing slash
224
	if (portroot[0] == '/')
225
		strncpy(tmppath, portroot, _Q_PATH_MAX);
226
	else if (pwd != NULL)
227
		snprintf(tmppath, _Q_PATH_MAX, "%s/%s", pwd, portroot);
228
	else {
229
		free(pwd);
230
		errp("Could not get absolute path for ROOT (\"%s\"), because of missing or not absolute $PWD", tmppath);
231
	}
232
	errno = 0;
233
	realpath(tmppath, abspath);
234
	if (errno != 0) {
235
		free(pwd);
236
		errp("Could not read real path of ROOT (\"%s\"): %s", tmppath, strerror(errno));
237
	}
238
	if (strlen(abspath) == 1)
239
		abspath[0] = '\0';
240
	real_root = xstrdup(abspath);
241
	real_root_length = strlen(real_root);
242
243
	// Get a copy of $ROOT, with no trailing slash
244
	// (this one is just for qfile(...) output)
245
	root_prefix = xstrdup(portroot);
246
	if (root_prefix[strlen(root_prefix) - 1] == '/')
247
		root_prefix[strlen(root_prefix) - 1] = '\0';
248
249
	// For each argument, we store its basename, its absolute dirname,
250
	// and the realpath of its dirname.  Dirnames and their realpaths
251
	// are stored without their $ROOT prefix, but $ROOT is used when
252
	// checking realpaths.
183
	basenames = xmalloc((argc-optind) * sizeof(char*));
253
	basenames = xmalloc((argc-optind) * sizeof(char*));
184
	dirnames = xmalloc((argc-optind) * sizeof(char*));
254
	dirnames = xmalloc((argc-optind) * sizeof(char*));
185
	realdirnames = xmalloc((argc-optind) * sizeof(char*));
255
	realdirnames = xmalloc((argc-optind) * sizeof(char*));
186
	if ((pwd = getenv("PWD")) != NULL) {
256
	// For optimization of qfile(), we also give it an array of the first char
187
		int pwdlen = strlen(pwd);
257
	// of each basename.  This way we avoid numerous strcmp() calls.
188
		if ((pwdlen > 0) && (pwd[pwdlen-1] == '/'))
258
	basenames_firstchars = xmalloc((argc-optind) * sizeof(char));
189
			pwd[pwdlen-1] = '\0';
259
	// Finally, if searching for orphans, we need an array to store the results
190
	}
260
	if (search_orphans)
261
		non_orphans = xmalloc((argc-optind) * sizeof(short));
191
	for (i = 0; i < (argc-optind); ++i) {
262
	for (i = 0; i < (argc-optind); ++i) {
192
		char tmppath[_Q_PATH_MAX];
193
		char abspath[_Q_PATH_MAX];
194
195
		basenames[i] = NULL;
263
		basenames[i] = NULL;
196
		dirnames[i] = NULL;
264
		dirnames[i] = NULL;
197
		realdirnames[i] = NULL;
265
		realdirnames[i] = NULL;
198
266
199
		// Record basename, but if it is "." or ".."
267
		// Record basename, but if it is ".", ".." or "/"
200
		strncpy(tmppath, basename(argv[i+optind]), _Q_PATH_MAX);
268
		strncpy(tmppath, basename(argv[i+optind]), _Q_PATH_MAX);
201
		if ((strlen(tmppath) > 2) || strncmp(tmppath, "..", strlen(tmppath))) {
269
		if ((strlen(tmppath) > 2) || 
270
				(strncmp(tmppath, "..", strlen(tmppath))
271
				 && strncmp(tmppath, "/", strlen(tmppath)))) {
202
			basenames[i] = xstrdup(tmppath);
272
			basenames[i] = xstrdup(tmppath);
273
			basenames_firstchars[i] = basenames[i][0];
203
			// If there is no "/" in the argument, then it's over.
274
			// If there is no "/" in the argument, then it's over.
204
			// (we are searching a simple file name)
275
			// (we are searching a simple file name)
205
			if (strchr(argv[i+optind], '/') == NULL)
276
			if (strchr(argv[i+optind], '/') == NULL)
206
				continue;
277
				continue;
207
		}
278
		}
208
279
209
		// Make sure we have an absolute path available
280
		// Make sure we have an absolute path available (with "realpath(ROOT)" prefix)
210
		if (argv[i+optind][0] == '/')
281
		if (argv[i+optind][0] == '/') {
211
			strncpy(abspath, argv[i+optind], _Q_PATH_MAX);
282
			if (assume_root_prefix)
212
		else if (pwd != NULL)
283
				strncpy(abspath, argv[i+optind], _Q_PATH_MAX);
213
			snprintf(abspath, _Q_PATH_MAX, "%s/%s", pwd, argv[i+optind]);
284
			else
214
		else {
285
				snprintf(abspath, _Q_PATH_MAX, "%s%s", real_root, argv[i+optind]);
215
			warn("$PWD not found in environment.");
286
		} else if (pwd != NULL) {
216
			warn("Skipping query item \"%s\".", argv[i+optind]);
287
			if (assume_root_prefix)
217
			continue;
288
				snprintf(abspath, _Q_PATH_MAX, "%s/%s", pwd, argv[i+optind]);
289
			else
290
				snprintf(abspath, _Q_PATH_MAX, "%s%s/%s", real_root, pwd, argv[i+optind]);
291
		} else {
292
			warn("$PWD was not found in environment, or is not an absolute path");
293
			goto skip_query_item;
218
		}
294
		}
219
295
220
		if (basenames[i] != NULL) {
296
		if (basenames[i] != NULL) {
221
			// Get both the dirname and its realpath
297
			// Get both the dirname and its realpath.  This paths will
222
			dirnames[i] = xstrdup(dirname(abspath));
298
			// have no trailing slash, but if it is the only char (ie., 
299
			// when searching for "/foobar").
300
			strncpy(tmppath, abspath, _Q_PATH_MAX);
301
			strncpy(abspath, dirname(tmppath), _Q_PATH_MAX);
302
			if (abspath[real_root_length] == '\0')
303
				strncat(abspath, "/", 1);
304
			dirnames[i] = xstrdup(abspath + real_root_length);
223
			errno = 0;
305
			errno = 0;
224
			realpath(dirnames[i], tmppath);
306
			realpath(abspath, tmppath);
225
			if (errno != 0) {
307
			if (errno != 0) {
226
				if (verbose) {
308
				if (verbose) {
227
					warn("Could not read real path of \"%s\": %s", dirnames[i], strerror(errno));
309
					warn("Could not read real path of \"%s\": %s", abspath, strerror(errno));
228
					warn("Results for query item \"%s\" may not be accurate.", argv[i+optind]);
310
					warn("Results for query item \"%s\" may be inaccurate.", argv[i+optind]);
229
				}
311
				}
230
			} else if (strcmp(dirnames[i], tmppath))
312
				continue;
231
				realdirnames[i] = xstrdup(tmppath);
313
			} 
314
			if (!qfile_is_prefix(tmppath, real_root, real_root_length)) {
315
				warn("Real path of \"%s\" is not under ROOT: %s", abspath, tmppath);
316
				goto skip_query_item;
317
			}
318
			if (tmppath[real_root_length] == '\0')
319
				strncat(tmppath, "/", 1);
320
			if (strcmp(dirnames[i], tmppath + real_root_length))
321
				realdirnames[i] = xstrdup(tmppath + real_root_length);
232
		} else {
322
		} else {
233
			// No basename means we are looking for something like "/foo/bar/.."
323
			// No basename means we are looking for something like "/foo/bar/.."
234
			// Dirname is meaningless here, we can only get realpath of the full 
324
			// Dirname is meaningless here, we can only get realpath of the full 
235
			// path and then split it.
325
			// path and then split it.
236
			errno = 0;
326
			errno = 0;
237
			realpath(tmppath, abspath);
327
			realpath(abspath, tmppath);
238
			if (errno != 0) {
328
			if (errno != 0) {
239
				warn("Could not read real path of \"%s\": %s", tmppath, strerror(errno));
329
				warn("Could not read real path of \"%s\": %s", abspath, strerror(errno));
240
				warn("Skipping query item \"%s\".", argv[i+optind]);
330
				goto skip_query_item;
241
				continue;
331
			}
332
			if (!qfile_is_prefix(tmppath, real_root, real_root_length)) {
333
				warn("Real path of \"%s\" is not under ROOT: %s", abspath, tmppath);
334
				goto skip_query_item;
242
			}
335
			}
243
			basenames[i] = xstrdup(basename(tmppath));
336
			strncpy(abspath, tmppath, _Q_PATH_MAX);
244
			realdirnames[i] = xstrdup(dirname(tmppath));
337
			basenames[i] = xstrdup(basename(abspath));
338
			basenames_firstchars[i] = basenames[i][0];
339
			strncpy(abspath, dirname(tmppath), _Q_PATH_MAX);
340
			if (tmppath[real_root_length] == '\0')
341
				strncat(tmppath, "/", 1);
342
			realdirnames[i] = xstrdup(abspath + real_root_length);
245
		}
343
		}
344
		continue;
345
346
		skip_query_item:
347
			--nb_of_queries;
348
			warn("Skipping query item \"%s\".", argv[i+optind]);
349
			if (basenames[i] != NULL) free(basenames[i]);
350
			if (dirnames[i] != NULL) free(dirnames[i]);
351
			if (realdirnames[i] != NULL) free(realdirnames[i]);
352
			basenames[i] = dirnames[i] = realdirnames[i] = NULL;
246
	}
353
	}
247
354
248
	/* open /var/db/pkg */
355
	/* open /var/db/pkg (but if all query items were skipped) */
249
	while ((dentry = q_vdb_get_next_dir(dir))) {
356
	while (nb_of_queries && (dentry = q_vdb_get_next_dir(dir))) {
250
		xasprintf(&p, "%s%s/%s", portroot, portvdb, dentry->d_name);
357
		xasprintf(&p, "%s/%s/%s", real_root, portvdb, dentry->d_name);
251
		qfile(p, (argc-optind), basenames, dirnames, realdirnames, non_orphans);
358
		qfile(p, (argc-optind), (assume_root_prefix ? root_prefix : NULL), real_root,
359
				basenames_firstchars, basenames, dirnames, realdirnames, non_orphans);
252
		free(p);
360
		free(p);
253
	}
361
	}
254
362
Lines 273-278 Link Here
273
	}
381
	}
274
	free(basenames); free(dirnames); free(realdirnames);
382
	free(basenames); free(dirnames); free(realdirnames);
275
383
384
	free(basenames_firstchars);
385
386
	if (pwd != NULL)
387
		free(pwd);
388
389
	free(real_root); free(root_prefix);
390
276
	return (found ? EXIT_SUCCESS : EXIT_FAILURE);
391
	return (found ? EXIT_SUCCESS : EXIT_FAILURE);
277
}
392
}
278
393

Return to bug 142217