static int read_targets_from_file(FILE *in, alpm_list_t **targets) { char line[BUFSIZ]; int i = 0, end = 0; while(!end) { line[i] = fgetc(in); if(line[i] == EOF) end = 1; if(isspace(line[i]) || end) { line[i] = '\0'; /* avoid adding zero length arg, if multiple spaces separate args */ if(i > 0) { if(!alpm_list_find_str(*targets, line)) *targets = alpm_list_add(*targets, strdup(line)); i = 0; } } else { ++i; if(i >= BUFSIZ) { fprintf(stderr, "error: buffer overflow on stdin\n"); return -1; } } } return 0; }
static pmpkg_t * alpm_pkg_find_update (pmpkg_t *pkg, const alpm_list_t *dbs) { const gchar *name; const alpm_list_t *i; g_return_val_if_fail (pkg != NULL, NULL); name = alpm_pkg_get_name (pkg); for (; dbs != NULL; dbs = dbs->next) { pmpkg_t *update = alpm_db_get_pkg (dbs->data, name); if (update != NULL) { if (alpm_pkg_vercmp (alpm_pkg_get_version (update), alpm_pkg_get_version (pkg)) > 0) { return update; } else { return NULL; } } i = alpm_db_get_pkgcache (dbs->data); for (; i != NULL; i = i->next) { if (alpm_list_find_str (alpm_pkg_get_replaces (i->data), name) != NULL) { return i->data; } } } return NULL; }
/** * walk dependencies, showing dependencies of the target */ static void walk_deps(alpm_list_t *dblist, alpm_pkg_t *pkg, tdepth *depth, int rev) { alpm_list_t *deps, *i; if(!pkg || ((max_depth >= 0) && (depth->level > max_depth))) { return; } walked = alpm_list_add(walked, (void *)alpm_pkg_get_name(pkg)); if(rev) { deps = alpm_pkg_compute_requiredby(pkg); } else { deps = get_pkg_dep_names(pkg); } for(i = deps; i; i = alpm_list_next(i)) { const char *pkgname = i->data; int last = alpm_list_next(i) ? 0 : 1; alpm_pkg_t *dep_pkg = alpm_find_dbs_satisfier(handle, dblist, pkgname); if(alpm_list_find_str(walked, dep_pkg ? alpm_pkg_get_name(dep_pkg) : pkgname)) { /* if we've already seen this package, don't print in "unique" output * and don't recurse */ if(!unique) { print(alpm_pkg_get_name(pkg), alpm_pkg_get_name(dep_pkg), pkgname, depth, last); } } else { print(alpm_pkg_get_name(pkg), alpm_pkg_get_name(dep_pkg), pkgname, depth, last); if(dep_pkg) { tdepth d = { depth, NULL, depth->level + 1 }; depth->next = &d; /* last dep, cut off the limb here */ if(last) { if(depth->prev) { depth->prev->next = &d; d.prev = depth->prev; depth = &d; } else { d.prev = NULL; } } walk_deps(dblist, dep_pkg, &d, rev); depth->next = NULL; } } } if(rev) { FREELIST(deps); } else { alpm_list_free(deps); } }
static gboolean alpm_pkg_is_syncfirst (pmpkg_t *pkg) { g_return_val_if_fail (pkg != NULL, FALSE); if (alpm_list_find_str (syncfirsts, alpm_pkg_get_name (pkg)) != NULL) { return TRUE; } return FALSE; }
static gboolean alpm_pkg_is_ignorepkg (pmpkg_t *pkg) { const alpm_list_t *ignorepkgs, *ignoregrps, *i; g_return_val_if_fail (pkg != NULL, TRUE); ignorepkgs = alpm_option_get_ignorepkgs (); if (alpm_list_find_str (ignorepkgs, alpm_pkg_get_name (pkg)) != NULL) { return TRUE; } ignoregrps = alpm_option_get_ignoregrps (); for (i = alpm_pkg_get_groups (pkg); i != NULL; i = i->next) { if (alpm_list_find_str (ignoregrps, i->data) != NULL) { return TRUE; } } return FALSE; }
static void print_graph(const char *parentname, const char *pkgname, const char *depname) { if(depname) { printf("\"%s\" -> \"%s\" [color=chocolate4];\n", parentname, depname); if(pkgname && strcmp(depname, pkgname) != 0 && !alpm_list_find_str(provisions, depname)) { printf("\"%s\" -> \"%s\" [arrowhead=none, color=grey];\n", depname, pkgname); provisions = alpm_list_add(provisions, (char *)depname); } } else if(pkgname) { printf("\"%s\" -> \"%s\" [color=chocolate4];\n", parentname, pkgname); } }
static gboolean pk_alpm_transaction_remove_simulate (PkBackendJob *job, GError **error) { PkBackend *backend = pk_backend_job_get_backend (job); PkBackendAlpmPrivate *priv = pk_backend_get_user_data (backend); const alpm_list_t *i; if (!pk_alpm_transaction_simulate (job, error)) return FALSE; for (i = alpm_trans_get_remove (priv->alpm); i != NULL; i = i->next) { const gchar *name = alpm_pkg_get_name (i->data); if (alpm_list_find_str (priv->holdpkgs, name)) { g_set_error (error, PK_ALPM_ERROR, PK_ALPM_ERR_PKG_HELD, "%s: %s", name, "could not remove HoldPkg"); return FALSE; } } return TRUE; }
/** Main function. * @param argc * @param argv * @return A return code indicating success, failure, etc. */ int main(int argc, char *argv[]) { int ret = 0; size_t i; struct sigaction new_action, old_action; const int signals[] = { SIGHUP, SIGINT, SIGTERM, SIGSEGV, SIGWINCH }; uid_t myuid = getuid(); /* Set signal handlers */ /* Set up the structure to specify the new action. */ new_action.sa_handler = handler; sigemptyset(&new_action.sa_mask); new_action.sa_flags = SA_RESTART; /* assign our handler to any signals we care about */ for(i = 0; i < sizeof(signals) / sizeof(signals[0]); i++) { int signal = signals[i]; sigaction(signal, NULL, &old_action); if(old_action.sa_handler != SIG_IGN) { sigaction(signal, &new_action, NULL); } } /* i18n init */ #if defined(ENABLE_NLS) localize(); #endif /* set user agent for downloading */ setuseragent(); /* init config data */ if(!(config = config_new())) { /* config_new prints the appropriate error message */ cleanup(1); } /* disable progressbar if the output is redirected */ if(!isatty(fileno(stdout))) { config->noprogressbar = 1; } /* Priority of options: * 1. command line * 2. config file * 3. compiled-in defaults * However, we have to parse the command line first because a config file * location can be specified here, so we need to make sure we prefer these * options over the config file coming second. */ /* parse the command line */ ret = parseargs(argc, argv); if(ret != 0) { cleanup(ret); } /* we support reading targets from stdin if a cmdline parameter is '-' */ if(alpm_list_find_str(pm_targets, "-")) { if(!isatty(fileno(stdin))) { int target_found = 0; size_t current_size = PATH_MAX; char *vdata, *line = malloc(current_size); int c; /* remove the '-' from the list */ pm_targets = alpm_list_remove_str(pm_targets, "-", &vdata); free(vdata); i = 0; do { c = fgetc(stdin); if(c == EOF || isspace(c)) { /* avoid adding zero length arg when multiple spaces separate args */ if(i > 0) { line[i] = '\0'; pm_targets = alpm_list_add(pm_targets, strdup(line)); target_found = 1; i = 0; } } else { line[i++] = (char)c; /* we may be at the end of our allocated buffer now */ if(i >= current_size) { char *new = realloc(line, current_size * 2); if(new) { line = new; current_size *= 2; } else { free(line); pm_printf(ALPM_LOG_ERROR, _("memory exhausted in argument parsing\n")); cleanup(EXIT_FAILURE); } } } } while(c != EOF);
/** Search for packages to upgrade and add them to the transaction. */ int SYMEXPORT alpm_sync_sysupgrade(alpm_handle_t *handle, int enable_downgrade) { alpm_list_t *i, *j, *k; alpm_trans_t *trans; alpm_db_t *db_local; alpm_list_t *dbs_sync; CHECK_HANDLE(handle, return -1); trans = handle->trans; db_local = handle->db_local; dbs_sync = handle->dbs_sync; ASSERT(trans != NULL, RET_ERR(handle, ALPM_ERR_TRANS_NULL, -1)); ASSERT(trans->state == STATE_INITIALIZED, RET_ERR(handle, ALPM_ERR_TRANS_NOT_INITIALIZED, -1)); _alpm_log(handle, ALPM_LOG_DEBUG, "checking for package upgrades\n"); for(i = _alpm_db_get_pkgcache(db_local); i; i = i->next) { alpm_pkg_t *lpkg = i->data; if(_alpm_pkg_find(trans->add, lpkg->name)) { _alpm_log(handle, ALPM_LOG_DEBUG, "%s is already in the target list -- skipping\n", lpkg->name); continue; } /* Search for literal then replacers in each sync database. * If found, don't check other databases */ for(j = dbs_sync; j; j = j->next) { alpm_db_t *sdb = j->data; /* Check sdb */ alpm_pkg_t *spkg = _alpm_db_get_pkgfromcache(sdb, lpkg->name); if(spkg) { /* 1. literal was found in sdb */ int cmp = _alpm_pkg_compare_versions(spkg, lpkg); if(cmp > 0) { _alpm_log(handle, ALPM_LOG_DEBUG, "new version of '%s' found (%s => %s)\n", lpkg->name, lpkg->version, spkg->version); /* check IgnorePkg/IgnoreGroup */ if(_alpm_pkg_should_ignore(handle, spkg) || _alpm_pkg_should_ignore(handle, lpkg)) { _alpm_log(handle, ALPM_LOG_WARNING, _("%s: ignoring package upgrade (%s => %s)\n"), lpkg->name, lpkg->version, spkg->version); } else { _alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); trans->add = alpm_list_add(trans->add, spkg); } } else if(cmp < 0) { if(enable_downgrade) { /* check IgnorePkg/IgnoreGroup */ if(_alpm_pkg_should_ignore(handle, spkg) || _alpm_pkg_should_ignore(handle, lpkg)) { _alpm_log(handle, ALPM_LOG_WARNING, _("%s: ignoring package downgrade (%s => %s)\n"), lpkg->name, lpkg->version, spkg->version); } else { _alpm_log(handle, ALPM_LOG_WARNING, _("%s: downgrading from version %s to version %s\n"), lpkg->name, lpkg->version, spkg->version); trans->add = alpm_list_add(trans->add, spkg); } } else { _alpm_log(handle, ALPM_LOG_WARNING, _("%s: local (%s) is newer than %s (%s)\n"), lpkg->name, lpkg->version, sdb->treename, spkg->version); } } /* jump to next local package */ break; } else { /* 2. search for replacers in sdb */ int found = 0; for(k = _alpm_db_get_pkgcache(sdb); k; k = k->next) { spkg = k->data; if(alpm_list_find_str(alpm_pkg_get_replaces(spkg), lpkg->name)) { found = 1; /* check IgnorePkg/IgnoreGroup */ if(_alpm_pkg_should_ignore(handle, spkg) || _alpm_pkg_should_ignore(handle, lpkg)) { _alpm_log(handle, ALPM_LOG_WARNING, _("ignoring package replacement (%s-%s => %s-%s)\n"), lpkg->name, lpkg->version, spkg->name, spkg->version); continue; } int doreplace = 0; QUESTION(trans, ALPM_TRANS_CONV_REPLACE_PKG, lpkg, spkg, sdb->treename, &doreplace); if(!doreplace) { continue; } /* If spkg is already in the target list, we append lpkg to spkg's * removes list */ alpm_pkg_t *tpkg = _alpm_pkg_find(trans->add, spkg->name); if(tpkg) { /* sanity check, multiple repos can contain spkg->name */ if(tpkg->origin_data.db != sdb) { _alpm_log(handle, ALPM_LOG_WARNING, _("cannot replace %s by %s\n"), lpkg->name, spkg->name); continue; } _alpm_log(handle, ALPM_LOG_DEBUG, "appending %s to the removes list of %s\n", lpkg->name, tpkg->name); tpkg->removes = alpm_list_add(tpkg->removes, lpkg); /* check the to-be-replaced package's reason field */ if(alpm_pkg_get_reason(lpkg) == ALPM_PKG_REASON_EXPLICIT) { tpkg->reason = ALPM_PKG_REASON_EXPLICIT; } } else { /* add spkg to the target list */ /* copy over reason */ spkg->reason = alpm_pkg_get_reason(lpkg); spkg->removes = alpm_list_add(NULL, lpkg); _alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s-%s to the transaction targets\n", spkg->name, spkg->version); trans->add = alpm_list_add(trans->add, spkg); } } } if(found) { break; /* jump to next local package */ } } } } return 0; }
/** * pacman_list_find_string: * @haystack: A #PacmanList. * @needle: A string to find. * * Searches @haystack for a string equal to @needle. * * Returns: A string from @haystack, or %NULL if none were found. */ gchar *pacman_list_find_string (const PacmanList *haystack, const gchar *needle) { return alpm_list_find_str (haystack, needle); }
int main (int argc, char **argv) { int ret=0, i; int need=0, given=0, cycle_db=0, db_order=0; alpm_list_t *t; struct sigaction a; init_config (argv[0]); a.sa_handler = handler; sigemptyset(&a.sa_mask); a.sa_flags = 0; sigaction(SIGINT, &a, NULL); sigaction(SIGTERM, &a, NULL); int opt; int opt_index=0; static struct option opts[] = { {"query", no_argument, 0, 'Q'}, {"sync", no_argument, 0, 'S'}, {"dbpath", required_argument, 0, 'b'}, {"deps", no_argument, 0, 'd'}, {"explicit", no_argument, 0, 'e'}, {"groups", no_argument, 0, 'g'}, {"help", no_argument, 0, 'h'}, {"info", no_argument, 0, 'i'}, {"list", no_argument, 0, 'l'}, {"foreign", no_argument, 0, 'm'}, {"file", no_argument, 0, 'p'}, {"quiet", no_argument, 0, 'q'}, {"root", required_argument, 0, 'r'}, {"search", no_argument, 0, 's'}, {"unrequired", no_argument, 0, 't'}, {"upgrades", no_argument, 0, 'u'}, {"config", required_argument, 0, 'c'}, {"just-one", no_argument, 0, '1'}, {"aur", no_argument, 0, 'A'}, {"escape", no_argument, 0, 'x'}, {"format", required_argument, 0, 'f'}, {"list-repo", required_argument, 0, 'L'}, {"query-type", required_argument, 0, 1000}, {"csep", required_argument, 0, 1001}, {"delimiter", required_argument, 0, 1001}, {"sort", required_argument, 0, 1002}, {"nocolor", no_argument, 0, 1003}, {"number", no_argument, 0, 1004}, {"get-res", no_argument, 0, 1005}, {"show-size", no_argument, 0, 1006}, {"aur-url", required_argument, 0, 1007}, {"insecure", no_argument, 0, 1008}, {"qdepends", no_argument, 0, 1009}, {"qconflicts", no_argument, 0, 1010}, {"qprovides", no_argument, 0, 1011}, {"qreplaces", no_argument, 0, 1012}, {"qrequires", no_argument, 0, 1013}, {"color", no_argument, 0, 1014}, {"version", no_argument, 0, 'v'}, {0, 0, 0, 0} }; while ((opt = getopt_long (argc, argv, "1Ac:b:def:ghiLlmpQqr:Sstuvx", opts, &opt_index)) != -1) { switch (opt) { case '1': config.just_one = 1; break; case 'A': if (config.aur) break; config.aur = ++db_order; given |= N_DB; break; case 'c': FREE (config.configfile); config.configfile = strndup (optarg, PATH_MAX); break; case 'b': FREE (config.dbpath); config.dbpath = strndup (optarg, PATH_MAX); break; case 'd': config.filter |= F_DEPS; break; case 'e': config.filter |= F_EXPLICIT; break; case 'x': config.escape = 1; break; case 'f': config.custom_out = 1; strncpy (config.format_out, optarg, PATH_MAX); format_str (config.format_out); break; case 'g': if (config.op) break; config.op = OP_LIST_GROUP; config.filter |= F_GROUP; cycle_db = 1; break; case 'i': if (config.op) { if (config.op == OP_INFO) config.op = OP_INFO_P; break; } config.op = OP_INFO; need |= N_TARGET | N_DB; break; case 'L': config.list = 1; break; case 'l': if (config.op) break; config.op = OP_LIST_REPO; need |= N_DB; cycle_db = 1; break; case 'm': config.filter |= F_FOREIGN; break; case 'p': config.is_file = 1; need |= N_TARGET; break; case 'Q': if (config.db_local) break; config.db_local = ++db_order; given |= N_DB; break; case 'q': config.quiet = 1; break; case 'r': FREE (config.rootdir); config.rootdir = strndup (optarg, PATH_MAX); break; case 's': if (config.op) break; config.op = OP_SEARCH; need |= N_DB; cycle_db = 1; break; case 'S': if (config.db_sync) break; config.db_sync = ++db_order; given |= N_DB; break; case 't': config.filter |= F_UNREQUIRED; break; case 1000: /* --query-type */ if (config.op) break; config.op = OP_QUERY; if (strcmp (optarg, "depends")==0) config.query = OP_Q_DEPENDS; else if (strcmp (optarg, "conflicts")==0) config.query = OP_Q_CONFLICTS; else if (strcmp (optarg, "provides")==0) config.query = OP_Q_PROVIDES; else if (strcmp (optarg, "replaces")==0) config.query = OP_Q_REPLACES; need |= N_TARGET | N_DB; break; case 1009: /* --qdepends */ SETQUERY (OP_Q_DEPENDS); break; case 1010: /* --qconflicts */ SETQUERY (OP_Q_CONFLICTS); break; case 1011: /* --qprovides */ SETQUERY (OP_Q_PROVIDES); break; case 1012: /* --qreplaces */ SETQUERY (OP_Q_REPLACES); break; case 1013: /* --qrequires */ SETQUERY (OP_Q_REQUIRES); break; case 1001: /* --delimiter */ strncpy (config.delimiter, optarg, SEP_LEN); format_str (config.delimiter); break; case 1002: /* --sort */ config.sort = optarg[0]; break; case 1003: /* --nocolor */ config.colors=0; break; case 1004: /* --number */ config.numbering = 1; break; case 1005: /* --get-res */ if (dup2(FD_RES, FD_RES) == FD_RES) config.get_res = 1; break; case 1006: /* --show-size */ config.show_size = 1; break; case 1007: /* --aur-url */ FREE (config.aur_url); config.aur_url = strdup (optarg); break; case 1008: /* --insecure */ config.insecure = 1; break; case 1014: /* --color */ config.colors=1; break; case 'u': config.filter |= F_UPGRADES; break; case 'v': version(); break; case 'h': usage (0); break; default: /* '?' */ usage (1); } } if (config.list) { /* -L displays respository list and exits. */ alpm_list_t *dbs = get_db_sync (); if (dbs) { for(t = dbs; t; t = alpm_list_next(t)) printf ("%s\n", (char *)t->data); FREELIST (dbs); } cleanup (0); } if (!config.custom_out) { if (config.colors) color_init(); #if defined(HAVE_GETTEXT) && defined(ENABLE_NLS) /* TODO: specific package-query locale ? */ setlocale (LC_ALL, ""); bindtextdomain ("yaourt", LOCALEDIR); textdomain ("yaourt"); #endif } if ((need & N_DB) && !(given & N_DB)) { fprintf(stderr, "search or information must have database target (-{Q,S,A}).\n"); exit(1); } for (i = optind; i < argc; i++) { if (!config.just_one || !alpm_list_find_str (targets, argv[i])) targets = alpm_list_add(targets, strdup(argv[i])); } if (i!=optind) { given |= N_TARGET; } if ((need & N_TARGET) && !(given & N_TARGET)) { fprintf(stderr, "no targets specified.\n"); usage(1); } if (targets == NULL) { if (config.op == OP_SEARCH) config.op = OP_LIST_REPO_S; } else if (!config.op && (given & N_DB)) /* Show info by default */ config.op = OP_INFO; // init_db_sync initializes alpm after parsing [options] if (!init_db_sync ()) cleanup(1); if (config.is_file) { for(t = targets; t; t = alpm_list_next(t)) { alpm_pkg_t *pkg=NULL; const char *filename = t->data; if (alpm_pkg_load (config.handle, filename, 0, ALPM_SIG_USE_DEFAULT, &pkg)!=0 || pkg==NULL) { fprintf(stderr, "unable to read %s.\n", filename); continue; } print_package (filename, pkg, alpm_pkg_get_str); ret++; } cleanup(!ret); } if (cycle_db || targets) { for (i=1; i<=db_order && (cycle_db || targets); i++) { /*printf ("%d, aur %d, local %d, sync %d\n", i, config.aur, config.db_local, config.db_sync);*/ if (config.db_sync == i) { for(t = alpm_get_syncdbs(config.handle); t; t = alpm_list_next(t)) ret += deal_db (t->data); if (!ret && config.op == OP_INFO_P) { config.op = OP_QUERY; config.query = OP_Q_PROVIDES; for(t = alpm_get_syncdbs(config.handle); t; t = alpm_list_next(t)) ret += deal_db (t->data); config.op = OP_INFO_P; } } else if (config.db_local == i) ret += deal_db (alpm_get_localdb(config.handle)); else if (config.aur == i) switch (config.op) { case OP_INFO: case OP_INFO_P: ret += aur_info (&targets); break; case OP_SEARCH: ret += aur_search (targets); break; default: break; } } } else if (!config.aur && config.db_local) ret += alpm_search_local (config.filter, NULL, NULL); else if (config.aur && !(given & N_TARGET)) { if (config.filter & F_FOREIGN) { /* -Am */ config.aur_foreign = 1; config.just_one = 1; alpm_search_local (config.filter, "%n", &targets); ret += aur_info (&targets); if (config.db_local) /* -AQm */ ret += search_pkg_by_name (alpm_get_localdb(config.handle), &targets); } else if (config.filter & F_UPGRADES) { /* -Au */ config.aur_upgrades = 1; if (config.db_local) /* -AQu */ ret += alpm_search_local (config.filter, NULL, NULL); alpm_search_local (F_FOREIGN | (config.filter & ~F_UPGRADES), "%n>%v", &targets); ret += aur_info (&targets); } } show_results(); /* Some cleanups */ cleanup(!ret); return 0; }
/** Unpack a list of files in an archive. * @param handle the context handle * @param path the archive to unpack * @param prefix where to extract the files * @param list a list of files within the archive to unpack or NULL for all * @param breakfirst break after the first entry found * @return 0 on success, 1 on failure */ int _alpm_unpack(alpm_handle_t *handle, const char *path, const char *prefix, alpm_list_t *list, int breakfirst) { int ret = 0; mode_t oldmask; struct archive *archive; struct archive_entry *entry; struct stat buf; int fd, cwdfd; fd = _alpm_open_archive(handle, path, &buf, &archive, ALPM_ERR_PKG_OPEN); if(fd < 0) { return 1; } oldmask = umask(0022); /* save the cwd so we can restore it later */ OPEN(cwdfd, ".", O_RDONLY); if(cwdfd < 0) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n")); } /* just in case our cwd was removed in the upgrade operation */ if(chdir(prefix) != 0) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"), prefix, strerror(errno)); ret = 1; goto cleanup; } while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) { const char *entryname; mode_t mode; entryname = archive_entry_pathname(entry); /* If specific files were requested, skip entries that don't match. */ if(list) { char *entry_prefix = strdup(entryname); char *p = strstr(entry_prefix,"/"); if(p) { *(p+1) = '\0'; } char *found = alpm_list_find_str(list, entry_prefix); free(entry_prefix); if(!found) { if(archive_read_data_skip(archive) != ARCHIVE_OK) { ret = 1; goto cleanup; } continue; } else { _alpm_log(handle, ALPM_LOG_DEBUG, "extracting: %s\n", entryname); } } mode = archive_entry_mode(entry); if(S_ISREG(mode)) { archive_entry_set_perm(entry, 0644); } else if(S_ISDIR(mode)) { archive_entry_set_perm(entry, 0755); } /* Extract the archive entry. */ int readret = archive_read_extract(archive, entry, 0); if(readret == ARCHIVE_WARN) { /* operation succeeded but a non-critical error was encountered */ _alpm_log(handle, ALPM_LOG_WARNING, _("warning given when extracting %s (%s)\n"), entryname, archive_error_string(archive)); } else if(readret != ARCHIVE_OK) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not extract %s (%s)\n"), entryname, archive_error_string(archive)); ret = 1; goto cleanup; } if(breakfirst) { break; } } cleanup: umask(oldmask); archive_read_finish(archive); CLOSE(fd); if(cwdfd >= 0) { if(fchdir(cwdfd) != 0) { _alpm_log(handle, ALPM_LOG_ERROR, _("could not restore working directory (%s)\n"), strerror(errno)); } CLOSE(cwdfd); } return ret; }
alpm_list_t *resolve_dependencies(struct pw_hashdb *hashdb, alpm_list_t *packages) { alpm_list_t *i, *k, *m, *q; alpm_list_t *deps, *newdeps; pmpkg_t *pkg; struct pkgpair pkgpair; struct pkgpair *pkgpair_ptr; char pkgbuild[PATH_MAX]; struct stat st; newdeps = NULL; for (i = packages; i; i = i->next) { snprintf(pkgbuild, PATH_MAX, "%s/PKGBUILD", i->data); /* Grab the list of new dependencies from PKGBUILD */ deps = grab_dependencies(pkgbuild); if (!deps) { continue; } if (config->verbose) { printf("\nResolving dependencies for %s\n", i->data); } for (k = deps; k; k = k->next) { pkgpair.pkgname = k->data; /* Check against newdeps */ if (alpm_list_find_str(newdeps, k->data)) { continue; } /* Check against localdb */ if (hash_search(hashdb->local, &pkgpair)) { if (config->verbose) { printf("%s%s - Already installed\n", TAB, k->data); } continue; } /* Check against sync dbs */ pkgpair_ptr = hash_search(hashdb->sync, &pkgpair); if (pkgpair_ptr) { if (config->verbose) { printf("%s%s can be found in %s repo\n", TAB, k->data, alpm_db_get_name(alpm_pkg_get_db(pkgpair_ptr->pkg))); } continue; } /* Check against provides */ pkgpair_ptr = hashbst_tree_search(hashdb->local_provides, k->data, hashdb->local, provides_search); if (pkgpair_ptr) { if (config->verbose) { printf("%s%s is provided by %s\n", TAB, k->data, pkgpair_ptr->pkgname); } continue; } pkgpair_ptr = hashbst_tree_search(hashdb->sync_provides, k->data, hashdb->sync, provides_search); if (pkgpair_ptr) { if (config->verbose) { printf("%s%s is provided by %s\n", TAB, k->data, pkgpair_ptr->pkgname); } continue; } /* Check the directory for pkg/PKGBUILD */ snprintf(pkgbuild, PATH_MAX, "%s/PKGBUILD", k->data); if (!stat(pkgbuild, &st)) { if (config->verbose) { printf("%s%s has been downloaded\n", TAB, k->data); } continue; } /* Add to newdeps */ newdeps = alpm_list_add(newdeps, strdup(k->data)); if (config->verbose) { printf("%s%s will be downloaded from the AUR\n", TAB, k->data); } } /* Free deps */ FREELIST(deps); } return newdeps; }
/* Find file conflicts that may occur during the transaction with two checks: * 1: check every target against every target * 2: check every target against the filesystem */ alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, char *root) { alpm_list_t *i, *conflicts = NULL; alpm_list_t *targets = trans->packages; int numtargs = alpm_list_count(targets); int current; ALPM_LOG_FUNC; if(db == NULL || targets == NULL || root == NULL) { return(NULL); } /* TODO this whole function needs a huge change, which hopefully will * be possible with real transactions. Right now we only do half as much * here as we do when we actually extract files in add.c with our 12 * different cases. */ for(current = 1, i = targets; i; i = i->next, current++) { alpm_list_t *j, *k, *tmpfiles = NULL; pmpkg_t *p1, *p2, *dbpkg; char path[PATH_MAX+1]; p1 = i->data; if(!p1) { continue; } double percent = (double)current / numtargs; PROGRESS(trans, PM_TRANS_PROGRESS_CONFLICTS_START, "", (percent * 100), numtargs, current); /* CHECK 1: check every target against every target */ _alpm_log(PM_LOG_DEBUG, "searching for file conflicts: %s\n", alpm_pkg_get_name(p1)); for(j = i->next; j; j = j->next) { p2 = j->data; if(!p2) { continue; } tmpfiles = chk_fileconflicts(alpm_pkg_get_files(p1), alpm_pkg_get_files(p2)); if(tmpfiles) { for(k = tmpfiles; k; k = k->next) { snprintf(path, PATH_MAX, "%s%s", root, (char *)k->data); conflicts = add_fileconflict(conflicts, PM_FILECONFLICT_TARGET, path, alpm_pkg_get_name(p1), alpm_pkg_get_name(p2)); } FREELIST(tmpfiles); } } /* declarations for second check */ struct stat lsbuf, sbuf; char *filestr = NULL; /* CHECK 2: check every target against the filesystem */ _alpm_log(PM_LOG_DEBUG, "searching for filesystem conflicts: %s\n", p1->name); dbpkg = _alpm_db_get_pkgfromcache(db, p1->name); /* Do two different checks here. f the package is currently installed, * then only check files that are new in the new package. If the package * is not currently installed, then simply stat the whole filelist */ if(dbpkg) { /* older ver of package currently installed */ tmpfiles = chk_filedifference(alpm_pkg_get_files(p1), alpm_pkg_get_files(dbpkg)); } else { /* no version of package currently installed */ tmpfiles = alpm_list_strdup(alpm_pkg_get_files(p1)); } /* loop over each file to be installed */ for(j = tmpfiles; j; j = j->next) { int skip_conflict = 0; filestr = j->data; snprintf(path, PATH_MAX, "%s%s", root, filestr); /* stat the file - if it exists, do some checks */ if(_alpm_lstat(path, &lsbuf) != 0) { continue; } stat(path, &sbuf); if(path[strlen(path)-1] == '/') { if(S_ISDIR(lsbuf.st_mode)) { _alpm_log(PM_LOG_DEBUG, "%s is a directory, not a conflict\n", path); skip_conflict = 1; } else if(S_ISLNK(lsbuf.st_mode) && S_ISDIR(sbuf.st_mode)) { _alpm_log(PM_LOG_DEBUG, "%s is a symlink to a dir, hopefully not a conflict\n", path); skip_conflict = 1; } } if(!skip_conflict) { _alpm_log(PM_LOG_DEBUG, "checking possible conflict: %s\n", path); /* Look at all the targets to see if file has changed hands */ int resolved_conflict = 0; /* have we acted on this conflict? */ for(k = targets; k; k = k->next) { p2 = k->data; if(!p2 || strcmp(p1->name, p2->name) == 0) { continue; } pmpkg_t *localp2 = _alpm_db_get_pkgfromcache(db, p2->name); /* Check if it used to exist in a package, but doesn't anymore */ alpm_list_t *pkgfiles, *localfiles; /* added for readability */ pkgfiles = alpm_pkg_get_files(p2); localfiles = alpm_pkg_get_files(localp2); if(localp2 && !alpm_list_find_str(pkgfiles, filestr) && alpm_list_find_str(localfiles, filestr)) { /* skip removal of file, but not add. this will prevent a second * package from removing the file when it was already installed * by its new owner (whether the file is in backup array or not */ trans->skip_remove = alpm_list_add(trans->skip_remove, strdup(path)); _alpm_log(PM_LOG_DEBUG, "file changed packages, adding to remove skiplist: %s\n", filestr); resolved_conflict = 1; break; } } if(!resolved_conflict) { _alpm_log(PM_LOG_DEBUG, "file found in conflict: %s\n", path); conflicts = add_fileconflict(conflicts, PM_FILECONFLICT_FILESYSTEM, path, p1->name, NULL); } } } FREELIST(tmpfiles); } return(conflicts); }