Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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