2 * $Id: codepage.c,v 1.4 2001-05-31 18:48:32 srittau Exp $
4 * Copyright (c) 2000 Adrian Sun
5 * All Rights Reserved. See COPYRIGHT.
7 * codepage support (based initially on some code from
11 * for single-byte maps, the codepage support devolves to a lookup
12 * table for all possible 8-bit values. for double-byte maps,
13 * the first byte is used as a hash index followed by a linked list of
16 * the badumap specifies illegal characters. these are 8-bit values
17 * with an associated rule field. here are the rules:
19 * illegal values: 0 is the only illegal value. no translation will
20 * occur in those cases.
30 #include <sys/types.h>
36 #include <netatalk/endian.h>
44 /* deal with linked lists */
45 #define CP_INIT(a) (a)->next = (a)->prev = (a)
46 #define CP_ADD(a, b) do { \
47 (b)->next = (a)->next; \
51 #define CP_REMOVE(a) do { \
52 (a)->prev->next = (a)->next; \
53 (a)->next->prev = (a)->prev; \
56 /* search for stuff */
58 static __inline__ unsigned char *codepage_find(struct codepage *page,
64 static int add_code(struct codepage *page, unsigned char *from,
68 union codepage_val *ptr;
71 if (page->quantum < 1) /* no quantum given. don't do anything */
74 if (page->quantum == 1) {
75 page->map[*from].value = *to;
80 if (ptr = codepage_find(page->map, from)) {
84 ptr = map[*from].hash;
86 space = (unsigned char *) malloc(sizeof(unsigned char)*quantum);
97 static struct codepage *init_codepage(const int quantum)
101 cp = (struct codepage *) malloc(sizeof(struct codepage));
105 if ((cp->map = (union codepage_val *)
106 calloc(MAPSIZE, sizeof(union codepage_val))) == NULL) {
111 cp->quantum = quantum;
116 static void free_codepage(struct codepage *cp)
124 if (cp->quantum > 1) {
125 /* deal with any linked lists that may exist */
126 for (i = 0; i < MAPSIZE; i++) {
127 struct codepage_hash *ptr, *h;
129 h = &cp->map[i].hash; /* we don't free this one */
130 while ((ptr = h->prev) != h) {
143 /* this is used by both codepages and generic mapping utilities. we
144 * allocate enough space to map all 8-bit characters if necessary.
145 * for double-byte mappings, we just use the table as a hash lookup.
146 * if we don't match, we don't convert.
148 int codepage_init(struct vol *vol, const int rules,
151 if ((rules & CODEPAGE_RULE_UTOM) && !vol->v_utompage) {
152 vol->v_utompage = init_codepage(quantum);
153 if (!vol->v_utompage)
157 if ((rules & CODEPAGE_RULE_MTOU) && !vol->v_mtoupage) {
158 vol->v_mtoupage = init_codepage(quantum);
159 if (!vol->v_mtoupage) {
164 if ((rules & CODEPAGE_RULE_BADU) && !vol->v_badumap) {
165 vol->v_badumap = init_codepage(quantum);
172 free_codepage(vol->v_mtoupage);
173 vol->v_mtoupage = NULL;
176 free_codepage(vol->v_utompage);
177 vol->v_utompage = NULL;
181 void codepage_free(struct vol *vol)
183 if (vol->v_utompage) {
184 free_codepage(vol->v_utompage);
185 vol->v_utompage = NULL;
188 if (vol->v_mtoupage) {
189 free_codepage(vol->v_mtoupage);
190 vol->v_mtoupage = NULL;
193 if (vol->v_badumap) {
194 free_codepage(vol->v_badumap);
195 vol->v_badumap = NULL;
200 int codepage_read(struct vol *vol, const char *path)
202 unsigned char buf[CODEPAGE_FILE_HEADER_SIZE], *cur;
204 int fd, i, quantum, rules;
206 if ((fd = open(path, O_RDONLY)) < 0) {
207 syslog(LOG_ERR, "%s: failed to open codepage", path);
211 /* Read the codepage file header. */
212 if(read(fd, buf, sizeof(buf)) != sizeof(buf)) {
213 syslog( LOG_ERR, "%s: failed to read codepage header", path);
217 /* Check the file id */
219 memcpy(&id, cur, sizeof(id));
222 if (id != CODEPAGE_FILE_ID) {
223 syslog( LOG_ERR, "%s: not a codepage", path);
227 /* check the version number */
228 if (*cur++ != CODEPAGE_FILE_VERSION) {
229 syslog( LOG_ERR, "%s: codepage version not supported", path);
236 /* find out the data quantum size. default to 1 if nothing's given. */
237 quantum = *cur ? *cur : 1;
240 /* rules used in this file. */
243 if (codepage_init(vol, rules, quantum) < 0) {
244 syslog( LOG_ERR, "%s: Unable to allocate memory", path);
250 /* skip to the start of the data */
251 memcpy(&id, cur , sizeof(id));
253 lseek(fd, id, SEEK_SET);
255 /* mtoupage is the the equivalent of samba's unix2dos. utompage is
256 * the equivalent of dos2unix. it's a little confusing due to a
257 * desire to match up with mtoupath and utompath.
258 * NOTE: we allow codepages to specify 7-bit mappings if they want.
261 while (read(fd, buf, i) == i) {
262 if (*buf & CODEPAGE_RULE_MTOU) {
263 if (add_code(vol->v_mtoupage, buf + 1, buf + 1 + quantum) < 0) {
264 syslog(LOG_ERR, "unable to allocate memory for mtoupage");
269 if (*buf & CODEPAGE_RULE_UTOM) {
270 if (add_code(vol->v_utompage, buf + 1 + quantum, buf + 1) < 0) {
271 syslog(LOG_ERR, "unable to allocate memory for utompage");
276 /* we only look at the first character here. if we need to
277 * do so, we can always use the quantum to expand the
278 * available flags. */
279 if (*buf & CODEPAGE_RULE_BADU)
280 vol->v_badumap->map[*(buf + 1)].value = *(buf + 1 + quantum);