Subject: long name ar fix to NetBSD-current (and probably FreeBSD, too) linker
To: None <current-users@sun-lamp.cs.berkeley.edu, freebsd-hackers@freefall.cdrom.com,>
From: Bill Sommerfeld <sommerfeld@orchard.medford.ma.us>
List: current-users
Date: 11/28/1993 22:27:15
The following patch to NetBSD-current ld/lib.c causes it to correctly
handle archive member names longer than OLDARMAXNAME (15) characters
long; without this behavior, ld reports "bad magic number" when it
tries to bring in a file with a long name from an archive.

As Mark Eichin recently reported, this is a long-standing bug in *BSD,
dating back to 386BSD 0.0, which, among other things, breaks the build
of Kerberos.

This bug likely also exists under FreeBSD.

This has been tested by rebuilding libc.a, libc_p.a, libc_pic.a, and
libc.so.1.1 without the `T' option to ar, as well as with a smaller
test case of a library containing a file named
"funkelhausersteinweitz.o".

Once you install and verify this change, you should also edit
src/share/bsd.lib.mk to change all occurances of "cTq" to "cq", and
reinstall it, then rebuild all archive libraries which contain
truncated object file names.

					- Bill

*** 1.1	1993/11/29 02:32:13
--- 1.2	1993/11/29 03:00:12
***************
*** 78,88 ****
  {
  	int             bytes_read;
  	register int    namelen;
! 	int             member_length;
  	register char  *name;
  	struct ar_hdr   hdr1;
  	register struct file_entry *subentry;
! 
  	lseek(desc, subfile_offset, 0);
  
  	bytes_read = read(desc, &hdr1, sizeof hdr1);
--- 78,88 ----
  {
  	int             bytes_read;
  	register int    namelen;
! 	int             member_length, content_length;
  	register char  *name;
  	struct ar_hdr   hdr1;
  	register struct file_entry *subentry;
! 	int starting_offset;
  	lseek(desc, subfile_offset, 0);
  
  	bytes_read = read(desc, &hdr1, sizeof hdr1);
***************
*** 104,125 ****
  	     && hdr1.ar_name[namelen] != '/';
  	     namelen++);
  
! 	name = (char *) xmalloc(namelen + 1);
! 	strncpy(name, hdr1.ar_name, namelen);
! 	name[namelen] = 0;
! 
  	subentry->filename = name;
  	subentry->local_sym_name = name;
  	subentry->symbols = 0;
  	subentry->strings = 0;
  	subentry->subfiles = 0;
! 	subentry->starting_offset = subfile_offset + sizeof hdr1;
  	subentry->superfile = library_entry;
  	subentry->library_flag = 0;
  	subentry->header_read_flag = 0;
  	subentry->just_syms_flag = 0;
  	subentry->chain = 0;
! 	subentry->total_size = member_length;
  
  	(*length_loc) = member_length;
  
--- 104,147 ----
  	     && hdr1.ar_name[namelen] != '/';
  	     namelen++);
  
! 	starting_offset = subfile_offset + sizeof hdr1;	
! 	content_length = member_length;
! #ifdef AR_EFMT1
! 	/*
! 	 * BSD 4.4 extended AR format: #1/<namelen>, with name as the
! 	 * first <namelen> bytes of the file
! 	 */
! 	if ((hdr1.ar_name[0]=='#') &&
! 	    (hdr1.ar_name[1]=='1') &&
! 	    (hdr1.ar_name[2]=='/') && 
! 	    (isdigit(hdr1.ar_name[3])))
! 	{
! 	    namelen = atoi (&hdr1.ar_name[3]);
! 	    name = (char *) xmalloc(namelen + 1);
! 	    read (desc, name, namelen);
! 	    name[namelen] = 0;
! 	    content_length -= namelen;
! 	    starting_offset += namelen;
! 	} else 
! #endif
! 	{
! 	    name = (char *) xmalloc(namelen + 1);
! 	    strncpy(name, hdr1.ar_name, namelen);
! 	    name[namelen] = 0;
! 	}
! 	
  	subentry->filename = name;
  	subentry->local_sym_name = name;
  	subentry->symbols = 0;
  	subentry->strings = 0;
  	subentry->subfiles = 0;
! 	subentry->starting_offset = starting_offset;
  	subentry->superfile = library_entry;
  	subentry->library_flag = 0;
  	subentry->header_read_flag = 0;
  	subentry->just_syms_flag = 0;
  	subentry->chain = 0;
! 	subentry->total_size = content_length;
  
  	(*length_loc) = member_length;
  


------------------------------------------------------------------------------