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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1620 - (hide annotations)
Wed Oct 31 22:54:58 2012 UTC (7 years, 10 months ago) by michael
File MIME type: text/x-chdr
File size: 13642 byte(s)
- Added conf_db.c based on ircservice's binary database for later use

1 michael 1620 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     *
4     * Copyright (C) 1996-2002 by Andrew Church <achurch@achurch.org>
5     * Copyright (C) 2012 by the Hybrid Development Team.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     */
22    
23     /*! \file conf_db.c
24     * \brief Includes file utilities for database handling
25     * \version $Id: conf_db.c 1569 2012-10-16 18:46:53Z michael $
26     */
27    
28     #include "stdinc.h"
29     #include "conf_db.h"
30     #include "memory.h"
31     #include "client.h"
32     #include "log.h"
33     #include "send.h"
34     #include "irc_string.h"
35    
36    
37     /*! \brief Return the version number on the file. Return 0 if there is no version
38     * number or the number doesn't make sense (i.e. less than 1 or greater
39     * than FILE_VERSION).
40     *
41     * \param f dbFile Struct Member
42     * \return int 0 if failure, 1 > is the version number
43     */
44     int
45     get_file_version(struct dbFILE *f)
46     {
47     FILE *fp = f->fp;
48     int version = fgetc(fp) << 24 | fgetc(fp) << 16 | fgetc(fp) << 8 | fgetc(fp);
49    
50     if (ferror(fp))
51     {
52     ilog(LOG_TYPE_IRCD, "Error reading version number on %s", f->filename);
53     return 0;
54     }
55     else if (feof(fp))
56     {
57     ilog(LOG_TYPE_IRCD, "Error reading version number on %s: End of file detected",
58     f->filename);
59     return 0;
60     }
61     else if (version < 1)
62     {
63     ilog(LOG_TYPE_IRCD, "Invalid version number (%d) on %s",
64     version, f->filename);
65     return 0;
66     }
67    
68     return version;
69     }
70    
71     /*! \brief Write the current version number to the file.
72     * \param f dbFile Struct Member
73     * \return 0 on error, 1 on success.
74     */
75     int
76     write_file_version(struct dbFILE *f, uint32_t version)
77     {
78     if (write_uint32(version, f) == -1)
79     {
80     ilog(LOG_TYPE_IRCD, "Error writing version number on %s",
81     f->filename);
82     return 0;
83     }
84    
85     return 1;
86     }
87    
88     /*! \brief Open the database for reading
89     * \param service If error whom to return the error as
90     * \param filename File to open as the database
91     * \return dbFile struct
92     */
93     static struct dbFILE *
94     open_db_read(const char *service, const char *filename)
95     {
96     struct dbFILE *f = MyMalloc(sizeof(*f));
97     FILE *fp = NULL;
98    
99     strlcpy(f->filename, filename, sizeof(f->filename));
100    
101     f->mode = 'r';
102     fp = fopen(f->filename, "rb");
103    
104     if (!fp)
105     {
106     int errno_save = errno;
107    
108     if (errno != ENOENT)
109     ilog(LOG_TYPE_IRCD, "Can not read %s database %s", service,
110     f->filename);
111    
112     MyFree(f);
113     errno = errno_save;
114     return NULL;
115     }
116    
117     f->fp = fp;
118     f->backupfp = NULL;
119    
120     return f;
121     }
122    
123     /*! \brief Open the database for writting
124     * \param service If error whom to return the error as
125     * \param filename File to open as the database
126     * \param version Database Version
127     * \return dbFile struct
128     */
129     static struct dbFILE *
130     open_db_write(const char *service, const char *filename,
131     uint32_t version)
132     {
133     struct dbFILE *f = MyMalloc(sizeof(*f));
134     int fd = 0;
135    
136     strlcpy(f->filename, filename, sizeof(f->filename));
137    
138     filename = f->filename;
139     f->mode = 'w';
140    
141     snprintf(f->backupname, sizeof(f->backupname), "%s.save", filename);
142    
143     if (!*f->backupname || !strcmp(f->backupname, filename))
144     {
145     int errno_save = errno;
146    
147     ilog(LOG_TYPE_IRCD, "Opening %s database %s for write: Filename too long",
148     service, filename);
149     MyFree(f);
150     errno = errno_save;
151     return NULL;
152     }
153    
154     unlink(filename);
155    
156     f->backupfp = fopen(filename, "rb");
157    
158     if (rename(filename, f->backupname) < 0 && errno != ENOENT)
159     {
160     int errno_save = errno;
161     static int walloped = 0;
162    
163     if (!walloped++)
164     sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
165     "Can not back up %s database %s",
166     service, filename);
167    
168     errno = errno_save;
169     ilog(LOG_TYPE_IRCD, "Can not back up %s database %s", service, filename);
170    
171     if (f->backupfp)
172     fclose(f->backupfp);
173    
174     MyFree(f);
175     errno = errno_save;
176     return NULL;
177     }
178    
179     unlink(filename);
180    
181     /* Use open() to avoid people sneaking a new file in under us */
182     fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0666);
183     f->fp = fdopen(fd, "wb"); /* will fail and return NULL if fd < 0 */
184    
185     if (!f->fp || !write_file_version(f, version))
186     {
187     int errno_save = errno;
188     static int walloped = 0;
189    
190     if (!walloped++)
191     sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
192     "Can't write to %s database %s",
193     service, filename);
194    
195     errno = errno_save;
196     ilog(LOG_TYPE_IRCD, "Can't write to %s database %s",
197     service, filename);
198    
199     if (f->fp)
200     {
201     fclose(f->fp);
202     unlink(filename);
203     }
204    
205     if (f->backupname[0] && rename(f->backupname, filename) < 0)
206     ilog(LOG_TYPE_IRCD, "Cannot restore backup copy of %s",
207     filename);
208    
209     MyFree(f);
210     errno = errno_save;
211     return NULL;
212     }
213    
214     return f;
215     }
216    
217     /*! \brief Open a database file for reading (*mode == 'r') or writing (*mode == 'w').
218     * Return the stream pointer, or NULL on error. When opening for write, it
219     * is an error for rename() to return an error (when backing up the original
220     * file) other than ENOENT, if NO_BACKUP_OKAY is not defined; it is an error
221     * if the version number cannot be written to the file; and it is a fatal
222     * error if opening the file for write fails and the backup was successfully
223     * made but cannot be restored.
224     *
225     * \param service If error whom to return the error as
226     * \param filename File to open as the database
227     * \param mode Mode for writting or reading
228     * \param version Database Version
229     * \return dbFile struct
230     */
231     struct dbFILE *
232     open_db(const char *service, const char *filename,
233     const char *mode, uint32_t version)
234     {
235     switch (*mode)
236     {
237     case 'r':
238     return open_db_read(service, filename);
239     break;
240     case 'w':
241     return open_db_write(service, filename, version);
242     break;
243     default:
244     errno = EINVAL;
245     return NULL;
246     }
247     }
248    
249     /*! \brief Restore the database file to its condition before open_db(). This is
250     * identical to close_db() for files open for reading; however, for files
251     * open for writing, we first attempt to restore any backup file before
252     * closing files.
253     *
254     * \param dbFile struct
255     */
256     void
257     restore_db(struct dbFILE *f)
258     {
259     int errno_save = errno;
260    
261     if (f->mode == 'w')
262     {
263     int ok = 0; /* Did we manage to restore the old file? */
264    
265     errno = errno_save = 0;
266    
267     if (f->backupname[0] && strcmp(f->backupname, f->filename))
268     if (rename(f->backupname, f->filename) == 0)
269     ok = 1;
270    
271     if (!ok && f->backupfp)
272     {
273     char buf[1024];
274     size_t i;
275    
276     ok = fseek(f->fp, 0, SEEK_SET) == 0;
277    
278     while (ok && (i = fread(buf, 1, sizeof(buf), f->backupfp)) > 0)
279     if (fwrite(buf, 1, i, f->fp) != i)
280     ok = 0;
281    
282     if (ok)
283     {
284     fflush(f->fp);
285     ftruncate(fileno(f->fp), ftell(f->fp));
286     }
287     }
288    
289     if (!ok && errno > 0)
290     ilog(LOG_TYPE_IRCD, "Unable to restore backup of %s", f->filename);
291    
292     errno_save = errno;
293    
294     if (f->backupfp)
295     fclose(f->backupfp);
296     if (f->backupname[0])
297     unlink(f->backupname);
298     }
299    
300     fclose(f->fp);
301    
302     if (!errno_save)
303     errno_save = errno;
304    
305     MyFree(f);
306     errno = errno_save;
307     }
308    
309     /*! \brief Close a database file. If the file was opened for write, remove the
310     * backup we (may have) created earlier.
311     *
312     * \param dbFile struct
313     */
314     void
315     close_db(struct dbFILE *f)
316     {
317     if (f->mode == 'w' && f->backupname[0] &&
318     strcmp(f->backupname, f->filename))
319     {
320     if (f->backupfp)
321     fclose(f->backupfp);
322    
323     unlink(f->backupname);
324     }
325    
326     fclose(f->fp);
327     MyFree(f);
328     }
329    
330     /*
331     * Read and write 2-, 4- and 8-byte quantities, pointers, and strings. All
332     * multibyte values are stored in big-endian order (most significant byte
333     * first). A pointer is stored as a byte, either 0 if NULL or 1 if not,
334     * and read pointers are returned as either (void *)0 or (void *)1. A
335     * string is stored with a 2-byte unsigned length (including the trailing
336     * \0) first; a length of 0 indicates that the string pointer is NULL.
337     * Written strings are truncated silently at 65534 bytes, and are always
338     * null-terminated.
339     */
340    
341     /*! \brief Read a unsigned 8bit integer
342     *
343     * \param ret 8bit integer to read
344     * \param dbFile struct
345     * \return -1 on error, 0 otherwise.
346     */
347     int
348     read_uint8(unsigned char *ret, struct dbFILE *f)
349     {
350     int c = fgetc(f->fp);
351    
352     if (c == EOF)
353     return -1;
354    
355     *ret = c;
356     return 0;
357     }
358    
359     /*! \brief Write a 8bit integer
360     *
361     * \param ret 8bit integer to write
362     * \param dbFile struct
363     * \return -1 on error, 0 otherwise.
364     */
365     int
366     write_uint8(unsigned char val, struct dbFILE *f)
367     {
368     if (fputc(val, f->fp) == EOF)
369     return -1;
370    
371     return 0;
372     }
373    
374     /*! \brief Read a unsigned 8bit integer
375     *
376     * \param ret 8bit integer to read
377     * \param dbFile struct
378     * \return -1 on error, 0 otherwise.
379     */
380     int
381     read_uint16(uint16_t *ret, struct dbFILE *f)
382     {
383     int c1 = fgetc(f->fp);
384     int c2 = fgetc(f->fp);
385    
386     if (c1 == EOF || c2 == EOF)
387     return -1;
388    
389     *ret = c1 << 8 | c2;
390     return 0;
391     }
392    
393     /*! \brief Write a unsigned 16bit integer
394     *
395     * \param ret 16bit integer to write
396     * \param dbFile struct
397     * \return -1 on error, 0 otherwise.
398     */
399     int
400     write_uint16(uint16_t val, struct dbFILE *f)
401     {
402     if (fputc((val >> 8) & 0xFF, f->fp) == EOF ||
403     fputc(val & 0xFF, f->fp) == EOF)
404     return -1;
405    
406     return 0;
407     }
408    
409     /*! \brief Read a unsigned 32bit integer
410     *
411     * \param ret unsigned 32bit integer to read
412     * \param dbFile struct
413     * \return -1 on error, 0 otherwise.
414     */
415     int
416     read_uint32(uint32_t *ret, struct dbFILE *f)
417     {
418     int c1 = fgetc(f->fp);
419     int c2 = fgetc(f->fp);
420     int c3 = fgetc(f->fp);
421     int c4 = fgetc(f->fp);
422    
423     if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF)
424     return -1;
425    
426     *ret = c1 << 24 | c2 << 16 | c3 << 8 | c4;
427     return 0;
428     }
429    
430    
431     /*! \brief Write a unsigned 32bit integer
432     *
433     * \param ret unsigned 32bit integer to write
434     * \param dbFile struct
435     * \return -1 on error, 0 otherwise.
436     */
437     int
438     write_uint32(uint32_t val, struct dbFILE *f)
439     {
440     if (fputc((val >> 24) & 0xFF, f->fp) == EOF)
441     return -1;
442     if (fputc((val >> 16) & 0xFF, f->fp) == EOF)
443     return -1;
444     if (fputc((val >> 8) & 0xFF, f->fp) == EOF)
445     return -1;
446     if (fputc((val) & 0xFF, f->fp) == EOF)
447     return -1;
448     return 0;
449     }
450    
451     /*! \brief Read a unsigned 64bit integer
452     *
453     * \param ret unsigned 64bit integer to read
454     * \param dbFile struct
455     * \return -1 on error, 0 otherwise.
456     */
457     int
458     read_uint64(uint64_t *ret, struct dbFILE *f)
459     {
460     int64_t c1 = fgetc(f->fp);
461     int64_t c2 = fgetc(f->fp);
462     int64_t c3 = fgetc(f->fp);
463     int64_t c4 = fgetc(f->fp);
464     int64_t c5 = fgetc(f->fp);
465     int64_t c6 = fgetc(f->fp);
466     int64_t c7 = fgetc(f->fp);
467     int64_t c8 = fgetc(f->fp);
468    
469     if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF ||
470     c5 == EOF || c6 == EOF || c7 == EOF || c8 == EOF)
471     return -1;
472    
473     *ret = c1 << 56 | c2 << 48 | c3 << 40 | c4 << 32 |
474     c5 << 24 | c6 << 16 | c7 << 8 | c8;
475     return 0;
476     }
477    
478    
479     /*! \brief Write a unsigned 64bit integer
480     *
481     * \param ret unsigned 64bit integer to write
482     * \param dbFile struct
483     * \return -1 on error, 0 otherwise.
484     */
485     int
486     write_uint64(uint64_t val, struct dbFILE *f)
487     {
488     if (fputc((val >> 56) & 0xFF, f->fp) == EOF)
489     return -1;
490     if (fputc((val >> 48) & 0xFF, f->fp) == EOF)
491     return -1;
492     if (fputc((val >> 40) & 0xFF, f->fp) == EOF)
493     return -1;
494     if (fputc((val >> 32) & 0xFF, f->fp) == EOF)
495     return -1;
496     if (fputc((val >> 24) & 0xFF, f->fp) == EOF)
497     return -1;
498     if (fputc((val >> 16) & 0xFF, f->fp) == EOF)
499     return -1;
500     if (fputc((val >> 8) & 0xFF, f->fp) == EOF)
501     return -1;
502     if (fputc((val) & 0xFF, f->fp) == EOF)
503     return -1;
504     return 0;
505     }
506    
507     /*! \brief Read Pointer
508     *
509     * \param ret pointer to read
510     * \param dbFile struct
511     * \return -1 on error, 0 otherwise.
512     */
513     int
514     read_ptr(void **ret, struct dbFILE *f)
515     {
516     int c = fgetc(f->fp);
517    
518     if (c == EOF)
519     return -1;
520    
521     *ret = (c ? (void *)1 : (void *)0);
522     return 0;
523     }
524    
525    
526     /*! \brief Write Pointer
527     *
528     * \param ret pointer to write
529     * \param dbFile struct
530     * \return -1 on error, 0 otherwise.
531     */
532     int
533     write_ptr(const void *ptr, struct dbFILE *f)
534     {
535     if (fputc(ptr ? 1 : 0, f->fp) == EOF)
536     return -1;
537     return 0;
538     }
539    
540     /*! \brief Read String
541     *
542     * \param ret string
543     * \param dbFile struct
544     * \return -1 on error, 0 otherwise.
545     */
546     int
547     read_string(char **ret, struct dbFILE *f)
548     {
549     char *s = NULL;
550     uint16_t len = 0;
551    
552     if (read_uint16(&len, f) < 0)
553     return -1;
554    
555     if (len == 0)
556     {
557     *ret = NULL;
558     return 0;
559     }
560    
561     s = MyMalloc(len);
562    
563     if (len != fread(s, 1, len, f->fp))
564     {
565     MyFree(s);
566     return -1;
567     }
568    
569     *ret = s;
570     return 0;
571     }
572    
573     /*! \brief Write String
574     *
575     * \param ret string
576     * \param dbFile struct
577     * \return -1 on error, 0 otherwise.
578     */
579     int
580     write_string(const char *s, struct dbFILE *f)
581     {
582     uint32_t len = 0;
583    
584     if (!s)
585     return write_uint16(0, f);
586    
587     len = strlen(s);
588    
589     if (len > 65534)
590     len = 65534;
591     if (write_uint16((uint16_t)(len + 1), f) < 0)
592     return -1;
593     if (len > 0 && fwrite(s, 1, len, f->fp) != len)
594     return -1;
595     if (fputc(0, f->fp) == EOF)
596     return -1;
597    
598     return 0;
599     }

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