rpm 5.2.1

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