summaryrefslogtreecommitdiff
path: root/pkgtools/pkg_filecheck/files/pkg_filecheck.c
diff options
context:
space:
mode:
Diffstat (limited to 'pkgtools/pkg_filecheck/files/pkg_filecheck.c')
-rw-r--r--pkgtools/pkg_filecheck/files/pkg_filecheck.c315
1 files changed, 315 insertions, 0 deletions
diff --git a/pkgtools/pkg_filecheck/files/pkg_filecheck.c b/pkgtools/pkg_filecheck/files/pkg_filecheck.c
new file mode 100644
index 00000000000..b372c625d69
--- /dev/null
+++ b/pkgtools/pkg_filecheck/files/pkg_filecheck.c
@@ -0,0 +1,315 @@
+/*
+ $NetBSD: pkg_filecheck.c,v 1.1.1.1 2003/07/13 16:15:34 wiz Exp $
+
+ pkg_filecheck.c -- check for files not owned by any package
+ Copyright (C) 2001 Dieter Baron
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY DIETER BARON ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL DIETER BARON BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <db.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+struct array {
+ void **p;
+ int len, alen;
+};
+
+char *prg;
+
+static int check(char **dir, DB **db, char **ignore);
+static int fts_sort(const FTSENT **e1, const FTSENT **e2);
+static void push(struct array *a, void *el);
+static int read_conf(char *fname, char ***dirp, DB ***dbp, char ***ignorep);
+
+
+
+int
+main(int argc, char *argv[])
+{
+ DB **db;
+ char **dir, **ignore;
+
+ char *cfgfile;
+ int c, i, err;
+
+ prg = argv[0];
+ opterr = 0;
+
+ cfgfile = "@PKG_SYSCONFDIR@/pkg_filecheck.conf";
+
+ while ((c=getopt(argc, argv, "c:h")) != -1) {
+ switch (c) {
+ case 'c':
+ cfgfile = optarg;
+ break;
+
+ case 'h':
+ printf("usage: %s [-h] [-c config-file]\n", prg);
+ exit(0);
+
+ default:
+ fprintf(stderr, "usage: %s [-h] [-c config-file]\n", prg);
+ exit(1);
+ }
+ }
+
+ if (read_conf(cfgfile, &dir, &db, &ignore) < 0)
+ exit(1);
+
+ err = check(dir, db, ignore);
+
+ for (i=0; db[i]; i++)
+ db[i]->close(db[i]);
+ free(dir);
+ free(db);
+ free(ignore);
+
+ exit(err ? 1 : 0);
+}
+
+
+
+static int
+check(char **dir, DB **db, char **ignore)
+{
+ FTS *fts;
+ FTSENT *ent;
+ DBT key, val;
+ int i, found;
+
+ if ((fts=fts_open(dir, FTS_PHYSICAL, fts_sort)) == NULL) {
+ fprintf(stderr, "%s: cannot walk direcotry hierarchy: %s",
+ prg, strerror(errno));
+ return -1;
+ }
+
+ while ((ent=fts_read(fts))) {
+ switch (ent->fts_info) {
+ case FTS_F:
+ key.data = ent->fts_path;
+ key.size = ent->fts_pathlen+1;
+
+ found = 0;
+ for (i=0; db[i]; i++)
+ if (db[i]->get(db[i], &key, &val, 0) == 0) {
+ found = 1;
+ break;
+ }
+
+ if (!found)
+ printf("%s\n", ent->fts_path);
+ break;
+
+ case FTS_D:
+ if (ignore)
+ for (i=0; ignore[i]; i++)
+ if (strcmp(ignore[i], ent->fts_path) == 0) {
+ fts_set(fts, ent, FTS_SKIP);
+ break;
+ }
+ break;
+
+ case FTS_DNR:
+ fprintf(stderr, "%s: cannot read directory `%s', skipped: %s\n",
+ prg, ent->fts_path, strerror(ent->fts_errno));
+ break;
+
+ case FTS_NS:
+ fprintf(stderr, "%s: cannot stat file `%s', skipped: %s\n",
+ prg, ent->fts_path, strerror(ent->fts_errno));
+ break;
+
+ case FTS_ERR:
+ fprintf(stderr, "%s: directory traversal error: %s\n",
+ prg, strerror(ent->fts_errno));
+ break;
+
+ case FTS_DC:
+ case FTS_DP:
+ case FTS_SL:
+ case FTS_SLNONE:
+ case FTS_DEFAULT:
+ /* ignore */
+ break;
+
+ default:
+ fprintf(stderr, "%s: unknown FTSENT type %d ignored\n",
+ prg, ent->fts_info);
+ break;
+ }
+ }
+
+ fts_close(fts);
+ return 0;
+}
+
+
+
+static int
+fts_sort(const FTSENT **e1, const FTSENT **e2)
+{
+ return strcmp((*e1)->fts_name, (*e2)->fts_name);
+}
+
+
+
+static int
+read_conf(char *fname, char ***dirp, DB ***dbp, char ***ignorep)
+{
+ struct array dir, db, ignore;
+ FILE *f;
+ DB *cdb;
+ char b[8192], *curd, *dbname, *cmd, *p;
+ int lineno, err;
+
+ dir.p = db.p = ignore.p = NULL;
+ dir.len = db.len = ignore.len = 0;
+ dir.alen = db.alen = ignore.alen = 0;
+
+ if ((f=fopen(fname, "r")) == NULL) {
+ fprintf(stderr, "%s: cannot open config file `%s': %s\n",
+ prg, fname, strerror(errno));
+ return -1;
+ }
+
+ curd = NULL;
+
+ lineno = 0;
+ while (fgets(b, 8192, f)) {
+ lineno++;
+ if (b[0] == '#')
+ continue;
+
+ cmd = b+strspn(b, " \t");
+ p = cmd+strcspn(cmd, " \t\n");
+ *(p++) = '\0';
+ p += strspn(p, " \t");
+ if (*p == '\n' || *p == '\0')
+ continue;
+
+ if (p[strlen(p)-1] == '\n')
+ p[strlen(p)-1] = '\0';
+
+ if (strcmp(cmd, "dir") == 0) {
+ free(curd);
+ curd = strdup(p);
+ }
+ else if (strcmp(cmd, "db") == 0) {
+ if (curd) {
+ dbname = malloc(strlen(curd) + strlen(p) + 2);
+ sprintf(dbname, "%s/%s", curd, p);
+ }
+ else
+ dbname = p;
+ if ((cdb=dbopen(dbname, O_RDONLY, 0, DB_BTREE, NULL)) == NULL) {
+ fprintf(stderr, "%s:%s:%d: cannot open data base `%s': %s\n",
+ prg, fname, lineno, dbname, strerror(errno));
+ free(dir.p);
+ free(db.p);
+ free(ignore.p);
+ return -1;
+ }
+ else
+ push(&db, cdb);
+
+ if (curd)
+ free(dbname);
+ }
+ else if (strcmp(cmd, "check") == 0)
+ push(&dir, strdup(p));
+ else if (strcmp(cmd, "ignore") == 0)
+ push(&ignore, strdup(p));
+ else {
+ fprintf(stderr, "%s:%s:%d: unrecognized command `%s'\n",
+ prg, fname, lineno, cmd);
+ }
+ }
+
+ fclose(f);
+
+ err = 0;
+
+ if (dir.p == NULL) {
+ fprintf(stderr, "%s: no directories to check\n",
+ prg);
+ err = 1;
+ }
+ if (db.p == NULL) {
+ fprintf(stderr, "%s: no file data bases given\n",
+ prg);
+ err = 1;
+ }
+
+ if (err) {
+ free(dir.p);
+ free(db.p);
+ free(ignore.p);
+ return -1;
+ }
+
+ *dirp = (char **)dir.p;
+ *dbp = (DB **)db.p;
+ *ignorep = (char **)ignore.p;
+
+ return 0;
+}
+
+
+
+static void
+push(struct array *a, void *el)
+{
+ int alen;
+ void *p;
+
+ if (a->len + 2 > a->alen) {
+ if (a->alen > 1024)
+ alen = a->alen+1024;
+ else
+ alen = a->alen * 2;
+
+ if ((p=realloc(a->p, alen*sizeof(void *))) == NULL) {
+ fprintf(stderr, "%s: malloc failure\n", prg);
+ exit(1);
+ }
+
+ a->p = p;
+ a->alen = alen;
+ }
+
+ a->p[a->len++] = el;
+ a->p[a->len] = NULL;
+}