- 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 }