]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/codepage.c
implemented config.h
[netatalk.git] / etc / afpd / codepage.c
1 /*
2  * Copyright (c) 2000 Adrian Sun
3  * All Rights Reserved. See COPYRIGHT.
4  *
5  * codepage support (based initially on some code from
6  * julian@whistle.com)
7  *
8  * the strategy:
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
12  * values.
13  *
14  * the badumap specifies illegal characters. these are 8-bit values
15  * with an associated rule field. here are the rules:
16  *   
17  *
18  * illegal values: 0 is the only illegal value. no translation will
19  * occur in those cases.  
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <syslog.h>
34
35 #include <netatalk/endian.h>
36
37 #include "globals.h"
38 #include "volume.h"
39 #include "codepage.h"
40
41 #define MAPSIZE 256
42
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; \
47   (b)->prev = (a); \
48   (a)->next = (b); \
49 } while (0)
50 #define CP_REMOVE(a) do {  \
51   (a)->prev->next = (a)->next; \
52   (a)->next->prev = (a)->prev; \
53 } while (0)
54
55 /* search for stuff */
56 #if 0
57 static __inline__ unsigned char *codepage_find(struct codepage *page,
58                                                unsigned char *from)
59 {
60 }
61 #endif
62
63 static int add_code(struct codepage *page, unsigned char *from,
64                     unsigned char *to)
65 {
66   union codepage_val *ptr;
67
68   if (page->quantum < 1) /* no quantum given. don't do anything */
69     return 1;
70
71   if (page->quantum == 1) {
72     page->map[*from].value = *to;
73     return 0;
74   }
75
76 #if 0
77   if (ptr = codepage_find(page->map, from)) {
78     
79   } else {
80     unsigned char *space;
81     ptr = map[*from].hash;
82
83     space = (unsigned char *) malloc(sizeof(unsigned char)*quantum);
84     if (!ptr->from) {
85     } else {
86     }
87     
88     map[*from].hash
89   }
90 #endif
91 }
92
93 static struct codepage *init_codepage(const int quantum)
94 {
95     struct codepage *cp;
96
97     cp = (struct codepage *) malloc(sizeof(struct codepage));
98     if (!cp)
99       return NULL;
100
101     if ((cp->map = (union codepage_val *)
102          calloc(MAPSIZE, sizeof(union codepage_val))) == NULL) {
103       free(cp);
104       return NULL;
105     }
106
107     cp->quantum = quantum;
108     return cp;
109 }
110
111
112 static void free_codepage(struct codepage *cp)
113 {
114   int i;
115
116   if (!cp)
117     return;
118
119   if (cp->map) {
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;
124         
125         h = &cp->map[i].hash; /* we don't free this one */
126         while ((ptr = h->prev) != h) {
127           CP_REMOVE(ptr);
128           free(ptr);
129         }
130       }
131     }
132     free(cp->map);
133   }
134   free(cp);
135 }
136
137
138
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.
143  */
144 int codepage_init(struct vol *vol, const int rules, 
145                   const int quantum)
146 {
147   if ((rules & CODEPAGE_RULE_MTOU) && !vol->v_utompage) {
148     vol->v_utompage = init_codepage(quantum);
149     if (!vol->v_utompage)
150       return -1;
151   }
152
153   if ((rules & CODEPAGE_RULE_UTOM) && !vol->v_mtoupage) {
154     vol->v_mtoupage = init_codepage(quantum);
155     if (!vol->v_mtoupage) {
156       goto err_utompage;
157     }
158   }
159
160   if ((rules & CODEPAGE_RULE_BADU)  && !vol->v_badumap) {
161     vol->v_badumap = init_codepage(quantum);
162     if (!vol->v_badumap)
163       goto err_mtoupage;
164   }
165   return 0;
166
167 err_mtoupage:
168     free_codepage(vol->v_mtoupage);
169     vol->v_mtoupage = NULL;
170
171 err_utompage:
172     free_codepage(vol->v_utompage);
173     vol->v_utompage = NULL;
174     return -1;
175 }
176
177 void codepage_free(struct vol *vol)
178 {
179   if (vol->v_utompage) {
180     free_codepage(vol->v_utompage);
181     vol->v_utompage = NULL;
182   }
183
184   if (vol->v_mtoupage) {
185     free_codepage(vol->v_mtoupage);
186     vol->v_mtoupage = NULL;
187   }
188
189   if (vol->v_badumap) {
190     free_codepage(vol->v_badumap);
191     vol->v_badumap = NULL;
192   }
193 }
194
195
196 int codepage_read(struct vol *vol, const char *path)
197 {
198   unsigned char buf[CODEPAGE_FILE_HEADER_SIZE], *cur;
199   u_int16_t id;
200   int fd, i, quantum, rules;
201   
202   if ((fd = open(path, O_RDONLY)) < 0) {
203     syslog(LOG_ERR, "%s: failed to open codepage", path);
204     return -1;
205   }
206   
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);
210     goto codepage_fail;
211   }
212
213   /* Check the file id */
214   cur = buf;
215   memcpy(&id, cur, sizeof(id));
216   cur += sizeof(id);
217   id = ntohs(id);
218   if (id != CODEPAGE_FILE_ID) {
219       syslog( LOG_ERR, "%s: not a codepage", path);
220       goto codepage_fail;
221   } 
222
223   /* check the version number */
224   if (*cur++ != CODEPAGE_FILE_VERSION) {
225       syslog( LOG_ERR, "%s: codepage version not supported", path);
226       goto codepage_fail;
227   } 
228
229   /* find out the data quantum size. default to 1 if nothing's given. */
230   quantum = *cur ? *cur : 1;
231   cur++;
232   
233   /* rules used in this file. */
234   rules = *cur++;
235
236   if (codepage_init(vol, rules, quantum) < 0) {
237     syslog( LOG_ERR, "%s: Unable to allocate memory", path);
238     goto codepage_fail;
239   }
240
241   /* offset to data */
242
243   /* skip to the start of the data */
244   memcpy(&id, cur , sizeof(id));
245   id = ntohs(id);
246   lseek(fd, id, SEEK_SET);
247
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. 
252    */
253   i = 1 + 2*quantum;
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");
258         break;
259       }
260     }
261
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");
265         break;
266       }
267     }
268       
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);
274   }
275   close(fd);
276   return 0;
277
278 codepage_fail:
279   close(fd);
280   return -1;
281 }