rpm
4.5
|
00001 00006 #include "system.h" 00007 00008 #ifndef PATH_MAX 00009 /*@-incondefs@*/ /* FIX: long int? */ 00010 # define PATH_MAX 255 00011 /*@=incondefs@*/ 00012 #endif 00013 00014 #include <rpmcli.h> 00015 00016 #include "rpmdb.h" 00017 #include "rpmfi.h" 00018 00019 #define _RPMGI_INTERNAL /* XXX for gi->flags */ 00020 #include "rpmgi.h" 00021 #include "rpmts.h" 00022 00023 #include "manifest.h" 00024 #include "misc.h" /* XXX for rpmGlob() */ 00025 00026 #include "debug.h" 00027 00028 /*@access rpmgi @*/ 00029 00032 static void printFileInfo(char * te, const char * name, 00033 unsigned int size, unsigned short mode, 00034 unsigned int mtime, 00035 unsigned short rdev, unsigned int nlink, 00036 const char * owner, const char * group, 00037 const char * linkto) 00038 /*@modifies *te @*/ 00039 { 00040 char sizefield[15]; 00041 char ownerfield[8+1], groupfield[8+1]; 00042 char timefield[100]; 00043 time_t when = mtime; /* important if sizeof(int_32) ! sizeof(time_t) */ 00044 struct tm * tm; 00045 static time_t now; 00046 static struct tm nowtm; 00047 const char * namefield = name; 00048 char * perms = rpmPermsString(mode); 00049 00050 /* On first call, grab snapshot of now */ 00051 if (now == 0) { 00052 now = time(NULL); 00053 tm = localtime(&now); 00054 /*@-boundsread@*/ 00055 if (tm) nowtm = *tm; /* structure assignment */ 00056 /*@=boundsread@*/ 00057 } 00058 00059 strncpy(ownerfield, owner, sizeof(ownerfield)); 00060 ownerfield[sizeof(ownerfield)-1] = '\0'; 00061 00062 strncpy(groupfield, group, sizeof(groupfield)); 00063 groupfield[sizeof(groupfield)-1] = '\0'; 00064 00065 /* this is normally right */ 00066 sprintf(sizefield, "%12u", size); 00067 00068 /* this knows too much about dev_t */ 00069 00070 if (S_ISLNK(mode)) { 00071 char *nf = alloca(strlen(name) + sizeof(" -> ") + strlen(linkto)); 00072 sprintf(nf, "%s -> %s", name, linkto); 00073 namefield = nf; 00074 } else if (S_ISCHR(mode)) { 00075 perms[0] = 'c'; 00076 sprintf(sizefield, "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff), 00077 ((unsigned)rdev & 0xff)); 00078 } else if (S_ISBLK(mode)) { 00079 perms[0] = 'b'; 00080 sprintf(sizefield, "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff), 00081 ((unsigned)rdev & 0xff)); 00082 } 00083 00084 /* Convert file mtime to display format */ 00085 tm = localtime(&when); 00086 timefield[0] = '\0'; 00087 if (tm != NULL) 00088 { const char *fmt; 00089 if (now > when + 6L * 30L * 24L * 60L * 60L || /* Old. */ 00090 now < when - 60L * 60L) /* In the future. */ 00091 { 00092 /* The file is fairly old or in the future. 00093 * POSIX says the cutoff is 6 months old; 00094 * approximate this by 6*30 days. 00095 * Allow a 1 hour slop factor for what is considered "the future", 00096 * to allow for NFS server/client clock disagreement. 00097 * Show the year instead of the time of day. 00098 */ 00099 fmt = "%b %e %Y"; 00100 } else { 00101 fmt = "%b %e %H:%M"; 00102 } 00103 (void)strftime(timefield, sizeof(timefield) - 1, fmt, tm); 00104 } 00105 00106 sprintf(te, "%s %4d %-7s %-8s %10s %s %s", perms, 00107 (int)nlink, ownerfield, groupfield, sizefield, timefield, namefield); 00108 perms = _free(perms); 00109 } 00110 00113 static inline /*@null@*/ const char * queryHeader(Header h, const char * qfmt) 00114 /*@*/ 00115 { 00116 const char * errstr = "(unkown error)"; 00117 const char * str; 00118 00119 /*@-modobserver@*/ 00120 str = headerSprintf(h, qfmt, rpmTagTable, rpmHeaderFormats, &errstr); 00121 /*@=modobserver@*/ 00122 if (str == NULL) 00123 rpmError(RPMERR_QFMT, _("incorrect format: %s\n"), errstr); 00124 return str; 00125 } 00126 00129 static void flushBuffer(char ** tp, char ** tep, int nonewline) 00130 /*@modifies *tp, **tp, *tep, **tep @*/ 00131 { 00132 char *t, *te; 00133 00134 t = *tp; 00135 te = *tep; 00136 if (te > t) { 00137 if (!nonewline) { 00138 *te++ = '\n'; 00139 *te = '\0'; 00140 } 00141 rpmMessage(RPMMESS_NORMAL, "%s", t); 00142 te = t; 00143 *t = '\0'; 00144 } 00145 *tp = t; 00146 *tep = te; 00147 } 00148 00149 int showQueryPackage(QVA_t qva, rpmts ts, Header h) 00150 { 00151 int scareMem = 0; 00152 rpmfi fi = NULL; 00153 size_t tb = 2 * BUFSIZ; 00154 size_t sb; 00155 char * t, * te; 00156 char * prefix = NULL; 00157 int rc = 0; /* XXX FIXME: need real return code */ 00158 int i; 00159 00160 te = t = xmalloc(tb); 00161 /*@-boundswrite@*/ 00162 *te = '\0'; 00163 /*@=boundswrite@*/ 00164 00165 if (qva->qva_queryFormat != NULL) { 00166 const char * str = queryHeader(h, qva->qva_queryFormat); 00167 /*@-branchstate@*/ 00168 if (str) { 00169 size_t tx = (te - t); 00170 00171 sb = strlen(str); 00172 if (sb) { 00173 tb += sb; 00174 t = xrealloc(t, tb); 00175 te = t + tx; 00176 } 00177 /*@-boundswrite@*/ 00178 /*@-usereleased@*/ 00179 te = stpcpy(te, str); 00180 /*@=usereleased@*/ 00181 /*@=boundswrite@*/ 00182 str = _free(str); 00183 flushBuffer(&t, &te, 1); 00184 } 00185 /*@=branchstate@*/ 00186 } 00187 00188 if (!(qva->qva_flags & QUERY_FOR_LIST)) 00189 goto exit; 00190 00191 fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem); 00192 if (rpmfiFC(fi) <= 0) { 00193 /*@-boundswrite@*/ 00194 te = stpcpy(te, _("(contains no files)")); 00195 /*@=boundswrite@*/ 00196 goto exit; 00197 } 00198 00199 fi = rpmfiInit(fi, 0); 00200 if (fi != NULL) 00201 while ((i = rpmfiNext(fi)) >= 0) { 00202 rpmfileAttrs fflags; 00203 unsigned short fmode; 00204 unsigned short frdev; 00205 unsigned int fmtime; 00206 rpmfileState fstate; 00207 size_t fsize; 00208 const char * fn; 00209 const char * fdigest; 00210 const char * fuser; 00211 const char * fgroup; 00212 const char * flink; 00213 int_32 fnlink; 00214 00215 fflags = rpmfiFFlags(fi); 00216 fmode = rpmfiFMode(fi); 00217 frdev = rpmfiFRdev(fi); 00218 fmtime = rpmfiFMtime(fi); 00219 fstate = rpmfiFState(fi); 00220 fsize = rpmfiFSize(fi); 00221 fn = rpmfiFN(fi); 00222 /*@-bounds@*/ 00223 { static char hex[] = "0123456789abcdef"; 00224 int dalgo = 0; 00225 size_t dlen = 0; 00226 const unsigned char * digest = rpmfiDigest(fi, &dalgo, &dlen); 00227 char * p; 00228 int j; 00229 fdigest = p = xcalloc(1, ((2 * dlen) + 1)); 00230 for (j = 0; j < dlen; j++) { 00231 unsigned k = *digest++; 00232 *p++ = hex[ (k >> 4) & 0xf ]; 00233 *p++ = hex[ (k ) & 0xf ]; 00234 } 00235 *p = '\0'; 00236 } 00237 /*@=bounds@*/ 00238 fuser = rpmfiFUser(fi); 00239 fgroup = rpmfiFGroup(fi); 00240 flink = rpmfiFLink(fi); 00241 fnlink = rpmfiFNlink(fi); 00242 assert(fn != NULL); 00243 assert(fdigest != NULL); 00244 00245 /* If querying only docs, skip non-doc files. */ 00246 if ((qva->qva_flags & QUERY_FOR_DOCS) && !(fflags & RPMFILE_DOC)) 00247 continue; 00248 00249 /* If querying only configs, skip non-config files. */ 00250 if ((qva->qva_flags & QUERY_FOR_CONFIG) && !(fflags & RPMFILE_CONFIG)) 00251 continue; 00252 00253 /* If not querying %config, skip config files. */ 00254 if ((qva->qva_fflags & RPMFILE_CONFIG) && (fflags & RPMFILE_CONFIG)) 00255 continue; 00256 00257 /* If not querying %doc, skip doc files. */ 00258 if ((qva->qva_fflags & RPMFILE_DOC) && (fflags & RPMFILE_DOC)) 00259 continue; 00260 00261 /* If not querying %ghost, skip ghost files. */ 00262 if ((qva->qva_fflags & RPMFILE_GHOST) && (fflags & RPMFILE_GHOST)) 00263 continue; 00264 00265 /* Insure space for header derived data */ 00266 sb = 0; 00267 if (fn) sb += strlen(fn); 00268 if (fdigest) sb += strlen(fdigest); 00269 if (fuser) sb += strlen(fuser); 00270 if (fgroup) sb += strlen(fgroup); 00271 if (flink) sb += strlen(flink); 00272 /*@-branchstate@*/ 00273 if ((sb + BUFSIZ) > tb) { 00274 size_t tx = (te - t); 00275 tb += sb + BUFSIZ; 00276 t = xrealloc(t, tb); 00277 te = t + tx; 00278 } 00279 /*@=branchstate@*/ 00280 00281 /*@-boundswrite@*/ 00282 if (!rpmIsVerbose() && prefix) 00283 te = stpcpy(te, prefix); 00284 00285 if (qva->qva_flags & QUERY_FOR_STATE) { 00286 switch (fstate) { 00287 case RPMFILE_STATE_NORMAL: 00288 te = stpcpy(te, _("normal ")); 00289 /*@switchbreak@*/ break; 00290 case RPMFILE_STATE_REPLACED: 00291 te = stpcpy(te, _("replaced ")); 00292 /*@switchbreak@*/ break; 00293 case RPMFILE_STATE_NOTINSTALLED: 00294 te = stpcpy(te, _("not installed ")); 00295 /*@switchbreak@*/ break; 00296 case RPMFILE_STATE_NETSHARED: 00297 te = stpcpy(te, _("net shared ")); 00298 /*@switchbreak@*/ break; 00299 case RPMFILE_STATE_WRONGCOLOR: 00300 te = stpcpy(te, _("wrong color ")); 00301 /*@switchbreak@*/ break; 00302 case RPMFILE_STATE_MISSING: 00303 te = stpcpy(te, _("(no state) ")); 00304 /*@switchbreak@*/ break; 00305 default: 00306 sprintf(te, _("(unknown %3d) "), fstate); 00307 te += strlen(te); 00308 /*@switchbreak@*/ break; 00309 } 00310 } 00311 /*@=boundswrite@*/ 00312 00313 if (qva->qva_flags & QUERY_FOR_DUMPFILES) { 00314 sprintf(te, "%s %d %d %s 0%o ", 00315 fn, (int)fsize, fmtime, fdigest, fmode); 00316 te += strlen(te); 00317 00318 if (fuser && fgroup) { 00319 /*@-nullpass@*/ 00320 sprintf(te, "%s %s", fuser, fgroup); 00321 /*@=nullpass@*/ 00322 te += strlen(te); 00323 } else { 00324 rpmError(RPMERR_INTERNAL, 00325 _("package has not file owner/group lists\n")); 00326 } 00327 00328 sprintf(te, " %s %s %u ", 00329 fflags & RPMFILE_CONFIG ? "1" : "0", 00330 fflags & RPMFILE_DOC ? "1" : "0", 00331 frdev); 00332 te += strlen(te); 00333 00334 sprintf(te, "%s", (flink && *flink ? flink : "X")); 00335 te += strlen(te); 00336 } else 00337 if (!rpmIsVerbose()) { 00338 /*@-boundswrite@*/ 00339 te = stpcpy(te, fn); 00340 /*@=boundswrite@*/ 00341 } 00342 else { 00343 00344 /* XXX Adjust directory link count and size for display output. */ 00345 if (S_ISDIR(fmode)) { 00346 fnlink++; 00347 fsize = 0; 00348 } 00349 00350 if (fuser && fgroup) { 00351 /*@-nullpass@*/ 00352 printFileInfo(te, fn, fsize, fmode, fmtime, frdev, fnlink, 00353 fuser, fgroup, flink); 00354 /*@=nullpass@*/ 00355 te += strlen(te); 00356 } else { 00357 rpmError(RPMERR_INTERNAL, 00358 _("package has neither file owner or id lists\n")); 00359 } 00360 } 00361 flushBuffer(&t, &te, 0); 00362 fdigest = _free(fdigest); 00363 } 00364 00365 rc = 0; 00366 00367 exit: 00368 flushBuffer(&t, &te, 0); 00369 t = _free(t); 00370 00371 fi = rpmfiFree(fi); 00372 return rc; 00373 } 00374 00375 void rpmDisplayQueryTags(FILE * fp) 00376 { 00377 const struct headerTagTableEntry_s * t; 00378 int i; 00379 const struct headerSprintfExtension_s * ext = rpmHeaderFormats; 00380 00381 for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) { 00382 if (t->name == NULL) 00383 continue; 00384 fprintf(fp, "%-20s", t->name + 7); 00385 if (rpmIsVerbose()) { 00386 /*@observer@*/ 00387 static const char * tagtypes[] = { 00388 "", "char", "int8", "int16", "int32", "int64", 00389 "string", "blob", "argv", "i18nstring", "asn1", "openpgp" 00390 }; 00391 fprintf(fp, " %6d", t->val); 00392 if (t->type > RPM_NULL_TYPE && t->type <= RPM_MAX_TYPE) 00393 fprintf(fp, " %s", tagtypes[t->type]); 00394 } 00395 fprintf(fp, "\n"); 00396 } 00397 00398 while (ext->name != NULL) { 00399 if (ext->type == HEADER_EXT_MORE) { 00400 ext = ext->u.more; 00401 continue; 00402 } 00403 /* XXX don't print query tags twice. */ 00404 for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) { 00405 if (t->name == NULL) /* XXX programmer error. */ 00406 /*@innercontinue@*/ continue; 00407 if (!strcmp(t->name, ext->name)) 00408 /*@innerbreak@*/ break; 00409 } 00410 if (i >= rpmTagTableSize && ext->type == HEADER_EXT_TAG) 00411 fprintf(fp, "%s\n", ext->name + 7); 00412 ext++; 00413 } 00414 } 00415 00416 static int rpmgiShowMatches(QVA_t qva, rpmts ts) 00417 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ 00418 /*@modifies qva, rpmGlobalMacroContext, h_errno, internalState @*/ 00419 { 00420 rpmgi gi = qva->qva_gi; 00421 int ec = 0; 00422 00423 while (rpmgiNext(gi) == RPMRC_OK) { 00424 Header h; 00425 int rc; 00426 00427 h = rpmgiHeader(gi); 00428 if (h == NULL) /* XXX perhaps stricter break instead? */ 00429 continue; 00430 if ((rc = qva->qva_showPackage(qva, ts, h)) != 0) 00431 ec = rc; 00432 if (qva->qva_source == RPMQV_DBOFFSET) 00433 break; 00434 } 00435 return ec; 00436 } 00437 00438 int rpmcliShowMatches(QVA_t qva, rpmts ts) 00439 { 00440 Header h; 00441 int ec = 1; 00442 00443 qva->qva_showFAIL = qva->qva_showOK = 0; 00444 while ((h = rpmdbNextIterator(qva->qva_mi)) != NULL) { 00445 ec = qva->qva_showPackage(qva, ts, h); 00446 if (ec) 00447 qva->qva_showFAIL++; 00448 else 00449 qva->qva_showOK++; 00450 if (qva->qva_source == RPMQV_DBOFFSET) 00451 break; 00452 } 00453 qva->qva_mi = rpmdbFreeIterator(qva->qva_mi); 00454 return ec; 00455 } 00456 00462 static inline unsigned char nibble(char c) 00463 /*@*/ 00464 { 00465 if (c >= '0' && c <= '9') 00466 return (c - '0'); 00467 if (c >= 'A' && c <= 'F') 00468 return (c - 'A') + 10; 00469 if (c >= 'a' && c <= 'f') 00470 return (c - 'a') + 10; 00471 return 0; 00472 } 00473 00474 int rpmQueryVerify(QVA_t qva, rpmts ts, const char * arg) 00475 { 00476 int res = 0; 00477 const char * s; 00478 int i; 00479 int provides_checked = 0; 00480 00481 (void) rpmdbCheckSignals(); 00482 00483 if (qva->qva_showPackage == NULL) 00484 return 1; 00485 00486 /*@-branchstate@*/ 00487 switch (qva->qva_source) { 00488 case RPMQV_RPM: 00489 res = rpmgiShowMatches(qva, ts); 00490 break; 00491 00492 case RPMQV_ALL: 00493 res = rpmgiShowMatches(qva, ts); 00494 break; 00495 00496 case RPMQV_HDLIST: 00497 res = rpmgiShowMatches(qva, ts); 00498 break; 00499 00500 case RPMQV_FTSWALK: 00501 res = rpmgiShowMatches(qva, ts); 00502 break; 00503 00504 case RPMQV_SPECSRPM: 00505 case RPMQV_SPECFILE: 00506 res = ((qva->qva_specQuery != NULL) 00507 ? qva->qva_specQuery(ts, qva, arg) : 1); 00508 break; 00509 00510 case RPMQV_GROUP: 00511 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_GROUP, arg, 0); 00512 if (qva->qva_mi == NULL) { 00513 rpmError(RPMERR_QUERYINFO, 00514 _("group %s does not contain any packages\n"), arg); 00515 res = 1; 00516 } else 00517 res = rpmcliShowMatches(qva, ts); 00518 break; 00519 00520 case RPMQV_TRIGGEREDBY: 00521 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_TRIGGERNAME, arg, 0); 00522 if (qva->qva_mi == NULL) { 00523 rpmError(RPMERR_QUERYINFO, _("no package triggers %s\n"), arg); 00524 res = 1; 00525 } else 00526 res = rpmcliShowMatches(qva, ts); 00527 break; 00528 00529 case RPMQV_PKGID: 00530 { unsigned char MD5[16]; 00531 unsigned char * t; 00532 00533 for (i = 0, s = arg; *s && isxdigit(*s); s++, i++) 00534 {}; 00535 if (i != 32) { 00536 rpmError(RPMERR_QUERYINFO, _("malformed %s: %s\n"), "pkgid", arg); 00537 return 1; 00538 } 00539 00540 MD5[0] = '\0'; 00541 for (i = 0, t = MD5, s = arg; i < 16; i++, t++, s += 2) 00542 *t = (nibble(s[0]) << 4) | nibble(s[1]); 00543 00544 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_SIGMD5, MD5, sizeof(MD5)); 00545 if (qva->qva_mi == NULL) { 00546 rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"), 00547 "pkgid", arg); 00548 res = 1; 00549 } else 00550 res = rpmcliShowMatches(qva, ts); 00551 } break; 00552 00553 case RPMQV_HDRID: 00554 for (i = 0, s = arg; *s && isxdigit(*s); s++, i++) 00555 {}; 00556 if (i != 40) { 00557 rpmError(RPMERR_QUERYINFO, _("malformed %s: %s\n"), "hdrid", arg); 00558 return 1; 00559 } 00560 00561 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_SHA1HEADER, arg, 0); 00562 if (qva->qva_mi == NULL) { 00563 rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"), 00564 "hdrid", arg); 00565 res = 1; 00566 } else 00567 res = rpmcliShowMatches(qva, ts); 00568 break; 00569 00570 case RPMQV_FILEID: 00571 { unsigned char * t; 00572 unsigned char * digest; 00573 size_t dlen; 00574 00575 /* Insure even no. of digits and at least 8 digits. */ 00576 for (dlen = 0, s = arg; *s && isxdigit(*s); s++, dlen++) 00577 {}; 00578 if ((dlen & 1) || dlen < 8) { 00579 rpmError(RPMERR_QUERY, _("malformed %s: %s\n"), "fileid", arg); 00580 return 1; 00581 } 00582 00583 dlen /= 2; 00584 digest = memset(alloca(dlen), 0, dlen); 00585 for (t = digest, s = arg; *s; t++, s += 2) 00586 *t = (nibble(s[0]) << 4) | nibble(s[1]); 00587 00588 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_FILEDIGESTS, digest, dlen); 00589 if (qva->qva_mi == NULL) { 00590 rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"), 00591 "fileid", arg); 00592 res = 1; 00593 } else 00594 res = rpmcliShowMatches(qva, ts); 00595 } break; 00596 00597 case RPMQV_TID: 00598 { int mybase = 10; 00599 const char * myarg = arg; 00600 char * end = NULL; 00601 unsigned iid; 00602 00603 /* XXX should be in strtoul */ 00604 if (*myarg == '0') { 00605 myarg++; 00606 mybase = 8; 00607 if (*myarg == 'x') { 00608 myarg++; 00609 mybase = 16; 00610 } 00611 } 00612 iid = (unsigned) strtoul(myarg, &end, mybase); 00613 if ((*end) || (end == arg) || (iid == UINT_MAX)) { 00614 rpmError(RPMERR_QUERY, _("malformed %s: %s\n"), "tid", arg); 00615 return 1; 00616 } 00617 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_INSTALLTID, &iid, sizeof(iid)); 00618 if (qva->qva_mi == NULL) { 00619 rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"), 00620 "tid", arg); 00621 res = 1; 00622 } else 00623 res = rpmcliShowMatches(qva, ts); 00624 } break; 00625 00626 case RPMQV_WHATNEEDS: 00627 case RPMQV_WHATREQUIRES: 00628 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_REQUIRENAME, arg, 0); 00629 if (qva->qva_mi == NULL) { 00630 rpmError(RPMERR_QUERYINFO, _("no package requires %s\n"), arg); 00631 res = 1; 00632 } else 00633 res = rpmcliShowMatches(qva, ts); 00634 break; 00635 00636 case RPMQV_WHATPROVIDES: 00637 if (arg[0] != '/') { 00638 provides_checked = 1; 00639 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, arg, 0); 00640 if (qva->qva_mi == NULL) { 00641 rpmError(RPMERR_QUERYINFO, _("no package provides %s\n"), arg); 00642 res = 1; 00643 } else 00644 res = rpmcliShowMatches(qva, ts); 00645 break; 00646 } 00647 /*@fallthrough@*/ 00648 case RPMQV_PATH: 00649 { char * fn; 00650 00651 for (s = arg; *s != '\0'; s++) 00652 if (!(*s == '.' || *s == '/')) 00653 /*@loopbreak@*/ break; 00654 00655 if (*s == '\0') { 00656 char fnbuf[PATH_MAX]; 00657 fn = realpath(arg, fnbuf); 00658 fn = xstrdup( (fn != NULL ? fn : arg) ); 00659 } else if (*arg != '/') { 00660 const char *curDir = currentDirectory(); 00661 fn = (char *) rpmGetPath(curDir, "/", arg, NULL); 00662 curDir = _free(curDir); 00663 } else 00664 fn = xstrdup(arg); 00665 assert(fn != NULL); 00666 (void) rpmCleanPath(fn); 00667 00668 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, fn, 0); 00669 if (qva->qva_mi == NULL && !provides_checked) 00670 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, fn, 0); 00671 00672 if (qva->qva_mi == NULL) { 00673 struct stat sb; 00674 if (Lstat(fn, &sb) != 0) 00675 rpmError(RPMERR_QUERY, _("file %s: %s\n"), fn, strerror(errno)); 00676 else 00677 rpmError(RPMERR_QUERYINFO, 00678 _("file %s is not owned by any package\n"), fn); 00679 res = 1; 00680 } else 00681 res = rpmcliShowMatches(qva, ts); 00682 00683 fn = _free(fn); 00684 } break; 00685 00686 case RPMQV_DBOFFSET: 00687 { int mybase = 10; 00688 const char * myarg = arg; 00689 char * end = NULL; 00690 unsigned recOffset; 00691 00692 /* XXX should be in strtoul */ 00693 if (*myarg == '0') { 00694 myarg++; 00695 mybase = 8; 00696 if (*myarg == 'x') { 00697 myarg++; 00698 mybase = 16; 00699 } 00700 } 00701 recOffset = (unsigned) strtoul(myarg, &end, mybase); 00702 if ((*end) || (end == arg) || (recOffset == UINT_MAX)) { 00703 rpmError(RPMERR_QUERYINFO, _("invalid package number: %s\n"), arg); 00704 return 1; 00705 } 00706 rpmMessage(RPMMESS_DEBUG, D_("package record number: %u\n"), recOffset); 00707 qva->qva_mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, &recOffset, sizeof(recOffset)); 00708 if (qva->qva_mi == NULL) { 00709 rpmError(RPMERR_QUERYINFO, 00710 _("record %u could not be read\n"), recOffset); 00711 res = 1; 00712 } else 00713 res = rpmcliShowMatches(qva, ts); 00714 } break; 00715 00716 case RPMQV_PACKAGE: 00717 /* XXX HACK to get rpmdbFindByLabel out of the API */ 00718 qva->qva_mi = rpmtsInitIterator(ts, RPMDBI_LABEL, arg, 0); 00719 if (qva->qva_mi == NULL) { 00720 rpmError(RPMERR_QUERYINFO, _("package %s is not installed\n"), arg); 00721 res = 1; 00722 } else { 00723 res = rpmcliShowMatches(qva, ts); 00724 /* detect foo.bogusarch empty iterations. */ 00725 if (qva->qva_showOK == 0 && qva->qva_showFAIL == 0) { 00726 rpmError(RPMERR_QUERYINFO, _("package %s is not installed\n"), arg); 00727 res = 1; 00728 } 00729 } 00730 break; 00731 } 00732 /*@=branchstate@*/ 00733 00734 return res; 00735 } 00736 00737 int rpmcliArgIter(rpmts ts, QVA_t qva, ARGV_t argv) 00738 { 00739 rpmRC rpmrc = RPMRC_NOTFOUND; 00740 int ec = 0; 00741 00742 switch (qva->qva_source) { 00743 case RPMQV_ALL: 00744 qva->qva_gi = rpmgiNew(ts, RPMDBI_PACKAGES, NULL, 0); 00745 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, ftsOpts, RPMGI_NONE); 00746 00747 if (qva->qva_gi != NULL && (qva->qva_gi->flags & RPMGI_TSADD)) /* Load the ts with headers. */ 00748 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) 00749 {}; 00750 if (rpmrc != RPMRC_NOTFOUND) 00751 return 1; /* XXX should be no. of failures. */ 00752 00753 /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */ 00754 ec = rpmQueryVerify(qva, ts, (const char *) argv); 00755 /*@=nullpass@*/ 00756 rpmtsEmpty(ts); 00757 break; 00758 case RPMQV_RPM: 00759 qva->qva_gi = rpmgiNew(ts, RPMDBI_ARGLIST, NULL, 0); 00760 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, ftsOpts, giFlags); 00761 00762 if (qva->qva_gi != NULL && (qva->qva_gi->flags & RPMGI_TSADD)) /* Load the ts with headers. */ 00763 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) 00764 {}; 00765 if (rpmrc != RPMRC_NOTFOUND) 00766 return 1; /* XXX should be no. of failures. */ 00767 00768 /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */ 00769 ec = rpmQueryVerify(qva, ts, NULL); 00770 /*@=nullpass@*/ 00771 rpmtsEmpty(ts); 00772 break; 00773 case RPMQV_HDLIST: 00774 qva->qva_gi = rpmgiNew(ts, RPMDBI_HDLIST, NULL, 0); 00775 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, ftsOpts, giFlags); 00776 00777 if (qva->qva_gi != NULL && (qva->qva_gi->flags & RPMGI_TSADD)) /* Load the ts with headers. */ 00778 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) 00779 {}; 00780 if (rpmrc != RPMRC_NOTFOUND) 00781 return 1; /* XXX should be no. of failures. */ 00782 00783 /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */ 00784 ec = rpmQueryVerify(qva, ts, NULL); 00785 /*@=nullpass@*/ 00786 rpmtsEmpty(ts); 00787 break; 00788 case RPMQV_FTSWALK: 00789 if (ftsOpts == 0) 00790 ftsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT); 00791 qva->qva_gi = rpmgiNew(ts, RPMDBI_FTSWALK, NULL, 0); 00792 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, ftsOpts, giFlags); 00793 00794 if (qva->qva_gi != NULL && (qva->qva_gi->flags & RPMGI_TSADD)) /* Load the ts with headers. */ 00795 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) 00796 {}; 00797 if (rpmrc != RPMRC_NOTFOUND) 00798 return 1; /* XXX should be no. of failures. */ 00799 00800 /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */ 00801 ec = rpmQueryVerify(qva, ts, NULL); 00802 /*@=nullpass@*/ 00803 rpmtsEmpty(ts); 00804 break; 00805 default: 00806 if (giFlags & RPMGI_TSADD) { 00807 qva->qva_gi = rpmgiNew(ts, RPMDBI_LABEL, NULL, 0); 00808 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, ftsOpts, 00809 (giFlags | (RPMGI_NOGLOB ))); 00810 if (qva->qva_gi != NULL && (qva->qva_gi->flags & RPMGI_TSADD)) /* Load the ts with headers. */ 00811 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) 00812 {}; 00813 if (rpmrc != RPMRC_NOTFOUND) 00814 return 1; /* XXX should be no. of failures. */ 00815 qva->qva_source = RPMQV_ALL; 00816 /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */ 00817 ec = rpmQueryVerify(qva, ts, NULL); 00818 /*@=nullpass@*/ 00819 rpmtsEmpty(ts); 00820 } else { 00821 qva->qva_gi = rpmgiNew(ts, RPMDBI_ARGLIST, NULL, 0); 00822 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, ftsOpts, 00823 (giFlags | (RPMGI_NOGLOB|RPMGI_NOHEADER))); 00824 while (rpmgiNext(qva->qva_gi) == RPMRC_OK) { 00825 const char * path; 00826 path = rpmgiHdrPath(qva->qva_gi); 00827 assert(path != NULL); 00828 ec += rpmQueryVerify(qva, ts, path); 00829 rpmtsEmpty(ts); 00830 } 00831 } 00832 break; 00833 } 00834 00835 qva->qva_gi = rpmgiFree(qva->qva_gi); 00836 00837 return ec; 00838 } 00839 00840 int rpmcliQuery(rpmts ts, QVA_t qva, const char ** argv) 00841 { 00842 rpmdepFlags depFlags = qva->depFlags, odepFlags; 00843 rpmtransFlags transFlags = qva->transFlags, otransFlags; 00844 rpmVSFlags vsflags, ovsflags; 00845 int ec = 0; 00846 00847 if (qva->qva_showPackage == NULL) 00848 qva->qva_showPackage = showQueryPackage; 00849 00850 /* If --queryformat unspecified, then set default now. */ 00851 if (!(qva->qva_flags & _QUERY_FOR_BITS) && qva->qva_queryFormat == NULL) { 00852 qva->qva_queryFormat = rpmExpand("%{?_query_all_fmt}\n", NULL); 00853 if (!(qva->qva_queryFormat != NULL && *qva->qva_queryFormat != '\0')) { 00854 qva->qva_queryFormat = _free(qva->qva_queryFormat); 00855 qva->qva_queryFormat = xstrdup("%{name}-%{version}-%{release}\n"); 00856 } 00857 } 00858 00859 vsflags = rpmExpandNumeric("%{?_vsflags_query}"); 00860 if (qva->qva_flags & VERIFY_DIGEST) 00861 vsflags |= _RPMVSF_NODIGESTS; 00862 if (qva->qva_flags & VERIFY_SIGNATURE) 00863 vsflags |= _RPMVSF_NOSIGNATURES; 00864 if (qva->qva_flags & VERIFY_HDRCHK) 00865 vsflags |= RPMVSF_NOHDRCHK; 00866 00867 odepFlags = rpmtsSetDFlags(ts, depFlags); 00868 otransFlags = rpmtsSetFlags(ts, transFlags); 00869 ovsflags = rpmtsSetVSFlags(ts, vsflags); 00870 ec = rpmcliArgIter(ts, qva, argv); 00871 vsflags = rpmtsSetVSFlags(ts, ovsflags); 00872 transFlags = rpmtsSetFlags(ts, otransFlags); 00873 depFlags = rpmtsSetDFlags(ts, odepFlags); 00874 00875 if (qva->qva_showPackage == showQueryPackage) 00876 qva->qva_showPackage = NULL; 00877 00878 return ec; 00879 }