Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

rpmdb/legacy.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 
00007 #if 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>
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 static int open_dso(const char * path, /*@null@*/ pid_t * pidp, /*@null@*/ size_t *fsizep)
00045         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00046         /*@modifies *pidp, *fsizep, rpmGlobalMacroContext,
00047                 fileSystem, internalState @*/
00048 {
00049 /*@only@*/
00050     static const char * cmd = NULL;
00051     static int initted = 0;
00052     int fdno;
00053 
00054     if (!initted) {
00055         cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
00056         initted++;
00057     }
00058 
00059 /*@-boundswrite@*/
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 /*@=boundswrite@*/
00069 
00070     fdno = open(path, O_RDONLY);
00071     if (fdno < 0)
00072         return fdno;
00073 
00074 /*@-boundsread@*/
00075     if (!(cmd && *cmd))
00076         return fdno;
00077 /*@=boundsread@*/
00078 
00079 #if HAVE_GELF_H && HAVE_LIBELF
00080  {  Elf *elf = NULL;
00081     Elf_Scn *scn = NULL;
00082     Elf_Data *data = NULL;
00083     GElf_Ehdr ehdr;
00084     GElf_Shdr shdr;
00085     GElf_Dyn dyn;
00086     int bingo;
00087 
00088     (void) elf_version(EV_CURRENT);
00089 
00090 /*@-evalorder@*/
00091     if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
00092      || elf_kind(elf) != ELF_K_ELF
00093      || gelf_getehdr(elf, &ehdr) == NULL
00094      || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
00095         goto exit;
00096 /*@=evalorder@*/
00097 
00098     bingo = 0;
00099     /*@-branchstate -uniondef @*/
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             int maxndx = data->d_size / shdr.sh_entsize;
00106             int ndx;
00107 
00108             for (ndx = 0; ndx < maxndx; ++ndx) {
00109                 (void) gelf_getdyn (data, ndx, &dyn);
00110                 if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
00111                     /*@innercontinue@*/ continue;
00112                 bingo = 1;
00113                 /*@innerbreak@*/ break;
00114             }
00115         }
00116     }
00117     /*@=branchstate =uniondef @*/
00118 
00119 /*@-boundswrite@*/
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 /*@=boundswrite@*/
00147 
00148 exit:
00149     if (elf) (void) elf_end(elf);
00150  }
00151 #endif
00152 
00153     return fdno;
00154 }
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     int xx;
00170 
00171 /*@-globs -internalglobs -mods @*/
00172     fdno = open_dso(path, &pid, &fsize);
00173 /*@=globs =internalglobs =mods @*/
00174     if (fdno < 0) {
00175         rc = 1;
00176         goto exit;
00177     }
00178 
00179     /* XXX 128 Mb resource cap for top(1) scrutiny, MADV_SEQUENTIAL better. */
00180     use_mmap = (pid == 0 && fsize <= 0x07ffffff);
00181 
00182     switch(ut) {
00183     case URL_IS_PATH:
00184     case URL_IS_UNKNOWN:
00185 #if HAVE_MMAP
00186       if (use_mmap) {
00187         DIGEST_CTX ctx;
00188         void * mapped = NULL;
00189 
00190         if (fsize) {
00191             mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0);
00192             if (mapped == (void *)-1) {
00193                 xx = close(fdno);
00194                 rc = 1;
00195                 break;
00196             }
00197 
00198 #ifdef  MADV_SEQUENTIAL
00199             xx = madvise(mapped, fsize, MADV_SEQUENTIAL);
00200 #endif
00201         }
00202 
00203         ctx = rpmDigestInit(digestalgo, RPMDIGEST_NONE);
00204         if (fsize)
00205             xx = rpmDigestUpdate(ctx, mapped, fsize);
00206         xx = rpmDigestFinal(ctx, &dsum, &dlen, asAscii);
00207         if (fsize)
00208             xx = munmap(mapped, fsize);
00209         xx = close(fdno);
00210         break;
00211       } /*@fallthrough@*/
00212 #endif
00213     case URL_IS_HTTPS:
00214     case URL_IS_HTTP:
00215     case URL_IS_FTP:
00216     case URL_IS_HKP:
00217     case URL_IS_DASH:
00218     default:
00219         /* Either use the pipe to prelink -y or open the URL. */
00220         fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r");
00221         (void) close(fdno);
00222         if (fd == NULL || Ferror(fd)) {
00223             rc = 1;
00224             if (fd != NULL)
00225                 (void) Fclose(fd);
00226             break;
00227         }
00228         
00229         fdInitDigest(fd, digestalgo, 0);
00230         fsize = 0;
00231         while ((rc = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00232             fsize += rc;
00233         fdFiniDigest(fd, digestalgo, &dsum, &dlen, asAscii);
00234         if (Ferror(fd))
00235             rc = 1;
00236 
00237         (void) Fclose(fd);
00238         break;
00239     }
00240 
00241     /* Reap the prelink -y helper. */
00242     if (pid) {
00243         int status;
00244         (void) waitpid(pid, &status, 0);
00245         if (!WIFEXITED(status) || WEXITSTATUS(status))
00246             rc = 1;
00247     }
00248 
00249 exit:
00250 /*@-boundswrite@*/
00251     if (fsizep)
00252         *fsizep = fsize;
00253     if (!rc)
00254         memcpy(digest, dsum, dlen);
00255 /*@=boundswrite@*/
00256     dsum = _free(dsum);
00257 
00258     return rc;
00259 }
00260 
00261 int domd5(const char * fn, unsigned char * digest, int asAscii, size_t *fsizep)
00262 {
00263     return dodigest(PGPHASHALGO_MD5, fn, digest, asAscii, fsizep);
00264 }
00265 
00266 void rpmfiBuildFNames(Header h, rpmTag tagN,
00267         /*@out@*/ const char *** fnp, /*@out@*/ int * fcp)
00268 {
00269     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00270     HFD_t hfd = headerFreeData;
00271     const char ** baseNames;
00272     const char ** dirNames;
00273     int * dirIndexes;
00274     int count;
00275     const char ** fileNames;
00276     int size;
00277     rpmTag dirNameTag = 0;
00278     rpmTag dirIndexesTag = 0;
00279     rpmTagType bnt, dnt;
00280     char * t;
00281     int i, xx;
00282 
00283     if (tagN == RPMTAG_BASENAMES) {
00284         dirNameTag = RPMTAG_DIRNAMES;
00285         dirIndexesTag = RPMTAG_DIRINDEXES;
00286     } else if (tagN == RPMTAG_ORIGBASENAMES) {
00287         dirNameTag = RPMTAG_ORIGDIRNAMES;
00288         dirIndexesTag = RPMTAG_ORIGDIRINDEXES;
00289     }
00290 
00291     if (!hge(h, tagN, &bnt, &baseNames, &count)) {
00292         if (fnp) *fnp = NULL;
00293         if (fcp) *fcp = 0;
00294         return;         /* no file list */
00295     }
00296 
00297     xx = hge(h, dirNameTag, &dnt, &dirNames, NULL);
00298     xx = hge(h, dirIndexesTag, NULL, &dirIndexes, &count);
00299 
00300     size = sizeof(*fileNames) * count;
00301     for (i = 0; i < count; i++) {
00302         const char * dn = NULL;
00303         (void) urlPath(dirNames[dirIndexes[i]], &dn);
00304         size += strlen(baseNames[i]) + strlen(dn) + 1;
00305     }
00306 
00307     fileNames = xmalloc(size);
00308     t = ((char *) fileNames) + (sizeof(*fileNames) * count);
00309     /*@-branchstate@*/
00310     for (i = 0; i < count; i++) {
00311         const char * dn = NULL;
00312         fileNames[i] = t;
00313         (void) urlPath(dirNames[dirIndexes[i]], &dn);
00314         t = stpcpy( stpcpy(t, dn), baseNames[i]);
00315         *t++ = '\0';
00316     }
00317     /*@=branchstate@*/
00318     baseNames = hfd(baseNames, bnt);
00319     dirNames = hfd(dirNames, dnt);
00320 
00321     /*@-branchstate@*/
00322     if (fnp)
00323         *fnp = fileNames;
00324     else
00325         fileNames = _free(fileNames);
00326     /*@=branchstate@*/
00327     if (fcp) *fcp = count;
00328 }

Generated on Tue Dec 27 22:41:16 2016 for rpm by  doxygen 1.4.4