Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <libsec.h>
6 #include "iso9660.h"
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 }
25 static int
26 strecmp(char *a, char *ea, char *b)
27 {
28 int r;
30 if((r = strncmp(a, b, ea-a)) != 0)
31 return r;
33 if(b[ea-a] == '\0')
34 return 0;
35 return 1;
36 }
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;
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 }
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;
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);
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 }
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;
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;
108 *p = '/';
109 p++;
110 } else
111 p = name;
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;
121 if(root->nchild%Ndirblock == 0) {
122 root->child = erealloc(root->child, (root->nchild+Ndirblock)*sizeof(Direc));
123 nd = root->child + off;
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;
133 /*
134 * Copy the tree src into dst.
135 */
136 void
137 copydirec(Direc *dst, Direc *src)
139 int i, n;
141 *dst = *src;
143 if((src->mode & DMDIR) == 0)
144 return;
146 n = (src->nchild + Ndirblock - 1);
147 n -= n%Ndirblock;
148 dst->child = emalloc(n*sizeof(Direc));
150 n = dst->nchild;
151 for(i=0; i<n; i++)
152 copydirec(&dst->child[i], &src->child[i]);
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)
162 int i;
164 if(!isroot && isbadname(d->name))
165 d->flags |= Dbadname;
167 if(strcmp(d->name, "_conform.map") == 0)
168 d->flags |= Dbadname;
170 for(i=0; i<d->nchild; i++)
171 _checknames(&d->child[i], isbadname, 0);
174 void
175 checknames(Direc *d, int (*isbadname)(char*))
177 _checknames(d, isbadname, 1);
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.
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*))
193 int i;
194 char new[1024];
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);
202 for(i=0; i<d->nchild; i++)
203 convertnames(&d->child[i], cvt);
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*))
214 int i, n;
216 n = d->nchild;
217 qsort(d->child, n, sizeof(d[0]), cmp);
219 for(i=0; i<n; i++)
220 dsort(&d->child[i], cmp);