static int pkg_repo_binary_add_pkg(struct pkg *pkg, const char *pkg_path, sqlite3 *sqlite, bool forced) { const char *name, *version, *origin, *comment, *desc; const char *arch, *maintainer, *www, *prefix, *sum, *rpath; const char *olddigest, *manifestdigest; int64_t flatsize, pkgsize; int64_t licenselogic; int ret; struct pkg_dep *dep = NULL; struct pkg_option *option = NULL; struct pkg_shlib *shlib = NULL; const pkg_object *obj, *licenses, *categories, *annotations; pkg_iter it; int64_t package_id; pkg_get(pkg, PKG_ORIGIN, &origin, PKG_NAME, &name, PKG_VERSION, &version, PKG_COMMENT, &comment, PKG_DESC, &desc, PKG_ARCH, &arch, PKG_MAINTAINER, &maintainer, PKG_WWW, &www, PKG_PREFIX, &prefix, PKG_FLATSIZE, &flatsize, PKG_LICENSE_LOGIC, &licenselogic, PKG_CKSUM, &sum, PKG_PKGSIZE, &pkgsize, PKG_REPOPATH, &rpath, PKG_LICENSES, &licenses, PKG_CATEGORIES, &categories, PKG_ANNOTATIONS, &annotations, PKG_OLD_DIGEST, &olddigest, PKG_DIGEST, &manifestdigest); try_again: if ((ret = pkg_repo_binary_run_prstatement(PKG, origin, name, version, comment, desc, arch, maintainer, www, prefix, pkgsize, flatsize, (int64_t)licenselogic, sum, rpath, manifestdigest, olddigest)) != SQLITE_DONE) { if (ret == SQLITE_CONSTRAINT) { switch(pkg_repo_binary_delete_conflicting(origin, version, pkg_path, forced)) { case EPKG_FATAL: /* sqlite error */ ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(PKG)); return (EPKG_FATAL); break; case EPKG_END: /* repo already has newer */ return (EPKG_END); break; default: /* conflict cleared, try again */ goto try_again; break; } } else { ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(PKG)); return (EPKG_FATAL); } } package_id = sqlite3_last_insert_rowid(sqlite); if (pkg_repo_binary_run_prstatement (FTS_APPEND, package_id, name, version, origin) != SQLITE_DONE) { ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(FTS_APPEND)); return (EPKG_FATAL); } dep = NULL; while (pkg_deps(pkg, &dep) == EPKG_OK) { if (pkg_repo_binary_run_prstatement(DEPS, pkg_dep_origin(dep), pkg_dep_name(dep), pkg_dep_version(dep), package_id) != SQLITE_DONE) { ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(DEPS)); return (EPKG_FATAL); } } it = NULL; while ((obj = pkg_object_iterate(categories, &it))) { ret = pkg_repo_binary_run_prstatement(CAT1, pkg_object_string(obj)); if (ret == SQLITE_DONE) ret = pkg_repo_binary_run_prstatement(CAT2, package_id, pkg_object_string(obj)); if (ret != SQLITE_DONE) { ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(CAT2)); return (EPKG_FATAL); } } it = NULL; while ((obj = pkg_object_iterate(licenses, &it))) { ret = pkg_repo_binary_run_prstatement(LIC1, pkg_object_string(obj)); if (ret == SQLITE_DONE) ret = pkg_repo_binary_run_prstatement(LIC2, package_id, pkg_object_string(obj)); if (ret != SQLITE_DONE) { ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(LIC2)); return (EPKG_FATAL); } } option = NULL; while (pkg_options(pkg, &option) == EPKG_OK) { ret = pkg_repo_binary_run_prstatement(OPT1, pkg_option_opt(option)); if (ret == SQLITE_DONE) ret = pkg_repo_binary_run_prstatement(OPT2, pkg_option_opt(option), pkg_option_value(option), package_id); if(ret != SQLITE_DONE) { ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(OPT2)); return (EPKG_FATAL); } } shlib = NULL; while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) { const char *shlib_name = pkg_shlib_name(shlib); ret = pkg_repo_binary_run_prstatement(SHLIB1, shlib_name); if (ret == SQLITE_DONE) ret = pkg_repo_binary_run_prstatement(SHLIB_REQD, package_id, shlib_name); if (ret != SQLITE_DONE) { ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(SHLIB_REQD)); return (EPKG_FATAL); } } shlib = NULL; while (pkg_shlibs_provided(pkg, &shlib) == EPKG_OK) { const char *shlib_name = pkg_shlib_name(shlib); ret = pkg_repo_binary_run_prstatement(SHLIB1, shlib_name); if (ret == SQLITE_DONE) ret = pkg_repo_binary_run_prstatement(SHLIB_PROV, package_id, shlib_name); if (ret != SQLITE_DONE) { ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(SHLIB_PROV)); return (EPKG_FATAL); } } it = NULL; while ((obj = pkg_object_iterate(annotations, &it))) { const char *note_tag = pkg_object_key(obj); const char *note_val = pkg_object_string(obj); ret = pkg_repo_binary_run_prstatement(ANNOTATE1, note_tag); if (ret == SQLITE_DONE) ret = pkg_repo_binary_run_prstatement(ANNOTATE1, note_val); if (ret == SQLITE_DONE) ret = pkg_repo_binary_run_prstatement(ANNOTATE2, package_id, note_tag, note_val); if (ret != SQLITE_DONE) { ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(ANNOTATE2)); return (EPKG_FATAL); } } return (EPKG_OK); }
void print_info(struct pkg * const pkg, unsigned int options) { struct pkg_category *cat = NULL; struct pkg_dep *dep = NULL; struct pkg_dir *dir = NULL; struct pkg_file *file = NULL; struct pkg_group *group = NULL; struct pkg_license *lic = NULL; struct pkg_option *option = NULL; struct pkg_shlib *shlib = NULL; struct pkg_user *user = NULL; bool multirepos_enabled = false; bool print_tag = false; bool show_locks = false; char size[7]; const char *name, *version, *prefix, *origin, *reponame, *repourl; const char *maintainer, *www, *comment, *desc, *message, *arch; const char *repopath; const char *tab; char *m; unsigned opt; int64_t flatsize, newflatsize, newpkgsize; lic_t licenselogic; bool locked; int cout = 0; /* Number of characters output */ int info_num; /* Number of different data items to print */ pkg_config_bool(PKG_CONFIG_MULTIREPOS, &multirepos_enabled); pkg_get(pkg, PKG_NAME, &name, PKG_VERSION, &version, PKG_PREFIX, &prefix, PKG_ORIGIN, &origin, PKG_REPONAME, &reponame, PKG_REPOURL, &repourl, PKG_MAINTAINER, &maintainer, PKG_WWW, &www, PKG_COMMENT, &comment, PKG_DESC, &desc, PKG_FLATSIZE, &flatsize, PKG_NEW_FLATSIZE, &newflatsize, PKG_NEW_PKGSIZE, &newpkgsize, PKG_LICENSE_LOGIC, &licenselogic, PKG_MESSAGE, &message, PKG_ARCH, &arch, PKG_REPOPATH, &repopath, PKG_LOCKED, &locked); if (!multirepos_enabled) pkg_config_string(PKG_CONFIG_REPO, &repourl); if (options & INFO_RAW) { /* Not for remote packages */ if (pkg_type(pkg) != PKG_REMOTE) { pkg_emit_manifest(pkg, &m); printf("%s\n", m); free(m); } return; } /* Show locking status when requested to display it and the package is locally installed */ if (pkg_type(pkg) == PKG_INSTALLED && (options & INFO_LOCKED) != 0) show_locks = true; if (!quiet) { /* Print a tag-line identifying the package -- either NAMEVER, ORIGIN or NAME (in that order of preference). This may be the only output from this function */ if (options & INFO_TAG_NAMEVER) cout = printf("%s-%s", name, version); else if (options & INFO_TAG_ORIGIN) cout = printf("%s", origin); else if (options & INFO_TAG_NAME) cout = printf("%s", name); } /* Don't display a tab if quiet, retains compatibility. */ tab = quiet ? "" : "\t"; /* If we printed a tag, and there are no other items to print, then just return now. If there's only one single-line item to print, show it at column 32 on the same line. If there's one multi-line item to print, start a new line. If there is more than one item to print per pkg, use 'key : value' style to show on a new line. */ info_num = 0; for (opt = 0x1U; opt <= INFO_LASTFIELD; opt <<= 1) if ((opt & options) != 0) info_num++; if (info_num == 0 && cout > 0) { printf("\n"); return; } if (info_num == 1) { /* Only one item to print */ print_tag = false; if (!quiet) { if (options & INFO_MULTILINE) printf(":\n"); else { if (cout < 31) cout = 31 - cout; else cout = 1; printf("%*s", cout, " "); } } } else { /* Several items to print */ print_tag = true; if (!quiet) printf("\n"); } for (opt = 0x1; opt <= INFO_LASTFIELD; opt <<= 1) { if ((opt & options) == 0) continue; switch (opt) { case INFO_NAME: if (print_tag) printf("%-15s: ", "Name"); printf("%s\n", name); break; case INFO_VERSION: if (print_tag) printf("%-15s: ", "Version"); printf("%s\n", version); break; case INFO_ORIGIN: if (print_tag) printf("%-15s: ", "Origin"); printf("%s\n", origin); break; case INFO_PREFIX: if (print_tag) printf("%-15s: ", "Prefix"); printf("%s\n", prefix); break; case INFO_REPOSITORY: if (pkg_type(pkg) == PKG_REMOTE && repourl != NULL && repourl[0] != '\0') { if (print_tag) printf("%-15s: ", "Repository"); printf("%s [%s]\n", reponame, repourl); } else if (!print_tag) printf("\n"); break; case INFO_CATEGORIES: if (pkg_list_count(pkg, PKG_CATEGORIES) > 0) { if (print_tag) printf("%-15s: ", "Categories"); if (pkg_categories(pkg, &cat) == EPKG_OK) printf("%s", pkg_category_name(cat)); while (pkg_categories(pkg, &cat) == EPKG_OK) printf(" %s", pkg_category_name(cat)); printf("\n"); } else if (!print_tag) printf("\n"); break; case INFO_LICENSES: if (pkg_list_count(pkg, PKG_LICENSES) > 0) { if (print_tag) printf("%-15s: ", "Licenses"); if (pkg_licenses(pkg, &lic) == EPKG_OK) printf("%s", pkg_license_name(lic)); while (pkg_licenses(pkg, &lic) == EPKG_OK) { if (licenselogic != 1) printf(" %c", licenselogic); printf(" %s", pkg_license_name(lic)); } printf("\n"); } else if (!print_tag) printf("\n"); break; case INFO_MAINTAINER: if (print_tag) printf("%-15s: ", "Maintainer"); printf("%s\n", maintainer); break; case INFO_WWW: if (print_tag) printf("%-15s: ", "WWW"); printf("%s\n", www); break; case INFO_COMMENT: if (print_tag) printf("%-15s: ", "Comment"); printf("%s\n", comment); break; case INFO_OPTIONS: if (pkg_list_count(pkg, PKG_OPTIONS) > 0) { if (print_tag) printf("%-15s:\n", "Options"); while (pkg_options(pkg, &option) == EPKG_OK) printf("%s%-15s: %s\n", tab, pkg_option_opt(option), pkg_option_value(option)); } break; case INFO_SHLIBS_REQUIRED: if (pkg_list_count(pkg, PKG_SHLIBS_REQUIRED) > 0) { if (print_tag) printf("%-15s:\n", "Shared Libs required"); while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) printf("%s%s\n", tab, pkg_shlib_name(shlib)); } break; case INFO_SHLIBS_PROVIDED: if (pkg_list_count(pkg, PKG_SHLIBS_PROVIDED) > 0) { if (print_tag) printf("%-15s:\n", "Shared Libs provided"); while (pkg_shlibs_provided(pkg, &shlib) == EPKG_OK) printf("%s%s\n", tab, pkg_shlib_name(shlib)); } break; case INFO_FLATSIZE: if (pkg_type(pkg) == PKG_INSTALLED || pkg_type(pkg) == PKG_FILE) humanize_number(size, sizeof(size), flatsize,"B", HN_AUTOSCALE, 0); else humanize_number(size, sizeof(size), newflatsize,"B", HN_AUTOSCALE, 0); if (print_tag) printf("%-15s: ", "Flat size"); printf("%s\n", size); break; case INFO_PKGSIZE: /* Remote pkgs only */ if (pkg_type(pkg) == PKG_REMOTE) { humanize_number(size, sizeof(size), newpkgsize,"B", HN_AUTOSCALE, 0); if (print_tag) printf("%-15s: ", "Pkg size"); printf("%s\n", size); } else if (!print_tag) printf("\n"); break; case INFO_DESCR: if (print_tag) printf("%-15s:\n", "Description"); printf("%s\n", desc); break; case INFO_MESSAGE: if (message) { if (print_tag) printf("%-15s:\n", "Message"); printf("%s\n", message); } break; case INFO_DEPS: if (pkg_list_count(pkg, PKG_DEPS) > 0) { if (print_tag) printf("%-15s:\n", "Depends on"); while (pkg_deps(pkg, &dep) == EPKG_OK) { printf("%s%s-%s", tab, pkg_dep_name(dep), pkg_dep_version(dep)); if (show_locks && pkg_dep_is_locked(dep)) printf(" (*)"); printf("\n"); } } break; case INFO_RDEPS: if (pkg_list_count(pkg, PKG_RDEPS) > 0) { if (print_tag) printf("%-15s:\n", "Required by"); while (pkg_rdeps(pkg, &dep) == EPKG_OK) { printf("%s%s-%s", tab, pkg_dep_name(dep), pkg_dep_version(dep)); if (show_locks && pkg_dep_is_locked(dep)) printf(" (*)"); printf("\n"); } } break; case INFO_FILES: /* Installed pkgs only */ if (pkg_type(pkg) != PKG_REMOTE && pkg_list_count(pkg, PKG_FILES) > 0) { if (print_tag) printf("%-15s:\n", "Files"); while (pkg_files(pkg, &file) == EPKG_OK) printf("%s%s\n", tab, pkg_file_path(file)); } break; case INFO_DIRS: /* Installed pkgs only */ if (pkg_type(pkg) != PKG_REMOTE && pkg_list_count(pkg, PKG_DIRS) > 0) { if (print_tag) printf("%-15s:\n", "Directories"); while (pkg_dirs(pkg, &dir) == EPKG_OK) printf("%s%s\n", tab, pkg_dir_path(dir)); } break; case INFO_USERS: /* Installed pkgs only */ if (pkg_type(pkg) != PKG_REMOTE && pkg_list_count(pkg, PKG_USERS) > 0) { if (print_tag) printf("%-15s: ", "Users"); if (pkg_users(pkg, &user) == EPKG_OK) printf("%s", pkg_user_name(user)); while (pkg_users(pkg, &user) == EPKG_OK) printf(" %s", pkg_user_name(user)); printf("\n"); } break; case INFO_GROUPS: /* Installed pkgs only */ if (pkg_type(pkg) != PKG_REMOTE && pkg_list_count(pkg, PKG_GROUPS) > 0) { if (print_tag) printf("%-15s: ", "Groups"); if (pkg_groups(pkg, &group) == EPKG_OK) printf("%s", pkg_group_name(group)); while (pkg_groups(pkg, &group) == EPKG_OK) printf(" %s", pkg_group_name(group)); printf("\n"); } break; case INFO_ARCH: if (print_tag) printf("%-15s: ", "Architecture"); printf("%s\n", arch); break; case INFO_REPOURL: if (pkg_type(pkg) == PKG_REMOTE && repourl != NULL && repourl[0] != '\0') { if (print_tag) printf("%-15s: ", "Pkg URL"); if (repourl[strlen(repourl) -1] == '/') printf("%s%s\n", repourl, repopath); else printf("%s/%s\n", repourl, repopath); } else if (!print_tag) printf("\n"); break; case INFO_LOCKED: if (print_tag) printf("%-15s: ", "Locked"); printf("%s\n", locked ? "yes" : "no"); break; } } }
static void format_str(struct pkg *pkg, struct sbuf *dest, const char *qstr, void *data) { char size[7]; const char *tmp; bool tmp2; int64_t flatsize; int64_t timestamp; lic_t licenselogic; sbuf_clear(dest); while (qstr[0] != '\0') { if (qstr[0] == '%') { qstr++; switch (qstr[0]) { case 'n': pkg_get(pkg, PKG_NAME, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'v': pkg_get(pkg, PKG_VERSION, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'o': pkg_get(pkg, PKG_ORIGIN, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'R': pkg_get(pkg, PKG_REPONAME, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'p': pkg_get(pkg, PKG_PREFIX, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'm': pkg_get(pkg, PKG_MAINTAINER, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'c': pkg_get(pkg, PKG_COMMENT, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'w': pkg_get(pkg, PKG_WWW, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'i': pkg_get(pkg, PKG_INFOS, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case 'a': pkg_get(pkg, PKG_AUTOMATIC, &tmp2); sbuf_printf(dest, "%d", tmp2); break; case 'k': pkg_get(pkg, PKG_LOCKED, &tmp2); sbuf_printf(dest, "%d", tmp2); break; case 't': pkg_get(pkg, PKG_TIME, ×tamp); sbuf_printf(dest, "%" PRId64, timestamp); break; case 's': qstr++; pkg_get(pkg, PKG_FLATSIZE, &flatsize); if (qstr[0] == 'h') { humanize_number(size, sizeof(size), flatsize, "B", HN_AUTOSCALE, 0); sbuf_cat(dest, size); } else if (qstr[0] == 'b') { sbuf_printf(dest, "%" PRId64, flatsize); } break; case 'e': pkg_get(pkg, PKG_DESC, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case '?': qstr++; switch (qstr[0]) { case 'd': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_DEPS) > 0); break; case 'r': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_RDEPS) > 0); break; case 'C': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_CATEGORIES) > 0); break; case 'F': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_FILES) > 0); break; case 'O': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_OPTIONS) > 0); break; case 'D': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_DIRS) > 0); break; case 'L': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_LICENSES) > 0); break; case 'U': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_USERS) > 0); break; case 'G': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_GROUPS) > 0); break; case 'B': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_SHLIBS_REQUIRED) > 0); break; case 'b': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_SHLIBS_PROVIDED) > 0); break; case 'A': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_ANNOTATIONS) > 0); break; } break; case '#': qstr++; switch (qstr[0]) { case 'd': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_DEPS)); break; case 'r': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_RDEPS)); break; case 'C': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_CATEGORIES)); break; case 'F': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_FILES)); break; case 'O': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_OPTIONS)); break; case 'D': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_DIRS)); break; case 'L': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_LICENSES)); break; case 'U': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_USERS)); break; case 'G': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_GROUPS)); break; case 'B': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_SHLIBS_REQUIRED)); break; case 'b': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_SHLIBS_PROVIDED)); break; case 'A': sbuf_printf(dest, "%d", pkg_list_count(pkg, PKG_ANNOTATIONS)); break; } break; case 'l': pkg_get(pkg, PKG_LICENSE_LOGIC, &licenselogic); switch (licenselogic) { case LICENSE_SINGLE: sbuf_cat(dest, "single"); break; case LICENSE_OR: sbuf_cat(dest, "or"); break; case LICENSE_AND: sbuf_cat(dest, "and"); break; } break; case 'd': qstr++; if (qstr[0] == 'n') sbuf_cat(dest, pkg_dep_name((struct pkg_dep *)data)); else if (qstr[0] == 'o') sbuf_cat(dest, pkg_dep_origin((struct pkg_dep *)data)); else if (qstr[0] == 'v') sbuf_cat(dest, pkg_dep_version((struct pkg_dep *)data)); break; case 'r': qstr++; if (qstr[0] == 'n') sbuf_cat(dest, pkg_dep_name((struct pkg_dep *)data)); else if (qstr[0] == 'o') sbuf_cat(dest, pkg_dep_origin((struct pkg_dep *)data)); else if (qstr[0] == 'v') sbuf_cat(dest, pkg_dep_version((struct pkg_dep *)data)); break; case 'C': sbuf_cat(dest, pkg_category_name((struct pkg_category *)data)); break; case 'F': qstr++; if (qstr[0] == 'p') sbuf_cat(dest, pkg_file_path((struct pkg_file *)data)); else if (qstr[0] == 's') sbuf_cat(dest, pkg_file_cksum((struct pkg_file *)data)); break; case 'O': qstr++; if (qstr[0] == 'k') sbuf_cat(dest, pkg_option_opt((struct pkg_option *)data)); else if (qstr[0] == 'v') sbuf_cat(dest, pkg_option_value((struct pkg_option *)data)); break; case 'D': sbuf_cat(dest, pkg_dir_path((struct pkg_dir *)data)); break; case 'L': sbuf_cat(dest, pkg_license_name((struct pkg_license *)data)); break; case 'U': sbuf_cat(dest, pkg_user_name((struct pkg_user *)data)); break; case 'G': sbuf_cat(dest, pkg_group_name((struct pkg_group *)data)); break; case 'B': case 'b': sbuf_cat(dest, pkg_shlib_name((struct pkg_shlib *)data)); break; case 'A': qstr++; if (qstr[0] == 't') sbuf_cat(dest, pkg_annotation_tag((struct pkg_note *)data)); else if (qstr[0] == 'v') sbuf_cat(dest, pkg_annotation_value((struct pkg_note *)data)); break; case 'M': pkg_get(pkg, PKG_MESSAGE, &tmp); if (tmp != NULL) sbuf_cat(dest, tmp); break; case '%': sbuf_putc(dest, '%'); break; } } else if (qstr[0] == '\\') { qstr++; switch (qstr[0]) { case 'n': sbuf_putc(dest, '\n'); break; case 'a': sbuf_putc(dest, '\a'); break; case 'b': sbuf_putc(dest, '\b'); break; case 'f': sbuf_putc(dest, '\f'); break; case 'r': sbuf_putc(dest, '\r'); break; case '\\': sbuf_putc(dest, '\\'); break; case 't': sbuf_putc(dest, '\t'); break; } } else { sbuf_putc(dest, qstr[0]); } qstr++; } sbuf_finish(dest); }
int pkg_create_repo(char *path, bool force, void (progress)(struct pkg *pkg, void *data), void *data) { FTS *fts = NULL; struct thd_data thd_data; int num_workers; size_t len; pthread_t *tids = NULL; struct pkg_dep *dep = NULL; struct pkg_category *category = NULL; struct pkg_license *license = NULL; struct pkg_option *option = NULL; struct pkg_shlib *shlib = NULL; sqlite3 *sqlite = NULL; int64_t package_id; char *errmsg = NULL; int retcode = EPKG_OK; int ret; char *repopath[2]; char repodb[MAXPATHLEN + 1]; char repopack[MAXPATHLEN + 1]; struct archive *a = NULL; struct archive_entry *ae = NULL; if (!is_dir(path)) { pkg_emit_error("%s is not a directory", path); return (EPKG_FATAL); } repopath[0] = path; repopath[1] = NULL; len = sizeof(num_workers); if (sysctlbyname("hw.ncpu", &num_workers, &len, NULL, 0) == -1) num_workers = 6; if ((fts = fts_open(repopath, FTS_PHYSICAL|FTS_NOCHDIR, NULL)) == NULL) { pkg_emit_errno("fts_open", path); retcode = EPKG_FATAL; goto cleanup; } snprintf(repodb, sizeof(repodb), "%s/repo.sqlite", path); snprintf(repopack, sizeof(repopack), "%s/repo.txz", path); if (access(repopack, F_OK) == 0) { a = archive_read_new(); archive_read_support_compression_all(a); archive_read_support_format_tar(a); ret = archive_read_open_filename(a, repopack, 4096); if (ret != ARCHIVE_OK) { /* if we can't unpack it it won't be useful for us */ unlink(repopack); } else { while (archive_read_next_header(a, &ae) == ARCHIVE_OK) { if (!strcmp(archive_entry_pathname(ae), "repo.sqlite")) { archive_entry_set_pathname(ae, repodb); archive_read_extract(a, ae, EXTRACT_ARCHIVE_FLAGS); break; } } } if (a != NULL) archive_read_finish(a); } if ((retcode = initialize_repo(repodb, force, &sqlite)) != EPKG_OK) goto cleanup; if ((retcode = initialize_prepared_statements(sqlite)) != EPKG_OK) goto cleanup; thd_data.root_path = path; thd_data.max_results = num_workers; thd_data.num_results = 0; thd_data.stop = false; thd_data.fts = fts; pthread_mutex_init(&thd_data.fts_m, NULL); STAILQ_INIT(&thd_data.results); thd_data.thd_finished = 0; pthread_mutex_init(&thd_data.results_m, NULL); pthread_cond_init(&thd_data.has_result, NULL); pthread_cond_init(&thd_data.has_room, NULL); /* Launch workers */ tids = calloc(num_workers, sizeof(pthread_t)); for (int i = 0; i < num_workers; i++) { pthread_create(&tids[i], NULL, (void *)&read_pkg_file, &thd_data); } for (;;) { struct pkg_result *r; const char *name, *version, *origin, *comment, *desc; const char *arch, *maintainer, *www, *prefix; int64_t flatsize; lic_t licenselogic; pthread_mutex_lock(&thd_data.results_m); while ((r = STAILQ_FIRST(&thd_data.results)) == NULL) { if (thd_data.thd_finished == num_workers) { break; } pthread_cond_wait(&thd_data.has_result, &thd_data.results_m); } if (r != NULL) { STAILQ_REMOVE_HEAD(&thd_data.results, next); thd_data.num_results--; pthread_cond_signal(&thd_data.has_room); } pthread_mutex_unlock(&thd_data.results_m); if (r == NULL) { break; } if (r->retcode != EPKG_OK) { continue; } /* do not add if package if already in repodb (possibly at a different pkg_path) */ if (run_prepared_statement(EXISTS, r->cksum) != SQLITE_ROW) { ERROR_SQLITE(sqlite); goto cleanup; } if (sqlite3_column_int(STMT(EXISTS), 0) > 0) { continue; } if (progress != NULL) progress(r->pkg, data); pkg_get(r->pkg, PKG_ORIGIN, &origin, PKG_NAME, &name, PKG_VERSION, &version, PKG_COMMENT, &comment, PKG_DESC, &desc, PKG_ARCH, &arch, PKG_MAINTAINER, &maintainer, PKG_WWW, &www, PKG_PREFIX, &prefix, PKG_FLATSIZE, &flatsize, PKG_LICENSE_LOGIC, &licenselogic); try_again: if ((ret = run_prepared_statement(PKG, origin, name, version, comment, desc, arch, maintainer, www, prefix, r->size, flatsize, (int64_t)licenselogic, r->cksum, r->path)) != SQLITE_DONE) { if (ret == SQLITE_CONSTRAINT) { switch(maybe_delete_conflicting(origin, version, r->path)) { case EPKG_FATAL: /* sqlite error */ ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; break; case EPKG_END: /* repo already has newer */ continue; break; default: /* conflict cleared, try again */ goto try_again; break; } } else { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } } package_id = sqlite3_last_insert_rowid(sqlite); dep = NULL; while (pkg_deps(r->pkg, &dep) == EPKG_OK) { if (run_prepared_statement(DEPS, pkg_dep_origin(dep), pkg_dep_name(dep), pkg_dep_version(dep), package_id) != SQLITE_DONE) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } } category = NULL; while (pkg_categories(r->pkg, &category) == EPKG_OK) { const char *cat_name = pkg_category_name(category); ret = run_prepared_statement(CAT1, cat_name); if (ret == SQLITE_DONE) ret = run_prepared_statement(CAT2, package_id, cat_name); if (ret != SQLITE_DONE) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } } license = NULL; while (pkg_licenses(r->pkg, &license) == EPKG_OK) { const char *lic_name = pkg_license_name(license); ret = run_prepared_statement(LIC1, lic_name); if (ret == SQLITE_DONE) ret = run_prepared_statement(LIC2, package_id, lic_name); if (ret != SQLITE_DONE) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } } option = NULL; while (pkg_options(r->pkg, &option) == EPKG_OK) { if (run_prepared_statement(OPTS, pkg_option_opt(option), pkg_option_value(option), package_id) != SQLITE_DONE) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } } shlib = NULL; while (pkg_shlibs(r->pkg, &shlib) == EPKG_OK) { const char *shlib_name = pkg_shlib_name(shlib); ret = run_prepared_statement(SHLIB1, shlib_name); if (ret == SQLITE_DONE) ret = run_prepared_statement(SHLIB2, package_id, shlib_name); if (ret != SQLITE_DONE) { ERROR_SQLITE(sqlite); retcode = EPKG_FATAL; goto cleanup; } } pkg_free(r->pkg); free(r); } if (pkgdb_transaction_commit(sqlite, NULL) != SQLITE_OK) retcode = EPKG_FATAL; cleanup: if (tids != NULL) { // Cancel running threads if (retcode != EPKG_OK) { pthread_mutex_lock(&thd_data.fts_m); thd_data.stop = true; pthread_mutex_unlock(&thd_data.fts_m); } // Join on threads to release thread IDs for (int i = 0; i < num_workers; i++) { pthread_join(tids[i], NULL); } free(tids); } if (fts != NULL) fts_close(fts); finalize_prepared_statements(); if (sqlite != NULL) sqlite3_close(sqlite); if (errmsg != NULL) sqlite3_free(errmsg); sqlite3_shutdown(); return (retcode); }
int pkgdb_repo_add_package(struct pkg *pkg, const char *pkg_path, sqlite3 *sqlite, const char *manifest_digest, bool forced) { const char *name, *version, *origin, *comment, *desc; const char *arch, *maintainer, *www, *prefix, *sum, *rpath; int64_t flatsize, pkgsize; lic_t licenselogic; int ret; struct pkg_dep *dep = NULL; struct pkg_category *category = NULL; struct pkg_license *license = NULL; struct pkg_option *option = NULL; struct pkg_shlib *shlib = NULL; struct pkg_note *note = NULL; int64_t package_id; pkg_get(pkg, PKG_ORIGIN, &origin, PKG_NAME, &name, PKG_VERSION, &version, PKG_COMMENT, &comment, PKG_DESC, &desc, PKG_ARCH, &arch, PKG_MAINTAINER, &maintainer, PKG_WWW, &www, PKG_PREFIX, &prefix, PKG_FLATSIZE, &flatsize, PKG_LICENSE_LOGIC, &licenselogic, PKG_CKSUM, &sum, PKG_PKGSIZE, &pkgsize, PKG_REPOPATH, &rpath); try_again: if ((ret = run_prepared_statement(PKG, origin, name, version, comment, desc, arch, maintainer, www, prefix, pkgsize, flatsize, (int64_t)licenselogic, sum, rpath, manifest_digest)) != SQLITE_DONE) { if (ret == SQLITE_CONSTRAINT) { switch(maybe_delete_conflicting(origin, version, pkg_path, forced)) { case EPKG_FATAL: /* sqlite error */ ERROR_SQLITE(sqlite); return (EPKG_FATAL); break; case EPKG_END: /* repo already has newer */ return (EPKG_END); break; default: /* conflict cleared, try again */ goto try_again; break; } } else { ERROR_SQLITE(sqlite); return (EPKG_FATAL); } } package_id = sqlite3_last_insert_rowid(sqlite); dep = NULL; while (pkg_deps(pkg, &dep) == EPKG_OK) { if (run_prepared_statement(DEPS, pkg_dep_origin(dep), pkg_dep_name(dep), pkg_dep_version(dep), package_id) != SQLITE_DONE) { ERROR_SQLITE(sqlite); return (EPKG_FATAL); } } category = NULL; while (pkg_categories(pkg, &category) == EPKG_OK) { const char *cat_name = pkg_category_name(category); ret = run_prepared_statement(CAT1, cat_name); if (ret == SQLITE_DONE) ret = run_prepared_statement(CAT2, package_id, cat_name); if (ret != SQLITE_DONE) { ERROR_SQLITE(sqlite); return (EPKG_FATAL); } } license = NULL; while (pkg_licenses(pkg, &license) == EPKG_OK) { const char *lic_name = pkg_license_name(license); ret = run_prepared_statement(LIC1, lic_name); if (ret == SQLITE_DONE) ret = run_prepared_statement(LIC2, package_id, lic_name); if (ret != SQLITE_DONE) { ERROR_SQLITE(sqlite); return (EPKG_FATAL); } } option = NULL; while (pkg_options(pkg, &option) == EPKG_OK) { ret = run_prepared_statement(OPT1, pkg_option_opt(option)); if (ret == SQLITE_DONE) ret = run_prepared_statement(OPT2, pkg_option_opt(option), pkg_option_value(option), package_id); if(ret != SQLITE_DONE) { ERROR_SQLITE(sqlite); return (EPKG_FATAL); } } shlib = NULL; while (pkg_shlibs_required(pkg, &shlib) == EPKG_OK) { const char *shlib_name = pkg_shlib_name(shlib); ret = run_prepared_statement(SHLIB1, shlib_name); if (ret == SQLITE_DONE) ret = run_prepared_statement(SHLIB_REQD, package_id, shlib_name); if (ret != SQLITE_DONE) { ERROR_SQLITE(sqlite); return (EPKG_FATAL); } } shlib = NULL; while (pkg_shlibs_provided(pkg, &shlib) == EPKG_OK) { const char *shlib_name = pkg_shlib_name(shlib); ret = run_prepared_statement(SHLIB1, shlib_name); if (ret == SQLITE_DONE) ret = run_prepared_statement(SHLIB_PROV, package_id, shlib_name); if (ret != SQLITE_DONE) { ERROR_SQLITE(sqlite); return (EPKG_FATAL); } } note = NULL; while (pkg_annotations(pkg, ¬e) == EPKG_OK) { const char *note_tag = pkg_annotation_tag(note); const char *note_val = pkg_annotation_value(note); ret = run_prepared_statement(ANNOTATE1, note_tag); if (ret == SQLITE_DONE) ret = run_prepared_statement(ANNOTATE1, note_val); if (ret == SQLITE_DONE) ret = run_prepared_statement(ANNOTATE2, package_id, note_tag, note_val); if (ret != SQLITE_DONE) { ERROR_SQLITE(sqlite); return (EPKG_FATAL); } } return (EPKG_OK); }