2
* $Id: codepage.c,v 1.8 2002/03/24 01:23:40 sibaz 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.
25
#endif /* HAVE_CONFIG_H */
30
#include <sys/types.h>
34
#endif /* HAVE_FCNTL_H */
37
#endif /* HAVE_UNISTD_H */
38
#include <atalk/logger.h>
40
#include <netatalk/endian.h>
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; \
55
#define CP_REMOVE(a) do { \
56
(a)->prev->next = (a)->next; \
57
(a)->next->prev = (a)->prev; \
60
/* search for stuff */
62
static __inline__ unsigned char *codepage_find(struct codepage *page,
68
static int add_code(struct codepage *page, unsigned char *from,
72
union codepage_val *ptr;
75
if (page->quantum < 1) /* no quantum given. don't do anything */
78
if (page->quantum == 1) {
79
page->map[*from].value = *to;
84
if (ptr = codepage_find(page->map, from)) {
88
ptr = map[*from].hash;
90
space = (unsigned char *) malloc(sizeof(unsigned char)*quantum);
101
static struct codepage *init_codepage(const int quantum)
105
cp = (struct codepage *) malloc(sizeof(struct codepage));
109
if ((cp->map = (union codepage_val *)
110
calloc(MAPSIZE, sizeof(union codepage_val))) == NULL) {
115
cp->quantum = quantum;
120
static void free_codepage(struct codepage *cp)
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;
133
h = &cp->map[i].hash; /* we don't free this one */
134
while ((ptr = h->prev) != h) {
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.
152
int codepage_init(struct vol *vol, const int rules,
155
if ((rules & CODEPAGE_RULE_UTOM) && !vol->v_utompage) {
156
vol->v_utompage = init_codepage(quantum);
157
if (!vol->v_utompage)
161
if ((rules & CODEPAGE_RULE_MTOU) && !vol->v_mtoupage) {
162
vol->v_mtoupage = init_codepage(quantum);
163
if (!vol->v_mtoupage) {
168
if ((rules & CODEPAGE_RULE_BADU) && !vol->v_badumap) {
169
vol->v_badumap = init_codepage(quantum);
176
free_codepage(vol->v_mtoupage);
177
vol->v_mtoupage = NULL;
180
free_codepage(vol->v_utompage);
181
vol->v_utompage = NULL;
185
void codepage_free(struct vol *vol)
187
if (vol->v_utompage) {
188
free_codepage(vol->v_utompage);
189
vol->v_utompage = NULL;
192
if (vol->v_mtoupage) {
193
free_codepage(vol->v_mtoupage);
194
vol->v_mtoupage = NULL;
197
if (vol->v_badumap) {
198
free_codepage(vol->v_badumap);
199
vol->v_badumap = NULL;
204
int codepage_read(struct vol *vol, const char *path)
206
unsigned char buf[CODEPAGE_FILE_HEADER_SIZE], *cur;
208
int fd, i, quantum, rules;
210
if ((fd = open(path, O_RDONLY)) < 0) {
211
LOG(log_error, logtype_afpd, "%s: failed to open codepage", path);
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);
221
/* Check the file id */
223
memcpy(&id, cur, sizeof(id));
226
if (id != CODEPAGE_FILE_ID) {
227
LOG(log_error, logtype_afpd, "%s: not a codepage", path);
231
/* check the version number */
232
if (*cur++ != CODEPAGE_FILE_VERSION) {
233
LOG(log_error, logtype_afpd, "%s: codepage version not supported", path);
240
/* find out the data quantum size. default to 1 if nothing's given. */
241
quantum = *cur ? *cur : 1;
244
/* rules used in this file. */
247
if (codepage_init(vol, rules, quantum) < 0) {
248
LOG(log_error, logtype_afpd, "%s: Unable to allocate memory", path);
254
/* skip to the start of the data */
255
memcpy(&id, cur , sizeof(id));
257
lseek(fd, id, SEEK_SET);
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.
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");
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");
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);