commit d946e4dc5df1c0fb9a06e6d94013613848c5df16 from: rsc date: Wed Apr 21 06:52:44 2004 UTC handle long names commit - a29753a17ffd2be43fbadb9f1851d1aacf771d44 commit + d946e4dc5df1c0fb9a06e6d94013613848c5df16 blob - 8bb80bbfefc2e915c6df6f68d94caec24c98afd0 blob + 14d2082dafb110ea30a9dcaec957ec7b6349043d --- src/cmd/mk/archive.c +++ src/cmd/mk/archive.c @@ -104,10 +104,12 @@ atimes(char *ar) { struct ar_hdr h; long t; - int fd, i; - char buf[1024]; - char name[sizeof(h.name)+1]; + int fd, i, namelen; + char buf[2048], *p, *strings; + char name[1024]; + Symtab *sym; + strings = nil; fd = open(ar, OREAD); if(fd < 0) return; @@ -116,23 +118,74 @@ atimes(char *ar) close(fd); return; } - while(read(fd, (char *)&h, sizeof(h)) == sizeof(h)){ + while(readn(fd, (char *)&h, sizeof(h)) == sizeof(h)){ t = atol(h.date); if(t == 0) /* as it sometimes happens; thanks ken */ t = 1; - strncpy(name, h.name, sizeof(h.name)); - for(i = sizeof(h.name)-1; i > 0 && name[i] == ' '; i--) + namelen = 0; + 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 */ - i--; - name[i+1]=0; + namelen = p-(strings+i); + if(namelen >= sizeof name){ + 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); - 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); if(t&01) t++; + t -= namelen; LSEEK(fd, t, 1); } close(fd); + free(strings); } static int