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 #include <sys/types.h>
24 #include <rpm/rpmfileutil.h>
25 #include <rpm/rpmurl.h>
26 #include <rpm/rpmmacro.h>
27 #include <rpm/rpmlog.h>
30 #include "rpmio/rpmio_internal.h"
34 static const char *rpm_config_dir = NULL;
35 static pthread_once_t configDirSet = PTHREAD_ONCE_INIT;
37 static int is_prelinked(int fdno)
40 #if HAVE_GELF_H && HAVE_LIBELF
43 Elf_Data *data = NULL;
48 (void) elf_version(EV_CURRENT);
50 if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL ||
51 elf_kind(elf) != ELF_K_ELF || gelf_getehdr(elf, &ehdr) == NULL ||
52 !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
55 while (!prelinked && (scn = elf_nextscn(elf, scn)) != NULL) {
56 (void) gelf_getshdr(scn, &shdr);
57 if (shdr.sh_type != SHT_DYNAMIC)
59 while (!prelinked && (data = elf_getdata (scn, data)) != NULL) {
60 int maxndx = data->d_size / shdr.sh_entsize;
62 for (int ndx = 0; ndx < maxndx; ++ndx) {
63 (void) gelf_getdyn (data, ndx, &dyn);
64 if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
73 if (elf) (void) elf_end(elf);
78 static int open_dso(const char * path, pid_t * pidp, rpm_loff_t *fsizep)
80 static const char * cmd = NULL;
81 static int initted = 0;
85 cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
92 struct stat sb, * st = &sb;
93 if (stat(path, st) < 0)
95 *fsizep = st->st_size;
98 fdno = open(path, O_RDONLY);
105 if (pidp != NULL && is_prelinked(fdno)) {
110 pipes[0] = pipes[1] = -1;
124 argvSplit(&av, cmd, " ");
127 dfd = dup2(pipes[1], STDOUT_FILENO);
129 if (dfd >= 0 && (lib = argvSearch(av, "library", NULL)) != NULL) {
130 *lib = (char *) path;
131 unsetenv("MALLOC_CHECK_");
132 execve(av[0], av+1, environ);
134 _exit(127); /* not normally reached */
145 int rpmDoDigest(int algo, const char * fn,int asAscii,
146 unsigned char * digest, rpm_loff_t * fsizep)
149 urltype ut = urlPath(fn, &path);
150 unsigned char * dig = NULL;
151 size_t diglen, buflen = 32 * BUFSIZ;
152 unsigned char *buf = xmalloc(buflen);
154 rpm_loff_t fsize = 0;
159 fdno = open_dso(path, &pid, &fsize);
174 /* Either use the pipe to prelink -y or open the URL. */
175 fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.ufdio");
177 if (fd == NULL || Ferror(fd)) {
184 fdInitDigest(fd, algo, 0);
186 while ((rc = Fread(buf, sizeof(*buf), buflen, fd)) > 0)
188 fdFiniDigest(fd, algo, (void **)&dig, &diglen, asAscii);
189 if (dig == NULL || Ferror(fd))
196 /* Reap the prelink -y helper. */
199 (void) waitpid(pid, &status, 0);
200 if (!WIFEXITED(status) || WEXITSTATUS(status))
208 memcpy(digest, dig, diglen);
215 FD_t rpmMkTemp(char *templ)
222 sfd = mkstemp(templ);
236 FD_t rpmMkTempFile(const char * prefix, char **fn)
238 const char *tpmacro = "%{_tmppath}"; /* always set from rpmrc */
240 static int _initialized = 0;
243 if (!prefix) prefix = "";
245 /* Create the temp directory if it doesn't already exist. */
248 tempfn = rpmGenPath(prefix, tpmacro, NULL);
249 if (rpmioMkpath(tempfn, 0755, (uid_t) -1, (gid_t) -1))
254 tempfn = rpmGetPath(prefix, tpmacro, "/rpm-tmp.XXXXXX", NULL);
255 tfd = rpmMkTemp(tempfn);
257 if (tfd == NULL || Ferror(tfd)) {
258 rpmlog(RPMLOG_ERR, _("error creating temporary file %s: %m\n"), tempfn);
263 if (tfd != NULL && fn)
271 int rpmioMkpath(const char * path, mode_t mode, uid_t uid, gid_t gid)
276 if (path == NULL || *path == '\0')
278 d = rstrcat(NULL, path);
279 if (d[strlen(d)-1] != '/') {
283 for (;(de=strchr(de+1,'/'));) {
293 rpmlog(RPMLOG_DEBUG, "created directory(s) %s mode 0%o\n", path, mode);
294 if (!(uid == (uid_t) -1 && gid == (gid_t) -1)) {
295 rc = chown(d, uid, gid);
299 } else if (!S_ISDIR(st.st_mode)) {
311 int rpmFileIsCompressed(const char * file, rpmCompressedMagic * compressed)
316 unsigned char magic[13];
318 *compressed = COMPRESSED_NOT;
320 fd = Fopen(file, "r.ufdio");
321 if (fd == NULL || Ferror(fd)) {
323 rpmlog(RPMLOG_ERR, _("File %s: %s\n"), file, Fstrerror(fd));
324 if (fd) (void) Fclose(fd);
327 nb = Fread(magic, sizeof(magic[0]), sizeof(magic), fd);
329 rpmlog(RPMLOG_ERR, _("File %s: %s\n"), file, Fstrerror(fd));
331 } else if (nb < sizeof(magic)) {
332 rpmlog(RPMLOG_ERR, _("File %s is smaller than %u bytes\n"),
333 file, (unsigned)sizeof(magic));
342 if ((magic[0] == 'B') && (magic[1] == 'Z') &&
344 *compressed = COMPRESSED_BZIP2;
345 } else if ((magic[0] == 'P') && (magic[1] == 'K') &&
346 (((magic[2] == 3) && (magic[3] == 4)) ||
347 ((magic[2] == '0') && (magic[3] == '0')))) { /* pkzip */
348 *compressed = COMPRESSED_ZIP;
349 } else if ((magic[0] == 0xfd) && (magic[1] == 0x37) &&
350 (magic[2] == 0x7a) && (magic[3] == 0x58) &&
351 (magic[4] == 0x5a) && (magic[5] == 0x00)) {
352 /* new style xz (lzma) with magic */
353 *compressed = COMPRESSED_XZ;
354 } else if ((magic[0] == 0x28) && (magic[1] == 0x85) &&
355 (magic[2] == 0x2f) ) {
356 *compressed = COMPRESSED_ZSTD;
357 } else if ((magic[0] == 'L') && (magic[1] == 'Z') &&
358 (magic[2] == 'I') && (magic[3] == 'P')) {
359 *compressed = COMPRESSED_LZIP;
360 } else if ((magic[0] == 'L') && (magic[1] == 'R') &&
361 (magic[2] == 'Z') && (magic[3] == 'I')) {
362 *compressed = COMPRESSED_LRZIP;
363 } else if (((magic[0] == 0037) && (magic[1] == 0213)) || /* gzip */
364 ((magic[0] == 0037) && (magic[1] == 0236)) || /* old gzip */
365 ((magic[0] == 0037) && (magic[1] == 0036)) || /* pack */
366 ((magic[0] == 0037) && (magic[1] == 0240)) || /* SCO lzh */
367 ((magic[0] == 0037) && (magic[1] == 0235)) /* compress */
369 *compressed = COMPRESSED_OTHER;
370 } else if ((magic[0] == '7') && (magic[1] == 'z') &&
371 (magic[2] == 0xbc) && (magic[3] == 0xaf) &&
372 (magic[4] == 0x27) && (magic[5] == 0x1c)) {
373 *compressed = COMPRESSED_7ZIP;
374 } else if (rpmFileHasSuffix(file, ".lzma")) {
375 *compressed = COMPRESSED_LZMA;
376 } else if (rpmFileHasSuffix(file, ".gem")) {
377 *compressed = COMPRESSED_GEM;
383 /* @todo "../sbin/./../bin/" not correct. */
384 char *rpmCleanPath(char * path)
393 /*fprintf(stderr, "*** RCP %s ->\n", path); */
396 /*fprintf(stderr, "*** got \"%.*s\"\trest \"%s\"\n", (t-path), path, s); */
398 case ':': /* handle url's */
399 if (s[1] == '/' && s[2] == '/') {
407 /* Move parent dir forward */
408 for (se = te + 1; se < t && *se != '/'; se++)
410 if (se < t && *se == '/') {
412 /*fprintf(stderr, "*** next pdir \"%.*s\"\n", (te-path), path); */
416 while (t > path && t[-1] == '/')
420 /* Leading .. is special */
421 /* Check that it is ../, so that we don't interpret */
422 /* ..?(i.e. "...") or ..* (i.e. "..bogus") as "..". */
423 /* in the case of "...", this ends up being processed*/
424 /* as "../.", and the last '.' is stripped. This */
425 /* would not be correct processing. */
426 if (begin && s[1] == '.' && (s[2] == '/' || s[2] == '\0')) {
427 /*fprintf(stderr, " leading \"..\"\n"); */
431 /* Single . is special */
432 if (begin && s[1] == '\0') {
435 /* Handle the ./ cases */
436 if (t > path && t[-1] == '/') {
437 /* Trim embedded ./ */
442 /* Trim trailing /. */
448 /* Trim embedded /../ and trailing /.. */
449 if (!begin && t > path && t[-1] == '/' && s[1] == '.' && (s[2] == '/' || s[2] == '\0')) {
451 /* Move parent dir forward */
453 for (--te; te > path && *te != '/'; te--)
455 /*fprintf(stderr, "*** prev pdir \"%.*s\"\n", (te-path), path); */
468 /* Trim trailing / (but leave single / alone) */
469 if (t > &path[1] && t[-1] == '/')
473 /*fprintf(stderr, "\t%s\n", path); */
477 /* Merge 3 args into path, any or all of which may be a url. */
479 char * rpmGenPath(const char * urlroot, const char * urlmdir,
482 char * xroot = rpmGetPath(urlroot, NULL);
483 const char * root = xroot;
484 char * xmdir = rpmGetPath(urlmdir, NULL);
485 const char * mdir = xmdir;
486 char * xfile = rpmGetPath(urlfile, NULL);
487 const char * file = xfile;
493 ut = urlPath(xroot, &root);
494 if (url == NULL && ut > URL_IS_DASH) {
498 if (root == NULL || *root == '\0') root = "/";
500 ut = urlPath(xmdir, &mdir);
501 if (url == NULL && ut > URL_IS_DASH) {
505 if (mdir == NULL || *mdir == '\0') mdir = "/";
507 ut = urlPath(xfile, &file);
508 if (url == NULL && ut > URL_IS_DASH) {
513 if (url && nurl > 0) {
514 char *t = rstrcat(NULL, url);
520 result = rpmGetPath(url, root, "/", mdir, "/", file, NULL);
529 /* Return concatenated and expanded canonical path. */
531 char * rpmGetPath(const char *path, ...)
534 char *dest = NULL, *res;
541 for (s = path; s; s = va_arg(ap, const char *)) {
546 res = rpmExpand(dest, NULL);
549 return rpmCleanPath(res);
552 char * rpmEscapeSpaces(const char * s)
559 for (se = s; *se; se++) {
566 t = te = xmalloc(nb);
567 for (se = s; *se; se++) {
576 int rpmFileHasSuffix(const char *path, const char *suffix)
578 size_t plen = strlen(path);
579 size_t slen = strlen(suffix);
580 return (plen >= slen && rstreq(path+plen-slen, suffix));
583 char * rpmGetCwd(void)
586 char * currDir = NULL;
590 currDir = xrealloc(currDir, currDirLen);
591 memset(currDir, 0, currDirLen);
592 } while (getcwd(currDir, currDirLen) == NULL && errno == ERANGE);
597 int rpmMkdirs(const char *root, const char *pathstr)
601 argvSplit(&dirs, pathstr, ":");
603 for (char **d = dirs; *d; d++) {
604 char *path = rpmGetPath(root ? root : "", *d, NULL);
605 if ((rc = rpmioMkpath(path, 0755, -1, -1)) != 0) {
606 const char *msg = _("failed to create directory");
607 /* try to be more informative if the failing part was a macro */
609 rpmlog(RPMLOG_ERR, "%s %s: %s: %m\n", msg, *d, path);
611 rpmlog(RPMLOG_ERR, "%s %s: %m\n", msg, path);
621 static void setConfigDir(void)
623 char *rpmenv = getenv("RPM_CONFIGDIR");
624 rpm_config_dir = rpmenv ? xstrdup(rpmenv) : RPMCONFIGDIR;
627 const char *rpmConfigDir(void)
629 pthread_once(&configDirSet, setConfigDir);
630 return rpm_config_dir;