char * xbps_repository_pkg_path(struct xbps_handle *xhp, xbps_dictionary_t pkg_repod) { const char *pkgver, *arch, *repoloc; char *lbinpkg = NULL; assert(xhp); assert(xbps_object_type(pkg_repod) == XBPS_TYPE_DICTIONARY); if (!xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &pkgver)) return NULL; if (!xbps_dictionary_get_cstring_nocopy(pkg_repod, "architecture", &arch)) return NULL; if (!xbps_dictionary_get_cstring_nocopy(pkg_repod, "repository", &repoloc)) return NULL; if (xbps_repository_is_remote(repoloc)) { /* * First check if binpkg is available in cachedir. */ lbinpkg = xbps_xasprintf("%s/%s.%s.xbps", xhp->cachedir, pkgver, arch); if (access(lbinpkg, R_OK) == 0) return lbinpkg; free(lbinpkg); } /* * Local and remote repositories use the same path. */ return xbps_xasprintf("%s/%s.%s.xbps", repoloc, pkgver, arch); }
bool xbps_repo_store(struct xbps_handle *xhp, const char *repo) { char *url = NULL; assert(xhp); assert(repo); if (xhp->repositories == NULL) { xhp->repositories = xbps_array_create(); assert(xhp->repositories); } /* * If it's a local repo and path is relative, make it absolute. */ if (!xbps_repository_is_remote(repo)) { if (repo[0] != '/' && repo[0] != '\0') { if ((url = realpath(repo, NULL)) == NULL) xbps_dbg_printf(xhp, "[repo] %s: realpath %s\n", __func__, repo); } } if (xbps_match_string_in_array(xhp->repositories, url ? url : repo)) { xbps_dbg_printf(xhp, "[repo] `%s' already stored\n", url ? url : repo); if (url) free(url); return false; } if (xbps_array_add_cstring(xhp->repositories, url ? url : repo)) { xbps_dbg_printf(xhp, "[repo] `%s' stored successfully\n", url ? url : repo); if (url) free(url); return true; } if (url) free(url); return false; }
/* * Returns -1 on error, 0 if transfer was not necessary (local/remote * size and/or mtime match) and 1 if downloaded successfully. */ int HIDDEN xbps_repo_sync(struct xbps_handle *xhp, const char *uri) { const char *arch, *fetchstr = NULL; char *repodata, *lrepodir, *uri_fixedp; int rv = 0; assert(uri != NULL); /* ignore non remote repositories */ if (!xbps_repository_is_remote(uri)) return 0; uri_fixedp = xbps_get_remote_repo_string(uri); if (uri_fixedp == NULL) return -1; if (xhp->target_arch) arch = xhp->target_arch; else arch = xhp->native_arch; /* * Full path to repository directory to store the plist * index file. */ lrepodir = xbps_xasprintf("%s/%s", xhp->metadir, uri_fixedp); free(uri_fixedp); /* * Create repodir in metadir. */ if ((rv = xbps_mkpath(lrepodir, 0755)) == -1) { if (errno != EEXIST) { xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL, errno, NULL, "[reposync] failed " "to create repodir `%s': %s", lrepodir, strerror(errno)); free(lrepodir); return rv; } } if (chdir(lrepodir) == -1) { xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL, errno, NULL, "[reposync] failed to change dir to repodir `%s': %s", lrepodir, strerror(errno)); free(lrepodir); return -1; } free(lrepodir); /* * Remote repository plist index full URL. */ repodata = xbps_xasprintf("%s/%s-repodata", uri, arch); /* reposync start cb */ xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC, 0, repodata, NULL); /* * Download plist index file from repository. */ if ((rv = xbps_fetch_file(xhp, repodata, NULL)) == -1) { /* reposync error cb */ fetchstr = xbps_fetch_error_string(); xbps_set_cb_state(xhp, XBPS_STATE_REPOSYNC_FAIL, fetchLastErrCode != 0 ? fetchLastErrCode : errno, NULL, "[reposync] failed to fetch file `%s': %s", repodata, fetchstr ? fetchstr : strerror(errno)); } else if (rv == 1) rv = 0; free(repodata); return rv; }
struct xbps_repo * xbps_repo_open(struct xbps_handle *xhp, const char *url) { struct xbps_repo *repo; const char *arch; char *repofile; assert(xhp); assert(url); if (xhp->target_arch) arch = xhp->target_arch; else arch = xhp->native_arch; repo = calloc(1, sizeof(struct xbps_repo)); assert(repo); repo->fd = -1; repo->xhp = xhp; repo->uri = url; if (xbps_repository_is_remote(url)) { /* remote repository */ char *rpath; if ((rpath = xbps_get_remote_repo_string(url)) == NULL) { free(repo); return NULL; } repofile = xbps_xasprintf("%s/%s/%s-repodata", xhp->metadir, rpath, arch); free(rpath); repo->is_remote = true; } else { /* local repository */ repofile = xbps_repo_path(xhp, url); } /* * In memory repo sync. */ if (xhp->flags & XBPS_FLAG_REPOS_MEMSYNC) { if (repo_open_remote(repo)) return repo; goto out; } /* * Open the repository archive. */ repo->fd = open(repofile, O_RDONLY|O_CLOEXEC); if (repo->fd == -1) { int rv = errno; xbps_dbg_printf(xhp, "[repo] `%s' open repodata %s\n", repofile, strerror(rv)); goto out; } if (repo_open_local(repo, repofile)) { free(repofile); return repo; } out: free(repofile); xbps_repo_close(repo); return NULL; }
static int compute_transaction_stats(struct xbps_handle *xhp) { xbps_dictionary_t pkg_metad; xbps_object_iterator_t iter; xbps_object_t obj; struct statvfs svfs; uint64_t rootdir_free_size, tsize, dlsize, instsize, rmsize; uint32_t inst_pkgcnt, up_pkgcnt, cf_pkgcnt, rm_pkgcnt, dl_pkgcnt; const char *tract, *pkgver, *repo; inst_pkgcnt = up_pkgcnt = cf_pkgcnt = rm_pkgcnt = dl_pkgcnt = 0; rootdir_free_size = tsize = dlsize = instsize = rmsize = 0; iter = xbps_array_iter_from_dict(xhp->transd, "packages"); if (iter == NULL) return EINVAL; while ((obj = xbps_object_iterator_next(iter)) != NULL) { bool preserve = false; /* * Count number of pkgs to be removed, configured, * installed and updated. */ xbps_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver); xbps_dictionary_get_cstring_nocopy(obj, "transaction", &tract); xbps_dictionary_get_cstring_nocopy(obj, "repository", &repo); xbps_dictionary_get_bool(obj, "preserve", &preserve); if (strcmp(tract, "configure") == 0) { cf_pkgcnt++; continue; } else if (strcmp(tract, "install") == 0) { inst_pkgcnt++; } else if (strcmp(tract, "update") == 0) { up_pkgcnt++; } else if (strcmp(tract, "remove") == 0) { rm_pkgcnt++; } tsize = 0; if ((strcmp(tract, "install") == 0) || (strcmp(tract, "update") == 0)) { xbps_dictionary_get_uint64(obj, "installed_size", &tsize); instsize += tsize; if (xbps_repository_is_remote(repo) && !xbps_binpkg_exists(xhp, obj)) { xbps_dictionary_get_uint64(obj, "filename-size", &tsize); /* signature file: 512 bytes */ tsize += 512; dlsize += tsize; instsize += tsize; dl_pkgcnt++; xbps_dictionary_set_bool(obj, "download", true); } } /* * If removing or updating a package, get installed_size * from pkg's metadata dictionary. */ if ((strcmp(tract, "remove") == 0) || ((strcmp(tract, "update") == 0) && !preserve)) { char *pkgname; pkgname = xbps_pkg_name(pkgver); assert(pkgname); pkg_metad = xbps_pkgdb_get_pkg(xhp, pkgname); free(pkgname); if (pkg_metad == NULL) continue; xbps_dictionary_get_uint64(pkg_metad, "installed_size", &tsize); rmsize += tsize; } } xbps_object_iterator_release(iter); if (instsize > rmsize) { instsize -= rmsize; rmsize = 0; } else if (rmsize > instsize) { rmsize -= instsize; instsize = 0; } else { instsize = rmsize = 0; } if (!xbps_dictionary_set_uint32(xhp->transd, "total-install-pkgs", inst_pkgcnt)) return EINVAL; if (!xbps_dictionary_set_uint32(xhp->transd, "total-update-pkgs", up_pkgcnt)) return EINVAL; if (!xbps_dictionary_set_uint32(xhp->transd, "total-configure-pkgs", cf_pkgcnt)) return EINVAL; if (!xbps_dictionary_set_uint32(xhp->transd, "total-remove-pkgs", rm_pkgcnt)) return EINVAL; if (!xbps_dictionary_set_uint32(xhp->transd, "total-download-pkgs", dl_pkgcnt)) return EINVAL; if (!xbps_dictionary_set_uint64(xhp->transd, "total-installed-size", instsize)) return EINVAL; if (!xbps_dictionary_set_uint64(xhp->transd, "total-download-size", dlsize)) return EINVAL; if (!xbps_dictionary_set_uint64(xhp->transd, "total-removed-size", rmsize)) return EINVAL; /* Get free space from target rootdir: return ENOSPC if there's not enough space */ if (statvfs(xhp->rootdir, &svfs) == -1) { xbps_dbg_printf(xhp, "%s: statvfs failed: %s\n", __func__, strerror(errno)); return 0; } /* compute free space on disk */ rootdir_free_size = svfs.f_bfree * svfs.f_bsize; if (!xbps_dictionary_set_uint64(xhp->transd, "disk-free-size", rootdir_free_size)) return EINVAL; if (instsize > rootdir_free_size) return ENOSPC; return 0; }