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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1620 - (show 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 /*
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