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