1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <libsec.h>
5 #include <ctype.h>
6 #include "iso9660.h"
7 
8 /*
9  * We keep an array sorted by bad atom pointer.
10  * The theory is that since we don't free memory very often,
11  * the array will be mostly sorted already and insertions will
12  * usually be near the end, so we won't spend much time
13  * keeping it sorted.
14  */
15 
16 /*
17  * Binary search a Tx list.
18  * If no entry is found, return a pointer to
19  * where a new such entry would go.
20  */
21 static Tx*
txsearch(char * atom,Tx * t,int n)22 txsearch(char *atom, Tx *t, int n)
23 {
24 	while(n > 0) {
25 		if(atom < t[n/2].bad)
26 			n = n/2;
27 		else if(atom > t[n/2].bad) {
28 			t += n/2+1;
29 			n -= (n/2+1);
30 		} else
31 			return &t[n/2];
32 	}
33 	return t;
34 }
35 
36 void
addtx(char * b,char * g)37 addtx(char *b, char *g)
38 {
39 	Tx *t;
40 	Conform *c;
41 
42 	if(map == nil)
43 		map = emalloc(sizeof(*map));
44 	c = map;
45 
46 	if(c->nt%32 == 0)
47 		c->t = erealloc(c->t, (c->nt+32)*sizeof(c->t[0]));
48 	t = txsearch(b, c->t, c->nt);
49 	if(t < c->t+c->nt && t->bad == b) {
50 		fprint(2, "warning: duplicate entry for %s in _conform.map\n", b);
51 		return;
52 	}
53 
54 	if(t != c->t+c->nt)
55 		memmove(t+1, t, (c->t+c->nt - t)*sizeof(Tx));
56 	t->bad = b;
57 	t->good = g;
58 	c->nt++;
59 }
60 
61 char*
conform(char * s,int isdir)62 conform(char *s, int isdir)
63 {
64 	Tx *t;
65 	char buf[10], *g;
66 	Conform *c;
67 
68 	c = map;
69 	s = atom(s);
70 	if(c){
71 		t = txsearch(s, c->t, c->nt);
72 		if(t < c->t+c->nt && t->bad == s)
73 			return t->good;
74 	}
75 
76 	sprint(buf, "%c%.6d", isdir ? 'D' : 'F', c ? c->nt : 0);
77 	g = atom(buf);
78 	addtx(s, g);
79 	return g;
80 }
81 
82 #ifdef NOTUSED
83 static int
isalldigit(char * s)84 isalldigit(char *s)
85 {
86 	while(*s)
87 		if(!isdigit(*s++))
88 			return 0;
89 	return 1;
90 }
91 #endif
92 
93 static int
goodcmp(const void * va,const void * vb)94 goodcmp(const void *va, const void *vb)
95 {
96 	Tx *a, *b;
97 
98 	a = (Tx*)va;
99 	b = (Tx*)vb;
100 	return strcmp(a->good, b->good);
101 }
102 
103 static int
badatomcmp(const void * va,const void * vb)104 badatomcmp(const void *va, const void *vb)
105 {
106 	Tx *a, *b;
107 
108 	a = (Tx*)va;
109 	b = (Tx*)vb;
110 	if(a->good < b->good)
111 		return -1;
112 	if(a->good > b->good)
113 		return 1;
114 	return 0;
115 }
116 
117 void
wrconform(Cdimg * cd,int n,ulong * pblock,ulong * plength)118 wrconform(Cdimg *cd, int n, ulong *pblock, ulong *plength)
119 {
120 	char buf[1024];
121 	int i;
122 	Conform *c;
123 
124 	c = map;
125 	*pblock = cd->nextblock;
126 	if(c==nil || n==c->nt){
127 		*plength = 0;
128 		return;
129 	}
130 
131 	Cwseek(cd, cd->nextblock*Blocksize);
132 	qsort(c->t, c->nt, sizeof(c->t[0]), goodcmp);
133 	for(i=n; i<c->nt; i++) {
134 		snprint(buf, sizeof buf, "%s %s\n", c->t[i].good, c->t[i].bad);
135 		Cwrite(cd, buf, strlen(buf));
136 	}
137 	qsort(c->t, c->nt, sizeof(c->t[0]), badatomcmp);
138 	*plength = Cwoffset(cd) - *pblock*Blocksize;
139 	chat("write _conform.map at %lud+%lud\n", *pblock, *plength);
140 	Cpadblock(cd);
141 }
142