/** * @brief Upgrade a specified list of packages. * * @param targets a list of packages (as strings) to upgrade * * @return 0 on success, 1 on failure */ int pacman_upgrade(alpm_list_t *targets) { alpm_list_t *i; alpm_siglevel_t level = alpm_option_get_default_siglevel(config->handle); if(targets == NULL) { pm_printf(ALPM_LOG_ERROR, _("no targets specified (use -h for help)\n")); return 1; } /* Check for URL targets and process them */ for(i = targets; i; i = alpm_list_next(i)) { if(strstr(i->data, "://")) { char *str = alpm_fetch_pkgurl(config->handle, i->data); if(str == NULL) { pm_fprintf(stderr, ALPM_LOG_ERROR, "'%s': %s\n", (char *)i->data, alpm_strerror(alpm_errno(config->handle))); return 1; } else { free(i->data); i->data = str; } } } /* Step 1: create a new transaction */ if(trans_init(config->flags, 1) == -1) { return 1; } printf(_("loading packages...\n")); /* add targets to the created transaction */ for(i = targets; i; i = alpm_list_next(i)) { char *targ = alpm_list_getdata(i); alpm_pkg_t *pkg; if(alpm_pkg_load(config->handle, targ, 1, level, &pkg) != 0) { pm_fprintf(stderr, ALPM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerror(alpm_errno(config->handle))); trans_release(); return 1; } if(alpm_add_pkg(config->handle, pkg) == -1) { pm_fprintf(stderr, ALPM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerror(alpm_errno(config->handle))); alpm_pkg_free(pkg); trans_release(); return 1; } config->explicit_adds = alpm_list_add(config->explicit_adds, pkg); } /* now that targets are resolved, we can hand it all off to the sync code */ return sync_prepare_execute(); }
/* Loop through the packages. For each package, * loop through files to check if they exist. */ static int check(alpm_pkg_t *pkg) { const char *root, *pkgname; size_t errors = 0; size_t rootlen; char f[PATH_MAX]; alpm_filelist_t *filelist; size_t i; root = alpm_option_get_root(config->handle); rootlen = strlen(root); if(rootlen + 1 > PATH_MAX) { /* we are in trouble here */ pm_fprintf(stderr, ALPM_LOG_ERROR, _("path too long: %s%s\n"), root, ""); return 1; } strcpy(f, root); pkgname = alpm_pkg_get_name(pkg); filelist = alpm_pkg_get_files(pkg); for(i = 0; i < filelist->count; i++) { const alpm_file_t *file = filelist->files + i; struct stat st; const char *path = file->name; if(rootlen + 1 + strlen(path) > PATH_MAX) { pm_fprintf(stderr, ALPM_LOG_WARNING, _("path too long: %s%s\n"), root, path); continue; } strcpy(f + rootlen, path); /* use lstat to prevent errors from symlinks */ if(lstat(f, &st) != 0) { if(config->quiet) { printf("%s %s\n", pkgname, f); } else { pm_printf(ALPM_LOG_WARNING, "%s: %s (%s)\n", pkgname, f, strerror(errno)); } errors++; } } if(!config->quiet) { printf(_n("%s: %jd total file, ", "%s: %jd total files, ", (unsigned long)filelist->count), pkgname, (intmax_t)filelist->count); printf(_n("%jd missing file\n", "%jd missing files\n", (unsigned long)errors), (intmax_t)errors); } return (errors != 0 ? 1 : 0); }
static int query_group(alpm_list_t *targets) { alpm_list_t *i, *j; char *grpname = NULL; int ret = 0; alpm_db_t *db_local = alpm_option_get_localdb(config->handle); if(targets == NULL) { for(j = alpm_db_get_groupcache(db_local); j; j = alpm_list_next(j)) { alpm_group_t *grp = alpm_list_getdata(j); const alpm_list_t *p; for(p = grp->packages; p; p = alpm_list_next(p)) { alpm_pkg_t *pkg = alpm_list_getdata(p); printf("%s %s\n", grp->name, alpm_pkg_get_name(pkg)); } } } else { for(i = targets; i; i = alpm_list_next(i)) { alpm_group_t *grp; grpname = alpm_list_getdata(i); grp = alpm_db_readgroup(db_local, grpname); if(grp) { const alpm_list_t *p; for(p = grp->packages; p; p = alpm_list_next(p)) { if(!config->quiet) { printf("%s %s\n", grpname, alpm_pkg_get_name(alpm_list_getdata(p))); } else { printf("%s\n", alpm_pkg_get_name(alpm_list_getdata(p))); } } } else { pm_fprintf(stderr, ALPM_LOG_ERROR, _("group '%s' was not found\n"), grpname); ret++; } } } return ret; }
/** * @brief Upgrade a specified list of packages. * * @param targets a list of packages (as strings) to upgrade * * @return 0 on success, 1 on failure */ int pacman_upgrade(alpm_list_t *targets) { alpm_list_t *i, *data = NULL; pgp_verify_t check_sig = alpm_option_get_default_sigverify(config->handle); int retval = 0; if(targets == NULL) { pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); return 1; } /* Check for URL targets and process them */ for(i = targets; i; i = alpm_list_next(i)) { if(strstr(i->data, "://")) { char *str = alpm_fetch_pkgurl(config->handle, i->data); if(str == NULL) { pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", (char *)i->data, alpm_strerror(alpm_errno(config->handle))); return 1; } else { free(i->data); i->data = str; } } } /* Step 1: create a new transaction */ if(trans_init(config->flags) == -1) { return 1; } /* add targets to the created transaction */ for(i = targets; i; i = alpm_list_next(i)) { char *targ = alpm_list_getdata(i); pmpkg_t *pkg; if(alpm_pkg_load(config->handle, targ, 1, check_sig, &pkg) != 0) { pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerror(alpm_errno(config->handle))); trans_release(); return 1; } if(alpm_add_pkg(config->handle, pkg) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerror(alpm_errno(config->handle))); alpm_pkg_free(pkg); trans_release(); return 1; } } /* Step 2: "compute" the transaction based on targets and flags */ /* TODO: No, compute nothing. This is stupid. */ if(alpm_trans_prepare(config->handle, &data) == -1) { enum _pmerrno_t err = alpm_errno(config->handle); pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerror(err)); switch(err) { case PM_ERR_PKG_INVALID_ARCH: for(i = data; i; i = alpm_list_next(i)) { char *pkg = alpm_list_getdata(i); printf(_(":: package %s does not have a valid architecture\n"), pkg); } break; case PM_ERR_UNSATISFIED_DEPS: for(i = data; i; i = alpm_list_next(i)) { pmdepmissing_t *miss = alpm_list_getdata(i); char *depstring = alpm_dep_compute_string(miss->depend); /* TODO indicate if the error was a virtual package or not: * :: %s: requires %s, provided by %s */ printf(_(":: %s: requires %s\n"), miss->target, depstring); free(depstring); } break; case PM_ERR_CONFLICTING_DEPS: for(i = data; i; i = alpm_list_next(i)) { pmconflict_t *conflict = alpm_list_getdata(i); if(strcmp(conflict->package1, conflict->reason) == 0 || strcmp(conflict->package2, conflict->reason) == 0) { printf(_(":: %s and %s are in conflict\n"), conflict->package1, conflict->package2); } else { printf(_(":: %s and %s are in conflict (%s)\n"), conflict->package1, conflict->package2, conflict->reason); } } break; default: break; } trans_release(); FREELIST(data); return 1; } /* Step 3: perform the installation */ alpm_list_t *packages = alpm_trans_get_add(config->handle); if(config->print) { print_packages(packages); trans_release(); return 0; } /* print targets and ask user confirmation */ if(packages == NULL) { /* we are done */ printf(_(" there is nothing to do\n")); trans_release(); return retval; } display_targets(alpm_trans_get_remove(config->handle), 0); display_targets(alpm_trans_get_add(config->handle), 1); printf("\n"); int confirm = yesno(_("Proceed with installation?")); if(!confirm) { trans_release(); return retval; } if(alpm_trans_commit(config->handle, &data) == -1) { enum _pmerrno_t err = alpm_errno(config->handle); pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), alpm_strerror(err)); switch(err) { case PM_ERR_FILE_CONFLICTS: for(i = data; i; i = alpm_list_next(i)) { pmfileconflict_t *conflict = alpm_list_getdata(i); switch(conflict->type) { case PM_FILECONFLICT_TARGET: printf(_("%s exists in both '%s' and '%s'\n"), conflict->file, conflict->target, conflict->ctarget); break; case PM_FILECONFLICT_FILESYSTEM: printf(_("%s: %s exists in filesystem\n"), conflict->target, conflict->file); break; } } break; case PM_ERR_PKG_INVALID: case PM_ERR_DLT_INVALID: for(i = data; i; i = alpm_list_next(i)) { char *filename = alpm_list_getdata(i); printf(_("%s is invalid or corrupted\n"), filename); } break; default: break; } FREELIST(data); trans_release(); return 1; } if(trans_release() == -1) { retval = 1; } return retval; }
/** * @brief Remove a specified list of packages. * * @param targets a list of packages (as strings) to remove from the system * * @return 0 on success, 1 on failure */ int pacman_remove(alpm_list_t *targets) { int retval = 0; alpm_list_t *i, *data = NULL; if(targets == NULL) { pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); return(1); } /* Step 0: create a new transaction */ if(trans_init(PM_TRANS_TYPE_REMOVE, config->flags) == -1) { return(1); } /* Step 1: add targets to the created transaction */ for(i = targets; i; i = alpm_list_next(i)) { char *targ = alpm_list_getdata(i); if(alpm_trans_addtarget(targ) == -1) { if(pm_errno == PM_ERR_PKG_NOT_FOUND) { printf(_("%s not found, searching for group...\n"), targ); pmgrp_t *grp = alpm_db_readgrp(db_local, targ); if(grp == NULL) { pm_fprintf(stderr, PM_LOG_ERROR, _("'%s': not found in local db\n"), targ); retval = 1; goto cleanup; } else { alpm_list_t *p, *pkgnames = NULL; /* convert packages to package names */ for(p = alpm_grp_get_pkgs(grp); p; p = alpm_list_next(p)) { pmpkg_t *pkg = alpm_list_getdata(p); pkgnames = alpm_list_add(pkgnames, (void *)alpm_pkg_get_name(pkg)); } printf(_(":: group %s:\n"), targ); list_display(" ", pkgnames); int all = yesno(1, _(" Remove whole content?")); for(p = pkgnames; p; p = alpm_list_next(p)) { char *pkgn = alpm_list_getdata(p); if(all || yesno(1, _(":: Remove %s from group %s?"), pkgn, targ)) { if(alpm_trans_addtarget(pkgn) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); retval = 1; alpm_list_free(pkgnames); goto cleanup; } } } alpm_list_free(pkgnames); } } else { pm_fprintf(stderr, PM_LOG_ERROR, "'%s': %s\n", targ, alpm_strerrorlast()); retval = 1; goto cleanup; } } } /* Step 2: prepare the transaction based on its type, targets and flags */ if(alpm_trans_prepare(&data) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, _("failed to prepare transaction (%s)\n"), alpm_strerrorlast()); switch(pm_errno) { case PM_ERR_UNSATISFIED_DEPS: for(i = data; i; i = alpm_list_next(i)) { pmdepmissing_t *miss = alpm_list_getdata(i); pmdepend_t *dep = alpm_miss_get_dep(miss); char *depstring = alpm_dep_get_string(dep); printf(_(":: %s: requires %s\n"), alpm_miss_get_target(miss), depstring); free(depstring); } FREELIST(data); break; default: break; } retval = 1; goto cleanup; } /* Warn user in case of dangerous operation */ if(config->flags & PM_TRANS_FLAG_RECURSE || config->flags & PM_TRANS_FLAG_CASCADE) { /* list transaction targets */ alpm_list_t *pkglist = alpm_trans_get_pkgs(); display_targets(pkglist, 0); printf("\n"); /* get confirmation */ if(yesno(1, _("Do you want to remove these packages?")) == 0) { retval = 1; goto cleanup; } } /* Step 3: actually perform the removal */ if(alpm_trans_commit(NULL) == -1) { pm_fprintf(stderr, PM_LOG_ERROR, _("failed to commit transaction (%s)\n"), alpm_strerrorlast()); retval = 1; } /* Step 4: release transaction resources */ cleanup: if(trans_release() == -1) { retval = 1; } return(retval); }
int pacman_query(alpm_list_t *targets) { int ret = 0; int match = 0; alpm_list_t *i; alpm_pkg_t *pkg = NULL; alpm_db_t *db_local; /* First: operations that do not require targets */ /* search for a package */ if(config->op_q_search) { ret = query_search(targets); return ret; } /* looking for groups */ if(config->group) { ret = query_group(targets); return ret; } if(config->op_q_foreign || config->op_q_upgrade) { if(check_syncdbs(1, 1)) { return 1; } } db_local = alpm_option_get_localdb(config->handle); /* operations on all packages in the local DB * valid: no-op (plain -Q), list, info, check * invalid: isfile, owns */ if(targets == NULL) { if(config->op_q_isfile || config->op_q_owns) { pm_printf(ALPM_LOG_ERROR, _("no targets specified (use -h for help)\n")); return 1; } for(i = alpm_db_get_pkgcache(db_local); i; i = alpm_list_next(i)) { pkg = alpm_list_getdata(i); if(filter(pkg)) { int value = display(pkg); if(value != 0) { ret = 1; } match = 1; } } if(!match) { ret = 1; } return ret; } /* Second: operations that require target(s) */ /* determine the owner of a file */ if(config->op_q_owns) { ret = query_fileowner(targets); return ret; } /* operations on named packages in the local DB * valid: no-op (plain -Q), list, info, check */ for(i = targets; i; i = alpm_list_next(i)) { char *strname = alpm_list_getdata(i); if(config->op_q_isfile) { alpm_pkg_load(config->handle, strname, 1, 0, &pkg); } else { pkg = alpm_db_get_pkg(db_local, strname); } if(pkg == NULL) { switch(alpm_errno(config->handle)) { case ALPM_ERR_PKG_NOT_FOUND: pm_fprintf(stderr, ALPM_LOG_ERROR, _("package '%s' was not found\n"), strname); if(!config->op_q_isfile && access(strname, R_OK) == 0) { pm_fprintf(stderr, ALPM_LOG_WARNING, _("'%s' is a file, you might want to use %s.\n"), strname, "-p/--file"); } break; default: pm_fprintf(stderr, ALPM_LOG_ERROR, _("could not load package '%s': %s\n"), strname, alpm_strerror(alpm_errno(config->handle))); break; } ret = 1; continue; } if(filter(pkg)) { int value = display(pkg); if(value != 0) { ret = 1; } match = 1; } if(config->op_q_isfile) { alpm_pkg_free(pkg); pkg = NULL; } } if(!match) { ret = 1; } return ret; }
static int query_fileowner(alpm_list_t *targets) { int ret = 0; char path[PATH_MAX]; const char *root; size_t rootlen; alpm_list_t *t; alpm_db_t *db_local; /* This code is here for safety only */ if(targets == NULL) { pm_fprintf(stderr, ALPM_LOG_ERROR, _("no file was specified for --owns\n")); return 1; } /* Set up our root path buffer. We only need to copy the location of root in * once, then we can just overwrite whatever file was there on the previous * iteration. */ root = alpm_option_get_root(config->handle); rootlen = strlen(root); if(rootlen + 1 > PATH_MAX) { /* we are in trouble here */ pm_fprintf(stderr, ALPM_LOG_ERROR, _("path too long: %s%s\n"), root, ""); return 1; } strcpy(path, root); db_local = alpm_option_get_localdb(config->handle); for(t = targets; t; t = alpm_list_next(t)) { char *filename, *dname, *rpath; const char *bname; struct stat buf; alpm_list_t *i; int found = 0; filename = strdup(alpm_list_getdata(t)); if(lstat(filename, &buf) == -1) { /* if it is not a path but a program name, then check in PATH */ if(strchr(filename, '/') == NULL) { if(search_path(&filename, &buf) == -1) { pm_fprintf(stderr, ALPM_LOG_ERROR, _("failed to find '%s' in PATH: %s\n"), filename, strerror(errno)); ret++; free(filename); continue; } } else { pm_fprintf(stderr, ALPM_LOG_ERROR, _("failed to read file '%s': %s\n"), filename, strerror(errno)); ret++; free(filename); continue; } } if(S_ISDIR(buf.st_mode)) { pm_fprintf(stderr, ALPM_LOG_ERROR, _("cannot determine ownership of directory '%s'\n"), filename); ret++; free(filename); continue; } bname = mbasename(filename); dname = mdirname(filename); /* for files in '/', there is no directory name to match */ if(strcmp(dname, "") == 0) { rpath = NULL; } else { rpath = resolve_path(dname); if(!rpath) { pm_fprintf(stderr, ALPM_LOG_ERROR, _("cannot determine real path for '%s': %s\n"), filename, strerror(errno)); free(filename); free(dname); free(rpath); ret++; continue; } } free(dname); for(i = alpm_db_get_pkgcache(db_local); i && !found; i = alpm_list_next(i)) { alpm_pkg_t *info = alpm_list_getdata(i); alpm_filelist_t *filelist = alpm_pkg_get_files(info); size_t j; for(j = 0; j < filelist->count; j++) { const alpm_file_t *file = filelist->files + j; char *ppath, *pdname; const char *pkgfile = file->name; /* avoid the costly resolve_path usage if the basenames don't match */ if(strcmp(mbasename(pkgfile), bname) != 0) { continue; } /* for files in '/', there is no directory name to match */ if(!rpath) { print_query_fileowner(filename, info); found = 1; continue; } if(rootlen + 1 + strlen(pkgfile) > PATH_MAX) { pm_fprintf(stderr, ALPM_LOG_ERROR, _("path too long: %s%s\n"), root, pkgfile); } /* concatenate our file and the root path */ strcpy(path + rootlen, pkgfile); pdname = mdirname(path); ppath = resolve_path(pdname); free(pdname); if(ppath && strcmp(ppath, rpath) == 0) { print_query_fileowner(filename, info); found = 1; } free(ppath); } } if(!found) { pm_fprintf(stderr, ALPM_LOG_ERROR, _("No package owns %s\n"), filename); ret++; } free(filename); free(rpath); } return ret; }
int pacman_query(alpm_list_t *targets) { int ret = 0; int match = 0; alpm_list_t *i; alpm_pkg_t *pkg = NULL; alpm_db_t *db_local; /* First: operations that do not require targets */ /* search for a package */ if(config->op_q_search) { ret = query_search(targets); return ret; } /* looking for groups */ if(config->group) { ret = query_group(targets); return ret; } if(config->op_q_foreign || config->op_q_upgrade) { if(check_syncdbs(1, 1)) { return 1; } } db_local = alpm_option_get_localdb(config->handle); /* operations on all packages in the local DB * valid: no-op (plain -Q), list, info, check * invalid: isfile, owns */ if(targets == NULL) { if(config->op_q_isfile || config->op_q_owns) { pm_printf(ALPM_LOG_ERROR, _("no targets specified (use -h for help)\n")); return 1; } for(i = alpm_db_get_pkgcache(db_local); i; i = alpm_list_next(i)) { pkg = alpm_list_getdata(i); if(filter(pkg)) { int value = display(pkg); if(value != 0) { ret = 1; } match = 1; } } if(!match) { ret = 1; } return ret; } /* Second: operations that require target(s) */ /* determine the owner of a file */ if(config->op_q_owns) { ret = query_fileowner(targets); return ret; } /* operations on named packages in the local DB * valid: no-op (plain -Q), list, info, check */ for(i = targets; i; i = alpm_list_next(i)) { char *strname = alpm_list_getdata(i); if(config->op_q_isfile) { alpm_pkg_load(config->handle, strname, 1, 0, &pkg); } else { pkg = alpm_db_get_pkg(db_local, strname); } if(pkg == NULL) { pm_fprintf(stderr, ALPM_LOG_ERROR, _("package \"%s\" not found\n"), strname); ret = 1; continue; } if(filter(pkg)) { int value = display(pkg); if(value != 0) { ret = 1; } match = 1; } if(config->op_q_isfile) { alpm_pkg_free(pkg); pkg = NULL; } } if(!match) { ret = 1; } return ret; }