URI:
       tdirec.c - 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
       ---
       tdirec.c (4245B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <bio.h>
            4 #include <libsec.h>
            5 
            6 #include "iso9660.h"
            7 
            8 void
            9 mkdirec(Direc *direc, XDir *d)
           10 {
           11         memset(direc, 0, sizeof(Direc));
           12         direc->name = atom(d->name);
           13         direc->uid = atom(d->uid);
           14         direc->gid = atom(d->gid);
           15         direc->uidno = d->uidno;
           16         direc->gidno = d->gidno;
           17         direc->mode = d->mode;
           18         direc->length = d->length;
           19         direc->mtime = d->mtime;
           20         direc->atime = d->atime;
           21         direc->ctime = d->ctime;
           22         direc->symlink = d->symlink;
           23 }
           24 
           25 static int
           26 strecmp(char *a, char *ea, char *b)
           27 {
           28         int r;
           29 
           30         if((r = strncmp(a, b, ea-a)) != 0)
           31                 return r;
           32 
           33         if(b[ea-a] == '\0')
           34                 return 0;
           35         return 1;
           36 }
           37 
           38 /*
           39  * Binary search a list of directories for the
           40  * entry with name name.
           41  * If no entry is found, return a pointer to
           42  * where a new such entry would go.
           43  */
           44 static Direc*
           45 dbsearch(char *name, int nname, Direc *d, int n)
           46 {
           47         int i;
           48 
           49         while(n > 0) {
           50                 i = strecmp(name, name+nname, d[n/2].name);
           51                 if(i < 0)
           52                         n = n/2;
           53                 else if(i > 0) {
           54                         d += n/2+1;
           55                         n -= (n/2+1);
           56                 } else
           57                         return &d[n/2];
           58         }
           59         return d;
           60 }
           61 
           62 /*
           63  * Walk to name, starting at d.
           64  */
           65 Direc*
           66 walkdirec(Direc *d, char *name)
           67 {
           68         char *p, *nextp, *slashp;
           69         Direc *nd;
           70 
           71         for(p=name; p && *p; p=nextp) {
           72                 if((slashp = strchr(p, '/')) != nil)
           73                         nextp = slashp+1;
           74                 else
           75                         nextp = slashp = p+strlen(p);
           76 
           77                 nd = dbsearch(p, slashp-p, d->child, d->nchild);
           78                 if(nd >= d->child+d->nchild || strecmp(p, slashp, nd->name) != 0)
           79                         return nil;
           80                 d = nd;
           81         }
           82         return d;
           83 }
           84 
           85 /*
           86  * Add the file ``name'' with attributes d to the
           87  * directory ``root''.  Name may contain multiple
           88  * elements; all but the last must exist already.
           89  *
           90  * The child lists are kept sorted by utfname.
           91  */
           92 Direc*
           93 adddirec(Direc *root, char *name, XDir *d)
           94 {
           95         char *p;
           96         Direc *nd;
           97         int off;
           98 
           99         if(name[0] == '/')
          100                 name++;
          101         if((p = strrchr(name, '/')) != nil) {
          102                 *p = '\0';
          103                 root = walkdirec(root, name);
          104                 if(root == nil) {
          105                         sysfatal("error in proto file: no entry for /%s but /%s/%s\n", name, name, p+1);
          106                         return nil;
          107                 }
          108                 *p = '/';
          109                 p++;
          110         } else
          111                 p = name;
          112 
          113         nd = dbsearch(p, strlen(p), root->child, root->nchild);
          114         off = nd - root->child;
          115         if(off < root->nchild && strcmp(nd->name, p) == 0) {
          116                 if ((d->mode & DMDIR) == 0)
          117                         fprint(2, "warning: proto lists %s twice\n", name);
          118                 return nil;
          119         }
          120 
          121         if(root->nchild%Ndirblock == 0) {
          122                 root->child = erealloc(root->child, (root->nchild+Ndirblock)*sizeof(Direc));
          123                 nd = root->child + off;
          124         }
          125 
          126         memmove(nd+1, nd, (root->nchild - off)*sizeof(Direc));
          127         mkdirec(nd, d);
          128         nd->name = atom(p);
          129         root->nchild++;
          130         return nd;
          131 }
          132 
          133 /*
          134  * Copy the tree src into dst.
          135  */
          136 void
          137 copydirec(Direc *dst, Direc *src)
          138 {
          139         int i, n;
          140 
          141         *dst = *src;
          142 
          143         if((src->mode & DMDIR) == 0)
          144                 return;
          145 
          146         n = (src->nchild + Ndirblock - 1);
          147         n -= n%Ndirblock;
          148         dst->child = emalloc(n*sizeof(Direc));
          149 
          150         n = dst->nchild;
          151         for(i=0; i<n; i++)
          152                 copydirec(&dst->child[i], &src->child[i]);
          153 }
          154 
          155 /*
          156  * Turn the Dbadname flag on for any entries
          157  * that have non-conforming names.
          158  */
          159 static void
          160 _checknames(Direc *d, int (*isbadname)(char*), int isroot)
          161 {
          162         int i;
          163 
          164         if(!isroot && isbadname(d->name))
          165                 d->flags |= Dbadname;
          166 
          167         if(strcmp(d->name, "_conform.map") == 0)
          168                 d->flags |= Dbadname;
          169 
          170         for(i=0; i<d->nchild; i++)
          171                 _checknames(&d->child[i], isbadname, 0);
          172 }
          173 
          174 void
          175 checknames(Direc *d, int (*isbadname)(char*))
          176 {
          177         _checknames(d, isbadname, 1);
          178 }
          179 
          180 /*
          181  * Set the names to conform to 8.3
          182  * by changing them to numbers.
          183  * Plan 9 gets the right names from its
          184  * own directory entry.
          185  *
          186  * We used to write a _conform.map file to translate
          187  * names.  Joliet should take care of most of the
          188  * interoperability with other systems now.
          189  */
          190 void
          191 convertnames(Direc *d, char* (*cvt)(char*, char*))
          192 {
          193         int i;
          194         char new[1024];
          195 
          196         if(d->flags & Dbadname)
          197                 cvt(new, conform(d->name, d->mode & DMDIR));
          198         else
          199                 cvt(new, d->name);
          200         d->confname = atom(new);
          201 
          202         for(i=0; i<d->nchild; i++)
          203                 convertnames(&d->child[i], cvt);
          204 }
          205 
          206 /*
          207  * Sort a directory with a given comparison function.
          208  * After this is called on a tree, adddirec should not be,
          209  * since the entries may no longer be sorted as adddirec expects.
          210  */
          211 void
          212 dsort(Direc *d, int (*cmp)(const void*, const void*))
          213 {
          214         int i, n;
          215 
          216         n = d->nchild;
          217         qsort(d->child, n, sizeof(d[0]), cmp);
          218 
          219         for(i=0; i<n; i++)
          220                 dsort(&d->child[i], cmp);
          221 }