/[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 1621 - (hide annotations)
Wed Oct 31 23:11:40 2012 UTC (7 years, 10 months ago) by michael
File MIME type: text/x-chdr
File size: 13467 byte(s)
- src/conf_db.c: Cleanup get_file_version()

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

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