static char rcsid[] = "@(#)$Id: bindata.c,v 1.7 2006/04/09 07:37:08 hurtta Exp $"; /****************************************************************************** * The Elm (ME+) Mail System - $Revision: 1.7 $ $State: Exp $ * * Author: Kari Hurtta *****************************************************************************/ #include "headers.h" #include "mmaputil.h" #include "cs_imp.h" #include "s_me.h" #include "bindata.h" #include #ifndef ANSI_C extern int errno; #endif DEBUG_VAR(Debug,__FILE__,"charset"); static unsigned char * us_str P_((char *str)); static unsigned char * us_str(str) char *str; { return (unsigned char *)str; } #ifdef MMAP #include #ifndef MAP_FAILED #define MAP_FAILED (void *)(-1) #endif #endif #define TEXT_MAGIC "ELMME+\n" /* TEXT_MAGIC is 8 bytes (including \0) */ struct bindata_header_1 { uint8 text_magic[sizeof TEXT_MAGIC]; uint16 magic; uint16 header_size; uint16 page_size; uint16 map_rev_map_div; /* MAP_REV_MAP_DIV */ uint16 csets_size; uint16 csets_pagecount; }; #define MAP_FILENAME_SIZE 32 struct csets_1 { /* both type 'binary' and 'ascii_set' is used same record */ uint8 filename[MAP_FILENAME_SIZE]; /* filename on elm.map.txt zero filled */ uint16 map[256]; /* charset byte to unicode */ uint8 revmap[MAP_REV_MAP_DIV]; /* unicode to charset byte mapping */ }; #define BINDATA_magic 0xFB01 enum bindata_format { bindata_bad = 0, bindata_format_1 = BINDATA_magic }; struct bindata_format_1 { int byte_swapped; int mmapped; struct bindata_header_1 *header; size_t header_length; struct csets_1 *csets; size_t csets_length; off_t csets_offset; int csets_count; }; /* This macro requires ANSI C preprocessor */ #if __STDC__ #define SYSCALL(x) { int ret_=x; int err_=errno;\ if (ret_ == -1) \ DPRINT(Debug,1,(&Debug,"bindata: syscall %s failed: errno=%d (%s)\n", \ #x,err_,error_description(err_))); } #else #define SYSCALL(x) x #endif static void free_bindata_1 P_((struct bindata_format_1 *v)); static void free_bindata_1(v) struct bindata_format_1 *v; { if (!v->mmapped) { /* malloced */ if (v->header_length) free(v->header); if (v->csets_length) free(v->csets); } else { #ifdef MMAP if (v->header_length) SYSCALL(munmap((void *)v->header,v->header_length)); if (v->csets_length) SYSCALL(munmap((void *)v->csets,v->csets_length)); #else panic("BINDATA PANIC",__FILE__,__LINE__,"free_bindata_1", "bindata: Internal error -- mmap not available",0); #endif v->mmapped = 0; } v->header = NULL; v->csets = NULL; v->header_length = 0; v->csets_length = 0; } /* Allocate maximun needed space */ static void malloc_bindata_1 P_((struct bindata_format_1 *v, int cscount)); static void malloc_bindata_1(v,cscount) struct bindata_format_1 *v; int cscount; { #ifdef MMAP uint16 pagesize = getpagesize(); #else uint16 pagesize = 512; #endif uint16 header_pages, csets_pages; v->byte_swapped = 0; /* generated -- not swapped */ v->mmapped = 0; /* malloced -- not mapped */ v->header_length = sizeof (struct bindata_header_1); v->header = safe_malloc(v->header_length); header_pages = pages(v->header_length,pagesize); v->csets_length = cscount * sizeof (struct csets_1); v->csets = safe_malloc(v->csets_length); csets_pages = pages(v->csets_length,pagesize); v->csets_count = 0; v->csets_offset = pagesize * (off_t) header_pages; strfcpy((char *)v->header->text_magic, TEXT_MAGIC,sizeof v->header->text_magic); v->header->magic = bindata_format_1; v->header->header_size = sizeof (struct bindata_header_1); v->header->page_size = pagesize; v->header->map_rev_map_div = MAP_REV_MAP_DIV; v->header->csets_size = sizeof (struct csets_1); v->header->csets_pagecount = csets_pages; } #define READ_VALUE(x,byte_swapped) (byte_swapped ? SWAP(x) : x) static void dump_header P_((struct bindata_format_1 *v, int byte_swapped, CONST char *filename)); static int write_bindata_1 P_((struct bindata_format_1 *v, int fd, CONST char *filename)); static int write_bindata_1(v, fd, filename) struct bindata_format_1 *v; int fd; CONST char *filename; { uint16 pagesize = READ_VALUE(v->header->page_size,v->byte_swapped); uint16 csets_pages = READ_VALUE(v->header->csets_pagecount, v->byte_swapped); if (!write_range(fd,0,v->header_length,(unsigned char*)v->header)) { int err = errno; DPRINT(Debug,1,(&Debug, "bindata: write_range failed: errno=%d (%s)\n", \ err,error_description(err))); lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable, "File %.50s is not writeable: %s"), filename, error_description(err)); return 0; } if (!write_range(fd,v->csets_offset,v->csets_length, (unsigned char *)(v->csets))) { int err = errno; DPRINT(Debug,1,(&Debug, "bindata: write_range failed: errno=%d (%s)\n", \ err,error_description(err))); lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable, "File %.50s is not writeable: %s"), filename, error_description(err)); return 0; } if (v->csets_length < csets_pages * (size_t) pagesize) { /* Be sure that file is big enough */ if (!write_range(fd, v->csets_offset + csets_pages * (off_t) pagesize -1, 1, us_str(" "))) { int err = errno; DPRINT(Debug,1,(&Debug, "bindata: write_range failed: errno=%d (%s)\n", \ err,error_description(err))); lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable, "File %.50s is not writeable: %s"), filename, error_description(err)); return 0; } } dump_header(v,v->byte_swapped,filename); return 1; } static void dump_header(v,byte_swapped,filename) struct bindata_format_1 *v; int byte_swapped; CONST char *filename; { if (v->header) { DPRINT(Debug,40,(&Debug,"============ Header dump: %-15s =======\n", filename)); DPRINT(Debug,40,(&Debug,"BYTE SWAPPED = %d\n",byte_swapped)); DPRINT(Debug,40,(&Debug, "magic %04X header_size %04X page_size %04X\n", READ_VALUE(v->header->magic,v->byte_swapped), READ_VALUE(v->header->header_size,v->byte_swapped), READ_VALUE(v->header->page_size,v->byte_swapped))); DPRINT(Debug,40,(&Debug, "map_rev_map_div %04X csets_size %04X\n", READ_VALUE(v->header->map_rev_map_div,v->byte_swapped), READ_VALUE(v->header->csets_size,v->byte_swapped))); DPRINT(Debug,40,(&Debug, "csets_pagecount %04X\n", READ_VALUE(v->header->csets_pagecount,v->byte_swapped))); DPRINT(Debug,40,(&Debug,"============ End dump: %-15s =======\n", filename)); } } static int calculate_sizes P_((struct bindata_format_1 *v, CONST char *filename)); static int calculate_sizes (v,filename) struct bindata_format_1 *v; CONST char *filename; { uint16 pagesize = READ_VALUE(v->header->page_size,v->byte_swapped); uint16 header_pages, csets_pages; if (READ_VALUE(v->header->header_size,v->byte_swapped) != sizeof (struct bindata_header_1) || READ_VALUE(v->header->csets_size,v->byte_swapped) != sizeof (struct csets_1)) { lib_error(CATGETS(elm_msg_cat, MeSet, MeCorruptedMapfile, "Mapfile %.30s is corrupted"), filename); DPRINT(Debug,1,(&Debug,"calculate_sizes failed #1 -- sizeof check\n")); return 0; } if (READ_VALUE(v->header->map_rev_map_div,v->byte_swapped) != MAP_REV_MAP_DIV) { lib_error(CATGETS(elm_msg_cat, MeSet, MeCorruptedMapfile, "Mapfile %.30s is corrupted"), filename); DPRINT(Debug,1,(&Debug,"calculate_sizes failed #2 -- MAP_REV_MAP_DIV\n")); return 0; } header_pages = pages(v->header_length,pagesize); v->csets_offset = pagesize * (off_t) header_pages; csets_pages = READ_VALUE(v->header->csets_pagecount,v->byte_swapped); v->csets_length = pagesize * (off_t) csets_pages; /* May give too big value */ v->csets_count = v->csets_length / sizeof (struct csets_1); return 1; } static void debug_output P_((struct bindata_format_1 *v, int status, int pagesize, char *str, CONST char *filename)); static void debug_output(v,status,pagesize,str,filename) struct bindata_format_1 *v; int status; int pagesize; char *str; CONST char *filename; { DPRINT(Debug,1,(&Debug, "%s: %s: status=%d, csets_count=%d, pagesize=%d\n", filename,str,status,v->csets_count, pagesize)); DPRINT(Debug,1,(&Debug, "%s: %s: header_length=%d, csets_length=%d,\n", filename,str,v->header_length,v->csets_length)); if (v->header) { DPRINT(Debug,5,(&Debug, "%s: %s: swapped=%d, page_size=%d, csets_pages=%d\n", filename,str,v->byte_swapped, READ_VALUE(v->header->page_size, v->byte_swapped), READ_VALUE(v->header->csets_pagecount, v->byte_swapped))); } } static int read_bindata_1 P_((struct bindata_format_1 *v, int fd, int byte_swapped, CONST char *filename)); static int read_bindata_1(v, fd, byte_swapped, filename) struct bindata_format_1 *v; int fd; int byte_swapped; CONST char *filename; { int status = 0; uint16 pagesize = 0; v->byte_swapped = byte_swapped; v->mmapped = 0; v->header_length = sizeof (struct bindata_header_1); v->header = safe_malloc(v->header_length); if (!read_range(fd,0,v->header_length,(unsigned char*)v->header)) { int err = errno; lib_error(CATGETS(elm_msg_cat, MeSet, MeFileUnreadable, "File %.50s is unreadable: %s"), filename, error_description(err)); status = 0; goto fail_1; } pagesize = READ_VALUE(v->header->page_size,v->byte_swapped); dump_header(v,byte_swapped,filename); if (!calculate_sizes(v,filename)) { status = 0; goto fail_1; } v->csets = safe_malloc(v->csets_length); if (!read_range(fd,v->csets_offset,v->csets_length, (unsigned char *)(v->csets))) { int err = errno; lib_error(CATGETS(elm_msg_cat, MeSet, MeFileUnreadable, "File %.50s is unreadable: %s"), filename, error_description(err)); status = 0; goto fail_2; } status = 1; if (!status) { fail_2: free(v->csets); v->csets = NULL; v->csets_length = 0; fail_1: free(v->header); v->header = NULL; v->header_length = 0; } debug_output(v,status,pagesize,"read",filename); return status; } static int mmap_bindata_1 P_((struct bindata_format_1 *v, int fd, int byte_swapped, CONST char *filename)); static int mmap_bindata_1(v, fd, byte_swapped, filename) struct bindata_format_1 *v; int fd; int byte_swapped; CONST char *filename; { int status = 0; #ifdef MMAP uint16 real_pagesize = getpagesize(); uint16 pagesize = 0; void * result; v->byte_swapped = byte_swapped; v->mmapped = 1; v->header_length = sizeof (struct bindata_header_1); result = mmap(0,v->header_length,PROT_READ,MAP_SHARED,fd,0); if (result == MAP_FAILED) { int err = errno; lib_error(CATGETS(elm_msg_cat, MeSet, MeFailedMMap, "Failed to mmap %.50s: %30s"), filename, error_description(err)); v->header = NULL; v->header_length = 0; status = 0; goto fail_1; } v->header = result; pagesize = READ_VALUE(v->header->page_size,v->byte_swapped); if (pagesize < real_pagesize || pagesize % real_pagesize != 0) { lib_error(CATGETS(elm_msg_cat, MeSet, MeIncompatiblePagesize, "Pagesize of %.50s (%d) incompatible with system pagesize (%d)"), filename, pagesize,real_pagesize); status = 0; goto fail_2; } dump_header(v,byte_swapped,filename); if (!calculate_sizes(v,filename)) { status = 0; goto fail_2; } result = mmap(0,v->csets_length,PROT_READ,MAP_SHARED,fd, v->csets_offset); if (result == MAP_FAILED) { int err = errno; lib_error(CATGETS(elm_msg_cat, MeSet, MeFailedMMap, "Failed to mmap %.50s: %30s"), filename, error_description(err)); v->csets = NULL; v->csets_length = 0; status = 0; goto fail_2; } v->csets = result; status = 1; if (!status) { fail_2: SYSCALL(munmap((void *)v->header,v->header_length)); v->header = NULL; v->header_length = 0; } fail_1: debug_output(v,status,pagesize,"mmap",filename); #endif return status; } static void trim_bindata_1 P_((struct bindata_format_1 *v)); static void trim_bindata_1(v) struct bindata_format_1 *v; { /* If malloced, truncate according of usage */ if (!v->mmapped && !v->byte_swapped) { uint16 pagesize = v->header->page_size; int n = v->csets_count; if (n < 1) n = 1; v->csets_length = n * sizeof (struct csets_1); v->header->csets_pagecount = pages(v->csets_length,pagesize); v->csets = safe_realloc(v->csets,v->csets_length); } /* zero fill unused area */ if (v->csets_count * sizeof (struct csets_1) < v->csets_length) { /* bzero is defined on hdrs/defs.h * notice pointer arithmetic */ bzero((void *)(v->csets + v->csets_count), v->csets_length - v->csets_count * sizeof (struct csets_1)); } } struct bindata_mapped_data { enum bindata_format format; union { struct bindata_format_1 f1; } v; }; void free_bindata(v) struct bindata_mapped_data * v; { switch(v->format) { case bindata_format_1: free_bindata_1(&(v->v.f1)); break; } v->format = bindata_bad; free(v); } int write_bindata(v,filename) struct bindata_mapped_data *v; CONST char *filename; { char *tmpname; int fd, err; int status = 0; if (0 != access(filename,WRITE_ACCESS)) { int err = errno; DPRINT(Debug,1,(&Debug, "bindata: access failed: errno=%d (%s)\n", \ err,error_description(err))); if (err != ENOENT) { lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable, "File %.50s is not writeable: %s"), filename, error_description(err)); return 0; } } tmpname = safe_strdup(filename); tmpname = strmcat(tmpname,".N"); err = can_open(tmpname,"w"); if (err) { DPRINT(Debug,1,(&Debug, "bindata: can_open failed: code=%d (%s)\n", \ err,error_description(err))); lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable, "File %.50s is not writeable: %s"), tmpname, error_description(err)); status = 0; goto fail; } fd = open(tmpname,O_WRONLY|O_CREAT|O_EXCL,0644); if (-1 == fd) { int err = errno; DPRINT(Debug,1,(&Debug, "bindata: open failed: errno=%d (%s)\n", \ err,error_description(err))); lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable, "File %.50s is not writeable: %s"), tmpname, error_description(err)); status = 0; goto fail; } switch(v->format) { case bindata_format_1: status = write_bindata_1(&(v->v.f1),fd,tmpname); break; } if (-1 == close(fd)) { int err = errno; DPRINT(Debug,1,(&Debug, "bindata: close failed: errno=%d (%s)\n", \ err,error_description(err))); lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable, "File %.50s is not writeable: %s"), tmpname, error_description(err)); status = 0; goto fail; } if (status) { if (-1 == rename(tmpname,filename)) { int err = errno; lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotRenamed, "Failed to rename temporary file to %.50s: %.30s"), filename, error_description(err)); status = 0; goto fail; } } fail: if (tmpname) free(tmpname); return status; } int get_bindata(ptr,filename) struct bindata_mapped_data **ptr; CONST char *filename; { struct bindata_mapped_data * res = *ptr; int status = 0; int fd, err; uint8 text_magic[sizeof TEXT_MAGIC]; uint16 magic; int n; err = can_open(filename,"r"); if (err) { lib_error(CATGETS(elm_msg_cat, MeSet, MeFileUnreadable, "File %.50s is unreadable: %s"), filename, error_description(err)); return 0; } fd = open(filename,O_RDONLY); if (-1 == fd) { int err = errno; lib_error(CATGETS(elm_msg_cat, MeSet, MeFileUnreadable, "File %.50s is unreadable: %s"), filename, error_description(err)); return 0; } n = read(fd,text_magic, sizeof text_magic); if (n != 8) { /* text_magic is assumed to be 8 bytes or there is error */ lib_error(CATGETS(elm_msg_cat, MeSet, MeCorruptedMapfile, "Mapfile %.30s is corrupted"), filename); close(fd); DPRINT(Debug,1,(&Debug,"get_bindata failed #1 -- text_magic read\n")); return 0; } if (0 != memcmp(text_magic,TEXT_MAGIC,8)) { lib_error(CATGETS(elm_msg_cat, MeSet, MeCorruptedMapfile, "Mapfile %.30s is corrupted"), filename); close(fd); DPRINT(Debug,1,(&Debug, "get_bindata failed #1 -- text_magic is wrong: %.8s\n", text_magic)); return 0; } n = read(fd,(void *)&magic, sizeof magic); if (n != 2) { /* magic is assumed to be 2 bytes or * there is 'Configure' error... */ lib_error(CATGETS(elm_msg_cat, MeSet, MeCorruptedMapfile, "Mapfile %.30s is corrupted"), filename); close(fd); DPRINT(Debug,1,(&Debug,"get_bindata failed #1 -- magic read\n")); return 0; } if (res) free_bindata(res); res = NULL; res = safe_malloc(sizeof (struct bindata_mapped_data)); res->format = bindata_bad; if (bindata_format_1 == magic) { res->format = bindata_format_1; if (!mmap_bindata_1(&(res->v.f1),fd,0,filename) && !read_bindata_1(&(res->v.f1),fd,0,filename)) { status = 0; } else status = 1; } else if (bindata_format_1 == SWAP(magic)) { res->format = bindata_format_1; if (!mmap_bindata_1(&(res->v.f1),fd,1,filename) && !read_bindata_1(&(res->v.f1),fd,1,filename)) { status = 0; } else status = 1; } else { lib_error(CATGETS(elm_msg_cat, MeSet, MeCorruptedMapfile, "Mapfile %.30s is corrupted"), filename); DPRINT(Debug,1,(&Debug, "get_bindata failed #2 -- magic check\n")); status = 0; } if (!status) { if (res) free(res); res = NULL; } close(fd); *ptr = res; return status; } static char * u8s_to_cs P_((uint8 *s)); static char * u8s_to_cs(s) uint8 *s; { return (char *)s; } static int add_bindata_1_map P_((struct bindata_format_1 *v, uint16 bytevector[256], unsigned char revvector[MAP_REV_MAP_DIV], const char *filename)); static int add_bindata_1_map(v,bytevector,revvector,filename) struct bindata_format_1 *v; uint16 bytevector[256]; unsigned char revvector[MAP_REV_MAP_DIV]; CONST char *filename; { int status = 0,i; struct csets_1 *y; int L; if (v->mmapped || v->byte_swapped) { DPRINT(Debug,1,(&Debug,"add_bindata_1_map failed #1 -- not malloced\n")); return 0; } if (strlen(filename) >= sizeof (y->filename)) { DPRINT(Debug,1,(&Debug,"add_bindata_1_map failed #2 -- too long filename\n")); return 0; } L = (v->csets_count+1) * sizeof (v->csets[0]); if (v->csets_length < L) { uint16 pagesize = v->header->page_size; v->csets_length = L; v->header->csets_pagecount = pages(v->csets_length,pagesize); v->csets = safe_realloc(v->csets, v->csets_length); } y = & (v->csets[v->csets_count] ); /* strncpy will \0 fill remainig space if needed There is \0 on end because strlen(filename) < sizeof (y->filename) */ strncpy(u8s_to_cs(y->filename),filename,sizeof (y->filename)); for (i = 0; i < 256; i++) y->map[i] = bytevector[i]; for (i = 0; i < MAP_REV_MAP_DIV; i++) y->revmap[i] = revvector[i]; v->csets_count++; status = 1; return status; } int add_bindata_map(v,bytevector,revvector,filename) struct bindata_mapped_data * v; uint16 bytevector[256]; unsigned char revvector[MAP_REV_MAP_DIV]; CONST char *filename; { int r = 0; switch(v->format) { case bindata_format_1: r = add_bindata_1_map(&(v->v.f1), bytevector,revvector,filename); break; } return r; } struct bindata_mapped_data * malloc_bindata(cscount) int cscount; { struct bindata_mapped_data *v = safe_malloc(sizeof (*v)); v->format = bindata_format_1; malloc_bindata_1(&(v->v.f1),cscount); return v; } void trim_bindata(v) struct bindata_mapped_data * v; { switch(v->format) { case bindata_format_1: trim_bindata_1(&(v->v.f1)); break; } } static int write_bindata_text_1 P_((struct bindata_format_1 *v, const char *dir, char ***filelist)); static int write_bindata_text_1(v, dir, filelist) struct bindata_format_1 *v; CONST char *dir; char ***filelist; { int status = 0; char **list = NULL; int m,Y = 0;; if (!v->csets_count) goto fail1; list = safe_malloc((v->csets_count +1) * sizeof (list[0])); for (m = 0; m < v->csets_count; m++) { char * name = NULL; FILE *F; int i; int err; if (! v->csets[m].filename[0]) continue; name = elm_message(FRM("%s/%s"), dir,v->csets[m].filename); err = can_open(name,"w"); if (err) { DPRINT(Debug,1,(&Debug, "bindata: can_open failed: code=%d (%s)\n", \ err,error_description(err))); lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable, "File %.50s is not writeable: %s"), name, error_description(err)); status = 0; goto fail; } F = fopen(name,"w"); if (!F) { int err = errno; DPRINT(Debug,1,(&Debug, "bindata: fopen failed: code=%d (%s)\n", err,error_description(err))); lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable, "File %.50s is not writeable: %s"), name, error_description(err)); status = 0; goto fail; } fprintf(F,"# %s\n",v->csets[m].filename); for (i = 0; i < 256; i++) { uint16 x = READ_VALUE(v->csets[m].map[i],v->byte_swapped); if (MAPPING_NONE == x) { fprintf(F, "0x%02X\t\t# NO VALUE\n", i); } else { fprintf(F, "0x%02X\t0x%04X\t#\n", i,x); } } if (EOF == fflush(F)) { int err = errno; DPRINT(Debug,1,(&Debug, "bindata: fflush failed: code=%d (%s)\n", \ err,error_description(err))); lib_error(CATGETS(elm_msg_cat, MeSet, MeFileNotWriteable, "File %.50s is not writeable: %s"), name, error_description(err)); status = 0; } fclose(F); list[Y++] = name; name = NULL; fail: if (name) free(name); } fail1: list[Y] = NULL; *filelist = list; return status; } int write_bindata_text(v,dir,filelist) struct bindata_mapped_data *v; CONST char * dir; char ***filelist; { int status = 0; char ** list = NULL; switch(v->format) { case bindata_format_1: status = write_bindata_text_1(&(v->v.f1),dir,&list); break; } *filelist = list; return status; } struct bindata_map_1 { struct bindata_format_1 *header; int cset_number; }; struct bindata_map { enum bindata_format format; union { struct bindata_map_1 f1; } v; }; struct bindata_map * give_mapping_1 P_((struct bindata_format_1 *v, const char *mapname)); struct bindata_map * give_mapping_1(v, mapname) struct bindata_format_1 *v; CONST char *mapname; { struct bindata_map *ret = NULL; int m; for (m = 0; m < v->csets_count; m++) { if (0 == strcmp(u8s_to_cs(v->csets[m].filename), mapname)) break; } if (m >= v->csets_count) return NULL; ret = safe_malloc(sizeof (*ret)); /* bzero is defined on hdrs/defs.h */ bzero((void *)ret, sizeof (*ret)); ret->format = bindata_format_1; ret->v.f1.header = v; ret->v.f1.cset_number = m; return ret; } struct bindata_map * give_mapping(v,mapname) struct bindata_mapped_data *v; CONST char *mapname; { struct bindata_map *ret = NULL; switch(v->format) { case bindata_format_1: ret = give_mapping_1(&(v->v.f1),mapname); break; } return ret; } static unsigned char lookup_binmap_rev_1 P_((struct bindata_map_1 *map, unsigned int val, int * found)); static unsigned char lookup_binmap_rev_1(map,val,found) struct bindata_map_1 *map; unsigned int val; int * found; { unsigned char c; int i; int byte_swapped = map->header->byte_swapped; struct csets_1 * cset = & (map->header->csets[map->cset_number]); /* map is two byte, revmap is one byte */ *found = 0; c = cset->revmap[val % MAP_REV_MAP_DIV]; /* Check case no collision */ if (READ_VALUE(cset->map[c],byte_swapped) == val) { *found = 1; return c; } if (!c) return 0; /* Do scan on case of collision */ for (i = 0; i < 256; i++) { if (val == READ_VALUE(cset->map[i],byte_swapped)) { *found = 1; return i; } } return 0; /* Not found */ } static uint16 lookup_binmap_1 P_((unsigned int ch, struct bindata_map_1 *map, int *found)); static uint16 lookup_binmap_1(ch,map,found) unsigned int ch; struct bindata_map_1 *map; int *found; { uint16 val; int byte_swapped = map->header->byte_swapped; struct csets_1 * cset = & (map->header->csets[map->cset_number]); /* map is two byte, revmap is one byte */ val = READ_VALUE(cset->map[ch],byte_swapped); if (val != MAPPING_NONE) { *found = 1; return val; } return 0x003F; /* '?' */ } unsigned char lookup_binmap_rev(map,val,found) struct bindata_map *map; unsigned int val; int * found; { *found = 0; switch(map->format) { case bindata_format_1: return lookup_binmap_rev_1(& (map->v.f1),val,found); } return 0; } uint16 lookup_binmap(ch,map,found) unsigned int ch; struct bindata_map *map; int *found; { *found = 0; switch(map->format) { case bindata_format_1: return lookup_binmap_1(ch,& (map->v.f1),found); } return 0x003F; /* '?' */ } /* ---------------------------------------------------------------------- */ struct bindata_mapped_data * default_bindata() { static struct bindata_mapped_data * res = NULL; static struct bindata_mapped_data * res_global = NULL; if (! bindata_path[0]) { DPRINT(Debug,4,(&Debug, "BINDATA path not expanded yet.\n")); if (bindata_path_global[0] && strcmp(bindata_path_global,"none") && !res_global) { static int tried = 0; if (!tried) { DPRINT(Debug,4,(&Debug, "Loading (global) BINDATA information ... (file %s)\n", bindata_path_global)); if (!get_bindata(&res_global,bindata_path_global)) { DPRINT(Debug,4,(&Debug, "... loading of BINDATA information failed\n")); } tried = 1; } return res_global; } if (res_global) { DPRINT(Debug,4,(&Debug, " ... using global.\n")); } return res_global; } if (0 != strcmp(bindata_path,"none") && !res) { static int tried = 0; if (0 == strcmp(bindata_path,bindata_path_global) && res_global) { DPRINT(Debug,4,(&Debug, "Using global as user BINDATA ... (file %s)\n", bindata_path)); res = res_global; } else if (!tried) { DPRINT(Debug,4,(&Debug, "Loading (user) BINDATA information ... (file %s)\n", bindata_path)); if (!get_bindata(&res,bindata_path)) { DPRINT(Debug,4,(&Debug, "... loading of BINDATA information failed\n")); } tried = 1; } } return res; } /* * Local Variables: * mode:c * c-basic-offset:4 * buffer-file-coding-system: iso-8859-1 * End: */