int repodata_flush(struct xbps_handle *xhp, const char *repodir, xbps_dictionary_t idx, xbps_dictionary_t idxfiles) { struct archive *ar; mode_t myumask; char *repofile, *tname, *xml; int repofd; /* Create a tempfile for our repository archive */ repofile = xbps_repo_path(xhp, repodir); tname = xbps_xasprintf("%s.XXXXXXXXXX", repofile); if ((repofd = mkstemp(tname)) == -1) return errno; /* Create and write our repository archive */ ar = archive_write_new(); assert(ar); archive_write_set_compression_gzip(ar); archive_write_set_format_pax_restricted(ar); archive_write_set_options(ar, "compression-level=9"); archive_write_open_fd(ar, repofd); xml = xbps_dictionary_externalize(idx); assert(xml); if (xbps_archive_append_buf(ar, xml, strlen(xml), XBPS_PKGINDEX, 0644, "root", "root") != 0) { free(xml); return -1; } free(xml); xml = xbps_dictionary_externalize(idxfiles); assert(xml); if (xbps_archive_append_buf(ar, xml, strlen(xml), XBPS_PKGINDEX_FILES, 0644, "root", "root") != 0) { free(xml); return -1; } free(xml); archive_write_finish(ar); /* Write data to tempfile and rename */ fdatasync(repofd); myumask = umask(0); (void)umask(myumask); assert(fchmod(repofd, 0666 & ~myumask) != -1); close(repofd); rename(tname, repofile); free(repofile); free(tname); return 0; }
static bool repo_open_remote(struct xbps_repo *repo) { char *rpath; bool rv; rpath = xbps_repo_path(repo->xhp, repo->uri); rv = xbps_repo_fetch_remote(repo, rpath); free(rpath); if (rv) { xbps_dbg_printf(repo->xhp, "[repo] `%s' used remotely (kept in memory).\n", repo->uri); if (repo->xhp->state_cb && xbps_repo_key_import(repo) != 0) rv = false; } return rv; }
bool xbps_repo_lock(struct xbps_handle *xhp, const char *repodir, int *lockfd, char **lockfname) { char *repofile, *lockfile; int fd, rv; assert(repodir); assert(lockfd); assert(lockfname); repofile = xbps_repo_path(xhp, repodir); assert(repofile); lockfile = xbps_xasprintf("%s.lock", repofile); free(repofile); for (;;) { fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0660); rv = errno; if (fd != -1) break; if (rv != EEXIST) { xbps_dbg_printf(xhp, "[repo] `%s' failed to " "create lock file %s\n", lockfile, strerror(rv)); free(lockfile); return false; } else { xbps_dbg_printf(xhp, "[repo] `%s' lock file exists," "waiting for 1s...\n", lockfile); sleep(1); } } *lockfname = lockfile; *lockfd = fd; return true; }
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; }