]>
Commit | Line | Data |
---|---|---|
1358b874 TL |
1 | /* db.c |
2 | ||
3 | Persistent database management routines for DHCPD... */ | |
4 | ||
5 | /* | |
f39b6e00 TL |
6 | * Copyright (c) 1996-1999 Internet Software Consortium. |
7 | * Use is subject to license terms which appear in the file named | |
8 | * ISC-LICENSE that should have accompanied this file when you | |
9 | * received it. If a file named ISC-LICENSE did not accompany this | |
10 | * file, or you are not sure the one you have is correct, you may | |
11 | * obtain an applicable copy of the license at: | |
1358b874 | 12 | * |
f39b6e00 | 13 | * http://www.isc.org/isc-license-1.0.html. |
1358b874 | 14 | * |
f39b6e00 TL |
15 | * This file is part of the ISC DHCP distribution. The documentation |
16 | * associated with this file is listed in the file DOCUMENTATION, | |
17 | * included in the top-level directory of this release. | |
1358b874 | 18 | * |
f39b6e00 TL |
19 | * Support and other services are available for ISC products - see |
20 | * http://www.isc.org for more information. | |
1358b874 TL |
21 | */ |
22 | ||
23 | #ifndef lint | |
24 | static char copyright[] = | |
4bd8800e | 25 | "$Id: db.c,v 1.42 2000/01/26 14:56:18 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; |
1358b874 TL |
26 | #endif /* not lint */ |
27 | ||
28 | #include "dhcpd.h" | |
0ebffe9c | 29 | #include <ctype.h> |
1358b874 TL |
30 | |
31 | FILE *db_file; | |
32 | ||
08804a9a TL |
33 | static int counting = 0; |
34 | static int count = 0; | |
35 | TIME write_time; | |
36 | ||
1358b874 TL |
37 | /* Write the specified lease to the current lease database file. */ |
38 | ||
39 | int write_lease (lease) | |
40 | struct lease *lease; | |
41 | { | |
42 | struct tm *t; | |
43 | char tbuf [64]; | |
a3115043 | 44 | int errors = 0; |
6fdff3b8 | 45 | int i; |
ea4eec7e | 46 | struct binding *b; |
1358b874 | 47 | |
08804a9a TL |
48 | if (counting) |
49 | ++count; | |
1358b874 | 50 | errno = 0; |
a3115043 TL |
51 | fprintf (db_file, "lease %s {\n", piaddr (lease -> ip_addr)); |
52 | if (errno) { | |
53 | ++errors; | |
54 | } | |
1358b874 | 55 | |
3f165a40 TL |
56 | /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until |
57 | somebody invents a time machine, I think we can safely disregard | |
58 | it. */ | |
612fded7 TL |
59 | if (lease -> starts != MAX_TIME) { |
60 | t = gmtime (&lease -> starts); | |
61 | sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;", | |
62 | t -> tm_wday, t -> tm_year + 1900, | |
63 | t -> tm_mon + 1, t -> tm_mday, | |
64 | t -> tm_hour, t -> tm_min, t -> tm_sec); | |
65 | } else | |
b5fa877f | 66 | strcpy (tbuf, "never;"); |
a3115043 | 67 | errno = 0; |
d00855e0 | 68 | fprintf (db_file, " starts %s\n", tbuf); |
a3115043 TL |
69 | if (errno) { |
70 | ++errors; | |
71 | } | |
1358b874 | 72 | |
612fded7 TL |
73 | if (lease -> ends != MAX_TIME) { |
74 | t = gmtime (&lease -> ends); | |
75 | sprintf (tbuf, "%d %d/%02d/%02d %02d:%02d:%02d;", | |
76 | t -> tm_wday, t -> tm_year + 1900, | |
77 | t -> tm_mon + 1, t -> tm_mday, | |
78 | t -> tm_hour, t -> tm_min, t -> tm_sec); | |
79 | } else | |
b5fa877f | 80 | strcpy (tbuf, "never;"); |
a3115043 | 81 | errno = 0; |
d00855e0 | 82 | fprintf (db_file, " ends %s", tbuf); |
a3115043 TL |
83 | if (errno) { |
84 | ++errors; | |
85 | } | |
1358b874 | 86 | |
ea4eec7e TL |
87 | if (lease -> tstp) { |
88 | t = gmtime (&lease -> tstp); | |
89 | errno = 0; | |
d00855e0 | 90 | fprintf (db_file, "\n tstp %d %d/%02d/%02d %02d:%02d:%02d;", |
ea4eec7e TL |
91 | t -> tm_wday, t -> tm_year + 1900, |
92 | t -> tm_mon + 1, t -> tm_mday, | |
93 | t -> tm_hour, t -> tm_min, t -> tm_sec); | |
94 | if (errno) { | |
95 | ++errors; | |
96 | } | |
fa674baf | 97 | } |
ea4eec7e TL |
98 | if (lease -> tsfp) { |
99 | t = gmtime (&lease -> tsfp); | |
100 | errno = 0; | |
d00855e0 | 101 | fprintf (db_file, "\n tsfp %d %d/%02d/%02d %02d:%02d:%02d;", |
ea4eec7e TL |
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 | if (errno) { | |
106 | ++errors; | |
107 | } | |
fa674baf TL |
108 | } |
109 | ||
110 | if (lease -> flags & PEER_IS_OWNER) { | |
111 | errno = 0; | |
d00855e0 | 112 | fprintf (db_file, "\n peer is owner;"); |
fa674baf TL |
113 | if (errno) { |
114 | ++errors; | |
115 | } | |
116 | } | |
fa674baf | 117 | |
e2bfe7b3 TL |
118 | /* If this lease is billed to a class and is still valid, |
119 | write it out. */ | |
120 | if (lease -> billing_class && lease -> ends > cur_time) | |
121 | if (!write_billing_class (lease -> billing_class)) | |
122 | ++errors; | |
123 | ||
1358b874 | 124 | if (lease -> hardware_addr.hlen) { |
a3115043 | 125 | errno = 0; |
d00855e0 | 126 | fprintf (db_file, "\n hardware %s %s;", |
fa674baf TL |
127 | hardware_types [lease -> hardware_addr.hbuf [0]], |
128 | print_hw_addr (lease -> hardware_addr.hbuf [0], | |
129 | lease -> hardware_addr.hlen - 1, | |
130 | &lease -> hardware_addr.hbuf [1])); | |
a3115043 TL |
131 | if (errno) { |
132 | ++errors; | |
133 | } | |
1358b874 TL |
134 | } |
135 | if (lease -> uid_len) { | |
136 | int i; | |
b1b7b521 | 137 | if (db_printable_len ((const char *)lease -> uid, |
77a5f871 | 138 | lease -> uid_len)) { |
d00855e0 | 139 | fprintf (db_file, "\n uid \"%*s\";", |
b1b7b521 | 140 | lease -> uid_len, lease -> uid); |
daaeeac1 | 141 | } else { |
a3115043 | 142 | errno = 0; |
d00855e0 | 143 | fprintf (db_file, "\n uid %2.2x", lease -> uid [0]); |
a3115043 TL |
144 | if (errno) { |
145 | ++errors; | |
146 | } | |
daaeeac1 TL |
147 | for (i = 1; i < lease -> uid_len; i++) { |
148 | errno = 0; | |
149 | fprintf (db_file, ":%2.2x", lease -> uid [i]); | |
150 | if (errno) { | |
151 | ++errors; | |
152 | } | |
153 | } | |
154 | putc (';', db_file); | |
a3115043 | 155 | } |
a3115043 TL |
156 | } |
157 | if (lease -> flags & BOOTP_LEASE) { | |
158 | errno = 0; | |
d00855e0 | 159 | fprintf (db_file, "\n dynamic-bootp;"); |
a3115043 | 160 | if (errno) { |
4006d804 TL |
161 | ++errors; |
162 | } | |
163 | } | |
164 | if (lease -> flags & ABANDONED_LEASE) { | |
165 | errno = 0; | |
d00855e0 | 166 | fprintf (db_file, "\n abandoned;"); |
4006d804 | 167 | if (errno) { |
a3115043 | 168 | ++errors; |
00d6d87c TL |
169 | } |
170 | } | |
d00855e0 TL |
171 | for (b = lease -> scope.bindings; b; b = b -> next) { |
172 | if (b -> value.data) { | |
173 | if (db_printable_len (b -> value.data, | |
174 | b -> value.len)) { | |
ea4eec7e | 175 | errno = 0; |
d00855e0 TL |
176 | fprintf (db_file, "\n set %s = \"%.*s\";", |
177 | b -> name, | |
178 | (int)b -> value.len, b -> value.data); | |
ea4eec7e TL |
179 | } else { |
180 | errno = 0; | |
d00855e0 | 181 | fprintf (db_file, "\n set %s = ", b -> name); |
ea4eec7e TL |
182 | if (errno) { |
183 | ++errors; | |
184 | } | |
185 | for (i = 0; i < b -> value.len; i++) { | |
186 | errno = 0; | |
187 | fprintf (db_file, "%2.2x%s", | |
188 | b -> value.data [i], | |
189 | i + 1 == b -> value.len | |
d00855e0 | 190 | ? "" : ":"); |
ea4eec7e TL |
191 | if (errno) { |
192 | ++errors; | |
193 | } | |
194 | } | |
195 | putc (';', db_file); | |
196 | } | |
d00855e0 | 197 | } |
0ebffe9c TL |
198 | } |
199 | if (lease -> client_hostname && | |
200 | db_printable (lease -> client_hostname)) { | |
00d6d87c | 201 | errno = 0; |
d00855e0 | 202 | fprintf (db_file, "\n client-hostname \"%s\";", |
00d6d87c TL |
203 | lease -> client_hostname); |
204 | if (errno) { | |
205 | ++errors; | |
206 | } | |
207 | } | |
0ebffe9c | 208 | if (lease -> hostname && db_printable (lease -> hostname)) { |
00d6d87c | 209 | errno = 0; |
d00855e0 | 210 | fprintf (db_file, "\n hostname \"%s\";", |
36b65b9c | 211 | lease -> hostname); |
00d6d87c TL |
212 | if (errno) { |
213 | ++errors; | |
a3115043 TL |
214 | } |
215 | } | |
fa098be8 TL |
216 | if (lease -> on_expiry) { |
217 | errno = 0; | |
d00855e0 | 218 | fprintf (db_file, "\n on expiry%s {", |
ea4eec7e | 219 | lease -> on_expiry == lease -> on_release |
d00855e0 | 220 | ? " or release" : ""); |
fa098be8 TL |
221 | if (errno) |
222 | ++errors; | |
d00855e0 | 223 | write_statements (db_file, lease -> on_expiry, 4); |
fa098be8 | 224 | /* XXX */ |
d00855e0 | 225 | fprintf (db_file, "\n }"); |
fa098be8 | 226 | } |
ea4eec7e | 227 | if (lease -> on_release && lease -> on_release != lease -> on_expiry) { |
fa098be8 | 228 | errno = 0; |
d00855e0 | 229 | fprintf (db_file, "\n on release {"); |
fa098be8 TL |
230 | if (errno) |
231 | ++errors; | |
d00855e0 | 232 | write_statements (db_file, lease -> on_release, 4); |
fa098be8 | 233 | /* XXX */ |
d00855e0 | 234 | fprintf (db_file, "\n }"); |
fa098be8 | 235 | } |
a3115043 TL |
236 | errno = 0; |
237 | fputs ("\n}\n", db_file); | |
238 | if (errno) { | |
239 | ++errors; | |
1358b874 | 240 | } |
a3115043 | 241 | if (errors) |
8ae2d595 | 242 | log_info ("write_lease: unable to write lease %s", |
a3115043 TL |
243 | piaddr (lease -> ip_addr)); |
244 | return !errors; | |
1358b874 TL |
245 | } |
246 | ||
612fded7 TL |
247 | int write_host (host) |
248 | struct host_decl *host; | |
249 | { | |
250 | int errors = 0; | |
251 | int i; | |
252 | struct data_string ip_addrs; | |
253 | ||
254 | if (!db_printable (host -> name)) | |
255 | return 0; | |
256 | ||
257 | if (counting) | |
258 | ++count; | |
259 | errno = 0; | |
260 | ||
261 | fprintf (db_file, "host %s {", host -> name); | |
262 | if (errno) { | |
263 | ++errors; | |
264 | } | |
265 | ||
fafd89d2 | 266 | if (host -> flags & HOST_DECL_DYNAMIC) { |
612fded7 | 267 | errno = 0; |
d00855e0 | 268 | fprintf (db_file, "\n dynamic;"); |
fafd89d2 | 269 | if (errno) |
612fded7 | 270 | ++errors; |
612fded7 | 271 | } |
fafd89d2 TL |
272 | |
273 | if (host -> flags & HOST_DECL_DELETED) { | |
612fded7 | 274 | errno = 0; |
d00855e0 | 275 | fprintf (db_file, "\n deleted;"); |
fafd89d2 | 276 | if (errno) |
612fded7 | 277 | ++errors; |
fafd89d2 TL |
278 | } else { |
279 | if (host -> interface.hlen) { | |
280 | errno = 0; | |
d00855e0 | 281 | fprintf (db_file, "\n hardware %s %s;", |
fa674baf TL |
282 | hardware_types [host -> interface.hbuf [0]], |
283 | print_hw_addr (host -> interface.hbuf [0], | |
284 | host -> interface.hlen - 1, | |
285 | &host -> interface.hbuf [1])); | |
fafd89d2 TL |
286 | if (errno) { |
287 | ++errors; | |
288 | } | |
612fded7 | 289 | } |
fafd89d2 TL |
290 | if (host -> client_identifier.len) { |
291 | int i; | |
612fded7 | 292 | errno = 0; |
b1b7b521 | 293 | if (db_printable_len ((const char *) |
77a5f871 | 294 | host -> client_identifier.data, |
daaeeac1 | 295 | host -> client_identifier.len)) { |
d00855e0 | 296 | fprintf (db_file, "\n uid \"%*s\";", |
daaeeac1 TL |
297 | host -> client_identifier.len, |
298 | host -> client_identifier.data); | |
299 | } else { | |
300 | fprintf (db_file, | |
d00855e0 | 301 | "\n uid %2.2x", |
daaeeac1 | 302 | host -> client_identifier.data [0]); |
fafd89d2 TL |
303 | if (errno) { |
304 | ++errors; | |
305 | } | |
daaeeac1 TL |
306 | for (i = 1; |
307 | i < host -> client_identifier.len; i++) { | |
308 | errno = 0; | |
309 | fprintf (db_file, ":%2.2x", | |
310 | host -> | |
311 | client_identifier.data [i]); | |
312 | if (errno) { | |
313 | ++errors; | |
314 | } | |
315 | } | |
316 | putc (';', db_file); | |
fafd89d2 | 317 | } |
612fded7 | 318 | } |
612fded7 | 319 | |
daaeeac1 | 320 | memset (&ip_addrs, 0, sizeof ip_addrs); |
fafd89d2 TL |
321 | if (host -> fixed_addr && |
322 | evaluate_option_cache (&ip_addrs, (struct packet *)0, | |
323 | (struct lease *)0, | |
324 | (struct option_state *)0, | |
325 | (struct option_state *)0, | |
d00855e0 | 326 | &global_scope, |
4bd8800e | 327 | host -> fixed_addr, MDL)) { |
fafd89d2 | 328 | |
daaeeac1 | 329 | errno = 0; |
d00855e0 | 330 | fprintf (db_file, "\n fixed-address "); |
612fded7 TL |
331 | if (errno) { |
332 | ++errors; | |
333 | } | |
fafd89d2 | 334 | for (i = 0; i < ip_addrs.len - 3; i += 4) { |
daaeeac1 TL |
335 | errno = 0; |
336 | fprintf (db_file, "%d.%d.%d.%d%s", | |
fafd89d2 TL |
337 | ip_addrs.data [i], |
338 | ip_addrs.data [i + 1], | |
339 | ip_addrs.data [i + 2], | |
340 | ip_addrs.data [i + 3], | |
341 | i + 7 < ip_addrs.len ? "," : ""); | |
342 | if (errno) { | |
343 | ++errors; | |
344 | } | |
345 | } | |
daaeeac1 TL |
346 | errno = 0; |
347 | fputc (';', db_file); | |
348 | if (errno) { | |
349 | ++errors; | |
350 | } | |
351 | } | |
352 | ||
353 | if (host -> named_group) { | |
354 | errno = 0; | |
d00855e0 | 355 | fprintf (db_file, "\n group \"%s\";", |
daaeeac1 TL |
356 | host -> named_group -> name); |
357 | if (errno) { | |
358 | ++errors; | |
359 | } | |
360 | } | |
361 | ||
d70e89d4 TL |
362 | if (host -> group && |
363 | (!host -> named_group || | |
dff4af5c TL |
364 | host -> group != host -> named_group -> group) && |
365 | host -> group != &root_group) { | |
daaeeac1 TL |
366 | errno = 0; |
367 | write_statements (db_file, | |
368 | host -> group -> statements, 8); | |
369 | if (errno) { | |
370 | ++errors; | |
371 | } | |
612fded7 TL |
372 | } |
373 | } | |
374 | ||
375 | errno = 0; | |
376 | fputs ("\n}\n", db_file); | |
377 | if (errno) { | |
378 | ++errors; | |
379 | } | |
380 | if (errors) | |
381 | log_info ("write_host: unable to write host %s", | |
382 | host -> name); | |
383 | return !errors; | |
384 | } | |
385 | ||
daaeeac1 TL |
386 | int write_group (group) |
387 | struct group_object *group; | |
388 | { | |
3b7c3de9 TL |
389 | int errors = 0; |
390 | int i; | |
391 | ||
392 | if (!db_printable (group -> name)) | |
393 | return 0; | |
394 | ||
395 | if (counting) | |
396 | ++count; | |
397 | errno = 0; | |
398 | ||
399 | fprintf (db_file, "group %s {", group -> name); | |
400 | if (errno) { | |
401 | ++errors; | |
402 | } | |
403 | ||
404 | if (group -> flags & GROUP_OBJECT_DYNAMIC) { | |
405 | errno = 0; | |
d00855e0 | 406 | fprintf (db_file, "\n dynamic;"); |
3b7c3de9 TL |
407 | if (errno) |
408 | ++errors; | |
409 | } | |
410 | ||
411 | if (group -> flags & GROUP_OBJECT_STATIC) { | |
412 | errno = 0; | |
d00855e0 | 413 | fprintf (db_file, "\n static;"); |
3b7c3de9 TL |
414 | if (errno) |
415 | ++errors; | |
416 | } | |
417 | ||
418 | if (group -> flags & GROUP_OBJECT_DELETED) { | |
419 | errno = 0; | |
d00855e0 | 420 | fprintf (db_file, "\n deleted;"); |
3b7c3de9 TL |
421 | if (errno) |
422 | ++errors; | |
423 | } else { | |
424 | if (group -> group) { | |
425 | errno = 0; | |
426 | write_statements (db_file, | |
427 | group -> group -> statements, 8); | |
428 | if (errno) { | |
429 | ++errors; | |
430 | } | |
431 | } | |
432 | } | |
433 | ||
434 | errno = 0; | |
435 | fputs ("\n}\n", db_file); | |
436 | if (errno) { | |
437 | ++errors; | |
438 | } | |
439 | if (errors) | |
440 | log_info ("write_group: unable to write group %s", | |
441 | group -> name); | |
442 | return !errors; | |
daaeeac1 TL |
443 | } |
444 | ||
0ebffe9c | 445 | int db_printable (s) |
b1b7b521 | 446 | const char *s; |
0ebffe9c TL |
447 | { |
448 | int i; | |
449 | for (i = 0; s [i]; i++) | |
450 | if (!isascii (s [i]) || !isprint (s [i])) | |
451 | return 0; | |
452 | return 1; | |
453 | } | |
454 | ||
daaeeac1 | 455 | int db_printable_len (s, len) |
b1b7b521 TL |
456 | const char *s; |
457 | unsigned len; | |
daaeeac1 TL |
458 | { |
459 | int i; | |
460 | for (i = 0; i < len; i++) | |
461 | if (!isascii (s [i]) || !isprint (s [i])) | |
462 | return 0; | |
463 | return 1; | |
464 | } | |
465 | ||
e2bfe7b3 TL |
466 | /* Write a spawned class to the database file. */ |
467 | ||
468 | int write_billing_class (class) | |
469 | struct class *class; | |
470 | { | |
471 | int errors = 0; | |
472 | int i; | |
473 | ||
474 | if (!class -> superclass) { | |
475 | errno = 0; | |
d00855e0 | 476 | fprintf (db_file, "\n billing class \"%s\";", class -> name); |
e2bfe7b3 TL |
477 | return !errno; |
478 | } | |
479 | ||
480 | errno = 0; | |
d00855e0 | 481 | fprintf (db_file, "\n billing subclass \"%s\"", |
e2bfe7b3 TL |
482 | class -> superclass -> name); |
483 | if (errno) | |
484 | ++errors; | |
485 | ||
486 | for (i = 0; i < class -> hash_string.len; i++) | |
487 | if (!isascii (class -> hash_string.data [i]) || | |
488 | !isprint (class -> hash_string.data [i])) | |
489 | break; | |
490 | if (i == class -> hash_string.len) { | |
491 | errno = 0; | |
b1b7b521 | 492 | fprintf (db_file, " \"%*s\";", |
e2bfe7b3 TL |
493 | class -> hash_string.len, |
494 | class -> hash_string.data); | |
495 | if (errno) | |
496 | ++errors; | |
497 | } else { | |
498 | errno = 0; | |
499 | fprintf (db_file, " %2.2x", class -> hash_string.data [0]); | |
500 | if (errno) | |
501 | ++errors; | |
502 | for (i = 1; i < class -> hash_string.len; i++) { | |
503 | errno = 0; | |
504 | fprintf (db_file, ":%2.2x", | |
505 | class -> hash_string.data [i]); | |
506 | if (errno) | |
507 | ++errors; | |
508 | } | |
509 | errno = 0; | |
510 | fprintf (db_file, ";"); | |
511 | if (errno) | |
512 | ++errors; | |
513 | } | |
514 | ||
515 | class -> dirty = 0; | |
516 | return !errors; | |
517 | } | |
518 | ||
1358b874 TL |
519 | /* Commit any leases that have been written out... */ |
520 | ||
521 | int commit_leases () | |
522 | { | |
a3115043 TL |
523 | /* Commit any outstanding writes to the lease database file. |
524 | We need to do this even if we're rewriting the file below, | |
525 | just in case the rewrite fails. */ | |
526 | if (fflush (db_file) == EOF) { | |
8ae2d595 | 527 | log_info ("commit_leases: unable to commit: %m"); |
a3115043 TL |
528 | return 0; |
529 | } | |
530 | if (fsync (fileno (db_file)) < 0) { | |
8ae2d595 | 531 | log_info ("commit_leases: unable to commit: %m"); |
a3115043 TL |
532 | return 0; |
533 | } | |
534 | ||
08804a9a TL |
535 | /* If we've written more than a thousand leases or if |
536 | we haven't rewritten the lease database in over an | |
537 | hour, rewrite it now. */ | |
538 | if (count > 1000 || (count && cur_time - write_time > 3600)) { | |
539 | count = 0; | |
540 | write_time = cur_time; | |
541 | new_lease_file (); | |
08804a9a | 542 | } |
1358b874 TL |
543 | return 1; |
544 | } | |
545 | ||
3b7c3de9 TL |
546 | void db_startup (testp) |
547 | int testp; | |
1358b874 TL |
548 | { |
549 | /* Read in the existing lease file... */ | |
550 | read_leases (); | |
551 | ||
3b7c3de9 | 552 | if (!testp) { |
96359f83 | 553 | db_file = fopen (path_dhcpd_db, "a"); |
05743349 | 554 | expire_all_pools (); |
3b7c3de9 TL |
555 | GET_TIME (&write_time); |
556 | new_lease_file (); | |
557 | } | |
1358b874 TL |
558 | } |
559 | ||
560 | void new_lease_file () | |
561 | { | |
562 | char newfname [512]; | |
563 | char backfname [512]; | |
564 | TIME t; | |
30856538 | 565 | int db_fd; |
1358b874 TL |
566 | |
567 | /* If we already have an open database, close it. */ | |
568 | if (db_file) { | |
569 | fclose (db_file); | |
570 | } | |
571 | ||
572 | /* Make a temporary lease file... */ | |
b16b7f33 TL |
573 | GET_TIME (&t); |
574 | sprintf (newfname, "%s.%d", path_dhcpd_db, (int)t); | |
30856538 TL |
575 | db_fd = open (newfname, O_WRONLY | O_TRUNC | O_CREAT, 0664); |
576 | if (db_fd < 0) { | |
8ae2d595 | 577 | log_fatal ("Can't create new lease file: %m"); |
30856538 TL |
578 | } |
579 | if ((db_file = fdopen (db_fd, "w")) == NULL) { | |
8ae2d595 | 580 | log_fatal ("Can't fdopen new lease file!"); |
1358b874 TL |
581 | } |
582 | ||
8f65e88d TL |
583 | /* Write an introduction so people don't complain about time |
584 | being off. */ | |
585 | fprintf (db_file, "# All times in this file are in UTC (GMT), not %s", | |
586 | "your local timezone. This is\n"); | |
587 | fprintf (db_file, "# not a bug, so please don't ask about it. %s", | |
468746fe TL |
588 | "There is no portable way to\n"); |
589 | fprintf (db_file, "# store leases in the local timezone, so please %s", | |
590 | "don't request this as a\n"); | |
591 | fprintf (db_file, "# feature. If this is inconvenient or %s", | |
592 | "confusing to you, we sincerely\n"); | |
593 | fprintf (db_file, "# apologize. Seriously, though - don't ask.\n"); | |
594 | fprintf (db_file, "# The format of this file is documented in the %s", | |
595 | "dhcpd.leases(5) manual page.\n\n"); | |
8f65e88d | 596 | |
1358b874 | 597 | /* Write out all the leases that we know of... */ |
08804a9a | 598 | counting = 0; |
1358b874 TL |
599 | write_leases (); |
600 | ||
601 | /* Get the old database out of the way... */ | |
e2ac5814 | 602 | sprintf (backfname, "%s~", path_dhcpd_db); |
a3115043 | 603 | if (unlink (backfname) < 0 && errno != ENOENT) |
8ae2d595 | 604 | log_fatal ("Can't remove old lease database backup %s: %m", |
a3115043 | 605 | backfname); |
e2ac5814 | 606 | if (link (path_dhcpd_db, backfname) < 0) |
8ae2d595 | 607 | log_fatal ("Can't backup lease database %s to %s: %m", |
e2ac5814 | 608 | path_dhcpd_db, backfname); |
1358b874 TL |
609 | |
610 | /* Move in the new file... */ | |
e2ac5814 | 611 | if (rename (newfname, path_dhcpd_db) < 0) |
8ae2d595 | 612 | log_fatal ("Can't install new lease database %s to %s: %m", |
e2ac5814 | 613 | newfname, path_dhcpd_db); |
08804a9a TL |
614 | |
615 | counting = 1; | |
1358b874 | 616 | } |