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>
23 #include <rpm/rpmfileutil.h>
24 #include <rpm/rpmurl.h>
25 #include <rpm/rpmmacro.h>
26 #include <rpm/rpmlog.h>
29 #include "rpmio/rpmio_internal.h"
33 static const char *rpm_config_dir = NULL;
35 static int is_prelinked(int fdno)
38 #if HAVE_GELF_H && HAVE_LIBELF
41 Elf_Data *data = NULL;
46 (void) elf_version(EV_CURRENT);
48 if ((elf = elf_begin (fdno, ELF_C_READ, NULL)) == NULL ||
49 elf_kind(elf) != ELF_K_ELF || gelf_getehdr(elf, &ehdr) == NULL ||
50 !(ehdr.e_type == ET_DYN || ehdr.e_type == ET_EXEC))
53 while (!prelinked && (scn = elf_nextscn(elf, scn)) != NULL) {
54 (void) gelf_getshdr(scn, &shdr);
55 if (shdr.sh_type != SHT_DYNAMIC)
57 while (!prelinked && (data = elf_getdata (scn, data)) != NULL) {
58 int maxndx = data->d_size / shdr.sh_entsize;
60 for (int ndx = 0; ndx < maxndx; ++ndx) {
61 (void) gelf_getdyn (data, ndx, &dyn);
62 if (!(dyn.d_tag == DT_GNU_PRELINKED || dyn.d_tag == DT_GNU_LIBLIST))
71 if (elf) (void) elf_end(elf);
76 static int open_dso(const char * path, pid_t * pidp, rpm_loff_t *fsizep)
78 static const char * cmd = NULL;
79 static int initted = 0;
83 cmd = rpmExpand("%{?__prelink_undo_cmd}", NULL);
90 struct stat sb, * st = &sb;
91 if (stat(path, st) < 0)
93 *fsizep = st->st_size;
96 fdno = open(path, O_RDONLY);
103 if (pidp != NULL && is_prelinked(fdno)) {
109 pipes[0] = pipes[1] = -1;
111 if (!(pid = fork())) {
113 argvSplit(&av, cmd, " ");
115 xx = close(pipes[0]);
116 xx = dup2(pipes[1], STDOUT_FILENO);
117 xx = close(pipes[1]);
118 if ((lib = argvSearch(av, "library", NULL)) != NULL) {
119 *lib = (char *) path;
120 unsetenv("MALLOC_CHECK_");
121 xx = execve(av[0], av+1, environ);
127 xx = close(pipes[1]);
133 int rpmDoDigest(int algo, const char * fn,int asAscii,
134 unsigned char * digest, rpm_loff_t * fsizep)
137 urltype ut = urlPath(fn, &path);
138 unsigned char * dig = NULL;
140 unsigned char buf[32*BUFSIZ];
142 rpm_loff_t fsize = 0;
147 fdno = open_dso(path, &pid, &fsize);
162 /* Either use the pipe to prelink -y or open the URL. */
163 fd = (pid != 0) ? fdDup(fdno) : Fopen(fn, "r.ufdio");
165 if (fd == NULL || Ferror(fd)) {
172 fdInitDigest(fd, algo, 0);
174 while ((rc = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
176 fdFiniDigest(fd, algo, (void **)&dig, &diglen, asAscii);
184 /* Reap the prelink -y helper. */
187 (void) waitpid(pid, &status, 0);
188 if (!WIFEXITED(status) || WEXITSTATUS(status))
196 memcpy(digest, dig, diglen);
202 FD_t rpmMkTemp(char *templ)
209 sfd = mkstemp(templ);
223 FD_t rpmMkTempFile(const char * prefix, char **fn)
225 const char *tpmacro = "%{_tmppath}"; /* always set from rpmrc */
227 static int _initialized = 0;
230 if (!prefix) prefix = "";
232 /* Create the temp directory if it doesn't already exist. */
235 tempfn = rpmGenPath(prefix, tpmacro, NULL);
236 if (rpmioMkpath(tempfn, 0755, (uid_t) -1, (gid_t) -1))
241 tempfn = rpmGetPath(prefix, tpmacro, "/rpm-tmp.XXXXXX", NULL);
242 tfd = rpmMkTemp(tempfn);
244 if (tfd == NULL || Ferror(tfd)) {
245 rpmlog(RPMLOG_ERR, _("error creating temporary file %s: %m\n"), tempfn);
250 if (tfd != NULL && fn)
258 int rpmioMkpath(const char * path, mode_t mode, uid_t uid, gid_t gid)
263 if (path == NULL || *path == '\0')
265 d = rstrcat(NULL, path);
266 if (d[strlen(d)-1] != '/') {
270 for (;(de=strchr(de+1,'/'));) {
280 rpmlog(RPMLOG_DEBUG, "created directory(s) %s mode 0%o\n", path, mode);
281 if (!(uid == (uid_t) -1 && gid == (gid_t) -1)) {
282 rc = chown(d, uid, gid);
286 } else if (!S_ISDIR(st.st_mode)) {
298 int rpmFileIsCompressed(const char * file, rpmCompressedMagic * compressed)
303 unsigned char magic[13];
305 *compressed = COMPRESSED_NOT;
307 fd = Fopen(file, "r.ufdio");
308 if (fd == NULL || Ferror(fd)) {
310 rpmlog(RPMLOG_ERR, _("File %s: %s\n"), file, Fstrerror(fd));
311 if (fd) (void) Fclose(fd);
314 nb = Fread(magic, sizeof(magic[0]), sizeof(magic), fd);
316 rpmlog(RPMLOG_ERR, _("File %s: %s\n"), file, Fstrerror(fd));
318 } else if (nb < sizeof(magic)) {
319 rpmlog(RPMLOG_ERR, _("File %s is smaller than %u bytes\n"),
320 file, (unsigned)sizeof(magic));
329 if ((magic[0] == 'B') && (magic[1] == 'Z')) {
330 *compressed = COMPRESSED_BZIP2;
331 } else if ((magic[0] == 'P') && (magic[1] == 'K') &&
332 (((magic[2] == 3) && (magic[3] == 4)) ||
333 ((magic[2] == '0') && (magic[3] == '0')))) { /* pkzip */
334 *compressed = COMPRESSED_ZIP;
335 } else if ((magic[0] == 0xfd) && (magic[1] == 0x37) &&
336 (magic[2] == 0x7a) && (magic[3] == 0x58) &&
337 (magic[4] == 0x5a) && (magic[5] == 0x00)) {
338 /* new style xz (lzma) with magic */
339 *compressed = COMPRESSED_XZ;
340 } else if ((magic[0] == 'L') && (magic[1] == 'Z') &&
341 (magic[2] == 'I') && (magic[3] == 'P')) {
342 *compressed = COMPRESSED_LZIP;
343 } else if ((magic[0] == 'L') && (magic[1] == 'R') &&
344 (magic[2] == 'Z') && (magic[3] == 'I')) {
345 *compressed = COMPRESSED_LRZIP;
346 } else if (((magic[0] == 0037) && (magic[1] == 0213)) || /* gzip */
347 ((magic[0] == 0037) && (magic[1] == 0236)) || /* old gzip */
348 ((magic[0] == 0037) && (magic[1] == 0036)) || /* pack */
349 ((magic[0] == 0037) && (magic[1] == 0240)) || /* SCO lzh */
350 ((magic[0] == 0037) && (magic[1] == 0235)) /* compress */
352 *compressed = COMPRESSED_OTHER;
353 } else if ((magic[0] == '7') && (magic[1] == 'z') &&
354 (magic[2] == 0xbc) && (magic[3] == 0xaf) &&
355 (magic[4] == 0x27) && (magic[5] == 0x1c)) {
356 *compressed = COMPRESSED_7ZIP;
357 } else if (rpmFileHasSuffix(file, ".lzma")) {
358 *compressed = COMPRESSED_LZMA;
364 /* @todo "../sbin/./../bin/" not correct. */
365 char *rpmCleanPath(char * path)
374 /*fprintf(stderr, "*** RCP %s ->\n", path); */
377 /*fprintf(stderr, "*** got \"%.*s\"\trest \"%s\"\n", (t-path), path, s); */
379 case ':': /* handle url's */
380 if (s[1] == '/' && s[2] == '/') {
388 /* Move parent dir forward */
389 for (se = te + 1; se < t && *se != '/'; se++)
391 if (se < t && *se == '/') {
393 /*fprintf(stderr, "*** next pdir \"%.*s\"\n", (te-path), path); */
397 while (t > path && t[-1] == '/')
401 /* Leading .. is special */
402 /* Check that it is ../, so that we don't interpret */
403 /* ..?(i.e. "...") or ..* (i.e. "..bogus") as "..". */
404 /* in the case of "...", this ends up being processed*/
405 /* as "../.", and the last '.' is stripped. This */
406 /* would not be correct processing. */
407 if (begin && s[1] == '.' && (s[2] == '/' || s[2] == '\0')) {
408 /*fprintf(stderr, " leading \"..\"\n"); */
412 /* Single . is special */
413 if (begin && s[1] == '\0') {
416 /* Handle the ./ cases */
417 if (t > path && t[-1] == '/') {
418 /* Trim embedded ./ */
423 /* Trim trailing /. */
429 /* Trim embedded /../ and trailing /.. */
430 if (!begin && t > path && t[-1] == '/' && s[1] == '.' && (s[2] == '/' || s[2] == '\0')) {
432 /* Move parent dir forward */
434 for (--te; te > path && *te != '/'; te--)
436 /*fprintf(stderr, "*** prev pdir \"%.*s\"\n", (te-path), path); */
449 /* Trim trailing / (but leave single / alone) */
450 if (t > &path[1] && t[-1] == '/')
454 /*fprintf(stderr, "\t%s\n", path); */
458 /* Merge 3 args into path, any or all of which may be a url. */
460 char * rpmGenPath(const char * urlroot, const char * urlmdir,
463 char * xroot = rpmGetPath(urlroot, NULL);
464 const char * root = xroot;
465 char * xmdir = rpmGetPath(urlmdir, NULL);
466 const char * mdir = xmdir;
467 char * xfile = rpmGetPath(urlfile, NULL);
468 const char * file = xfile;
474 ut = urlPath(xroot, &root);
475 if (url == NULL && ut > URL_IS_DASH) {
479 if (root == NULL || *root == '\0') root = "/";
481 ut = urlPath(xmdir, &mdir);
482 if (url == NULL && ut > URL_IS_DASH) {
486 if (mdir == NULL || *mdir == '\0') mdir = "/";
488 ut = urlPath(xfile, &file);
489 if (url == NULL && ut > URL_IS_DASH) {
494 if (url && nurl > 0) {
495 char *t = rstrcat(NULL, url);
501 result = rpmGetPath(url, root, "/", mdir, "/", file, NULL);
510 /* Return concatenated and expanded canonical path. */
512 char * rpmGetPath(const char *path, ...)
515 char *dest = NULL, *res;
522 for (s = path; s; s = va_arg(ap, const char *)) {
527 res = rpmExpand(dest, NULL);
530 return rpmCleanPath(res);
533 char * rpmEscapeSpaces(const char * s)
540 for (se = s; *se; se++) {
547 t = te = xmalloc(nb);
548 for (se = s; *se; se++) {
557 int rpmFileHasSuffix(const char *path, const char *suffix)
559 size_t plen = strlen(path);
560 size_t slen = strlen(suffix);
561 return (plen >= slen && rstreq(path+plen-slen, suffix));
564 char * rpmGetCwd(void)
567 char * currDir = NULL;
571 currDir = xrealloc(currDir, currDirLen);
572 memset(currDir, 0, currDirLen);
573 } while (getcwd(currDir, currDirLen) == NULL && errno == ERANGE);
578 int rpmMkdirs(const char *root, const char *pathstr)
582 argvSplit(&dirs, pathstr, ":");
584 for (char **d = dirs; *d; d++) {
585 char *path = rpmGetPath(root ? root : "", *d, NULL);
586 if ((rc = rpmioMkpath(path, 0755, -1, -1)) != 0) {
587 const char *msg = _("failed to create directory");
588 /* try to be more informative if the failing part was a macro */
590 rpmlog(RPMLOG_ERR, "%s %s: %s: %m\n", msg, *d, path);
592 rpmlog(RPMLOG_ERR, "%s %s: %m\n", msg, path);
602 const char *rpmConfigDir(void)
604 if (rpm_config_dir == NULL) {
605 char *rpmenv = getenv("RPM_CONFIGDIR");
606 rpm_config_dir = rpmenv ? xstrdup(rpmenv) : RPMCONFIGDIR;
608 return rpm_config_dir;