00001
00005 #include "system.h"
00006
00007 #if HAVE_GELF_H
00008 #if LIBELF_H_LFS_CONFLICT
00009
00010
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, pid_t * pidp, size_t *fsizep)
00045
00046
00047
00048 {
00049
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
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
00070 fdno = open(path, O_RDONLY);
00071 if (fdno < 0)
00072 return fdno;
00073
00074
00075 if (!(cmd && *cmd))
00076 return fdno;
00077
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
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
00097
00098 bingo = 0;
00099
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 continue;
00112 bingo = 1;
00113 break;
00114 }
00115 }
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
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
00172 fdno = open_dso(path, &pid, &fsize);
00173
00174 if (fdno < 0) {
00175 rc = 1;
00176 goto exit;
00177 }
00178
00179
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 }
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
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
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
00251 if (fsizep)
00252 *fsizep = fsize;
00253 if (!rc)
00254 memcpy(digest, dsum, dlen);
00255
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 const char *** fnp, 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;
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
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
00318 baseNames = hfd(baseNames, bnt);
00319 dirNames = hfd(dirNames, dnt);
00320
00321
00322 if (fnp)
00323 *fnp = fileNames;
00324 else
00325 fileNames = _free(fileNames);
00326
00327 if (fcp) *fcp = count;
00328 }