int exec_search(int argc, char **argv) { const char *pattern = NULL; const char *reponame = NULL; int ret = EPKG_OK, ch; int flags; uint64_t opt = 0; match_t match = MATCH_REGEX; pkgdb_field search = FIELD_NONE; pkgdb_field label = FIELD_NONE; struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; bool atleastone = false; bool old_quiet; struct option longopts[] = { { "case-sensitive", no_argument, NULL, 'C' }, { "comment", no_argument, NULL, 'c' }, { "description", no_argument, NULL, 'D' }, { "depends-on", no_argument, NULL, 'd' }, { "exact", no_argument, NULL, 'e' }, { "full", no_argument, NULL, 'f' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "label", required_argument, NULL, 'L' }, { "origins", no_argument, NULL, 'o' }, { "prefix", no_argument, NULL, 'p' }, { "quiet", no_argument, NULL, 'q' }, { "query-modifier", required_argument, NULL, 'Q' }, { "repository", required_argument, NULL, 'r' }, { "raw", no_argument, NULL, 'R' }, { "search", required_argument, NULL, 'S' }, { "size", no_argument, NULL, 's' }, { "no-repo-update", no_argument, NULL, 'U' }, { "regex", no_argument, NULL, 'x' }, { "raw-format", required_argument, NULL, 1 }, { NULL, 0, NULL, 0 }, }; while ((ch = getopt_long(argc, argv, "+CcDdefgiL:opqQ:r:RS:sUx", longopts, NULL)) != -1) { switch (ch) { case 'C': pkgdb_set_case_sensitivity(true); break; case 'c': /* Same as -S comment */ search = search_label_opt("comment"); break; case 'D': /* Same as -S description */ search = search_label_opt("description"); break; case 'd': /* Same as -Q depends-on */ opt |= modifier_opt("depends-on"); break; case 'e': match = MATCH_EXACT; break; case 'f': /* Same as -Q full */ opt |= modifier_opt("full"); break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'L': label = search_label_opt(optarg); break; case 'o': /* Same as -L origin */ label = search_label_opt("origin"); break; case 'p': /* Same as -Q prefix */ opt |= modifier_opt("prefix"); break; case 'q': quiet = true; break; case 'Q': opt |= modifier_opt(optarg); break; case 'r': reponame = optarg; break; case 'R': opt = INFO_RAW; break; case 'S': search = search_label_opt(optarg); break; case 's': /* Same as -Q size */ opt |= modifier_opt("size"); break; case 'U': auto_update = false; break; case 'x': match = MATCH_REGEX; break; case 1: if (strcasecmp(optarg, "json") == 0) opt |= INFO_RAW_JSON; else if (strcasecmp(optarg, "json-compact") == 0) opt |= INFO_RAW_JSON_COMPACT; else if (strcasecmp(optarg, "yaml") == 0) opt |= INFO_RAW_YAML; else if (strcasecmp(optarg, "ucl") == 0) opt |= INFO_RAW_UCL; else errx(EX_USAGE, "Invalid format '%s' for the " "raw output, expecting json, json-compact " "or yaml", optarg); break; default: usage_search(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc != 1) { usage_search(); return (EX_USAGE); } pattern = argv[0]; if (pattern[0] == '\0') { fprintf(stderr, "Pattern must not be empty.\n"); return (EX_USAGE); } if (search == FIELD_NONE) { if (strchr(pattern, '/') != NULL) search = FIELD_ORIGIN; else search = FIELD_NAMEVER; /* Default search */ } if (label == FIELD_NONE) label = search; /* By default, show what was searched */ switch(label) { case FIELD_NONE: break; /* should never happen */ case FIELD_ORIGIN: opt |= INFO_TAG_ORIGIN|INFO_COMMENT; break; case FIELD_NAME: opt |= INFO_TAG_NAME|INFO_COMMENT; break; case FIELD_NAMEVER: opt |= INFO_TAG_NAMEVER|INFO_COMMENT; break; case FIELD_COMMENT: opt |= INFO_TAG_NAMEVER|INFO_COMMENT; break; case FIELD_DESC: opt |= INFO_TAG_NAMEVER|INFO_DESCR; break; } if (quiet) { opt = INFO_TAG_NAMEVER; quiet = false; } ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_REPO); switch(ret) { case EPKG_ENOACCESS: warnx("Insufficient privileges to query the package database"); return (EX_NOPERM); case EPKG_ENODB: if (!auto_update) { warnx("Unable to open remote repository catalogues. Try running '%s update' first.", getprogname()); return (EX_IOERR); } break; case EPKG_OK: break; default: return (EX_IOERR); } /* first update the remote repositories if needed */ old_quiet = quiet; quiet = true; if (auto_update && (ret = pkgcli_update(false, false, reponame)) != EPKG_OK) return (ret); quiet = old_quiet; if (pkgdb_open_all(&db, PKGDB_REMOTE, reponame) != EPKG_OK) return (EX_IOERR); if ((it = pkgdb_repo_search(db, pattern, match, search, search, reponame)) == NULL) { pkgdb_close(db); return (EX_IOERR); } if (opt & INFO_RAW) { if ((opt & (INFO_RAW_JSON|INFO_RAW_JSON_COMPACT)) == 0) opt |= INFO_RAW_YAML; } flags = info_flags(opt, true); while ((ret = pkgdb_it_next(it, &pkg, flags)) == EPKG_OK) { print_info(pkg, opt); atleastone = true; } pkg_free(pkg); pkgdb_it_free(it); pkgdb_close(db); if (!atleastone) ret = EPKG_FATAL; return ((ret == EPKG_OK || ret == EPKG_END) ? EX_OK : EX_SOFTWARE); }
int exec_info(int argc, char **argv) { struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; int query_flags; struct pkg *pkg = NULL; uint64_t opt = INFO_TAG_NAMEVER; match_t match = MATCH_GLOB; char *pkgname; char *pkgversion = NULL, *pkgversion2 = NULL; const char *file = NULL; int ch, fd; int ret = EPKG_OK; int retcode = 0; bool gotone = false; int i, j; int sign = 0; int sign2 = 0; int open_flags = 0; bool pkg_exists = false; bool origin_search = false; bool e_flag = false; struct pkg_manifest_key *keys = NULL; #ifdef HAVE_CAPSICUM cap_rights_t rights; #endif struct option longopts[] = { { "all", no_argument, NULL, 'a' }, { "annotations", no_argument, NULL, 'A' }, { "provided-shlibs", no_argument, NULL, 'b' }, { "required-shlibs", no_argument, NULL, 'B' }, { "case-sensitive", no_argument, NULL, 'C' }, { "dependencies", no_argument, NULL, 'd' }, { "pkg-message", no_argument, NULL, 'D' }, { "exists", no_argument, NULL, 'e' }, { "show-name-only", no_argument, NULL, 'E' }, { "full", no_argument, NULL, 'f' }, { "file", required_argument, NULL, 'F' }, { "glob", no_argument, NULL, 'g' }, { "case-insensitive", no_argument, NULL, 'i' }, { "comment", no_argument, NULL, 'I' }, { "locked", no_argument, NULL, 'k' }, { "list-files", no_argument, NULL, 'l' }, { "origin", no_argument, NULL, 'o' }, { "by-origin", no_argument, NULL, 'O' }, { "prefix", no_argument, NULL, 'p' }, { "quiet", no_argument, NULL, 'q' }, { "required-by", no_argument, NULL, 'r' }, { "raw", no_argument, NULL, 'R' }, { "size", no_argument, NULL, 's' }, { "regex", no_argument, NULL, 'x' }, { "raw-format", required_argument, NULL, 1 }, { NULL, 0, NULL, 0 }, }; /* TODO: exclusive opts ? */ while ((ch = getopt_long(argc, argv, "+aAbBCdDeEfF:giIkloOpqrRsx", longopts, NULL)) != -1) { switch (ch) { case 'a': match = MATCH_ALL; break; case 'A': opt |= INFO_ANNOTATIONS; break; case 'b': opt |= INFO_SHLIBS_PROVIDED; break; case 'B': opt |= INFO_SHLIBS_REQUIRED; break; case 'C': pkgdb_set_case_sensitivity(true); break; case 'd': opt |= INFO_DEPS; break; case 'D': opt |= INFO_MESSAGE; break; case 'e': pkg_exists = true;; retcode = 1; break; case 'E': /* ports compatibility */ e_flag = true; break; case 'f': opt |= INFO_FULL; break; case 'F': file = optarg; break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'I': opt |= INFO_COMMENT; break; case 'k': opt |= INFO_LOCKED; break; case 'l': opt |= INFO_FILES; break; case 'o': opt |= INFO_ORIGIN; break; case 'O': origin_search = true; /* only for ports compat */ break; case 'p': opt |= INFO_PREFIX; break; case 'q': quiet = true; break; case 'r': opt |= INFO_RDEPS; break; case 'R': opt |= INFO_RAW; break; case 's': opt |= INFO_FLATSIZE; break; case 'x': match = MATCH_REGEX; break; case 1: if (strcasecmp(optarg, "json") == 0) opt |= INFO_RAW_JSON; else if (strcasecmp(optarg, "json-compact") == 0) opt |= INFO_RAW_JSON_COMPACT; else if (strcasecmp(optarg, "yaml") == 0) opt |= INFO_RAW_YAML; else if (strcasecmp(optarg, "ucl") == 0) opt |= INFO_RAW_UCL; else errx(EX_USAGE, "Invalid format '%s' for the " "raw output, expecting json, json-compact " "or yaml", optarg); break; default: usage_info(); return(EX_USAGE); } } if (argc == 1 || (argc == 2 && quiet)) 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 ((fd = open(file, O_RDONLY)) == -1) { warn("Unable to open %s", file); return (EX_IOERR); } #ifdef HAVE_CAPSICUM cap_rights_init(&rights, CAP_READ, CAP_FSTAT); if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS ) { warn("cap_rights_limit() failed"); close(fd); return (EX_SOFTWARE); } if (cap_enter() < 0 && errno != ENOSYS) { warn("cap_enter() failed"); close(fd); return (EX_SOFTWARE); } #endif if (opt == INFO_TAG_NAMEVER) opt |= INFO_FULL; pkg_manifest_keys_new(&keys); if (opt & INFO_RAW) { if ((opt & (INFO_RAW_JSON|INFO_RAW_JSON_COMPACT|INFO_RAW_UCL)) == 0) opt |= INFO_RAW_YAML; } if ((opt & (INFO_RAW | INFO_FILES | INFO_DIRS)) == 0) open_flags = PKG_OPEN_MANIFEST_COMPACT; if (pkg_open_fd(&pkg, fd, keys, open_flags) != EPKG_OK) { close(fd); return (1); } pkg_manifest_keys_free(keys); print_info(pkg, opt); close(fd); pkg_free(pkg); return (EX_OK); } 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 (match == MATCH_ALL) return (EX_OK); if (origin_search) return (EX_OK); if (!quiet) warnx("No packages installed"); return (EX_UNAVAILABLE); } 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); } i = 0; do { gotone = false; pkgname = argv[i]; /* * 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++; } } if (match != MATCH_ALL && pkgname[0] == '\0') { fprintf(stderr, "Pattern must not be empty.\n"); i++; continue; } if ((it = pkgdb_query(db, pkgname, match)) == NULL) { goto cleanup; } /* 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 */ /* * only show full version in case of match glob with a * single argument specified which does not contains * any glob pattern */ if (argc == 1 && !origin_search && !quiet && !e_flag && match == MATCH_GLOB && strcspn(pkgname, "*[]{}()") == strlen(pkgname) && opt == INFO_TAG_NAMEVER) opt |= INFO_FULL; query_flags = info_flags(opt, false); 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); cleanup: pkg_free(pkg); pkgdb_release_lock(db, PKGDB_LOCK_READONLY); pkgdb_close(db); return (retcode); }
int exec_search(int argc, char **argv) { const char *pattern = NULL; const char *reponame = NULL; int ret = EPKG_OK, ch; int flags; unsigned int opt = 0; match_t match = MATCH_REGEX; pkgdb_field search = FIELD_NONE; pkgdb_field label = FIELD_NONE; struct pkgdb *db = NULL; struct pkgdb_it *it = NULL; struct pkg *pkg = NULL; bool atleastone = false; while ((ch = getopt(argc, argv, "cDdefgiL:opqQ:r:S:sx")) != -1) { switch (ch) { case 'c': /* Same as -S comment */ search = search_label_opt("comment"); break; case 'D': /* Same as -S description */ search = search_label_opt("description"); break; case 'd': /* Same as -Q depends-on */ opt |= modifier_opt("depends-on"); break; case 'e': match = MATCH_EXACT; break; case 'f': /* Same as -Q full */ opt |= modifier_opt("full"); break; case 'g': match = MATCH_GLOB; break; case 'i': pkgdb_set_case_sensitivity(false); break; case 'L': label = search_label_opt(optarg); break; case 'o': /* Same as -L origin */ label = search_label_opt("origin"); break; case 'p': /* Same as -Q prefix */ opt |= modifier_opt("prefix"); break; case 'q': quiet = true; break; case 'Q': opt |= modifier_opt(optarg); break; case 'r': reponame = optarg; break; case 'S': search = search_label_opt(optarg); break; case 's': /* Same as -Q size */ opt |= modifier_opt("size"); break; case 'x': match = MATCH_REGEX; break; default: usage_search(); return (EX_USAGE); } } argc -= optind; argv += optind; if (argc != 1) { usage_search(); return (EX_USAGE); } pattern = argv[0]; if (pattern[0] == '\0') { fprintf(stderr, "Pattern must not be empty!\n"); return (EX_USAGE); } if (search == FIELD_NONE) { if (strchr(pattern, '/') != NULL) search = FIELD_ORIGIN; else search = FIELD_NAMEVER; /* Default search */ } if (label == FIELD_NONE) label = search; /* By default, show what was searched */ switch(label) { case FIELD_NONE: break; /* should never happen */ case FIELD_ORIGIN: opt |= INFO_TAG_ORIGIN; break; case FIELD_NAME: opt |= INFO_TAG_NAME; break; case FIELD_NAMEVER: opt |= INFO_TAG_NAMEVER; break; case FIELD_COMMENT: opt |= INFO_TAG_NAMEVER|INFO_COMMENT; break; case FIELD_DESC: opt |= INFO_TAG_NAMEVER|INFO_DESCR; break; } if (pkgdb_open(&db, PKGDB_REMOTE) != EPKG_OK) return (EX_IOERR); if ((it = pkgdb_search(db, pattern, match, search, search, reponame)) == NULL) { pkgdb_close(db); return (EX_IOERR); } flags = info_flags(opt); while ((ret = pkgdb_it_next(it, &pkg, flags)) == EPKG_OK) { print_info(pkg, opt); atleastone = true; } pkg_free(pkg); pkgdb_it_free(it); pkgdb_close(db); if (!atleastone) ret = EPKG_FATAL; return ((ret == EPKG_OK || ret == EPKG_END) ? EX_OK : EX_SOFTWARE); }
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); }