RPM Package Manager, CVS Repository
  http://rpm5.org/cvs/
  ____________________________________________________________________________

  Server: rpm5.org                         Name:   Jeff Johnson
  Root:   /v/rpm/cvs                       Email:  [EMAIL PROTECTED]
  Module: rpm                              Date:   16-Mar-2008 19:07:27
  Branch: HEAD                             Handle: 2008031618072700

  Modified files:
    rpm/rpmio               rpmmtree.c

  Log:
    - jbj: rpmmtree: heh, rpmioInit() parsing options already, don't do twice.
    - jbj: rpmmtree: calculate multiple digests in parallel for speed.
    - jbj: rpmmtree: get rid of per-digest strings, alggos/digests as arrays.
    - jbj: rpmmtree: rpmdc import form rpmdigest.c no help, rip it out.

  Summary:
    Revision    Changes     Path
    1.24        +334 -507   rpm/rpmio/rpmmtree.c
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmmtree.c
  ============================================================================
  $ cvs diff -u -r1.23 -r1.24 rpmmtree.c
  --- rpm/rpmio/rpmmtree.c      16 Mar 2008 00:42:04 -0000      1.23
  +++ rpm/rpmio/rpmmtree.c      16 Mar 2008 18:07:27 -0000      1.24
  @@ -120,15 +120,8 @@
       struct _node     *prev, *next;           /*!< left, right */
       struct stat              sb;                     /*!< parsed stat(2) 
info */
       char             *slink;                 /*!< symbolic link reference */
  -#ifdef       NOTYET
       ARGI_t           algos;                  /*!< digest algorithms */
       ARGV_t           digests;                /*!< digest strings */
  -#else
  -    char             *md5digest;             /*!< MD5 digest */
  -    char             *sha1digest;            /*!< SHA-1 digest */
  -    char             *sha256digest;          /*!< SHA-256 digest */
  -    char             *rmd160digest;          /*!< RIPEMD-160 digest */
  -#endif
   
       uint32_t         cksum;                  /*!< check sum */
   
  @@ -231,6 +224,15 @@
   /[EMAIL PROTECTED]@*/
   static LIST_HEAD(, exclude) excludes;
   
  +/[EMAIL PROTECTED]@*/
  +static struct rpmop_s dc_totalops;
  +
  +/[EMAIL PROTECTED]@*/
  +static struct rpmop_s dc_readops;
  +
  +/[EMAIL PROTECTED]@*/
  +static struct rpmop_s dc_digestops;
  +
   /*==============================================================*/
   
   #if !defined(POPT_ARG_ARGV)
  @@ -329,6 +331,10 @@
   {
       KEY *k, tmp;
   
  +    if (needvaluep != NULL)
  +     *needvaluep = 0;
  +    if (*name == '\0')
  +     return 0;
       tmp.name = name;
       k = (KEY *)bsearch(&tmp, keylist, sizeof(keylist) / sizeof(keylist[0]),
            sizeof(keylist[0]), keycompare);
  @@ -340,12 +346,12 @@
       return k->val;
   }
   
  -#ifdef       NOTYET
   static const char *
   flags_to_string(u_long fflags)
        /[EMAIL PROTECTED]/
   {
   #if defined(__linux__)
  +    fflags = fflags;
       return xstrdup("none");
   #else
       char * string = fflagstostr(fflags);
  @@ -356,7 +362,6 @@
       return string;
   #endif
   }
  -#endif
   
   /*==============================================================*/
   
  @@ -1320,18 +1325,17 @@
        /[EMAIL PROTECTED] fileSystem, internalState @*/
        /[EMAIL PROTECTED] t, ip, fileSystem, internalState @*/
   {
  -    enum mtreeKeys_e type;
  -    char *kw, *val = NULL;
  -    struct group *gr;
  -    struct passwd *pw;
  -    mode_t *m;
  -    int value;
  -    char *ep;
  +    char *kw;
   
       for (; (kw = strtok(t, "= \t\n")) != NULL; t = NULL) {
  -     ip->flags |= type = parsekey(kw, &value);
  -     if (value && (val = strtok(NULL, " \t\n")) == NULL)
  +     int needvalue;
  +     enum mtreeKeys_e type = parsekey(kw, &needvalue);
  +     char *val = NULL;
  +     char *ep;
  +
  +     if (needvalue && (val = strtok(NULL, " \t\n")) == NULL)
                mtree_error("missing value");
  +     ip->flags |= type;
        switch(type) {
        case MTREE_KEYS_CKSUM:
            ip->cksum = strtoul(val, &ep, 10);
  @@ -1339,7 +1343,8 @@
                mtree_error("invalid checksum %s", val);
            /[EMAIL PROTECTED]@*/ break;
        case MTREE_KEYS_MD5:
  -         ip->md5digest = xstrdup(val);
  +         (void) argiAdd(&ip->algos, -1, PGPHASHALGO_MD5);
  +         (void) argvAdd(&ip->digests, val);
            /[EMAIL PROTECTED]@*/ break;
        case MTREE_KEYS_FLAGS:
   #if defined(__linux__)
  @@ -1361,32 +1366,37 @@
                mtree_error("invalid gid %s", val);
            /[EMAIL PROTECTED]@*/ break;
        case MTREE_KEYS_GNAME:
  -         if ((gr = getgrnam(val)) == NULL)
  +     {   struct group *gr = getgrnam(val);
  +         if (gr == NULL)
                mtree_error("unknown group %s", val);
            ip->sb.st_gid = gr->gr_gid;
  -         /[EMAIL PROTECTED]@*/ break;
  +     }   /[EMAIL PROTECTED]@*/ break;
        case MTREE_KEYS_IGN:
            /* just set flag bit */
            /[EMAIL PROTECTED]@*/ break;
        case MTREE_KEYS_MODE:
  +     {   mode_t *m;
            if ((m = setmode(val)) == NULL)
                mtree_error("invalid file mode %s", val);
            ip->sb.st_mode = getmode(m, 0);
            free(m);
  -         /[EMAIL PROTECTED]@*/ break;
  +     }   /[EMAIL PROTECTED]@*/ break;
        case MTREE_KEYS_NLINK:
            ip->sb.st_nlink = strtoul(val, &ep, 10);
            if (*ep != '\0')
                mtree_error("invalid link count %s", val);
            /[EMAIL PROTECTED]@*/ break;
        case MTREE_KEYS_RMD160:
  -         ip->rmd160digest = xstrdup(val);
  +         (void) argiAdd(&ip->algos, -1, PGPHASHALGO_RIPEMD160);
  +         (void) argvAdd(&ip->digests, val);
            /[EMAIL PROTECTED]@*/ break;
        case MTREE_KEYS_SHA1:
  -         ip->sha1digest = xstrdup(val);
  +         (void) argiAdd(&ip->algos, -1, PGPHASHALGO_SHA1);
  +         (void) argvAdd(&ip->digests, val);
            /[EMAIL PROTECTED]@*/ break;
        case MTREE_KEYS_SHA256:
  -         ip->sha256digest = xstrdup(val);
  +         (void) argiAdd(&ip->algos, -1, PGPHASHALGO_SHA256);
  +         (void) argvAdd(&ip->digests, val);
            /[EMAIL PROTECTED]@*/ break;
        case MTREE_KEYS_SIZE:
   /[EMAIL PROTECTED]@*/
  @@ -1460,10 +1470,11 @@
                mtree_error("invalid uid %s", val);
            /[EMAIL PROTECTED]@*/ break;
        case MTREE_KEYS_UNAME:
  -         if ((pw = getpwnam(val)) == NULL)
  +     {   struct passwd *pw = getpwnam(val);
  +         if (pw == NULL)
                mtree_error("unknown user %s", val);
            ip->sb.st_uid = pw->pw_uid;
  -         /[EMAIL PROTECTED]@*/ break;
  +     }   /[EMAIL PROTECTED]@*/ break;
        case MTREE_KEYS_NONE:
        case MTREE_KEYS_DONE:
        case MTREE_KEYS_MAGIC:
  @@ -1603,180 +1614,6 @@
   
   /*==============================================================*/
   
  -#define FILE_BUFFER                  0x1000
  -typedef struct rpmdc_s * rpmdc;
  -
  -#define _DFB(n) ((1 << (n)) | 0x40000000)
  -#define F_ISSET(_dc, _FLAG) ((_dc)->flags & ((RPMDC_FLAGS_##_FLAG) & 
~0x40000000))
  -
  -enum dcFlags_e {
  -    RPMDC_FLAGS_BINARY       = _DFB( 0),     /*!< -b,--binary ... */
  -    RPMDC_FLAGS_WARN = _DFB( 1),     /*!< -w,--warn ... */
  -    RPMDC_FLAGS_STATUS       = _DFB( 2)      /*!<    --status ... */
  -};
  -
  -struct rpmdc_s {
  -    enum dcFlags_e flags;
  -    uint32_t algo;           /*!< default digest algorithm. */
  -/[EMAIL PROTECTED]@*/
  -    const char * digest;
  -    size_t digestlen;
  -/[EMAIL PROTECTED]@*/
  -    const char * fn;
  -    FD_t fd;
  -/[EMAIL PROTECTED]@*/
  -    ARGV_t manifests;                /*!< array of file manifests to verify. 
*/
  -/[EMAIL PROTECTED]@*/
  -    ARGI_t algos;            /*!< array of file digest algorithms. */
  -/[EMAIL PROTECTED]@*/
  -    ARGV_t digests;          /*!< array of file digests. */
  -/[EMAIL PROTECTED]@*/
  -    ARGV_t paths;            /*!< array of file paths. */
  -    unsigned char buf[BUFSIZ];
  -    ssize_t nb;
  -    int ix;
  -    int nfails;
  -};
  -
  -/[EMAIL PROTECTED]@*/
  -static struct rpmdc_s __dc;
  -
  -/[EMAIL PROTECTED]@*/
  -static rpmdc _dc = &__dc;
  -
  -/[EMAIL PROTECTED]@*/
  -static struct rpmop_s dc_totalops;
  -
  -/[EMAIL PROTECTED]@*/
  -static struct rpmop_s dc_readops;
  -
  -/[EMAIL PROTECTED]@*/
  -static struct rpmop_s dc_digestops;
  -
  -static int rpmdcPrintFile(rpmdc dc, uint32_t algo, const char * algoName)
  -     /[EMAIL PROTECTED] fileSystem, internalState @*/
  -     /[EMAIL PROTECTED] dc, fileSystem, internalState @*/
  -{
  -    static int asAscii = 1;
  -    int rc = 0;
  -
  -    fdFiniDigest(dc->fd, algo, &dc->digest, &dc->digestlen, asAscii);
  -assert(dc->digest != NULL);
  -    if (dc->manifests != NULL) {
  -     const char * msg = "OK";
  -     if ((rc = strcmp(dc->digest, dc->digests[dc->ix])) != 0) {
  -         msg = "FAILED";
  -         dc->nfails++;
  -     }
  -     if (rc || !F_ISSET(dc, STATUS))
  -         fprintf(stdout, "%s: %s\n", dc->fn, msg);
  -    } else {
  -     if (!F_ISSET(dc, STATUS)) {
  -         if (algoName != NULL) fprintf(stdout, "%s:", algoName);
  -         fprintf(stdout, "%s %c%s\n", dc->digest,
  -             (F_ISSET(dc, BINARY) ? '*' : ' '), dc->fn);
  -         (void) fflush(stdout);
  -     }
  -     dc->digest = _free(dc->digest);
  -    }
  -    return rc;
  -}
  -
  -static int rpmdcFiniFile(rpmdc dc)
  -     /[EMAIL PROTECTED] fileSystem, internalState @*/
  -     /[EMAIL PROTECTED] dc, fileSystem, internalState @*/
  -{
  -    uint32_t algo= (dc->manifests != NULL ? dc->algos->vals[dc->ix] : 
dc->algo);
  -    int rc = 0;
  -    int xx;
  -
  -    switch (algo) {
  -    default:
  -     xx = rpmdcPrintFile(dc, algo, NULL);
  -     if (xx) rc = xx;
  -     break;
  -    case 256:                /* --all digests requested. */
  -      {      struct poptOption * opt = rpmioDigestPoptTable;
  -     for (; (opt->longName || opt->shortName || opt->arg) ; opt++) {
  -         if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL)
  -             continue;
  -         if (opt->arg != (void *)&rpmioDigestHashAlgo)
  -             continue;
  -         dc->algo = opt->val;
  -         if (!(dc->algo > 0 && dc->algo < 256))
  -             continue;
  -         xx = rpmdcPrintFile(dc, dc->algo, opt->longName);
  -         if (xx) rc = xx;
  -     }
  -      }      break;
  -    }
  -    (void) rpmswAdd(&dc_readops, fdstat_op(dc->fd, FDSTAT_READ));
  -    (void) rpmswAdd(&dc_digestops, fdstat_op(dc->fd, FDSTAT_DIGEST));
  -    (void) Fclose(dc->fd);
  -    dc->fd = NULL;
  -    return rc;
  -}
  -
  -static int rpmdcCalcFile(rpmdc dc)
  -     /[EMAIL PROTECTED] fileSystem @*/
  -     /[EMAIL PROTECTED] dc, fileSystem @*/
  -{
  -    int rc = 0;
  -
  -    do {
  -     dc->nb = Fread(dc->buf, sizeof(dc->buf[0]), sizeof(dc->buf), dc->fd);
  -     if (Ferror(dc->fd)) {
  -         rc = 2;
  -         break;
  -     }
  -    } while (dc->nb > 0);
  -
  -    return rc;
  -}
  -
  -static int rpmdcInitFile(rpmdc dc)
  -     /[EMAIL PROTECTED] h_errno, fileSystem, internalState @*/
  -     /[EMAIL PROTECTED] dc, fileSystem, internalState @*/
  -{
  -    uint32_t algo= (dc->manifests != NULL ? dc->algos->vals[dc->ix] : 
dc->algo);
  -    int rc = 0;
  -
  -    /* XXX Stat(2) to insure files only? */
  -    dc->fd = Fopen(dc->fn, "r.ufdio");
  -    if (dc->fd == NULL || Ferror(dc->fd)) {
  -     fprintf(stderr, _("open of %s failed: %s\n"), dc->fn, 
Fstrerror(dc->fd));
  -     if (dc->fd != NULL) (void) Fclose(dc->fd);
  -     dc->fd = NULL;
  -     rc = 2;
  -     goto exit;
  -    }
  -
  -    switch (dc->algo) {
  -    default:
  -     /* XXX TODO: instantiate verify digests for all identical paths. */
  -     fdInitDigest(dc->fd, algo, 0);
  -     break;
  -    case 256:                /* --all digests requested. */
  -      {      struct poptOption * opt = rpmioDigestPoptTable;
  -     for (; (opt->longName || opt->shortName || opt->arg) ; opt++) {
  -         if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL)
  -             continue;
  -         if (opt->longName == NULL)
  -             continue;
  -         if (!(opt->val > 0 && opt->val < 256))
  -             continue;
  -         algo = opt->val;
  -         fdInitDigest(dc->fd, algo, 0);
  -     }
  -      }      break;
  -    }
  -
  -exit:
  -    return rc;
  -}
  -
  -/*==============================================================*/
  -
   /[EMAIL PROTECTED]@*/
   static const char *
   ftype(unsigned type)
  @@ -1836,13 +1673,13 @@
   #define      COMPAREINDENTNAMELEN    8
   #define      LABEL                   \
       if (!label++) {           \
  -     len = printf("%s: ", SKIPDOTSLASH(p->fts_path)); \
  +     int len = printf("%s: ", SKIPDOTSLASH(p->fts_path)); \
        if (len > COMPAREINDENTNAMELEN) { \
            tab = "\t";         \
            (void) printf("\n"); \
        } else {                \
            tab = "";           \
  -         (void) printf("%*s", COMPAREINDENTNAMELEN - (int)len, ""); \
  +         (void) printf("%*s", COMPAREINDENTNAMELEN - len, ""); \
        }                       \
       }
   
  @@ -1855,21 +1692,52 @@
        }                       \
       } while (0)                      \
   
  +/[EMAIL PROTECTED]@*/
  +static const char * algo2name(uint32_t algo)
  +     /[EMAIL PROTECTED]/
  +{
  +    switch (algo) {
  +    case PGPHASHALGO_MD5:          return "MD5";
  +    case PGPHASHALGO_SHA1:         return "SHA1";
  +    case PGPHASHALGO_RIPEMD160:    return "RIPEMD160";
  +    case PGPHASHALGO_MD2:          return "MD2";
  +    case PGPHASHALGO_TIGER192:     return "TIGER192";
  +    case PGPHASHALGO_HAVAL_5_160:  return "HAVAL-5-160";
  +    case PGPHASHALGO_SHA256:       return "SHA256";
  +    case PGPHASHALGO_SHA384:       return "SHA384";
  +    case PGPHASHALGO_SHA512:       return "SHA512";
  +
  +    case PGPHASHALGO_MD4:       return "MD4";
  +    case PGPHASHALGO_RIPEMD128:         return "RIPEMD128";
  +    case PGPHASHALGO_CRC32:     return "CRC32";
  +    case PGPHASHALGO_ADLER32:           return "ADLER32";
  +    case PGPHASHALGO_CRC64:     return "CRC64";
  +    case PGPHASHALGO_JLU32:     return "JLU32";
  +    case PGPHASHALGO_SHA224:    return "SHA224";
  +    case PGPHASHALGO_RIPEMD256:         return "RIPEMD256";
  +    case PGPHASHALGO_RIPEMD320:         return "RIPEMD320";
  +    case PGPHASHALGO_SALSA10:           return "SALSA10";
  +    case PGPHASHALGO_SALSA20:           return "SALSA20";
  +
  +    default:                       return "Unknown";
  +    }
  +    /[EMAIL PROTECTED]@*/
  +}
  +
   static int
  -compare(const char * name, NODE *const s, FTSENT *const p)
  -     /[EMAIL PROTECTED] _dc, errno, h_errno, fileSystem, internalState @*/
  -     /[EMAIL PROTECTED] _dc, errno, fileSystem, internalState @*/
  +compare(rpmfts fts, NODE *const s)
  +     /[EMAIL PROTECTED] errno, h_errno, fileSystem, internalState @*/
  +     /[EMAIL PROTECTED] errno, fileSystem, internalState @*/
   
   {
  -    static int asAscii = 1;
  +    const char * name = s->name;
  +    FTSENT *const p = fts->p;
       const char * fts_accpath = p->fts_accpath;
       struct stat *const st = p->fts_statp;
       enum mtreeKeys_e keys = s->flags;
  -    uint32_t len, val;
       int label = 0;
       const char *cp;
       const char *tab = "";
  -    int xx;
   
       switch(s->type) {
       case F_BLOCK:
  @@ -2015,140 +1883,79 @@
            tab = "\t";   
        }
       }
  -    if (KF_ISSET(keys, CKSUM)) {
  +
  +    /* Any digests to calculate? */
  +    if (KF_ISSET(keys, CKSUM) || s->algos != NULL) {
        FD_t fd = Fopen(fts_accpath, "r.ufdio");
  +     uint32_t vlen, val;
  +     int i;
  +
        if (fd == NULL || Ferror(fd)) {
            LABEL;
  -         (void) printf("%scksum: %s: %s\n", tab,
  -                     fts_accpath, Fstrerror(fd));
  -     } else if (crc(fd, &val, &len)) {
  +         (void) printf("%scksum: %s: %s\n", tab, fts_accpath, Fstrerror(fd));
  +         goto cleanup;
  +     }
  +
  +     /* Setup all digest calculations.  Reversed order is effete ... */
  +     if (s->algos != NULL)
  +     for (i = s->algos->nvals; i-- > 0;)
  +         fdInitDigest(fd, s->algos->vals[i], 0);
  +
  +     /* Compute the cksum and digests. */
  +     if (KF_ISSET(keys, CKSUM))
  +         i = crc(fd, &val, &vlen);
  +     else {
  +         char buffer[16 * 1024];
  +         while (Fread(buffer, sizeof(buffer[0]), sizeof(buffer), fd) > 0)
  +             {};
  +         i = (Ferror(fd) ? 1 : 0);
  +     }
  +     if (i) {
            LABEL;
  -         (void) printf("%scksum: %s: %s\n", tab,
  -                     fts_accpath, Fstrerror(fd));
  -     } else {
  +         (void) printf("%scksum: %s: %s\n", tab, fts_accpath, Fstrerror(fd));
  +         goto cleanup;
  +     }
  +
  +     /* Verify cksum. */
  +     if (KF_ISSET(keys, CKSUM)) {
            if (s->cksum != val) {
                LABEL;
                (void) printf("%scksum (%u, %u)\n", tab,
                                (unsigned) s->cksum, (unsigned) val);
  +             tab = "\t";
            }
        }
  -     if (fd != NULL) (void) Fclose(fd);
  -     tab = "\t";
  -    }
  -/[EMAIL PROTECTED]@*/        /* dc->fn might modify fts_accpath */
  -    if (KF_ISSET(keys, MD5)) {
  -     rpmdc dc = _dc;
  -     dc->fn = fts_accpath;
  -     dc->algo = PGPHASHALGO_MD5;
  -     xx = rpmdcInitFile(dc);
  -     xx = rpmdcCalcFile(dc);
  -     /* XXX hotwire around rpmdcFini() for now. */
  -     fdFiniDigest(dc->fd, dc->algo, &dc->digest, &dc->digestlen, asAscii);
  -     if (dc->digest == NULL) {
  -         LABEL;
  -         printf("%sMD5File: %s: %s\n", tab, fts_accpath, strerror(errno));
  -         tab = "\t";
  -     } else if (strcmp(dc->digest, s->md5digest)) {
  -         LABEL;
  -         printf("%sMD5 (%s, %s)\n", tab, s->md5digest, dc->digest);
  -         tab = "\t";
  -     }
  -     if (dc->fd != NULL) {
  -         (void) rpmswAdd(&dc_readops, fdstat_op(dc->fd, FDSTAT_READ));
  -         (void) rpmswAdd(&dc_digestops, fdstat_op(dc->fd, FDSTAT_DIGEST));
  -         (void) Fclose(dc->fd);
  -         dc->fd = NULL;
  -         dc->digest = _free(dc->digest);
  -         dc->digestlen = 0;
  -     }
  -     dc->algo = 0;
  -     dc->fn = NULL;
  -    }
  -    if (KF_ISSET(keys, RMD160)) {
  -     rpmdc dc = _dc;
  -     dc->fn = fts_accpath;
  -     dc->algo = PGPHASHALGO_RIPEMD160;
  -     xx = rpmdcInitFile(dc);
  -     xx = rpmdcCalcFile(dc);
  -     /* XXX hotwire around rpmdcFini() for now. */
  -     fdFiniDigest(dc->fd, dc->algo, &dc->digest, &dc->digestlen, asAscii);
  -     if (dc->digest == NULL) {
  -         LABEL;
  -         printf("%sRMD160File: %s: %s\n", tab, fts_accpath, strerror(errno));
  -         tab = "\t";
  -     } else if (strcmp(dc->digest, s->rmd160digest)) {
  -         LABEL;
  -         printf("%sRMD160 (%s, %s)\n", tab, s->rmd160digest, dc->digest);
  -         tab = "\t";
  -     }
  -     if (dc->fd != NULL) {
  -         (void) rpmswAdd(&dc_readops, fdstat_op(dc->fd, FDSTAT_READ));
  -         (void) rpmswAdd(&dc_digestops, fdstat_op(dc->fd, FDSTAT_DIGEST));
  -         (void) Fclose(dc->fd);
  -         dc->fd = NULL;
  -         dc->digest = _free(dc->digest);
  -         dc->digestlen = 0;
  -     }
  -     dc->algo = 0;
  -     dc->fn = NULL;
  -    }
  -    if (KF_ISSET(keys, SHA1)) {
  -     rpmdc dc = _dc;
  -     dc->fn = fts_accpath;
  -     dc->algo = PGPHASHALGO_SHA1;
  -     xx = rpmdcInitFile(dc);
  -     xx = rpmdcCalcFile(dc);
  -     /* XXX hotwire around rpmdcFini() for now. */
  -     fdFiniDigest(dc->fd, dc->algo, &dc->digest, &dc->digestlen, asAscii);
  -     if (dc->digest == NULL) {
  -         LABEL;
  -         printf("%sSHA1File: %s: %s\n", tab, fts_accpath, strerror(errno));
  -         tab = "\t";
  -     } else if (strcmp(dc->digest, s->sha1digest)) {
  -         LABEL;
  -         printf("%sSHA1 (%s, %s)\n", tab, s->sha1digest, dc->digest);
  -         tab = "\t";
  -     }
  -     if (dc->fd != NULL) {
  -         (void) rpmswAdd(&dc_readops, fdstat_op(dc->fd, FDSTAT_READ));
  -         (void) rpmswAdd(&dc_digestops, fdstat_op(dc->fd, FDSTAT_DIGEST));
  -         (void) Fclose(dc->fd);
  -         dc->fd = NULL;
  -         dc->digest = _free(dc->digest);
  -         dc->digestlen = 0;
  -     }
  -     dc->algo = 0;
  -     dc->fn = NULL;
  -    }
  -    if (KF_ISSET(keys, SHA256)) {
  -     rpmdc dc = _dc;
  -     dc->fn = fts_accpath;
  -     dc->algo = PGPHASHALGO_SHA256;
  -     xx = rpmdcInitFile(dc);
  -     xx = rpmdcCalcFile(dc);
  -     /* XXX hotwire around rpmdcFini() for now. */
  -     fdFiniDigest(dc->fd, dc->algo, &dc->digest, &dc->digestlen, asAscii);
  -     if (dc->digest == NULL) {
  -         LABEL;
  -         printf("%sSHA256File: %s: %s\n", tab, fts_accpath, strerror(errno));
  -         tab = "\t";
  -     } else if (strcmp(dc->digest, s->sha1digest)) {
  -         LABEL;
  -         printf("%sSHA256 (%s, %s)\n", tab, s->sha1digest, dc->digest);
  -         tab = "\t";
  +
  +     /* Verify all the digests. */
  +     if (s->algos != NULL)
  +     for (i = 0; i < (int) s->algos->nvals; i++) {
  +         static int asAscii = 1;
  +         uint32_t algo = s->algos->vals[i];
  +         const char * digest = NULL;
  +         size_t digestlen = 0;
  +
  +         fdFiniDigest(fd, algo, &digest, &digestlen, asAscii);
  +assert(digest != NULL);
  +         if (strcmp(digest, s->digests[i])) {
  +             LABEL;
  +             printf("%s%s (%s, %s)\n", tab, algo2name(algo),
  +                     s->digests[i], digest);
  +             tab = "\t";
  +         }
  +         digest = _free(digest);
  +         digestlen = 0;
        }
  -     if (dc->fd != NULL) {
  -         (void) rpmswAdd(&dc_readops, fdstat_op(dc->fd, FDSTAT_READ));
  -         (void) rpmswAdd(&dc_digestops, fdstat_op(dc->fd, FDSTAT_DIGEST));
  -         (void) Fclose(dc->fd);
  -         dc->fd = NULL;
  -         dc->digest = _free(dc->digest);
  -         dc->digestlen = 0;
  +
  +     /* Accumulate statistics and clean up. */
  +cleanup:
  +     if (fd != NULL) {
  +         (void) rpmswAdd(&dc_readops, fdstat_op(fd, FDSTAT_READ));
  +         (void) rpmswAdd(&dc_digestops, fdstat_op(fd, FDSTAT_DIGEST));
  +         (void) Fclose(fd);
  +         fd = NULL;
        }
  -     dc->algo = 0;
  -     dc->fn = NULL;
       }
  -/[EMAIL PROTECTED]@*/
  +
       if (KF_ISSET(keys, SLINK) && strcmp(cp = rlink(name), s->slink)) {
        LABEL;
        (void) printf("%slink ref (%s, %s)\n", tab, cp, s->slink);
  @@ -2195,40 +2002,6 @@
   
   /*==============================================================*/
   
  -#define      CWALKINDENTNAMELEN      15
  -#define      MAXLINELEN      80
  -
  -static int
  -dsort(const FTSENT ** a, const FTSENT ** b)
  -     /[EMAIL PROTECTED]/
  -{
  -    if (S_ISDIR((*a)->fts_statp->st_mode)) {
  -     if (!S_ISDIR((*b)->fts_statp->st_mode))
  -         return 1;
  -    } else if (S_ISDIR((*b)->fts_statp->st_mode))
  -     return -1;
  -    return strcmp((*a)->fts_name, (*b)->fts_name);
  -}
  -
  -static void
  -output(int indent, int * offset, const char * fmt, ...)
  -     /[EMAIL PROTECTED] fileSystem @*/
  -     /[EMAIL PROTECTED] *offset, fileSystem @*/
  -{
  -    char buf[1024];
  -    va_list ap;
  -
  -    va_start(ap, fmt);
  -    (void) vsnprintf(buf, sizeof(buf), fmt, ap);
  -    va_end(ap);
  -
  -    if (*offset + strlen(buf) > MAXLINELEN - 3) {
  -     (void)printf(" \\\n%*s", CWALKINDENTNAMELEN + indent, "");
  -     *offset = CWALKINDENTNAMELEN + indent;
  -    }
  -    *offset += printf(" %s", buf) + 1;
  -}
  -
   #define      MAXGID  5000
   #define      MAXUID  5000
   #define      MAXMODE MBITS + 1
  @@ -2366,13 +2139,9 @@
        if (KF_ISSET(keys, NLINK))
            (void) printf(" nlink=1");
        if (KF_ISSET(keys, FLAGS)) {
  -#if defined(__linux__) || !defined(NOTYET)
  -         (void) printf(" flags=none");
  -#else
            const char * fflags = flags_to_string(saveflags);
            (void) printf(" flags=%s", fflags);
            fflags = _free(fflags);
  -#endif
        }
        (void) printf("\n");
        *puid = saveuid;
  @@ -2383,30 +2152,50 @@
       return (0);
   }
   
  +#define      CWALKINDENTNAMELEN      15
  +#define      MAXLINELEN      80
  +
  +
  +static void
  +output(int indent, int * offset, const char * fmt, ...)
  +     /[EMAIL PROTECTED] fileSystem @*/
  +     /[EMAIL PROTECTED] *offset, fileSystem @*/
  +{
  +    char buf[1024];
  +    va_list ap;
  +
  +    va_start(ap, fmt);
  +    (void) vsnprintf(buf, sizeof(buf), fmt, ap);
  +    va_end(ap);
  +
  +    if (*offset + strlen(buf) > MAXLINELEN - 3) {
  +     (void)printf(" \\\n%*s", CWALKINDENTNAMELEN + indent, "");
  +     *offset = CWALKINDENTNAMELEN + indent;
  +    }
  +    *offset += printf(" %s", buf) + 1;
  +}
  +
   static void
   mtreeVisitF(rpmfts fts)
  -     /[EMAIL PROTECTED] _dc, errno, h_errno, fileSystem, internalState @*/
  -     /[EMAIL PROTECTED] _dc, errno, fileSystem, internalState @*/
  +     /[EMAIL PROTECTED] errno, h_errno, fileSystem, internalState @*/
  +     /[EMAIL PROTECTED] errno, fileSystem, internalState @*/
   {
  -    static int asAscii = 1;
       enum mtreeKeys_e keys = fts->keys;
       const char * fts_accpath = fts->p->fts_accpath;
       unsigned short fts_info = fts->p->fts_info;
       struct stat *const st = fts->p->fts_statp;
       int indent = (MF_ISSET(INDENT) ? fts->p->fts_level * 4 : 0);
  -    uint32_t len, val;
       int offset;
  -    char * escaped_name = xmalloc(fts->p->fts_namelen * 4  +  1);
  -    int xx;
   
  -    (void) strvis(escaped_name, fts->p->fts_name, VIS_WHITE | VIS_OCTAL);
  +    {        char * escname = xmalloc(fts->p->fts_namelen * 4  +  1);
  +     (void) strvis(escname, fts->p->fts_name, VIS_WHITE | VIS_OCTAL);
   
  -    if (MF_ISSET(INDENT) || S_ISDIR(st->st_mode))
  -     offset = printf("%*s%s", indent, "", escaped_name);
  -    else
  -     offset = printf("%*s    %s", indent, "", escaped_name);
  -
  -    escaped_name = _free(escaped_name);
  +     if (MF_ISSET(INDENT) || S_ISDIR(st->st_mode))
  +         offset = printf("%*s%s", indent, "", escname);
  +     else
  +         offset = printf("%*s    %s", indent, "", escname);
  +     escname = _free(escname);
  +    }
   
       if (offset > (CWALKINDENTNAMELEN + indent))
        offset = MAXLINELEN;
  @@ -2459,115 +2248,153 @@
   #endif
        output(indent, &offset, "time=%lu.%lu", tv.tv_sec, tv.tv_usec);
       }
  -    if (KF_ISSET(keys, CKSUM) && S_ISREG(st->st_mode)) {
  -     FD_t fd = Fopen(fts_accpath, "r.ufdio");
  -     if (fd == NULL || Ferror(fd) || crc(fd, &val, &len))
  -         mtree_error("%s: %s", fts_accpath, Fstrerror(fd));
  -     if (fd != NULL) (void) Fclose(fd);
  -     output(indent, &offset, "cksum=%lu", (unsigned long)val);
  -    }
  -/[EMAIL PROTECTED]@*/        /* dc->fn might modify fts_accpath */
  -    if (KF_ISSET(keys, MD5) && S_ISREG(st->st_mode)) {
  -     rpmdc dc = _dc;
  -     dc->fn = fts_accpath;
  -     dc->algo = PGPHASHALGO_MD5;
  -     xx = rpmdcInitFile(dc);
  -     xx = rpmdcCalcFile(dc);
  -     /* XXX hotwire around rpmdcFini() for now. */
  -     fdFiniDigest(dc->fd, dc->algo, &dc->digest, &dc->digestlen, asAscii);
  -     if (dc->digest == NULL)
  -         mtree_error("%s: %s", fts_accpath, strerror(errno));
  -     else
  -         output(indent, &offset, "md5digest=%s", dc->digest);
  -     if (dc->fd != NULL) {
  -         (void) rpmswAdd(&dc_readops, fdstat_op(dc->fd, FDSTAT_READ));
  -         (void) rpmswAdd(&dc_digestops, fdstat_op(dc->fd, FDSTAT_DIGEST));
  -         (void) Fclose(dc->fd);
  -         dc->fd = NULL;
  -         dc->digest = _free(dc->digest);
  -         dc->digestlen = 0;
  -     }
  -     dc->algo = 0;
  -     dc->fn = NULL;
  -    }
  -    if (KF_ISSET(keys, RMD160) && S_ISREG(st->st_mode)) {
  -     rpmdc dc = _dc;
  -     dc->fn = fts_accpath;
  -     dc->algo = PGPHASHALGO_RIPEMD160;
  -     xx = rpmdcInitFile(dc);
  -     xx = rpmdcCalcFile(dc);
  -     /* XXX hotwire around rpmdcFini() for now. */
  -     fdFiniDigest(dc->fd, dc->algo, &dc->digest, &dc->digestlen, asAscii);
  -     if (dc->digest == NULL)
  -         mtree_error("%s: %s", fts_accpath, strerror(errno));
  -     else
  -         output(indent, &offset, "rmd160digest=%s", dc->digest);
  -     if (dc->fd != NULL) {
  -         (void) rpmswAdd(&dc_readops, fdstat_op(dc->fd, FDSTAT_READ));
  -         (void) rpmswAdd(&dc_digestops, fdstat_op(dc->fd, FDSTAT_DIGEST));
  -         (void) Fclose(dc->fd);
  -         dc->fd = NULL;
  -         dc->digest = _free(dc->digest);
  -         dc->digestlen = 0;
  -     }
  -     dc->algo = 0;
  -     dc->fn = NULL;
  -    }
  -    if (KF_ISSET(keys, SHA1) && S_ISREG(st->st_mode)) {
  -     rpmdc dc = _dc;
  -     dc->fn = fts_accpath;
  -     dc->algo = PGPHASHALGO_SHA1;
  -     xx = rpmdcInitFile(dc);
  -     xx = rpmdcCalcFile(dc);
  -     /* XXX hotwire around rpmdcFini() for now. */
  -     fdFiniDigest(dc->fd, dc->algo, &dc->digest, &dc->digestlen, asAscii);
  -     if (dc->digest == NULL)
  -         mtree_error("%s: %s", fts_accpath, strerror(errno));
  -     else
  -         output(indent, &offset, "sha1digest=%s", dc->digest);
  -     if (dc->fd != NULL) {
  -         (void) rpmswAdd(&dc_readops, fdstat_op(dc->fd, FDSTAT_READ));
  -         (void) rpmswAdd(&dc_digestops, fdstat_op(dc->fd, FDSTAT_DIGEST));
  -         (void) Fclose(dc->fd);
  -         dc->fd = NULL;
  -         dc->digest = _free(dc->digest);
  -         dc->digestlen = 0;
  -     }
  -     dc->algo = 0;
  -     dc->fn = NULL;
  -    }
  -    if (KF_ISSET(keys, SHA256) && S_ISREG(st->st_mode)) {
  -     rpmdc dc = _dc;
  -     dc->fn = fts_accpath;
  -     dc->algo = PGPHASHALGO_SHA256;
  -     xx = rpmdcInitFile(dc);
  -     xx = rpmdcCalcFile(dc);
  -     /* XXX hotwire around rpmdcFini() for now. */
  -     fdFiniDigest(dc->fd, dc->algo, &dc->digest, &dc->digestlen, asAscii);
  -     if (dc->digest == NULL)
  -         mtree_error("%s: %s", fts_accpath, strerror(errno));
  -     else
  -         output(indent, &offset, "sha256digest=%s", dc->digest);
  -     if (dc->fd != NULL) {
  -         (void) rpmswAdd(&dc_readops, fdstat_op(dc->fd, FDSTAT_READ));
  -         (void) rpmswAdd(&dc_digestops, fdstat_op(dc->fd, FDSTAT_DIGEST));
  -         (void) Fclose(dc->fd);
  -         dc->fd = NULL;
  -         dc->digest = _free(dc->digest);
  -         dc->digestlen = 0;
  +
  +    /* Only files can have digests. */
  +    if (S_ISREG(st->st_mode)) {
  +     ARGI_t algos = NULL;
  +
  +     /* Mark all digests that need calculating. */
  +     if (KF_ISSET(keys, MD5))
  +         (void) argiAdd(&algos, -1, PGPHASHALGO_MD5);
  +     if (KF_ISSET(keys, RMD160))
  +         (void) argiAdd(&algos, -1, PGPHASHALGO_RIPEMD160);
  +     if (KF_ISSET(keys, SHA1))
  +         (void) argiAdd(&algos, -1, PGPHASHALGO_SHA1);
  +     if (KF_ISSET(keys, SHA256))
  +         (void) argiAdd(&algos, -1, PGPHASHALGO_SHA256);
  +
  +     /* Any digests to calculate? */
  +     if (KF_ISSET(keys, CKSUM) || algos != NULL) {
  +         FD_t fd = Fopen(fts_accpath, "r.ufdio");
  +         uint32_t len, val;
  +         int i;
  +
  +         if (fd == NULL || Ferror(fd)) {
  +#ifdef       NOTYET  /* XXX can't exit in a library API. */
  +             (void) printf("%scksum: %s: %s\n", tab, fts_accpath, 
Fstrerror(fd));
  +             goto cleanup;
  +#else
  +             mtree_error("%s: %s", fts_accpath, Fstrerror(fd));
  +             /[EMAIL PROTECTED]@*/
  +#endif
  +         }
  +
  +         /* Setup all digest calculations.  Reversed order is effete ... */
  +         if (algos != NULL)
  +         for (i = algos->nvals; i-- > 0;)
  +             fdInitDigest(fd, algos->vals[i], 0);
  +
  +         /* Compute the cksum and digests. */
  +         if (KF_ISSET(keys, CKSUM))
  +             i = crc(fd, &val, &len);
  +         else {
  +             char buffer[16 * 1024];
  +             while (Fread(buffer, sizeof(buffer[0]), sizeof(buffer), fd) > 0)
  +                 {};
  +             i = (Ferror(fd) ? 1 : 0);
  +         }
  +         if (i) {
  +#ifdef       NOTYET  /* XXX can't exit in a library API. */
  +             (void) printf("%scksum: %s: %s\n", tab, fts_accpath, 
Fstrerror(fd));
  +#else
  +             mtree_error("%s: %s", fts_accpath, Fstrerror(fd));
  +             /[EMAIL PROTECTED]@*/
  +#endif
  +             goto cleanup;
  +         }
  +
  +         /* Output cksum. */
  +         if (KF_ISSET(keys, CKSUM)) {
  +             output(indent, &offset, "cksum=%lu", (unsigned long)val);
  +         }
  +
  +         /* Output all the digests. */
  +         if (algos != NULL)
  +         for (i = 0; i < (int) algos->nvals; i++) {
  +             static int asAscii = 1;
  +             uint32_t algo = algos->vals[i];
  +             const char * digest = NULL;
  +             size_t digestlen = 0;
  +             const char * tagname;
  +
  +             fdFiniDigest(fd, algo, &digest, &digestlen, asAscii);
  +#ifdef       NOTYET  /* XXX can't exit in a library API. */
  +assert(digest != NULL);
  +#else
  +             if (digest == NULL)
  +                 mtree_error("%s: %s", fts_accpath, Fstrerror(fd));
  +#endif
  +             tagname = NULL;
  +             switch (algo) {
  +             case PGPHASHALGO_MD5:
  +                 tagname = "md5";    /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_SHA1:
  +                 tagname = "sha1";   /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_RIPEMD160:
  +                 tagname = "rmd160"; /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_MD2:
  +                 tagname = "md2";    /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_TIGER192:
  +                 tagname = "tiger192";       /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_HAVAL_5_160:
  +                 tagname = "haval";  /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_SHA256:
  +                 tagname = "sha256"; /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_SHA384:
  +                 tagname = "sha384"; /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_SHA512:
  +                 tagname = "sha512"; /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_MD4:
  +                 tagname = "md4";    /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_RIPEMD128:
  +                 tagname = "rmd128"; /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_CRC32:
  +                 /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_ADLER32:
  +                 /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_CRC64:
  +                 /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_JLU32:
  +                 /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_SHA224:
  +                 tagname = "sha224"; /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_RIPEMD256:
  +                 tagname = "rmd256"; /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_RIPEMD320:
  +                 tagname = "rmd320"; /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_SALSA10:
  +                 /[EMAIL PROTECTED]@*/ break;
  +             case PGPHASHALGO_SALSA20:
  +                 /[EMAIL PROTECTED]@*/ break;
  +             default:
  +                 /[EMAIL PROTECTED]@*/ break;
  +             }
  +             if (tagname != NULL)
  +                 output(indent, &offset, "%sdigest=%s", tagname, digest);
  +             digest = _free(digest);
  +             digestlen = 0;
  +         }
  +
  +     /* Accumulate statistics and clean up. */
  +cleanup:
  +         if (fd != NULL) {
  +             (void) rpmswAdd(&dc_readops, fdstat_op(fd, FDSTAT_READ));
  +             (void) rpmswAdd(&dc_digestops, fdstat_op(fd, FDSTAT_DIGEST));
  +             (void) Fclose(fd);
  +             fd = NULL;
  +         }
        }
  -     dc->algo = 0;
  -     dc->fn = NULL;
       }
  -/[EMAIL PROTECTED]@*/
  +
       if (KF_ISSET(keys, SLINK) && (fts_info == FTS_SL || fts_info == 
FTS_SLNONE))
       {
        const char * name = rlink(fts_accpath);
  -     escaped_name = xmalloc(strlen(name) * 4  +  1);
  -     (void) strvis(escaped_name, name, VIS_WHITE | VIS_OCTAL);
  -     output(indent, &offset, "link=%s", escaped_name);
  -     escaped_name = _free(escaped_name);
  +     char * escname = xmalloc(strlen(name) * 4  +  1);
  +     (void) strvis(escname, name, VIS_WHITE | VIS_OCTAL);
  +     output(indent, &offset, "link=%s", escname);
  +     escname = _free(escname);
       }
  +
       if (KF_ISSET(keys, FLAGS) && !S_ISLNK(st->st_mode)) {
   #if defined(__linux__)
        output(indent, &offset, "flags=none");
  @@ -2655,6 +2482,18 @@
       return 0;
   }
   
  +static int
  +dsort(const FTSENT ** a, const FTSENT ** b)
  +     /[EMAIL PROTECTED]/
  +{
  +    if (S_ISDIR((*a)->fts_statp->st_mode)) {
  +     if (!S_ISDIR((*b)->fts_statp->st_mode))
  +         return 1;
  +    } else if (S_ISDIR((*b)->fts_statp->st_mode))
  +     return -1;
  +    return strcmp((*a)->fts_name, (*b)->fts_name);
  +}
  +
   int
   mtreeCWalk(rpmfts fts)
   {
  @@ -2814,7 +2653,7 @@
                {
                    ep->flags |= MTREE_KEYS_VISIT;
                    if (!KF_ISSET(ep->flags, NOCHANGE) &&
  -                     compare(ep->name, ep, fts->p))
  +                     compare(fts, ep))
                            rval = MISMATCHEXIT;
                    if (KF_ISSET(ep->flags, IGN))
                            (void) Fts_set(fts->t, fts->p, FTS_SKIP);
  @@ -2866,24 +2705,21 @@
       if (opt->arg == NULL)
       switch (opt->val) {
   
  -    /* XXX TODO: Mac OS X differs here. */
       case 'f':
  +     /* XXX TODO: Mac OS X differs here. */
        if (!(freopen(arg, "r", stdin)))
            mtree_error("%s: %s", arg, strerror(errno));
        break;
  +    case 'k':
  +     /* XXX fts->keys = KEYDEFAULT in main(), clear default now. */
  +     _rpmfts->keys = MTREE_KEYS_TYPE;
  +     /[EMAIL PROTECTED]@*/
       case 'K':
   /[EMAIL PROTECTED]@*/
        while ((p = strsep((char **)&arg, " \t,")) != NULL)
  -         if (*p != '\0')
  -             _rpmfts->keys |= parsekey(p, NULL);
  +         _rpmfts->keys |= parsekey(p, NULL);
   /[EMAIL PROTECTED]@*/
        break;
  -    case 'k':
  -     _rpmfts->keys = MTREE_KEYS_TYPE;
  -     while ((p = strsep((char **)&arg, " \t,")) != NULL)
  -         if (*p != '\0')
  -             _rpmfts->keys |= parsekey(p, NULL);
  -     break;
   #if !defined(POPT_ARG_ARGV)
       case 'p':
   assert(arg != NULL);
  @@ -3037,26 +2873,17 @@
                fileSystem, internalState @*/
   {
       rpmfts fts = _rpmfts;
  -    poptContext optCon = rpmioInit(argc, argv, optionsTable);
  +    poptContext optCon;
       int rc;
   
       LIST_INIT(&excludes);
       fts->keys = KEYDEFAULT;
       fts->fflags = 0xffffffff;
   
  -    /* Process all options, whine if unknown. */
  -    while ((rc = poptGetNextOpt(optCon)) > 0) {
  -        const char * optArg = poptGetOptArg(optCon);
  -/[EMAIL PROTECTED] -modobserver -observertrans @*/
  -     optArg = _free(optArg);
  -/[EMAIL PROTECTED] =modobserver =observertrans @*/
  -        switch (rc) {
  -        default:
  -         mtree_error("Option table misconfigured");
  -            /[EMAIL PROTECTED]@*/ /[EMAIL PROTECTED]@*/ break;
  -        }
  -    }
  +    /* Process options. */
  +    optCon = rpmioInit(argc, argv, optionsTable);
   
  +    /* XXX ./rpmmtree w no args waits for stdin. poptPrintUsage more better. 
*/
       argv = (char **) poptGetArgs(optCon);
       if (!(argv == NULL || argv[0] == NULL)) {
        poptPrintUsage(optCon, stderr, 0);
  @@ .
______________________________________________________________________
RPM Package Manager                                    http://rpm5.org
CVS Sources Repository                                rpm-cvs@rpm5.org

Reply via email to