summaryrefslogtreecommitdiffstats
path: root/expac.c
diff options
context:
space:
mode:
authorDave Reisner <dreisner@archlinux.org>2014-11-16 16:51:30 -0500
committerDave Reisner <dreisner@archlinux.org>2014-11-16 16:54:30 -0500
commitc16a1cea13c70e9c40a8db82d561e71bd04f404f (patch)
tree1adf263ea9a8b1d7b2f84d0e858571a4888606f2 /expac.c
parent13145a3957ac029fc5e3f538f676c0075255822d (diff)
downloadexpac-c16a1cea13c70e9c40a8db82d561e71bd04f404f.tar.xz
Reorg a bit, introduce a control struct
Diffstat (limited to 'expac.c')
-rw-r--r--expac.c439
1 files changed, 132 insertions, 307 deletions
diff --git a/expac.c b/expac.c
index b519d4d..b6f7b0e 100644
--- a/expac.c
+++ b/expac.c
@@ -36,6 +36,10 @@
#include <string.h>
#include <time.h>
+#include "expac.h"
+#include "conf.h"
+#include "util.h"
+
#define DEFAULT_DELIM "\n"
#define DEFAULT_LISTDELIM " "
#define DEFAULT_TIMEFMT "%c"
@@ -50,208 +54,23 @@ static char const digits[] = "0123456789";
static char const printf_flags[] = "'-+ #0I";
alpm_db_t *db_local = NULL;
-alpm_list_t *dblist = NULL;
alpm_list_t *targets = NULL;
bool opt_readone = false;
bool opt_verbose = false;
bool opt_search = false;
-bool opt_local = false;
bool opt_groups = false;
bool opt_localpkg = false;
char opt_humansize = 'B';
+SearchCorpus opt_corpus = SEARCH_LOCAL;
const char *opt_format = NULL;
const char *opt_timefmt = DEFAULT_TIMEFMT;
const char *opt_listdelim = DEFAULT_LISTDELIM;
const char *opt_delim = DEFAULT_DELIM;
+const char *opt_config_file = "/etc/pacman.conf";
int opt_pkgcounter = 0;
typedef const char *(*extractfn)(void*);
-typedef struct config_t {
- char **repos;
- int size;
- int capacity;
-} config_t;
-
-static inline void freep(void *p) { free(*(void **)p); }
-static inline void fclosep(FILE **p) { if (*p) fclose(*p); }
-static inline void globfreep(glob_t *p) { globfree(p); }
-#define _cleanup_(x) __attribute__((cleanup(x)))
-#define _cleanup_free_ _cleanup_(freep)
-
-static size_t strtrim(char *str) {
- char *left = str, *right;
-
- if (!str || *str == '\0') {
- return 0;
- }
-
- while (isspace((unsigned char)*left)) {
- left++;
- }
- if (left != str) {
- memmove(str, left, (strlen(left) + 1));
- left = str;
- }
-
- if (*str == '\0') {
- return 0;
- }
-
- right = strchr(str, '\0') - 1;
- while (isspace((unsigned char)*right)) {
- right--;
- }
- *++right = '\0';
-
- return right - left;
-}
-
-int is_section(const char *s, int n) {
- return s[0] == '[' && s[n-1] == ']';
-}
-
-static int config_add_repo(config_t *config, char *reponame) {
- /* first time setup */
- if (config->repos == NULL) {
- config->repos = calloc(10, sizeof(char*));
- if (config->repos == NULL) {
- return -ENOMEM;
- }
-
- config->size = 0;
- config->capacity = 10;
- }
-
- /* grow when needed */
- if (config->size == config->capacity) {
- void *ptr;
-
- ptr = realloc(config->repos, config->capacity * 2.5 * sizeof(char*));
- if (ptr == NULL) {
- return -ENOMEM;
- }
-
- config->repos = ptr;
- }
-
- config->repos[config->size] = strdup(reponame);
- ++config->size;
-
- return 0;
-}
-
-void config_reset(config_t *config) {
- if (config == NULL)
- return;
-
- for (int i = 0; i < config->size; ++i)
- free(config->repos[i]);
-
- free(config->repos);
-}
-
-static int parse_one_file(config_t *config, const char *filename, char **section);
-
-static int parse_include(config_t *config, const char *include, char **section) {
- _cleanup_(globfreep) glob_t globbuf = {};
-
- if (glob(include, GLOB_NOCHECK, NULL, &globbuf) != 0) {
- fprintf(stderr, "warning: globbing failed on '%s': out of memory\n",
- include);
- return -ENOMEM;
- }
-
- for (size_t i = 0; i < globbuf.gl_pathc; ++i) {
- int r;
- r = parse_one_file(config, globbuf.gl_pathv[i], section);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static char *split_keyval(char *line, const char *sep) {
- strsep(&line, sep);
- return line;
-}
-
-static int parse_one_file(config_t *config, const char *filename, char **section) {
- _cleanup_(fclosep) FILE *fp = NULL;
- _cleanup_free_ char *line = NULL;
- size_t n = 0;
- int in_options = 0;
-
- if (*section)
- in_options = strcmp(*section, "options") == 0;
-
- fp = fopen(filename, "r");
- if (fp == NULL)
- return -errno;
-
- for (;;) {
- ssize_t len;
-
- errno = 0;
- len = getline(&line, &n, fp);
- if (len < 0) {
- if (errno != 0)
- return -errno;
-
- /* EOF */
- break;
- }
-
- len = strtrim(line);
- if (len == 0 || line[0] == '#')
- continue;
-
- if (is_section(line, len)) {
- free(*section);
- *section = strndup(&line[1], len - 2);
- if (*section == NULL)
- return -ENOMEM;
-
- in_options = strcmp(*section, "options") == 0;
- if (!in_options) {
- int r;
-
- r = config_add_repo(config, *section);
- if (r < 0)
- return r;
-
- }
- continue;
- }
-
- if (in_options && memchr(line, '=', len)) {
- char *val;
-
- val = split_keyval(line, "=");
- strtrim(line);
-
- if (strcmp(line, "Include") == 0) {
- int k;
-
- strtrim(val);
-
- k = parse_include(config, val, section);
- if (k < 0)
- return k;
- }
- }
- }
-
- return 0;
-}
-
-static int config_parse(config_t *config, const char *filename) {
- _cleanup_free_ char *section = NULL;
-
- return parse_one_file(config, filename, &section);
-}
-
static const char *alpm_backup_get_name(alpm_backup_t *bkup) {
return bkup->name;
}
@@ -303,35 +122,6 @@ static char *format_optdep(alpm_depend_t *optdep) {
return out;
}
-static alpm_handle_t *alpm_init(void) {
- alpm_handle_t *alpm = NULL;
- enum _alpm_errno_t alpm_errno = 0;
- config_t config = { NULL, 0, 0 };
- int r;
-
- alpm = alpm_initialize("/", "/var/lib/pacman", &alpm_errno);
- if (!alpm) {
- alpm_strerror(alpm_errno);
- return NULL;
- }
-
- db_local = alpm_get_localdb(alpm);
-
- r = config_parse(&config, "/etc/pacman.conf");
- if (r < 0) {
- fprintf(stderr, "error: failed to parse config: %s\n", strerror(-r));
- return NULL;
- }
-
- for (int i = 0; i < config.size; ++i) {
- alpm_register_syncdb(alpm, config.repos[i], 0);
- }
-
- config_reset(&config);
-
- return alpm;
-}
-
static const char *alpm_dep_get_name(void *dep) {
return ((alpm_depend_t*)dep)->name;
}
@@ -356,8 +146,7 @@ static void usage(void) {
"For more details see expac(1).\n");
}
-static int parse_options(int argc, char *argv[], alpm_handle_t *alpm) {
- int opt, option_index = 0;
+static int parse_options(int argc, char *argv[]) {
const char *i;
static struct option opts[] = {
@@ -376,22 +165,19 @@ static int parse_options(int argc, char *argv[], alpm_handle_t *alpm) {
{0, 0, 0, 0}
};
- while (-1 != (opt = getopt_long(argc, argv, "1l:d:gH:hf:pQSst:v", opts, &option_index))) {
+ for (;;) {
+ int opt;
+
+ opt = getopt_long(argc, argv, "1l:d:gH:hf:pQSst:v", opts, NULL);
+ if (opt < 0)
+ break;
+
switch (opt) {
case 'S':
- if (dblist) {
- fprintf(stderr, "error: can only select one repo option (use -h for help)\n");
- return 1;
- }
- dblist = alpm_list_copy(alpm_get_syncdbs(alpm));
+ opt_corpus = SEARCH_SYNC;
break;
case 'Q':
- if (dblist) {
- fprintf(stderr, "error: can only select one repo option (use -h for help)\n");
- return 1;
- }
- dblist = alpm_list_add(dblist, db_local);
- opt_local = true;
+ opt_corpus = SEARCH_LOCAL;
break;
case '1':
opt_readone = true;
@@ -406,13 +192,13 @@ static int parse_options(int argc, char *argv[], alpm_handle_t *alpm) {
opt_listdelim = optarg;
break;
case 'H':
- for(i = SIZE_TOKENS; *i; i++) {
- if(*i == *optarg) {
+ for (i = SIZE_TOKENS; *i; i++) {
+ if (*i == *optarg) {
opt_humansize = *optarg;
break;
}
}
- if(*i == '\0') {
+ if (*i == '\0') {
fprintf(stderr, "error: invalid SI size formatter: %c\n", *optarg);
return 1;
}
@@ -421,7 +207,7 @@ static int parse_options(int argc, char *argv[], alpm_handle_t *alpm) {
usage();
return 1;
case 'p':
- opt_localpkg = true;
+ opt_corpus = SEARCH_FILE;
break;
case 's':
opt_search = true;
@@ -440,9 +226,9 @@ static int parse_options(int argc, char *argv[], alpm_handle_t *alpm) {
}
}
- if (optind < argc) {
+ if (optind < argc)
opt_format = argv[optind++];
- } else {
+ else {
fprintf(stderr, "error: missing format string (use -h for help)\n");
return 1;
}
@@ -588,7 +374,7 @@ static bool backup_file_is_modified(const alpm_backup_t *backup_file) {
static alpm_list_t *get_modified_files(alpm_pkg_t *pkg) {
alpm_list_t *i, *modified_files = NULL;
- for(i = alpm_pkg_get_backup(pkg); i; i = alpm_list_next(i)) {
+ for(i = alpm_pkg_get_backup(pkg); i; i = i->next) {
const alpm_backup_t *backup = i->data;
if(backup->hash && backup_file_is_modified(backup)) {
modified_files = alpm_list_add(modified_files, backup->name);
@@ -809,126 +595,165 @@ static alpm_list_t *search_groups(alpm_list_t *dbs, alpm_list_t *groupnames) {
return packages;
}
-static alpm_list_t *resolve_pkg(alpm_list_t *targets) {
+static alpm_list_t *resolve_pkg(alpm_list_t *dblist, alpm_list_t *targets) {
char *pkgname, *reponame;
alpm_list_t *t, *r, *ret = NULL;
- if (targets == NULL) {
+ if (targets == NULL)
return all_packages(dblist);
- } else if (opt_search) {
+ else if (opt_search)
return search_packages(dblist, targets);
- } else if (opt_groups) {
+ else if (opt_groups)
return search_groups(dblist, targets);
- }
/* resolve each target individually from the repo pool */
- for (t = targets; t; t = alpm_list_next(t)) {
+ for (t = targets; t; t = t->next) {
alpm_pkg_t *pkg = NULL;
int found = 0;
pkgname = reponame = t->data;
- if (strchr(pkgname, '/')) {
+ if (strchr(pkgname, '/'))
strsep(&pkgname, "/");
- } else {
+ else
reponame = NULL;
- }
- for (r = dblist; r; r = alpm_list_next(r)) {
+ for (r = dblist; r; r = r->next) {
alpm_db_t *repo = r->data;
- if (reponame && strcmp(reponame, alpm_db_get_name(repo)) != 0) {
+ if (reponame && strcmp(reponame, alpm_db_get_name(repo)) != 0)
continue;
- }
pkg = alpm_db_get_pkg(repo, pkgname);
- if (pkg == NULL) {
+ if (pkg == NULL)
continue;
- }
found = 1;
ret = alpm_list_add(ret, pkg);
- if (opt_readone) {
+ if (opt_readone)
break;
- }
}
- if (!found && opt_verbose) {
+ if (!found && opt_verbose)
fprintf(stderr, "error: package `%s' not found\n", pkgname);
- }
}
return ret;
}
-static alpm_list_t *gather_packages(alpm_handle_t *alpm, alpm_list_t *targets) {
- alpm_list_t *results = NULL;
+void expac_free(Expac *expac) {
+ if (expac == NULL)
+ return;
- if (opt_localpkg) {
- alpm_list_t *i;
+ alpm_release(expac->alpm);
+}
- /* load each target as a package */
- for (i = targets; i; i = alpm_list_next(i)) {
- alpm_pkg_t *pkg;
- int err;
+int expac_new(Expac **expac, int argc, char **argv) {
+ Expac *e;
+ enum _alpm_errno_t alpm_errno = 0;
+ config_t config = { NULL, 0, 0 };
+ int r;
- err = alpm_pkg_load(alpm, i->data, 0, 0, &pkg);
- if (err) {
- fprintf(stderr, "error: %s: %s\n", (const char*)i->data,
- alpm_strerror(alpm_errno(alpm)));
- continue;
- }
- results = alpm_list_add(results, pkg);
+ r = parse_options(argc, argv);
+ if (r < 0)
+ return r;
+
+ e = calloc(1, sizeof(*e));
+ if (e == NULL)
+ return -ENOMEM;
+
+ r = config_parse(&config, opt_config_file);
+ if (r < 0)
+ return r;
+
+ e->alpm = alpm_initialize("/", "/var/lib/pacman", &alpm_errno);
+ if (!e->alpm)
+ return -alpm_errno;
+
+ e->db_local = alpm_get_localdb(e->alpm);
+
+ for (int i = 0; i < config.size; ++i)
+ alpm_register_syncdb(e->alpm, config.repos[i], 0);
+
+ config_reset(&config);
+
+ *expac = e;
+
+ return 0;
+}
+
+int expac_search_files(Expac *expac, alpm_list_t *targets, alpm_list_t **results) {
+ alpm_list_t *i;
+
+ /* load each target as a package */
+ for (i = targets; i; i = alpm_list_next(i)) {
+ alpm_pkg_t *pkg;
+ int err;
+
+ err = alpm_pkg_load(expac->alpm, i->data, 0, 0, &pkg);
+ if (err) {
+ fprintf(stderr, "error: %s: %s\n", (const char*)i->data,
+ alpm_strerror(alpm_errno(expac->alpm)));
+ continue;
}
- } else {
- results = resolve_pkg(targets);
+ *results = alpm_list_add(*results, pkg);
}
- return results;
+ return 0;
}
-int main(int argc, char *argv[]) {
- int ret = 1;
- alpm_handle_t *alpm;
- alpm_list_t *results = NULL, *i;
+int expac_search_local(Expac *expac, alpm_list_t *targets, alpm_list_t **results) {
+ alpm_list_t *dblist;
- alpm = alpm_init();
- if (!alpm) {
- return ret;
- }
+ dblist = alpm_list_add(NULL, alpm_get_localdb(expac->alpm));
- ret = parse_options(argc, argv, alpm);
- if (ret != 0) {
- goto finish;
- }
+ *results = resolve_pkg(dblist, targets);
- /* ensure sane defaults */
- if (!dblist && !opt_localpkg) {
- opt_local = true;
- dblist = alpm_list_add(dblist, db_local);
- }
+ alpm_list_free(dblist);
- results = gather_packages(alpm, targets);
- if (results == NULL) {
- ret = 1;
- goto finish;
- }
+ return 0;
+}
- for (i = results; i; i = alpm_list_next(i)) {
- alpm_pkg_t *pkg = i->data;
- ret += print_pkg(pkg, opt_format);
- }
- ret = !!ret; /* clamp to zero/one */
+int expac_search_sync(Expac *expac, alpm_list_t *targets, alpm_list_t **results) {
+ *results = resolve_pkg(alpm_get_syncdbs(expac->alpm), targets);
+ return 0;
+}
- if(opt_localpkg) {
- alpm_list_free_inner(results, (alpm_list_fn_free)alpm_pkg_free);
+int expac_search(Expac *expac, alpm_list_t *targets, alpm_list_t **results) {
+ switch (opt_corpus) {
+ case SEARCH_LOCAL:
+ return expac_search_local(expac, targets, results);
+ case SEARCH_SYNC:
+ return expac_search_sync(expac, targets, results);
+ case SEARCH_FILE:
+ return expac_search_files(expac, targets, results);
}
+
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ alpm_list_t *results = NULL;
+ Expac *expac;
+ int r;
+
+ r = expac_new(&expac, argc, argv);
+ if (r < 0)
+ return 1;
+
+ r = expac_search(expac, targets, &results);
+ if (r < 0)
+ return 1;
+
+ if (alpm_list_count(results) == 0)
+ return 1;
+
+ for (alpm_list_t *i = results; i; i = i->next)
+ print_pkg(i->data, opt_format);
+
alpm_list_free(results);
+ expac_free(expac);
-finish:
- alpm_list_free(dblist);
- alpm_list_free(targets);
- alpm_release(alpm);
- return ret;
+ return r;
}
/* vim: set et ts=2 sw=2: */