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 }