]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/codepage.c
apply parts of the netbsd build patch by Patrick Welche <prlw1@newn.cam.ac.uk>, mostl...
[netatalk.git] / etc / afpd / codepage.c
1 /*
2  * $Id: codepage.c,v 1.8 2002-03-24 01:23:40 sibaz Exp $
3  *
4  * Copyright (c) 2000 Adrian Sun
5  * All Rights Reserved. See COPYRIGHT.
6  *
7  * codepage support (based initially on some code from
8  * julian@whistle.com)
9  *
10  * the strategy:
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
14  * values.
15  *
16  * the badumap specifies illegal characters. these are 8-bit values
17  * with an associated rule field. here are the rules:
18  *   
19  * illegal values: 0 is the only illegal value. no translation will
20  * occur in those cases.  
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif /* HAVE_CONFIG_H */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #ifdef HAVE_FCNTL_H
33 #include <fcntl.h>
34 #endif /* HAVE_FCNTL_H */
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif /* HAVE_UNISTD_H */
38 #include <atalk/logger.h>
39
40 #include <netatalk/endian.h>
41
42 #include "globals.h"
43 #include "volume.h"
44 #include "codepage.h"
45
46 #define MAPSIZE 256
47
48 /* deal with linked lists */
49 #define CP_INIT(a) (a)->next = (a)->prev = (a)
50 #define CP_ADD(a, b) do { \
51   (b)->next = (a)->next; \
52   (b)->prev = (a); \
53   (a)->next = (b); \
54 } while (0)
55 #define CP_REMOVE(a) do {  \
56   (a)->prev->next = (a)->next; \
57   (a)->next->prev = (a)->prev; \
58 } while (0)
59
60 /* search for stuff */
61 #if 0
62 static __inline__ unsigned char *codepage_find(struct codepage *page,
63         unsigned char *from)
64 {
65 }
66 #endif
67
68 static int add_code(struct codepage *page, unsigned char *from,
69                     unsigned char *to)
70 {
71 #if 0
72     union codepage_val *ptr;
73 #endif /* 0 */
74
75     if (page->quantum < 1) /* no quantum given. don't do anything */
76         return 1;
77
78     if (page->quantum == 1) {
79         page->map[*from].value = *to;
80         return 0;
81     }
82
83 #if 0
84     if (ptr = codepage_find(page->map, from)) {
85
86     } else {
87         unsigned char *space;
88         ptr = map[*from].hash;
89
90         space = (unsigned char *) malloc(sizeof(unsigned char)*quantum);
91         if (!ptr->from) {
92         } else {
93         }
94
95         map[*from].hash
96     }
97 #endif /* 0 */
98     return 0;
99 }
100
101 static struct codepage *init_codepage(const int quantum)
102 {
103     struct codepage *cp;
104
105     cp = (struct codepage *) malloc(sizeof(struct codepage));
106     if (!cp)
107         return NULL;
108
109     if ((cp->map = (union codepage_val *)
110                    calloc(MAPSIZE, sizeof(union codepage_val))) == NULL) {
111         free(cp);
112         return NULL;
113     }
114
115     cp->quantum = quantum;
116     return cp;
117 }
118
119
120 static void free_codepage(struct codepage *cp)
121 {
122     int i;
123
124     if (!cp)
125         return;
126
127     if (cp->map) {
128         if (cp->quantum > 1) {
129             /* deal with any linked lists that may exist */
130             for (i = 0; i < MAPSIZE; i++) {
131                 struct codepage_hash *ptr, *h;
132
133                 h = &cp->map[i].hash; /* we don't free this one */
134                 while ((ptr = h->prev) != h) {
135                     CP_REMOVE(ptr);
136                     free(ptr);
137                 }
138             }
139         }
140         free(cp->map);
141     }
142     free(cp);
143 }
144
145
146
147 /* this is used by both codepages and generic mapping utilities. we
148  * allocate enough space to map all 8-bit characters if necessary.
149  * for double-byte mappings, we just use the table as a hash lookup.
150  * if we don't match, we don't convert.
151  */
152 int codepage_init(struct vol *vol, const int rules,
153                   const int quantum)
154 {
155     if ((rules & CODEPAGE_RULE_UTOM) && !vol->v_utompage) {
156         vol->v_utompage = init_codepage(quantum);
157         if (!vol->v_utompage)
158             goto err_utompage;
159     }
160
161     if ((rules & CODEPAGE_RULE_MTOU) && !vol->v_mtoupage) {
162         vol->v_mtoupage = init_codepage(quantum);
163         if (!vol->v_mtoupage) {
164             goto err_mtoupage;
165         }
166     }
167
168     if ((rules & CODEPAGE_RULE_BADU)  && !vol->v_badumap) {
169         vol->v_badumap = init_codepage(quantum);
170         if (!vol->v_badumap)
171             goto err_mtoupage;
172     }
173     return 0;
174
175 err_mtoupage:
176     free_codepage(vol->v_mtoupage);
177     vol->v_mtoupage = NULL;
178
179 err_utompage:
180     free_codepage(vol->v_utompage);
181     vol->v_utompage = NULL;
182     return -1;
183 }
184
185 void codepage_free(struct vol *vol)
186 {
187     if (vol->v_utompage) {
188         free_codepage(vol->v_utompage);
189         vol->v_utompage = NULL;
190     }
191
192     if (vol->v_mtoupage) {
193         free_codepage(vol->v_mtoupage);
194         vol->v_mtoupage = NULL;
195     }
196
197     if (vol->v_badumap) {
198         free_codepage(vol->v_badumap);
199         vol->v_badumap = NULL;
200     }
201 }
202
203
204 int codepage_read(struct vol *vol, const char *path)
205 {
206     unsigned char buf[CODEPAGE_FILE_HEADER_SIZE], *cur;
207     u_int16_t id;
208     int fd, i, quantum, rules;
209
210     if ((fd = open(path, O_RDONLY)) < 0) {
211         LOG(log_error, logtype_afpd, "%s: failed to open codepage", path);
212         return -1;
213     }
214
215     /* Read the codepage file header. */
216     if(read(fd, buf, sizeof(buf)) != sizeof(buf)) {
217         LOG(log_error, logtype_afpd, "%s: failed to read codepage header", path);
218         goto codepage_fail;
219     }
220
221     /* Check the file id */
222     cur = buf;
223     memcpy(&id, cur, sizeof(id));
224     cur += sizeof(id);
225     id = ntohs(id);
226     if (id != CODEPAGE_FILE_ID) {
227         LOG(log_error, logtype_afpd, "%s: not a codepage", path);
228         goto codepage_fail;
229     }
230
231     /* check the version number */
232     if (*cur++ != CODEPAGE_FILE_VERSION) {
233         LOG(log_error, logtype_afpd, "%s: codepage version not supported", path);
234         goto codepage_fail;
235     }
236
237     /* ignore namelen */
238     cur++;
239
240     /* find out the data quantum size. default to 1 if nothing's given. */
241     quantum = *cur ? *cur : 1;
242     cur++;
243
244     /* rules used in this file. */
245     rules = *cur++;
246
247     if (codepage_init(vol, rules, quantum) < 0) {
248         LOG(log_error, logtype_afpd, "%s: Unable to allocate memory", path);
249         goto codepage_fail;
250     }
251
252     /* offset to data */
253
254     /* skip to the start of the data */
255     memcpy(&id, cur , sizeof(id));
256     id = ntohs(id);
257     lseek(fd, id, SEEK_SET);
258
259     /* mtoupage is the the equivalent of samba's unix2dos. utompage is
260      * the equivalent of dos2unix. it's a little confusing due to a
261      * desire to match up with mtoupath and utompath. 
262      * NOTE: we allow codepages to specify 7-bit mappings if they want. 
263      */
264     i = 1 + 2*quantum;
265     while (read(fd, buf, i) == i) {
266         if (*buf & CODEPAGE_RULE_MTOU) {
267             if (add_code(vol->v_mtoupage, buf + 1, buf + 1 + quantum) < 0) {
268                 LOG(log_error, logtype_afpd, "unable to allocate memory for mtoupage");
269                 break;
270             }
271         }
272
273         if (*buf & CODEPAGE_RULE_UTOM) {
274             if (add_code(vol->v_utompage, buf + 1 + quantum, buf + 1) < 0) {
275                 LOG(log_error, logtype_afpd, "unable to allocate memory for utompage");
276                 break;
277             }
278         }
279
280         /* we only look at the first character here. if we need to
281          * do so, we can always use the quantum to expand the 
282          * available flags. */
283         if (*buf & CODEPAGE_RULE_BADU)
284             vol->v_badumap->map[*(buf + 1)].value = *(buf + 1 + quantum);
285     }
286     close(fd);
287     return 0;
288
289 codepage_fail:
290     close(fd);
291     return -1;
292 }