]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/codepage.c
Joe Clarke's fix for linux/quota.h checking, removed NO_DLFCN_H define
[netatalk.git] / etc / afpd / codepage.c
1 /*
2  * $Id: codepage.c,v 1.4 2001-05-31 18:48:32 srittau 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
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <syslog.h>
35
36 #include <netatalk/endian.h>
37
38 #include "globals.h"
39 #include "volume.h"
40 #include "codepage.h"
41
42 #define MAPSIZE 256
43
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; \
48   (b)->prev = (a); \
49   (a)->next = (b); \
50 } while (0)
51 #define CP_REMOVE(a) do {  \
52   (a)->prev->next = (a)->next; \
53   (a)->next->prev = (a)->prev; \
54 } while (0)
55
56 /* search for stuff */
57 #if 0
58 static __inline__ unsigned char *codepage_find(struct codepage *page,
59                                                unsigned char *from)
60 {
61 }
62 #endif
63
64 static int add_code(struct codepage *page, unsigned char *from,
65                     unsigned char *to)
66 {
67 #if 0
68   union codepage_val *ptr;
69 #endif
70
71   if (page->quantum < 1) /* no quantum given. don't do anything */
72     return 1;
73
74   if (page->quantum == 1) {
75     page->map[*from].value = *to;
76     return 0;
77   }
78
79 #if 0
80   if (ptr = codepage_find(page->map, from)) {
81     
82   } else {
83     unsigned char *space;
84     ptr = map[*from].hash;
85
86     space = (unsigned char *) malloc(sizeof(unsigned char)*quantum);
87     if (!ptr->from) {
88     } else {
89     }
90     
91     map[*from].hash
92   }
93 #endif
94   return 0;
95 }
96
97 static struct codepage *init_codepage(const int quantum)
98 {
99     struct codepage *cp;
100
101     cp = (struct codepage *) malloc(sizeof(struct codepage));
102     if (!cp)
103       return NULL;
104
105     if ((cp->map = (union codepage_val *)
106          calloc(MAPSIZE, sizeof(union codepage_val))) == NULL) {
107       free(cp);
108       return NULL;
109     }
110
111     cp->quantum = quantum;
112     return cp;
113 }
114
115
116 static void free_codepage(struct codepage *cp)
117 {
118   int i;
119
120   if (!cp)
121     return;
122
123   if (cp->map) {
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;
128         
129         h = &cp->map[i].hash; /* we don't free this one */
130         while ((ptr = h->prev) != h) {
131           CP_REMOVE(ptr);
132           free(ptr);
133         }
134       }
135     }
136     free(cp->map);
137   }
138   free(cp);
139 }
140
141
142
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.
147  */
148 int codepage_init(struct vol *vol, const int rules, 
149                   const int quantum)
150 {
151   if ((rules & CODEPAGE_RULE_UTOM) && !vol->v_utompage) {
152     vol->v_utompage = init_codepage(quantum);
153     if (!vol->v_utompage)
154       goto err_utompage;
155   }
156
157   if ((rules & CODEPAGE_RULE_MTOU) && !vol->v_mtoupage) {
158     vol->v_mtoupage = init_codepage(quantum);
159     if (!vol->v_mtoupage) {
160       goto err_mtoupage;
161     }
162   }
163
164   if ((rules & CODEPAGE_RULE_BADU)  && !vol->v_badumap) {
165     vol->v_badumap = init_codepage(quantum);
166     if (!vol->v_badumap)
167       goto err_mtoupage;
168   }
169   return 0;
170
171 err_mtoupage:
172     free_codepage(vol->v_mtoupage);
173     vol->v_mtoupage = NULL;
174
175 err_utompage:
176     free_codepage(vol->v_utompage);
177     vol->v_utompage = NULL;
178     return -1;
179 }
180
181 void codepage_free(struct vol *vol)
182 {
183   if (vol->v_utompage) {
184     free_codepage(vol->v_utompage);
185     vol->v_utompage = NULL;
186   }
187
188   if (vol->v_mtoupage) {
189     free_codepage(vol->v_mtoupage);
190     vol->v_mtoupage = NULL;
191   }
192
193   if (vol->v_badumap) {
194     free_codepage(vol->v_badumap);
195     vol->v_badumap = NULL;
196   }
197 }
198
199
200 int codepage_read(struct vol *vol, const char *path)
201 {
202   unsigned char buf[CODEPAGE_FILE_HEADER_SIZE], *cur;
203   u_int16_t id;
204   int fd, i, quantum, rules;
205   
206   if ((fd = open(path, O_RDONLY)) < 0) {
207     syslog(LOG_ERR, "%s: failed to open codepage", path);
208     return -1;
209   }
210   
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);
214     goto codepage_fail;
215   }
216
217   /* Check the file id */
218   cur = buf;
219   memcpy(&id, cur, sizeof(id));
220   cur += sizeof(id);
221   id = ntohs(id);
222   if (id != CODEPAGE_FILE_ID) {
223       syslog( LOG_ERR, "%s: not a codepage", path);
224       goto codepage_fail;
225   } 
226
227   /* check the version number */
228   if (*cur++ != CODEPAGE_FILE_VERSION) {
229       syslog( LOG_ERR, "%s: codepage version not supported", path);
230       goto codepage_fail;
231   } 
232
233   /* ignore namelen */
234   cur++;
235
236   /* find out the data quantum size. default to 1 if nothing's given. */
237   quantum = *cur ? *cur : 1;
238   cur++;
239   
240   /* rules used in this file. */
241   rules = *cur++;
242
243   if (codepage_init(vol, rules, quantum) < 0) {
244     syslog( LOG_ERR, "%s: Unable to allocate memory", path);
245     goto codepage_fail;
246   }
247
248   /* offset to data */
249
250   /* skip to the start of the data */
251   memcpy(&id, cur , sizeof(id));
252   id = ntohs(id);
253   lseek(fd, id, SEEK_SET);
254
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. 
259    */
260   i = 1 + 2*quantum;
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");
265         break;
266       }
267     }
268
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");
272         break;
273       }
274     }
275       
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);
281   }
282   close(fd);
283   return 0;
284
285 codepage_fail:
286   close(fd);
287   return -1;
288 }