rpm 5.2.1
|
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 00417 int rpmcliShowMatches(QVA_t qva, rpmts ts) 00418 { 00419 Header h; 00420 int ec = 1; 00421 00422 qva->qva_showFAIL = qva->qva_showOK = 0; 00423 while ((h = rpmmiNext(qva->qva_mi)) != NULL) { 00424 ec = qva->qva_showPackage(qva, ts, h); 00425 if (ec) 00426 qva->qva_showFAIL++; 00427 else 00428 qva->qva_showOK++; 00429 if (qva->qva_source == RPMQV_DBOFFSET) 00430 break; 00431 } 00432 qva->qva_mi = rpmmiFree(qva->qva_mi); 00433 return ec; 00434 } 00435 00441 static inline unsigned char nibble(char c) 00442 /*@*/ 00443 { 00444 if (c >= '0' && c <= '9') 00445 return (c - '0'); 00446 if (c >= 'A' && c <= 'F') 00447 return (c - 'A') + 10; 00448 if (c >= 'a' && c <= 'f') 00449 return (c - 'a') + 10; 00450 return 0; 00451 } 00452 00453 int rpmQueryVerify(QVA_t qva, rpmts ts, const char * arg) 00454 { 00455 int res = 0; 00456 const char * s; 00457 int i; 00458 int provides_checked = 0; 00459 00460 (void) rpmdbCheckSignals(); 00461 00462 if (qva->qva_showPackage == NULL) 00463 return 1; 00464 00465 switch (qva->qva_source) { 00466 #ifdef NOTYET 00467 default: 00468 #endif 00469 case RPMQV_GROUP: 00470 case RPMQV_TRIGGEREDBY: 00471 case RPMQV_WHATCONFLICTS: 00472 case RPMQV_WHATOBSOLETES: 00473 qva->qva_mi = rpmtsInitIterator(ts, qva->qva_source, arg, 0); 00474 if (qva->qva_mi == NULL) { 00475 rpmlog(RPMLOG_NOTICE, _("key \"%s\" not found in %s table\n"), 00476 arg, tagName((rpmTag)qva->qva_source)); 00477 res = 1; 00478 } else 00479 res = rpmcliShowMatches(qva, ts); 00480 break; 00481 00482 case RPMQV_RPM: 00483 res = rpmgiShowMatches(qva, ts); 00484 break; 00485 00486 case RPMQV_ALL: 00487 res = rpmgiShowMatches(qva, ts); 00488 break; 00489 00490 case RPMQV_HDLIST: 00491 res = rpmgiShowMatches(qva, ts); 00492 break; 00493 00494 case RPMQV_FTSWALK: 00495 res = rpmgiShowMatches(qva, ts); 00496 break; 00497 00498 case RPMQV_SPECSRPM: 00499 case RPMQV_SPECFILE: 00500 res = ((qva->qva_specQuery != NULL) 00501 ? qva->qva_specQuery(ts, qva, arg) : 1); 00502 break; 00503 00504 #ifdef DYING 00505 case RPMQV_GROUP: 00506 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_GROUP, arg, 0); 00507 if (qva->qva_mi == NULL) { 00508 rpmlog(RPMLOG_ERR, 00509 _("group %s does not contain any packages\n"), arg); 00510 res = 1; 00511 } else 00512 res = rpmcliShowMatches(qva, ts); 00513 break; 00514 00515 case RPMQV_TRIGGEREDBY: 00516 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_TRIGGERNAME, arg, 0); 00517 if (qva->qva_mi == NULL) { 00518 rpmlog(RPMLOG_NOTICE, _("no package triggers %s\n"), arg); 00519 res = 1; 00520 } else 00521 res = rpmcliShowMatches(qva, ts); 00522 break; 00523 #endif 00524 00525 case RPMQV_SOURCEPKGID: 00526 case RPMQV_PKGID: 00527 { unsigned char MD5[16]; 00528 unsigned char * t; 00529 rpmuint32_t tag; 00530 00531 for (i = 0, s = arg; *s && isxdigit(*s); s++, i++) 00532 {}; 00533 if (i != 32) { 00534 rpmlog(RPMLOG_NOTICE, _("malformed %s: %s\n"), "pkgid", arg); 00535 return 1; 00536 } 00537 00538 MD5[0] = '\0'; 00539 for (i = 0, t = MD5, s = arg; i < 16; i++, t++, s += 2) 00540 *t = (nibble(s[0]) << 4) | nibble(s[1]); 00541 00542 tag = (qva->qva_source == RPMQV_PKGID 00543 ? RPMTAG_SOURCEPKGID : RPMTAG_PKGID); 00544 qva->qva_mi = rpmtsInitIterator(ts, tag, MD5, sizeof(MD5)); 00545 if (qva->qva_mi == NULL) { 00546 rpmlog(RPMLOG_NOTICE, _("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 rpmlog(RPMLOG_NOTICE, _("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 rpmlog(RPMLOG_NOTICE, _("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 rpmlog(RPMLOG_ERR, _("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 rpmlog(RPMLOG_NOTICE, _("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 rpmlog(RPMLOG_ERR, _("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 rpmlog(RPMLOG_NOTICE, _("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 rpmlog(RPMLOG_NOTICE, _("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 rpmlog(RPMLOG_NOTICE, _("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 rpmlog(RPMLOG_NOTICE, _("file %s: %s\n"), fn, strerror(errno)); 00676 else 00677 rpmlog(RPMLOG_NOTICE, 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 rpmlog(RPMLOG_NOTICE, _("invalid package number: %s\n"), arg); 00704 return 1; 00705 } 00706 rpmlog(RPMLOG_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 rpmlog(RPMLOG_NOTICE, 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 rpmlog(RPMLOG_NOTICE, _("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 rpmlog(RPMLOG_NOTICE, _("package %s is not installed\n"), arg); 00727 res = 1; 00728 } 00729 } 00730 break; 00731 } 00732 00733 return res; 00734 } 00735 00736 int rpmcliArgIter(rpmts ts, QVA_t qva, ARGV_t argv) 00737 /*@globals rpmioFtsOpts @*/ 00738 /*@modifies rpmioFtsOpts @*/ 00739 { 00740 rpmRC rpmrc = RPMRC_NOTFOUND; 00741 int ec = 0; 00742 00743 switch (qva->qva_source) { 00744 case RPMQV_ALL: 00745 qva->qva_gi = rpmgiNew(ts, RPMDBI_PACKAGES, NULL, 0); 00746 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, RPMGI_NONE); 00747 00748 if (rpmgiGetFlags(qva->qva_gi) & RPMGI_TSADD) /* Load the ts with headers. */ 00749 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) 00750 {}; 00751 if (rpmrc != RPMRC_NOTFOUND) 00752 return 1; /* XXX should be no. of failures. */ 00753 00754 /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */ 00755 ec = rpmQueryVerify(qva, ts, (const char *) argv); 00756 /*@=nullpass@*/ 00757 rpmtsEmpty(ts); 00758 break; 00759 case RPMQV_RPM: 00760 qva->qva_gi = rpmgiNew(ts, RPMDBI_ARGLIST, NULL, 0); 00761 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, giFlags); 00762 00763 if (rpmgiGetFlags(qva->qva_gi) & RPMGI_TSADD) /* Load the ts with headers. */ 00764 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) 00765 {}; 00766 if (rpmrc != RPMRC_NOTFOUND) 00767 return 1; /* XXX should be no. of failures. */ 00768 00769 /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */ 00770 ec = rpmQueryVerify(qva, ts, NULL); 00771 /*@=nullpass@*/ 00772 rpmtsEmpty(ts); 00773 break; 00774 case RPMQV_HDLIST: 00775 qva->qva_gi = rpmgiNew(ts, RPMDBI_HDLIST, NULL, 0); 00776 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, giFlags); 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, NULL); 00786 /*@=nullpass@*/ 00787 rpmtsEmpty(ts); 00788 break; 00789 case RPMQV_FTSWALK: 00790 if (rpmioFtsOpts == 0) 00791 rpmioFtsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT); 00792 qva->qva_gi = rpmgiNew(ts, RPMDBI_FTSWALK, NULL, 0); 00793 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, giFlags); 00794 00795 if (rpmgiGetFlags(qva->qva_gi) & RPMGI_TSADD) /* Load the ts with headers. */ 00796 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) 00797 {}; 00798 if (rpmrc != RPMRC_NOTFOUND) 00799 return 1; /* XXX should be no. of failures. */ 00800 00801 /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */ 00802 ec = rpmQueryVerify(qva, ts, NULL); 00803 /*@=nullpass@*/ 00804 rpmtsEmpty(ts); 00805 break; 00806 default: 00807 if (giFlags & RPMGI_TSADD) { 00808 qva->qva_gi = rpmgiNew(ts, RPMDBI_LABEL, NULL, 0); 00809 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, 00810 (giFlags | (RPMGI_NOGLOB ))); 00811 if (rpmgiGetFlags(qva->qva_gi) & RPMGI_TSADD) /* Load the ts with headers. */ 00812 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) 00813 {}; 00814 if (rpmrc != RPMRC_NOTFOUND) 00815 return 1; /* XXX should be no. of failures. */ 00816 qva->qva_source = RPMQV_ALL; 00817 /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */ 00818 ec = rpmQueryVerify(qva, ts, NULL); 00819 /*@=nullpass@*/ 00820 rpmtsEmpty(ts); 00821 } else { 00822 qva->qva_gi = rpmgiNew(ts, RPMDBI_ARGLIST, NULL, 0); 00823 qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, 00824 (giFlags | (RPMGI_NOGLOB|RPMGI_NOHEADER))); 00825 while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) { 00826 const char * path; 00827 path = rpmgiHdrPath(qva->qva_gi); 00828 assert(path != NULL); 00829 ec += rpmQueryVerify(qva, ts, path); 00830 rpmtsEmpty(ts); 00831 } 00832 } 00833 break; 00834 } 00835 00836 qva->qva_gi = rpmgiFree(qva->qva_gi); 00837 00838 return ec; 00839 } 00840 00841 int rpmcliQuery(rpmts ts, QVA_t qva, const char ** argv) 00842 { 00843 rpmdepFlags depFlags = qva->depFlags, odepFlags; 00844 rpmtransFlags transFlags = qva->transFlags, otransFlags; 00845 rpmVSFlags vsflags, ovsflags; 00846 int ec = 0; 00847 00848 if (qva->qva_showPackage == NULL) 00849 qva->qva_showPackage = showQueryPackage; 00850 00851 /* If --queryformat unspecified, then set default now. */ 00852 if (!(qva->qva_flags & _QUERY_FOR_BITS) && qva->qva_queryFormat == NULL) { 00853 qva->qva_queryFormat = rpmExpand("%{?_query_all_fmt}\n", NULL); 00854 if (!(qva->qva_queryFormat != NULL && *qva->qva_queryFormat != '\0')) { 00855 qva->qva_queryFormat = _free(qva->qva_queryFormat); 00856 qva->qva_queryFormat = xstrdup("%{name}-%{version}-%{release}.%{arch}\n"); 00857 } 00858 } 00859 00860 vsflags = rpmExpandNumeric("%{?_vsflags_query}"); 00861 if (qva->qva_flags & VERIFY_DIGEST) 00862 vsflags |= _RPMVSF_NODIGESTS; 00863 if (qva->qva_flags & VERIFY_SIGNATURE) 00864 vsflags |= _RPMVSF_NOSIGNATURES; 00865 if (qva->qva_flags & VERIFY_HDRCHK) 00866 vsflags |= RPMVSF_NOHDRCHK; 00867 00868 odepFlags = rpmtsSetDFlags(ts, depFlags); 00869 otransFlags = rpmtsSetFlags(ts, transFlags); 00870 ovsflags = rpmtsSetVSFlags(ts, vsflags); 00871 ec = rpmcliArgIter(ts, qva, argv); 00872 vsflags = rpmtsSetVSFlags(ts, ovsflags); 00873 transFlags = rpmtsSetFlags(ts, otransFlags); 00874 depFlags = rpmtsSetDFlags(ts, odepFlags); 00875 00876 if (qva->qva_showPackage == showQueryPackage) 00877 qva->qva_showPackage = NULL; 00878 00879 return ec; 00880 }