/* Return opened file descriptor */ static int repo_fetch_remote_tmp(struct pkg_repo *repo, const char *filename, const char *extension, time_t *t, int *rc) { char url[MAXPATHLEN]; char tmp[MAXPATHLEN]; int fd; mode_t mask; const char *tmpdir; snprintf(url, MAXPATHLEN, "%s/%s.%s", pkg_repo_url(repo), filename, extension); tmpdir = getenv("TMPDIR"); if (tmpdir == NULL) tmpdir = "/tmp"; mkdirs(tmpdir); snprintf(tmp, MAXPATHLEN, "%s/%s.%s.XXXXXX", tmpdir, filename, extension); mask = umask(022); fd = mkstemp(tmp); umask(mask); if (fd == -1) { pkg_emit_error("Could not create temporary file %s, " "aborting update.\n", tmp); *rc = EPKG_FATAL; return (-1); } (void)unlink(tmp); if ((*rc = pkg_fetch_file_to_fd(repo, url, fd, t)) != EPKG_OK) { close(fd); fd = -1; } return (fd); }
int pkg_fetch_file_tmp(struct pkg_repo *repo, const char *url, char *dest, time_t t) { int fd = -1; int retcode = EPKG_FATAL; fd = mkstemp(dest); if (fd == -1) { pkg_emit_errno("mkstemp", dest); return(EPKG_FATAL); } retcode = pkg_fetch_file_to_fd(repo, url, fd, &t, 0, -1); if (t != 0) { struct timeval ftimes[2] = { { .tv_sec = t, .tv_usec = 0 }, { .tv_sec = t, .tv_usec = 0 } };
static int pkg_repo_fetch_remote_tmp(struct pkg_repo *repo, const char *filename, const char *extension, time_t *t, int *rc) { char url[MAXPATHLEN]; char tmp[MAXPATHLEN]; int fd; const char *tmpdir, *dot; /* * XXX: here we support old naming scheme, such as filename.yaml */ dot = strrchr(filename, '.'); if (dot != NULL) { snprintf(tmp, MIN(sizeof(tmp), dot - filename + 1), "%s", filename); snprintf(url, sizeof(url), "%s/%s.%s", pkg_repo_url(repo), tmp, extension); } else { snprintf(url, sizeof(url), "%s/%s.%s", pkg_repo_url(repo), filename, extension); } tmpdir = getenv("TMPDIR"); if (tmpdir == NULL) tmpdir = "/tmp"; mkdirs(tmpdir); snprintf(tmp, sizeof(tmp), "%s/%s.%s.XXXXXX", tmpdir, filename, extension); fd = mkstemp(tmp); if (fd == -1) { pkg_emit_error("Could not create temporary file %s, " "aborting update.\n", tmp); *rc = EPKG_FATAL; return (-1); } (void)unlink(tmp); if ((*rc = pkg_fetch_file_to_fd(repo, url, fd, t)) != EPKG_OK) { close(fd); fd = -1; } return (fd); }
int pkg_fetch_file(const char *url, const char *dest, time_t t) { int fd = -1; int retcode = EPKG_FATAL; if ((fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0600)) == -1) { pkg_emit_errno("open", dest); return(EPKG_FATAL); } retcode = pkg_fetch_file_to_fd(url, fd, t); close(fd); /* Remove local file if fetch failed */ if (retcode != EPKG_OK) unlink(dest); return (retcode); }
int pkg_fetch_file(struct pkg_repo *repo, const char *url, const char *dest, time_t t) { int fd = -1; int retcode = EPKG_FATAL; if ((fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644)) == -1) { pkg_emit_errno("open", dest); return(EPKG_FATAL); } retcode = pkg_fetch_file_to_fd(repo, url, fd, &t); if (t != 0) { struct timeval ftimes[2] = { { .tv_sec = t, .tv_usec = 0 }, { .tv_sec = t, .tv_usec = 0 } };
int pkg_update(const char *name, const char *packagesite, bool force) { char url[MAXPATHLEN]; struct archive *a = NULL; struct archive_entry *ae = NULL; char repofile[MAXPATHLEN]; char repofile_unchecked[MAXPATHLEN]; char tmp[MAXPATHLEN]; const char *dbdir = NULL; const char *repokey; unsigned char *sig = NULL; int siglen = 0; int fd, rc = EPKG_FATAL, ret; struct stat st; time_t t = 0; sqlite3 *sqlite; char *archreq = NULL; const char *myarch; int64_t res; const char *tmpdir; snprintf(url, MAXPATHLEN, "%s/repo.txz", packagesite); tmpdir = getenv("TMPDIR"); if (tmpdir == NULL) tmpdir = "/tmp"; strlcpy(tmp, tmpdir, sizeof(tmp)); strlcat(tmp, "/repo.txz.XXXXXX", sizeof(tmp)); fd = mkstemp(tmp); if (fd == -1) { pkg_emit_error("Could not create temporary file %s, " "aborting update.\n", tmp); return (EPKG_FATAL); } if (pkg_config_string(PKG_CONFIG_DBDIR, &dbdir) != EPKG_OK) { pkg_emit_error("Cant get dbdir config entry"); return (EPKG_FATAL); } snprintf(repofile, sizeof(repofile), "%s/%s.sqlite", dbdir, name); if (force) t = 0; /* Always fetch */ else { if (stat(repofile, &st) != -1) { t = st.st_mtime; /* add 1 minute to the timestamp because * repo.sqlite is always newer than repo.txz, * 1 minute should be enough. */ t += 60; } } rc = pkg_fetch_file_to_fd(url, fd, t); close(fd); if (rc != EPKG_OK) { goto cleanup; } if (eaccess(repofile, W_OK) == -1) { pkg_emit_error("Insufficient privilege to update %s\n", repofile); rc = EPKG_ENOACCESS; goto cleanup; } a = archive_read_new(); archive_read_support_compression_all(a); archive_read_support_format_tar(a); archive_read_open_filename(a, tmp, 4096); while (archive_read_next_header(a, &ae) == ARCHIVE_OK) { if (strcmp(archive_entry_pathname(ae), "repo.sqlite") == 0) { snprintf(repofile_unchecked, sizeof(repofile_unchecked), "%s.unchecked", repofile); archive_entry_set_pathname(ae, repofile_unchecked); /* * The repo should be owned by root and not writable */ archive_entry_set_uid(ae, 0); archive_entry_set_gid(ae, 0); archive_entry_set_perm(ae, 0644); archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS); } if (strcmp(archive_entry_pathname(ae), "signature") == 0) { siglen = archive_entry_size(ae); sig = malloc(siglen); archive_read_data(a, sig, siglen); } } if (pkg_config_string(PKG_CONFIG_REPOKEY, &repokey) != EPKG_OK) { free(sig); return (EPKG_FATAL); } if (repokey != NULL) { if (sig != NULL) { ret = rsa_verify(repofile_unchecked, repokey, sig, siglen - 1); if (ret != EPKG_OK) { pkg_emit_error("Invalid signature, " "removing repository.\n"); unlink(repofile_unchecked); free(sig); rc = EPKG_FATAL; goto cleanup; } free(sig); } else { pkg_emit_error("No signature found in the repository. " "Can not validate against %s key.", repokey); rc = EPKG_FATAL; unlink(repofile_unchecked); goto cleanup; } } /* check is the repository is for valid architecture */ sqlite3_initialize(); if (sqlite3_open(repofile_unchecked, &sqlite) != SQLITE_OK) { unlink(repofile_unchecked); pkg_emit_error("Corrupted repository"); rc = EPKG_FATAL; goto cleanup; } pkg_config_string(PKG_CONFIG_ABI, &myarch); archreq = sqlite3_mprintf("select count(arch) from packages " "where arch not GLOB '%q'", myarch); if (get_pragma(sqlite, archreq, &res) != EPKG_OK) { sqlite3_free(archreq); pkg_emit_error("Unable to query repository"); rc = EPKG_FATAL; sqlite3_close(sqlite); goto cleanup; } if (res > 0) { pkg_emit_error("At least one of the packages provided by" "the repository is not compatible with your abi: %s", myarch); rc = EPKG_FATAL; sqlite3_close(sqlite); goto cleanup; } sqlite3_close(sqlite); sqlite3_shutdown(); if (rename(repofile_unchecked, repofile) != 0) { pkg_emit_errno("rename", ""); rc = EPKG_FATAL; goto cleanup; } if ((rc = remote_add_indexes(name)) != EPKG_OK) goto cleanup; rc = EPKG_OK; cleanup: if (a != NULL) archive_read_finish(a); (void)unlink(tmp); return (rc); }