/[svn]/ircd-hybrid/trunk/src/conf_db.c
ViewVC logotype

Diff of /ircd-hybrid/trunk/src/conf_db.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1667 by michael, Sun Nov 18 17:03:18 2012 UTC revision 1668 by michael, Mon Nov 19 21:28:28 2012 UTC
# Line 1  Line 1 
1  /*  /*
2   *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).   *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3   *   *
4   *  Copyright (C) 1996-2002 by Andrew Church <achurch@achurch.org>   *  Copyright (C) 1996-2009 by Andrew Church <achurch@achurch.org>
5   *  Copyright (C) 2012 by the Hybrid Development Team.   *  Copyright (C) 2012 by the Hybrid Development Team.
6   *   *
7   *  This program is free software; you can redistribute it and/or modify   *  This program is free software; you can redistribute it and/or modify
# Line 88  write_file_version(struct dbFILE *f, uin Line 88  write_file_version(struct dbFILE *f, uin
88   * \return dbFile struct   * \return dbFile struct
89   */   */
90  static struct dbFILE *  static struct dbFILE *
91  open_db_read(const char *service, const char *filename)  open_db_read(const char *filename)
92  {  {
93    struct dbFILE *f = MyMalloc(sizeof(*f));    struct dbFILE *f = MyMalloc(sizeof(*f));
94    FILE *fp = NULL;    FILE *fp = NULL;
# Line 103  open_db_read(const char *service, const Line 103  open_db_read(const char *service, const
103      int errno_save = errno;      int errno_save = errno;
104    
105      if (errno != ENOENT)      if (errno != ENOENT)
106        ilog(LOG_TYPE_IRCD, "Can't read %s database %s", service,        ilog(LOG_TYPE_IRCD, "Can't read database file %s", f->filename);
            f->filename);  
107    
108      MyFree(f);      MyFree(f);
109      errno = errno_save;      errno = errno_save;
# Line 112  open_db_read(const char *service, const Line 111  open_db_read(const char *service, const
111    }    }
112    
113    f->fp = fp;    f->fp = fp;
   f->backupfp = NULL;  
   
114    return f;    return f;
115  }  }
116    
117  /*! \brief Open the database for writting  /*! \brief Open the database for writting
  * \param service If error whom to return the error as  
118   * \param filename File to open as the database   * \param filename File to open as the database
119   * \param version Database Version   * \param version Database Version
120   * \return dbFile struct   * \return dbFile struct
121   */   */
122  static struct dbFILE *  static struct dbFILE *
123  open_db_write(const char *service, const char *filename,  open_db_write(const char *filename, uint32_t version)
               uint32_t version)  
124  {  {
125    struct dbFILE *f = MyMalloc(sizeof(*f));    struct dbFILE *f = MyMalloc(sizeof(*f));
126    int fd = 0;    int fd = 0;
# Line 135  open_db_write(const char *service, const Line 130  open_db_write(const char *service, const
130    filename = f->filename;    filename = f->filename;
131    f->mode = 'w';    f->mode = 'w';
132    
133    snprintf(f->backupname, sizeof(f->backupname), "%s.save", filename);    snprintf(f->tempname, sizeof(f->tempname), "%s.new", filename);
134    
135    if (!*f->backupname || !strcmp(f->backupname, filename))    if (f->tempname[0] == '\0' || !strcmp(f->tempname, filename))
136    {    {
137      int errno_save = errno;      ilog(LOG_TYPE_IRCD, "Opening database file %s for write: Filename too long",
138             filename);
     ilog(LOG_TYPE_IRCD, "Opening %s database %s for write: Filename too long",  
          service, filename);  
     MyFree(f);  
     errno = errno_save;  
     return NULL;  
   }  
   
   unlink(filename);  
   
   f->backupfp = fopen(filename, "rb");  
   
   if (rename(filename, f->backupname) < 0 && errno != ENOENT)  
   {  
     int errno_save = errno;  
     static int walloped = 0;  
   
     if (!walloped++)  
       sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,  
                            "Can't back up %s database %s",  
                            service, filename);  
   
     errno = errno_save;  
     ilog(LOG_TYPE_IRCD, "Can't back up %s database %s", service, filename);  
   
     if (f->backupfp)  
       fclose(f->backupfp);  
   
139      MyFree(f);      MyFree(f);
140      errno = errno_save;      errno = ENAMETOOLONG;
141      return NULL;      return NULL;
142    }    }
143    
144    unlink(filename);    remove(f->tempname);
145    
146    /* Use open() to avoid people sneaking a new file in under us */    /* Use open() to avoid people sneaking a new file in under us */
147    if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666)) >= 0)    fd = open(f->tempname, O_WRONLY | O_CREAT | O_EXCL, 0666);
148      if (fd >= 0)
149      f->fp = fdopen(fd, "wb");      f->fp = fdopen(fd, "wb");
150    
151    if (!f->fp || !write_file_version(f, version))    if (!f->fp || !write_file_version(f, version))
# Line 186  open_db_write(const char *service, const Line 155  open_db_write(const char *service, const
155    
156      if (!walloped++)      if (!walloped++)
157        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
158                             "Can't write to %s database %s",                             "Can't create temporary database file %s",
159                             service, filename);                             f->tempname);
160    
161      errno = errno_save;      errno = errno_save;
162      ilog(LOG_TYPE_IRCD, "Can't write to %s database %s",      ilog(LOG_TYPE_IRCD, "Can't create temporary database file %s",
163           service, filename);          f->tempname);
164    
165      if (f->fp)      if (f->fp)
     {  
166        fclose(f->fp);        fclose(f->fp);
       unlink(filename);  
     }  
167    
168      if (f->backupname[0] && rename(f->backupname, filename) < 0)      remove(f->tempname);
169        ilog(LOG_TYPE_IRCD, "Can't restore backup copy of %s",      MyFree(f);
170             filename);  
171        errno = errno_save;
172       MyFree(f);      return NULL;
      errno = errno_save;  
      return NULL;  
173    }    }
174    
175    return f;    return f;
176  }  }
177    
178  /*! \brief Open a database file for reading (*mode == 'r') or writing (*mode == 'w').  /*! \brief Open a database file for reading (*mode == 'r') or writing (*mode == 'w').
179   * Return the stream pointer, or NULL on error.  When opening for write, it   * Return the stream pointer, or NULL on error.  When opening for write, the
180   * is an error for rename() to return an error (when backing up the original   * file actually opened is a temporary file, which will be renamed to the
181   * file) other than ENOENT, if NO_BACKUP_OKAY is not defined; it is an error   * original file on close.
182   * if the version number cannot be written to the file; and it is a fatal   *
183   * error if opening the file for write fails and the backup was successfully   * `version' is only used when opening a file for writing, and indicates the
184   * made but cannot be restored.   * version number to write to the file.
185   *   *
  * \param service If error whom to return the error as  
186   * \param filename File to open as the database   * \param filename File to open as the database
187   * \param mode Mode for writting or reading   * \param mode Mode for writting or reading
188   * \param version Database Version   * \param version Database Version
189   * \return dbFile struct   * \return dbFile struct
190   */   */
191  struct dbFILE *  struct dbFILE *
192  open_db(const char *service, const char *filename,  open_db(const char *filename, const char *mode, uint32_t version)
         const char *mode, uint32_t version)  
193  {  {
194    switch (*mode)    switch (*mode)
195    {    {
196      case 'r':      case 'r':
197        return open_db_read(service, filename);        return open_db_read(filename);
198        break;        break;
199      case 'w':      case 'w':
200        return open_db_write(service, filename, version);        return open_db_write(filename, version);
201        break;        break;
202      default:      default:
203        errno = EINVAL;        errno = EINVAL;
# Line 243  open_db(const char *service, const char Line 205  open_db(const char *service, const char
205    }    }
206  }  }
207    
208  /*! \brief Restore the database file to its condition before open_db().  This is  /*! \brief  Restore the database file to its condition before open_db(). This is
209   * identical to close_db() for files open for reading; however, for files   * identical to close_db() for files open for reading; however, for files
210   * open for writing, we first attempt to restore any backup file before   * open for writing, we discard the new temporary file instead of renaming
211   * closing files.   * it over the old file.  The value of errno is preserved.
212   *   *
213   * \param dbFile struct   * \param dbFile struct
214   */   */
# Line 255  restore_db(struct dbFILE *f) Line 217  restore_db(struct dbFILE *f)
217  {  {
218    int errno_save = errno;    int errno_save = errno;
219    
220    if (f->mode == 'w')    if (f->fp)
221    {      fclose(f->fp);
222      int ok = 0;             /* Did we manage to restore the old file? */    if (f->mode == 'w' && f->tempname[0])
223        remove(f->tempname);
     errno = errno_save = 0;  
   
     if (f->backupname[0] && strcmp(f->backupname, f->filename))  
       if (rename(f->backupname, f->filename) == 0)  
         ok = 1;  
   
     if (!ok && f->backupfp)  
     {  
       char buf[1024];  
       size_t i;  
   
       ok = fseek(f->fp, 0, SEEK_SET) == 0;  
   
       while (ok && (i = fread(buf, 1, sizeof(buf), f->backupfp)) > 0)  
         if (fwrite(buf, 1, i, f->fp) != i)  
           ok = 0;  
   
       if (ok)  
       {  
         fflush(f->fp);  
         ftruncate(fileno(f->fp), ftell(f->fp));  
       }  
     }  
   
     if (!ok && errno > 0)  
       ilog(LOG_TYPE_IRCD, "Unable to restore backup of %s", f->filename);  
   
     errno_save = errno;  
   
     if (f->backupfp)  
       fclose(f->backupfp);  
     if (f->backupname[0])  
       unlink(f->backupname);  
   }  
   
   fclose(f->fp);  
   
   if (!errno_save)  
     errno_save = errno;  
224    
225    MyFree(f);    MyFree(f);
226    errno = errno_save;    errno = errno_save;
227  }  }
228    
229  /*! \brief Close a database file.  If the file was opened for write, remove the  /*! \brief Close a database file.  If the file was opened for write, moves the new
230   * backup we (may have) created earlier.   * file over the old one, and logs/wallops an error message if the rename()
231     * fails.
232   *   *
233   * \param dbFile struct   * \param dbFile struct
234   */   */
235  void  int
236  close_db(struct dbFILE *f)  close_db(struct dbFILE *f)
237  {  {
238    if (f->mode == 'w' && f->backupname[0] &&    int res;
239        strcmp(f->backupname, f->filename))  
240      if (!f->fp)
241    {    {
242      if (f->backupfp)      errno = EINVAL;
243        fclose(f->backupfp);      return -1;
244      }
245    
246      res = fclose(f->fp);
247      f->fp = NULL;
248    
249      unlink(f->backupname);    if (res != 0)
250        return -1;
251    
252      if (f->mode == 'w' && f->tempname[0] && strcmp(f->tempname, f->filename))
253      {
254        if (rename(f->tempname, f->filename) < 0)
255        {
256          int errno_save = errno;
257    
258          sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "Unable to move new "
259                               "data to database file %s; new data NOT saved.",
260                               f->filename);
261          errno = errno_save;
262          ilog(LOG_TYPE_IRCD, "Unable to move new data to database file %s; new "
263               "data NOT saved.", f->filename);
264          remove(f->tempname);
265        }
266    }    }
267    
   fclose(f->fp);  
268    MyFree(f);    MyFree(f);
269      return 0;
270  }  }
271    
272  /*  /*
# Line 617  save_kline_database(void) Line 562  save_kline_database(void)
562    struct dbFILE *f = NULL;    struct dbFILE *f = NULL;
563    dlink_node *ptr = NULL;    dlink_node *ptr = NULL;
564    
565    if (!(f = open_db("kline", KPATH, "w", KLINE_DB_VERSION)))    if (!(f = open_db(KPATH, "w", KLINE_DB_VERSION)))
566      return;      return;
567    
568    for (i = 0; i < ATABLE_SIZE; ++i)    for (i = 0; i < ATABLE_SIZE; ++i)
# Line 666  load_kline_database(void) Line 611  load_kline_database(void)
611    uint64_t field_4 = 0;    uint64_t field_4 = 0;
612    uint64_t field_5 = 0;    uint64_t field_5 = 0;
613    
614    if (!(f = open_db("kline", KPATH, "r", KLINE_DB_VERSION)))    if (!(f = open_db(KPATH, "r", KLINE_DB_VERSION)))
615      return;      return;
616    
617    if (get_file_version(f) < 1)    if (get_file_version(f) < 1)
# Line 707  save_dline_database(void) Line 652  save_dline_database(void)
652    struct dbFILE *f = NULL;    struct dbFILE *f = NULL;
653    dlink_node *ptr = NULL;    dlink_node *ptr = NULL;
654    
655    if (!(f = open_db("dline", DLPATH, "w", KLINE_DB_VERSION)))    if (!(f = open_db(DLPATH, "w", KLINE_DB_VERSION)))
656      return;      return;
657    
658    for (i = 0; i < ATABLE_SIZE; ++i)    for (i = 0; i < ATABLE_SIZE; ++i)
# Line 754  load_dline_database(void) Line 699  load_dline_database(void)
699    uint64_t field_3 = 0;    uint64_t field_3 = 0;
700    uint64_t field_4 = 0;    uint64_t field_4 = 0;
701    
702    if (!(f = open_db("dline", DLPATH, "r", KLINE_DB_VERSION)))    if (!(f = open_db(DLPATH, "r", KLINE_DB_VERSION)))
703      return;      return;
704    
705    if (get_file_version(f) < 1)    if (get_file_version(f) < 1)
# Line 793  save_gline_database(void) Line 738  save_gline_database(void)
738    struct dbFILE *f = NULL;    struct dbFILE *f = NULL;
739    dlink_node *ptr = NULL;    dlink_node *ptr = NULL;
740    
741    if (!(f = open_db("gline", GPATH, "w", KLINE_DB_VERSION)))    if (!(f = open_db(GPATH, "w", KLINE_DB_VERSION)))
742      return;      return;
743    
744    for (i = 0; i < ATABLE_SIZE; ++i)    for (i = 0; i < ATABLE_SIZE; ++i)
# Line 842  load_gline_database(void) Line 787  load_gline_database(void)
787    uint64_t field_4 = 0;    uint64_t field_4 = 0;
788    uint64_t field_5 = 0;    uint64_t field_5 = 0;
789    
790    if (!(f = open_db("gline", GPATH, "r", KLINE_DB_VERSION)))    if (!(f = open_db(GPATH, "r", KLINE_DB_VERSION)))
791      return;      return;
792    
793    if (get_file_version(f) < 1)    if (get_file_version(f) < 1)
# Line 883  save_resv_database(void) Line 828  save_resv_database(void)
828    dlink_node *ptr = NULL;    dlink_node *ptr = NULL;
829    struct MaskItem *conf = NULL;    struct MaskItem *conf = NULL;
830    
831    if (!(f = open_db("resv", RESVPATH, "w", KLINE_DB_VERSION)))    if (!(f = open_db(RESVPATH, "w", KLINE_DB_VERSION)))
832      return;      return;
833    
834    DLINK_FOREACH(ptr, resv_channel_list.head)    DLINK_FOREACH(ptr, resv_channel_list.head)
# Line 944  load_resv_database(void) Line 889  load_resv_database(void)
889    char *reason = NULL;    char *reason = NULL;
890    struct MaskItem *conf = NULL;    struct MaskItem *conf = NULL;
891    
892    if (!(f = open_db("resv", RESVPATH, "r", KLINE_DB_VERSION)))    if (!(f = open_db(RESVPATH, "r", KLINE_DB_VERSION)))
893      return;      return;
894    
895    if (get_file_version(f) < 1)    if (get_file_version(f) < 1)
# Line 996  save_xline_database(void) Line 941  save_xline_database(void)
941    dlink_node *ptr = NULL;    dlink_node *ptr = NULL;
942    struct MaskItem *conf = NULL;    struct MaskItem *conf = NULL;
943    
944    if (!(f = open_db("xline", XPATH, "w", KLINE_DB_VERSION)))    if (!(f = open_db(XPATH, "w", KLINE_DB_VERSION)))
945      return;      return;
946    
947    DLINK_FOREACH(ptr, xconf_items.head)    DLINK_FOREACH(ptr, xconf_items.head)
# Line 1036  load_xline_database(void) Line 981  load_xline_database(void)
981    char *reason = NULL;    char *reason = NULL;
982    struct MaskItem *conf = NULL;    struct MaskItem *conf = NULL;
983    
984    if (!(f = open_db("xline", XPATH, "r", KLINE_DB_VERSION)))    if (!(f = open_db(XPATH, "r", KLINE_DB_VERSION)))
985      return;      return;
986    
987    if (get_file_version(f) < 1)    if (get_file_version(f) < 1)

Legend:
Removed from v.1667  
changed lines
  Added in v.1668

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28