PR binutils/12710

* archive.c (_bfd_get_elt_at_filepos): Set correct error value if
	unable to read a file pointed to by an entry in a thin archive.
	(adjust_relative_path): Use lrealpath to canonicalize paths.
	Handle the case where the reference path is above the current
	path in the directory tree.
This commit is contained in:
Nick Clifton 2011-05-27 10:52:30 +00:00
parent f20db198c0
commit c49486096b
2 changed files with 89 additions and 12 deletions

View File

@ -1,3 +1,12 @@
2011-05-27 Nick Clifton <nickc@redhat.com>
PR binutils/12710
* archive.c (_bfd_get_elt_at_filepos): Set correct error value if
unable to read a file pointed to by an entry in a thin archive.
(adjust_relative_path): Use lrealpath to canonicalize paths.
Handle the case where the reference path is above the current
path in the directory tree.
2011-05-26 H.J. Lu <hongjiu.lu@intel.com>
PR ld/12809

View File

@ -629,6 +629,8 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
/* It's not an element of a nested archive;
open the external file as a bfd. */
n_nfd = bfd_openr (filename, NULL);
if (n_nfd == NULL)
bfd_set_error (bfd_error_malformed_archive);
}
else
{
@ -717,6 +719,7 @@ bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file)
else
{
unsigned int size = arelt_size (last_file);
filestart = last_file->proxy_origin;
if (! bfd_is_thin_archive (archive))
filestart += size;
@ -750,7 +753,7 @@ bfd_generic_archive_p (bfd *abfd)
if (strncmp (armag, ARMAG, SARMAG) != 0
&& strncmp (armag, ARMAGB, SARMAG) != 0
&& ! bfd_is_thin_archive (abfd))
return 0;
return NULL;
tdata_hold = bfd_ardata (abfd);
@ -1333,18 +1336,46 @@ normalize (bfd *abfd ATTRIBUTE_UNUSED, const char *file)
}
#endif
/* Adjust a relative path name based on the reference path. */
/* Adjust a relative path name based on the reference path.
For example:
Relative path Reference path Result
------------- -------------- ------
bar.o lib.a bar.o
foo/bar.o lib.a foo/bar.o
bar.o foo/lib.a ../bar.o
foo/bar.o baz/lib.a ../foo/bar.o
bar.o ../lib.a <parent of current dir>/bar.o
../bar.o ../lib.a bar.o
../bar.o lib.a ../bar.o
foo/bar.o ../lib.a <parent of current dir>/foo/bar.o
bar.o ../../lib.a <grandparent>/<parent>/bar.o
bar.o foo/baz/lib.a ../../bar.o
Note - the returned string is in a static buffer. */
static const char *
adjust_relative_path (const char * path, const char * ref_path)
{
static char *pathbuf = NULL;
static int pathbuf_len = 0;
const char *pathp = path;
const char *refp = ref_path;
int element_count = 0;
int len;
static unsigned int pathbuf_len = 0;
const char *pathp;
const char *refp;
char * lpath;
char * rpath;
unsigned int len;
unsigned int dir_up = 0;
unsigned int dir_down = 0;
char *newp;
char * pwd = getpwd ();
const char * down;
/* Remove symlinks, '.' and '..' from the paths, if possible. */
lpath = lrealpath (path);
pathp = lpath == NULL ? path : lpath;
rpath = lrealpath (ref_path);
refp = rpath == NULL ? ref_path : rpath;
/* Remove common leading path elements. */
for (;;)
@ -1363,12 +1394,42 @@ adjust_relative_path (const char * path, const char * ref_path)
refp = e2 + 1;
}
len = strlen (pathp) + 1;
/* For each leading path element in the reference path,
insert "../" into the path. */
for (; *refp; ++refp)
if (IS_DIR_SEPARATOR (*refp))
++element_count;
len = 3 * element_count + strlen (path) + 1;
{
/* PR 12710: If the path element is "../" then instead of
inserting "../" we need to insert the name of the directory
at the current level. */
if (refp > ref_path + 1
&& refp[-1] == '.'
&& refp[-2] == '.')
dir_down ++;
else
dir_up ++;
}
/* If the lrealpath calls above succeeded then we should never
see dir_up and dir_down both being non-zero. */
len += 3 * dir_up;
if (dir_down)
{
down = pwd + strlen (pwd) - 1;
while (dir_down && down > pwd)
{
if (IS_DIR_SEPARATOR (*down))
--dir_down;
}
BFD_ASSERT (dir_down == 0);
len += strlen (down) + 1;
}
else
down = NULL;
if (len > pathbuf_len)
{
@ -1377,19 +1438,26 @@ adjust_relative_path (const char * path, const char * ref_path)
pathbuf_len = 0;
pathbuf = (char *) bfd_malloc (len);
if (pathbuf == NULL)
return path;
goto out;
pathbuf_len = len;
}
newp = pathbuf;
while (element_count-- > 0)
while (dir_up-- > 0)
{
/* FIXME: Support Windows style path separators as well. */
strcpy (newp, "../");
newp += 3;
}
if (down)
sprintf (newp, "%s/%s", down, pathp);
else
strcpy (newp, pathp);
out:
free (lpath);
free (rpath);
return pathbuf;
}