Switch from bioq_insert_tail() to bioqdisksort(). When the kernel is
[dragonfly.git] / contrib / dhcp-3.0 / server / db.c
blob614d6a01ec707ce51462fb90ce968b9abdc95ac3
1 /* db.c
3 Persistent database management routines for DHCPD... */
5 /*
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
35 #ifndef lint
36 static char copyright[] =
37 "$Id: db.c,v 1.63.2.11 2004/06/17 20:54:40 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
38 #endif /* not lint */
40 #include "dhcpd.h"
41 #include <ctype.h>
42 #include "version.h"
44 FILE *db_file;
46 static int counting = 0;
47 static int count = 0;
48 TIME write_time;
49 int lease_file_is_corrupt = 0;
51 /* Write the specified lease to the current lease database file. */
53 int write_lease (lease)
54 struct lease *lease;
56 struct tm *t;
57 char tbuf [64];
58 int errors = 0;
59 int i;
60 struct binding *b;
61 char *s;
63 /* If the lease file is corrupt, don't try to write any more leases
64 until we've written a good lease file. */
65 if (lease_file_is_corrupt)
66 if (!new_lease_file ())
67 return 0;
69 if (counting)
70 ++count;
71 errno = 0;
72 fprintf (db_file, "lease %s {", piaddr (lease -> ip_addr));
73 if (errno) {
74 ++errors;
77 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
78 somebody invents a time machine, I think we can safely disregard
79 it. */
80 if (lease -> starts) {
81 if (lease -> starts != MAX_TIME) {
82 t = gmtime (&lease -> starts);
83 /* %Audit% Cannot exceed 59 bytes. %2004.06.17,Safe% */
84 sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
85 t -> tm_wday, t -> tm_year + 1900,
86 t -> tm_mon + 1, t -> tm_mday,
87 t -> tm_hour, t -> tm_min, t -> tm_sec);
88 } else
89 strcpy (tbuf, "never;");
90 errno = 0;
91 fprintf (db_file, "\n starts %s", tbuf);
92 if (errno) {
93 ++errors;
97 if (lease -> ends) {
98 if (lease -> ends != MAX_TIME) {
99 t = gmtime (&lease -> ends);
100 /* %Audit% Cannot exceed 59 bytes. %2004.06.17,Safe% */
101 sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;",
102 t -> tm_wday, t -> tm_year + 1900,
103 t -> tm_mon + 1, t -> tm_mday,
104 t -> tm_hour, t -> tm_min, t -> tm_sec);
105 } else
106 strcpy (tbuf, "never;");
107 errno = 0;
108 fprintf (db_file, "\n ends %s", tbuf);
109 if (errno) {
110 ++errors;
114 if (lease -> tstp) {
115 t = gmtime (&lease -> tstp);
116 errno = 0;
117 fprintf (db_file, "\n tstp %d %d/%02d/%02d %02d:%02d:%02d;",
118 t -> tm_wday, t -> tm_year + 1900,
119 t -> tm_mon + 1, t -> tm_mday,
120 t -> tm_hour, t -> tm_min, t -> tm_sec);
121 if (errno) {
122 ++errors;
125 if (lease -> tsfp) {
126 t = gmtime (&lease -> tsfp);
127 errno = 0;
128 fprintf (db_file, "\n tsfp %d %d/%02d/%02d %02d:%02d:%02d;",
129 t -> tm_wday, t -> tm_year + 1900,
130 t -> tm_mon + 1, t -> tm_mday,
131 t -> tm_hour, t -> tm_min, t -> tm_sec);
132 if (errno) {
133 ++errors;
136 if (lease -> cltt) {
137 t = gmtime (&lease -> cltt);
138 errno = 0;
139 fprintf (db_file, "\n cltt %d %d/%02d/%02d %02d:%02d:%02d;",
140 t -> tm_wday, t -> tm_year + 1900,
141 t -> tm_mon + 1, t -> tm_mday,
142 t -> tm_hour, t -> tm_min, t -> tm_sec);
143 if (errno) {
144 ++errors;
148 if (lease -> binding_state == FTS_ACTIVE &&
149 (lease -> flags & BOOTP_LEASE)) {
150 fprintf (db_file, "\n binding state bootp;\n");
151 } else {
152 fprintf (db_file, "\n binding state %s;",
153 ((lease -> binding_state > 0 &&
154 lease -> binding_state <= FTS_LAST)
155 ? binding_state_names [lease -> binding_state - 1]
156 : "abandoned"));
159 if (lease -> binding_state != lease -> next_binding_state) {
160 if (lease -> next_binding_state == FTS_ACTIVE &&
161 (lease -> flags & BOOTP_LEASE))
162 fprintf (db_file, "\n next binding state bootp;\n");
163 else
164 fprintf (db_file, "\n next binding state %s;",
165 ((lease -> next_binding_state > 0 &&
166 lease -> next_binding_state <= FTS_LAST)
167 ? (binding_state_names
168 [lease -> next_binding_state - 1])
169 : "abandoned"));
172 /* If this lease is billed to a class and is still valid,
173 write it out. */
174 if (lease -> billing_class && lease -> ends > cur_time) {
175 if (!write_billing_class (lease -> billing_class)) {
176 log_error ("unable to write class %s",
177 lease -> billing_class -> name);
178 ++errors;
182 if (lease -> hardware_addr.hlen) {
183 errno = 0;
184 fprintf (db_file, "\n hardware %s %s;",
185 hardware_types [lease -> hardware_addr.hbuf [0]],
186 print_hw_addr (lease -> hardware_addr.hbuf [0],
187 lease -> hardware_addr.hlen - 1,
188 &lease -> hardware_addr.hbuf [1]));
189 if (errno) {
190 ++errors;
193 if (lease -> uid_len) {
194 int i;
195 s = quotify_buf (lease -> uid, lease -> uid_len, MDL);
196 if (s) {
197 fprintf (db_file, "\n uid \"%s\";", s);
198 if (errno)
199 ++errors;
200 dfree (s, MDL);
201 } else
202 ++errors;
204 if (lease -> scope) {
205 for (b = lease -> scope -> bindings; b; b = b -> next) {
206 if (!b -> value)
207 continue;
208 if (b -> value -> type == binding_data) {
209 if (b -> value -> value.data.data) {
210 s = quotify_buf (b -> value -> value.data.data,
211 b -> value -> value.data.len, MDL);
212 if (s) {
213 errno = 0;
214 fprintf (db_file, "\n set %s = \"%s\";",
215 b -> name, s);
216 if (errno)
217 ++errors;
218 dfree (s, MDL);
219 } else
220 ++errors;
222 } else if (b -> value -> type == binding_numeric) {
223 errno = 0;
224 fprintf (db_file, "\n set %s = %%%ld;",
225 b -> name, b -> value -> value.intval);
226 if (errno)
227 ++errors;
228 } else if (b -> value -> type == binding_boolean) {
229 errno = 0;
230 fprintf (db_file, "\n set %s = %s;",
231 b -> name,
232 b -> value -> value.intval ? "true" : "false");
233 if (errno)
234 ++errors;
235 } else if (b -> value -> type == binding_dns) {
236 log_error ("%s: persistent dns values not supported.",
237 b -> name);
238 } else if (b -> value -> type == binding_function) {
239 log_error ("%s: persistent functions not supported.",
240 b -> name);
241 } else {
242 log_error ("%s: unknown binding type %d",
243 b -> name, b -> value -> type);
247 if (lease -> agent_options) {
248 struct option_cache *oc;
249 struct data_string ds;
250 pair p;
252 memset (&ds, 0, sizeof ds);
253 for (p = lease -> agent_options -> first; p; p = p -> cdr) {
254 oc = (struct option_cache *)p -> car;
255 if (oc -> data.len) {
256 errno = 0;
257 fprintf (db_file, "\n option agent.%s %s;",
258 oc -> option -> name,
259 pretty_print_option (oc -> option, oc -> data.data,
260 oc -> data.len, 1, 1));
261 if (errno)
262 ++errors;
266 if (lease -> client_hostname &&
267 db_printable (lease -> client_hostname)) {
268 s = quotify_string (lease -> client_hostname, MDL);
269 if (s) {
270 errno = 0;
271 fprintf (db_file, "\n client-hostname \"%s\";", s);
272 if (errno)
273 ++errors;
274 dfree (s, MDL);
275 } else
276 ++errors;
278 if (lease -> on_expiry) {
279 errno = 0;
280 fprintf (db_file, "\n on expiry%s {",
281 lease -> on_expiry == lease -> on_release
282 ? " or release" : "");
283 if (errno)
284 ++errors;
285 write_statements (db_file, lease -> on_expiry, 4);
286 /* XXX */
287 fprintf (db_file, "\n }");
289 if (lease -> on_release && lease -> on_release != lease -> on_expiry) {
290 errno = 0;
291 fprintf (db_file, "\n on release {");
292 if (errno)
293 ++errors;
294 write_statements (db_file, lease -> on_release, 4);
295 /* XXX */
296 fprintf (db_file, "\n }");
298 errno = 0;
299 fputs ("\n}\n", db_file);
300 if (errno) {
301 ++errors;
303 if (errors)
304 log_info ("write_lease: unable to write lease %s",
305 piaddr (lease -> ip_addr));
306 if (errors)
307 lease_file_is_corrupt = 1;
308 return !errors;
311 int write_host (host)
312 struct host_decl *host;
314 int errors = 0;
315 int i;
316 struct data_string ip_addrs;
318 /* If the lease file is corrupt, don't try to write any more leases
319 until we've written a good lease file. */
320 if (lease_file_is_corrupt)
321 if (!new_lease_file ())
322 return 0;
324 if (!db_printable (host -> name))
325 return 0;
327 if (counting)
328 ++count;
329 errno = 0;
331 fprintf (db_file, "host %s {", host -> name);
332 if (errno) {
333 ++errors;
336 if (host -> flags & HOST_DECL_DYNAMIC) {
337 errno = 0;
338 fprintf (db_file, "\n dynamic;");
339 if (errno)
340 ++errors;
343 if (host -> flags & HOST_DECL_DELETED) {
344 errno = 0;
345 fprintf (db_file, "\n deleted;");
346 if (errno)
347 ++errors;
348 } else {
349 if (host -> interface.hlen) {
350 errno = 0;
351 fprintf (db_file, "\n hardware %s %s;",
352 hardware_types [host -> interface.hbuf [0]],
353 print_hw_addr (host -> interface.hbuf [0],
354 host -> interface.hlen - 1,
355 &host -> interface.hbuf [1]));
356 if (errno) {
357 ++errors;
360 if (host -> client_identifier.len) {
361 int i;
362 errno = 0;
363 if (db_printable_len (host -> client_identifier.data,
364 host -> client_identifier.len)) {
365 fprintf (db_file, "\n uid \"%.*s\";",
366 (int)host -> client_identifier.len,
367 host -> client_identifier.data);
368 } else {
369 fprintf (db_file,
370 "\n uid %2.2x",
371 host -> client_identifier.data [0]);
372 if (errno) {
373 ++errors;
375 for (i = 1;
376 i < host -> client_identifier.len; i++) {
377 errno = 0;
378 fprintf (db_file, ":%2.2x",
379 host ->
380 client_identifier.data [i]);
381 if (errno) {
382 ++errors;
385 putc (';', db_file);
389 memset (&ip_addrs, 0, sizeof ip_addrs);
390 if (host -> fixed_addr &&
391 evaluate_option_cache (&ip_addrs, (struct packet *)0,
392 (struct lease *)0,
393 (struct client_state *)0,
394 (struct option_state *)0,
395 (struct option_state *)0,
396 &global_scope,
397 host -> fixed_addr, MDL)) {
399 errno = 0;
400 fprintf (db_file, "\n fixed-address ");
401 if (errno) {
402 ++errors;
404 for (i = 0; i < ip_addrs.len - 3; i += 4) {
405 errno = 0;
406 fprintf (db_file, "%u.%u.%u.%u%s",
407 ip_addrs.data [i] & 0xff,
408 ip_addrs.data [i + 1] & 0xff,
409 ip_addrs.data [i + 2] & 0xff,
410 ip_addrs.data [i + 3] & 0xff,
411 i + 7 < ip_addrs.len ? "," : "");
412 if (errno) {
413 ++errors;
416 errno = 0;
417 fputc (';', db_file);
418 if (errno) {
419 ++errors;
423 if (host -> named_group) {
424 errno = 0;
425 fprintf (db_file, "\n group \"%s\";",
426 host -> named_group -> name);
427 if (errno) {
428 ++errors;
432 if (host -> group &&
433 (!host -> named_group ||
434 host -> group != host -> named_group -> group) &&
435 host -> group != root_group) {
436 errno = 0;
437 write_statements (db_file,
438 host -> group -> statements, 8);
439 if (errno) {
440 ++errors;
445 errno = 0;
446 fputs ("\n}\n", db_file);
447 if (errno) {
448 ++errors;
450 if (errors) {
451 log_info ("write_host: unable to write host %s",
452 host -> name);
453 lease_file_is_corrupt = 1;
455 return !errors;
458 int write_group (group)
459 struct group_object *group;
461 int errors = 0;
462 int i;
464 /* If the lease file is corrupt, don't try to write any more leases
465 until we've written a good lease file. */
466 if (lease_file_is_corrupt)
467 if (!new_lease_file ())
468 return 0;
470 if (!db_printable (group -> name))
471 return 0;
473 if (counting)
474 ++count;
475 errno = 0;
477 fprintf (db_file, "group %s {", group -> name);
478 if (errno) {
479 ++errors;
482 if (group -> flags & GROUP_OBJECT_DYNAMIC) {
483 errno = 0;
484 fprintf (db_file, "\n dynamic;");
485 if (errno)
486 ++errors;
489 if (group -> flags & GROUP_OBJECT_STATIC) {
490 errno = 0;
491 fprintf (db_file, "\n static;");
492 if (errno)
493 ++errors;
496 if (group -> flags & GROUP_OBJECT_DELETED) {
497 errno = 0;
498 fprintf (db_file, "\n deleted;");
499 if (errno)
500 ++errors;
501 } else {
502 if (group -> group) {
503 errno = 0;
504 write_statements (db_file,
505 group -> group -> statements, 8);
506 if (errno) {
507 ++errors;
512 errno = 0;
513 fputs ("\n}\n", db_file);
514 if (errno) {
515 ++errors;
517 if (errors) {
518 log_info ("write_group: unable to write group %s",
519 group -> name);
520 lease_file_is_corrupt = 1;
522 return !errors;
525 #if defined (FAILOVER_PROTOCOL)
526 int write_failover_state (dhcp_failover_state_t *state)
528 struct tm *t;
529 int errors = 0;
531 if (lease_file_is_corrupt)
532 if (!new_lease_file ())
533 return 0;
535 errno = 0;
536 fprintf (db_file, "\nfailover peer \"%s\" state {", state -> name);
537 if (errno)
538 ++errors;
540 t = gmtime (&state -> me.stos);
541 errno = 0;
542 fprintf (db_file, "\n my state %s at %d %d/%02d/%02d %02d:%02d:%02d;",
543 /* Never record our state as "startup"! */
544 (state -> me.state == startup
545 ? dhcp_failover_state_name_print (state -> saved_state)
546 : dhcp_failover_state_name_print (state -> me.state)),
547 t -> tm_wday, t -> tm_year + 1900,
548 t -> tm_mon + 1, t -> tm_mday,
549 t -> tm_hour, t -> tm_min, t -> tm_sec);
550 if (errno)
551 ++errors;
553 t = gmtime (&state -> partner.stos);
554 errno = 0;
555 fprintf (db_file,
556 "\n partner state %s at %d %d/%02d/%02d %02d:%02d:%02d;",
557 dhcp_failover_state_name_print (state -> partner.state),
558 t -> tm_wday, t -> tm_year + 1900,
559 t -> tm_mon + 1, t -> tm_mday,
560 t -> tm_hour, t -> tm_min, t -> tm_sec);
561 if (errno)
562 ++errors;
564 if (state -> i_am == secondary) {
565 errno = 0;
566 fprintf (db_file, "\n mclt %ld;",
567 (unsigned long)state -> mclt);
568 if (errno)
569 ++errors;
571 fprintf (db_file, "\n}\n");
572 if (errno)
573 ++errors;
575 if (errors) {
576 log_info ("write_failover_state: unable to write state %s",
577 state -> name);
578 lease_file_is_corrupt = 1;
579 return 0;
581 return 1;
584 #endif
586 int db_printable (s)
587 const char *s;
589 int i;
590 for (i = 0; s [i]; i++)
591 if (!isascii (s [i]) || !isprint (s [i])
592 || s [i] == '"' || s [i] == '\\')
593 return 0;
594 return 1;
597 int db_printable_len (s, len)
598 const unsigned char *s;
599 unsigned len;
601 int i;
602 for (i = 0; i < len; i++)
603 if (!isascii (s [i]) || !isprint (s [i]) ||
604 s [i] == '"' || s [i] == '\\')
605 return 0;
606 return 1;
609 void write_named_billing_class (const char *name, unsigned len,
610 struct class *class)
612 /* XXX billing classes that are modified by OMAPI need
613 XXX to be detected and written out here. */
616 void write_billing_classes ()
618 struct collection *lp;
619 struct class *cp;
620 struct hash_bucket *bp;
621 int i;
623 for (lp = collections; lp; lp = lp -> next) {
624 for (cp = lp -> classes; cp; cp = cp -> nic) {
625 if (cp -> spawning && cp -> hash) {
626 class_hash_foreach (cp -> hash, write_named_billing_class);
632 /* Write a spawned class to the database file. */
634 int write_billing_class (class)
635 struct class *class;
637 int errors = 0;
638 int i;
640 if (lease_file_is_corrupt)
641 if (!new_lease_file ())
642 return 0;
644 if (!class -> superclass) {
645 errno = 0;
646 fprintf (db_file, "\n billing class \"%s\";", class -> name);
647 return !errno;
650 errno = 0;
651 fprintf (db_file, "\n billing subclass \"%s\"",
652 class -> superclass -> name);
653 if (errno)
654 ++errors;
656 for (i = 0; i < class -> hash_string.len; i++)
657 if (!isascii (class -> hash_string.data [i]) ||
658 !isprint (class -> hash_string.data [i]))
659 break;
660 if (i == class -> hash_string.len) {
661 errno = 0;
662 fprintf (db_file, " \"%.*s\";",
663 (int)class -> hash_string.len,
664 class -> hash_string.data);
665 if (errno)
666 ++errors;
667 } else {
668 errno = 0;
669 fprintf (db_file, " %2.2x", class -> hash_string.data [0]);
670 if (errno)
671 ++errors;
672 for (i = 1; i < class -> hash_string.len; i++) {
673 errno = 0;
674 fprintf (db_file, ":%2.2x",
675 class -> hash_string.data [i]);
676 if (errno)
677 ++errors;
679 errno = 0;
680 fprintf (db_file, ";");
681 if (errno)
682 ++errors;
685 class -> dirty = !errors;
686 if (errors)
687 lease_file_is_corrupt = 1;
688 return !errors;
691 /* Commit leases after a timeout. */
692 void commit_leases_timeout (void *foo)
694 commit_leases ();
697 /* Commit any leases that have been written out... */
699 int commit_leases ()
701 /* Commit any outstanding writes to the lease database file.
702 We need to do this even if we're rewriting the file below,
703 just in case the rewrite fails. */
704 if (fflush (db_file) == EOF) {
705 log_info ("commit_leases: unable to commit: %m");
706 return 0;
708 if (fsync (fileno (db_file)) < 0) {
709 log_info ("commit_leases: unable to commit: %m");
710 return 0;
713 /* If we haven't rewritten the lease database in over an
714 hour, rewrite it now. (The length of time should probably
715 be configurable. */
716 if (count && cur_time - write_time > 3600) {
717 count = 0;
718 write_time = cur_time;
719 new_lease_file ();
721 return 1;
724 void db_startup (testp)
725 int testp;
727 isc_result_t status;
729 #if defined (TRACING)
730 if (!trace_playback ()) {
731 #endif
732 /* Read in the existing lease file... */
733 status = read_conf_file (path_dhcpd_db,
734 (struct group *)0, 0, 1);
735 /* XXX ignore status? */
736 #if defined (TRACING)
738 #endif
740 #if defined (TRACING)
741 /* If we're playing back, there is no lease file, so we can't
742 append it, so we create one immediately (maybe this isn't
743 the best solution... */
744 if (trace_playback ()) {
745 new_lease_file ();
747 #endif
748 if (!testp) {
749 db_file = fopen (path_dhcpd_db, "a");
750 if (!db_file)
751 log_fatal ("Can't open %s for append.", path_dhcpd_db);
752 expire_all_pools ();
753 #if defined (TRACING)
754 if (trace_playback ())
755 write_time = cur_time;
756 else
757 #endif
758 GET_TIME (&write_time);
759 new_lease_file ();
763 int new_lease_file ()
765 char newfname [512];
766 char backfname [512];
767 TIME t;
768 int db_fd;
770 /* If we already have an open database, close it. */
771 if (db_file) {
772 fclose (db_file);
773 db_file = (FILE *)0;
776 /* Make a temporary lease file... */
777 GET_TIME (&t);
779 /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
780 * This should never happen since the path is a configuration
781 * variable from build-time or command-line. But if it should,
782 * either by malice or ignorance, we panic, since the potential
783 * for havoc is high.
785 if (snprintf (newfname, sizeof newfname, "%s.%d",
786 path_dhcpd_db, (int)t) >= sizeof newfname)
787 log_fatal("new_lease_file: lease file path too long");
789 db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664);
790 if (db_fd < 0) {
791 log_error ("Can't create new lease file: %m");
792 return 0;
794 if ((db_file = fdopen (db_fd, "w")) == NULL) {
795 log_error ("Can't fdopen new lease file!");
796 goto fail;
799 /* Write an introduction so people don't complain about time
800 being off. */
801 errno = 0;
802 fprintf (db_file, "# All times in this file are in UTC (GMT), not %s",
803 "your local timezone. This is\n");
804 if (errno != 0)
805 goto fail;
806 fprintf (db_file, "# not a bug, so please don't ask about it. %s",
807 "There is no portable way to\n");
808 if (errno != 0)
809 goto fail;
810 fprintf (db_file, "# store leases in the local timezone, so please %s",
811 "don't request this as a\n");
812 if (errno != 0)
813 goto fail;
814 fprintf (db_file, "# feature. If this is inconvenient or %s",
815 "confusing to you, we sincerely\n");
816 if (errno != 0)
817 goto fail;
818 fprintf (db_file, "# apologize. Seriously, though - don't ask.\n");
819 if (errno != 0)
820 goto fail;
821 fprintf (db_file, "# The format of this file is documented in the %s",
822 "dhcpd.leases(5) manual page.\n");
823 if (errno != 0)
824 goto fail;
825 fprintf (db_file, "# This lease file was written by isc-dhcp-%s\n\n",
826 DHCP_VERSION);
827 if (errno != 0)
828 goto fail;
830 /* Write out all the leases that we know of... */
831 counting = 0;
832 if (!write_leases ())
833 goto fail;
835 #if defined (TRACING)
836 if (!trace_playback ()) {
837 #endif
838 /* %Audit% Truncated filename causes panic. %2004.06.17,Safe%
839 * This should never happen since the path is a configuration
840 * variable from build-time or command-line. But if it should,
841 * either by malice or ignorance, we panic, since the potential
842 * for havoc is too high.
844 if (snprintf (backfname, sizeof backfname, "%s~", path_dhcpd_db)
845 >= sizeof backfname)
846 log_fatal("new_lease_file: backup lease file path too long");
848 /* Get the old database out of the way... */
849 if (unlink (backfname) < 0 && errno != ENOENT) {
850 log_error ("Can't remove old lease database backup %s: %m",
851 backfname);
852 goto fail;
854 if (link (path_dhcpd_db, backfname) < 0) {
855 log_error ("Can't backup lease database %s to %s: %m",
856 path_dhcpd_db, backfname);
857 goto fail;
859 #if defined (TRACING)
861 #endif
863 /* Move in the new file... */
864 if (rename (newfname, path_dhcpd_db) < 0) {
865 log_error ("Can't install new lease database %s to %s: %m",
866 newfname, path_dhcpd_db);
867 goto fail;
870 counting = 1;
871 lease_file_is_corrupt = 0;
872 return 1;
874 fail:
875 unlink (newfname);
876 lease_file_is_corrupt = 1;
877 return 0;
880 int group_writer (struct group_object *group)
882 if (!write_group (group))
883 return 0;
884 if (!commit_leases ())
885 return 0;
886 return 1;