Beispiel #1
0
/* Extracts the downloaded archive and removes it upon success.
 * Assumed to be in destination directory before calling this.
 * Returns -1 on fatal errors, > 0 on extraction errors, 0 on success.
 */
int extract_file(const char *filename)
{
	/* Extract the archive */
	struct archive *archive;
	struct archive_entry *entry;
	int ret;
	int errors = 0;
	int extract_flags = ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME;

	archive = archive_read_new();
	if (!archive) {
		return error(PW_ERR_ARCHIVE_CREATE);
	}

	archive_read_support_compression_all(archive);
	archive_read_support_format_all(archive);
	ret = archive_read_open_filename(archive, filename, 16384);

	if (ret != ARCHIVE_OK) {
		return error(PW_ERR_ARCHIVE_OPEN);
	}

	while (archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
		ret = archive_read_extract(archive, entry, extract_flags);

		if (ret == ARCHIVE_WARN && archive_errno(archive) != ENOSPC) {
			pw_fprintf(PW_LOG_WARNING, stderr,
					   "warning given when extracting %s: %s\n",
					   archive_entry_pathname(entry),
					   archive_error_string(archive));

		} else if (ret != ARCHIVE_OK) {
			pw_fprintf(PW_LOG_ERROR, stderr, "Could not extract %s\n",
					   archive_entry_pathname(entry));
			++errors;
		}

		if (config->verbose) {
			printf("X %s\n", archive_entry_pathname(entry));
		}
	}

	archive_read_finish(archive);

	/* Everything successful. Remove the file */
	unlink(filename);
	return errors;
}
Beispiel #2
0
/* From git */
int wait_or_whine(pid_t pid, char *argv0)
{
	int status, ret = 0;
	pid_t waiting;

	while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
		;

	if (waiting < 0) {
		return error(PW_ERR_WAITPID_FAILED);
	} else if (waiting != pid) {
		return error(PW_ERR_WAITPID_CONFUSED);
	} else if (WIFSIGNALED(status)) {
		ret = WTERMSIG(status);
		ret -= 127;
		RET_ERR(PW_ERR_WAITPID_SIGNAL, ret);
	} else if (WIFEXITED(status)) {
		ret = WEXITSTATUS(status);

		if (ret == 127) {
			ret = -1;
			pw_fprintf(PW_LOG_ERROR, stderr, "Failed to execute %s\n",
					   argv0);
		}

	} else {
		return error(PW_ERR_WAITPID_CONFUSED);
	}

	return ret;
}
Beispiel #3
0
int powaur_list_aur(void)
{
    struct pw_hashdb *hashdb = build_hashdb();
    if (!hashdb) {
        pw_fprintf(PW_LOG_ERROR, stderr, "Failed to build hashdb!\n");
        return -1;
    }

    hash_walk(hashdb->aur, pkgpair_print_color);
    hashdb_free(hashdb);
    return 0;
}
Beispiel #4
0
int powaur_crawl(alpm_list_t *targets)
{
    int ret = 0;
    char cwd[PATH_MAX];
    if (!getcwd(cwd, PATH_MAX)) {
        return error(PW_ERR_GETCWD);
    }

    if (chdir(powaur_dir)) {
        return error(PW_ERR_CHDIR, powaur_dir);
    }

    struct pw_hashdb *hashdb = build_hashdb();
    if (!hashdb) {
        pw_fprintf(PW_LOG_ERROR, stderr, "Unable to build hash database!\n");
        ret = -1;
    }

    alpm_list_t *i, *target_pkgs;
    struct graph *graph;
    struct stack *topost = stack_new(sizeof(int));
    int have_cycles;
    for (i = targets; i; i = i->next) {
        stack_reset(topost);
        graph = NULL;
        target_pkgs = alpm_list_add(NULL, i->data);
        build_dep_graph(&graph, hashdb, target_pkgs, RESOLVE_THOROUGH);
        if (have_cycles) {
            printf("Cyclic dependencies for package \"%s\"\n", i->data);
        }

        graph_toposort(graph, topost);
        if (stack_empty(topost)) {
            printf("Package \"%s\" has no dependencies.\n", i->data);
        } else {
            printf("\n");
            pw_printf(PW_LOG_INFO, "\"%s\" topological order: ", i->data);
            print_topo_order(graph, topost);
        }

        graph_free(graph);
        alpm_list_free(target_pkgs);
    }

    stack_free(topost);
    hashdb_free(hashdb);

    if (chdir(cwd)) {
        return error(PW_ERR_RESTORECWD);
    }
    return ret;
}
Beispiel #5
0
/* -Qi */
static int query_info(alpm_db_t *localdb, alpm_list_t *targets)
{
    int ret, hits, found, pkgcount;
    alpm_list_t *i, *k, *dbcache;
    alpm_pkg_t *pkg;

    ret = pkgcount = hits = found = 0;
    dbcache = alpm_db_get_pkgcache(localdb);

    for (i = targets; i; i = i->next, ++pkgcount) {
        found = 0;
        for (k = dbcache; k; k = k->next) {
            pkg = k->data;
            if (!strcmp(i->data, alpm_pkg_get_name(pkg))) {
                if (hits++) {
                    printf("\n");
                }

                found = 1;
                pacman_pkgdump(pkg, PKG_FROM_LOCAL);
                break;
            }
        }

        if (!found) {
            if (pkgcount) {
                printf("\n");
            }

            ret = -1;
            pw_fprintf(PW_LOG_ERROR, stderr, "package %s not found\n", i->data);
        }
    }

    return ret;
}
Beispiel #6
0
void build_dep_graph(struct graph **graph, struct pw_hashdb *hashdb,
                     alpm_list_t *targets, int resolve_lvl)
{
    if (!graph) {
        return;
    }

    if (!*graph) {
        *graph = graph_new((pw_hash_fn) sdbm, (pw_hashcmp_fn) strcmp);
    }

    struct stack *st = stack_new(sizeof(struct pkgpair));
    struct hash_table *resolved = hash_new(HASH_TABLE, (pw_hash_fn) sdbm,
                                           (pw_hashcmp_fn) strcmp);
    struct hash_table *immediate = hash_new(HASH_TABLE, (pw_hash_fn) sdbm,
                                            (pw_hashcmp_fn) strcmp);
    int ret;
    struct pkgpair pkgpair, deppkg;
    alpm_list_t *i;
    alpm_list_t *deps;

    CURL *curl;
    curl = curl_easy_new();
    if (!curl) {
        error(PW_ERR_CURL_INIT);
        return;
    }

    /* Push all packages down stack */
    for (i = targets; i; i = i->next) {
        pkgpair.pkgname = i->data;
        pkgpair.pkg = NULL;
        stack_push(st, &pkgpair);
    }

    while (!stack_empty(st)) {
        stack_pop(st, &pkgpair);
        deps = NULL;

        if (hash_search(resolved, (void *) pkgpair.pkgname)) {
            goto cleanup_deps;
        }

        ret = crawl_resolve(curl, hashdb, &pkgpair, &deps, resolve_lvl);
        if (ret) {
            pw_fprintf(PW_LOG_ERROR, stderr, "Error in resolving packages.\n");
            goto cleanup;
        }

        for (i = deps; i; i = i->next) {
            deppkg.pkgname = i->data;
            deppkg.pkg = NULL;

            /* immediate vs thorough resolve */
            should_we_continue_resolving(curl, hashdb, st, &deppkg, resolve_lvl);

            /* dep --> current */
            graph_add_edge(*graph, i->data, (void *) pkgpair.pkgname);
        }

        hash_insert(resolved, (void *) pkgpair.pkgname);

        /* Add immediate dependencies, for pretty printing purposes */
        add_immediate_deps(hashdb, pkgpair.pkgname, deps, immediate);
cleanup_deps:
        alpm_list_free(deps);
    }

cleanup:
    hash_free(resolved);
    hash_free(immediate);
    stack_free(st);
    curl_easy_cleanup(curl);
}
Beispiel #7
0
int powaur_query(alpm_list_t *targets)
{
    alpm_db_t *localdb = alpm_option_get_localdb(config->handle);
    if (!localdb) {
        return error(PW_ERR_INIT_LOCALDB);
    }

    alpm_list_t *dblist = NULL;
    alpm_list_t *i, *j, *dbcache;
    alpm_pkg_t *pkg, *spkg;
    int ret = 0, found;

    /* -i and -s conflicting options */
    if (config->op_q_info && config->op_q_search) {
        pw_fprintf(PW_LOG_ERROR, stderr, "-i (info) and -s (search) are "
                   "mutually exclusive.\n");
        return -1;
    }

    /* No targets */
    if (targets == NULL) {
        dblist = alpm_list_add(dblist, localdb);

        if (config->op_q_info) {
            /* -Qi, detailed info */
            ret = pacman_db_dump(PKG_FROM_LOCAL, DUMP_Q_INFO);
        } else if (config->op_q_search) {
            /* -Qs
             * repo/pkg ver (grp)
             * desc
             */
            ret = pacman_db_dump(PKG_FROM_LOCAL, DUMP_Q_SEARCH);
        } else {
            /* -Q
             * repo/pkg ver (grp)
             */
            ret = pacman_db_dump(PKG_FROM_LOCAL, DUMP_Q);
        }

        alpm_list_free(dblist);
        return ret;
    }

    if (config->op_q_info) {
        ret = query_info(localdb, targets);
    } else if (config->op_q_search) {
        ret = query_search(localdb, targets->data);
    } else {
        /* Plain -Q */
        alpm_list_t *sdbs = alpm_option_get_syncdbs(config->handle);
        dbcache = alpm_db_get_pkgcache(localdb);

        for (i = targets; i; i = i->next) {
            found = 0;
            for (j = dbcache; j; j = j->next) {
                pkg = j->data;
                if (!strcmp(i->data, alpm_pkg_get_name(pkg))) {
                    print_pkg_pretty(sdbs, pkg, DUMP_Q);
                    found = 1;
                    break;
                }
            }

            if (!found) {
                printf("package \"%s\" not found\n", i->data);
                ret = -1;
            }
        }
    }

    return ret;
}
Beispiel #8
0
/* fp is guaranteed to be non-NULL.
 * returns 0 on success, -1 on failure, 1 if not all options specified
 */
int parse_powaur_config(FILE *fp)
{
	int ret, parsed;
	char buf[PATH_MAX];
	char *line, *key, *val;
	size_t len;

	ret = parsed = 0;

	while (line = fgets(buf, PATH_MAX, fp)) {
		line = strtrim(line);
		len = strlen(line);

		/* Ignore empty lines and comments */
		if (!len || line[0] == '#') {
			continue;
		}

		val = strchr(line, '=');
		if (!val) {
			continue;
		}

		*val = 0;
		++val;

		key = strtrim(line);
		val = strtrim(val);

		if (!strcmp(key, "Editor")) {
			if (powaur_editor) {
				pw_fprintf(PW_LOG_ERROR, stderr, "%s%sRepeated Editor option!\n",
						   comstrs.tab, comstrs.tab);
				ret = -1;
				goto cleanup;
			}

			powaur_editor = strdup(val);
			if (!powaur_editor) {
				ret = -1;
				goto cleanup;
			}

			++parsed;
			pw_printf(PW_LOG_DEBUG, "%s%sParsed Editor = %s\n", comstrs.tab,
					  comstrs.tab, powaur_editor);

		} else if (!strcmp(key, "TmpDir")) {
			if (powaur_dir) {
				pw_fprintf(PW_LOG_ERROR, stderr, "%s%sRepeated TmpDir option!\n",
						   comstrs.tab, comstrs.tab);
				ret = -1;
				goto cleanup;
			}

			powaur_dir = strdup(val);
			if (!powaur_dir) {
				ret = -1;
				goto cleanup;
			}

			++parsed;
			pw_printf(PW_LOG_DEBUG, "%s%sParsed TmpDir = %s\n", comstrs.tab,
					  comstrs.tab, powaur_dir);
		}
	}

cleanup:

	if (ret) {
		if (!parsed) {
			free(powaur_editor);
			free(powaur_dir);
			powaur_editor = powaur_dir = NULL;
			return -1;
		} else {
			return 1;
		}
	}

	return 0;
}
Beispiel #9
0
/* returns 0 upon success.
 * returns -1 upon failure to change dir / download PKGBUILD / install package
 */
int powaur_sync(alpm_list_t *targets)
{
	alpm_list_t *i;
	int ret, status;
	char orgdir[PATH_MAX];
	CURL *curl;

	ret = status = 0;

	curl = curl_easy_new();
	if (!curl) {
		return error(PW_ERR_CURL_INIT);
	}

	/* Makes no sense to run info and search tgt */
	if (config->op_s_search && config->op_s_info) {
		pw_fprintf(PW_LOG_ERROR, stderr,
				   "-s (search) and -i (info) are mutually exclusive\n");
		ret = -1;
		goto final_cleanup;
	} else if (config->op_s_check && !config->op_s_upgrade) {
		pw_fprintf(PW_LOG_ERROR, stderr, "--check must be used with -u!\n");
		ret = -1;
		goto final_cleanup;
	}

	/* -Su, checks packages against AUR */
	if (config->op_s_upgrade) {
		ret = sync_upgrade(curl, targets);
		goto final_cleanup;
	}

	if (targets == NULL) {
		if (config->op_s_search) {
			ret = pacman_db_dump(PKG_FROM_SYNC, DUMP_S_SEARCH);
		} else if (config->op_s_info) {
			ret = pacman_db_dump(PKG_FROM_SYNC, DUMP_S_INFO);
		} else {
			pw_fprintf(PW_LOG_ERROR, stderr, "No targets specified for sync\n");
			ret = -1;
		}

		goto final_cleanup;
	}

	if (config->op_s_search) {
		/* Search for packages on AUR */
		ret = sync_search(curl, targets);
		goto final_cleanup;
	} else if (config->op_s_info) {
		ret = sync_info(curl, targets);
		goto final_cleanup;
	}

	/* Save our current directory */
	if (!getcwd(orgdir, PATH_MAX)) {
		ret = error(PW_ERR_GETCWD);
		goto final_cleanup;
	}

	if (ret = chdir(powaur_dir)) {
		error(PW_ERR_CHDIR, powaur_dir);
		goto cleanup;
	}

	/* -S */
	ret = sync_targets(curl, targets);

cleanup:
	if (chdir(orgdir)) {
		ret = error(PW_ERR_RESTORECWD);
	}

final_cleanup:
	curl_easy_cleanup(curl);
	return ret ? -1 : 0;
}
Beispiel #10
0
/* Normal -S, install packages from AUR
 * returns 0 on success, -1 on failure
 */
static int sync_targets(CURL *curl, alpm_list_t *targets)
{
	struct pw_hashdb *hashdb = build_hashdb();
	struct pkgpair pkgpair;
	struct pkgpair *pkgpair_ptr;
	struct aurpkg_t *aurpkg;
	alpm_pkg_t *lpkg;
	alpm_list_t *i;
	alpm_list_t *reinstall, *new_packages, *upgrade, *downgrade, *not_aur;
	alpm_list_t *aurpkg_list, *final_targets;
	int vercmp;
	int joined = 0, ret = 0;

	reinstall = new_packages = upgrade = downgrade = aurpkg_list = not_aur = NULL;
	final_targets = NULL;
	if (!hashdb) {
		pw_fprintf(PW_LOG_ERROR, stderr, "Failed to create hashdb\n");
		goto cleanup;
	}

	for (i = targets; i; i = i->next) {
		aurpkg_list = query_aur(curl, i->data, AUR_QUERY_INFO);
		if (!aurpkg_list) {
			not_aur = alpm_list_add(not_aur, i->data);
			goto free_aurpkg;
		}

		/* Check version string */
		pkgpair.pkgname = i->data;
		pkgpair_ptr = hash_search(hashdb->aur, &pkgpair);

		/* Locally installed AUR */
		if (pkgpair_ptr) {
			aurpkg = aurpkg_list->data;
			lpkg = pkgpair_ptr->pkg;
			vercmp = alpm_pkg_vercmp(aurpkg->version, alpm_pkg_get_version(lpkg));

			if (vercmp > 0) {
				upgrade = alpm_list_add(upgrade, i->data);
			} else if (vercmp == 0) {
				reinstall = alpm_list_add(reinstall, i->data);
			} else {
				downgrade = alpm_list_add(downgrade, i->data);
			}
		} else {
			new_packages = alpm_list_add(new_packages, i->data);
		}

free_aurpkg:
		alpm_list_free_inner(aurpkg_list, (alpm_list_fn_free) aurpkg_free);
		alpm_list_free(aurpkg_list);
	}

	if (not_aur) {
		printf("\n%sThese packages are not from the AUR:%s\n", color.bred, color.nocolor);
		print_list(not_aur);
	}

	if (downgrade) {
		printf("\n%sLocally installed but newer than AUR, ignoring:%s\n",
			   color.bcyan, color.nocolor);
		print_list(downgrade);
	}

	if (reinstall) {
		printf("\n%sReinstalling:%s\n", color.byellow, color.nocolor);
		print_list(reinstall);
	}

	if (upgrade) {
		printf("\n%sUpgrading:%s\n", color.bblue, color.nocolor);
		print_list(upgrade);
	}

	if (new_packages) {
		printf("\n%sSyncing:%s\n", color.bmag, color.nocolor);
		print_list(new_packages);
	}

	printf("\n");
	if (config->noconfirm || yesno("Do you wish to proceed?")) {
		final_targets = alpm_list_join(reinstall, upgrade);
		final_targets = alpm_list_join(final_targets, new_packages);
		joined = 1;
		ret = upgrade_pkgs(final_targets, hashdb);
	}

cleanup:
	hashdb_free(hashdb);
	alpm_list_free(downgrade);
	alpm_list_free(not_aur);

	if (joined) {
		alpm_list_free(final_targets);
	} else {
		alpm_list_free(reinstall);
		alpm_list_free(new_packages);
		alpm_list_free(upgrade);
	}

	return ret;
}
Beispiel #11
0
/* -Su, checks AUR packages */
static int sync_upgrade(CURL *curl, alpm_list_t *targets)
{
	int ret = 0;
	int cnt = 0;
	int upgrade_all;
	struct pkgpair pkgpair;
	struct pw_hashdb *hashdb = build_hashdb();
	if (!hashdb) {
		pw_fprintf(PW_LOG_ERROR, stderr, "Failed to build hash database.");
		return -1;
	}

	/* Make sure that packages are from AUR */
	alpm_list_t *i, *new_targs = NULL;
	for (i = targets; i; i = i->next) {
		pkgpair.pkgname = i->data;
		if (!hash_search(hashdb->aur, &pkgpair)) {
			if (cnt++) {
				printf(", ");
			}

			pw_printf(PW_LOG_NORM, "%s", i->data);
		} else {
			new_targs = alpm_list_add(new_targs, i->data);
		}
	}

	if (cnt > 1) {
		printf(" are not AUR packages and will not be checked.\n");
	} else if (cnt == 1) {
		printf(" is not an AUR package and will not be checked.\n");
	}

	alpm_list_t *outdated_pkgs = NULL;
	if (!targets) {
		/* Check all AUR packages */
		outdated_pkgs = get_outdated_pkgs(curl, hashdb, NULL);
	} else {
		if (!new_targs) {
			goto cleanup;
		}

		outdated_pkgs = get_outdated_pkgs(curl, hashdb, new_targs);
	}

	if (!outdated_pkgs) {
		pw_printf(PW_LOG_INFO, "All AUR packages are up to date.\n");
		goto cleanup;
	}

	printf("\n");
	pw_printf(PW_LOG_INFO, "Targets:\n");
	print_aurpkg_list(outdated_pkgs);
	printf("\n");

	/* --check, don't upgrade */
	if (config->op_s_check) {
		goto cleanup;
	}

	upgrade_all = config->noconfirm || yesno("Do you wish to upgrade the above packages?");
	if (upgrade_all) {
		/* Experimental */
		alpm_list_t *final_targets = NULL;
		struct aurpkg_t *aurpkg;
		for (i = outdated_pkgs; i; i = i->next) {
			aurpkg = i->data;
			final_targets = alpm_list_add(final_targets, aurpkg->name);
		}
		ret = upgrade_pkgs(final_targets, hashdb);
		alpm_list_free(final_targets);
	}

cleanup:
	alpm_list_free_inner(outdated_pkgs, (alpm_list_fn_free) aurpkg_free);
	alpm_list_free(outdated_pkgs);
	alpm_list_free(new_targs);
	hashdb_free(hashdb);
	return ret;
}
Beispiel #12
0
/* Returns a list of outdated AUR packages among targets or all AUR packages.
 * The list and the packages are to be freed by the caller.
 *
 * @param curl curl easy handle
 * @param targets list of strings (package names) that are _definitely_ AUR packages
 */
static alpm_list_t *get_outdated_pkgs(CURL *curl, struct pw_hashdb *hashdb,
									  alpm_list_t *targets)
{
	alpm_list_t *i;
	alpm_list_t *outdated_pkgs = NULL;
	alpm_list_t *pkglist, *targs;
	struct pkgpair pkgpair;
	struct pkgpair *pkgpair_ptr;
	struct aurpkg_t *aurpkg;
	const char *pkgname, *pkgver;

	if (targets) {
		targs = targets;
	} else {
		targs = NULL;
		alpm_list_t *tmp_targs = hash_to_list(hashdb->aur);
		for (i = tmp_targs; i; i = i->next) {
			pkgpair_ptr = i->data;
			targs = alpm_list_add(targs, (void *) pkgpair_ptr->pkgname);
		}
		alpm_list_free(tmp_targs);
	}

	for (i = targs; i; i = i->next) {
		pkglist = query_aur(curl, i->data, AUR_QUERY_INFO);
		if (!pkglist) {
			continue;
		}

		pkgpair.pkgname = i->data;
		pkgpair_ptr = hash_search(hashdb->aur, &pkgpair);
		if (!pkgpair_ptr) {
			/* Shouldn't happen */
			pw_fprintf(PW_LOG_ERROR, stderr, "Unable to find AUR package \"%s\""
					   "in hashdb!\n", i->data);
		}

		aurpkg = pkglist->data;
		pkgver = alpm_pkg_get_version(pkgpair_ptr->pkg);
		pkgname = i->data;

		if (alpm_pkg_vercmp(aurpkg->version, pkgver) > 0) {
			/* Just show outdated package for now */
			pw_printf(PW_LOG_INFO, "%s %s is outdated, %s%s%s%s is available\n",
					  pkgname, pkgver, color.bred, aurpkg->version,
					  color.nocolor, color.bold);

			/* Add to upgrade list */
			outdated_pkgs = alpm_list_add(outdated_pkgs, aurpkg);
			pkglist->data = NULL;
		} else if (config->verbose) {
			pw_printf(PW_LOG_INFO, "%s %s is up to date.\n", pkgname,
					  pkgver);
		}

		alpm_list_free_inner(pkglist, (alpm_list_fn_free) aurpkg_free);
		alpm_list_free(pkglist);
	}

	if (!targets) {
		alpm_list_free(targs);
	}
	return outdated_pkgs;
}
Beispiel #13
0
int powaur_backup(alpm_list_t *targets)
{
	int ret = 0;
	char localdb[PATH_MAX];
	struct archive *a;
	struct archive_entry *entry;
	struct stat st;

	char cwd[PATH_MAX];
	char backup_dest[PATH_MAX];
	char backup[MINI_BUFSZ];

	time_t time_now;
	struct tm tm_st;

	if (targets != NULL && alpm_list_count(targets) != 1) {
		pw_fprintf(PW_LOG_ERROR, stderr, "-B only takes 1 argument.\n");
		return -1;
	}

	a = archive_write_new();
	if (!a) {
		return error(PW_ERR_ARCHIVE_CREATE);
	}

	archive_write_set_compression_bzip2(a);
	archive_write_set_format_pax_restricted(a);

	/* Filename = pacman-YYYY-MM-DD_HHhMM.tar.bz2 */
	time(&time_now);
	localtime_r(&time_now, &tm_st);
	strftime(backup, MINI_BUFSZ, "pacman-%Y-%m-%d_%Hh%M.tar.bz2", &tm_st);

	if (!getcwd(cwd, PATH_MAX)) {
		error(PW_ERR_GETCWD);
		ret = -1;
		goto cleanup;
	}

	/* Get full path */
	if (targets) {
		snprintf(backup_dest, PATH_MAX, "%s/%s", targets->data, backup);
	} else {
		snprintf(backup_dest, PATH_MAX, "%s/%s", cwd, backup);
	}

	if (archive_write_open_filename(a, backup_dest) != ARCHIVE_OK) {
		PW_SETERRNO(PW_ERR_ARCHIVE_OPEN);
		ret = -1;
		goto cleanup;
	}

	if (ret = chdir(pacman_dbpath)) {
		error(PW_ERR_CHDIR, pacman_dbpath);
		goto restore_cwd;
	}

	/* Create entry for the current directory. */
	entry = archive_entry_new();
	if (!entry) {
		error(PW_ERR_ARCHIVE_ENTRY);
		goto restore_cwd;
	}

	snprintf(localdb, PATH_MAX, "%s", "local");
	if (ret = stat(localdb, &st)) {
		error(PW_ERR_STAT, localdb);
		goto free_entry;
	}

	archive_entry_set_pathname(entry, localdb);
	archive_entry_copy_stat(entry, &st);
	archive_write_header(a, entry);

	pw_printf(PW_LOG_INFO, "Saving pacman database in %s\n", backup_dest);

	ret = write_dir_archive(localdb, a);

	if (!ret) {
		pw_printf(PW_LOG_INFO, "Pacman database successfully saved in %s\n",
				  backup_dest);
	} else {
		pw_fprintf(PW_LOG_ERROR, stderr, "Pacman database not saved.\n");
	}

free_entry:
	archive_entry_free(entry);

restore_cwd:
	if (chdir(cwd)) {
		PW_SETERRNO(PW_ERR_RESTORECWD);
		ret = -1;
	}

cleanup:
	archive_write_finish(a);
	return ret;
}
Beispiel #14
0
/* Writes a directory to an archive */
static int write_dir_archive(char *dirname, struct archive *a)
{
	int ret = 0;

	struct archive_entry *entry;
	struct dirent *dir_entry;
	DIR *dirp;
	struct stat st;

	char filename[PATH_MAX];
	char buf[PATH_MAX];
	int fd;
	ssize_t bytesread;

	dirp = opendir(dirname);
	if (!dirp) {
		return error(PW_ERR_OPENDIR);
	}

	while (dir_entry = readdir(dirp)) {
		if (!strcmp(dir_entry->d_name, ".") || !strcmp(dir_entry->d_name, "..")) {
			continue;
		}

		snprintf(filename, PATH_MAX, "%s/%s", dirname, dir_entry->d_name);
		if (stat(filename, &st)) {
			pw_fprintf(PW_LOG_ERROR, stderr, "%s: Failed to stat file %s\n",
					   __func__, filename);
			ret = -1;
			goto free_entry;
		}

		entry = archive_entry_new();
		if (!entry) {
			pw_fprintf(PW_LOG_ERROR, stderr, "%s: Failed to create new entry\n",
					   __func__);
			ret = -1;
			goto free_entry;
		}

		archive_entry_set_pathname(entry, filename);
		archive_entry_copy_stat(entry, &st);
		archive_write_header(a, entry);

		if (st.st_mode & S_IFDIR) {
			/* Directory entry. NOTE: Recursion
			 * I don't really like recursion but there doesn't seem to be
			 * a more elegant way out.
			 */
			snprintf(filename, PATH_MAX, "%s/%s", dirname, dir_entry->d_name);
			if (ret = write_dir_archive(filename, a)) {
				goto free_entry;
			}

		} else {
			fd = open(filename, O_RDONLY);
			if (fd < 0) {
				pw_fprintf(PW_LOG_ERROR, stderr, "Cannot open %s\n", filename);
				goto free_entry;
			}

			while (bytesread = read(fd, buf, PATH_MAX)) {
				archive_write_data(a, buf, bytesread);
			}

			close(fd);
		}

free_entry:
		archive_entry_free(entry);
		entry = NULL;
	}

	closedir(dirp);
	return ret;
}