--- rpm-5.4.5/lib/rpmds.c.16022~ 2012-02-24 14:17:17.278202493 +0100 +++ rpm-5.4.5/lib/rpmds.c 2012-02-24 14:19:52.416279821 +0100 @@ -2916,7 +2916,7 @@ static char * sonameDep(/*@returned@*/ c if (isElf64) { /* XXX: eehhk, would've been nice with consistency, mandriva legacy... :| */ if (!devel && s[strlen(s)-1] != ')') - (void) stpcpy( stpcpy(tmp, s), "()(64bit)"); + tmp = stpcpy( stpcpy(tmp, s), "()(64bit)"); else { tmp = stpcpy(tmp, s); if (devel) @@ -2995,8 +2995,11 @@ foo: scn = gelf_offscn (elf, phdr->p_offset); shdr = gelf_getshdr(scn, &shdr_mem); data = elf_getdata (scn, data); - interp_name = strdup(data->d_buf); - goto end; + if (data && data->d_buf) { + interp_name = strdup(data->d_buf); + goto end; + } + /* no 'data' most likely implies that this is an elf interpreter itself */ } if (elf_getshdrstrndx (elf, &shstrndx) >= 0) @@ -3016,6 +3019,15 @@ foo: for (cnt = 0; cnt <= dynsize; ++cnt) { dyn = gelf_getdyn (data, cnt, &dyn_mem); + /* if this an elf interpeter, the only thing we want is to find SONAME + * and return it + */ + if (phdr) { + if (dyn->d_tag != DT_SONAME) + continue; + interp_name = strdup(elf_strptr(elf, shdr->sh_link, dyn->d_un.d_val)); + goto end; + } if (rpath == NULL) { if (dyn->d_tag == DT_RPATH) rpath = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val); @@ -3025,7 +3037,7 @@ foo: cnt = -1; continue; } - else if (rpath && DT_NEEDED == dyn->d_tag) { + else if (rpath && dyn->d_tag == DT_NEEDED) { char *tmp, *tmp2; char buf[1024]; char path[1024] = ""; @@ -3083,6 +3095,7 @@ foo: strcpy(tmp, path_n); strcat(tmp, "/"); strcat(tmp, libpath); + if (stat(tmp, &statbuf) == 0 && statbuf.st_mode & S_IRUSR) { path[0] = '\0'; break; @@ -3514,6 +3527,7 @@ int rpmdsSymlink(const char * fn, int fl char buf[BUFSIZ]; const char * s; int is_executable; + int is_symlink; const char * soname = NULL; rpmds ds; int xx; @@ -3539,12 +3553,6 @@ int rpmdsSymlink(const char * fn, int fl if ((s = strrchr(fn, '.')) && strcmp(s, ".so")) return 0; - if ((lnklen = readlink(fn, path, MAXPATHLEN - 1)) == -1) { - warn("%s", fn); - return -1; - } - path[lnklen] = '\0'; - /*@-castfcnptr@*/ if (_rpmds_debug < 0) fprintf(stderr, "*** rpmdsELF(%s, %d, %p, %p)\n", fn, flags, (void *)add, context); @@ -3555,6 +3563,62 @@ fprintf(stderr, "*** rpmdsELF(%s, %d, %p if (lstat(fn, st) != 0) return -1; is_executable = (int)(st->st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)); + is_symlink = S_ISLNK(st->st_mode); + } + + if (is_symlink) { +#ifdef NOT_YET + if ((lnklen = readlink(fn, path, MAXPATHLEN - 1)) == -1) { + warn("%s", fn); + return -1; + } + /* XXX: unused, path should expand to absolute path... */ + path[lnklen] = '\0'; +#endif + } else { + FILE *fp = fopen(fn, "r"); + char buf[BUFSIZ]; + char *in; + stpcpy(path, fn); + fn = NULL; + if (fp == NULL || ferror(fp)) { + if (fp) (void) fclose(fp); + return -1; + } + /* try resolve ld scripts + * certainly *not* state of the art, but should in practice work + * everywhere where relevant... + */ + while ((in = fgets(buf, sizeof(buf) - 1, fp))) { + in[sizeof(buf)-1] = '\0'; + if ((in = strstr(in, "GROUP")) && + (in = strchr(in, '(')) && + (fn = strchr(in, '/')) && + (in = strchr(fn, ' '))) { + *in = '\0'; + break; + } + if (ferror(fp) || feof(fp)) + break; + } + fclose(fp); + if (!fn) + return -1; + else { + /* XXX: try determine relative root */ + struct stat sb, * st = &sb; + + while((in = strrchr(path, '/'))) { + stpcpy(in, fn); + if (stat(path, st) == 0) { + fn = path; + break; + } + *in = 0; + } + if (!fn) + return -1; + } } fdno = open(fn, O_RDONLY); @@ -3644,8 +3708,10 @@ assert(s != NULL); /*@=uniondef @*/ exit: - if (gotSONAME && !skipR) + if (gotSONAME && !skipR) { for (i = 0, cnt = argvCount(deps); i < cnt; i++) { + if (deps[i][0] == 'l' && deps[i][1] == 'd') + continue; ds = rpmdsSingle(RPMTAG_REQUIRENAME, sonameDep(buf, deps[i], isElf64, 1, isuClibc), "", RPMSENSE_FIND_REQUIRES); @@ -3653,6 +3719,7 @@ exit: (void)rpmdsFree(ds); ds = NULL; } + } deps = argvFree(deps); if (elf) (void) elf_end(elf); --- rpm-5.4.5/lib/rpmfc.c.16022~ 2012-02-24 13:46:30.693282090 +0100 +++ rpm-5.4.5/lib/rpmfc.c 2012-02-24 14:20:56.062311544 +0100 @@ -518,7 +518,7 @@ assert(EVR != NULL); * build/reqprov.c:addReqProv() */ int overlap = 0, res = 0; - if (*depsp) { + if (*depsp && rpmExpandNumeric("%{?_use_internal_dependency_generator}")) { int ix = rpmdsSearch(*depsp, ds); if (ix >= 0) { /* do not consider dependency ranges like R: foo > 1, R: foo < 3 @@ -1045,6 +1045,11 @@ static int rpmfcSYMLINK(rpmfc fc) flags |= RPMELF_FLAG_SKIPPROVIDES; if (fc->skipReq) flags |= RPMELF_FLAG_SKIPREQUIRES; + /* XXX: Remove symlink classifier from linker scripts now that we've been + * able to feed it to the generator. + */ + if (fc->fcolor->vals[fc->ix] == (RPMFC_WHITE|RPMFC_INCLUDE|RPMFC_TEXT|RPMFC_SYMLINK)) + fc->fcolor->vals[fc->ix] &= ~RPMFC_SYMLINK; return rpmdsSymlink(fn, flags, rpmfcMergePR, fc); } @@ -1362,6 +1367,36 @@ if (_rpmfc_debug) /* XXX noisy */ /* Add (filtered) entry to sorted class dictionary. */ fcolor = rpmfcColoring(se); + + /* Quick&dirty hack for linker scripts replacing regular + * symlinks. Better *really* needs to be done ASAP. + */ +#if defined(RPM_VENDOR_MANDRIVA) + if (fcolor == (RPMFC_WHITE|RPMFC_INCLUDE|RPMFC_TEXT)) { + char * fn; + + if ((fn = strrchr(s, '.')) && !strcmp(fn, ".so")) { + FILE * fp = fopen(s, "r"); + char buf[BUFSIZ]; + char * in; + if (fp == NULL || ferror(fp)) { + if (fp) (void) fclose(fp); + } + while ((in = fgets(buf, sizeof(buf) - 1, fp))) { + in[sizeof(buf)-1] = '\0'; + if (ferror(fp) || feof(fp)) + break; + if ((fn = strstr(in, "GROUP")) && + (fn = strchr(fn, '(')) && (fn = strchr(in, '/'))) { + fcolor |= RPMFC_SYMLINK; + break; + } + } + if (fp) + fclose(fp); + } + } +#endif xx = argiAdd(&fc->fcolor, (int)fc->ix, fcolor); if (fcolor != RPMFC_WHITE && (fcolor & RPMFC_INCLUDE))