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 <hurtta+elm@ozone.FMI.FI>
*****************************************************************************/
#include "headers.h"
#include "mmaputil.h"
#include "cs_imp.h"
#include "s_me.h"
#include "bindata.h"
#include <errno.h>
#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 <sys/mman.h>
#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:
*/
syntax highlighted by Code2HTML, v. 0.9.1