[PATCH] Package content search and listing functionality for cygcheck
Igor Pechtchanski
pechtcha@cs.nyu.edu
Fri Aug 15 19:38:00 GMT 2003
Corinna,
Thanks for the feedback. Replies inline below.
On Fri, 15 Aug 2003, Corinna Vinschen wrote:
> On Thu, Aug 14, 2003 at 03:30:44PM -0400, Igor Pechtchanski wrote:
> > This patch adds the functionality to cygcheck to list (using the "-l" or
> > "--list-package" flag) the contents of and search (using the "-f" or
> > "--find-package" flag and passing the absolute paths to the files) for
> > files in the *installed* packages. Please test this and feel free to give
> > feedback. I've done some refactoring of the code in dump_setup.cc as
>
> Cool, especially the -f which allows the same as `rpm -qf'. However,
> you asked for feedback... (I dropped the "Use -h to see..." from below
> examples, we should get rid of it anyway)
>
> On Cygwin:
>
> $ cygcheck -f /usr/bin/tcsh.exe
> /usr/bin/tcsh.exe: found in package tcsh-6.12.00-6
>
> On Linux:
>
> $ rpm -qf /usr/bin/tcsh
> tcsh-6.12.00-134
>
> Shouldn't we also just print the package name? It doesn't really matter,
> just a question...
Fixed.
> But we have two problems which are no problems in Linux and it would be
> nice(TM) to have a neat solution for them. Example:
>
> $ cygcheck -f /usr/bin/tcsh
> $
>
> Huh? No .exe, no package :-(
>
> $ cygcheck -f /bin/tcsh
> $
Fixed. One thing left to do is to verify that /usr/bin is indeed an alias
for /bin (and /usr/lib an alias for /lib) -- although I think plenty of
other things will break if this is not the case.
> Do you see what I mean? Since /bin and /usr/bin (same for /lib) are
> the same directory, one could ask for the same file in /bin and would
> not get the package reply. Bummer. I don't see that as a big problem
> for files in /lib but I guess you should expect that a good bunch of
> people don't get the idea to ask for the same file in /usr/bin again.
>
> Corinna
Well, I agree with all the above points, so here's another iteration.
Same ChangeLog (except for the date -- reposting just in case).
Igor
==============================================================================
ChangeLog:
2003-08-15 Igor Pechtchanski <pechtcha@cs.nyu.edu>
* cygcheck.cc (find_package,list_package): New global
variables.
(usage): Add "--find-package" and "--list-package" options,
reformat output.
(longopts, opts): Add "--find-package" and "--list-package"
options.
(main): Process the "--find-package" and "--list-package"
flags. Add new semantic checks. Add calls to find_package()
and list_package().
* dump_setup.cc: Fix header comment.
(match_argv): Change return type to int to distinguish
between real matches and default ones.
(open_package_list): New static function.
(check_package_files): Factor out opening the package list
file into open_package_list().
(get_packages): New static function.
(dump_setup): Factor out getting a list of packages into
get_packages().
(package_list, package_find): New global functions.
--
http://cs.nyu.edu/~pechtcha/
|\ _,,,---,,_ pechtcha@cs.nyu.edu
ZZZzz /,`.-'`' -. ;-;;,_ igor@watson.ibm.com
|,4- ) )-,_. ,\ ( `'-' Igor Pechtchanski, Ph.D.
'---''(_/--' `-'\_) fL a.k.a JaguaR-R-R-r-r-r-.-.-. Meow!
"I have since come to realize that being between your mentor and his route
to the bathroom is a major career booster." -- Patrick Naughton
-------------- next part --------------
Index: cygcheck.cc
===================================================================
RCS file: /cvs/src/src/winsup/utils/cygcheck.cc,v
retrieving revision 1.35
diff -u -p -r1.35 cygcheck.cc
--- cygcheck.cc 13 Jun 2003 02:36:12 -0000 1.35
+++ cygcheck.cc 15 Aug 2003 16:23:14 -0000
@@ -26,6 +26,8 @@ int sysinfo = 0;
int givehelp = 0;
int keycheck = 0;
int check_setup = 0;
+int find_package = 0;
+int list_package = 0;
#ifdef __GNUC__
typedef long long longlong;
@@ -34,6 +36,8 @@ typedef __int64 longlong;
#endif
void dump_setup (int, char **, bool);
+void package_find (int, char **);
+void package_list (int, char **);
static const char version[] = "$Revision: 1.35 $";
@@ -1317,13 +1321,15 @@ usage (FILE * stream, int status)
Usage: cygcheck [OPTIONS] [PROGRAM...]\n\
Check system information or PROGRAM library dependencies\n\
\n\
- -c, --check-setup check packages installed via setup.exe\n\
- -s, --sysinfo system information (not with -k)\n\
- -v, --verbose verbose output (indented) (for -s or programs)\n\
- -r, --registry registry search (requires -s)\n\
- -k, --keycheck perform a keyboard check session (not with -s)\n\
- -h, --help give help about the info (not with -c)\n\
- -V, --version output version information and exit\n\
+ -c, --check-setup check packages installed via setup.exe\n\
+ -s, --sysinfo system information (not with -k)\n\
+ -v, --verbose verbose output (indented) (for -s or programs)\n\
+ -r, --registry registry search (requires -s)\n\
+ -k, --keycheck perform a keyboard check session (not with -[scfl])\n\
+ -f, --find-package find installed packages containing files (not with -[cl])\n\
+ -l, --list-package list the contents of installed packages (not with -[cf])\n\
+ -h, --help give help about the info (not with -[cfl])\n\
+ -V, --version output version information and exit\n\
You must at least give either -s or -k or a program name\n");
exit (status);
}
@@ -1334,12 +1340,14 @@ struct option longopts[] = {
{"registry", no_argument, NULL, 'r'},
{"verbose", no_argument, NULL, 'v'},
{"keycheck", no_argument, NULL, 'k'},
+ {"find-package", no_argument, NULL, 'f'},
+ {"list-package", no_argument, NULL, 'l'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, 0, 'V'},
{0, no_argument, NULL, 0}
};
-static char opts[] = "chkrsvV";
+static char opts[] = "cfhklrsvV";
static void
print_version ()
@@ -1387,6 +1395,12 @@ main (int argc, char **argv)
case 'k':
keycheck = 1;
break;
+ case 'f':
+ find_package = 1;
+ break;
+ case 'l':
+ list_package = 1;
+ break;
case 'h':
givehelp = 1;
break;
@@ -1405,7 +1419,13 @@ main (int argc, char **argv)
else
usage (stderr, 1);
- if ((check_setup || sysinfo) && keycheck)
+ if ((check_setup || sysinfo || find_package || list_package) && keycheck)
+ usage (stderr, 1);
+
+ if ((find_package || list_package) && check_setup)
+ usage (stderr, 1);
+
+ if (find_package && list_package)
usage (stderr, 1);
if (keycheck)
@@ -1413,7 +1433,7 @@ main (int argc, char **argv)
init_paths ();
- /* FIXME: Add help for check_setup */
+ /* FIXME: Add help for check_setup and {list,find}_package */
if (argc >= 1 && givehelp && !check_setup)
{
if (argc == 1)
@@ -1436,6 +1456,16 @@ main (int argc, char **argv)
if (check_setup)
{
dump_setup (verbose, argv, true);
+ puts ("");
+ }
+ else if (find_package)
+ {
+ package_find (verbose, argv);
+ puts ("");
+ }
+ else if (list_package)
+ {
+ package_list (verbose, argv);
puts ("");
}
else
Index: dump_setup.cc
===================================================================
RCS file: /cvs/src/src/winsup/utils/dump_setup.cc,v
retrieving revision 1.9
diff -u -p -r1.9 dump_setup.cc
--- dump_setup.cc 13 Aug 2003 19:37:40 -0000 1.9
+++ dump_setup.cc 15 Aug 2003 16:23:14 -0000
@@ -1,4 +1,4 @@
-/* path.cc
+/* dump_setup.cc
Copyright 2001 Red Hat, Inc.
@@ -165,15 +165,15 @@ compar (const void *a, const void *b)
}
}
-bool
+int
match_argv (char **argv, const char *name)
{
if (!argv || !*argv)
- return true;
+ return -1;
for (char **a = argv; *a; a++)
if (strcasecmp (*a, name) == 0)
- return true;
- return false;
+ return a - argv + 1;
+ return 0;
}
static bool
@@ -234,17 +234,13 @@ file_exists (int verbose, char *filename
return true;
}
-static bool
-check_package_files (int verbose, char *package)
+static FILE *
+open_package_list (char *package)
{
char filelist[MAX_PATH + 1] = "etc/setup/";
strcat (strcat (filelist, package), ".lst.gz");
if (!file_exists (false, filelist, NULL, NULL))
- {
- if (verbose)
- printf ("Missing file list /%s for package %s\n", filelist, package);
- return false;
- }
+ return NULL;
static char *zcat;
static char *zcat_end;
@@ -260,6 +256,21 @@ check_package_files (int verbose, char *
strcpy (zcat_end, filelist);
FILE *fp = popen (zcat, "rt");
+ return fp;
+}
+
+static bool
+check_package_files (int verbose, char *package)
+{
+ FILE *fp = open_package_list (package);
+ if (!fp)
+ {
+ if (verbose)
+ printf ("Can't open file list /etc/setup/%s.lst.gz for package %s\n",
+ package, package);
+ return false;
+ }
+
bool result = true;
char buf[MAX_PATH + 1];
while (fgets (buf, MAX_PATH, fp))
@@ -286,25 +297,17 @@ check_package_files (int verbose, char *
return result;
}
-void
-dump_setup (int verbose, char **argv, bool check_files)
-{
+/**
+ * Returns a calloc'd sorted list of packages or NULL if no info.
+ * The last entry in the list is {NULL,NULL}.
+ */
+static pkgver *
+get_packages (char **argv) {
char *setup = cygpath ("/etc/setup/installed.db", NULL);
FILE *fp = fopen (setup, "rt");
- puts ("Cygwin Package Information");
if (fp == NULL)
- {
- puts ("No package information found");
- goto err;
- }
-
- if (verbose)
- {
- bool need_nl = dump_file ("Last downloaded files to: ", "last-cache");
- if (dump_file ("Last downloaded files from: ", "last-mirror") || need_nl)
- puts ("");
- }
+ return NULL;
int nlines;
nlines = 0;
@@ -312,12 +315,15 @@ dump_setup (int verbose, char **argv, bo
while (fgets (buf, 4096, fp))
nlines += 2; /* potentially binary + source */
if (!nlines)
- goto err;
+ {
+ fclose (fp);
+ return NULL;
+ }
rewind (fp);
pkgver *packages;
- packages = (pkgver *) calloc (nlines, sizeof(packages[0]));
+ packages = (pkgver *) calloc (nlines + 1, sizeof(packages[0]));
int n;
for (n = 0; fgets (buf, 4096, fp) && n < nlines;)
{
@@ -349,23 +355,139 @@ dump_setup (int verbose, char **argv, bo
}
}
+ packages[n].name = packages[n].ver = NULL;
+
qsort (packages, n, sizeof (packages[0]), compar);
+ fclose (fp);
+
+ return packages;
+}
+
+void
+dump_setup (int verbose, char **argv, bool check_files)
+{
+ pkgver *packages = get_packages(argv);
+
+ puts ("Cygwin Package Information");
+ if (packages == NULL)
+ {
+ puts ("No setup information found");
+ return;
+ }
+
+ if (verbose)
+ {
+ bool need_nl = dump_file ("Last downloaded files to: ", "last-cache");
+ if (dump_file ("Last downloaded files from: ", "last-mirror") || need_nl)
+ puts ("");
+ }
+
printf ("%-*s %-*s %s\n", package_len, "Package", version_len, "Version", check_files?"Status":"");
- for (int i = 0; i < n; i++)
+ for (int i = 0; packages[i].name; i++)
{
printf ("%-*s %-*s %s\n", package_len, packages[i].name, version_len,
packages[i].ver, check_files ?
(check_package_files (verbose, packages[i].name) ? "OK" : "Incomplete") : "");
fflush(stdout);
}
- fclose (fp);
+
+ free (packages);
return;
+}
+
+void
+package_list (int verbose, char **argv)
+{
+ pkgver *packages = get_packages(argv);
+ if (packages == NULL)
+ {
+ puts ("No setup information found");
+ return;
+ }
+
+ for (int i = 0; packages[i].name; i++)
+ {
+ FILE *fp = open_package_list (packages[i].name);
+ if (!fp)
+ {
+ if (verbose)
+ printf ("Can't open file list /etc/setup/%s.lst.gz for package %s\n",
+ packages[i].name, packages[i].name);
+ return;
+ }
+
+ printf ("Package: %s-%s\n", packages[i].name, packages[i].ver);
+
+ char buf[MAX_PATH + 1];
+ while (fgets (buf, MAX_PATH, fp))
+ {
+ char *lastchar = strchr(buf, '\n');
+ if (lastchar[-1] != '/')
+ printf (" /%s", buf);
+ }
+
+ fclose (fp);
+ }
+
+ free (packages);
+
+ return;
+}
+
+void
+package_find (int verbose, char **argv)
+{
+ pkgver *packages = get_packages(NULL);
+ if (packages == NULL)
+ {
+ puts ("No setup information found");
+ return;
+ }
+
+ for (int i = 0; packages[i].name; i++)
+ {
+ FILE *fp = open_package_list (packages[i].name);
+ if (!fp)
+ {
+ if (verbose)
+ printf ("Can't open file list /etc/setup/%s.lst.gz for package %s\n",
+ packages[i].name, packages[i].name);
+ return;
+ }
+
+ char buf[MAX_PATH + 2];
+ buf[0] = '/';
+ while (fgets (buf + 1, MAX_PATH, fp))
+ {
+ char *filename = strtok(buf, "\n");
+ int flen = strlen (filename);
+ if (filename[flen - 1] != '/')
+ {
+ // FIXME: verify that /bin is mounted on /usr/bin; ditto for /lib
+ bool is_alias = !strncmp(filename, "/usr/bin/", 9) ||
+ !strncmp(filename, "/usr/lib", 9);
+ int a = match_argv (argv, filename);
+ if (!a && is_alias)
+ a = match_argv (argv, filename + 4);
+ if (!a && !strcmp(filename + flen - 4, ".exe"))
+ {
+ filename[flen - 4] = '\0';
+ a = match_argv (argv, filename);
+ }
+ if (!a && is_alias)
+ a = match_argv (argv, filename + 4);
+ if (a > 0)
+ printf ("%s-%s\n", packages[i].name, packages[i].ver);
+ }
+ }
+
+ fclose (fp);
+ }
+
+ free (packages);
-err:
- puts ("No setup information found");
- if (fp)
- fclose (fp);
return;
}
+
More information about the Cygwin-patches
mailing list