7 #if !defined(DT_GNU_PRELINKED)
8 #define DT_GNU_PRELINKED 0x6ffffdf5
10 #if !defined(DT_GNU_LIBLIST)
11 #define DT_GNU_LIBLIST 0x6ffffef9
16 #if defined(HAVE_MMAP)
25 #include <rpm/rpmfileutil.h>
26 #include <rpm/rpmurl.h>
27 #include <rpm/rpmmacro.h>
28 #include <rpm/rpmlog.h>
31 #include "rpmio/rpmio_internal.h"
35 static const char *rpm_config_dir = NULL;
37 static int open_dso(const char * path, pid_t * pidp, rpm_loff_t *fsizep)
39 static const char * cmd = NULL;
40 static int initted = 0;
44 cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
51 struct stat sb, * st = &sb;
52 if (stat(path, st) < 0)
54 *fsizep = st->st_size;
57 fdno = open(path, O_RDONLY);
64 #if HAVE_GELF_H && HAVE_LIBELF
67 Elf_Data *data = NULL;
73 (void) elf_version(EV_CURRENT);
75 if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
76 || elf_kind(elf) != ELF_K_ELF
77 || gelf_getehdr(elf, &ehdr) == NULL
78 || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
82 while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) {
83 (void) gelf_getshdr(scn, &shdr);
84 if (shdr.sh_type != SHT_DYNAMIC)
86 while (!bingo && (data = elf_getdata (scn, data)) != NULL) {
87 int maxndx = data->d_size / shdr.sh_entsize;
90 for (ndx = 0; ndx < maxndx; ++ndx) {
91 (void) gelf_getdyn (data, ndx, &dyn);
92 if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
100 if (pidp != NULL && bingo) {
106 pipes[0] = pipes[1] = -1;
108 if (!(pid = fork())) {
110 argvSplit(&av, cmd, " ");
112 xx = close(pipes[0]);
113 xx = dup2(pipes[1], STDOUT_FILENO);
114 xx = close(pipes[1]);
115 if ((lib = argvSearch(av, "library", NULL)) != NULL) {
116 *lib = (char *) path;
117 unsetenv("MALLOC_CHECK_");
118 xx = execve(av[0], av+1, environ);
124 xx = close(pipes[1]);
128 if (elf) (void) elf_end(elf);
135 int rpmDoDigest(int algo, const char * fn,int asAscii,
136 unsigned char * digest, rpm_loff_t * fsizep)
139 urltype ut = urlPath(fn, &path);
140 unsigned char * dig = NULL;
142 unsigned char buf[32*BUFSIZ];
144 rpm_loff_t fsize = 0;
149 fdno = open_dso(path, &pid, &fsize);
155 /* file to large (32 MB), do not mmap file */
156 if (fsize > (size_t) 32*1024*1024)
157 if (ut == URL_IS_PATH || ut == URL_IS_UNKNOWN)
158 ut = URL_IS_DASH; /* force fd io */
170 mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0);
171 if (mapped == MAP_FAILED) {
177 #ifdef MADV_SEQUENTIAL
178 xx = madvise(mapped, fsize, MADV_SEQUENTIAL);
182 ctx = rpmDigestInit(algo, RPMDIGEST_NONE);
184 xx = rpmDigestUpdate(ctx, mapped, fsize);
185 xx = rpmDigestFinal(ctx, (void **)&dig, &diglen, asAscii);
187 xx = munmap(mapped, fsize);
198 /* Either use the pipe to prelink -y or open the URL. */
199 fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.ufdio");
201 if (fd == NULL || Ferror(fd)) {
208 fdInitDigest(fd, algo, 0);
210 while ((rc = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
212 fdFiniDigest(fd, algo, (void **)&dig, &diglen, asAscii);
220 /* Reap the prelink -y helper. */
223 (void) waitpid(pid, &status, 0);
224 if (!WIFEXITED(status) || WEXITSTATUS(status))
232 memcpy(digest, dig, diglen);
238 FD_t rpmMkTemp(char *templ)
243 sfd = mkstemp(templ);
255 FD_t rpmMkTempFile(const char * prefix, char **fn)
257 const char *tpmacro = "%{_tmppath}"; /* always set from rpmrc */
259 static int _initialized = 0;
262 if (!prefix) prefix = "";
264 /* Create the temp directory if it doesn't already exist. */
267 tempfn = rpmGenPath(prefix, tpmacro, NULL);
268 if (rpmioMkpath(tempfn, 0755, (uid_t) -1, (gid_t) -1))
273 tempfn = rpmGetPath(prefix, tpmacro, "/rpm-tmp.XXXXXX", NULL);
274 tfd = rpmMkTemp(tempfn);
276 if (tfd == NULL || Ferror(tfd)) {
277 rpmlog(RPMLOG_ERR, _("error creating temporary file %s: %m\n"), tempfn);
282 if (tfd != NULL && fn)
290 int rpmioMkpath(const char * path, mode_t mode, uid_t uid, gid_t gid)
295 if (path == NULL || *path == '\0')
297 d = rstrcat(NULL, path);
298 if (d[strlen(d)-1] != '/') {
302 for (;(de=strchr(de+1,'/'));) {
312 rpmlog(RPMLOG_DEBUG, "created directory(s) %s mode 0%o\n", path, mode);
313 if (!(uid == (uid_t) -1 && gid == (gid_t) -1)) {
314 rc = chown(d, uid, gid);
318 } else if (!S_ISDIR(st.st_mode)) {
330 int rpmFileIsCompressed(const char * file, rpmCompressedMagic * compressed)
335 unsigned char magic[13];
337 *compressed = COMPRESSED_NOT;
339 fd = Fopen(file, "r.ufdio");
340 if (fd == NULL || Ferror(fd)) {
342 rpmlog(RPMLOG_ERR, _("File %s: %s\n"), file, Fstrerror(fd));
343 if (fd) (void) Fclose(fd);
346 nb = Fread(magic, sizeof(magic[0]), sizeof(magic), fd);
348 rpmlog(RPMLOG_ERR, _("File %s: %s\n"), file, Fstrerror(fd));
350 } else if (nb < sizeof(magic)) {
351 rpmlog(RPMLOG_ERR, _("File %s is smaller than %u bytes\n"),
352 file, (unsigned)sizeof(magic));
361 if ((magic[0] == 'B') && (magic[1] == 'Z')) {
362 *compressed = COMPRESSED_BZIP2;
363 } else if ((magic[0] == 0120) && (magic[1] == 0113) &&
364 (magic[2] == 0003) && (magic[3] == 0004)) { /* pkzip */
365 *compressed = COMPRESSED_ZIP;
366 } else if ((magic[0] == 0xfd) && (magic[1] == 0x37) &&
367 (magic[2] == 0x7a) && (magic[3] == 0x58) &&
368 (magic[4] == 0x5a) && (magic[5] == 0x00)) {
369 /* new style xz (lzma) with magic */
370 *compressed = COMPRESSED_XZ;
371 } else if (((magic[0] == 0037) && (magic[1] == 0213)) || /* gzip */
372 ((magic[0] == 0037) && (magic[1] == 0236)) || /* old gzip */
373 ((magic[0] == 0037) && (magic[1] == 0036)) || /* pack */
374 ((magic[0] == 0037) && (magic[1] == 0240)) || /* SCO lzh */
375 ((magic[0] == 0037) && (magic[1] == 0235)) /* compress */
377 *compressed = COMPRESSED_OTHER;
378 } else if (rpmFileHasSuffix(file, ".lzma")) {
379 *compressed = COMPRESSED_LZMA;
385 /* @todo "../sbin/./../bin/" not correct. */
386 char *rpmCleanPath(char * path)
395 /*fprintf(stderr, "*** RCP %s ->\n", path); */
398 /*fprintf(stderr, "*** got \"%.*s\"\trest \"%s\"\n", (t-path), path, s); */
400 case ':': /* handle url's */
401 if (s[1] == '/' && s[2] == '/') {
409 /* Move parent dir forward */
410 for (se = te + 1; se < t && *se != '/'; se++)
412 if (se < t && *se == '/') {
414 /*fprintf(stderr, "*** next pdir \"%.*s\"\n", (te-path), path); */
418 while (t > path && t[-1] == '/')
422 /* Leading .. is special */
423 /* Check that it is ../, so that we don't interpret */
424 /* ..?(i.e. "...") or ..* (i.e. "..bogus") as "..". */
425 /* in the case of "...", this ends up being processed*/
426 /* as "../.", and the last '.' is stripped. This */
427 /* would not be correct processing. */
428 if (begin && s[1] == '.' && (s[2] == '/' || s[2] == '\0')) {
429 /*fprintf(stderr, " leading \"..\"\n"); */
433 /* Single . is special */
434 if (begin && s[1] == '\0') {
437 /* Handle the ./ cases */
438 if (t > path && t[-1] == '/') {
439 /* Trim embedded ./ */
444 /* Trim trailing /. */
450 /* Trim embedded /../ and trailing /.. */
451 if (!begin && t > path && t[-1] == '/' && s[1] == '.' && (s[2] == '/' || s[2] == '\0')) {
453 /* Move parent dir forward */
455 for (--te; te > path && *te != '/'; te--)
457 /*fprintf(stderr, "*** prev pdir \"%.*s\"\n", (te-path), path); */
470 /* Trim trailing / (but leave single / alone) */
471 if (t > &path[1] && t[-1] == '/')
475 /*fprintf(stderr, "\t%s\n", path); */
479 /* Merge 3 args into path, any or all of which may be a url. */
481 char * rpmGenPath(const char * urlroot, const char * urlmdir,
484 char * xroot = rpmGetPath(urlroot, NULL);
485 const char * root = xroot;
486 char * xmdir = rpmGetPath(urlmdir, NULL);
487 const char * mdir = xmdir;
488 char * xfile = rpmGetPath(urlfile, NULL);
489 const char * file = xfile;
495 ut = urlPath(xroot, &root);
496 if (url == NULL && ut > URL_IS_DASH) {
500 if (root == NULL || *root == '\0') root = "/";
502 ut = urlPath(xmdir, &mdir);
503 if (url == NULL && ut > URL_IS_DASH) {
507 if (mdir == NULL || *mdir == '\0') mdir = "/";
509 ut = urlPath(xfile, &file);
510 if (url == NULL && ut > URL_IS_DASH) {
515 if (url && nurl > 0) {
516 char *t = rstrcat(NULL, url);
522 result = rpmGetPath(url, root, "/", mdir, "/", file, NULL);
524 xroot = _free(xroot);
525 xmdir = _free(xmdir);
526 xfile = _free(xfile);
531 /* Return concatenated and expanded canonical path. */
533 char * rpmGetPath(const char *path, ...)
536 char *dest = NULL, *res;
543 for (s = path; s; s = va_arg(ap, const char *)) {
548 res = rpmExpand(dest, NULL);
551 return rpmCleanPath(res);
554 int rpmGlob(const char * patterns, int * argcPtr, ARGV_t * argvPtr)
557 const char ** av = NULL;
560 char * globRoot = NULL;
561 const char *home = getenv("HOME");
564 char * old_collate = NULL;
565 char * old_ctype = NULL;
572 if (home != NULL && strlen(home) > 0)
573 gflags |= GLOB_TILDE;
575 /* Can't use argvSplit() here, it doesn't handle whitespace etc escapes */
576 rc = poptParseArgvString(patterns, &ac, &av);
581 t = setlocale(LC_COLLATE, NULL);
583 old_collate = xstrdup(t);
584 t = setlocale(LC_CTYPE, NULL);
586 old_ctype = xstrdup(t);
587 (void) setlocale(LC_COLLATE, "C");
588 (void) setlocale(LC_CTYPE, "C");
592 for (j = 0; j < ac; j++) {
595 int ut = urlPath(av[j], &path);
596 int local = (ut == URL_IS_PATH) || (ut == URL_IS_UNKNOWN);
599 if (!local || (!glob_pattern_p(av[j], 0) && strchr(path, '~') == NULL)) {
600 argvAdd(&argv, av[j]);
607 rc = glob(av[j], gflags, NULL, &gl);
611 /* XXX Prepend the URL leader for globs that have stripped it off */
613 for (i = 0; i < gl.gl_pathc; i++) {
614 if ((nb = strlen(&(gl.gl_pathv[i][0]))) > maxb)
618 nb = ((ut == URL_IS_PATH) ? (path - av[j]) : 0);
621 globURL = globRoot = xmalloc(maxb);
626 strncpy(globRoot, av[j], nb);
639 for (i = 0; i < gl.gl_pathc; i++) {
640 const char * globFile = &(gl.gl_pathv[i][0]);
641 if (globRoot > globURL && globRoot[-1] == '/')
642 while (*globFile == '/') globFile++;
643 strcpy(globRoot, globFile);
644 argvAdd(&argv, globURL);
647 globURL = _free(globURL);
650 argc = argvCount(argv);
664 (void) setlocale(LC_COLLATE, old_collate);
665 old_collate = _free(old_collate);
668 (void) setlocale(LC_CTYPE, old_ctype);
669 old_ctype = _free(old_ctype);
673 if (rc || argvPtr == NULL) {
679 char * rpmEscapeSpaces(const char * s)
686 for (se = s; *se; se++) {
693 t = te = xmalloc(nb);
694 for (se = s; *se; se++) {
703 int rpmFileHasSuffix(const char *path, const char *suffix)
705 size_t plen = strlen(path);
706 size_t slen = strlen(suffix);
707 return (plen >= slen && rstreq(path+plen-slen, suffix));
710 char * rpmGetCwd(void)
713 char * currDir = NULL;
717 currDir = xrealloc(currDir, currDirLen);
718 memset(currDir, 0, currDirLen);
719 } while (getcwd(currDir, currDirLen) == NULL && errno == ERANGE);
724 int rpmMkdirs(const char *root, const char *pathstr)
728 argvSplit(&dirs, pathstr, ":");
730 for (char **d = dirs; *d; d++) {
731 char *path = rpmGetPath(root ? root : "", *d, NULL);
732 if ((rc = rpmioMkpath(path, 0755, -1, -1)) != 0) {
733 const char *msg = _("failed to create directory");
734 /* try to be more informative if the failing part was a macro */
736 rpmlog(RPMLOG_ERR, "%s %s: %s: %m\n", msg, *d, path);
738 rpmlog(RPMLOG_ERR, "%s %s: %m\n", msg, path);
748 const char *rpmConfigDir(void)
750 if (rpm_config_dir == NULL) {
751 char *rpmenv = getenv("RPM_CONFIGDIR");
752 rpm_config_dir = rpmenv ? xstrdup(rpmenv) : RPMCONFIGDIR;
754 return rpm_config_dir;