2 * Copyright (c) 2000 Adrian Sun
3 * All Rights Reserved. See COPYRIGHT.
5 * codepage support (based initially on some code from
9 * for single-byte maps, the codepage support devolves to a lookup
10 * table for all possible 8-bit values. for double-byte maps,
11 * the first byte is used as a hash index followed by a linked list of
14 * the badumap specifies illegal characters. these are 8-bit values
15 * with an associated rule field. here are the rules:
18 * illegal values: 0 is the only illegal value. no translation will
19 * occur in those cases.
29 #include <sys/types.h>
35 #include <netatalk/endian.h>
43 /* deal with linked lists */
44 #define CP_INIT(a) (a)->next = (a)->prev = (a)
45 #define CP_ADD(a, b) do { \
46 (b)->next = (a)->next; \
50 #define CP_REMOVE(a) do { \
51 (a)->prev->next = (a)->next; \
52 (a)->next->prev = (a)->prev; \
55 /* search for stuff */
57 static __inline__ unsigned char *codepage_find(struct codepage *page,
63 static int add_code(struct codepage *page, unsigned char *from,
66 union codepage_val *ptr;
68 if (page->quantum < 1) /* no quantum given. don't do anything */
71 if (page->quantum == 1) {
72 page->map[*from].value = *to;
77 if (ptr = codepage_find(page->map, from)) {
81 ptr = map[*from].hash;
83 space = (unsigned char *) malloc(sizeof(unsigned char)*quantum);
93 static struct codepage *init_codepage(const int quantum)
97 cp = (struct codepage *) malloc(sizeof(struct codepage));
101 if ((cp->map = (union codepage_val *)
102 calloc(MAPSIZE, sizeof(union codepage_val))) == NULL) {
107 cp->quantum = quantum;
112 static void free_codepage(struct codepage *cp)
120 if (cp->quantum > 1) {
121 /* deal with any linked lists that may exist */
122 for (i = 0; i < MAPSIZE; i++) {
123 struct codepage_hash *ptr, *h;
125 h = &cp->map[i].hash; /* we don't free this one */
126 while ((ptr = h->prev) != h) {
139 /* this is used by both codepages and generic mapping utilities. we
140 * allocate enough space to map all 8-bit characters if necessary.
141 * for double-byte mappings, we just use the table as a hash lookup.
142 * if we don't match, we don't convert.
144 int codepage_init(struct vol *vol, const int rules,
147 if ((rules & CODEPAGE_RULE_MTOU) && !vol->v_utompage) {
148 vol->v_utompage = init_codepage(quantum);
149 if (!vol->v_utompage)
153 if ((rules & CODEPAGE_RULE_UTOM) && !vol->v_mtoupage) {
154 vol->v_mtoupage = init_codepage(quantum);
155 if (!vol->v_mtoupage) {
160 if ((rules & CODEPAGE_RULE_BADU) && !vol->v_badumap) {
161 vol->v_badumap = init_codepage(quantum);
168 free_codepage(vol->v_mtoupage);
169 vol->v_mtoupage = NULL;
172 free_codepage(vol->v_utompage);
173 vol->v_utompage = NULL;
177 void codepage_free(struct vol *vol)
179 if (vol->v_utompage) {
180 free_codepage(vol->v_utompage);
181 vol->v_utompage = NULL;
184 if (vol->v_mtoupage) {
185 free_codepage(vol->v_mtoupage);
186 vol->v_mtoupage = NULL;
189 if (vol->v_badumap) {
190 free_codepage(vol->v_badumap);
191 vol->v_badumap = NULL;
196 int codepage_read(struct vol *vol, const char *path)
198 unsigned char buf[CODEPAGE_FILE_HEADER_SIZE], *cur;
200 int fd, i, quantum, rules;
202 if ((fd = open(path, O_RDONLY)) < 0) {
203 syslog(LOG_ERR, "%s: failed to open codepage", path);
207 /* Read the codepage file header. */
208 if(read(fd, buf, sizeof(buf)) != sizeof(buf)) {
209 syslog( LOG_ERR, "%s: failed to read codepage header", path);
213 /* Check the file id */
215 memcpy(&id, cur, sizeof(id));
218 if (id != CODEPAGE_FILE_ID) {
219 syslog( LOG_ERR, "%s: not a codepage", path);
223 /* check the version number */
224 if (*cur++ != CODEPAGE_FILE_VERSION) {
225 syslog( LOG_ERR, "%s: codepage version not supported", path);
229 /* find out the data quantum size. default to 1 if nothing's given. */
230 quantum = *cur ? *cur : 1;
233 /* rules used in this file. */
236 if (codepage_init(vol, rules, quantum) < 0) {
237 syslog( LOG_ERR, "%s: Unable to allocate memory", path);
243 /* skip to the start of the data */
244 memcpy(&id, cur , sizeof(id));
246 lseek(fd, id, SEEK_SET);
248 /* mtoupage is the the equivalent of samba's unix2dos. utompage is
249 * the equivalent of dos2unix. it's a little confusing due to a
250 * desire to match up with mtoupath and utompath.
251 * NOTE: we allow codepages to specify 7-bit mappings if they want.
254 while (read(fd, buf, i) == i) {
255 if (*buf & CODEPAGE_RULE_MTOU) {
256 if (add_code(vol->v_mtoupage, buf + 1, buf + 1 + quantum) < 0) {
257 syslog(LOG_ERR, "unable to allocate memory for mtoupage");
262 if (*buf & CODEPAGE_RULE_UTOM) {
263 if (add_code(vol->v_utompage, buf + 1 + quantum, buf + 1) < 0) {
264 syslog(LOG_ERR, "unable to allocate memory for utompage");
269 /* we only look at the first character here. if we need to
270 * do so, we can always use the quantum to expand the
271 * available flags. */
272 if (*buf & CODEPAGE_RULE_BADU)
273 vol->v_badumap->map[*(buf + 1)].value = *(buf + 1 + quantum);