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