aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/9660/conform.c
blob: 530b4d561bd6b7f5517925239758131d55da40f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <libsec.h>
#include <ctype.h>
#include "iso9660.h"

/*
 * We keep an array sorted by bad atom pointer.
 * The theory is that since we don't free memory very often,
 * the array will be mostly sorted already and insertions will
 * usually be near the end, so we won't spend much time
 * keeping it sorted.
 */

/*
 * Binary search a Tx list.
 * If no entry is found, return a pointer to
 * where a new such entry would go.
 */
static Tx*
txsearch(char *atom, Tx *t, int n)
{
	while(n > 0) {
		if(atom < t[n/2].bad)
			n = n/2;
		else if(atom > t[n/2].bad) {
			t += n/2+1;
			n -= (n/2+1);
		} else
			return &t[n/2];
	}
	return t;
}

void
addtx(char *b, char *g)
{
	Tx *t;
	Conform *c;

	if(map == nil)
		map = emalloc(sizeof(*map));
	c = map;

	if(c->nt%32 == 0)
		c->t = erealloc(c->t, (c->nt+32)*sizeof(c->t[0]));
	t = txsearch(b, c->t, c->nt);
	if(t < c->t+c->nt && t->bad == b) {
		fprint(2, "warning: duplicate entry for %s in _conform.map\n", b);
		return;
	}

	if(t != c->t+c->nt)
		memmove(t+1, t, (c->t+c->nt - t)*sizeof(Tx));
	t->bad = b;
	t->good = g;
	c->nt++;
}

char*
conform(char *s, int isdir)
{
	Tx *t;
	char buf[10], *g;
	Conform *c;

	c = map;
	s = atom(s);
	if(c){
		t = txsearch(s, c->t, c->nt);
		if(t < c->t+c->nt && t->bad == s)
			return t->good;
	}

	sprint(buf, "%c%.6d", isdir ? 'D' : 'F', c ? c->nt : 0);
	g = atom(buf);
	addtx(s, g);
	return g;
}

#ifdef NOTUSED
static int
isalldigit(char *s)
{
	while(*s)
		if(!isdigit(*s++))
			return 0;
	return 1;
}
#endif

static int
goodcmp(const void *va, const void *vb)
{
	Tx *a, *b;

	a = (Tx*)va;
	b = (Tx*)vb;
	return strcmp(a->good, b->good);
}

static int
badatomcmp(const void *va, const void *vb)
{
	Tx *a, *b;

	a = (Tx*)va;
	b = (Tx*)vb;
	if(a->good < b->good)
		return -1;
	if(a->good > b->good)
		return 1;
	return 0;
}

void
wrconform(Cdimg *cd, int n, ulong *pblock, ulong *plength)
{
	char buf[1024];
	int i;
	Conform *c;

	c = map;
	*pblock = cd->nextblock;
	if(c==nil || n==c->nt){
		*plength = 0;
		return;
	}

	Cwseek(cd, cd->nextblock*Blocksize);
	qsort(c->t, c->nt, sizeof(c->t[0]), goodcmp);
	for(i=n; i<c->nt; i++) {
		snprint(buf, sizeof buf, "%s %s\n", c->t[i].good, c->t[i].bad);
		Cwrite(cd, buf, strlen(buf));
	}
	qsort(c->t, c->nt, sizeof(c->t[0]), badatomcmp);
	*plength = Cwoffset(cd) - *pblock*Blocksize;
	chat("write _conform.map at %lud+%lud\n", *pblock, *plength);
	Cpadblock(cd);
}