180ee5cbfSDavid du Colombier #include <u.h>
280ee5cbfSDavid du Colombier #include <libc.h>
380ee5cbfSDavid du Colombier #include <bio.h>
480ee5cbfSDavid du Colombier #include <libsec.h>
580ee5cbfSDavid du Colombier
680ee5cbfSDavid du Colombier #include "iso9660.h"
780ee5cbfSDavid du Colombier
880ee5cbfSDavid du Colombier void
mkdirec(Direc * direc,XDir * d)980ee5cbfSDavid du Colombier mkdirec(Direc *direc, XDir *d)
1080ee5cbfSDavid du Colombier {
1180ee5cbfSDavid du Colombier memset(direc, 0, sizeof(Direc));
1280ee5cbfSDavid du Colombier direc->name = atom(d->name);
1380ee5cbfSDavid du Colombier direc->uid = atom(d->uid);
1480ee5cbfSDavid du Colombier direc->gid = atom(d->gid);
1580ee5cbfSDavid du Colombier direc->uidno = d->uidno;
1680ee5cbfSDavid du Colombier direc->gidno = d->gidno;
1780ee5cbfSDavid du Colombier direc->mode = d->mode;
1880ee5cbfSDavid du Colombier direc->length = d->length;
1980ee5cbfSDavid du Colombier direc->mtime = d->mtime;
2080ee5cbfSDavid du Colombier direc->atime = d->atime;
2180ee5cbfSDavid du Colombier direc->ctime = d->ctime;
2280ee5cbfSDavid du Colombier direc->symlink = d->symlink;
2380ee5cbfSDavid du Colombier }
2480ee5cbfSDavid du Colombier
259a747e4fSDavid du Colombier static int
strecmp(char * a,char * ea,char * b)269a747e4fSDavid du Colombier strecmp(char *a, char *ea, char *b)
279a747e4fSDavid du Colombier {
289a747e4fSDavid du Colombier int r;
299a747e4fSDavid du Colombier
309a747e4fSDavid du Colombier if((r = strncmp(a, b, ea-a)) != 0)
319a747e4fSDavid du Colombier return r;
329a747e4fSDavid du Colombier
339a747e4fSDavid du Colombier if(b[ea-a] == '\0')
349a747e4fSDavid du Colombier return 0;
359a747e4fSDavid du Colombier return 1;
369a747e4fSDavid du Colombier }
379a747e4fSDavid du Colombier
3880ee5cbfSDavid du Colombier /*
3980ee5cbfSDavid du Colombier * Binary search a list of directories for the
4080ee5cbfSDavid du Colombier * entry with name name.
4180ee5cbfSDavid du Colombier * If no entry is found, return a pointer to
4280ee5cbfSDavid du Colombier * where a new such entry would go.
4380ee5cbfSDavid du Colombier */
4480ee5cbfSDavid du Colombier static Direc*
dbsearch(char * name,int nname,Direc * d,int n)459a747e4fSDavid du Colombier dbsearch(char *name, int nname, Direc *d, int n)
4680ee5cbfSDavid du Colombier {
4780ee5cbfSDavid du Colombier int i;
489a747e4fSDavid du Colombier
4980ee5cbfSDavid du Colombier while(n > 0) {
509a747e4fSDavid du Colombier i = strecmp(name, name+nname, d[n/2].name);
5180ee5cbfSDavid du Colombier if(i < 0)
5280ee5cbfSDavid du Colombier n = n/2;
5380ee5cbfSDavid du Colombier else if(i > 0) {
5480ee5cbfSDavid du Colombier d += n/2+1;
5580ee5cbfSDavid du Colombier n -= (n/2+1);
5680ee5cbfSDavid du Colombier } else
5780ee5cbfSDavid du Colombier return &d[n/2];
5880ee5cbfSDavid du Colombier }
5980ee5cbfSDavid du Colombier return d;
6080ee5cbfSDavid du Colombier }
6180ee5cbfSDavid du Colombier
6280ee5cbfSDavid du Colombier /*
6380ee5cbfSDavid du Colombier * Walk to name, starting at d.
6480ee5cbfSDavid du Colombier */
6580ee5cbfSDavid du Colombier Direc*
walkdirec(Direc * d,char * name)6680ee5cbfSDavid du Colombier walkdirec(Direc *d, char *name)
6780ee5cbfSDavid du Colombier {
689a747e4fSDavid du Colombier char *p, *nextp, *slashp;
6980ee5cbfSDavid du Colombier Direc *nd;
7080ee5cbfSDavid du Colombier
7180ee5cbfSDavid du Colombier for(p=name; p && *p; p=nextp) {
729a747e4fSDavid du Colombier if((slashp = strchr(p, '/')) != nil)
739a747e4fSDavid du Colombier nextp = slashp+1;
749a747e4fSDavid du Colombier else
759a747e4fSDavid du Colombier nextp = slashp = p+strlen(p);
7680ee5cbfSDavid du Colombier
779a747e4fSDavid du Colombier nd = dbsearch(p, slashp-p, d->child, d->nchild);
789a747e4fSDavid du Colombier if(nd >= d->child+d->nchild || strecmp(p, slashp, nd->name) != 0)
7980ee5cbfSDavid du Colombier return nil;
8080ee5cbfSDavid du Colombier d = nd;
8180ee5cbfSDavid du Colombier }
8280ee5cbfSDavid du Colombier return d;
8380ee5cbfSDavid du Colombier }
8480ee5cbfSDavid du Colombier
8580ee5cbfSDavid du Colombier /*
8680ee5cbfSDavid du Colombier * Add the file ``name'' with attributes d to the
8780ee5cbfSDavid du Colombier * directory ``root''. Name may contain multiple
8880ee5cbfSDavid du Colombier * elements; all but the last must exist already.
8980ee5cbfSDavid du Colombier *
9080ee5cbfSDavid du Colombier * The child lists are kept sorted by utfname.
9180ee5cbfSDavid du Colombier */
9280ee5cbfSDavid du Colombier Direc*
adddirec(Direc * root,char * name,XDir * d)9380ee5cbfSDavid du Colombier adddirec(Direc *root, char *name, XDir *d)
9480ee5cbfSDavid du Colombier {
9580ee5cbfSDavid du Colombier char *p;
9680ee5cbfSDavid du Colombier Direc *nd;
9780ee5cbfSDavid du Colombier int off;
9880ee5cbfSDavid du Colombier
9980ee5cbfSDavid du Colombier if(name[0] == '/')
10080ee5cbfSDavid du Colombier name++;
10180ee5cbfSDavid du Colombier if((p = strrchr(name, '/')) != nil) {
10280ee5cbfSDavid du Colombier *p = '\0';
10380ee5cbfSDavid du Colombier root = walkdirec(root, name);
10480ee5cbfSDavid du Colombier if(root == nil) {
105*14cc0f53SDavid du Colombier sysfatal("error in proto file: no entry for /%s but /%s/%s", name, name, p+1);
10680ee5cbfSDavid du Colombier return nil;
10780ee5cbfSDavid du Colombier }
10880ee5cbfSDavid du Colombier *p = '/';
10980ee5cbfSDavid du Colombier p++;
11080ee5cbfSDavid du Colombier } else
11180ee5cbfSDavid du Colombier p = name;
11280ee5cbfSDavid du Colombier
1139a747e4fSDavid du Colombier nd = dbsearch(p, strlen(p), root->child, root->nchild);
11480ee5cbfSDavid du Colombier off = nd - root->child;
11580ee5cbfSDavid du Colombier if(off < root->nchild && strcmp(nd->name, p) == 0) {
1169a747e4fSDavid du Colombier if ((d->mode & DMDIR) == 0)
11780ee5cbfSDavid du Colombier fprint(2, "warning: proto lists %s twice\n", name);
11880ee5cbfSDavid du Colombier return nil;
11980ee5cbfSDavid du Colombier }
12080ee5cbfSDavid du Colombier
12180ee5cbfSDavid du Colombier if(root->nchild%Ndirblock == 0) {
12280ee5cbfSDavid du Colombier root->child = erealloc(root->child, (root->nchild+Ndirblock)*sizeof(Direc));
12380ee5cbfSDavid du Colombier nd = root->child + off;
12480ee5cbfSDavid du Colombier }
12580ee5cbfSDavid du Colombier
12680ee5cbfSDavid du Colombier memmove(nd+1, nd, (root->nchild - off)*sizeof(Direc));
12780ee5cbfSDavid du Colombier mkdirec(nd, d);
12880ee5cbfSDavid du Colombier nd->name = atom(p);
12980ee5cbfSDavid du Colombier root->nchild++;
13080ee5cbfSDavid du Colombier return nd;
13180ee5cbfSDavid du Colombier }
13280ee5cbfSDavid du Colombier
13380ee5cbfSDavid du Colombier /*
13480ee5cbfSDavid du Colombier * Copy the tree src into dst.
13580ee5cbfSDavid du Colombier */
13680ee5cbfSDavid du Colombier void
copydirec(Direc * dst,Direc * src)13780ee5cbfSDavid du Colombier copydirec(Direc *dst, Direc *src)
13880ee5cbfSDavid du Colombier {
13980ee5cbfSDavid du Colombier int i, n;
14080ee5cbfSDavid du Colombier
14180ee5cbfSDavid du Colombier *dst = *src;
14280ee5cbfSDavid du Colombier
1439a747e4fSDavid du Colombier if((src->mode & DMDIR) == 0)
14480ee5cbfSDavid du Colombier return;
14580ee5cbfSDavid du Colombier
14680ee5cbfSDavid du Colombier n = (src->nchild + Ndirblock - 1);
14780ee5cbfSDavid du Colombier n -= n%Ndirblock;
14880ee5cbfSDavid du Colombier dst->child = emalloc(n*sizeof(Direc));
14980ee5cbfSDavid du Colombier
15080ee5cbfSDavid du Colombier n = dst->nchild;
15180ee5cbfSDavid du Colombier for(i=0; i<n; i++)
15280ee5cbfSDavid du Colombier copydirec(&dst->child[i], &src->child[i]);
15380ee5cbfSDavid du Colombier }
15480ee5cbfSDavid du Colombier
15580ee5cbfSDavid du Colombier /*
15680ee5cbfSDavid du Colombier * Turn the Dbadname flag on for any entries
15780ee5cbfSDavid du Colombier * that have non-conforming names.
15880ee5cbfSDavid du Colombier */
15980ee5cbfSDavid du Colombier static void
_checknames(Direc * d,int (* isbadname)(char *),int isroot)16080ee5cbfSDavid du Colombier _checknames(Direc *d, int (*isbadname)(char*), int isroot)
16180ee5cbfSDavid du Colombier {
16280ee5cbfSDavid du Colombier int i;
16380ee5cbfSDavid du Colombier
16480ee5cbfSDavid du Colombier if(!isroot && isbadname(d->name))
16580ee5cbfSDavid du Colombier d->flags |= Dbadname;
16680ee5cbfSDavid du Colombier
16780ee5cbfSDavid du Colombier if(strcmp(d->name, "_conform.map") == 0)
16880ee5cbfSDavid du Colombier d->flags |= Dbadname;
16980ee5cbfSDavid du Colombier
17080ee5cbfSDavid du Colombier for(i=0; i<d->nchild; i++)
17180ee5cbfSDavid du Colombier _checknames(&d->child[i], isbadname, 0);
17280ee5cbfSDavid du Colombier }
17380ee5cbfSDavid du Colombier
17480ee5cbfSDavid du Colombier void
checknames(Direc * d,int (* isbadname)(char *))17580ee5cbfSDavid du Colombier checknames(Direc *d, int (*isbadname)(char*))
17680ee5cbfSDavid du Colombier {
17780ee5cbfSDavid du Colombier _checknames(d, isbadname, 1);
17880ee5cbfSDavid du Colombier }
17980ee5cbfSDavid du Colombier
18080ee5cbfSDavid du Colombier /*
18180ee5cbfSDavid du Colombier * Set the names to conform to 8.3
18280ee5cbfSDavid du Colombier * by changing them to numbers.
18380ee5cbfSDavid du Colombier * Plan 9 gets the right names from its
18480ee5cbfSDavid du Colombier * own directory entry.
18580ee5cbfSDavid du Colombier *
18680ee5cbfSDavid du Colombier * We used to write a _conform.map file to translate
18780ee5cbfSDavid du Colombier * names. Joliet should take care of most of the
18880ee5cbfSDavid du Colombier * interoperability with other systems now.
18980ee5cbfSDavid du Colombier */
19080ee5cbfSDavid du Colombier void
convertnames(Direc * d,char * (* cvt)(char *,char *))19180ee5cbfSDavid du Colombier convertnames(Direc *d, char* (*cvt)(char*, char*))
19280ee5cbfSDavid du Colombier {
19380ee5cbfSDavid du Colombier int i;
19480ee5cbfSDavid du Colombier char new[1024];
19580ee5cbfSDavid du Colombier
19680ee5cbfSDavid du Colombier if(d->flags & Dbadname)
1979a747e4fSDavid du Colombier cvt(new, conform(d->name, d->mode & DMDIR));
19880ee5cbfSDavid du Colombier else
19980ee5cbfSDavid du Colombier cvt(new, d->name);
20080ee5cbfSDavid du Colombier d->confname = atom(new);
20180ee5cbfSDavid du Colombier
20280ee5cbfSDavid du Colombier for(i=0; i<d->nchild; i++)
20380ee5cbfSDavid du Colombier convertnames(&d->child[i], cvt);
20480ee5cbfSDavid du Colombier }
20580ee5cbfSDavid du Colombier
20680ee5cbfSDavid du Colombier /*
20780ee5cbfSDavid du Colombier * Sort a directory with a given comparison function.
20880ee5cbfSDavid du Colombier * After this is called on a tree, adddirec should not be,
20980ee5cbfSDavid du Colombier * since the entries may no longer be sorted as adddirec expects.
21080ee5cbfSDavid du Colombier */
21180ee5cbfSDavid du Colombier void
dsort(Direc * d,int (* cmp)(const void *,const void *))21280ee5cbfSDavid du Colombier dsort(Direc *d, int (*cmp)(const void*, const void*))
21380ee5cbfSDavid du Colombier {
21480ee5cbfSDavid du Colombier int i, n;
21580ee5cbfSDavid du Colombier
21680ee5cbfSDavid du Colombier n = d->nchild;
21780ee5cbfSDavid du Colombier qsort(d->child, n, sizeof(d[0]), cmp);
21880ee5cbfSDavid du Colombier
21980ee5cbfSDavid du Colombier for(i=0; i<n; i++)
22080ee5cbfSDavid du Colombier dsort(&d->child[i], cmp);
22180ee5cbfSDavid du Colombier }
22280ee5cbfSDavid du Colombier
223