sj3/depend.c

747 lines
17 KiB
C

/*
* Copyright (c) 1991-1994 Sony Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL SONY CORPORATION BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Sony Corporation
* shall not be used in advertising or otherwise to promote the sale, use
* or other dealings in this Software without prior written authorization
* from Sony Corporation.
*
*/
#include <sys/types.h>
#include "sj_kcnv.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <unistd.h>
#include "Dict.h"
#include "sj3err.h"
#include "kanakan.h"
#if defined(__FD_SET) && !defined(FD_SET)
#define FD_SET __FD_SET
#define FD_CLR __FD_CLR
#endif
extern int serv_errno;
extern Global* work_base;
DictFile* dictlink = NULL;
StdyFile* stdylink = NULL;
static long
get4byte(unsigned char* p) {
long i;
i = *p;
i = (i << 8) + *++p;
i = (i << 8) + *++p;
return ((i << 8) + *++p);
}
static void
Put4byte(unsigned char* p, long n) {
p += 3;
*p-- = n;
n >>= 8;
*p-- = n;
n >>= 8;
*p-- = n;
n >>= 8;
*p = n;
}
#define put4byte(p, n) Put4byte((p), (long)(n))
static int
fgetfile(FILE* fp, long pos, int len, void* p) {
if(fseek(fp, pos, 0) == ERROR) {
serv_errno = SJ3_FileSeekError;
return ERROR;
}
if(fread(p, len, 1, fp) != 1) {
serv_errno = SJ3_FileReadError;
return ERROR;
}
return SJ3_NormalEnd;
}
static int
fputfile(FILE* fp, long pos, int len, unsigned char* p) {
if(fseek(fp, pos, 0) == ERROR) {
serv_errno = SJ3_FileSeekError;
return ERROR;
}
if(fwrite(p, len, 1, fp) != 1) {
serv_errno = SJ3_FileWriteError;
return ERROR;
}
return SJ3_NormalEnd;
}
static int
getfile(int fd, off_t pos, int len, void* p) {
if(lseek(fd, pos, L_SET) == ERROR) {
serv_errno = SJ3_FileSeekError;
return ERROR;
}
if(read(fd, p, len) != len) {
serv_errno = SJ3_FileReadError;
return ERROR;
}
return SJ3_NormalEnd;
}
static int
putfile(int fd, off_t pos, int len, void* p) {
if(lseek(fd, pos, L_SET) == ERROR) {
serv_errno = SJ3_FileSeekError;
return ERROR;
}
if(write(fd, p, len) != len) {
serv_errno = SJ3_FileWriteError;
return ERROR;
}
return SJ3_NormalEnd;
}
static int
check_passwd(unsigned char* buf, char* passwd) {
buf += PasswdPos;
return (*buf && strncmp(passwd, buf, PasswdLen)) ? FALSE : TRUE;
}
static void
set_passwd(unsigned char* buf, char* passwd) {
strncpy(buf + PasswdPos, passwd, PasswdLen);
}
static int
check_dictfile(unsigned char* buf) {
return (DictVersion != get4byte(buf + VersionPos)) ? FALSE : TRUE;
}
static DictFile*
search_same_dict(ino_t ino) {
DictFile* p;
for(p = dictlink; p != NULL; p = p->link)
if(p->dict.dicid == ino) return p;
return NULL;
}
static int
getofs(DictFile* dp) {
idxofs = dp->ofsptr;
return 0;
}
static int
getidx(DictFile* dp) {
idxbuf = dp->buffer + dp->idxstrt;
return 0;
}
static int
getdic(DictFile* dp, TypeDicSeg seg) {
if(seg >= dp->dict.segunit) return -1;
dicbuf = dp->buffer + dp->segstrt + dp->dict.seglen * seg;
return 0;
}
static int
putidx(DictFile* dp, TypeDicSeg seg) {
return putfile(dp->fd, dp->idxstrt, dp->dict.idxlen, idxbuf);
}
static int
putdic(DictFile* dp, TypeDicSeg seg) {
unsigned char* p;
long i, j;
if(seg >= dp->dict.maxunit) return -1;
i = dp->segstrt + dp->dict.seglen * (seg + 1);
if(i > dp->bufsiz) {
if(!(p = (unsigned char*)malloc(i))) return -1;
memcpy(dp->buffer, p, dp->bufsiz);
if(idxbuf - dp->buffer == dp->idxstrt)
idxbuf = p + dp->idxstrt;
if((dicbuf >= dp->buffer) &&
((j = dicbuf - dp->buffer) < dp->bufsiz))
dicbuf = p + j;
free((char*)(dp->buffer));
dp->buffer = p;
dp->bufsiz = i;
}
i = dp->segstrt + dp->dict.seglen * seg;
if((p = dp->buffer + i) != dicbuf) memcpy(dicbuf, p, dp->dict.seglen);
return putfile(dp->fd, i, dp->dict.seglen, p);
}
static int
rszdic(DictFile* dp, TypeDicSeg seg) {
long i;
unsigned char* p;
i = dp->segstrt + dp->dict.seglen * seg;
if(dp->bufsiz != i) {
if(!(p = (unsigned char*)malloc(i))) return -1;
memcpy(dp->buffer, p, ((i > dp->bufsiz) ? dp->bufsiz : i));
if(idxbuf - dp->buffer == dp->idxstrt)
idxbuf = p + dp->idxstrt;
if((dicbuf >= dp->buffer) &&
((i = dicbuf - dp->buffer) < dp->bufsiz))
dicbuf = p + i;
free((char*)(dp->buffer));
dp->buffer = p;
dp->bufsiz = i;
if(ftruncate(dp->fd, i) == -1) return -1;
}
put4byte(dp->buffer + DictSegNum, seg);
return putfile(dp->fd, 0, HeaderLength, dp->buffer);
}
DictFile*
opendict(char* name, char* passwd) {
FILE* fp;
struct stat sbuf;
DictFile* dfp;
unsigned char tmp[HeaderLength];
int i;
unsigned char* dp;
if(stat(name, &sbuf) == ERROR) {
if(errno == ENOENT)
serv_errno = SJ3_FileNotExist;
else
serv_errno = SJ3_CannotAccessFile;
return NULL;
}
if((dfp = search_same_dict(sbuf.st_ino)) != NULL) {
dfp->refcnt++;
return dfp;
}
if((fp = fopen(name, "r+")) == NULL) {
if((fp = fopen(name, "r")) == NULL) {
serv_errno = SJ3_CannotOpenFile;
return NULL;
}
i = FALSE;
} else
i = TRUE;
if(fgetfile(fp, 0L, sizeof(tmp), tmp) == ERROR) goto error1;
if(!check_dictfile(tmp)) {
serv_errno = SJ3_IllegalDictFile;
goto error1;
}
if(!check_passwd(tmp, passwd)) {
serv_errno = SJ3_IncorrectPasswd;
goto error1;
}
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__bsdi__) || defined(__DragonFly__)
if((dp = (unsigned char*)malloc((long)sbuf.st_size)) == NULL) {
#else
if((dp = (unsigned char*)malloc(sbuf.st_size)) == NULL) {
#endif
serv_errno = SJ3_NotEnoughMemory;
goto error1;
}
if((dfp = (DictFile*)malloc(sizeof(*dfp))) == NULL) {
serv_errno = SJ3_NotEnoughMemory;
goto error2;
}
memset(dfp, '\0', sizeof(*dfp));
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__bsdi__) || defined(__DragonFly__)
if(fgetfile(fp, 0L, (long)sbuf.st_size, dp) == ERROR) goto error3;
#else
if(fgetfile(fp, 0L, sbuf.st_size, dp) == ERROR) goto error3;
#endif
dfp->dict.dicid = sbuf.st_ino;
dfp->dict.idxlen = get4byte(dp + DictIdxLen);
dfp->dict.seglen = get4byte(dp + DictSegLen);
dfp->dict.segunit = get4byte(dp + DictSegNum);
dfp->dict.maxunit = i ? get4byte(dp + DictSegMax) : 0;
dfp->dict.getofs = getofs;
dfp->dict.getidx = getidx;
dfp->dict.getdic = getdic;
dfp->dict.putidx = putidx;
dfp->dict.putdic = putdic;
dfp->dict.rszdic = rszdic;
dfp->refcnt = 1;
dfp->fp = fp;
dfp->fd = fileno(fp);
dfp->buffer = dp;
dfp->bufsiz = sbuf.st_size;
dfp->idxstrt = get4byte(dp + DictIdxPos);
dfp->segstrt = get4byte(dp + DictSegPos);
i = dfp->dict.segunit;
if(i < dfp->dict.maxunit) i = dfp->dict.maxunit;
i *= sizeof(TypeIdxOfs);
if((dfp->ofsptr = (TypeIdxOfs*)malloc(i)) == NULL) {
serv_errno = SJ3_NotEnoughMemory;
goto error3;
}
mkidxtbl(&(dfp->dict));
dfp->link = dictlink;
dictlink = dfp;
return dfp;
error3:
free((char*)dfp);
error2:
free((char*)dp);
error1:
fclose(fp);
return NULL;
}
int closedict(DictFile* dfp) {
DictFile* df;
if(--dfp->refcnt > 0) return 0;
if(dictlink == dfp)
dictlink = dfp->link;
else {
for(df = dictlink; df; df = df->link)
if(df->link == dfp) {
df->link = dfp->link;
break;
}
}
if(dfp->fp) fclose(dfp->fp);
free((char*)(dfp->ofsptr));
free((char*)(dfp->buffer));
free((char*)dfp);
return 0;
}
static fd_set zero_fd_set = {{0}};
void lock_dict(DictFile* p, int fd) {
FD_SET(fd, &(p->lock));
}
void unlock_dict(DictFile* p, int fd) {
FD_CLR(fd, &(p->lock));
}
int is_dict_locked(DictFile* p) {
return memcmp(&(p->lock), &zero_fd_set, sizeof(zero_fd_set));
}
static int
check_stdyfile(unsigned char* buf) {
return (StdyVersion != get4byte(buf + VersionPos)) ? FALSE : TRUE;
}
static StdyFile*
search_same_stdy(ino_t ino) {
StdyFile* p;
for(p = stdylink; p != NULL; p = p->link)
if(p->inode == ino) return p;
return NULL;
}
StdyFile*
openstdy(char* name, char* passwd) {
FILE* fp;
struct stat sbuf;
StdyFile* sfp;
unsigned char* hd;
STDYIN* sp;
unsigned short* cip;
unsigned char* clp;
long stdycnt, stdypos, stdylen, stdymax;
long clidxpos, clidxlen;
long clstdypos, clstdylen, clstdystep;
long len;
if(stat(name, &sbuf) == ERROR) {
if(errno == ENOENT)
serv_errno = SJ3_FileNotExist;
else
serv_errno = SJ3_CannotAccessFile;
return NULL;
}
if((sfp = search_same_stdy(sbuf.st_ino)) != NULL) {
sfp->refcnt++;
return sfp;
}
if((hd = (unsigned char*)malloc(HeaderLength + CommentLength)) == NULL) {
serv_errno = SJ3_NotEnoughMemory;
return NULL;
}
if((fp = fopen(name, "r+")) == NULL) {
serv_errno = SJ3_CannotOpenFile;
goto error0;
}
if(fgetfile(fp, 0L, HeaderLength + CommentLength, hd) == ERROR)
goto error1;
if(!check_stdyfile(hd)) {
serv_errno = SJ3_IllegalStdyFile;
goto error1;
}
if(!check_passwd(hd, passwd)) {
serv_errno = SJ3_IncorrectPasswd;
goto error1;
}
stdycnt = get4byte(hd + StdyNormCnt);
stdypos = get4byte(hd + StdyNormPos);
stdylen = get4byte(hd + StdyNormLen);
stdymax = get4byte(hd + StdyNormNum);
clidxpos = get4byte(hd + StdyClIdxPos);
clidxlen = get4byte(hd + StdyClIdxLen);
clstdypos = get4byte(hd + StdyClSegPos);
clstdylen = get4byte(hd + StdyClSegLen);
clstdystep = get4byte(hd + StdyClIdxStep);
len = sizeof(STDYIN) * stdymax;
if((sfp = (StdyFile*)malloc(sizeof(*sfp))) == NULL) {
serv_errno = SJ3_NotEnoughMemory;
goto error1;
}
memset(sfp, '\0', sizeof(*sfp));
if((sp = (STDYIN*)malloc(len)) == NULL) {
serv_errno = SJ3_NotEnoughMemory;
goto error2;
}
if((cip = (unsigned short*)malloc(clidxlen)) == NULL) {
serv_errno = SJ3_NotEnoughMemory;
goto error3;
}
if((clp = (unsigned char*)malloc(clstdylen)) == NULL) {
serv_errno = SJ3_NotEnoughMemory;
goto error4;
}
if(fgetfile(fp, clidxpos, clidxlen, cip) == ERROR) goto error5;
if(fgetfile(fp, clstdypos, clstdylen, clp) == ERROR) goto error5;
if(fgetfile(fp, stdypos, len, sp) == ERROR) stdycnt = 0;
sfp->stdy.stdycnt = stdycnt;
sfp->stdy.stdymax = stdymax;
sfp->stdy.stdydic = sp;
sfp->stdy.clstdystep = clstdystep;
sfp->stdy.clstdyidx = cip;
sfp->stdy.clstdylen = clstdylen;
sfp->stdy.clstdydic = clp;
sfp->refcnt = 1;
sfp->inode = sbuf.st_ino;
sfp->fp = fp;
sfp->fd = fileno(fp);
sfp->header = hd;
sfp->link = stdylink;
stdylink = sfp;
return sfp;
error5:
free((char*)clp);
error4:
free((char*)cip);
error3:
free((char*)sp);
error2:
free((char*)sfp);
error1:
fclose(fp);
error0:
free((char*)hd);
return NULL;
}
int closestdy(StdyFile* sfp) {
StdyFile* sf;
if(--sfp->refcnt > 0) return 0;
if(stdylink == sfp)
stdylink = sfp->link;
else {
for(sf = stdylink; sf; sf = sf->link)
if(sf->link == sfp) {
sf->link = sfp->link;
break;
}
}
if(sfp->fp) fclose(sfp->fp);
free((char*)sfp->stdy.stdydic);
free((char*)sfp->stdy.clstdyidx);
free((char*)sfp->stdy.clstdydic);
free((char*)sfp->header);
free((char*)sfp);
return 0;
}
int putstydic(void) {
int fd;
unsigned char* hd;
StdyFile* sf;
long len;
sf = (StdyFile*)stdy_base;
fd = sf->fd;
hd = sf->header;
put4byte(hd + StdyNormCnt, sf->stdy.stdycnt);
len = sizeof(STDYIN) * sf->stdy.stdymax;
put4byte(hd + StdyNormLen, len);
if(putfile(fd, 0, HeaderLength + CommentLength, hd)) return ERROR;
return putfile(fd, get4byte(hd + StdyNormPos), len, sf->stdy.stdydic);
}
int putcldic(void) {
int fd;
unsigned char* hd;
StdyFile* sf;
sf = (StdyFile*)stdy_base;
fd = sf->fd;
hd = sf->header;
if(putfile(fd, get4byte(hd + StdyClIdxPos),
get4byte(hd + StdyClIdxLen), sf->stdy.clstdyidx))
return ERROR;
return putfile(fd, get4byte(hd + StdyClSegPos),
get4byte(hd + StdyClSegLen), sf->stdy.clstdydic);
}
int makedict(char* path, int idxlen, int seglen, int segnum) {
FILE* fp;
unsigned char tmp[HeaderLength + CommentLength];
long pos = HeaderLength + CommentLength;
int ret = ERROR;
int i;
if(idxlen < MinIdxLen || seglen < MinSegLen || segnum < MinSegNum) {
serv_errno = SJ3_IllegalParameter;
return ret;
}
if(!(fp = fopen(path, "w"))) {
serv_errno = SJ3_CannotCreateFile;
return ret;
}
memset(tmp, '\0', sizeof(tmp));
put4byte(tmp + VersionPos, DictVersion);
put4byte(tmp + DictIdxPos, pos);
put4byte(tmp + DictIdxLen, idxlen);
if(fseek(fp, pos, 0) == ERROR) {
serv_errno = SJ3_FileSeekError;
goto error;
}
for(i = 0; i < idxlen; i++)
if(putc(0, fp)) {
serv_errno = SJ3_FileWriteError;
goto error;
}
pos += idxlen;
put4byte(tmp + DictSegPos, pos);
put4byte(tmp + DictSegLen, seglen);
put4byte(tmp + DictSegNum, 1);
put4byte(tmp + DictSegMax, segnum);
if(fseek(fp, pos, 0) == ERROR) {
serv_errno = SJ3_FileSeekError;
goto error;
}
if(putc(0, fp)) {
serv_errno = SJ3_FileWriteError;
goto error;
}
for(i = 1; i < seglen; i++)
if(putc(0xff, fp) != 0xff) {
serv_errno = SJ3_FileWriteError;
goto error;
}
if(fputfile(fp, 0L, sizeof(tmp), tmp) == SJ3_NormalEnd)
ret = SJ3_NormalEnd;
error:
fclose(fp);
if(ret != SJ3_NormalEnd) unlink(path);
return ret;
}
int makestdy(char* path, int stynum, int clstep, int cllen) {
FILE* fp;
unsigned char tmp[HeaderLength + CommentLength];
long pos = HeaderLength + CommentLength;
int ret = ERROR;
int i, j;
if(stynum == 0) stynum = MinStyNum;
if(clstep == 0) clstep = MinClStep;
if(cllen == 0) cllen = MinClLen;
if(stynum < MinStyNum || clstep < MinClStep || cllen < MinClLen) {
serv_errno = SJ3_IllegalParameter;
return ret;
}
if(stynum > MaxStyNum || clstep > MaxClStep || cllen > MaxClLen) {
serv_errno = SJ3_IllegalParameter;
return ret;
}
if(!(fp = fopen(path, "w"))) {
serv_errno = SJ3_CannotCreateFile;
return ret;
}
memset(tmp, '\0', sizeof(tmp));
put4byte(tmp + VersionPos, StdyVersion);
j = 256 * sizeof(unsigned short);
put4byte(tmp + StdyClIdxPos, pos);
put4byte(tmp + StdyClIdxLen, j);
put4byte(tmp + StdyClIdxStep, clstep);
if(fseek(fp, pos, 0) == ERROR) {
serv_errno = SJ3_FileSeekError;
goto error;
}
for(i = 0; i < j; i++)
if(putc(0, fp)) {
serv_errno = SJ3_FileWriteError;
goto error;
}
pos += j;
put4byte(tmp + StdyClSegPos, pos);
put4byte(tmp + StdyClSegLen, cllen);
if(fseek(fp, pos, 0) == ERROR) {
serv_errno = SJ3_FileSeekError;
goto error;
}
for(i = 0; i < cllen; i++)
if(putc(0, fp)) {
serv_errno = SJ3_FileWriteError;
goto error;
}
pos += cllen;
j = sizeof(STDYIN) * stynum;
put4byte(tmp + StdyNormPos, pos);
put4byte(tmp + StdyNormLen, j);
put4byte(tmp + StdyNormNum, stynum);
put4byte(tmp + StdyNormCnt, 0);
if(fseek(fp, pos, 0) == ERROR) {
serv_errno = SJ3_FileSeekError;
goto error;
}
for(i = 0; i < j; i++) {
if(putc(0, fp)) {
serv_errno = SJ3_FileWriteError;
goto error;
}
}
pos += j;
if(fputfile(fp, 0L, sizeof(tmp), tmp) == SJ3_NormalEnd)
ret = SJ3_NormalEnd;
error:
fclose(fp);
if(ret != SJ3_NormalEnd) unlink(path);
return ret;
}
void sj_closeall(void) {
while(dictlink) closedict(dictlink);
while(stdylink) closestdy(stdylink);
}
int set_dictpass(DictFile* dp, char* pass) {
set_passwd(dp->buffer, pass);
return putfile(dp->fd, 0, HeaderLength + CommentLength, dp->buffer);
}
int set_stdypass(char* pass) {
StdyFile* sp;
sp = (StdyFile*)stdy_base;
set_passwd(sp->header, pass);
return putfile(sp->fd, 0, HeaderLength + CommentLength, sp->header);
}
static void
set_comment(unsigned char* buf, char* comment) {
strncpy(buf + HeaderLength, comment, CommentLength);
}
int set_dictcmnt(DictFile* dp, char* cmnt) {
set_comment(dp->buffer, cmnt);
return putfile(dp->fd, 0, HeaderLength + CommentLength, dp->buffer);
}
int set_stdycmnt(char* cmnt) {
StdyFile* sp;
sp = (StdyFile*)stdy_base;
set_comment(sp->header, cmnt);
return putfile(sp->fd, 0, HeaderLength + CommentLength, sp->header);
}
void get_stdysize(int* stynum, int* clstep, int* cllen) {
*stynum = StudyMax;
*clstep = ClStudyStep;
*cllen = ClStudyLen;
}