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)
20 #include <sys/types.h>
27 #include <rpm/rpmfileutil.h>
28 #include <rpm/rpmurl.h>
29 #include <rpm/rpmmacro.h>
30 #include <rpm/rpmlog.h>
33 #include "rpmio/rpmio_internal.h"
37 static const char *rpm_config_dir = NULL;
39 static int open_dso(const char * path, pid_t * pidp, rpm_loff_t *fsizep)
41 static const char * cmd = NULL;
42 static int initted = 0;
46 cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
53 struct stat sb, * st = &sb;
54 if (stat(path, st) < 0)
56 *fsizep = st->st_size;
59 fdno = open(path, O_RDONLY);
66 #if HAVE_GELF_H && HAVE_LIBELF
69 Elf_Data *data = NULL;
75 (void) elf_version(EV_CURRENT);
77 if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL
78 || elf_kind(elf) != ELF_K_ELF
79 || gelf_getehdr(elf, &ehdr) == NULL
80 || !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
84 while (!bingo && (scn = elf_nextscn(elf, scn)) != NULL) {
85 (void) gelf_getshdr(scn, &shdr);
86 if (shdr.sh_type != SHT_DYNAMIC)
88 while (!bingo && (data = elf_getdata (scn, data)) != NULL) {
89 int maxndx = data->d_size / shdr.sh_entsize;
92 for (ndx = 0; ndx < maxndx; ++ndx) {
93 (void) gelf_getdyn (data, ndx, &dyn);
94 if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
102 if (pidp != NULL && bingo) {
108 pipes[0] = pipes[1] = -1;
110 if (!(pid = fork())) {
112 argvSplit(&av, cmd, " ");
114 xx = close(pipes[0]);
115 xx = dup2(pipes[1], STDOUT_FILENO);
116 xx = close(pipes[1]);
117 if ((lib = argvSearch(av, "library", NULL)) != NULL) {
118 *lib = (char *) path;
119 unsetenv("MALLOC_CHECK_");
120 xx = execve(av[0], av+1, environ);
126 xx = close(pipes[1]);
130 if (elf) (void) elf_end(elf);
137 int rpmDoDigest(int algo, const char * fn,int asAscii,
138 unsigned char * digest, rpm_loff_t * fsizep)
141 urltype ut = urlPath(fn, &path);
142 unsigned char * dig = NULL;
144 unsigned char buf[32*BUFSIZ];
146 rpm_loff_t fsize = 0;
151 fdno = open_dso(path, &pid, &fsize);
157 /* file to large (32 MB), do not mmap file */
158 if (fsize > (size_t) 32*1024*1024)
159 if (ut == URL_IS_PATH || ut == URL_IS_UNKNOWN)
160 ut = URL_IS_DASH; /* force fd io */
172 mapped = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fdno, 0);
173 if (mapped == MAP_FAILED) {
179 #ifdef MADV_SEQUENTIAL
180 xx = madvise(mapped, fsize, MADV_SEQUENTIAL);
184 ctx = rpmDigestInit(algo, RPMDIGEST_NONE);
186 xx = rpmDigestUpdate(ctx, mapped, fsize);
187 xx = rpmDigestFinal(ctx, (void **)&dig, &diglen, asAscii);
189 xx = munmap(mapped, fsize);
200 /* Either use the pipe to prelink -y or open the URL. */
201 fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.ufdio");
203 if (fd == NULL || Ferror(fd)) {
210 fdInitDigest(fd, algo, 0);
212 while ((rc = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
214 fdFiniDigest(fd, algo, (void **)&dig, &diglen, asAscii);
222 /* Reap the prelink -y helper. */
225 (void) waitpid(pid, &status, 0);
226 if (!WIFEXITED(status) || WEXITSTATUS(status))
234 memcpy(digest, dig, diglen);
240 FD_t rpmMkTemp(char *templ)
247 sfd = mkstemp(templ);
261 FD_t rpmMkTempFile(const char * prefix, char **fn)
263 const char *tpmacro = "%{_tmppath}"; /* always set from rpmrc */
265 static int _initialized = 0;
268 if (!prefix) prefix = "";
270 /* Create the temp directory if it doesn't already exist. */
273 tempfn = rpmGenPath(prefix, tpmacro, NULL);
274 if (rpmioMkpath(tempfn, 0755, (uid_t) -1, (gid_t) -1))
279 tempfn = rpmGetPath(prefix, tpmacro, "/rpm-tmp.XXXXXX", NULL);
280 tfd = rpmMkTemp(tempfn);
282 if (tfd == NULL || Ferror(tfd)) {
283 rpmlog(RPMLOG_ERR, _("error creating temporary file %s: %m\n"), tempfn);
288 if (tfd != NULL && fn)
296 int rpmioMkpath(const char * path, mode_t mode, uid_t uid, gid_t gid)
301 if (path == NULL || *path == '\0')
303 d = rstrcat(NULL, path);
304 if (d[strlen(d)-1] != '/') {
308 for (;(de=strchr(de+1,'/'));) {
318 rpmlog(RPMLOG_DEBUG, "created directory(s) %s mode 0%o\n", path, mode);
319 if (!(uid == (uid_t) -1 && gid == (gid_t) -1)) {
320 rc = chown(d, uid, gid);
324 } else if (!S_ISDIR(st.st_mode)) {
336 int rpmFileIsCompressed(const char * file, rpmCompressedMagic * compressed)
341 unsigned char magic[13];
343 *compressed = COMPRESSED_NOT;
345 fd = Fopen(file, "r.ufdio");
346 if (fd == NULL || Ferror(fd)) {
348 rpmlog(RPMLOG_ERR, _("File %s: %s\n"), file, Fstrerror(fd));
349 if (fd) (void) Fclose(fd);
352 nb = Fread(magic, sizeof(magic[0]), sizeof(magic), fd);
354 rpmlog(RPMLOG_ERR, _("File %s: %s\n"), file, Fstrerror(fd));
356 } else if (nb < sizeof(magic)) {
357 rpmlog(RPMLOG_ERR, _("File %s is smaller than %u bytes\n"),
358 file, (unsigned)sizeof(magic));
367 if ((magic[0] == 'B') && (magic[1] == 'Z')) {
368 *compressed = COMPRESSED_BZIP2;
369 } else if ((magic[0] == 'P') && (magic[1] == 'K') &&
370 (((magic[2] == 3) && (magic[3] == 4)) ||
371 ((magic[2] == '0') && (magic[3] == '0')))) { /* pkzip */
372 *compressed = COMPRESSED_ZIP;
373 } else if ((magic[0] == 0xfd) && (magic[1] == 0x37) &&
374 (magic[2] == 0x7a) && (magic[3] == 0x58) &&
375 (magic[4] == 0x5a) && (magic[5] == 0x00)) {
376 /* new style xz (lzma) with magic */
377 *compressed = COMPRESSED_XZ;
378 } else if ((magic[0] == 'L') && (magic[1] == 'Z') &&
379 (magic[2] == 'I') && (magic[3] == 'P')) {
380 *compressed = COMPRESSED_LZIP;
381 } else if ((magic[0] == 'L') && (magic[1] == 'R') &&
382 (magic[2] == 'Z') && (magic[3] == 'I')) {
383 *compressed = COMPRESSED_LRZIP;
384 } else if (((magic[0] == 0037) && (magic[1] == 0213)) || /* gzip */
385 ((magic[0] == 0037) && (magic[1] == 0236)) || /* old gzip */
386 ((magic[0] == 0037) && (magic[1] == 0036)) || /* pack */
387 ((magic[0] == 0037) && (magic[1] == 0240)) || /* SCO lzh */
388 ((magic[0] == 0037) && (magic[1] == 0235)) /* compress */
390 *compressed = COMPRESSED_OTHER;
391 } else if (rpmFileHasSuffix(file, ".lzma")) {
392 *compressed = COMPRESSED_LZMA;
398 /* @todo "../sbin/./../bin/" not correct. */
399 char *rpmCleanPath(char * path)
408 /*fprintf(stderr, "*** RCP %s ->\n", path); */
411 /*fprintf(stderr, "*** got \"%.*s\"\trest \"%s\"\n", (t-path), path, s); */
413 case ':': /* handle url's */
414 if (s[1] == '/' && s[2] == '/') {
422 /* Move parent dir forward */
423 for (se = te + 1; se < t && *se != '/'; se++)
425 if (se < t && *se == '/') {
427 /*fprintf(stderr, "*** next pdir \"%.*s\"\n", (te-path), path); */
431 while (t > path && t[-1] == '/')
435 /* Leading .. is special */
436 /* Check that it is ../, so that we don't interpret */
437 /* ..?(i.e. "...") or ..* (i.e. "..bogus") as "..". */
438 /* in the case of "...", this ends up being processed*/
439 /* as "../.", and the last '.' is stripped. This */
440 /* would not be correct processing. */
441 if (begin && s[1] == '.' && (s[2] == '/' || s[2] == '\0')) {
442 /*fprintf(stderr, " leading \"..\"\n"); */
446 /* Single . is special */
447 if (begin && s[1] == '\0') {
450 /* Handle the ./ cases */
451 if (t > path && t[-1] == '/') {
452 /* Trim embedded ./ */
457 /* Trim trailing /. */
463 /* Trim embedded /../ and trailing /.. */
464 if (!begin && t > path && t[-1] == '/' && s[1] == '.' && (s[2] == '/' || s[2] == '\0')) {
466 /* Move parent dir forward */
468 for (--te; te > path && *te != '/'; te--)
470 /*fprintf(stderr, "*** prev pdir \"%.*s\"\n", (te-path), path); */
483 /* Trim trailing / (but leave single / alone) */
484 if (t > &path[1] && t[-1] == '/')
488 /*fprintf(stderr, "\t%s\n", path); */
492 /* Merge 3 args into path, any or all of which may be a url. */
494 char * rpmGenPath(const char * urlroot, const char * urlmdir,
497 char * xroot = rpmGetPath(urlroot, NULL);
498 const char * root = xroot;
499 char * xmdir = rpmGetPath(urlmdir, NULL);
500 const char * mdir = xmdir;
501 char * xfile = rpmGetPath(urlfile, NULL);
502 const char * file = xfile;
508 ut = urlPath(xroot, &root);
509 if (url == NULL && ut > URL_IS_DASH) {
513 if (root == NULL || *root == '\0') root = "/";
515 ut = urlPath(xmdir, &mdir);
516 if (url == NULL && ut > URL_IS_DASH) {
520 if (mdir == NULL || *mdir == '\0') mdir = "/";
522 ut = urlPath(xfile, &file);
523 if (url == NULL && ut > URL_IS_DASH) {
528 if (url && nurl > 0) {
529 char *t = rstrcat(NULL, url);
535 result = rpmGetPath(url, root, "/", mdir, "/", file, NULL);
544 /* Return concatenated and expanded canonical path. */
546 char * rpmGetPath(const char *path, ...)
549 char *dest = NULL, *res;
556 for (s = path; s; s = va_arg(ap, const char *)) {
561 res = rpmExpand(dest, NULL);
564 return rpmCleanPath(res);
567 int rpmGlob(const char * patterns, int * argcPtr, ARGV_t * argvPtr)
570 const char ** av = NULL;
573 char * globRoot = NULL;
574 const char *home = getenv("HOME");
577 char * old_collate = NULL;
578 char * old_ctype = NULL;
585 if (home != NULL && strlen(home) > 0)
586 gflags |= GLOB_TILDE;
588 /* Can't use argvSplit() here, it doesn't handle whitespace etc escapes */
589 rc = poptParseArgvString(patterns, &ac, &av);
594 t = setlocale(LC_COLLATE, NULL);
596 old_collate = xstrdup(t);
597 t = setlocale(LC_CTYPE, NULL);
599 old_ctype = xstrdup(t);
600 (void) setlocale(LC_COLLATE, "C");
601 (void) setlocale(LC_CTYPE, "C");
605 for (j = 0; j < ac; j++) {
608 int ut = urlPath(av[j], &path);
609 int local = (ut == URL_IS_PATH) || (ut == URL_IS_UNKNOWN);
610 size_t plen = strlen(path);
612 int dir_only = (plen > 0 && path[plen-1] == '/');
615 if (!local || (!glob_pattern_p(av[j], 0) && strchr(path, '~') == NULL)) {
616 argvAdd(&argv, av[j]);
622 flags |= GLOB_ONLYDIR;
628 rc = glob(av[j], flags, NULL, &gl);
632 /* XXX Prepend the URL leader for globs that have stripped it off */
634 for (i = 0; i < gl.gl_pathc; i++) {
635 if ((nb = strlen(&(gl.gl_pathv[i][0]))) > maxb)
639 nb = ((ut == URL_IS_PATH) ? (path - av[j]) : 0);
642 globURL = globRoot = xmalloc(maxb);
647 strncpy(globRoot, av[j], nb);
660 for (i = 0; i < gl.gl_pathc; i++) {
661 const char * globFile = &(gl.gl_pathv[i][0]);
665 if (lstat(gl.gl_pathv[i], &sb) || !S_ISDIR(sb.st_mode))
669 if (globRoot > globURL && globRoot[-1] == '/')
670 while (*globFile == '/') globFile++;
671 strcpy(globRoot, globFile);
672 argvAdd(&argv, globURL);
678 argc = argvCount(argv);
692 (void) setlocale(LC_COLLATE, old_collate);
696 (void) setlocale(LC_CTYPE, old_ctype);
701 if (rc || argvPtr == NULL) {
707 char * rpmEscapeSpaces(const char * s)
714 for (se = s; *se; se++) {
721 t = te = xmalloc(nb);
722 for (se = s; *se; se++) {
731 int rpmFileHasSuffix(const char *path, const char *suffix)
733 size_t plen = strlen(path);
734 size_t slen = strlen(suffix);
735 return (plen >= slen && rstreq(path+plen-slen, suffix));
738 char * rpmGetCwd(void)
741 char * currDir = NULL;
745 currDir = xrealloc(currDir, currDirLen);
746 memset(currDir, 0, currDirLen);
747 } while (getcwd(currDir, currDirLen) == NULL && errno == ERANGE);
752 int rpmMkdirs(const char *root, const char *pathstr)
756 argvSplit(&dirs, pathstr, ":");
758 for (char **d = dirs; *d; d++) {
759 char *path = rpmGetPath(root ? root : "", *d, NULL);
760 if ((rc = rpmioMkpath(path, 0755, -1, -1)) != 0) {
761 const char *msg = _("failed to create directory");
762 /* try to be more informative if the failing part was a macro */
764 rpmlog(RPMLOG_ERR, "%s %s: %s: %m\n", msg, *d, path);
766 rpmlog(RPMLOG_ERR, "%s %s: %m\n", msg, path);
776 const char *rpmConfigDir(void)
778 if (rpm_config_dir == NULL) {
779 char *rpmenv = getenv("RPM_CONFIGDIR");
780 rpm_config_dir = rpmenv ? xstrdup(rpmenv) : RPMCONFIGDIR;
782 return rpm_config_dir;