URI: 
       thandle long names - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit d946e4dc5df1c0fb9a06e6d94013613848c5df16
   DIR parent a29753a17ffd2be43fbadb9f1851d1aacf771d44
  HTML Author: rsc <devnull@localhost>
       Date:   Wed, 21 Apr 2004 06:52:44 +0000
       
       handle long names
       
       Diffstat:
         M src/cmd/mk/archive.c                |      73 ++++++++++++++++++++++++++-----
       
       1 file changed, 63 insertions(+), 10 deletions(-)
       ---
   DIR diff --git a/src/cmd/mk/archive.c b/src/cmd/mk/archive.c
       t@@ -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;
       t@@ -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