diff Wnn/jserver/readfile.c @ 0:bbc77ca4def5

initial import
author Yoshiki Yazawa <yaz@cc.rim.or.jp>
date Thu, 13 Dec 2007 04:30:14 +0900
parents
children 790205f476c0
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Wnn/jserver/readfile.c	Thu Dec 13 04:30:14 2007 +0900
@@ -0,0 +1,1131 @@
+/*
+ * FreeWnn is a network-extensible Kana-to-Kanji conversion system.
+ * This file is part of FreeWnn.
+ * 
+ * Copyright Kyoto University Research Institute for Mathematical Sciences
+ *                 1987, 1988, 1989, 1990, 1991, 1992
+ * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999
+ * Copyright ASTEC, Inc. 1987, 1988, 1989, 1990, 1991, 1992
+ * Copyright FreeWnn Project 1999, 2000, 2002, 2003
+ *
+ * Maintainer:  FreeWnn Project   <freewnn@tomo.gr.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+  (Updatable, Stable) dictionary read routine.
+*/
+static char rcs_id[] = "$Id: readfile.c,v 1.9 2003/06/07 02:23:58 hiroo Exp $";
+
+#if defined(HAVE_CONFIG_H)
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#if STDC_HEADERS
+#  include <stdlib.h>
+#  include <string.h>
+#else
+#  if HAVE_MALLOC_H
+#    include <malloc.h>
+#  endif
+#  if HAVE_STRINGS_H
+#    include <strings.h>
+#  endif
+#endif /* STDC_HEADERS */
+
+#if defined(HAVE_SYS_TYPES_H)
+#include <sys/types.h>
+#endif
+
+#include "commonhd.h"
+#include "de_header.h"
+#include "jdata.h"
+
+#ifdef WRITE_CHECK
+static int vfwrite (void*, int, int, FILE *);
+#endif
+static struct JT *readdict (FILE *);
+static struct JT *copy_dict (struct JT *);
+static int write_file_real (struct wnn_file *, FILE *, int);
+static int writedict (struct JT *, FILE *);
+static int write_hindo_of_dict (struct JT *, FILE *);
+static struct JT * free_dict (struct JT *);
+static struct HJT *readhindo (FILE *);
+static int writehindo (struct HJT *, FILE *);
+static struct HJT * free_hindo (struct HJT *);
+static int alloc_dict (struct JT *);
+static int check_and_change_pwd (char *, char *, char *);
+
+#define vfread(A, B, C, fp) ((fp)?fread((A),(B),(C),(fp)):fread_cur((A),(B),(C)))
+#ifndef WRITE_CHECK
+#define vfwrite(A, B, C, fp) {if(fp) {fwrite((A),(B),(C),(fp));}else\
+                                     {fwrite_cur((A),(B),(C));}}
+#endif
+#define vclose(fp) {if(fp) {fclose(fp);}else{fclose_cur();}}
+
+#ifdef WRITE_CHECK
+static int
+vfwrite (void *ptr, int size, int nitems, FILE *fp)
+{
+  if (fp)
+    {
+      if (fwrite (ptr, size, nitems, fp) != nitems)
+        return (-1);
+    }
+  else
+    {
+      fwrite_cur (ptr, size, nitems);
+    }
+  return (0);
+}
+#endif
+
+int
+read_file (struct wnn_file *wf)
+{
+  FILE *fp;
+  struct wnn_file_head fh;
+  if (wf->localf == REMOTE)
+    {
+      if (fopen_read_cur (wf->name) == NULL)
+        {
+          wnn_errorno = WNN_FILE_READ_ERROR;
+          log_err ("read_file:could not open file %s.", wf->name);
+          return (-1);
+        }
+      fp = NULL;
+    }
+  else
+    {
+#ifdef WRITE_CHECK
+      check_backup (wf->name);
+#endif
+      if ((fp = fopen (wf->name, "r")) == NULL)
+        {
+          wnn_errorno = WNN_FILE_READ_ERROR;
+          log_err("read_file:could not open file %s.", wf->name);
+          return (-1);
+        }
+    }
+  if (input_file_header (fp, &fh) == -1)
+    {
+      wnn_errorno = WNN_NOT_A_FILE;
+      goto ERROR_RET;
+    }
+  bcopy ((char *) &(fh.file_uniq), (char *) &(wf->f_uniq), WNN_F_UNIQ_LEN);
+  bcopy ((char *) &(fh.file_uniq_org), (char *) &(wf->f_uniq_org), WNN_F_UNIQ_LEN);
+  strncpy (wf->passwd, fh.file_passwd, WNN_PASSWD_LEN);
+  wf->file_type = fh.file_type;
+  wf->ref_count = 0;
+
+  switch (fh.file_type)
+    {
+    case WNN_FT_DICT_FILE:
+      wf->area = (char *) readdict (fp);
+      if (wf->area == NULL)
+        goto ERROR_RET;
+      break;
+    case WNN_FT_HINDO_FILE:
+      wf->area = (char *) readhindo (fp);
+      if (wf->area == NULL)
+        goto ERROR_RET;
+      break;
+    case WNN_FT_FUZOKUGO_FILE:
+      wf->area = (char *) fzk_read (fp);
+      if (wf->area == NULL)
+        goto ERROR_RET;
+      break;
+    }
+  vclose (fp);
+  return (0);
+ERROR_RET:
+  vclose (fp);
+  return (-1);
+}
+
+static struct JT *
+readdict (FILE *fp)
+{
+  struct JT *jt1;
+  long x;
+
+  jt1 = (struct JT *) malloc (sizeof (struct JT));
+  jt1->node = 0;
+  if (input_header_jt (fp, jt1) == -1)
+    {
+      wnn_errorno = WNN_NOT_A_FILE;
+      free (jt1);
+      return (NULL);
+    }
+  if (jt1->syurui == WNN_UD_DICT)
+    {
+      jt1->bufsize_serial = (jt1->maxserial + MAXSERIAL);
+      jt1->bufsize_kanji = (jt1->maxkanji + MAXKANJI);
+      jt1->bufsize_hontai = (jt1->maxhontai + MAXHONTAI);
+      jt1->bufsize_table = (jt1->maxtable + MAXTABLE);
+      jt1->bufsize_ri1[D_YOMI] = 0;
+      jt1->bufsize_ri1[D_KANJI] = 0;
+#if     defined(CONVERT_by_STROKE) || defined(CONVERT_with_SiSheng)
+    }
+  else if ((jt1->syurui & 0xff) == WNN_REV_DICT)
+    {
+#else
+    }
+  else if (jt1->syurui == WNN_REV_DICT)
+    {
+#endif /* CONVERT_by_STROKE || CONVERT_with_SiSheng */
+      jt1->bufsize_serial = (jt1->maxserial + MAXSERIAL);
+      jt1->bufsize_kanji = (jt1->maxkanji + MAXKANJI);
+      jt1->bufsize_hontai = (jt1->maxhontai + MAXHONTAI);
+      jt1->bufsize_table = 0;
+      jt1->bufsize_ri1[D_YOMI] = (jt1->maxri1[D_YOMI] + MAXTABLE);
+      jt1->bufsize_ri1[D_KANJI] = (jt1->maxri1[D_KANJI] + MAXTABLE);
+    }
+  else if (jt1->syurui == WNN_STATIC_DICT)
+    {                           /* WNN_STATIC_DICT */
+      jt1->bufsize_serial = jt1->maxserial;
+      jt1->bufsize_kanji = jt1->maxkanji;
+      jt1->bufsize_hontai = jt1->maxhontai;
+      jt1->bufsize_table = 0;
+      jt1->bufsize_ri1[D_YOMI] = 0;
+      jt1->bufsize_ri1[D_KANJI] = 0;
+    }
+  else
+    {
+      wnn_errorno = WNN_NOT_A_DICT;
+      log_err ("not a correct dictionary.");
+      free (jt1);
+      return (NULL);
+    }
+  if (alloc_dict (jt1) == -1)
+    {
+      free (jt1);
+      return (NULL);
+    }
+  if (vfread (jt1->comment, 2, jt1->maxcomment, fp) != jt1->maxcomment)
+    {
+      wnn_errorno = WNN_NOT_A_DICT;
+      log_err ("not a correct dictionary.");
+      goto error;
+    }
+
+  if (vfread (jt1->hinsi_list, 2, jt1->maxhinsi_list, fp) != jt1->maxhinsi_list)
+    {
+      wnn_errorno = WNN_NOT_A_DICT;
+      log_err ("not a correct dictionary.");
+      goto error;
+    }
+
+  if (vfread (jt1->hindo, 1, jt1->maxserial, fp) != jt1->maxserial)
+    {
+      wnn_errorno = WNN_NOT_A_DICT;
+      log_err ("not a correct dictionary.");
+      goto error;
+    }
+  if (vfread (jt1->hinsi, 2, jt1->maxserial, fp) != jt1->maxserial)
+    {
+      wnn_errorno = WNN_NOT_A_DICT;
+      log_err ("not a correct dictionary.");
+      goto error;
+    }
+#ifdef  CONVERT_with_SiSheng
+  if (jt1->syurui == CWNN_REV_DICT)
+    if (vfread (jt1->sisheng, 2, jt1->maxserial, fp) != jt1->maxserial)
+      {
+        wnn_errorno = WNN_NOT_A_DICT;
+        log_err ("not a correct dictionary.");
+        goto error;
+      }
+#endif /* CONVERT_with_SiSheng */
+  if (vfread (jt1->kanji, 1, jt1->maxkanji, fp) != jt1->maxkanji)
+    {
+      wnn_errorno = WNN_NOT_A_DICT;
+      log_err ("not a correct dictionary.");
+      goto error;
+    }
+  if (vfread (jt1->table, sizeof (struct uind1), jt1->maxtable, fp) != jt1->maxtable)
+    {
+      wnn_errorno = WNN_NOT_A_DICT;
+      log_err ("not a correct dictionary.");
+      goto error;
+    }
+  if (vfread (jt1->ri1[D_YOMI], sizeof (struct rind1), jt1->maxri1[D_YOMI], fp) != jt1->maxri1[D_YOMI])
+    {
+      wnn_errorno = WNN_NOT_A_DICT;
+      log_err ("not a correct dictionary.");
+      goto error;
+    }
+  if (vfread (jt1->ri1[D_KANJI], sizeof (struct rind1), jt1->maxri1[D_KANJI], fp) != jt1->maxri1[D_KANJI])
+    {
+      wnn_errorno = WNN_NOT_A_DICT;
+      log_err ("not a correct dictionary.");
+      goto error;
+    }
+  if (vfread (jt1->hontai, 1, jt1->maxhontai, fp) != jt1->maxhontai)
+    {
+      wnn_errorno = WNN_NOT_A_DICT;
+      log_err ("not a correct dictionary.");
+      goto error;
+    }
+  if (vfread (jt1->ri2, sizeof (struct rind2), jt1->maxri2, fp) != jt1->maxri2)
+    {
+      wnn_errorno = WNN_NOT_A_DICT;
+      log_err ("not a correct dictionary.");
+      goto error;
+    }
+
+  if (fp != NULL)
+    {
+      x = ftell (fp);
+      fseek (fp, 0, 2);
+      if (x != ftell (fp))
+        {
+          wnn_errorno = WNN_NOT_A_DICT;
+	  log_err ("not a correct dictionary.");
+          goto error;
+        }
+    }
+
+  make_hinsi_list (jt1);
+
+  if (jt1->maxhontai == 0 && (jt1->syurui == WNN_UD_DICT || jt1->syurui == WNN_STATIC_DICT))
+    {
+      jt1->maxhontai = 4;
+    }
+  if (little_endian ())
+    {
+      revdic (jt1, 0);
+    }
+  jt1->dirty = 0;
+  jt1->hdirty = 0;
+#ifdef  CONVERT_by_STROKE
+  if (jt1->syurui == BWNN_REV_DICT)
+    if ((jt1->max_bnode = create_b_index (jt1)) == -1)
+      {
+        goto error;
+      }
+#endif /* CONVERT_by_STROKE */
+  return (jt1);
+error:
+  jt1 = free_dict (jt1);
+  return (NULL);
+}
+
+/*
+ * user_jisho_realloc: ユーザー辞書に語を登録し過ぎて一杯になった時reallocする
+ *   return value: success:SUCCESS (non zero), failure:NULL
+ */
+int
+ud_realloc_hontai (struct JT *jt)
+{
+  size_t new_bufsize;
+  UCHAR *tp;
+
+  log_debug ("hontai realloc occured.");
+  new_bufsize = jt->maxhontai + MAXHONTAI;
+  if ((tp = (UCHAR *) realloc (jt->hontai, new_bufsize)) == NULL)
+    {
+      wnn_errorno = WNN_MALLOC_ERR;
+      log_err ("could not make the jisho area bigger.");
+      return (NULL);
+    }
+  jt->bufsize_hontai = new_bufsize;
+  jt->hontai = tp;
+  return (SUCCESS);
+}
+
+int
+ud_realloc_kanji (struct JT *jt)          /* Also for rd */
+{
+  size_t new_bufsize;
+  UCHAR *tp;
+
+  log_debug ("kanji realloc occured.");
+  new_bufsize = jt->maxkanji + MAXKANJI;
+  if ((tp = (UCHAR *) realloc (jt->kanji, new_bufsize)) == NULL)
+    {
+      wnn_errorno = WNN_MALLOC_ERR;
+      log_err ("could not make the jisho area bigger.");
+      return (NULL);
+    }
+  jt->bufsize_kanji = new_bufsize;
+  jt->kanji = tp;
+  return (SUCCESS);
+}
+
+int
+ud_realloc_serial (struct JT *jt)         /* Also for rd */
+{
+  size_t new_bufsize;
+  UCHAR *tp_hindo;
+  unsigned short *tp_hinsi;
+#ifdef  CONVERT_with_SiSheng
+  unsigned short *tp_sisheng;
+#endif
+  struct rind2 *tp_ri2;
+
+  log_debug ("serial realloc occured.");
+  new_bufsize = jt->maxserial + MAXSERIAL;
+
+  tp_hindo = (UCHAR *) realloc (jt->hindo, new_bufsize * sizeof (*jt->hindo));
+  tp_hinsi = (unsigned short *) realloc (jt->hinsi, new_bufsize * sizeof (*jt->hinsi));
+
+#ifdef  CONVERT_with_SiSheng
+  tp_sisheng = (unsigned short *) realloc (jt->sisheng,
+					   new_bufsize * sizeof (*jt->sisheng));
+#endif /* CONVERT_with_SiSheng */
+
+  if (tp_hindo == NULL || tp_hinsi == NULL
+#ifdef  CONVERT_with_SiSheng
+     || tp_sisheng == NULL
+#endif /* CONVERT_with_SiSheng */
+    )
+    {
+      free (tp_hindo);
+      free (tp_hinsi);
+#ifdef  CONVERT_with_SiSheng
+      free (tp_sisheng);
+#endif /* CONVERT_with_SiSheng */
+
+      wnn_errorno = WNN_MALLOC_ERR;
+      log_err ("could notmake the jisho area bigger.");
+      return (NULL);
+    }
+  jt->bufsize_serial = new_bufsize;
+  jt->hindo = tp_hindo;
+  jt->hinsi = tp_hinsi;
+#ifdef  CONVERT_with_SiSheng
+  jt->sisheng = tp_sisheng;
+#endif /* CONVERT_with_SiSheng */
+
+
+#if defined(CONVERT_by_STROKE) || defined(CONVERT_with_SiSheng)
+  if ((jt->syurui & 0xff) == WNN_REV_DICT)
+#else
+  if (jt->syurui == WNN_REV_DICT)
+#endif /* CONVERT_by_STROKE || CONVERT_with_SiSheng */
+    {
+      tp_ri2 = (struct rind2 *) realloc (jt->ri2,
+					 new_bufsize * sizeof (struct rind2));
+      if (tp_ri2 == NULL)
+        {
+          wnn_errorno = WNN_MALLOC_ERR;
+          log_err ("could not make the jisho area bigger.");
+          return (NULL);
+        }
+      jt->ri2 = tp_ri2;
+    }
+
+  return (SUCCESS);
+}
+
+int
+ud_realloc_table (struct JT *jt)
+{
+  size_t new_bufsize;              
+  struct uind1 *tp;
+
+  log_debug ("table realloc occured.");
+  new_bufsize = jt->maxtable + MAXTABLE;
+  tp = (struct uind1 *) realloc (jt->table, new_bufsize * sizeof (struct uind1));
+  if (tp == NULL)
+    {
+      wnn_errorno = WNN_MALLOC_ERR;
+      log_err ("could not make the jisho area bigger.");
+      return (NULL);
+    }
+  jt->bufsize_table = new_bufsize;
+  jt->table = tp;
+  return (SUCCESS);
+}
+
+int
+rd_realloc_ri1 (struct JT *jt, int which)
+{
+  size_t new_bufsize;
+  struct rind1 *tp;
+
+  log_debug ("ri1 reallocation occured.");
+  new_bufsize = jt->maxri1[which] + MAXTABLE;
+  tp = (struct rind1 *) realloc (jt->ri1[which],
+				 new_bufsize * sizeof (struct rind1));
+  if (tp == NULL)
+    {
+      wnn_errorno = WNN_MALLOC_ERR;
+      log_err ("could not make the jisho area bigger.");
+      return (NULL);
+    }
+  jt->bufsize_ri1[which] = new_bufsize;
+  jt->ri1[which] = tp;
+  return (SUCCESS);
+}
+
+
+int
+hindo_file_realloc (struct HJT *hjt)
+{
+  size_t new_bufsize;
+  UCHAR *tp;
+
+  log_debug ("hindo file reallocation occured.");
+  new_bufsize = hjt->maxserial + MAXSERIAL;
+  tp = (UCHAR *) realloc (hjt->hindo, new_bufsize * sizeof (*hjt->hindo));
+  if (tp == NULL)
+    {
+      wnn_errorno = WNN_MALLOC_ERR;
+      log_err ("could not make the hindo file area bigger.");
+      return (NULL);
+    }
+  hjt->bufsize_serial = new_bufsize;
+  hjt->hindo = tp;
+  return (SUCCESS);
+}
+
+#ifdef CONVERT_by_STROKE
+int
+rd_realloc_bind (struct JT *jt)
+{
+  size_t new_bufsize;
+  struct b_node *tp;
+
+  log_debug ("jt->bind reallocation occured.");
+  new_bufsize = jt->bufsize_bnode + MAXBIND;
+  tp = (struct b_node *) realloc (jt->bind, new_bufsize * sizeof (struct b_node));
+  if (tp == NULL)
+    {
+      wnn_errorno = WNN_MALLOC_ERR;
+      log_err ("could not make the jisho area bigger.");
+      return (NULL);
+    }
+  jt->bufsize_bnode = new_bufsize;
+  jt->bind = tp;
+  return (SUCCESS);
+}
+#endif /* CONVERT_by_STROKE */
+
+static struct JT *
+copy_dict (struct JT *jt1)
+{
+  struct JT *jt2;
+
+  jt2 = (struct JT *) malloc (sizeof (struct JT));
+  *jt2 = *jt1;
+
+  if (alloc_dict (jt2) == -1)
+    {
+      free (jt2);
+      return (NULL);
+    }
+  bcopy (jt1->hindo, jt2->hindo, jt1->maxserial);
+  bcopy (jt1->hinsi, jt2->hinsi, jt1->maxserial * 2);
+#ifdef  CONVERT_with_SiSheng
+  if (jt1->syurui == CWNN_REV_DICT)     /* Chinese PinYin dic only  */
+    bcopy (jt1->sisheng, jt2->sisheng, jt1->maxserial * 2);
+#endif /* CONVERT_with_SiSheng */
+  bcopy (jt1->kanji, jt2->kanji, jt1->maxkanji);
+  bcopy (jt1->table, jt2->table, jt1->maxtable * sizeof (struct uind1));
+  bcopy (jt1->hontai, jt2->hontai, jt1->maxhontai);
+  bcopy (jt1->comment, jt2->comment, jt1->maxcomment * sizeof (w_char));
+  bcopy (jt1->hinsi_list, jt2->hinsi_list, jt1->maxhinsi_list * sizeof (w_char));
+  bcopy (jt1->ri2, jt2->ri2, jt1->maxri2 * sizeof (struct rind2));
+  bcopy (jt1->ri1[D_YOMI], jt2->ri1[D_YOMI], jt1->maxri1[D_YOMI] * sizeof (struct rind1));
+  bcopy (jt1->ri1[D_KANJI], jt2->ri1[D_KANJI], jt1->maxri1[D_KANJI] * sizeof (struct rind1));
+  return (jt2);
+}
+
+
+int
+must_write_file (struct wnn_file *wf, struct wnn_file_uniq *uniq)
+{
+  if (f_uniq_cmp (&(wf->f_uniq), uniq))
+    return (3);
+  /* The File to write is not read. */
+  switch (wf->file_type)
+    {
+    case WNN_FT_DICT_FILE:
+      {
+        struct JT *jt = (struct JT *) wf->area;
+        if (jt->dirty)
+          return 1;
+        if (jt->hdirty)
+          return 2;
+        return 0;
+      }
+    case WNN_FT_HINDO_FILE:
+      {
+        struct HJT *hjt = (struct HJT *) wf->area;
+        if (!(hjt->hdirty))
+          return (0);
+        else
+          return 1;
+      }
+    case WNN_FT_FUZOKUGO_FILE:
+      wnn_errorno = NOT_SUPPORTED_OPERATION;
+      return (-1);
+    }
+  return (-1);
+}
+
+void
+clear_dirty_bit (struct wnn_file *wf)
+{
+  switch (wf->file_type)
+    {
+    case WNN_FT_DICT_FILE:
+      {
+        struct JT *jt = (struct JT *) wf->area;
+        jt->dirty = 0;
+        jt->hdirty = 0;
+      }
+      break;
+    case WNN_FT_HINDO_FILE:
+      {
+        struct HJT *hjt = (struct HJT *) wf->area;
+        hjt->hdirty = 0;
+      }
+      break;
+    case WNN_FT_FUZOKUGO_FILE:
+      break;
+    }
+}
+
+
+int
+rcv_file (struct wnn_file *wf, int mode)
+{
+  FILE *fp;
+  int x;
+
+/*    if(wf->localf == REMOTE){
+      }
+*/
+  if (fopen_write_cur (wf->name) == NULL)
+    {
+      log_err ("receive_file:No file %s.", wf->name);
+      wnn_errorno = WNN_FILE_WRITE_ERROR;
+      return (-1);
+    }
+  fp = NULL;
+  x = write_file_real (wf, fp, mode);
+  vclose (fp);
+  return (x);
+}
+
+int
+write_file (struct wnn_file *wf, char *n)
+{
+  FILE *fp;
+  int mode = 3;
+  struct wnn_file_head fh;
+#ifdef WRITE_CHECK
+  char *tmp = NULL, *backup = NULL;
+
+  check_backup (n);
+#endif
+  if ((fp = fopen (n, "r")) != NULL)
+    {                           /* Old File Exist */
+      if (input_file_header (fp, &fh) == -1)
+        {
+          wnn_errorno = WNN_NOT_A_FILE;
+          fclose (fp);
+          return (-1);
+        }
+      mode = must_write_file (wf, &(fh.file_uniq));
+      fclose (fp);
+      if (mode == -1)
+        return -1;
+    }
+
+  if (mode == 0)
+    {
+      return (0);               /* Need Not Write */
+    }
+  else if (mode == 1 || mode == 3)
+    {                           /* 3 when the file is not the one to be read. */
+#ifdef WRITE_CHECK
+      backup = make_backup_file (n);
+      if ((tmp = make_tmp_file (n, 0, &fp)) == NULL)
+        {
+          delete_tmp_file (backup);
+#else /* WRITE_CHECK */
+      if ((fp = fopen (n, "w+")) == NULL)
+        {
+#endif /* WRITE_CHECK */
+          wnn_errorno = WNN_FILE_WRITE_ERROR;
+          return (-1);
+        }
+    }
+  else if (mode == 2)
+    {
+#ifdef WRITE_CHECK
+      backup = make_backup_file (n);
+      if ((tmp = make_tmp_file (n, 1, &fp)) == NULL)
+        {
+          delete_tmp_file (backup);
+#else /* WRITE_CHECK */
+      if ((fp = fopen (n, "r+")) == NULL)
+        {                       /* New File */
+#endif /* WRITE_CHECK */
+          wnn_errorno = WNN_FILE_WRITE_ERROR;
+          return (-1);
+        }
+    }
+  if (write_file_real (wf, fp, mode) == -1)
+    {
+      fclose (fp);
+#ifdef WRITE_CHECK
+      delete_tmp_file (tmp);
+      delete_tmp_file (backup);
+#endif /* WRITE_CHECK */
+      return -1;
+    }
+  fclose (fp);
+#ifdef WRITE_CHECK
+  move_tmp_to_org (tmp, n, 1);
+  delete_tmp_file (backup);
+#endif /* WRITE_CHECK */
+  if ((mode == 1) || (mode == 2))
+    {
+      clear_dirty_bit (wf);
+    }
+  return (0);
+}
+
+static int
+write_file_real (struct wnn_file *wf,
+		 FILE *fp,
+		 int mode	/* 1 For All, 2 For only hindo */ )
+{
+  struct wnn_file_head fh;
+
+  if (fp)
+    rewind (fp);
+  bcopy ((char *) &wf->f_uniq, (char *) &(fh.file_uniq), WNN_F_UNIQ_LEN);
+  bcopy ((char *) &wf->f_uniq_org, (char *) &(fh.file_uniq_org), WNN_F_UNIQ_LEN);
+  bcopy (wf->passwd, fh.file_passwd, WNN_PASSWD_LEN);
+  fh.file_type = wf->file_type;
+
+  if (output_file_header (fp, &fh) == -1)
+    {
+      wnn_errorno = WNN_FILE_WRITE_ERROR;
+      goto ERROR_RET;
+    }
+  switch (fh.file_type)
+    {
+    case WNN_FT_DICT_FILE:
+      {
+        struct JT *jt2;
+        struct JT *jt = (struct JT *) wf->area;
+        if (little_endian () && jt->dirty)
+          {
+            if ((jt2 = copy_dict ((struct JT *) wf->area)) == NULL)
+              goto ERROR_RET;
+            revdic (jt2, 1);
+            if (writedict (jt2, fp) == -1)
+              goto ERROR_RET;
+            jt2 = free_dict (jt2);
+          }
+        else
+          {
+/*            if(writedict(wf->area, fp) == -1)goto ERROR_RET; */
+            if (mode == 2)
+              {
+                if (write_hindo_of_dict (wf->area, fp) == -1)
+                  goto ERROR_RET;
+              }
+            else
+              {
+                if (writedict (wf->area, fp) == -1)
+                  goto ERROR_RET;
+              }
+          }
+      }
+      break;
+    case WNN_FT_HINDO_FILE:
+      if (writehindo (wf->area, fp) == -1)
+        goto ERROR_RET;
+      break;
+    case WNN_FT_FUZOKUGO_FILE:
+      wnn_errorno = NOT_SUPPORTED_OPERATION;
+      goto ERROR_RET;
+    }
+  return (0);
+ERROR_RET:
+  return (-1);
+}
+
+static int
+writedict (struct JT *jt1, FILE *fp)
+{
+
+  if (output_header_jt (fp, jt1) == -1)
+    return (-1);
+#ifdef WRITE_CHECK
+  if ((vfwrite (jt1->comment, 2, jt1->maxcomment, fp) == -1) ||
+      (vfwrite (jt1->hinsi_list, 2, jt1->maxhinsi_list, fp) == -1) || (vfwrite (jt1->hindo, 1, jt1->maxserial, fp) == -1) || (vfwrite (jt1->hinsi, 2, jt1->maxserial, fp) == -1))
+    return (-1);
+#ifdef  CONVERT_with_SiSheng
+  if (jt1->syurui == CWNN_REV_DICT)     /* for Chinese PinYin dic only */
+    if (vfwrite (jt1->sisheng, 2, jt1->maxserial, fp) == -1)
+      return (-1);
+#endif /* CONVERT_with_SiSheng */
+  if ((vfwrite (jt1->kanji, 1, jt1->maxkanji, fp) == -1) ||
+      (vfwrite (jt1->table, sizeof (struct uind1), jt1->maxtable, fp) == -1) ||
+      (vfwrite (jt1->ri1[D_YOMI], sizeof (struct rind1),
+                jt1->maxri1[D_YOMI], fp) == -1) ||
+      (vfwrite (jt1->ri1[D_KANJI], sizeof (struct rind1),
+                jt1->maxri1[D_KANJI], fp) == -1) || (vfwrite (jt1->hontai, 1, jt1->maxhontai, fp) == -1) || (vfwrite (jt1->ri2, sizeof (struct rind2), jt1->maxri2, fp) == -1))
+    return (-1);
+#else /* WRITE_CHECK */
+  vfwrite (jt1->comment, 2, jt1->maxcomment, fp);
+  vfwrite (jt1->hinsi_list, 2, jt1->maxhinsi_list, fp);
+  vfwrite (jt1->hindo, 1, jt1->maxserial, fp);
+  vfwrite (jt1->hinsi, 2, jt1->maxserial, fp);
+#ifdef  CONVERT_with_SiSheng
+  if (jt1->syurui == CWNN_REV_DICT)     /* for Chinese PinYin dic only */
+    vfwrite (jt1->sisheng, 2, jt1->maxserial, fp);
+#endif /* CONVERT_with_SiSheng */
+  vfwrite (jt1->kanji, 1, jt1->maxkanji, fp);
+  vfwrite (jt1->table, sizeof (struct uind1), jt1->maxtable, fp);
+  vfwrite (jt1->ri1[D_YOMI], sizeof (struct rind1), jt1->maxri1[D_YOMI], fp);
+  vfwrite (jt1->ri1[D_KANJI], sizeof (struct rind1), jt1->maxri1[D_KANJI], fp);
+  vfwrite (jt1->hontai, 1, jt1->maxhontai, fp);
+  vfwrite (jt1->ri2, sizeof (struct rind2), jt1->maxri2, fp);
+#endif /* WRITE_CHECK */
+
+  return (0);
+}
+
+static int
+write_hindo_of_dict (struct JT *jt1, FILE *fp)
+{
+  if (output_header_jt (fp, jt1) == -1)
+    return (-1);
+#ifdef WRITE_CHECK
+  if ((vfwrite (jt1->comment, 2, jt1->maxcomment, fp) == -1) || (vfwrite (jt1->hindo, 1, jt1->maxserial, fp) == -1))
+    return (-1);
+#else /* WRITE_CHECK */
+  vfwrite (jt1->comment, 2, jt1->maxcomment, fp);
+  vfwrite (jt1->hindo, 1, jt1->maxserial, fp);
+#endif /* WRITE_CHECK */
+  return (0);
+}
+
+
+
+int
+discardfile (struct wnn_file *wf)
+{
+#ifdef nodef
+  FILE *fp;
+  if (wf->localf == LOCAL)
+    {
+      if ((fp = fopen (wf->name, "r")) == NULL)
+        {
+          log_err ("discardfile:No file %s.", wf->name);
+          return (-1);
+        }
+      fclose (fp);
+    }
+#endif
+  switch (wf->file_type)
+    {
+    case WNN_FT_DICT_FILE:
+      wf->area = free_dict (wf->area);
+      break;
+    case WNN_FT_HINDO_FILE:
+      wf->area = free_hindo (wf->area);
+      break;
+    case WNN_FT_FUZOKUGO_FILE:
+/*
+        fzk_discard(wf->area);
+*/
+      break;
+    }
+  return (0);
+}
+
+static struct JT *
+free_dict (struct JT *jt)
+{
+  if (jt)
+    {
+      free (jt->hindo);
+      free (jt->hinsi);
+#ifdef  CONVERT_with_SiSheng
+      free (jt->sisheng);
+#endif /* CONVERT_with_SiSheng */
+      free (jt->kanji);
+      free (jt->table);
+      free (jt->hontai);
+      free (jt->comment);
+      free (jt->hinsi_list);
+      free (jt->ri1[D_YOMI]);
+      free (jt->ri1[D_KANJI]);
+      free (jt->ri2);
+      free (jt->node);
+#ifdef  CONVERT_by_STROKE
+      free (jt->bind);
+#endif /* CONVERT_by_STROKE */
+      free (jt);
+    }
+  return (NULL);
+}
+
+
+
+static struct HJT *
+readhindo (FILE *fp)
+{
+  struct HJT *hjt1;
+
+  hjt1 = (struct HJT *) malloc (sizeof (struct HJT));
+  if (input_header_hjt (fp, hjt1) == -1)
+    {
+      wnn_errorno = WNN_NOT_A_FILE;
+      free (hjt1);
+      return (NULL);
+    }
+
+  hjt1->bufsize_serial = (hjt1->maxserial + MAXSERIAL);
+
+  hjt1->hindo = (UCHAR *) NULL;
+  hjt1->comment = (w_char *) NULL;
+  if ((hjt1->hindo = (UCHAR *) malloc (hjt1->bufsize_serial)) == NULL || (hjt1->comment = (w_char *) malloc (hjt1->maxcomment * sizeof (w_char))) == NULL)
+    {
+      wnn_errorno = WNN_MALLOC_ERR;
+      free (hjt1->hindo);
+      free (hjt1->comment);
+      free (hjt1);
+      log_err ("could not allocate hindo area.");
+      return (NULL);
+    }
+
+  if (vfread (hjt1->comment, 2, hjt1->maxcomment, fp) != hjt1->maxcomment)
+    {
+      wnn_errorno = WNN_NOT_HINDO_FILE;
+      log_err ("not a correct hindo file.");
+      goto error;
+    }
+
+  if (vfread (hjt1->hindo, 1, hjt1->maxserial, fp) != hjt1->maxserial)
+    {
+      wnn_errorno = WNN_NOT_HINDO_FILE;
+      log_err ("not a correct hindo file.");
+      goto error;
+    }
+  hjt1->hdirty = 0;
+  return (hjt1);
+error:
+  hjt1 = free_hindo (hjt1);
+  return (NULL);
+}
+
+
+static int
+writehindo (struct HJT *hjt1, FILE *fp)
+{
+  if (output_header_hjt (fp, hjt1) == -1)
+    return (-1);
+#ifdef WRITE_CHECK
+  if (vfwrite (hjt1->hindo, 1, hjt1->maxserial, fp) == -1)
+    return (-1);
+#else
+  vfwrite (hjt1->hindo, 1, hjt1->maxserial, fp);
+#endif
+  return (0);
+}
+
+static struct HJT *
+free_hindo (struct HJT *hjt)
+{
+  if (hjt)
+    {
+      free (hjt->hindo);
+      free (hjt->comment);
+      free (hjt);
+    }
+  return (NULL);
+}
+
+
+int
+create_hindo_file1 (struct wnn_file *wf,
+		    char *fn,
+		    w_char *comm,
+		    char *passwd)
+{
+
+  return (create_hindo_file (&(wf->f_uniq_org), fn, comm, passwd, ((struct JT *) (wf->area))->maxserial));
+}
+
+int
+match_dic_and_hindo_p (struct wnn_file *wfp, struct wnn_file *whfp)
+{
+  struct HJT *hjtp;
+  hjtp = (struct HJT *) (whfp->area);
+  if (bcmp ((char *) &wfp->f_uniq_org, (char *) (&(hjtp->dic_file_uniq)), WNN_F_UNIQ_LEN) == 0)
+    return (1);
+  return (0);
+}
+
+static int
+alloc_dict (struct JT *jt1)
+{
+  jt1->hindo = (UCHAR *) NULL;
+  jt1->hinsi = (unsigned short *) NULL;
+#ifdef  CONVERT_with_SiSheng
+  jt1->sisheng = (unsigned short *) NULL;
+#endif /* CONVERT_with_SiSheng */
+  jt1->kanji = (UCHAR *) NULL;
+  jt1->table = (struct uind1 *) NULL;
+  jt1->hontai = (UCHAR *) NULL;
+  jt1->comment = (w_char *) NULL;
+  jt1->hinsi_list = (w_char *) NULL;
+  jt1->ri1[D_YOMI] = (struct rind1 *) NULL;
+  jt1->ri1[D_KANJI] = (struct rind1 *) NULL;
+  jt1->ri2 = (struct rind2 *) NULL;
+  jt1->node = (struct wnn_hinsi_node *) NULL;
+#ifdef  CONVERT_by_STROKE
+  jt1->bind = (struct b_node *) NULL;
+#endif /* CONVERT_by_STROKE */
+  if (((jt1->hindo = (UCHAR *) malloc (jt1->bufsize_serial)) == NULL) || ((jt1->hinsi = (unsigned short *) (malloc (jt1->bufsize_serial * sizeof (short)))) == NULL) ||
+#ifdef  CONVERT_with_SiSheng
+      ((jt1->sisheng = (unsigned short *) (malloc (jt1->bufsize_serial * sizeof (short)))) == NULL) ||
+#endif /* CONVERT_with_SiSheng */
+      ((jt1->kanji = (UCHAR *) malloc (jt1->bufsize_kanji)) == NULL) ||
+      ((jt1->table = (struct uind1 *) malloc (jt1->bufsize_table * sizeof (struct uind1))) == NULL) ||
+      ((jt1->hontai = (UCHAR *) malloc (jt1->bufsize_hontai)) == NULL) ||
+      ((jt1->comment = (w_char *) malloc (jt1->maxcomment * sizeof (w_char))) == NULL) ||
+      ((jt1->hinsi_list = (w_char *) malloc (jt1->maxhinsi_list * sizeof (w_char))) == NULL) ||
+      ((jt1->ri1[D_YOMI] = (struct rind1 *) malloc (jt1->bufsize_ri1[D_YOMI] * sizeof (struct rind1))) == NULL) ||
+      ((jt1->ri1[D_KANJI] = (struct rind1 *) malloc (jt1->bufsize_ri1[D_KANJI] * sizeof (struct rind1))) == NULL) ||
+      ((jt1->ri2 = (struct rind2 *) malloc (jt1->bufsize_serial * sizeof (struct rind2))) == NULL))
+    {
+      wnn_errorno = WNN_MALLOC_ERR;
+      free (jt1->hindo);
+      free (jt1->hinsi);
+#ifdef  CONVERT_with_SiSheng
+      free (jt1->sisheng);
+#endif /* CONVERT_with_SiSheng */
+      free (jt1->kanji);
+      free (jt1->table);
+      free (jt1->hontai);
+      free (jt1->comment);
+      free (jt1->hinsi_list);
+      free (jt1->ri1[D_YOMI]);
+      free (jt1->ri1[D_KANJI]);
+      free (jt1->ri2);
+      log_err ("could not allocate jisho area.");
+      return (-1);
+    }
+  return (0);
+}
+
+int
+file_comment_set (struct wnn_file *wf, w_char *com)
+{
+  struct JT *jt;
+  struct HJT *hjt;
+  size_t new_size;
+  w_char *tp;
+
+  switch (wf->file_type)
+    {
+    case WNN_FT_DICT_FILE:
+      jt = (struct JT *) wf->area;
+      new_size = Strlen (com) + 1;
+      if ((tp = (w_char *) realloc (jt->comment, jt->maxcomment * sizeof (w_char))) == NULL)
+	{
+	  return (NULL);
+	}
+      jt->maxcomment = new_size;
+      jt->comment = tp;
+      Strcpy (jt->comment, com);
+      jt->dirty = 1;
+      break;
+    case WNN_FT_HINDO_FILE:
+      hjt = (struct HJT *) wf->area;
+      new_size = Strlen (com) + 1;
+      if ((tp = (w_char *) realloc (hjt->comment, new_size * sizeof (w_char))) == NULL)
+	{
+	  return (NULL);
+	}
+      hjt->maxcomment = new_size;
+      hjt->comment = tp;
+      Strcpy (hjt->comment, com);
+      hjt->hdirty = 1;
+      break;
+    case WNN_FT_FUZOKUGO_FILE:
+      wnn_errorno = NOT_SUPPORTED_OPERATION;
+      return (NULL);
+    }
+  return (SUCCESS);
+}
+
+int
+file_password_set (struct wnn_file *wf,
+		   int which,
+		   char *old,
+		   char *new)
+{
+  struct JT *jt;
+  struct HJT *hjt;
+
+  if (which == 0)
+    which = 3;
+  if (wf->file_type == WNN_FT_FUZOKUGO_FILE)
+    {
+      wnn_errorno = NOT_SUPPORTED_OPERATION;
+      return (-1);
+    }
+  if (which & 0x01 || wf->file_type == WNN_FT_HINDO_FILE)
+    {
+      if (check_and_change_pwd (wf->passwd, old, new) == -1)
+        return (-1);
+      if (wf->file_type == WNN_FT_DICT_FILE)
+        {
+          jt = (struct JT *) wf->area;
+          jt->dirty = 1;
+        }
+      else
+        {
+          hjt = (struct HJT *) wf->area;
+          hjt->hdirty = 1;
+        }
+    }
+  if (wf->file_type == WNN_FT_DICT_FILE && (which & 0x02))
+    {
+      jt = (struct JT *) wf->area;
+      if (check_and_change_pwd (jt->hpasswd, old, new) == -1)
+        return (-1);
+      jt->dirty = 1;
+    }
+  return (0);
+}
+
+static int
+check_and_change_pwd (char *pwd, char *old, char *new)
+{
+  if (!check_pwd (old, pwd))
+    {
+      wnn_errorno = WNN_INCORRECT_PASSWD;
+      return (-1);
+    }
+  new_pwd (new, pwd);
+  return (0);
+}