handle long names

This commit is contained in:
rsc 2004-04-21 06:52:44 +00:00
parent a29753a17f
commit d946e4dc5d

View file

@ -104,10 +104,12 @@ atimes(char *ar)
{ {
struct ar_hdr h; struct ar_hdr h;
long t; long t;
int fd, i; int fd, i, namelen;
char buf[1024]; char buf[2048], *p, *strings;
char name[sizeof(h.name)+1]; char name[1024];
Symtab *sym;
strings = nil;
fd = open(ar, OREAD); fd = open(ar, OREAD);
if(fd < 0) if(fd < 0)
return; return;
@ -116,23 +118,74 @@ atimes(char *ar)
close(fd); close(fd);
return; return;
} }
while(read(fd, (char *)&h, sizeof(h)) == sizeof(h)){ while(readn(fd, (char *)&h, sizeof(h)) == sizeof(h)){
t = atol(h.date); t = atol(h.date);
if(t == 0) /* as it sometimes happens; thanks ken */ if(t == 0) /* as it sometimes happens; thanks ken */
t = 1; t = 1;
strncpy(name, h.name, sizeof(h.name)); namelen = 0;
for(i = sizeof(h.name)-1; i > 0 && name[i] == ' '; i--) if(memcmp(h.name, "#1/", 3) == 0){ /* BSD */
namelen = atoi(h.name+3);
if(namelen >= sizeof name){
namelen = 0;
goto skip;
}
if(readn(fd, name, namelen) != namelen)
break;
name[namelen] = 0;
}else if(memcmp(h.name, "// ", 2) == 0){ /* GNU */
/* date, uid, gid, mode all ' ' */
for(i=2; i<16+12+6+6+8; i++)
if(h.name[i] != ' ')
goto skip;
t = atol(h.size);
if(t&01)
t++;
free(strings);
strings = malloc(t+1);
if(strings){
if(readn(fd, strings, t) != t){
free(strings);
strings = nil;
break;
}
strings[t] = 0;
continue;
}
goto skip;
}else if(strings && h.name[0]=='/' && isdigit(h.name[1])){
i = strtol(h.name+1, &p, 10);
if(*p != ' ' || strlen(strings) < i)
goto skip;
p = strings+i;
for(; *p && *p != '/'; p++)
; ;
if(name[i] == '/') /* system V bug */ namelen = p-(strings+i);
i--; if(namelen >= sizeof name){
name[i+1]=0; namelen = 0;
goto skip;
}
memmove(name, strings+i, namelen);
name[namelen] = 0;
namelen = 0;
}else{
strncpy(name, h.name, sizeof(h.name));
for(i = sizeof(h.name)-1; i > 0 && name[i] == ' '; i--)
;
if(name[i] == '/') /* system V bug */
i--;
name[i+1]=0;
}
snprint(buf, sizeof buf, "%s(%s)", ar, name); snprint(buf, sizeof buf, "%s(%s)", ar, name);
symlook(strdup(buf), S_TIME, (void *)t)->value = (void *)t; sym = symlook(strdup(buf), S_TIME, (void *)t);
sym->value = (void *)t;
skip:
t = atol(h.size); t = atol(h.size);
if(t&01) t++; if(t&01) t++;
t -= namelen;
LSEEK(fd, t, 1); LSEEK(fd, t, 1);
} }
close(fd); close(fd);
free(strings);
} }
static int static int