int exec_add(int argc, char **argv) { struct pkgdb *db = NULL; struct sbuf *failedpkgs = sbuf_new_auto(); char path[MAXPATHLEN + 1]; char *file; int retcode = EPKG_OK; int i; int failedpkgcount = 0; struct pkg *p = NULL; if (argc < 2) { usage_add(); return (EX_USAGE); } if (geteuid() != 0) { warnx("adding packages can only be done as root"); return (EX_NOPERM); } if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) { return (EX_IOERR); } for (i = 1; i < argc; i++) { if (is_url(argv[i]) == EPKG_OK) { snprintf(path, sizeof(path), "./%s", basename(argv[i])); if ((retcode = pkg_fetch_file(argv[i], path)) != EPKG_OK) break; file = path; } else file = argv[i]; pkg_open(&p, file, NULL); if ((retcode = pkg_add(db, file, 0)) != EPKG_OK) { sbuf_cat(failedpkgs, argv[i]); if (i != argc - 1) sbuf_printf(failedpkgs, ", "); failedpkgcount++; } } pkgdb_close(db); if(failedpkgcount > 0) { sbuf_finish(failedpkgs); printf("Failed to install the following %d package(s): %s.\n", failedpkgcount, sbuf_data(failedpkgs)); } sbuf_delete(failedpkgs); return (retcode == EPKG_OK ? EX_OK : EX_SOFTWARE); }
int pkg_repo_binary_ensure_loaded(struct pkg_repo *repo, struct pkg *pkg, unsigned flags) { sqlite3 *sqlite = PRIV_GET(repo); struct pkg_manifest_key *keys = NULL; struct pkg *cached = NULL; char path[MAXPATHLEN]; if (pkg->type != PKG_INSTALLED && (flags & (PKG_LOAD_FILES|PKG_LOAD_DIRS)) != 0 && (pkg->flags & (PKG_LOAD_FILES|PKG_LOAD_DIRS)) == 0) { /* * Try to get that information from fetched package in cache */ pkg_manifest_keys_new(&keys); if (pkg_repo_cached_name(pkg, path, sizeof(path)) != EPKG_OK) return (EPKG_FATAL); pkg_debug(1, "Binary> loading %s", path); if (pkg_open(&cached, path, keys, PKG_OPEN_TRY) != EPKG_OK) { pkg_free(cached); return (EPKG_FATAL); } /* Now move required elements to the provided package */ pkg_list_free(pkg, PKG_FILES); pkg_list_free(pkg, PKG_DIRS); pkg->files = cached->files; pkg->filehash = cached->filehash; pkg->dirs = cached->dirs; pkg->dirhash = cached->dirhash; cached->files = NULL; cached->filehash = NULL; cached->dirs = NULL; cached->dirhash = NULL; pkg_free(cached); pkg->flags |= (PKG_LOAD_FILES|PKG_LOAD_DIRS); } return (pkgdb_ensure_loaded_sqlite(sqlite, pkg, flags)); }
int main(int argc, char **argv) { int n; if (argc < 2) { fprintf(stderr, "%s", srv_usage); return 1; } while (argv[1][0] == '-') { if (BU_STR_EQUAL(argv[1], "-d")) { debug++; } else if (BU_STR_EQUAL(argv[1], "-x")) { sscanf(argv[2], "%x", (unsigned int *)&RTG.debug); argc--; argv++; } else if (BU_STR_EQUAL(argv[1], "-X")) { sscanf(argv[2], "%x", (unsigned int *)&rdebug); argc--; argv++; } else { fprintf(stderr, "%s", srv_usage); return 3; } argc--; argv++; } if (argc != 3 && argc != 4) { fprintf(stderr, "%s", srv_usage); return 2; } control_host = argv[1]; tcp_port = argv[2]; /* Note that the LIBPKG error logger can not be * "bu_log", as that can cause bu_log to be entered recursively. * Given the special version of bu_log in use here, * that will result in a deadlock in bu_semaphore_acquire(res_syscall)! * libpkg will default to stderr via pkg_errlog(), which is fine. */ pcsrv = pkg_open(control_host, tcp_port, "tcp", "", "", pkgswitch, NULL); if (pcsrv == PKC_ERROR) { fprintf(stderr, "rtsrv: unable to contact %s, port %s\n", control_host, tcp_port); return 1; } if (argc == 4) { /* Slip one command to dispatcher */ (void)pkg_send(MSG_CMD, argv[3], strlen(argv[3])+1, pcsrv); /* Prevent chasing the package with an immediate TCP close */ sleep(1); pkg_close(pcsrv); return 0; } #ifdef SO_SNDBUF /* increase the default send buffer size to 32k since we're * sending pixels more than likely. */ { int val = 32767; n = setsockopt(pcsrv->pkc_fd, SOL_SOCKET, SO_SNDBUF, (const void *)&val, sizeof(val)); if (n < 0) perror("setsockopt: SO_SNDBUF"); } #endif if (!debug) { /* A fresh process */ if (fork()) return 0; /* Go into our own process group */ n = bu_process_id(); #ifdef HAVE_SETPGID if (setpgid(n, n) < 0) perror("setpgid"); #else /* SysV uses setpgrp with no args and it can't fail, * obsoleted by setpgid. */ setpgrp(); #endif /* * Unless controller process has specifically said * that this is an interactive session, e.g., for a demo, * drop to the lowest sensible priority. */ if (!interactive) { bu_nice_set(19); /* lowest priority */ } /* Close off the world */ fclose(stdin); fclose(stdout); fclose(stderr); (void)close(0); (void)close(1); (void)close(2); /* For stdio & perror safety, reopen 0, 1, 2 */ (void)open("/dev/null", 0); /* to fd 0 */ n = dup(0); /* to fd 1 */ if (n == -1) perror("dup"); n = dup(0); /* to fd 2 */ if (n == -1) perror("dup"); #if defined(HAVE_SYS_IOCTL_H) && defined(TIOCNOTTY) n = open("/dev/tty", 2); if (n >= 0) { (void)ioctl(n, TIOCNOTTY, 0); (void)close(n); } #endif } /* Send our version string */ if (pkg_send(MSG_VERSION, PROTOCOL_VERSION, strlen(PROTOCOL_VERSION)+1, pcsrv) < 0) { fprintf(stderr, "pkg_send MSG_VERSION error\n"); return 1; } if (debug) fprintf(stderr, "PROTOCOL_VERSION='%s'\n", PROTOCOL_VERSION); /* * Now that the fork() has been done, it is safe to initialize * the parallel processing support. */ avail_cpus = bu_avail_cpus(); /* Need to set rtg_parallel non_zero here for RES_INIT to work */ npsw = avail_cpus; if (npsw > 1) { RTG.rtg_parallel = 1; } else RTG.rtg_parallel = 0; bu_semaphore_init(RT_SEM_LAST); bu_log("using %d of %d cpus\n", npsw, avail_cpus); /* * Initialize the non-parallel memory resource. * The parallel guys are initialized after the rt_dirbuild(). */ rt_init_resource(&rt_uniresource, MAX_PSW, NULL); bn_rand_init(rt_uniresource.re_randptr, MAX_PSW); BU_LIST_INIT(&WorkHead); for (;;) { struct pkg_queue *lp; fd_set ifds; struct timeval tv; /* First, process any packages in library buffers */ if (pkg_process(pcsrv) < 0) { bu_log("pkg_get error\n"); break; } /* Second, see if any input to read */ FD_ZERO(&ifds); FD_SET(pcsrv->pkc_fd, &ifds); tv.tv_sec = BU_LIST_NON_EMPTY(&WorkHead) ? 0L : 9999L; tv.tv_usec = 0L; if (select(pcsrv->pkc_fd+1, &ifds, (fd_set *)0, (fd_set *)0, &tv) != 0) { n = pkg_suckin(pcsrv); if (n < 0) { bu_log("pkg_suckin error\n"); break; } else if (n == 0) { /* EOF detected */ break; } else { /* All is well */ } } /* Third, process any new packages in library buffers */ if (pkg_process(pcsrv) < 0) { bu_log("pkg_get error\n"); break; } /* Finally, more work may have just arrived, check our list */ if (BU_LIST_NON_EMPTY(&WorkHead)) { lp = BU_LIST_FIRST(pkg_queue, &WorkHead); BU_LIST_DEQUEUE(&lp->l); switch (lp->type) { case MSG_MATRIX: ph_matrix((struct pkg_conn *)0, lp->buf); break; case MSG_LINES: ph_lines((struct pkg_conn *)0, lp->buf); break; case MSG_OPTIONS: ph_options((struct pkg_conn *)0, lp->buf); break; case MSG_GETTREES: ph_gettrees((struct pkg_conn *)0, lp->buf); break; default: bu_log("bad list element, type=%d\n", lp->type); return 33; } BU_PUT(lp, struct pkg_queue); } } return 0; /* bu_exit(0, NULL) */ }
int exec_query(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; char *pkgname = NULL; int query_flags = PKG_LOAD_BASIC; match_t match = MATCH_EXACT; int ch; int ret = EPKG_OK; int retcode = EXIT_SUCCESS; int i; char multiline = 0; while ((ch = getopt(argc, argv, "agxXf:")) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'g': match = MATCH_GLOB; break; case 'x': match = MATCH_REGEX; break; case 'X': match = MATCH_EREGEX; break; case 'f': pkgname = optarg; break; default: usage_query(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc == 0) { usage_query(); return (EX_USAGE); } if ((argc == 1) ^ (match == MATCH_ALL) && pkgname == NULL) { usage_query(); return (EX_USAGE); } if (analyse_query_string(argv[0], &query_flags, &multiline) != EPKG_OK) return (EX_USAGE); if (pkgname != NULL) { if (pkg_open(&pkg, pkgname, NULL) != EPKG_OK) { return (1); } print_query(pkg, argv[0], multiline); pkg_free(pkg); return (0); } if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK) return (EX_IOERR); if (match == MATCH_ALL) { if ((it = pkgdb_query(db, NULL, match)) == NULL) return (EX_IOERR); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) print_query(pkg, argv[0], multiline); if (ret != EPKG_END) retcode = EX_SOFTWARE; pkgdb_it_free(it); } else { for (i = 1; i < argc; i++) { pkgname = argv[i]; if ((it = pkgdb_query(db, pkgname, match)) == NULL) return (EX_IOERR); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) print_query(pkg, argv[0], multiline); if (ret != EPKG_END) { retcode = EX_SOFTWARE; break; } pkgdb_it_free(it); } } pkg_free(pkg); pkgdb_close(db); return (retcode); }
int exec_query(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; struct pkg_manifest_key *keys = NULL; char *pkgname = NULL; int query_flags = PKG_LOAD_BASIC; match_t match = MATCH_EXACT; int ch; int ret; int retcode = EX_OK; int i; char multiline = 0; char *condition = NULL; struct sbuf *sqlcond = NULL; const unsigned int q_flags_len = NELEM(accepted_query_flags); struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "case-sensitive", no_argument, NULL, 'C' }, { "evaluate", required_argument, NULL, 'e' }, { "file", required_argument, NULL, 'F' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "regex", no_argument, NULL, 'x' }, { NULL, 0, NULL, 0 }, }; while ((ch = getopt_long(argc, argv, "+aCe:F:gix", longopts, NULL)) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'e': match = MATCH_CONDITION; condition = optarg; break; case 'F': pkgname = optarg; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'x': match = MATCH_REGEX; break; default: usage_query(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc == 0) { usage_query(); return (EX_USAGE); } /* Default to all packages if no pkg provided */ if (argc == 1 && pkgname == NULL && condition == NULL && match == MATCH_EXACT) { match = MATCH_ALL; } else if (((argc == 1) ^ (match == MATCH_ALL)) && pkgname == NULL && condition == NULL) { usage_query(); return (EX_USAGE); } if (analyse_query_string(argv[0], accepted_query_flags, q_flags_len, &query_flags, &multiline) != EPKG_OK) return (EX_USAGE); if (pkgname != NULL) { pkg_manifest_keys_new(&keys); if (pkg_open(&pkg, pkgname, keys, 0) != EPKG_OK) { return (EX_IOERR); } pkg_manifest_keys_free(keys); print_query(pkg, argv[0], multiline); pkg_free(pkg); return (EX_OK); } if (condition != NULL) { sqlcond = sbuf_new_auto(); if (format_sql_condition(condition, sqlcond, false) != EPKG_OK) { sbuf_delete(sqlcond); return (EX_USAGE); } sbuf_finish(sqlcond); } ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); if (ret == EPKG_ENOACCESS) { warnx("Insufficient privileges to query the package database"); return (EX_NOPERM); } else if (ret == EPKG_ENODB) { if (!quiet) warnx("No packages installed"); return (EX_OK); } else if (ret != EPKG_OK) return (EX_IOERR); ret = pkgdb_open(&db, PKGDB_DEFAULT); if (ret != EPKG_OK) return (EX_IOERR); if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) { pkgdb_close(db); warnx("Cannot get a read lock on a database, it is locked by another process"); return (EX_TEMPFAIL); } if (match == MATCH_ALL || match == MATCH_CONDITION) { const char *condition_sql = NULL; if (match == MATCH_CONDITION && sqlcond) condition_sql = sbuf_data(sqlcond); if ((it = pkgdb_query(db, condition_sql, match)) == NULL) return (EX_IOERR); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) print_query(pkg, argv[0], multiline); if (ret != EPKG_END) retcode = EX_SOFTWARE; pkgdb_it_free(it); } else { int nprinted = 0; for (i = 1; i < argc; i++) { pkgname = argv[i]; if ((it = pkgdb_query(db, pkgname, match)) == NULL) { retcode = EX_IOERR; goto cleanup; } while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) { nprinted++; print_query(pkg, argv[0], multiline); } if (ret != EPKG_END) { retcode = EX_SOFTWARE; break; } pkgdb_it_free(it); } if (nprinted == 0 && retcode == EX_OK) { /* ensure to return a non-zero status when no package were found. */ retcode = EX_UNAVAILABLE; } } cleanup: pkg_free(pkg); pkgdb_release_lock(db, PKGDB_LOCK_READONLY); pkgdb_close(db); return (retcode); }
void read_pkg_file(void *data) { struct thd_data *d = (struct thd_data*) data; struct pkg_result *r; FTSENT *fts_ent = NULL; char fts_accpath[MAXPATHLEN + 1]; char fts_path[MAXPATHLEN + 1]; char fts_name[MAXPATHLEN + 1]; off_t st_size; int fts_info; char *ext = NULL; char *pkg_path; for (;;) { fts_ent = NULL; /* * Get a file to read from. * Copy the data we need from the fts entry localy because as soon as * we unlock the fts_m mutex, we can not access it. */ pthread_mutex_lock(&d->fts_m); if (d->stop == false) { fts_ent = fts_read(d->fts); } if (fts_ent != NULL) { strlcpy(fts_accpath, fts_ent->fts_accpath, sizeof(fts_accpath)); strlcpy(fts_path, fts_ent->fts_path, sizeof(fts_path)); strlcpy(fts_name, fts_ent->fts_name, sizeof(fts_name)); st_size = fts_ent->fts_statp->st_size; fts_info = fts_ent->fts_info; } pthread_mutex_unlock(&d->fts_m); // There is no more jobs, exit the main loop. if (fts_ent == NULL) break; /* skip everything that is not a file */ if (fts_info != FTS_F) continue; ext = strrchr(fts_name, '.'); if (ext == NULL) continue; if (strcmp(ext, ".tgz") != 0 && strcmp(ext, ".tbz") != 0 && strcmp(ext, ".txz") != 0 && strcmp(ext, ".tar") != 0) continue; if (strcmp(fts_name, "repo.txz") == 0) continue; pkg_path = fts_path; pkg_path += strlen(d->root_path); while (pkg_path[0] == '/') pkg_path++; r = calloc(1, sizeof(struct pkg_result)); strlcpy(r->path, pkg_path, sizeof(r->path)); r->size = st_size; sha256_file(fts_accpath, r->cksum); if (pkg_open(&r->pkg, fts_accpath) != EPKG_OK) { r->retcode = EPKG_WARN; } /* Add result to the FIFO and notify */ pthread_mutex_lock(&d->results_m); while (d->num_results >= d->max_results) { pthread_cond_wait(&d->has_room, &d->results_m); } STAILQ_INSERT_TAIL(&d->results, r, next); d->num_results++; pthread_cond_signal(&d->has_result); pthread_mutex_unlock(&d->results_m); } /* * This thread is about to exit. * Notify the main thread that we are done. */ pthread_mutex_lock(&d->results_m); d->thd_finished++; pthread_cond_signal(&d->has_result); pthread_mutex_unlock(&d->results_m); }
int pkg_create_repo(char *path, void (progress)(struct pkg *pkg, void *data), void *data) { FTS *fts = NULL; FTSENT *ent = NULL; struct stat st; struct pkg *pkg = NULL; struct pkg_dep *dep = NULL; struct pkg_category *category = NULL; struct pkg_license *license = NULL; struct pkg_option *option = NULL; struct sbuf *manifest = sbuf_new_auto(); char *ext = NULL; sqlite3 *sqlite = NULL; sqlite3_stmt *stmt_deps = NULL; sqlite3_stmt *stmt_pkg = NULL; sqlite3_stmt *stmt_lic1 = NULL; sqlite3_stmt *stmt_lic2 = NULL; sqlite3_stmt *stmt_cat1 = NULL; sqlite3_stmt *stmt_cat2 = NULL; sqlite3_stmt *stmt_opts = NULL; int64_t package_id; char *errmsg = NULL; int retcode = EPKG_OK; char *pkg_path; char cksum[SHA256_DIGEST_LENGTH * 2 +1]; char *repopath[2]; char repodb[MAXPATHLEN + 1]; const char initsql[] = "" "CREATE TABLE packages (" "id INTEGER PRIMARY KEY," "origin TEXT UNIQUE," "name TEXT NOT NULL," "version TEXT NOT NULL," "comment TEXT NOT NULL," "desc TEXT NOT NULL," "arch TEXT NOT NULL," "osversion TEXT NOT NULL," "maintainer TEXT NOT NULL," "www TEXT," "prefix TEXT NOT NULL," "pkgsize INTEGER NOT NULL," "flatsize INTEGER NOT NULL," "licenselogic INTEGER NOT NULL," "cksum TEXT NOT NULL," "path TEXT NOT NULL," /* relative path to the package in the repository */ "pkg_format_version INTEGER" ");" "CREATE TABLE deps (" "origin TEXT," "name TEXT," "version TEXT," "package_id INTEGER REFERENCES packages(id)," "UNIQUE(package_id, origin)" ");" "CREATE TABLE categories (" "id INTEGER PRIMARY KEY, " "name TEXT NOT NULL UNIQUE " ");" "CREATE TABLE pkg_categories (" "package_id INTEGER REFERENCES packages(id), " "category_id INTEGER REFERENCES categories(id), " "UNIQUE(package_id, category_id)" ");" "CREATE TABLE licenses (" "id INTEGER PRIMARY KEY," "name TEXT NOT NULL UNIQUE" ");" "CREATE TABLE pkg_licenses (" "package_id INTEGER REFERENCES packages(id), " "license_id INTEGER REFERENCES licenses(id), " "UNIQUE(package_id, license_id)" ");" "CREATE TABLE options (" "package_id INTEGER REFERENCES packages(id), " "option TEXT," "value TEXT," "UNIQUE (package_id, option)" ");" "PRAGMA user_version=2;" ; const char pkgsql[] = "" "INSERT INTO packages (" "origin, name, version, comment, desc, arch, osversion, " "maintainer, www, prefix, pkgsize, flatsize, licenselogic, cksum, path" ")" "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15);"; const char depssql[] = "" "INSERT INTO deps (origin, name, version, package_id) " "VALUES (?1, ?2, ?3, ?4);"; const char licsql[] = "INSERT OR IGNORE INTO licenses(name) VALUES(?1);"; const char addlicsql[] = "INSERT OR ROLLBACK INTO pkg_licenses(package_id, license_id) " "VALUES (?1, (SELECT id FROM licenses WHERE name = ?2));"; const char catsql[] = "INSERT OR IGNORE INTO categories(name) VALUES(?1);"; const char addcatsql[] = "INSERT OR ROLLBACK INTO pkg_categories(package_id, category_id) " "VALUES (?1, (SELECT id FROM categories WHERE name = ?2));"; const char addoption[] = "INSERT OR ROLLBACK INTO options (option, value, package_id) " "VALUES (?1, ?2, ?3);"; if (!is_dir(path)) { pkg_emit_error("%s is not a directory", path); return EPKG_FATAL; } repopath[0] = path; repopath[1] = NULL; snprintf(repodb, sizeof(repodb), "%s/repo.sqlite", path); if (stat(repodb, &st) != -1) if (unlink(repodb) != 0) { pkg_emit_errno("unlink", path); return EPKG_FATAL; } sqlite3_initialize(); if (sqlite3_open(repodb, &sqlite) != SQLITE_OK) { sqlite3_shutdown(); return (EPKG_FATAL); } if ((retcode = sql_exec(sqlite, initsql)) != EPKG_OK) goto cleanup; if ((retcode = sql_exec(sqlite, "BEGIN TRANSACTION;")) != EPKG_OK) goto cleanup; if (sqlite3_prepare_v2(sqlite, pkgsql, -1, &stmt_pkg, NULL) != SQLITE_OK) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } if (sqlite3_prepare_v2(sqlite, depssql, -1, &stmt_deps, NULL) != SQLITE_OK) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } if (sqlite3_prepare_v2(sqlite, licsql, -1, &stmt_lic1, NULL) != SQLITE_OK) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } if (sqlite3_prepare_v2(sqlite, addlicsql, -1, &stmt_lic2, NULL) != SQLITE_OK) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } if (sqlite3_prepare_v2(sqlite, addoption, -1, &stmt_opts, NULL) != SQLITE_OK) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } if ((fts = fts_open(repopath, FTS_PHYSICAL, NULL)) == NULL) { pkg_emit_errno("fts_open", path); retcode = EPKG_FATAL; goto cleanup; } if (sqlite3_prepare_v2(sqlite, catsql, -1, &stmt_cat1, NULL) != SQLITE_OK) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } if (sqlite3_prepare_v2(sqlite, addcatsql, -1, &stmt_cat2, NULL) != SQLITE_OK) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } while ((ent = fts_read(fts)) != NULL) { cksum[0] = '\0'; /* skip everything that is not a file */ if (ent->fts_info != FTS_F) continue; ext = strrchr(ent->fts_name, '.'); if (ext == NULL) continue; if (strcmp(ext, ".tgz") != 0 && strcmp(ext, ".tbz") != 0 && strcmp(ext, ".txz") != 0 && strcmp(ext, ".tar") != 0) continue; pkg_path = ent->fts_path; pkg_path += strlen(path); while (pkg_path[0] == '/' ) pkg_path++; if (pkg_open(&pkg, ent->fts_accpath, manifest) != EPKG_OK) { retcode = EPKG_WARN; continue; } if (progress != NULL) progress(pkg, data); sqlite3_bind_text(stmt_pkg, 1, pkg_get(pkg, PKG_ORIGIN), -1, SQLITE_STATIC); sqlite3_bind_text(stmt_pkg, 2, pkg_get(pkg, PKG_NAME), -1, SQLITE_STATIC); sqlite3_bind_text(stmt_pkg, 3, pkg_get(pkg, PKG_VERSION), -1, SQLITE_STATIC); sqlite3_bind_text(stmt_pkg, 4, pkg_get(pkg, PKG_COMMENT), -1, SQLITE_STATIC); sqlite3_bind_text(stmt_pkg, 5, pkg_get(pkg, PKG_DESC), -1, SQLITE_STATIC); sqlite3_bind_text(stmt_pkg, 6, pkg_get(pkg, PKG_ARCH), -1, SQLITE_STATIC); sqlite3_bind_text(stmt_pkg, 7, pkg_get(pkg, PKG_OSVERSION), -1, SQLITE_STATIC); sqlite3_bind_text(stmt_pkg, 8, pkg_get(pkg, PKG_MAINTAINER), -1, SQLITE_STATIC); sqlite3_bind_text(stmt_pkg, 9, pkg_get(pkg, PKG_WWW), -1, SQLITE_STATIC); sqlite3_bind_text(stmt_pkg, 10, pkg_get(pkg, PKG_PREFIX), -1, SQLITE_STATIC); sqlite3_bind_int64(stmt_pkg, 11, ent->fts_statp->st_size); sqlite3_bind_int64(stmt_pkg, 12, pkg_flatsize(pkg)); sha256_file(ent->fts_accpath, cksum); sqlite3_bind_int64(stmt_pkg, 13, pkg_licenselogic(pkg)); sqlite3_bind_text(stmt_pkg, 14, cksum, -1, SQLITE_STATIC); sqlite3_bind_text(stmt_pkg, 15, pkg_path, -1, SQLITE_STATIC); if (sqlite3_step(stmt_pkg) != SQLITE_DONE) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } sqlite3_reset(stmt_pkg); package_id = sqlite3_last_insert_rowid(sqlite); dep = NULL; while (pkg_deps(pkg, &dep) == EPKG_OK) { sqlite3_bind_text(stmt_deps, 1, pkg_dep_origin(dep), -1, SQLITE_STATIC); sqlite3_bind_text(stmt_deps, 2, pkg_dep_name(dep), -1, SQLITE_STATIC); sqlite3_bind_text(stmt_deps, 3, pkg_dep_version(dep), -1, SQLITE_STATIC); sqlite3_bind_int64(stmt_deps, 4, package_id); if (sqlite3_step(stmt_deps) != SQLITE_DONE) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } sqlite3_reset(stmt_deps); } category = NULL; while (pkg_categories(pkg, &category) == EPKG_OK) { sqlite3_bind_text(stmt_cat1, 1, pkg_category_name(category), -1, SQLITE_STATIC); sqlite3_bind_int64(stmt_cat2, 1, package_id); sqlite3_bind_text(stmt_cat2, 2, pkg_category_name(category), -1, SQLITE_STATIC); if (sqlite3_step(stmt_cat1) != SQLITE_DONE) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } if (sqlite3_step(stmt_cat2) != SQLITE_DONE) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } sqlite3_reset(stmt_cat1); sqlite3_reset(stmt_cat2); } license = NULL; while (pkg_licenses(pkg, &license) == EPKG_OK) { sqlite3_bind_text(stmt_lic1, 1, pkg_license_name(license), -1, SQLITE_STATIC); sqlite3_bind_int64(stmt_lic2, 1, package_id); sqlite3_bind_text(stmt_lic2, 2, pkg_license_name(license), -1, SQLITE_STATIC); if (sqlite3_step(stmt_lic1) != SQLITE_DONE) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } if (sqlite3_step(stmt_lic2) != SQLITE_DONE) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } sqlite3_reset(stmt_lic1); sqlite3_reset(stmt_lic2); } option = NULL; while (pkg_options(pkg, &option) == EPKG_OK) { sqlite3_bind_text(stmt_opts, 1, pkg_option_opt(option), -1, SQLITE_STATIC); sqlite3_bind_text(stmt_opts, 2, pkg_option_value(option), -1, SQLITE_STATIC); sqlite3_bind_int64(stmt_opts, 3, package_id); if (sqlite3_step(stmt_opts) != SQLITE_DONE) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } sqlite3_reset(stmt_opts); } } if (sqlite3_exec(sqlite, "COMMIT;", NULL, NULL, &errmsg) != SQLITE_OK) { pkg_emit_error("sqlite: %s", errmsg); retcode = EPKG_FATAL; } cleanup: if (fts != NULL) fts_close(fts); if (pkg != NULL) pkg_free(pkg); if (stmt_pkg != NULL) sqlite3_finalize(stmt_pkg); if (stmt_deps != NULL) sqlite3_finalize(stmt_deps); if (stmt_cat1 != NULL) sqlite3_finalize(stmt_cat1); if (stmt_cat2 != NULL) sqlite3_finalize(stmt_cat2); if (stmt_lic1 != NULL) sqlite3_finalize(stmt_lic1); if (stmt_lic2 != NULL) sqlite3_finalize(stmt_lic2); if (stmt_opts != NULL) sqlite3_finalize(stmt_opts); if (sqlite != NULL) sqlite3_close(sqlite); if (errmsg != NULL) sqlite3_free(errmsg); sbuf_delete(manifest); sqlite3_shutdown(); return (retcode); }
int exec_query(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; struct pkg_manifest_key *keys = NULL; char *pkgname = NULL; int query_flags = PKG_LOAD_BASIC; match_t match = MATCH_EXACT; int ch; int ret; int retcode = EX_OK; int i; char multiline = 0; char *condition = NULL; struct sbuf *sqlcond = NULL; const unsigned int q_flags_len = (sizeof(accepted_query_flags)/sizeof(accepted_query_flags[0])); while ((ch = getopt(argc, argv, "agixF:e:")) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'x': match = MATCH_REGEX; break; case 'F': pkgname = optarg; break; case 'e': match = MATCH_CONDITION; condition = optarg; break; default: usage_query(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc == 0) { usage_query(); return (EX_USAGE); } /* Default to all packages if no pkg provided */ if (argc == 1 && pkgname == NULL && condition == NULL && match == MATCH_EXACT) { match = MATCH_ALL; } else if ((argc == 1) ^ (match == MATCH_ALL) && pkgname == NULL && condition == NULL) { usage_query(); return (EX_USAGE); } if (analyse_query_string(argv[0], accepted_query_flags, q_flags_len, &query_flags, &multiline) != EPKG_OK) return (EX_USAGE); if (pkgname != NULL) { pkg_manifest_keys_new(&keys); if (pkg_open(&pkg, pkgname, keys, 0) != EPKG_OK) { return (EX_IOERR); } pkg_manifest_keys_free(keys); print_query(pkg, argv[0], multiline); pkg_free(pkg); return (EX_OK); } if (condition != NULL) { sqlcond = sbuf_new_auto(); if (format_sql_condition(condition, sqlcond, false) != EPKG_OK) { sbuf_delete(sqlcond); return (EX_USAGE); } sbuf_finish(sqlcond); } ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL); if (ret == EPKG_ENOACCESS) { warnx("Insufficient privilege to query package database"); return (EX_NOPERM); } else if (ret == EPKG_ENODB) { if (!quiet) warnx("No packages installed"); return (EX_OK); } else if (ret != EPKG_OK) return (EX_IOERR); ret = pkgdb_open(&db, PKGDB_DEFAULT); if (ret != EPKG_OK) return (EX_IOERR); if (match == MATCH_ALL || match == MATCH_CONDITION) { const char *condition_sql = NULL; if (match == MATCH_CONDITION && sqlcond) condition_sql = sbuf_data(sqlcond); if ((it = pkgdb_query(db, condition_sql, match)) == NULL) return (EX_IOERR); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) print_query(pkg, argv[0], multiline); if (ret != EPKG_END) retcode = EX_SOFTWARE; pkgdb_it_free(it); } else { int nprinted = 0; for (i = 1; i < argc; i++) { pkgname = argv[i]; if ((it = pkgdb_query(db, pkgname, match)) == NULL) return (EX_IOERR); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) { nprinted++; print_query(pkg, argv[0], multiline); } if (ret != EPKG_END) { retcode = EX_SOFTWARE; break; } pkgdb_it_free(it); } if (nprinted == 0 && retcode == EX_OK) { /* ensure to return a non-zero status when no package were found. */ retcode = EX_UNAVAILABLE; } } pkg_free(pkg); pkgdb_close(db); return (retcode); }
int exec_info(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; int query_flags; struct pkg *pkg = NULL; unsigned int opt = INFO_TAG_NAMEVER; match_t match = MATCH_EXACT; char *pkgname; char *pkgversion = NULL, *pkgversion2 = NULL; const char *file = NULL; int ch; int ret = EPKG_OK; int retcode = 0; bool gotone = false; int i, j; int sign = 0; int sign2 = 0; bool pkg_exists = false; bool origin_search = false; /* TODO: exclusive opts ? */ while ((ch = getopt(argc, argv, "aDegxEIdrklBsqopOfF:R")) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'O': origin_search = true; /* only for ports compat */ break; case 'e': pkg_exists = true;; retcode = 1; break; case 'g': match = MATCH_GLOB; break; case 'x': match = MATCH_REGEX; break; case 'D': opt |= INFO_MESSAGE; break; case 'd': opt |= INFO_DEPS; break; case 'I': opt |= INFO_COMMENT; break; case 'r': opt |= INFO_RDEPS; break; case 'k': opt |= INFO_LOCKED; break; case 'l': opt |= INFO_FILES; break; case 'B': opt |= INFO_SHLIBS; break; case 's': opt |= INFO_FLATSIZE; break; case 'E': /* ports compatibility */ /* FALLSTHROUGH */ case 'q': quiet = true; break; case 'o': opt |= INFO_ORIGIN; break; case 'p': opt |= INFO_PREFIX; break; case 'f': opt |= INFO_FULL; break; case 'F': file = optarg; break; case 'R': opt |= INFO_RAW; break; default: usage_info(); return(EX_USAGE); } } if (argc == 1) match = MATCH_ALL; argc -= optind; argv += optind; if (argc == 0 && file == NULL && match != MATCH_ALL) { /* which -O bsd.*.mk always execpt clean output */ if (origin_search) return (EX_OK); usage_info(); return (EX_USAGE); } /* When no other data is requested, default is to print * 'name-ver comment' For -O, just print name-ver */ if (!origin_search && (opt & INFO_ALL) == 0 && match == MATCH_ALL && !quiet) opt |= INFO_COMMENT; /* Special compatibility: handle -O and -q -O */ if (origin_search) { if (quiet) { opt = INFO_TAG_NAMEVER; quiet = false; } else { opt = INFO_TAG_NAMEVER|INFO_COMMENT; } } if (match == MATCH_ALL && opt == INFO_TAG_NAMEVER) quiet = false; if (file != NULL) { if (pkg_open(&pkg, file) != EPKG_OK) { return (1); } print_info(pkg, opt); pkg_free(pkg); return (0); } ret = pkgdb_open(&db, PKGDB_DEFAULT); if (ret == EPKG_ENODB) { if (geteuid() == 0) return (EX_IOERR); if (match == MATCH_ALL) return (EX_OK); if (!quiet) printf("No packages installed.\n"); return (EX_UNAVAILABLE); } if (ret != EPKG_OK) return (EX_IOERR); i = 0; do { gotone = false; pkgname = argv[i]; if (match != MATCH_ALL && pkgname[0] == '\0') { fprintf(stderr, "Pattern must not be empty.\n"); i++; continue; } /* * allow to search for origin with a trailing / * likes audio/linux-vsound depending on ${PORTSDIR}/audio/sox/ */ if (argc > 0 && pkgname[strlen(pkgname) -1] == '/') pkgname[strlen(pkgname) -1] = '\0'; if (argc > 0) { j=0; while (pkgname[j] != '\0') { if (pkgname[j] == '<') { if (pkgversion) { pkgversion2 = pkgname + j; sign2 = LT; pkgversion2[0] = '\0'; pkgversion2++; if (pkgversion2[0] == '=') { pkgversion2++; sign=LE; j++; } } else { pkgversion = pkgname + j; sign = LT; pkgversion[0] = '\0'; pkgversion++; if (pkgversion[0] == '=') { pkgversion++; sign=LE; j++; } } } else if (pkgname[j] == '>') { if (pkgversion) { pkgversion2 = pkgname + j; sign2 = GT; pkgversion2[0] = '\0'; pkgversion2++; if (pkgversion2[0] == '=') { pkgversion2++; sign=GE; j++; } } else { pkgversion = pkgname + j; sign = GT; pkgversion[0] = '\0'; pkgversion++; if (pkgversion[0] == '=') { pkgversion++; sign=GE; j++; } } } else if (pkgname[j] == '=') { if (pkgversion) { pkgversion2 = pkgname + j; sign2 = EQ; pkgversion2[0] = '\0'; pkgversion2++; if (pkgversion2[0] == '=') { pkgversion2++; sign=EQ; j++; } } else { pkgversion = pkgname + j; sign = EQ; pkgversion[0] = '\0'; pkgversion++; if (pkgversion[0] == '=') { pkgversion++; sign=EQ; j++; } } } j++; } } else pkgversion = NULL; if ((it = pkgdb_query(db, pkgname, match)) == NULL) { return (EX_IOERR); } /* this is place for compatibility hacks */ /* ports infrastructure expects pkg info -q -O to always return 0 even * if the ports doesn't exists */ if (origin_search) gotone = true; /* end of compatibility hacks */ query_flags = info_flags(opt); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) { gotone = true; const char *version; pkg_get(pkg, PKG_VERSION, &version); if (pkgversion != NULL) { switch (pkg_version_cmp(version, pkgversion)) { case -1: if (sign != LT && sign != LE) { gotone = false; continue; } break; case 0: if (sign != LE && sign != GE && sign != EQ) { gotone = false; continue; } break; case 1: if (sign != GT && sign != GE) { gotone = false; continue; } break; } } if (pkgversion2 != NULL) { switch (pkg_version_cmp(version, pkgversion2)) { case -1: if (sign2 != LT && sign2 != LE) { gotone = false; continue; } break; case 0: if (sign2 != LE && sign2 != GE && sign2 != EQ) { gotone = false; continue; } break; case 1: if (sign2 != GT && sign2 != GE) { gotone = false; continue; } break; } } if (pkg_exists) retcode = EX_OK; else print_info(pkg, opt); } if (ret != EPKG_END) { retcode = EX_IOERR; } if (retcode == EX_OK && !gotone && match != MATCH_ALL) { if (!quiet) warnx("No package(s) matching %s", argv[i]); retcode = EX_SOFTWARE; } pkgdb_it_free(it); i++; } while (i < argc); pkg_free(pkg); pkgdb_close(db); return (retcode); }
int exec_clean(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; struct pkg *p = NULL; FTS *fts = NULL; FTSENT *ent = NULL; struct dl_head dl = STAILQ_HEAD_INITIALIZER(dl); const char *cachedir; char *paths[2]; char *repopath; bool dry_run = false; bool yes; int retcode = EX_SOFTWARE; int ret; int ch; pkg_config_bool(PKG_CONFIG_ASSUME_ALWAYS_YES, &yes); while ((ch = getopt(argc, argv, "nqy")) != -1) { switch (ch) { case 'n': dry_run = true; break; case 'q': quiet = true; break; case 'y': yes = true; break; default: usage_clean(); return (EX_USAGE); } } argc -= optind; argv += optind; if (pkg_config_string(PKG_CONFIG_CACHEDIR, &cachedir) != EPKG_OK) { warnx("Cannot get cachedir config entry"); return 1; } paths[0] = __DECONST(char*, cachedir); paths[1] = NULL; if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) { goto cleanup; } if ((fts = fts_open(paths, FTS_PHYSICAL, NULL)) == NULL) { warn("fts_open(%s)", cachedir); goto cleanup; } /* Build the list of out-of-date or obsolete packages */ while ((ent = fts_read(fts)) != NULL) { const char *origin, *pkgrepopath; if (ent->fts_info != FTS_F) continue; repopath = ent->fts_path + strlen(cachedir); if (repopath[0] == '/') repopath++; if (pkg_open(&pkg, ent->fts_path) != EPKG_OK) { if (!quiet) warnx("skipping %s", ent->fts_path); continue; } pkg_get(pkg, PKG_ORIGIN, &origin); it = pkgdb_search(db, origin, MATCH_EXACT, FIELD_ORIGIN, FIELD_NONE, NULL); if (it == NULL) { if (!quiet) warnx("skipping %s", ent->fts_path); continue; } if ((ret = pkgdb_it_next(it, &p, PKG_LOAD_BASIC)) == EPKG_FATAL) { if (!quiet) warnx("skipping %s", ent->fts_path); continue; } pkg_get(p, PKG_REPOPATH, &pkgrepopath); if (ret == EPKG_END) { ret = add_to_dellist(&dl, REMOVED, ent->fts_path, origin, NULL, NULL); } else if (strcmp(repopath, pkgrepopath)) { const char *newname; const char *newversion; pkg_get(p, PKG_NAME, &newname, PKG_VERSION, &newversion); ret = add_to_dellist(&dl, OUT_OF_DATE, ent->fts_path, origin, newname, newversion); } else { char local_cksum[SHA256_DIGEST_LENGTH * 2 +1]; const char *cksum; pkg_get(p, PKG_CKSUM, &cksum); if (hash_file(ent->fts_path, local_cksum) == EPKG_OK) { if (strcmp(cksum, local_cksum) != 0) { ret = add_to_dellist(&dl, CKSUM_MISMATCH, ent->fts_path, origin, NULL, NULL); } } } if (ret != EPKG_OK && ret != EPKG_END) { retcode = EX_OSERR; /* out of memory */ goto cleanup; } pkgdb_it_free(it); } if (STAILQ_EMPTY(&dl)) { if (!quiet) printf("Nothing to do.\n"); retcode = EX_OK; goto cleanup; } if (dry_run || !yes || !quiet) display_dellist(&dl, cachedir); if (!dry_run) { if (!yes) yes = query_yesno( "\nProceed with cleaning cache [y/N]: "); if (yes) retcode = delete_dellist(&dl); } else retcode = EX_OK; cleanup: free_dellist(&dl); pkg_free(pkg); pkg_free(p); if (fts != NULL) fts_close(fts); if (db != NULL) pkgdb_close(db); return (retcode); }
int exec_query(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; char *pkgname = NULL; int query_flags = PKG_LOAD_BASIC; match_t match = MATCH_EXACT; int ch; int ret = EPKG_OK; int retcode = EX_OK; int i; char multiline = 0; char *condition = NULL; struct sbuf *sqlcond = NULL; const unsigned int q_flags_len = (sizeof(accepted_query_flags)/sizeof(accepted_query_flags[0])); while ((ch = getopt(argc, argv, "agxXF:e:")) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'g': match = MATCH_GLOB; break; case 'x': match = MATCH_REGEX; break; case 'X': match = MATCH_EREGEX; break; case 'F': pkgname = optarg; break; case 'e': match = MATCH_CONDITION; condition = optarg; break; default: usage_query(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc == 0) { usage_query(); return (EX_USAGE); } /* Default to all packages if no pkg provided */ if (argc == 1 && pkgname == NULL && condition == NULL && match == MATCH_EXACT) { match = MATCH_ALL; } else if ((argc == 1) ^ (match == MATCH_ALL) && pkgname == NULL && condition == NULL) { usage_query(); return (EX_USAGE); } if (analyse_query_string(argv[0], accepted_query_flags, q_flags_len, &query_flags, &multiline) != EPKG_OK) return (EX_USAGE); if (pkgname != NULL) { if (pkg_open(&pkg, pkgname) != EPKG_OK) { return (EX_IOERR); } print_query(pkg, argv[0], multiline); pkg_free(pkg); return (EX_OK); } if (condition != NULL) { sqlcond = sbuf_new_auto(); if (format_sql_condition(condition, sqlcond, false) != EPKG_OK) { sbuf_delete(sqlcond); return (EX_USAGE); } sbuf_finish(sqlcond); } ret = pkgdb_open(&db, PKGDB_DEFAULT); if (ret == EPKG_ENODB) { if (geteuid() == 0) return (EX_IOERR); /* do not fail if run as a user */ return (EX_OK); } if (ret != EPKG_OK) return (EX_IOERR); if (match == MATCH_ALL || match == MATCH_CONDITION) { const char *condition_sql = NULL; if (match == MATCH_CONDITION && sqlcond) condition_sql = sbuf_data(sqlcond); if ((it = pkgdb_query(db, condition_sql, match)) == NULL) return (EX_IOERR); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) print_query(pkg, argv[0], multiline); if (ret != EPKG_END) retcode = EX_SOFTWARE; pkgdb_it_free(it); } else { for (i = 1; i < argc; i++) { pkgname = argv[i]; if ((it = pkgdb_query(db, pkgname, match)) == NULL) return (EX_IOERR); while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) print_query(pkg, argv[0], multiline); if (ret != EPKG_END) { retcode = EX_SOFTWARE; break; } pkgdb_it_free(it); } } pkg_free(pkg); pkgdb_close(db); return (retcode); }
void read_pkg_file(void *data) { struct thd_data *d = (struct thd_data*) data; struct pkg_result *r; struct pkg_manifest_key *keys = NULL; FTSENT *fts_ent = NULL; char fts_accpath[MAXPATHLEN + 1]; char fts_path[MAXPATHLEN + 1]; char fts_name[MAXPATHLEN + 1]; off_t st_size; int fts_info, flags; char *ext = NULL; char *pkg_path; pkg_manifest_keys_new(&keys); for (;;) { fts_ent = NULL; /* * Get a file to read from. * Copy the data we need from the fts entry localy because as soon as * we unlock the fts_m mutex, we can not access it. */ pthread_mutex_lock(&d->fts_m); if (!d->stop) fts_ent = fts_read(d->fts); if (fts_ent != NULL) { strlcpy(fts_accpath, fts_ent->fts_accpath, sizeof(fts_accpath)); strlcpy(fts_path, fts_ent->fts_path, sizeof(fts_path)); strlcpy(fts_name, fts_ent->fts_name, sizeof(fts_name)); st_size = fts_ent->fts_statp->st_size; fts_info = fts_ent->fts_info; } pthread_mutex_unlock(&d->fts_m); // There is no more jobs, exit the main loop. if (fts_ent == NULL) break; /* skip everything that is not a file */ if (fts_info != FTS_F) continue; ext = strrchr(fts_name, '.'); if (ext == NULL) continue; if (strcmp(ext, ".tgz") != 0 && strcmp(ext, ".tbz") != 0 && strcmp(ext, ".txz") != 0 && strcmp(ext, ".tar") != 0) continue; *ext = '\0'; if (strcmp(fts_name, repo_db_archive) == 0 || strcmp(fts_name, repo_packagesite_archive) == 0 || strcmp(fts_name, repo_filesite_archive) == 0 || strcmp(fts_name, repo_digests_archive) == 0) continue; *ext = '.'; pkg_path = fts_path; pkg_path += strlen(d->root_path); while (pkg_path[0] == '/') pkg_path++; r = calloc(1, sizeof(struct pkg_result)); strlcpy(r->path, pkg_path, sizeof(r->path)); if (d->read_files) flags = PKG_OPEN_MANIFEST_ONLY; else flags = PKG_OPEN_MANIFEST_ONLY | PKG_OPEN_MANIFEST_COMPACT; if (pkg_open(&r->pkg, fts_accpath, keys, flags) != EPKG_OK) { r->retcode = EPKG_WARN; } else { sha256_file(fts_accpath, r->cksum); pkg_set(r->pkg, PKG_CKSUM, r->cksum, PKG_REPOPATH, pkg_path, PKG_PKGSIZE, st_size); } /* Add result to the FIFO and notify */ pthread_mutex_lock(&d->results_m); while (d->num_results >= d->max_results) { pthread_cond_wait(&d->has_room, &d->results_m); } LL_APPEND(d->results, r); d->num_results++; pthread_cond_signal(&d->has_result); pthread_mutex_unlock(&d->results_m); } /* * This thread is about to exit. * Notify the main thread that we are done. */ pthread_mutex_lock(&d->results_m); d->thd_finished++; pthread_cond_signal(&d->has_result); pthread_mutex_unlock(&d->results_m); pkg_manifest_keys_free(keys); }