pkgtools

morpheus pkg tools
git clone git://git.2f30.org/pkgtools
Log | Files | Refs | README | LICENSE

db.c (3281B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include "pkg.h"
      3 
      4 int fflag = 0;
      5 int vflag = 0;
      6 
      7 struct db *
      8 db_new(const char *root)
      9 {
     10 	struct db *db;
     11 	struct sigaction sa;
     12 
     13 	db = emalloc(sizeof(*db));
     14 	TAILQ_INIT(&db->pkg_head);
     15 	TAILQ_INIT(&db->pkg_rm_head);
     16 
     17 	if (!realpath(root, db->root)) {
     18 		weprintf("realpath %s:", root);
     19 		free(db);
     20 		return NULL;
     21 	}
     22 
     23 	estrlcpy(db->path, db->root, sizeof(db->path));
     24 	estrlcat(db->path, DBPATH, sizeof(db->path));
     25 
     26 	db->pkgdir = opendir(db->path);
     27 	if (!db->pkgdir) {
     28 		weprintf("opendir %s:", db->path);
     29 		free(db);
     30 		return NULL;
     31 	}
     32 
     33 	TAILQ_INIT(&db->rejrule_head);
     34 	rej_load(db);
     35 
     36 	memset(&sa, 0, sizeof(sa));
     37 	sa.sa_handler = SIG_IGN;
     38 	sigaction(SIGHUP, &sa, 0);
     39 	sigaction(SIGINT, &sa, 0);
     40 	sigaction(SIGQUIT, &sa, 0);
     41 	sigaction(SIGTERM, &sa, 0);
     42 
     43 	return db;
     44 }
     45 
     46 int
     47 db_free(struct db *db)
     48 {
     49 	struct pkg *pkg, *tmp;
     50 
     51 	for (pkg = TAILQ_FIRST(&db->pkg_head); pkg; pkg = tmp) {
     52 		tmp = TAILQ_NEXT(pkg, entry);
     53 		TAILQ_REMOVE(&db->pkg_head, pkg, entry);
     54 		pkg_free(pkg);
     55 	}
     56 
     57 	for (pkg = TAILQ_FIRST(&db->pkg_rm_head); pkg; pkg = tmp) {
     58 		tmp = TAILQ_NEXT(pkg, entry);
     59 		TAILQ_REMOVE(&db->pkg_rm_head, pkg, entry);
     60 		pkg_free(pkg);
     61 	}
     62 
     63 	closedir(db->pkgdir);
     64 	rej_free(db);
     65 	free(db);
     66 	return 0;
     67 }
     68 
     69 int
     70 db_add(struct db *db, struct pkg *pkg)
     71 {
     72 	char path[PATH_MAX];
     73 	char *name, *version;
     74 	struct pkgentry *pe;
     75 	FILE *fp;
     76 
     77 	parse_name(pkg->path, &name);
     78 	parse_version(pkg->path, &version);
     79 	estrlcpy(path, db->path, sizeof(path));
     80 	estrlcat(path, "/", sizeof(path));
     81 	estrlcat(path, name, sizeof(path));
     82 	if (version) {
     83 		estrlcat(path, "#", sizeof(path));
     84 		estrlcat(path, version, sizeof(path));
     85 	}
     86 	free(name);
     87 	free(version);
     88 
     89 	if (!(fp = fopen(path, "w"))) {
     90 		weprintf("fopen %s:", path);
     91 		return -1;
     92 	}
     93 
     94 	TAILQ_FOREACH(pe, &pkg->pe_head, entry) {
     95 		if (vflag == 1)
     96 			printf("installed %s\n", pe->path);
     97 		fputs(pe->rpath, fp);
     98 		fputc('\n', fp);
     99 	}
    100 
    101 	if (vflag == 1)
    102 		printf("adding %s\n", path);
    103 	fflush(fp);
    104 	if (fsync(fileno(fp)) < 0)
    105 		weprintf("fsync %s:", path);
    106 	fclose(fp);
    107 
    108 	return 0;
    109 }
    110 
    111 int
    112 db_rm(struct db *db, struct pkg *pkg)
    113 {
    114 	(void) db;
    115 
    116 	if (vflag == 1)
    117 		printf("removing %s\n", pkg->path);
    118 	if (remove(pkg->path) < 0) {
    119 		weprintf("remove %s:", pkg->path);
    120 		return -1;
    121 	}
    122 	sync();
    123 	return 0;
    124 }
    125 
    126 int
    127 db_load(struct db *db)
    128 {
    129 	struct pkg *pkg;
    130 	struct dirent *dp;
    131 
    132 	while ((dp = readdir(db->pkgdir))) {
    133 		if (strcmp(dp->d_name, ".") == 0 ||
    134 		    strcmp(dp->d_name, "..") == 0)
    135 			continue;
    136 		pkg = pkg_load(db, dp->d_name);
    137 		if (!pkg)
    138 			return -1;
    139 		TAILQ_INSERT_TAIL(&db->pkg_head, pkg, entry);
    140 	}
    141 
    142 	return 0;
    143 }
    144 
    145 /* Walk through all packages in the db and call `cb' for each one */
    146 int
    147 db_walk(struct db *db, int (*cb)(struct db *, struct pkg *, void *), void *data)
    148 {
    149 	struct pkg *pkg;
    150 	int r;
    151 
    152 	TAILQ_FOREACH(pkg, &db->pkg_head, entry) {
    153 		r = cb(db, pkg, data);
    154 		if (r < 0)
    155 			return -1;
    156 		/* terminate traversal */
    157 		if (r > 0)
    158 			return 1;
    159 	}
    160 	return 0;
    161 }
    162 
    163 /* Return the number of packages that have references to the given path */
    164 int
    165 db_links(struct db *db, const char *path)
    166 {
    167 	struct pkg *pkg;
    168 	struct pkgentry *pe;
    169 	int links = 0;
    170 
    171 	TAILQ_FOREACH(pkg, &db->pkg_head, entry)
    172 		TAILQ_FOREACH(pe, &pkg->pe_head, entry)
    173 			if (strcmp(pe->path, path) == 0)
    174 				links++;
    175 	return links;
    176 }