• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

rpmdb/legacy.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 #if defined(HAVE_GELF_H)
00008 #if LIBELF_H_LFS_CONFLICT
00009 /* some gelf.h/libelf.h implementations (Solaris) are
00010  * incompatible with the Large File API
00011  */
00012 # undef _LARGEFILE64_SOURCE
00013 # undef _LARGEFILE_SOURCE
00014 # undef _FILE_OFFSET_BITS
00015 # define _FILE_OFFSET_BITS 32
00016 #endif
00017 #include <gelf.h>
00018 
00019 #if !defined(DT_GNU_PRELINKED)
00020 #define DT_GNU_PRELINKED        0x6ffffdf5
00021 #endif
00022 #if !defined(DT_GNU_LIBLIST)
00023 #define DT_GNU_LIBLIST          0x6ffffef9
00024 #endif
00025 
00026 #endif
00027 
00028 #include "rpmio_internal.h"
00029 #include <rpmlib.h>     /* XXX rpmMkdirPath */
00030 #include <rpmmacro.h>
00031 #include "misc.h"
00032 #include "legacy.h"
00033 #include "debug.h"
00034 
00035 #define alloca_strdup(_s)       strcpy(alloca(strlen(_s)+1), (_s))
00036 
00044 /*@-compdef -moduncon -noeffectuncon @*/
00045 static int open_dso(const char * path, /*@null@*/ pid_t * pidp, /*@null@*/ size_t *fsizep)
00046         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00047         /*@modifies *pidp, *fsizep, rpmGlobalMacroContext,
00048                 fileSystem, internalState @*/
00049 {
00050 /*@only@*/
00051     static const char * cmd = NULL;
00052     static int oneshot = 0;
00053     int fdno;
00054 
00055     if (!oneshot) {
00056         cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
00057         oneshot++;
00058     }
00059 
00060     if (pidp) *pidp = 0;
00061 
00062     if (fsizep) {
00063         struct stat sb, * st = &sb;
00064         if (stat(path, st) < 0)
00065             return -1;
00066         *fsizep = st->st_size;
00067     }
00068 
00069     fdno = open(path, O_RDONLY);
00070     if (fdno < 0)
00071         return fdno;
00072 
00073     if (!(cmd && *cmd))
00074         return fdno;
00075 
00076 #if defined(HAVE_GELF_H) && defined(HAVE_LIBELF)
00077  {  Elf *elf = NULL;
00078     Elf_Scn *scn = NULL;
00079     Elf_Data *data = NULL;
00080     GElf_Ehdr ehdr;
00081     GElf_Shdr shdr;
00082     GElf_Dyn dyn;
00083     int bingo;
00084 
00085     (void) elf_version(EV_CURRENT);
00086 
00087 /*@-evalorder@*/
00088     if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
00089      || elf_kind(elf) != ELF_K_ELF
00090      || gelf_getehdr(elf, &ehdr) == NULL
00091      || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
00092         goto exit;
00093 /*@=evalorder@*/
00094 
00095     bingo = 0;
00096     while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) {
00097         (void) gelf_getshdr(scn, &shdr);
00098         if (shdr.sh_type != SHT_DYNAMIC)
00099             continue;
00100         while (!bingo && (data = elf_getdata (scn, data)) != NULL) {
00101             unsigned maxndx = (unsigned) (data->d_size / shdr.sh_entsize);
00102             unsigned ndx;
00103 
00104             for (ndx = 0; ndx < maxndx; ++ndx) {
00105 /*@-uniondef@*/
00106                 (void) gelf_getdyn (data, ndx, &dyn);
00107 /*@=uniondef@*/
00108                 if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
00109                     /*@innercontinue@*/ continue;
00110                 bingo = 1;
00111                 /*@innerbreak@*/ break;
00112             }
00113         }
00114     }
00115 
00116     if (pidp != NULL && bingo) {
00117         int pipes[2];
00118         pid_t pid;
00119         int xx;
00120 
00121         xx = close(fdno);
00122         pipes[0] = pipes[1] = -1;
00123         xx = pipe(pipes);
00124         if (!(pid = fork())) {
00125             const char ** av;
00126             int ac;
00127             xx = close(pipes[0]);
00128             xx = dup2(pipes[1], STDOUT_FILENO);
00129             xx = close(pipes[1]);
00130             if (!poptParseArgvString(cmd, &ac, &av)) {
00131                 av[ac-1] = path;
00132                 av[ac] = NULL;
00133                 unsetenv("MALLOC_CHECK_");
00134                 xx = execve(av[0], (char *const *)av+1, environ);
00135             }
00136             _exit(127);
00137         }
00138         *pidp = pid;
00139         fdno = pipes[0];
00140         xx = close(pipes[1]);
00141     }
00142 
00143 exit:
00144     if (elf) (void) elf_end(elf);
00145  }
00146 #endif
00147 
00148     return fdno;
00149 }
00150 /*@=compdef =moduncon =noeffectuncon @*/
00151 
00152 int dodigest(int digestalgo, const char * fn, unsigned char * digest, int asAscii, size_t *fsizep)
00153 {
00154     const char * path;
00155     urltype ut = urlPath(fn, &path);
00156     unsigned char * dsum = NULL;
00157     size_t dlen;
00158     unsigned char buf[32*BUFSIZ];
00159     FD_t fd;
00160     size_t fsize = 0;
00161     pid_t pid = 0;
00162     int use_mmap;
00163     int rc = 0;
00164     int fdno;
00165 #if defined(HAVE_MMAP)
00166     int xx;
00167 #endif
00168 
00169 /*@-globs -internalglobs -mods @*/
00170     fdno = open_dso(path, &pid, &fsize);
00171 /*@=globs =internalglobs =mods @*/
00172     if (fdno < 0) {
00173         rc = 1;
00174         goto exit;
00175     }
00176 
00177     /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_SEQUENTIAL better. */
00178     use_mmap = (pid == 0 && fsize <= 0x07ffffff);
00179 
00180     switch(ut) {
00181     case URL_IS_PATH:
00182     case URL_IS_UNKNOWN:
00183 #if defined(HAVE_MMAP)
00184       if (use_mmap) {
00185         DIGEST_CTX ctx;
00186         void * mapped = NULL;
00187 
00188         if (fsize) {
00189             mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0);
00190             if (mapped == (void *)-1) {
00191                 xx = close(fdno);
00192                 rc = 1;
00193                 break;
00194             }
00195 
00196 #if defined(HAVE_MADVISE) && defined(MADV_SEQUENTIAL)
00197             xx = madvise(mapped, fsize, MADV_SEQUENTIAL);
00198 #endif
00199         }
00200 
00201         ctx = rpmDigestInit(digestalgo, RPMDIGEST_NONE);
00202         if (fsize)
00203             xx = rpmDigestUpdate(ctx, mapped, fsize);
00204         xx = rpmDigestFinal(ctx, &dsum, &dlen, asAscii);
00205         if (fsize)
00206             xx = munmap(mapped, fsize);
00207         xx = close(fdno);
00208         break;
00209       } /*@fallthrough@*/
00210 #endif
00211     case URL_IS_HTTPS:
00212     case URL_IS_HTTP:
00213     case URL_IS_FTP:
00214     case URL_IS_HKP:
00215     case URL_IS_DASH:
00216     default:
00217         /* Either use the pipe to prelink -y or open the URL. */
00218         fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.fdio");
00219         (void) close(fdno);
00220         if (fd == NULL || Ferror(fd)) {
00221             rc = 1;
00222             if (fd != NULL)
00223                 (void) Fclose(fd);
00224             break;
00225         }
00226         
00227         fdInitDigest(fd, digestalgo, 0);
00228         fsize = 0;
00229         while ((rc = (int) Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00230             fsize += rc;
00231         fdFiniDigest(fd, digestalgo, &dsum, &dlen, asAscii);
00232         if (Ferror(fd))
00233             rc = 1;
00234 
00235         (void) Fclose(fd);
00236         break;
00237     }
00238 
00239     /* Reap the prelink -y helper. */
00240     if (pid) {
00241         int status;
00242         (void) waitpid(pid, &status, 0);
00243         if (!WIFEXITED(status) || WEXITSTATUS(status))
00244             rc = 1;
00245     }
00246 
00247 exit:
00248     if (fsizep)
00249         *fsizep = fsize;
00250     if (!rc)
00251         memcpy(digest, dsum, dlen);
00252     dsum = _free(dsum);
00253 
00254     return rc;
00255 }
00256 
00257 int domd5(const char * fn, unsigned char * digest, int asAscii, size_t *fsizep)
00258 {
00259     return dodigest(PGPHASHALGO_MD5, fn, digest, asAscii, fsizep);
00260 }

Generated on Mon Nov 29 2010 05:18:46 for rpm by  doxygen 1.7.2