Calculating file checksums aint legacy activity
authorPanu Matilainen <pmatilai@redhat.com>
Thu, 22 Nov 2007 14:06:11 +0000 (16:06 +0200)
committerPanu Matilainen <pmatilai@redhat.com>
Thu, 22 Nov 2007 14:06:11 +0000 (16:06 +0200)
- move the checksumming into librpmio
- rename domd5() to rpmDoDigest() with future expansion for specifying
  digest algorithm type (ignored for now)
- rearrange parameters to leave return types last
- one less rpmio_internal outside rpmio/, whee...
- used all over the rpm tree, and it knows about handling prelinked files
  so potentially useful for outside users, might as well export it
- new public header rpmfilutil.h for collecting this sort of stuff

12 files changed:
Makefile.am
build/files.c
lib/formats.c
lib/rpmfi.c
lib/signature.c
lib/transaction.c
lib/verify.c
rpmdb/legacy.c
rpmdb/legacy.h
rpmio/Makefile.am
rpmio/rpmfileutil.c [new file with mode: 0644]
rpmio/rpmfileutil.h [new file with mode: 0644]

index 55de0c7..9cc5dbb 100644 (file)
@@ -48,6 +48,7 @@ pkginclude_HEADERS += rpmio/rpmpgp.h
 pkginclude_HEADERS += rpmio/rpmsq.h
 pkginclude_HEADERS += rpmio/rpmstring.h
 pkginclude_HEADERS += rpmio/rpmsw.h
+pkginclude_HEADERS += rpmio/rpmfileutil.h
 
 pkginclude_HEADERS += rpmdb/header.h
 pkginclude_HEADERS += rpmdb/rpmdb.h
index 6f944ec..a197acc 100644 (file)
@@ -29,7 +29,8 @@
 
 #include "buildio.h"
 
-#include "legacy.h"    /* XXX domd5, expandFileList, compressFileList */
+#include <rpmfileutil.h>       /* rpmDoDigest() */
+#include "legacy.h"    /* XXX expandFileList, compressFileList */
 #include <rpmlog.h>
 #include "debug.h"
 
@@ -1195,7 +1196,8 @@ static void genCpioListAndHeader(FileList fl,
        
        buf[0] = '\0';
        if (S_ISREG(flp->fl_mode))
-           (void) domd5(flp->diskURL, (unsigned char *)buf, 1, NULL);
+           (void) rpmDoDigest(PGPHASHALGO_MD5, flp->diskURL, 1, 
+                              (unsigned char *)buf, NULL);
        s = buf;
        (void) headerAddOrAppendEntry(h, RPMTAG_FILEMD5S, RPM_STRING_ARRAY_TYPE,
                               &s, 1);
index d18a5fa..8d32828 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <rpmfi.h>
 
-#include "legacy.h"
+#include "legacy.h"    /* XXX rpmfiBuildFNames() */
 #include "manifest.h"
 
 #include "debug.h"
index d38b4d3..42cee3c 100644 (file)
@@ -19,7 +19,7 @@
 #include <rpmte.h>
 #include <rpmts.h>
 
-#include "legacy.h"     /* XXX domd5 */
+#include <rpmfileutil.h>/* XXX domd5 */
 #include <rpmstring.h>
 #include <rpmmacro.h>  /* XXX rpmCleanPath */
 
@@ -523,7 +523,8 @@ rpmFileAction rpmfiDecideFate(const rpmfi ofi, rpmfi nfi, int skipMissing)
        const unsigned char * omd5, * nmd5;
        omd5 = rpmfiMD5(ofi);
        if (diskWhat == REG) {
-           if (domd5(fn, (unsigned char *)buffer, 0, NULL))
+           if (rpmDoDigest(PGPHASHALGO_MD5, fn, 0, 
+               (unsigned char *)buffer, NULL))
                return FA_CREATE;       /* assume file has been removed */
            if (omd5 && !memcmp(omd5, buffer, 16))
                return FA_CREATE;       /* unmodified config file, replace. */
@@ -578,7 +579,7 @@ int rpmfiConfigConflict(const rpmfi fi)
     memset(buffer, 0, sizeof(buffer));
     if (newWhat == REG) {
        const unsigned char * nmd5;
-       if (domd5(fn, (unsigned char *)buffer, 0, NULL))
+       if (rpmDoDigest(PGPHASHALGO_MD5, fn, 0, (unsigned char *)buffer, NULL))
            return 0;   /* assume file has been removed */
        nmd5 = rpmfiMD5(fi);
        if (nmd5 && !memcmp(nmd5, buffer, 16))
index 3cee85a..7d58c1e 100644 (file)
@@ -14,7 +14,7 @@
 
 #include <rpmlog.h>
 #include "misc.h"      /* XXX for dosetenv() and makeTempFile() */
-#include "legacy.h"    /* XXX for mdbinfile() */
+#include "rpmfileutil.h"
 #include "rpmlead.h"
 #include "signature.h"
 #include "header_internal.h"
@@ -733,7 +733,7 @@ int rpmAddSignature(Header sigh, const char * file, int32_t sigTag,
     case RPMSIGTAG_MD5:
        pktlen = 16;
        pkt = memset(alloca(pktlen), 0, pktlen);
-       if (domd5(file, pkt, 0, NULL)
+       if (rpmDoDigest(PGPHASHALGO_MD5, file, 0, pkt, NULL)
         || !headerAddEntry(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
            break;
        ret = 0;
index be028b8..e71a69d 100644 (file)
@@ -27,9 +27,9 @@
 
 #include "cpio.h"
 #include "fprint.h"
-#include "legacy.h"    /* XXX domd5 */
+#include <rpmfileutil.h>
 #include <rpmstring.h>
-#include "misc.h"      /* currentDirectory */
+#include "misc.h"              /* currentDirectory */
 
 #include "debug.h"
 
@@ -574,7 +574,8 @@ assert(otherFi != NULL);
            /* Here is a pre-existing modified config file that needs saving. */
            {   unsigned char md5sum[50];
                const unsigned char * MD5 = rpmfiMD5(fi);
-               if (!domd5(fn, md5sum, 0, NULL) && memcmp(MD5, md5sum, 16)) {
+               if (!rpmDoDigest(PGPHASHALGO_MD5, fn, 0, md5sum, NULL) &&
+                   memcmp(MD5, md5sum, 16)) {
                    fi->actions[i] = FA_BACKUP;
                    break;
                }
index 08c1a73..d73cd61 100644 (file)
@@ -11,7 +11,7 @@
 #include <rpmfi.h>
 #include <rpmts.h>
 
-#include "legacy.h"    /* XXX domd5() */
+#include "rpmfileutil.h"
 #include "ugid.h"      /* uidToUname(), gnameToGid */
 #include "debug.h"
 
@@ -113,7 +113,7 @@ int rpmVerifyFile(const rpmts ts, const rpmfi fi,
        size_t fsize;
 
        /* XXX If --nomd5, then prelinked library sizes are not corrected. */
-       rc = domd5(fn, md5sum, 0, &fsize);
+       rc = rpmDoDigest(PGPHASHALGO_MD5, fn, 0, md5sum, &fsize);
        sb.st_size = fsize;
        if (rc)
            *res |= (RPMVERIFY_READFAIL|RPMVERIFY_MD5);
index 0be71e2..8b7fb3a 100644 (file)
@@ -4,21 +4,6 @@
 
 #include "system.h"
 
-#if HAVE_GELF_H
-
-#include <gelf.h>
-
-#if !defined(DT_GNU_PRELINKED)
-#define        DT_GNU_PRELINKED        0x6ffffdf5
-#endif
-#if !defined(DT_GNU_LIBLIST)
-#define        DT_GNU_LIBLIST          0x6ffffef9
-#endif
-
-#endif
-
-#include <rpmurl.h>
-#include "rpmio_internal.h"    /* XXX fdInitDigest, fdFiniDigest */
 #include <rpmlib.h>
 #include <rpmmacro.h>
 #include <rpmstring.h>
  * @retval fsizep      file size
  * @return             -1 on error, otherwise, an open file descriptor
  */ 
-static int open_dso(const char * path, pid_t * pidp, size_t *fsizep)
-{
-    static const char * cmd = NULL;
-    static int initted = 0;
-    int fdno;
-
-    if (!initted) {
-       cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
-       initted++;
-    }
-
-    if (pidp) *pidp = 0;
-
-    if (fsizep) {
-       struct stat sb, * st = &sb;
-       if (stat(path, st) < 0)
-           return -1;
-       *fsizep = st->st_size;
-    }
-
-    fdno = open(path, O_RDONLY);
-    if (fdno < 0)
-       return fdno;
-
-    if (!(cmd && *cmd))
-       return fdno;
-
-#if HAVE_GELF_H && HAVE_LIBELF
- {  Elf *elf = NULL;
-    Elf_Scn *scn = NULL;
-    Elf_Data *data = NULL;
-    GElf_Ehdr ehdr;
-    GElf_Shdr shdr;
-    GElf_Dyn dyn;
-    int bingo;
-
-    (void) elf_version(EV_CURRENT);
-
-    if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
-     || elf_kind(elf) != ELF_K_ELF
-     || gelf_getehdr(elf, &ehdr) == NULL
-     || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
-       goto exit;
-
-    bingo = 0;
-    while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) {
-       (void) gelf_getshdr(scn, &shdr);
-       if (shdr.sh_type != SHT_DYNAMIC)
-           continue;
-       while (!bingo && (data = elf_getdata (scn, data)) != NULL) {
-           int maxndx = data->d_size / shdr.sh_entsize;
-           int ndx;
-
-            for (ndx = 0; ndx < maxndx; ++ndx) {
-               (void) gelf_getdyn (data, ndx, &dyn);
-               if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
-                   continue;
-               bingo = 1;
-               break;
-           }
-       }
-    }
-
-    if (pidp != NULL && bingo) {
-       int pipes[2];
-       pid_t pid;
-       int xx;
-
-       xx = close(fdno);
-       pipes[0] = pipes[1] = -1;
-       xx = pipe(pipes);
-       if (!(pid = fork())) {
-           const char ** av;
-           int ac;
-           xx = close(pipes[0]);
-           xx = dup2(pipes[1], STDOUT_FILENO);
-           xx = close(pipes[1]);
-           if (!poptParseArgvString(cmd, &ac, &av)) {
-               av[ac-1] = path;
-               av[ac] = NULL;
-               unsetenv("MALLOC_CHECK_");
-               xx = execve(av[0], (char *const *)av+1, environ);
-           }
-           _exit(127);
-       }
-       *pidp = pid;
-       fdno = pipes[0];
-       xx = close(pipes[1]);
-    }
-
-exit:
-    if (elf) (void) elf_end(elf);
- }
-#endif
-
-    return fdno;
-}
-
-int domd5(const char * fn, unsigned char * digest, int asAscii, size_t *fsizep)
-{
-    const char * path;
-    urltype ut = urlPath(fn, &path);
-    unsigned char * md5sum = NULL;
-    size_t md5len;
-    unsigned char buf[32*BUFSIZ];
-    FD_t fd;
-    size_t fsize = 0;
-    pid_t pid = 0;
-    int rc = 0;
-    int fdno;
-
-    fdno = open_dso(path, &pid, &fsize);
-    if (fdno < 0) {
-       rc = 1;
-       goto exit;
-    }
-
-    /* file to large (32 MB), do not mmap file */
-    if (fsize > (size_t) 32*1024*1024)
-      if (ut == URL_IS_PATH || ut == URL_IS_UNKNOWN)
-       ut = URL_IS_DASH; /* force fd io */
-
-    switch(ut) {
-    case URL_IS_PATH:
-    case URL_IS_UNKNOWN:
-#ifdef HAVE_MMAP
-      if (pid == 0) {
-       DIGEST_CTX ctx;
-       void * mapped;
-
-       if (fsize) {
-           mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0);
-           if (mapped == (void *)-1) {
-               xx = close(fdno);
-               rc = 1;
-               break;
-           }
-
-#ifdef MADV_SEQUENTIAL
-           xx = madvise(mapped, fsize, MADV_SEQUENTIAL);
-#endif
-       }
-
-       ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
-       if (fsize)
-           xx = rpmDigestUpdate(ctx, mapped, fsize);
-       xx = rpmDigestFinal(ctx, (void **)&md5sum, &md5len, asAscii);
-       if (fsize)
-           xx = munmap(mapped, fsize);
-       xx = close(fdno);
-       break;
-      }
-#endif
-    case URL_IS_HTTPS:
-    case URL_IS_HTTP:
-    case URL_IS_FTP:
-    case URL_IS_HKP:
-    case URL_IS_DASH:
-    default:
-       /* Either use the pipe to prelink -y or open the URL. */
-       fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.ufdio");
-       (void) close(fdno);
-       if (fd == NULL || Ferror(fd)) {
-           rc = 1;
-           if (fd != NULL)
-               (void) Fclose(fd);
-           break;
-       }
-       
-       fdInitDigest(fd, PGPHASHALGO_MD5, 0);
-       fsize = 0;
-       while ((rc = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
-           fsize += rc;
-       fdFiniDigest(fd, PGPHASHALGO_MD5, (void **)&md5sum, &md5len, asAscii);
-       if (Ferror(fd))
-           rc = 1;
-
-       (void) Fclose(fd);
-       break;
-    }
-
-    /* Reap the prelink -y helper. */
-    if (pid) {
-       int status;
-       (void) waitpid(pid, &status, 0);
-       if (!WIFEXITED(status) || WEXITSTATUS(status))
-           rc = 1;
-    }
-
-exit:
-    if (fsizep)
-       *fsizep = fsize;
-    if (!rc)
-       memcpy(digest, md5sum, md5len);
-    md5sum = _free(md5sum);
-
-    return rc;
-}
-
 int _noDirTokens = 0;
 
 static int dncmp(const void * a, const void * b)
index aa44696..fcec32b 100644 (file)
@@ -15,17 +15,6 @@ extern "C" {
 #endif
 
 /**
- * Return MD5 sum and size of a file.
- * @param fn           file name
- * @retval digest      address of md5sum
- * @param asAscii      return md5sum as ascii string?
- * @retval *fsizep     file size pointer (or NULL)
- * @return             0 on success, 1 on error
- */
-int domd5(const char * fn, unsigned char * digest, int asAscii,
-               size_t *fsizep);
-
-/**
  * Convert absolute path tag to (dirname,basename,dirindex) tags.
  * @param h            header
  */
index 0149100..0510be0 100644 (file)
@@ -15,7 +15,7 @@ librpmio_la_SOURCES = \
        rpmhook.c rpmio.c rpmlog.c rpmlua.c rpmmalloc.c \
        rpmpgp.c rpmrpc.c rpmsq.c rpmsw.c strcasecmp.c url.c ugid.c \
        rpmio_internal.h rpmlua.h rpmhook.h ugid.h fts.h \
-       rpmstring.c 
+       rpmstring.c rpmfileutil.c
 
 librpmio_la_LDFLAGS = -release 4.4
 librpmio_la_LIBADD = \
diff --git a/rpmio/rpmfileutil.c b/rpmio/rpmfileutil.c
new file mode 100644 (file)
index 0000000..e79a65a
--- /dev/null
@@ -0,0 +1,221 @@
+#include "system.h"
+
+#if HAVE_GELF_H
+
+#include <gelf.h>
+
+#if !defined(DT_GNU_PRELINKED)
+#define DT_GNU_PRELINKED        0x6ffffdf5
+#endif
+#if !defined(DT_GNU_LIBLIST)
+#define DT_GNU_LIBLIST          0x6ffffef9
+#endif
+
+#endif
+
+#include "rpmio_internal.h"
+#include <rpmfileutil.h>
+#include <rpmurl.h>
+#include <rpmmacro.h>
+#include <argv.h>
+
+static int open_dso(const char * path, pid_t * pidp, size_t *fsizep)
+{
+    static const char * cmd = NULL;
+    static int initted = 0;
+    int fdno;
+
+    if (!initted) {
+       cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
+       initted++;
+    }
+
+    if (pidp) *pidp = 0;
+
+    if (fsizep) {
+       struct stat sb, * st = &sb;
+       if (stat(path, st) < 0)
+           return -1;
+       *fsizep = st->st_size;
+    }
+
+    fdno = open(path, O_RDONLY);
+    if (fdno < 0)
+       return fdno;
+
+    if (!(cmd && *cmd))
+       return fdno;
+
+#if HAVE_GELF_H && HAVE_LIBELF
+ {  Elf *elf = NULL;
+    Elf_Scn *scn = NULL;
+    Elf_Data *data = NULL;
+    GElf_Ehdr ehdr;
+    GElf_Shdr shdr;
+    GElf_Dyn dyn;
+    int bingo;
+
+    (void) elf_version(EV_CURRENT);
+
+    if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
+     || elf_kind(elf) != ELF_K_ELF
+     || gelf_getehdr(elf, &ehdr) == NULL
+     || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
+       goto exit;
+
+    bingo = 0;
+    while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) {
+       (void) gelf_getshdr(scn, &shdr);
+       if (shdr.sh_type != SHT_DYNAMIC)
+           continue;
+       while (!bingo && (data = elf_getdata (scn, data)) != NULL) {
+           int maxndx = data->d_size / shdr.sh_entsize;
+           int ndx;
+
+            for (ndx = 0; ndx < maxndx; ++ndx) {
+               (void) gelf_getdyn (data, ndx, &dyn);
+               if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
+                   continue;
+               bingo = 1;
+               break;
+           }
+       }
+    }
+
+    if (pidp != NULL && bingo) {
+       int pipes[2];
+       pid_t pid;
+       int xx;
+
+       xx = close(fdno);
+       pipes[0] = pipes[1] = -1;
+       xx = pipe(pipes);
+       if (!(pid = fork())) {
+           ARGV_t av, lib;
+           argvSplit(&av, cmd, " ");
+
+           xx = close(pipes[0]);
+           xx = dup2(pipes[1], STDOUT_FILENO);
+           xx = close(pipes[1]);
+           if ((lib = argvSearch(av, "library", NULL)) != NULL) {
+               *lib = path;
+               unsetenv("MALLOC_CHECK_");
+               xx = execve(av[0], (char *const *)av+1, environ);
+           }
+           _exit(127);
+       }
+       *pidp = pid;
+       fdno = pipes[0];
+       xx = close(pipes[1]);
+    }
+
+exit:
+    if (elf) (void) elf_end(elf);
+ }
+#endif
+
+    return fdno;
+}
+
+int rpmDoDigest(pgpHashAlgo algo, const char * fn,int asAscii,
+                unsigned char * digest, size_t * fsizep)
+{
+    const char * path;
+    urltype ut = urlPath(fn, &path);
+    unsigned char * md5sum = NULL;
+    size_t md5len;
+    unsigned char buf[32*BUFSIZ];
+    FD_t fd;
+    size_t fsize = 0;
+    pid_t pid = 0;
+    int rc = 0;
+    int fdno;
+
+    fdno = open_dso(path, &pid, &fsize);
+    if (fdno < 0) {
+       rc = 1;
+       goto exit;
+    }
+
+    /* file to large (32 MB), do not mmap file */
+    if (fsize > (size_t) 32*1024*1024)
+      if (ut == URL_IS_PATH || ut == URL_IS_UNKNOWN)
+       ut = URL_IS_DASH; /* force fd io */
+
+    switch(ut) {
+    case URL_IS_PATH:
+    case URL_IS_UNKNOWN:
+#ifdef HAVE_MMAP
+      if (pid == 0) {
+       DIGEST_CTX ctx;
+       void * mapped;
+
+       if (fsize) {
+           mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0);
+           if (mapped == (void *)-1) {
+               xx = close(fdno);
+               rc = 1;
+               break;
+           }
+
+#ifdef MADV_SEQUENTIAL
+           xx = madvise(mapped, fsize, MADV_SEQUENTIAL);
+#endif
+       }
+
+       ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
+       if (fsize)
+           xx = rpmDigestUpdate(ctx, mapped, fsize);
+       xx = rpmDigestFinal(ctx, (void **)&md5sum, &md5len, asAscii);
+       if (fsize)
+           xx = munmap(mapped, fsize);
+       xx = close(fdno);
+       break;
+      }
+#endif
+    case URL_IS_HTTPS:
+    case URL_IS_HTTP:
+    case URL_IS_FTP:
+    case URL_IS_HKP:
+    case URL_IS_DASH:
+    default:
+       /* Either use the pipe to prelink -y or open the URL. */
+       fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.ufdio");
+       (void) close(fdno);
+       if (fd == NULL || Ferror(fd)) {
+           rc = 1;
+           if (fd != NULL)
+               (void) Fclose(fd);
+           break;
+       }
+       
+       fdInitDigest(fd, PGPHASHALGO_MD5, 0);
+       fsize = 0;
+       while ((rc = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
+           fsize += rc;
+       fdFiniDigest(fd, PGPHASHALGO_MD5, (void **)&md5sum, &md5len, asAscii);
+       if (Ferror(fd))
+           rc = 1;
+
+       (void) Fclose(fd);
+       break;
+    }
+
+    /* Reap the prelink -y helper. */
+    if (pid) {
+       int status;
+       (void) waitpid(pid, &status, 0);
+       if (!WIFEXITED(status) || WEXITSTATUS(status))
+           rc = 1;
+    }
+
+exit:
+    if (fsizep)
+       *fsizep = fsize;
+    if (!rc)
+       memcpy(digest, md5sum, md5len);
+    md5sum = _free(md5sum);
+
+    return rc;
+}
+
diff --git a/rpmio/rpmfileutil.h b/rpmio/rpmfileutil.h
new file mode 100644 (file)
index 0000000..b2f72f5
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _RPMFILEUTIL_H
+#define _RPMFILEUTIL_H
+
+#include <rpmpgp.h>
+
+/**
+ * Calculate a file digest and size.
+ * @param algo         digest algorithm (ignored for now, md5 used)
+ * @param fn           file name
+ * @param asAscii      return checksum as ascii string?
+ * @retval digest      address of calculated checksum
+ * @retval *fsizep     file size pointer (or NULL)
+ * @return             0 on success, 1 on error
+ */
+int rpmDoDigest(pgpHashAlgo algo, const char * fn,int asAscii,
+                 unsigned char * digest, size_t * fsizep);
+
+#endif /* _RPMFILEUTIL_H */