rpm 5.3.7
|
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 if (qva->qva_mi == NULL) { 00703 struct stat sb; 00704 if (!gotpattern && Lstat(fn, &sb) != 0) 00705 rpmlog(RPMLOG_NOTICE, _("file %s: %s\n"), fn, strerror(errno)); 00706 else 00707 rpmlog(RPMLOG_NOTICE, 00708 _("file %s is not owned by any package\n"), fn); 00709 res = 1; 00710 } else 00711 res = rpmcliShowMatches(qva, ts); 00712 00713 fn = _free(fn); 00714 } break; 00715 00716 case RPMQV_DBOFFSET: 00717 { int mybase = 10; 00718 const char * myarg = arg; 00719 char * end = NULL; 00720 uint32_t hdrNum; 00721 00722 /* XXX should be in strtoul */ 00723 if (*myarg == '0') { 00724 myarg++; 00725 mybase = 8; 00726 if (*myarg == 'x') { 00727 myarg++; 00728 mybase = 16; 00729 } 00730 } 00731 hdrNum = (uint32_t) strtoul(myarg, &end, mybase); 00732 if ((*end) || (end == arg) || (hdrNum == UINT_MAX)) { 00733 rpmlog(RPMLOG_NOTICE, _("invalid package number: %s\n"), arg); 00734 return 1; 00735 } 00736 rpmlog(RPMLOG_DEBUG, D_("package record number: %u\n"), (unsigned)hdrNum); 00737 qva->qva_mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, &hdrNum, sizeof(hdrNum)); 00738 if (qva->qva_mi == NULL) { 00739 rpmlog(RPMLOG_NOTICE, 00740 _("record %u could not be read\n"), (unsigned)hdrNum); 00741 res = 1; 00742 } else 00743 res = rpmcliShowMatches(qva, ts); 00744 } break; 00745 00746 case RPMQV_PACKAGE: 00747 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_NVRA, arg, 0); 00748 if (qva->qva_mi == NULL) { 00749 rpmlog(RPMLOG_NOTICE, _("package %s is not installed\n"), arg); 00750 res = 1; 00751 } else { 00752 res = rpmcliShowMatches(qva, ts); 00753 /* detect foo.bogusarch empty iterations. */ 00754 if (qva->qva_showOK == 0 && qva->qva_showFAIL == 0) { 00755 rpmlog(RPMLOG_NOTICE, _("package %s is not installed\n"), arg); 00756 res = 1; 00757 } 00758 } 00759 break; 00760 } 00761 00762 return res; 00763 } 00764 00765 int rpmcliArgIter(rpmts ts, QVA_t qva, ARGV_t argv) 00766 /*@globals rpmioFtsOpts @*/ 00767 /*@modifies rpmioFtsOpts @*/ 00768 { 00769 rpmRC rpmrc = RPMRC_NOTFOUND; 00770 int ec = 0; 00771 00772 switch (qva->qva_source) { 00773 case RPMQV_ALL: 00774 qva->qva_gi = rpmgiNew(ts, RPMDBI_PACKAGES, NULL, 0); 00775 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, RPMGI_NONE); 00776 00777 if (rpmgiGetFlags(qva->qva_gi) & 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, (const char *) argv); 00785 /*@=nullpass@*/ 00786 rpmtsEmpty(ts); 00787 break; 00788 case RPMQV_RPM: 00789 qva->qva_gi = rpmgiNew(ts, RPMDBI_ARGLIST, NULL, 0); 00790 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, giFlags); 00791 00792 if (rpmgiGetFlags(qva->qva_gi) & RPMGI_TSADD) /* Load the ts with headers. */ 00793 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) 00794 {}; 00795 if (rpmrc != RPMRC_NOTFOUND) 00796 return 1; /* XXX should be no. of failures. */ 00797 00798 /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */ 00799 ec = rpmQueryVerify(qva, ts, NULL); 00800 /*@=nullpass@*/ 00801 rpmtsEmpty(ts); 00802 break; 00803 case RPMQV_HDLIST: 00804 qva->qva_gi = rpmgiNew(ts, RPMDBI_HDLIST, NULL, 0); 00805 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, giFlags); 00806 00807 if (rpmgiGetFlags(qva->qva_gi) & RPMGI_TSADD) /* Load the ts with headers. */ 00808 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) 00809 {}; 00810 if (rpmrc != RPMRC_NOTFOUND) 00811 return 1; /* XXX should be no. of failures. */ 00812 00813 /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */ 00814 ec = rpmQueryVerify(qva, ts, NULL); 00815 /*@=nullpass@*/ 00816 rpmtsEmpty(ts); 00817 break; 00818 case RPMQV_FTSWALK: 00819 if (rpmioFtsOpts == 0) 00820 rpmioFtsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT); 00821 qva->qva_gi = rpmgiNew(ts, RPMDBI_FTSWALK, NULL, 0); 00822 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, giFlags); 00823 00824 if (rpmgiGetFlags(qva->qva_gi) & RPMGI_TSADD) /* Load the ts with headers. */ 00825 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) 00826 {}; 00827 if (rpmrc != RPMRC_NOTFOUND) 00828 return 1; /* XXX should be no. of failures. */ 00829 00830 /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */ 00831 ec = rpmQueryVerify(qva, ts, NULL); 00832 /*@=nullpass@*/ 00833 rpmtsEmpty(ts); 00834 break; 00835 default: 00836 if (giFlags & RPMGI_TSADD) { 00837 qva->qva_gi = rpmgiNew(ts, RPMTAG_NVRA, NULL, 0); 00838 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, 00839 (giFlags | (RPMGI_NOGLOB ))); 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 qva->qva_source = RPMQV_ALL; 00846 /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */ 00847 ec = rpmQueryVerify(qva, ts, NULL); 00848 /*@=nullpass@*/ 00849 rpmtsEmpty(ts); 00850 } else { 00851 qva->qva_gi = rpmgiNew(ts, RPMDBI_ARGLIST, NULL, 0); 00852 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, 00853 (giFlags | (RPMGI_NOGLOB|RPMGI_NOHEADER))); 00854 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) { 00855 const char * path; 00856 path = rpmgiHdrPath(qva->qva_gi); 00857 assert(path != NULL); 00858 ec += rpmQueryVerify(qva, ts, path); 00859 rpmtsEmpty(ts); 00860 } 00861 } 00862 break; 00863 } 00864 00865 qva->qva_gi = rpmgiFree(qva->qva_gi); 00866 00867 return ec; 00868 } 00869 00870 int rpmcliQuery(rpmts ts, QVA_t qva, const char ** argv) 00871 { 00872 rpmdepFlags depFlags = qva->depFlags, odepFlags; 00873 rpmtransFlags transFlags = qva->transFlags, otransFlags; 00874 rpmVSFlags vsflags, ovsflags; 00875 int ec = 0; 00876 00877 if (qva->qva_showPackage == NULL) 00878 qva->qva_showPackage = showQueryPackage; 00879 00880 /* If --queryformat unspecified, then set default now. */ 00881 if (!(qva->qva_flags & _QUERY_FOR_BITS) && qva->qva_queryFormat == NULL) { 00882 qva->qva_queryFormat = rpmExpand("%{?_query_all_fmt}\n", NULL); 00883 if (!(qva->qva_queryFormat != NULL && *qva->qva_queryFormat != '\0')) { 00884 qva->qva_queryFormat = _free(qva->qva_queryFormat); 00885 qva->qva_queryFormat = xstrdup("%{name}-%{version}-%{release}.%{arch}\n"); 00886 } 00887 } 00888 00889 vsflags = rpmExpandNumeric("%{?_vsflags_query}"); 00890 if (qva->qva_flags & VERIFY_DIGEST) 00891 vsflags |= _RPMVSF_NODIGESTS; 00892 if (qva->qva_flags & VERIFY_SIGNATURE) 00893 vsflags |= _RPMVSF_NOSIGNATURES; 00894 if (qva->qva_flags & VERIFY_HDRCHK) 00895 vsflags |= RPMVSF_NOHDRCHK; 00896 00897 odepFlags = rpmtsSetDFlags(ts, depFlags); 00898 otransFlags = rpmtsSetFlags(ts, transFlags); 00899 ovsflags = rpmtsSetVSFlags(ts, vsflags); 00900 ec = rpmcliArgIter(ts, qva, argv); 00901 vsflags = rpmtsSetVSFlags(ts, ovsflags); 00902 transFlags = rpmtsSetFlags(ts, otransFlags); 00903 depFlags = rpmtsSetDFlags(ts, odepFlags); 00904 00905 if (qva->qva_showPackage == showQueryPackage) 00906 qva->qva_showPackage = NULL; 00907 00908 return ec; 00909 }