Commit | Line | Data |
---|---|---|
805e021f CE |
1 | /* |
2 | * Copyright 2000, International Business Machines Corporation and others. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * This software has been released under the terms of the IBM Public | |
6 | * License. For details, see the LICENSE file in the top-level source | |
7 | * directory or online at http://www.openafs.org/dl/license10.html | |
8 | */ | |
9 | ||
10 | #include <afsconfig.h> | |
11 | #include <afs/param.h> | |
12 | #include <afs/stds.h> | |
13 | ||
14 | #include <roken.h> | |
15 | ||
16 | #ifdef AFS_NT40_ENV | |
17 | #include <WINNT/afsevent.h> | |
18 | #endif | |
19 | #include <afs/cmd.h> | |
20 | #include <lwp.h> | |
21 | #include <ubik.h> | |
22 | #include <rx/xdr.h> | |
23 | #include <rx/rx.h> | |
24 | #include <rx/rxkad.h> | |
25 | #include <rx/rx_globals.h> | |
26 | #include <afs/cellconfig.h> | |
27 | #include <afs/bubasics.h> | |
28 | #include <afs/afsutil.h> | |
29 | #include <afs/com_err.h> | |
30 | #include <afs/audit.h> | |
31 | ||
32 | #include "budb_errs.h" | |
33 | #include "database.h" | |
34 | #include "error_macros.h" | |
35 | #include "budb_internal.h" | |
36 | #include "globals.h" | |
37 | ||
38 | struct ubik_dbase *BU_dbase; | |
39 | struct afsconf_dir *BU_conf; /* for getting cell info */ | |
40 | ||
41 | int argHandler(struct cmd_syndesc *, void *); | |
42 | int truncateDatabase(void); | |
43 | int parseServerList(struct cmd_item *); | |
44 | ||
45 | char lcell[MAXKTCREALMLEN]; | |
46 | afs_uint32 myHost = 0; | |
47 | int helpOption; | |
48 | static struct logOptions logopts; | |
49 | ||
50 | /* server's global configuration information. This is exported to other | |
51 | * files/routines | |
52 | */ | |
53 | ||
54 | buServerConfT globalConf; | |
55 | buServerConfP globalConfPtr = &globalConf; | |
56 | char dbDir[AFSDIR_PATH_MAX], cellConfDir[AFSDIR_PATH_MAX]; | |
57 | /* debugging control */ | |
58 | int debugging = 0; | |
59 | ||
60 | int rxBind = 0; | |
61 | int lwps = 3; | |
62 | ||
63 | #define MINLWP 3 | |
64 | #define MAXLWP 16 | |
65 | ||
66 | #define ADDRSPERSITE 16 /* Same global is in rx/rx_user.c */ | |
67 | afs_uint32 SHostAddrs[ADDRSPERSITE]; | |
68 | ||
69 | /* check whether caller is authorized to manage RX statistics */ | |
70 | int | |
71 | BU_rxstat_userok(struct rx_call *call) | |
72 | { | |
73 | return afsconf_SuperUser(BU_conf, call, NULL); | |
74 | } | |
75 | ||
76 | /** | |
77 | * Return true if this name is a member of the local realm. | |
78 | */ | |
79 | int | |
80 | BU_IsLocalRealmMatch(void *rock, char *name, char *inst, char *cell) | |
81 | { | |
82 | struct afsconf_dir *dir = (struct afsconf_dir *)rock; | |
83 | afs_int32 islocal = 0; /* default to no */ | |
84 | int code; | |
85 | ||
86 | code = afsconf_IsLocalRealmMatch(dir, &islocal, name, inst, cell); | |
87 | if (code) { | |
88 | LogError(code, "Failed local realm check; name=%s, inst=%s, cell=%s\n", | |
89 | name, inst, cell); | |
90 | } | |
91 | return islocal; | |
92 | } | |
93 | ||
94 | int | |
95 | convert_cell_to_ubik(struct afsconf_cell *cellinfo, afs_uint32 *myHost, | |
96 | afs_uint32 *serverList) | |
97 | { | |
98 | int i; | |
99 | char hostname[64]; | |
100 | struct hostent *th; | |
101 | ||
102 | /* get this host */ | |
103 | gethostname(hostname, sizeof(hostname)); | |
104 | th = gethostbyname(hostname); | |
105 | if (!th) { | |
106 | printf("prserver: couldn't get address of this host.\n"); | |
107 | BUDB_EXIT(1); | |
108 | } | |
109 | memcpy(myHost, th->h_addr, sizeof(afs_uint32)); | |
110 | ||
111 | for (i = 0; i < cellinfo->numServers; i++) | |
112 | /* omit my host from serverList */ | |
113 | if (cellinfo->hostAddr[i].sin_addr.s_addr != *myHost) | |
114 | *serverList++ = cellinfo->hostAddr[i].sin_addr.s_addr; | |
115 | ||
116 | *serverList = 0; /* terminate list */ | |
117 | return 0; | |
118 | } | |
119 | ||
120 | /* MyBeforeProc | |
121 | * The whole purpose of MyBeforeProc is to detect | |
122 | * if the -help option was not within the command line. | |
123 | * If it were, this routine would never have been called. | |
124 | */ | |
125 | static int | |
126 | MyBeforeProc(struct cmd_syndesc *as, void *arock) | |
127 | { | |
128 | helpOption = 0; | |
129 | return 0; | |
130 | } | |
131 | ||
132 | /* initializeCommands | |
133 | * initialize all the supported commands and their arguments | |
134 | */ | |
135 | ||
136 | void | |
137 | initializeArgHandler(void) | |
138 | { | |
139 | struct cmd_syndesc *cptr; | |
140 | ||
141 | cmd_SetBeforeProc(MyBeforeProc, NULL); | |
142 | ||
143 | cptr = cmd_CreateSyntax(NULL, argHandler, NULL, 0, "Backup database server"); | |
144 | ||
145 | cmd_AddParm(cptr, "-database", CMD_SINGLE, CMD_OPTIONAL, | |
146 | "database directory"); | |
147 | ||
148 | cmd_AddParm(cptr, "-cellservdb", CMD_SINGLE, CMD_OPTIONAL, | |
149 | "cell configuration directory"); | |
150 | ||
151 | cmd_AddParm(cptr, "-resetdb", CMD_FLAG, CMD_OPTIONAL, | |
152 | "truncate the database"); | |
153 | ||
154 | cmd_AddParm(cptr, "-noauth", CMD_FLAG, CMD_OPTIONAL, | |
155 | "run without authentication"); | |
156 | ||
157 | cmd_AddParm(cptr, "-smallht", CMD_FLAG, CMD_OPTIONAL, | |
158 | "use small hash tables"); | |
159 | ||
160 | cmd_AddParm(cptr, "-servers", CMD_LIST, CMD_OPTIONAL, | |
161 | "list of ubik database servers"); | |
162 | ||
163 | cmd_AddParm(cptr, "-ubikbuffers", CMD_SINGLE, CMD_OPTIONAL, | |
164 | "the number of ubik buffers"); | |
165 | ||
166 | cmd_AddParm(cptr, "-auditlog", CMD_SINGLE, CMD_OPTIONAL, | |
167 | "audit log path"); | |
168 | ||
169 | cmd_AddParm(cptr, "-p", CMD_SINGLE, CMD_OPTIONAL, | |
170 | "number of processes"); | |
171 | ||
172 | cmd_AddParm(cptr, "-rxbind", CMD_FLAG, CMD_OPTIONAL, | |
173 | "bind the Rx socket (primary interface only)"); | |
174 | ||
175 | cmd_AddParm(cptr, "-audit-interface", CMD_SINGLE, CMD_OPTIONAL, | |
176 | "audit interface (file or sysvmq)"); | |
177 | ||
178 | cmd_AddParm(cptr, "-transarc-logs", CMD_FLAG, CMD_OPTIONAL, | |
179 | "enable Transarc style logging"); | |
180 | } | |
181 | ||
182 | int | |
183 | argHandler(struct cmd_syndesc *as, void *arock) | |
184 | { | |
185 | ||
186 | /* globalConfPtr provides the handle for the configuration information */ | |
187 | ||
188 | /* database directory */ | |
189 | if (as->parms[0].items != 0) { | |
190 | globalConfPtr->databaseDirectory = strdup(as->parms[0].items->data); | |
191 | if (globalConfPtr->databaseDirectory == 0) | |
192 | BUDB_EXIT(-1); | |
193 | } | |
194 | ||
195 | /* -cellservdb, cell configuration directory */ | |
196 | if (as->parms[1].items != 0) { | |
197 | globalConfPtr->cellConfigdir = strdup(as->parms[1].items->data); | |
198 | if (globalConfPtr->cellConfigdir == 0) | |
199 | BUDB_EXIT(-1); | |
200 | ||
201 | globalConfPtr->debugFlags |= DF_RECHECKNOAUTH; | |
202 | } | |
203 | ||
204 | /* truncate the database */ | |
205 | if (as->parms[2].items != 0) | |
206 | truncateDatabase(); | |
207 | ||
208 | /* run without authentication */ | |
209 | if (as->parms[3].items != 0) | |
210 | globalConfPtr->debugFlags |= DF_NOAUTH; | |
211 | ||
212 | /* use small hash tables */ | |
213 | if (as->parms[4].items != 0) | |
214 | globalConfPtr->debugFlags |= DF_SMALLHT; | |
215 | ||
216 | /* user provided list of ubik database servers */ | |
217 | if (as->parms[5].items != 0) | |
218 | parseServerList(as->parms[5].items); | |
219 | ||
220 | /* user provided the number of ubik buffers */ | |
221 | if (as->parms[6].items != 0) | |
222 | ubik_nBuffers = atoi(as->parms[6].items->data); | |
223 | else | |
224 | ubik_nBuffers = 0; | |
225 | ||
226 | /* param 7 (-auditlog) handled below */ | |
227 | ||
228 | /* user provided the number of threads */ | |
229 | if (as->parms[8].items != 0) { | |
230 | lwps = atoi(as->parms[8].items->data); | |
231 | if (lwps > MAXLWP) { | |
232 | printf ("Warning: '-p %d' is too big; using %d instead\n", | |
233 | lwps, MAXLWP); | |
234 | lwps = MAXLWP; | |
235 | } | |
236 | if (lwps < MINLWP) { | |
237 | printf ("Warning: '-p %d' is too small; using %d instead\n", | |
238 | lwps, MINLWP); | |
239 | lwps = MINLWP; | |
240 | } | |
241 | } | |
242 | ||
243 | /* user provided rxbind option */ | |
244 | if (as->parms[9].items != 0) { | |
245 | rxBind = 1; | |
246 | } | |
247 | ||
248 | /* -audit-interface */ | |
249 | if (as->parms[10].items != 0) { | |
250 | char *interface = as->parms[10].items->data; | |
251 | ||
252 | if (osi_audit_interface(interface)) { | |
253 | printf("Invalid audit interface '%s'\n", interface); | |
254 | BUDB_EXIT(-1); | |
255 | } | |
256 | } | |
257 | /* -transarc-logs */ | |
258 | if (as->parms[11].items != 0) { | |
259 | logopts.lopt_rotateOnOpen = 1; | |
260 | logopts.lopt_rotateStyle = logRotate_old; | |
261 | } | |
262 | ||
263 | /* -auditlog */ | |
264 | /* needs to be after -audit-interface, so we osi_audit_interface | |
265 | * before we osi_audit_file */ | |
266 | if (as->parms[7].items != 0) { | |
267 | char *fileName = as->parms[7].items->data; | |
268 | ||
269 | osi_audit_file(fileName); | |
270 | } | |
271 | ||
272 | return 0; | |
273 | } | |
274 | ||
275 | /* --- */ | |
276 | ||
277 | int | |
278 | parseServerList(struct cmd_item *itemPtr) | |
279 | { | |
280 | struct cmd_item *save; | |
281 | char **serverArgs; | |
282 | char **ptr; | |
283 | afs_int32 nservers = 0; | |
284 | afs_int32 code = 0; | |
285 | ||
286 | save = itemPtr; | |
287 | ||
288 | /* compute number of servers in the list */ | |
289 | while (itemPtr) { | |
290 | nservers++; | |
291 | itemPtr = itemPtr->next; | |
292 | } | |
293 | ||
294 | LogDebug(3, "%d servers\n", nservers); | |
295 | ||
296 | /* now can allocate the space for the server arguments */ | |
297 | serverArgs = malloc((nservers + 2) * sizeof(char *)); | |
298 | if (serverArgs == 0) | |
299 | ERROR(-1); | |
300 | ||
301 | ptr = serverArgs; | |
302 | *ptr++ = ""; | |
303 | *ptr++ = "-servers"; | |
304 | ||
305 | /* now go through and construct the list of servers */ | |
306 | itemPtr = save; | |
307 | while (itemPtr) { | |
308 | *ptr++ = itemPtr->data; | |
309 | itemPtr = itemPtr->next; | |
310 | } | |
311 | ||
312 | code = | |
313 | ubik_ParseServerList(nservers + 2, serverArgs, &globalConfPtr->myHost, | |
314 | globalConfPtr->serverList); | |
315 | if (code) | |
316 | ERROR(code); | |
317 | ||
318 | /* free space for the server args */ | |
319 | free(serverArgs); | |
320 | ||
321 | error_exit: | |
322 | return (code); | |
323 | } | |
324 | ||
325 | /* truncateDatabase | |
326 | * truncates just the database file. | |
327 | */ | |
328 | ||
329 | int | |
330 | truncateDatabase(void) | |
331 | { | |
332 | char *path; | |
333 | afs_int32 code = 0; | |
334 | int fd,r; | |
335 | ||
336 | r = asprintf(&path, "%s%s%s", | |
337 | globalConfPtr->databaseDirectory, | |
338 | globalConfPtr->databaseName, | |
339 | globalConfPtr->databaseExtension); | |
340 | if (r < 0 || path == NULL) | |
341 | ERROR(-1); | |
342 | ||
343 | fd = open(path, O_RDWR, 0755); | |
344 | if (!fd) { | |
345 | code = errno; | |
346 | } else { | |
347 | if (ftruncate(fd, 0) != 0) { | |
348 | code = errno; | |
349 | } else | |
350 | close(fd); | |
351 | } | |
352 | ||
353 | free(path); | |
354 | ||
355 | error_exit: | |
356 | return (code); | |
357 | } | |
358 | ||
359 | ||
360 | /* --- */ | |
361 | ||
362 | #include "AFS_component_version_number.c" | |
363 | ||
364 | int | |
365 | main(int argc, char **argv) | |
366 | { | |
367 | char *whoami = argv[0]; | |
368 | char *dbNamePtr = 0; | |
369 | struct afsconf_cell cellinfo_s; | |
370 | struct afsconf_cell *cellinfo = NULL; | |
371 | time_t currentTime; | |
372 | afs_int32 code = 0; | |
373 | afs_uint32 host = ntohl(INADDR_ANY); | |
374 | int r; | |
375 | ||
376 | char clones[MAXHOSTSPERCELL]; | |
377 | ||
378 | struct rx_service *tservice; | |
379 | struct rx_securityClass **securityClasses; | |
380 | afs_int32 numClasses; | |
381 | ||
382 | extern int rx_stackSize; | |
383 | ||
384 | #ifdef AFS_NT40_ENV | |
385 | /* initialize winsock */ | |
386 | if (afs_winsockInit() < 0) { | |
387 | ReportErrorEventAlt(AFSEVT_SVR_WINSOCK_INIT_FAILED, 0, argv[0], 0); | |
388 | fprintf(stderr, "%s: Couldn't initialize winsock.\n", whoami); | |
389 | exit(1); | |
390 | } | |
391 | #endif | |
392 | ||
393 | #ifdef AFS_AIX32_ENV | |
394 | /* | |
395 | * The following signal action for AIX is necessary so that in case of a | |
396 | * crash (i.e. core is generated) we can include the user's data section | |
397 | * in the core dump. Unfortunately, by default, only a partial core is | |
398 | * generated which, in many cases, isn't too useful. | |
399 | */ | |
400 | struct sigaction nsa; | |
401 | ||
402 | sigemptyset(&nsa.sa_mask); | |
403 | nsa.sa_handler = SIG_DFL; | |
404 | nsa.sa_flags = SA_FULLDUMP; | |
405 | sigaction(SIGSEGV, &nsa, NULL); | |
406 | sigaction(SIGABRT, &nsa, NULL); | |
407 | #endif | |
408 | ||
409 | memset(&cellinfo_s, 0, sizeof(cellinfo_s)); | |
410 | memset(clones, 0, sizeof(clones)); | |
411 | ||
412 | memset(&logopts, 0, sizeof(logopts)); | |
413 | logopts.lopt_dest = logDest_file; | |
414 | logopts.lopt_filename = AFSDIR_SERVER_BUDBLOG_FILEPATH; | |
415 | ||
416 | osi_audit_init(); | |
417 | osi_audit(BUDB_StartEvent, 0, AUD_END); | |
418 | ||
419 | initialize_BUDB_error_table(); | |
420 | initializeArgHandler(); | |
421 | ||
422 | /* Initialize dirpaths */ | |
423 | if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) { | |
424 | #ifdef AFS_NT40_ENV | |
425 | ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0); | |
426 | #endif | |
427 | afs_com_err(whoami, errno, "; Unable to obtain AFS server directory."); | |
428 | exit(2); | |
429 | } | |
430 | ||
431 | memset(globalConfPtr, 0, sizeof(*globalConfPtr)); | |
432 | ||
433 | /* set default configuration values */ | |
434 | strcpy(dbDir, AFSDIR_SERVER_DB_DIRPATH); | |
435 | strcat(dbDir, "/"); | |
436 | globalConfPtr->databaseDirectory = dbDir; | |
437 | globalConfPtr->databaseName = DEFAULT_DBPREFIX; | |
438 | strcpy(cellConfDir, AFSDIR_SERVER_ETC_DIRPATH); | |
439 | globalConfPtr->cellConfigdir = cellConfDir; | |
440 | ||
441 | srandom(1); | |
442 | ||
443 | #ifdef AFS_PTHREAD_ENV | |
444 | SetLogThreadNumProgram( rx_GetThreadNum ); | |
445 | #endif | |
446 | ||
447 | /* process the user supplied args */ | |
448 | helpOption = 1; | |
449 | code = cmd_Dispatch(argc, argv); | |
450 | if (code) | |
451 | ERROR(code); | |
452 | ||
453 | /* exit if there was a help option */ | |
454 | if (helpOption) | |
455 | BUDB_EXIT(0); | |
456 | ||
457 | /* open the log file */ | |
458 | OpenLog(&logopts); | |
459 | ||
460 | /* open the cell's configuration directory */ | |
461 | LogDebug(4, "opening %s\n", globalConfPtr->cellConfigdir); | |
462 | ||
463 | BU_conf = afsconf_Open(globalConfPtr->cellConfigdir); | |
464 | if (BU_conf == 0) { | |
465 | LogError(code, "Failed getting cell info\n"); | |
466 | afs_com_err(whoami, code, "Failed getting cell info"); | |
467 | ERROR(BUDB_NOCELLS); | |
468 | } | |
469 | ||
470 | code = afsconf_GetLocalCell(BU_conf, lcell, sizeof(lcell)); | |
471 | if (code) { | |
472 | LogError(0, "** Can't determine local cell name!\n"); | |
473 | ERROR(code); | |
474 | } | |
475 | ||
476 | if (globalConfPtr->myHost == 0) { | |
477 | /* if user hasn't supplied a list of servers, extract server | |
478 | * list from the cell's database | |
479 | */ | |
480 | ||
481 | cellinfo = &cellinfo_s; | |
482 | ||
483 | LogDebug(1, "Using server list from %s cell database.\n", lcell); | |
484 | ||
485 | code = afsconf_GetExtendedCellInfo (BU_conf, lcell, 0, cellinfo, | |
486 | clones); | |
487 | if (code) { | |
488 | LogError(0, "Can't read cell information\n"); | |
489 | ERROR(code); | |
490 | } | |
491 | ||
492 | code = | |
493 | convert_cell_to_ubik(cellinfo, &globalConfPtr->myHost, | |
494 | globalConfPtr->serverList); | |
495 | if (code) | |
496 | ERROR(code); | |
497 | } | |
498 | ||
499 | /* initialize audit user check */ | |
500 | osi_audit_set_user_check(BU_conf, BU_IsLocalRealmMatch); | |
501 | ||
502 | /* initialize ubik */ | |
503 | ubik_SetClientSecurityProcs(afsconf_ClientAuth, afsconf_UpToDate, BU_conf); | |
504 | ubik_SetServerSecurityProcs(afsconf_BuildServerSecurityObjects, | |
505 | afsconf_CheckAuth, BU_conf); | |
506 | ||
507 | if (ubik_nBuffers == 0) | |
508 | ubik_nBuffers = 400; | |
509 | ||
510 | LogError(0, "Will allocate %d ubik buffers\n", ubik_nBuffers); | |
511 | ||
512 | r = asprintf(&dbNamePtr, "%s%s", globalConfPtr->databaseDirectory, | |
513 | globalConfPtr->databaseName); | |
514 | if (r < 0 || dbNamePtr == 0) | |
515 | ERROR(-1); | |
516 | ||
517 | rx_SetRxDeadTime(60); /* 60 seconds inactive before timeout */ | |
518 | ||
519 | if (rxBind) { | |
520 | afs_int32 ccode; | |
521 | if (AFSDIR_SERVER_NETRESTRICT_FILEPATH || | |
522 | AFSDIR_SERVER_NETINFO_FILEPATH) { | |
523 | char reason[1024]; | |
524 | ccode = afsconf_ParseNetFiles(SHostAddrs, NULL, NULL, | |
525 | ADDRSPERSITE, reason, | |
526 | AFSDIR_SERVER_NETINFO_FILEPATH, | |
527 | AFSDIR_SERVER_NETRESTRICT_FILEPATH); | |
528 | } else | |
529 | { | |
530 | ccode = rx_getAllAddr(SHostAddrs, ADDRSPERSITE); | |
531 | } | |
532 | if (ccode == 1) { | |
533 | host = SHostAddrs[0]; | |
534 | rx_InitHost(host, htons(AFSCONF_BUDBPORT)); | |
535 | } | |
536 | } | |
537 | ||
538 | /* Disable jumbograms */ | |
539 | rx_SetNoJumbo(); | |
540 | ||
541 | if (cellinfo) { | |
542 | code = ubik_ServerInitByInfo(globalConfPtr->myHost, | |
543 | htons(AFSCONF_BUDBPORT), | |
544 | cellinfo, | |
545 | clones, | |
546 | dbNamePtr, /* name prefix */ | |
547 | &BU_dbase); | |
548 | } else { | |
549 | code = ubik_ServerInit(globalConfPtr->myHost, htons(AFSCONF_BUDBPORT), | |
550 | globalConfPtr->serverList, | |
551 | dbNamePtr, /* name prefix */ | |
552 | &BU_dbase); | |
553 | } | |
554 | ||
555 | if (code) { | |
556 | LogError(code, "Ubik init failed\n"); | |
557 | afs_com_err(whoami, code, "Ubik init failed"); | |
558 | ERROR(code); | |
559 | } | |
560 | ||
561 | afsconf_BuildServerSecurityObjects(BU_conf, &securityClasses, &numClasses); | |
562 | ||
563 | tservice = | |
564 | rx_NewServiceHost(host, 0, BUDB_SERVICE, "BackupDatabase", | |
565 | securityClasses, numClasses, BUDB_ExecuteRequest); | |
566 | ||
567 | if (tservice == (struct rx_service *)0) { | |
568 | LogError(0, "Could not create backup database rx service\n"); | |
569 | printf("Could not create backup database rx service\n"); | |
570 | BUDB_EXIT(3); | |
571 | } | |
572 | rx_SetMinProcs(tservice, 1); | |
573 | rx_SetMaxProcs(tservice, lwps); | |
574 | rx_SetStackSize(tservice, 10000); | |
575 | ||
576 | /* allow super users to manage RX statistics */ | |
577 | rx_SetRxStatUserOk(BU_rxstat_userok); | |
578 | ||
579 | /* misc. initialization */ | |
580 | ||
581 | /* database dump synchronization */ | |
582 | memset(dumpSyncPtr, 0, sizeof(*dumpSyncPtr)); | |
583 | Lock_Init(&dumpSyncPtr->ds_lock); | |
584 | ||
585 | rx_StartServer(0); /* start handling requests */ | |
586 | ||
587 | code = InitProcs(); | |
588 | if (code) | |
589 | ERROR(code); | |
590 | ||
591 | ||
592 | currentTime = time(0); | |
593 | LogError(0, "Ready to process requests at %s\n", ctime(¤tTime)); | |
594 | ||
595 | rx_ServerProc(NULL); /* donate this LWP */ | |
596 | ||
597 | error_exit: | |
598 | osi_audit(BUDB_FinishEvent, code, AUD_END); | |
599 | return (code); | |
600 | } | |
601 | ||
602 | void | |
603 | consistencyCheckDb(void) | |
604 | { | |
605 | /* do consistency checks on structure sizes */ | |
606 | if ((sizeof(struct htBlock) > BLOCKSIZE) | |
607 | || (sizeof(struct vfBlock) > BLOCKSIZE) | |
608 | || (sizeof(struct viBlock) > BLOCKSIZE) | |
609 | || (sizeof(struct dBlock) > BLOCKSIZE) | |
610 | || (sizeof(struct tBlock) > BLOCKSIZE) | |
611 | ) { | |
612 | fprintf(stderr, "Block layout error!\n"); | |
613 | BUDB_EXIT(99); | |
614 | } | |
615 | } | |
616 | ||
617 | void | |
618 | LogDebug(int level, char *fmt, ... ) | |
619 | { | |
620 | if (debugging >= level) { | |
621 | va_list ap; | |
622 | va_start(ap, fmt); | |
623 | vFSLog(fmt, ap); | |
624 | va_end(ap); | |
625 | } | |
626 | } | |
627 | ||
628 | void | |
629 | Log(char *fmt, ...) | |
630 | { | |
631 | va_list ap; | |
632 | ||
633 | va_start(ap, fmt); | |
634 | vFSLog(fmt, ap); | |
635 | va_end(ap); | |
636 | } | |
637 | ||
638 | void | |
639 | LogError(long code, char *fmt, ... ) | |
640 | { | |
641 | va_list ap; | |
642 | int len; | |
643 | char buffer[1024]; | |
644 | ||
645 | va_start(ap, fmt); | |
646 | len = vsnprintf(buffer, sizeof(buffer), fmt, ap); | |
647 | va_end(ap); | |
648 | if (len >= 1024) { | |
649 | len = 1023; | |
650 | buffer[1023] = '\0'; | |
651 | } | |
652 | /* Be consistent with (unintentional?) historic behavior. */ | |
653 | if (code) { | |
654 | FSLog("%s: %s\n", afs_error_table_name(code), afs_error_message(code)); | |
655 | WriteLogBuffer(buffer, len); | |
656 | } else { | |
657 | FSLog("%s", buffer); | |
658 | } | |
659 | } |