]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/disk/9660/direc.c
merge
[plan9front.git] / sys / src / cmd / disk / 9660 / direc.c
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", 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 }
222