DEVEL15-openafs-string-header-cleanup-20071030
[openafs.git] / src / libadmin / bos / afs_bosAdmin.c
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
13 RCSID
14     ("$Header$");
15
16 #include <stdio.h>
17 #include <afs/stds.h>
18 #include "afs_bosAdmin.h"
19 #include "../adminutil/afs_AdminInternal.h"
20 #include <afs/afs_AdminErrors.h>
21 #include <afs/afs_utilAdmin.h>
22 #include <afs/bosint.h>
23 #include <afs/bnode.h>
24 #include <afs/ktime.h>
25 #include <afs/dirpath.h>
26 #include <fcntl.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <stdlib.h>
30 #ifdef AFS_NT40_ENV
31 #include <io.h>
32 #else
33 #include <unistd.h>
34 #endif
35 #include <string.h>
36
37 typedef struct bos_server {
38     int begin_magic;
39     int is_valid;
40     struct rx_connection *server;
41     struct rx_connection *server_encrypt;
42     struct rx_connection *server_stats;
43     int end_magic;
44 } bos_server_t, *bos_server_p;
45
46 /*
47  * isValidServerHandle - validate a bos_server_p.
48  *
49  * PARAMETERS
50  *
51  * IN serverHandle - the handle to validate
52  *
53  * LOCKS
54  *
55  * No locks are obtained or released by this function
56  *
57  * RETURN CODES
58  *
59  * Returns != 0 upon successful completion.
60  */
61
62 int
63 isValidServerHandle(const bos_server_p serverHandle, afs_status_p st)
64 {
65     int rc = 0;
66     afs_status_t tst = 0;
67
68     if (serverHandle == NULL) {
69         tst = ADMBOSSERVERHANDLENULL;
70         goto fail_IsValidServerHandle;
71     }
72
73     if ((serverHandle->begin_magic != BEGIN_MAGIC)
74         || (serverHandle->end_magic != END_MAGIC)) {
75         tst = ADMBOSSERVERHANDLEBADMAGIC;
76         goto fail_IsValidServerHandle;
77     }
78
79     if (serverHandle->is_valid == 0) {
80         tst = ADMBOSSERVERHANDLEINVALID;
81         goto fail_IsValidServerHandle;
82     }
83
84     if (serverHandle->server == NULL) {
85         tst = ADMBOSSERVERHANDLENOSERVER;
86         goto fail_IsValidServerHandle;
87     }
88
89     if (serverHandle->server_encrypt == NULL) {
90         tst = ADMBOSSERVERHANDLENOSERVER;
91         goto fail_IsValidServerHandle;
92     }
93     rc = 1;
94
95   fail_IsValidServerHandle:
96
97     if (st != NULL) {
98         *st = tst;
99     }
100     return rc;
101 }
102
103 /*
104  * IsValidCellHandle - verify that a cell handle can be used to make bos
105  * requests.
106  *
107  * PARAMETERS
108  *
109  * IN cellHandle - the cellHandle to be validated.
110  *
111  * LOCKS
112  *
113  * No locks are obtained or released by this function
114  *
115  * RETURN CODES
116  *
117  * Returns != 0 upon successful completion.
118  */
119
120 static int
121 IsValidCellHandle(afs_cell_handle_p cellHandle, afs_status_p st)
122 {
123     int rc = 0;
124     afs_status_t tst = 0;
125
126     if (!CellHandleIsValid((void *)cellHandle, &tst)) {
127         goto fail_IsValidCellHandle;
128     }
129
130     if (cellHandle->tokens == NULL) {
131         tst = ADMBOSCELLHANDLENOTOKENS;
132         goto fail_IsValidCellHandle;
133     }
134     rc = 1;
135
136   fail_IsValidCellHandle:
137
138     if (st != NULL) {
139         *st = tst;
140     }
141     return rc;
142 }
143
144 /*
145  * bos_ServerOpen - open a bos server for work.
146  *
147  * PARAMETERS
148  *
149  * IN cellHandle - a previously opened cellHandle.
150  *
151  * IN serverName - the name of the machine that houses the bosserver of 
152  * interest.
153  *
154  * OUT serverHandleP - upon successful completion, this void pointer
155  * will point to a valid server handle for use in future operations.
156  *
157  * LOCKS
158  *
159  * No locks are obtained or released by this function
160  *
161  * RETURN CODES
162  *
163  * Returns != 0 upon successful completion.
164  */
165
166 int ADMINAPI
167 bos_ServerOpen(const void *cellHandle, const char *serverName,
168                void **serverHandleP, afs_status_p st)
169 {
170     int rc = 0;
171     afs_status_t tst = 0;
172     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
173     bos_server_p bos_server = (bos_server_p) malloc(sizeof(bos_server_t));
174     int serverAddress;
175
176     /*
177      * Validate parameters
178      */
179
180     if (!IsValidCellHandle(c_handle, &tst)) {
181         goto fail_bos_ServerOpen;
182     }
183
184     if ((serverName == NULL) || (*serverName == 0)) {
185         tst = ADMBOSSERVERNAMENULL;
186         goto fail_bos_ServerOpen;
187     }
188
189     if (serverHandleP == NULL) {
190         tst = ADMBOSSERVERHANDLEPNULL;
191         goto fail_bos_ServerOpen;
192     }
193
194     if (util_AdminServerAddressGetFromName(serverName, &serverAddress, &tst)
195         == 0) {
196         goto fail_bos_ServerOpen;
197     }
198
199     if (bos_server == NULL) {
200         tst = ADMNOMEM;
201         goto fail_bos_ServerOpen;
202     }
203
204     bos_server->server =
205         rx_GetCachedConnection(htonl(serverAddress), htons(AFSCONF_NANNYPORT),
206                                1,
207                                c_handle->tokens->afs_sc[c_handle->tokens->
208                                                         sc_index],
209                                c_handle->tokens->sc_index);
210
211     bos_server->server_encrypt =
212         rx_GetCachedConnection(htonl(serverAddress), htons(AFSCONF_NANNYPORT),
213                                1,
214                                c_handle->tokens->afs_encrypt_sc[c_handle->
215                                                                 tokens->
216                                                                 sc_index],
217                                c_handle->tokens->sc_index);
218
219     bos_server->server_stats =
220         rx_GetCachedConnection(htonl(serverAddress), htons(AFSCONF_NANNYPORT),
221                                RX_STATS_SERVICE_ID,
222                                c_handle->tokens->afs_sc[c_handle->tokens->
223                                                         sc_index],
224                                c_handle->tokens->sc_index);
225
226     if ((bos_server->server == NULL) || (bos_server->server_encrypt == NULL)) {
227         tst = ADMBOSSERVERNOCONNECTION;
228         goto fail_bos_ServerOpen;
229     }
230
231     bos_server->begin_magic = BEGIN_MAGIC;
232     bos_server->is_valid = 1;
233     bos_server->end_magic = END_MAGIC;
234
235     *serverHandleP = (void *)bos_server;
236     rc = 1;
237
238   fail_bos_ServerOpen:
239
240     if ((rc == 0) && (bos_server != NULL)) {
241         if (bos_server->server) {
242             rx_ReleaseCachedConnection(bos_server->server);
243         }
244         if (bos_server->server_encrypt) {
245             rx_ReleaseCachedConnection(bos_server->server_encrypt);
246         }
247         free(bos_server);
248     }
249
250     if (st != NULL) {
251         *st = tst;
252     }
253     return rc;
254 }
255
256 /*
257  * bos_ServerClose - close a bos server handle
258  *
259  * PARAMETERS
260  *
261  * IN serverHandle - a bos server handle previously returned by bos_ServerOpen
262  *
263  * LOCKS
264  *
265  * No locks are obtained or released by this function
266  *
267  * RETURN CODES
268  *
269  * Returns != 0 upon successful completion.
270  */
271
272 int ADMINAPI
273 bos_ServerClose(const void *serverHandle, afs_status_p st)
274 {
275     int rc = 0;
276     afs_status_t tst = 0;
277     bos_server_p b_handle = (bos_server_p) serverHandle;
278
279     if (isValidServerHandle(b_handle, &tst)) {
280         rx_ReleaseCachedConnection(b_handle->server);
281         b_handle->is_valid = 0;
282         free(b_handle);
283         rc = 1;
284     }
285
286     if (st != NULL) {
287         *st = tst;
288     }
289     return rc;
290 }
291
292 /*
293  * bos_ProcessCreate - create a new process to run at a bos server.
294  *
295  * PARAMETERS
296  *
297  * IN serverHandle - a previously opened serverHandle.
298  *
299  * IN processName - the name of the process to create.
300  *
301  * IN processType - the type of process to create.
302  *
303  * IN process - the path to the process binary at the bos server.
304  *
305  * IN cronTime - the time specification for cron processes.
306  *
307  * IN notifier - the path to the notifier binary at the bos server.
308  *
309  * LOCKS
310  *
311  * No locks are obtained or released by this function
312  *
313  * RETURN CODES
314  *
315  * Returns != 0 upon successful completion.
316  */
317
318 /*
319  * CAUTION - this list must match bos_ProcessType_t definition
320  */
321
322 static char *processTypes[] = { "simple", "fs", "cron", 0 };
323
324 int ADMINAPI
325 bos_ProcessCreate(const void *serverHandle, const char *processName,
326                   bos_ProcessType_t processType, const char *process,
327                   const char *cronTime, const char *notifier, afs_status_p st)
328 {
329     int rc = 0;
330     afs_status_t tst = 0;
331     bos_server_p b_handle = (bos_server_p) serverHandle;
332
333     if (!isValidServerHandle(b_handle, &tst)) {
334         goto fail_bos_ProcessCreate;
335     }
336
337     if (processType == BOS_PROCESS_FS) {
338         tst = ADMBOSPROCESSCREATEBADTYPE;
339         goto fail_bos_ProcessCreate;
340     }
341
342     if ((processName == NULL) || (*processName == 0)) {
343         tst = ADMBOSPROCESSNAMENULL;
344         goto fail_bos_ProcessCreate;
345     }
346
347     if ((process == NULL) || (*process == 0)) {
348         tst = ADMBOSPROCESSNULL;
349         goto fail_bos_ProcessCreate;
350     }
351
352     if ((processType == BOS_PROCESS_CRON) && (cronTime == NULL)) {
353         tst = ADMBOSCRONTIMENULL;
354         goto fail_bos_ProcessCreate;
355     }
356
357     if ((processType == BOS_PROCESS_SIMPLE) && (cronTime != NULL)) {
358         tst = ADMBOSCRONTIMENOTNULL;
359         goto fail_bos_ProcessCreate;
360     }
361
362     tst =
363         BOZO_CreateBnode(b_handle->server, processTypes[processType],
364                          processName, process, (cronTime) ? cronTime : "", "",
365                          "", "", (notifier) ? notifier : NONOTIFIER);
366     if (tst == 0) {
367         rc = 1;
368     }
369
370   fail_bos_ProcessCreate:
371
372     if (st != NULL) {
373         *st = tst;
374     }
375     return rc;
376 }
377
378 /*
379  * bos_FSProcessCreate - create the fs group of processes at the boserver.
380  *
381  * PARAMETERS
382  *
383  * IN serverHandle - a previously opened serverHandle.
384  *
385  * IN processName - the name of the process to create.
386  *
387  * IN fileserverPath - the path to the fileserver binary at the bos server.
388  *
389  * IN volserverPath - the path to the volserver binary at the bos server.
390  *
391  * IN salvagerPath - the path to the salvager binary at the bos server.
392  *
393  * IN notifier - the path to the notifier binary at the bos server.
394  *
395  * LOCKS
396  *
397  * No locks are obtained or released by this function
398  *
399  * RETURN CODES
400  *
401  * Returns != 0 upon successful completion.
402  */
403
404 int ADMINAPI
405 bos_FSProcessCreate(const void *serverHandle, const char *processName,
406                     const char *fileserverPath, const char *volserverPath,
407                     const char *salvagerPath, const char *notifier,
408                     afs_status_p st)
409 {
410     int rc = 0;
411     afs_status_t tst = 0;
412     bos_server_p b_handle = (bos_server_p) serverHandle;
413
414     if (!isValidServerHandle(b_handle, &tst)) {
415         goto fail_bos_ProcessCreate;
416     }
417
418     if ((processName == NULL) || (*processName == 0)) {
419         tst = ADMBOSPROCESSNAMENULL;
420         goto fail_bos_ProcessCreate;
421     }
422
423     if ((fileserverPath == NULL) || (*fileserverPath == 0)) {
424         tst = ADMBOSFILESERVERPATHNULL;
425         goto fail_bos_ProcessCreate;
426     }
427
428     if ((volserverPath == NULL) || (*volserverPath == 0)) {
429         tst = ADMBOSVOLSERVERPATHNULL;
430         goto fail_bos_ProcessCreate;
431     }
432
433     if ((salvagerPath == NULL) || (*salvagerPath == 0)) {
434         tst = ADMBOSSALVAGERPATHNULL;
435         goto fail_bos_ProcessCreate;
436     }
437
438     tst =
439         BOZO_CreateBnode(b_handle->server, processTypes[BOS_PROCESS_FS],
440                          processName, fileserverPath, volserverPath,
441                          salvagerPath, "", "",
442                          (notifier) ? notifier : NONOTIFIER);
443     if (tst == 0) {
444         rc = 1;
445     }
446
447   fail_bos_ProcessCreate:
448
449     if (st != NULL) {
450         *st = tst;
451     }
452     return rc;
453 }
454
455 /*
456  * bos_ProcessDelete - delete an existing process at a bos server.
457  *
458  * PARAMETERS
459  *
460  * IN serverHandle - a previously opened serverHandle.
461  *
462  * IN processName - the name of the process to delete.
463  *
464  * LOCKS
465  *
466  * No locks are obtained or released by this function
467  *
468  * RETURN CODES
469  *
470  * Returns != 0 upon successful completion.
471  */
472
473 int ADMINAPI
474 bos_ProcessDelete(const void *serverHandle, const char *processName,
475                   afs_status_p st)
476 {
477     int rc = 0;
478     afs_status_t tst = 0;
479     bos_server_p b_handle = (bos_server_p) serverHandle;
480
481     if (!isValidServerHandle(b_handle, &tst)) {
482         goto fail_bos_ProcessDelete;
483     }
484
485     if ((processName == NULL) || (*processName == 0)) {
486         tst = ADMBOSPROCESSNAMENULL;
487         goto fail_bos_ProcessDelete;
488     }
489
490     tst = BOZO_DeleteBnode(b_handle->server, processName);
491
492     if (tst == 0) {
493         rc = 1;
494     }
495
496   fail_bos_ProcessDelete:
497
498     if (st != NULL) {
499         *st = tst;
500     }
501     return rc;
502 }
503
504 /*
505  * bos_ProcessExecutionStateGet - get the current execution state of a 
506  * process
507  *
508  * PARAMETERS
509  *
510  * IN serverHandle - a previously opened serverHandle.
511  *
512  * IN processName - the name of the process to retrieve.
513  *
514  * OUT processStatusP - upon successful completion the process execution state
515  *
516  * OUT auxiliaryProcessStatus - set to point to aux proc status if available.
517  * Pass a pointer to an char array at least BOS_MAX_NAME_LEN long.
518  *
519  * LOCKS
520  *
521  * No locks are obtained or released by this function
522  *
523  * RETURN CODES
524  *
525  * Returns != 0 upon successful completion.
526  */
527
528 int ADMINAPI
529 bos_ProcessExecutionStateGet(const void *serverHandle,
530                              const char *processName,
531                              bos_ProcessExecutionState_p processStatusP,
532                              char *auxiliaryProcessStatus, afs_status_p st)
533 {
534     int rc = 0;
535     afs_status_t tst = 0;
536     bos_server_p b_handle = (bos_server_p) serverHandle;
537     afs_int32 state;
538
539     if (!isValidServerHandle(b_handle, &tst)) {
540         goto fail_bos_ProcessExecutionStateGet;
541     }
542
543     if ((processName == NULL) || (*processName == 0)) {
544         tst = ADMBOSPROCESSNAMENULL;
545         goto fail_bos_ProcessExecutionStateGet;
546     }
547
548     if (processStatusP == NULL) {
549         tst = ADMBOSPROCESSSTATUSPNULL;
550         goto fail_bos_ProcessExecutionStateGet;
551     }
552
553     if (auxiliaryProcessStatus == NULL) {
554         tst = ADMBOSAUXILIARYPROCESSSTATUSNULL;
555         goto fail_bos_ProcessExecutionStateGet;
556     }
557
558     tst =
559         BOZO_GetStatus(b_handle->server, processName, &state,
560                        &auxiliaryProcessStatus);
561
562     if (tst != 0) {
563         goto fail_bos_ProcessExecutionStateGet;
564     }
565
566     *processStatusP = (bos_ProcessExecutionState_t) state;
567     rc = 1;
568
569   fail_bos_ProcessExecutionStateGet:
570
571     if (st != NULL) {
572         *st = tst;
573     }
574     return rc;
575 }
576
577 /*
578  * SetExecutionState - set the execution state of a process
579  *
580  * PARAMETERS
581  *
582  * IN serverHandle - a previously opened serverHandle.
583  *
584  * IN processName - the name of the process to modify.
585  *
586  * IN processStatus - the new process state.
587  *
588  * IN func - the function to call to set the status.
589  *
590  * LOCKS
591  *
592  * No locks are obtained or released by this function
593  *
594  * RETURN CODES
595  *
596  * Returns != 0 upon successful completion.
597  */
598
599 static int
600 SetExecutionState(const void *serverHandle, const char *processName,
601                   const bos_ProcessExecutionState_t processStatus,
602                   int (*func) (struct rx_connection *, const char *,
603                                afs_int32), afs_status_p st)
604 {
605     int rc = 0;
606     afs_status_t tst = 0;
607     bos_server_p b_handle = (bos_server_p) serverHandle;
608     afs_int32 state;
609
610     if (!isValidServerHandle(b_handle, &tst)) {
611         goto fail_SetExecutionState;
612     }
613
614     if ((processName == NULL) || (*processName == 0)) {
615         tst = ADMBOSPROCESSNAMENULL;
616         goto fail_SetExecutionState;
617     }
618
619     if ((processStatus != BOS_PROCESS_STOPPED)
620         && (processStatus != BOS_PROCESS_RUNNING)) {
621         tst = ADMBOSPROCESSSTATUSSET;
622         goto fail_SetExecutionState;
623     }
624
625     state = (afs_int32) processStatus;
626
627     tst = func(b_handle->server, processName, state);
628
629     if (tst == 0) {
630         rc = 1;
631     }
632
633   fail_SetExecutionState:
634
635     if (st != NULL) {
636         *st = tst;
637     }
638     return rc;
639 }
640
641 /*
642  * bos_ProcessExecutionStateSet - set the execution state of a process
643  *
644  * PARAMETERS
645  *
646  * IN serverHandle - a previously opened serverHandle.
647  *
648  * IN processName - the name of the process to modify.
649  *
650  * IN processStatus - the new process state.
651  *
652  * LOCKS
653  *
654  * No locks are obtained or released by this function
655  *
656  * RETURN CODES
657  *
658  * Returns != 0 upon successful completion.
659  */
660
661 int ADMINAPI
662 bos_ProcessExecutionStateSet(const void *serverHandle,
663                              const char *processName,
664                              bos_ProcessExecutionState_t processStatus,
665                              afs_status_p st)
666 {
667     return SetExecutionState(serverHandle, processName, processStatus,
668                              BOZO_SetStatus, st);
669 }
670
671 /*
672  * bos_ProcessExecutionStateSetTemporary - set the execution state of a process
673  * temporarily
674  *
675  * PARAMETERS
676  *
677  * IN serverHandle - a previously opened serverHandle.
678  *
679  * IN processName - the name of the process to modify.
680  *
681  * IN processStatus - the new process state.
682  *
683  * LOCKS
684  *
685  * No locks are obtained or released by this function
686  *
687  * RETURN CODES
688  *
689  * Returns != 0 upon successful completion.
690  */
691
692 int ADMINAPI
693 bos_ProcessExecutionStateSetTemporary(const void *serverHandle,
694                                       const char *processName,
695                                       bos_ProcessExecutionState_t
696                                       processStatus, afs_status_p st)
697 {
698     return SetExecutionState(serverHandle, processName, processStatus,
699                              BOZO_SetTStatus, st);
700 }
701
702 /*
703  * The iterator functions and data for the process name retrieval functions
704  */
705
706 typedef struct process_name_get {
707     int next;
708     struct rx_connection *server;
709     char process[CACHED_ITEMS][BOS_MAX_NAME_LEN];
710 } process_name_get_t, *process_name_get_p;
711
712 static int
713 GetProcessNameRPC(void *rpc_specific, int slot, int *last_item,
714                   int *last_item_contains_data, afs_status_p st)
715 {
716     int rc = 0;
717     afs_status_t tst = 0;
718     process_name_get_p proc = (process_name_get_p) rpc_specific;
719     char *ptr = (char *)&proc->process[slot];
720
721     tst = BOZO_EnumerateInstance(proc->server, proc->next++, &ptr);
722
723     if (tst == 0) {
724         rc = 1;
725     } else if (tst == BZDOM) {
726         tst = 0;
727         rc = 1;
728         *last_item = 1;
729         *last_item_contains_data = 0;
730     }
731
732     if (st != NULL) {
733         *st = tst;
734     }
735     return rc;
736 }
737
738 static int
739 GetProcessNameFromCache(void *rpc_specific, int slot, void *dest,
740                         afs_status_p st)
741 {
742     int rc = 0;
743     afs_status_t tst = 0;
744     process_name_get_p proc = (process_name_get_p) rpc_specific;
745
746     strcpy((char *)dest, (char *)&proc->process[slot]);
747     rc = 1;
748
749     if (st != NULL) {
750         *st = tst;
751     }
752     return rc;
753 }
754
755 /*
756  * bos_ProcessNameGetBegin - begin iterating over the list of processes
757  * at a particular bos server.
758  *
759  * PARAMETERS
760  *
761  * IN serverHandle - a previously opened serverHandle.
762  *
763  * OUT iter - an iterator that can be passed to bos_ProcessNameGetNext
764  * to retrieve the process names.
765  *
766  * LOCKS
767  *
768  * No locks are obtained or released by this function
769  *
770  * RETURN CODES
771  *
772  * Returns != 0 upon successful completion.
773  *
774  */
775
776 int ADMINAPI
777 bos_ProcessNameGetBegin(const void *serverHandle, void **iterationIdP,
778                         afs_status_p st)
779 {
780     int rc = 0;
781     afs_status_t tst = 0;
782     bos_server_p b_handle = (bos_server_p) serverHandle;
783     afs_admin_iterator_p iter =
784         (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
785     process_name_get_p proc =
786         (process_name_get_p) malloc(sizeof(process_name_get_t));
787
788     if (!isValidServerHandle(b_handle, &tst)) {
789         goto fail_bos_ProcessNameGetBegin;
790     }
791
792     if (iterationIdP == NULL) {
793         tst = ADMITERATIONIDPNULL;
794         goto fail_bos_ProcessNameGetBegin;
795     }
796
797     if ((iter == NULL) || (proc == NULL)) {
798         tst = ADMNOMEM;
799         goto fail_bos_ProcessNameGetBegin;
800     }
801
802     proc->next = 0;
803     proc->server = b_handle->server;
804
805     if (IteratorInit
806         (iter, (void *)proc, GetProcessNameRPC, GetProcessNameFromCache, NULL,
807          NULL, &tst)) {
808         *iterationIdP = (void *)iter;
809     } else {
810         goto fail_bos_ProcessNameGetBegin;
811     }
812     rc = 1;
813
814   fail_bos_ProcessNameGetBegin:
815
816     if (rc == 0) {
817         if (iter != NULL) {
818             free(iter);
819         }
820         if (proc != NULL) {
821             free(proc);
822         }
823     }
824
825     if (st != NULL) {
826         *st = tst;
827     }
828     return rc;
829 }
830
831 /*
832  * bos_ProcessNameGetNext - retrieve the next process name from the bos server.
833  *
834  * PARAMETERS
835  *
836  * IN iterationId - an iterator previously returned by bos_ProcessNameGetBegin
837  *
838  * OUT processName - upon successful completion contains the next process name
839  * retrieved from the server.
840  *
841  * LOCKS
842  *
843  * No locks are obtained or released by this function
844  *
845  * RETURN CODES
846  *
847  * Returns != 0 upon successful completion.
848  *
849  */
850
851 int ADMINAPI
852 bos_ProcessNameGetNext(const void *iterationId, char *processName,
853                        afs_status_p st)
854 {
855     int rc = 0;
856     afs_status_t tst = 0;
857     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
858
859     if (processName == NULL) {
860         tst = ADMBOSPROCESSNAMENULL;
861         goto fail_bos_ProcessNameGetNext;
862     }
863
864     if (iterationId == NULL) {
865         tst = ADMITERATIONIDPNULL;
866         goto fail_bos_ProcessNameGetNext;
867     }
868
869     rc = IteratorNext(iter, (void *)processName, &tst);
870
871   fail_bos_ProcessNameGetNext:
872
873     if (st != NULL) {
874         *st = tst;
875     }
876     return rc;
877 }
878
879 /*
880  * bos_ProcessNameGetDone - finish using a process name iterator.
881  *
882  * PARAMETERS
883  *
884  * IN iterationId - an iterator previously returned by bos_ProcessNameGetBegin
885  *
886  * LOCKS
887  *
888  * No locks are obtained or released by this function
889  *
890  * RETURN CODES
891  *
892  * Returns != 0 upon successful completion.
893  *
894  */
895
896 int ADMINAPI
897 bos_ProcessNameGetDone(const void *iterationId, afs_status_p st)
898 {
899     int rc = 0;
900     afs_status_t tst = 0;
901     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
902
903     if (iterationId == NULL) {
904         tst = ADMITERATIONIDPNULL;
905         goto fail_bos_ProcessNameGetDone;
906     }
907
908     rc = IteratorDone(iter, &tst);
909
910   fail_bos_ProcessNameGetDone:
911
912     if (st != NULL) {
913         *st = tst;
914     }
915     return rc;
916 }
917
918 /*
919  * bos_ProcessInfoGet - get information about a single process
920  *
921  * PARAMETERS
922  *
923  * IN serverHandle - a previously opened serverHandle.
924  *
925  * IN processName - the process of interest.
926  *
927  * OUT processTypeP - upon successful completion contains the process type
928  *
929  * OUT processInfoP - upon successful completion contains the process info
930  *
931  * LOCKS
932  *
933  * No locks are obtained or released by this function
934  *
935  * RETURN CODES
936  *
937  * Returns != 0 upon successful completion.
938  *
939  */
940
941 int ADMINAPI
942 bos_ProcessInfoGet(const void *serverHandle, const char *processName,
943                    bos_ProcessType_p processTypeP,
944                    bos_ProcessInfo_p processInfoP, afs_status_p st)
945 {
946     int rc = 0;
947     afs_status_t tst = 0;
948     bos_server_p b_handle = (bos_server_p) serverHandle;
949     char type[BOS_MAX_NAME_LEN];
950     char *ptr = type;
951     struct bozo_status status;
952     int i;
953
954     if (!isValidServerHandle(b_handle, &tst)) {
955         goto fail_bos_ProcessInfoGet;
956     }
957
958     if ((processName == NULL) || (*processName == 0)) {
959         tst = ADMBOSPROCESSNAMENULL;
960         goto fail_bos_ProcessInfoGet;
961     }
962
963     if (processTypeP == NULL) {
964         tst = ADMBOSPROCESSTYPEPNULL;
965         goto fail_bos_ProcessInfoGet;
966     }
967
968     if (processInfoP == NULL) {
969         tst = ADMBOSPROCESSINFOPNULL;
970         goto fail_bos_ProcessInfoGet;
971     }
972
973     tst = BOZO_GetInstanceInfo(b_handle->server, processName, &ptr, &status);
974
975     if (tst != 0) {
976         goto fail_bos_ProcessInfoGet;
977     }
978
979
980     for (i = 0; (processTypes[i] != NULL); i++) {
981         if (!strcmp(processTypes[i], type)) {
982             *processTypeP = (bos_ProcessType_t) i;
983             break;
984         }
985     }
986
987     if (processTypes[i] == NULL) {
988         tst = ADMBOSINVALIDPROCESSTYPE;
989         goto fail_bos_ProcessInfoGet;
990     }
991
992     processInfoP->processGoal = (bos_ProcessExecutionState_t) status.goal;
993     processInfoP->processStartTime = status.procStartTime;
994     processInfoP->numberProcessStarts = status.procStarts;
995     processInfoP->processExitTime = status.lastAnyExit;
996     processInfoP->processExitErrorTime = status.lastErrorExit;
997     processInfoP->processErrorCode = status.errorCode;
998     processInfoP->processErrorSignal = status.errorSignal;
999     processInfoP->state = BOS_PROCESS_OK;
1000
1001     if (status.flags & BOZO_ERRORSTOP) {
1002         processInfoP->state |= BOS_PROCESS_TOO_MANY_ERRORS;
1003     }
1004     if (status.flags & BOZO_HASCORE) {
1005         processInfoP->state |= BOS_PROCESS_CORE_DUMPED;
1006     }
1007     if (status.flags & BOZO_BADDIRACCESS) {
1008         processInfoP->state |= BOS_PROCESS_BAD_FILE_ACCESS;
1009     }
1010     rc = 1;
1011
1012   fail_bos_ProcessInfoGet:
1013
1014     if (st != NULL) {
1015         *st = tst;
1016     }
1017     return rc;
1018 }
1019
1020 /*
1021  * The iterator functions and data for the parameter retrieval functions
1022  */
1023
1024 typedef struct param_get {
1025     int next;
1026     struct rx_connection *server;
1027     char processName[BOS_MAX_NAME_LEN];
1028     char param[CACHED_ITEMS][BOS_MAX_NAME_LEN];
1029 } param_get_t, *param_get_p;
1030
1031 static int
1032 GetParameterRPC(void *rpc_specific, int slot, int *last_item,
1033                 int *last_item_contains_data, afs_status_p st)
1034 {
1035     int rc = 0;
1036     afs_status_t tst = 0;
1037     param_get_p param = (param_get_p) rpc_specific;
1038     char *ptr = (char *)&param->param[slot];
1039
1040     tst =
1041         BOZO_GetInstanceParm(param->server, param->processName, param->next++,
1042                              &ptr);
1043
1044     if (tst == 0) {
1045         rc = 1;
1046     } else if (tst == BZDOM) {
1047         tst = 0;
1048         rc = 1;
1049         *last_item = 1;
1050         *last_item_contains_data = 0;
1051     }
1052
1053     if (st != NULL) {
1054         *st = tst;
1055     }
1056     return rc;
1057 }
1058
1059 static int
1060 GetParameterFromCache(void *rpc_specific, int slot, void *dest,
1061                       afs_status_p st)
1062 {
1063     int rc = 0;
1064     afs_status_t tst = 0;
1065     param_get_p param = (param_get_p) rpc_specific;
1066
1067     strcpy((char *)dest, (char *)&param->param[slot]);
1068     rc = 1;
1069
1070     if (st != NULL) {
1071         *st = tst;
1072     }
1073     return rc;
1074 }
1075
1076 /*
1077  * bos_ProcessParameterGetBegin - begin iterating over the parameters
1078  * of a particular process.
1079  *
1080  * PARAMETERS
1081  *
1082  * IN serverHandle - a previously opened serverHandle.
1083  *
1084  * IN processName - the process whose parameters are returned.
1085  *
1086  * OUT iter - an iterator that can be passed to bos_ProcessParameterGetNext
1087  * to retrieve the parameters.
1088  *
1089  * LOCKS
1090  *
1091  * No locks are obtained or released by this function
1092  *
1093  * RETURN CODES
1094  *
1095  * Returns != 0 upon successful completion.
1096  *
1097  */
1098
1099 int ADMINAPI
1100 bos_ProcessParameterGetBegin(const void *serverHandle,
1101                              const char *processName, void **iterationIdP,
1102                              afs_status_p st)
1103 {
1104     int rc = 0;
1105     afs_status_t tst = 0;
1106     bos_server_p b_handle = (bos_server_p) serverHandle;
1107     afs_admin_iterator_p iter =
1108         (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1109     param_get_p param = (param_get_p) malloc(sizeof(param_get_t));
1110
1111     if (!isValidServerHandle(b_handle, &tst)) {
1112         goto fail_bos_ProcessParameterGetBegin;
1113     }
1114
1115     if ((processName == NULL) || (*processName == 0)) {
1116         tst = ADMBOSPROCESSNAMENULL;
1117         goto fail_bos_ProcessParameterGetBegin;
1118     }
1119
1120     if (iterationIdP == NULL) {
1121         tst = ADMITERATIONIDPNULL;
1122         goto fail_bos_ProcessParameterGetBegin;
1123     }
1124
1125     if ((iter == NULL) || (param == NULL)) {
1126         tst = ADMNOMEM;
1127         goto fail_bos_ProcessParameterGetBegin;
1128     }
1129
1130     param->next = 0;
1131     param->server = b_handle->server;
1132     strcpy(param->processName, processName);
1133
1134     if (IteratorInit
1135         (iter, (void *)param, GetParameterRPC, GetParameterFromCache, NULL,
1136          NULL, &tst)) {
1137         *iterationIdP = (void *)iter;
1138     } else {
1139         goto fail_bos_ProcessParameterGetBegin;
1140     }
1141     rc = 1;
1142
1143   fail_bos_ProcessParameterGetBegin:
1144
1145     if (rc == 0) {
1146         if (iter != NULL) {
1147             free(iter);
1148         }
1149         if (param != NULL) {
1150             free(param);
1151         }
1152     }
1153
1154     if (st != NULL) {
1155         *st = tst;
1156     }
1157     return rc;
1158 }
1159
1160 /*
1161  * bos_ProcessParameterGetNext - retrieve the next parameter 
1162  * from the bos server.
1163  *
1164  * PARAMETERS
1165  *
1166  * IN iterationId - an iterator previously returned by 
1167  * bos_ProcessParameterGetBegin
1168  *
1169  * OUT parameter - upon successful completion contains the next parameter
1170  * retrieved from the server.
1171  *
1172  * LOCKS
1173  *
1174  * No locks are obtained or released by this function
1175  *
1176  * RETURN CODES
1177  *
1178  * Returns != 0 upon successful completion.
1179  *
1180  */
1181
1182 int ADMINAPI
1183 bos_ProcessParameterGetNext(const void *iterationId, char *parameter,
1184                             afs_status_p st)
1185 {
1186     int rc = 0;
1187     afs_status_t tst = 0;
1188     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1189
1190     if (iterationId == NULL) {
1191         tst = ADMITERATIONIDPNULL;
1192         goto fail_bos_ProcessParameterGetNext;
1193     }
1194
1195     if (parameter == NULL) {
1196         tst = ADMBOSPARAMETERNULL;
1197         goto fail_bos_ProcessParameterGetNext;
1198     }
1199
1200     rc = IteratorNext(iter, (void *)parameter, &tst);
1201
1202   fail_bos_ProcessParameterGetNext:
1203
1204     if (st != NULL) {
1205         *st = tst;
1206     }
1207     return rc;
1208 }
1209
1210 /*
1211  * bos_ProcessParameterGetDone - finish using a process name iterator.
1212  *
1213  * PARAMETERS
1214  *
1215  * IN iterationId - an iterator previously returned by
1216  * bos_ProcessParameterGetBegin
1217  *
1218  * LOCKS
1219  *
1220  * No locks are obtained or released by this function
1221  *
1222  * RETURN CODES
1223  *
1224  * Returns != 0 upon successful completion.
1225  *
1226  */
1227
1228 int ADMINAPI
1229 bos_ProcessParameterGetDone(const void *iterationId, afs_status_p st)
1230 {
1231     int rc = 0;
1232     afs_status_t tst = 0;
1233     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1234
1235     if (iterationId == NULL) {
1236         tst = ADMITERATIONIDPNULL;
1237         goto fail_bos_ProcessParameterGetDone;
1238     }
1239
1240     rc = IteratorDone(iter, &tst);
1241
1242   fail_bos_ProcessParameterGetDone:
1243
1244     if (st != NULL) {
1245         *st = tst;
1246     }
1247     return rc;
1248 }
1249
1250 /*
1251  * bos_ProcessNotifierGet - retrieve the notifier associated with a
1252  * process.
1253  *
1254  * PARAMETERS
1255  *
1256  * IN serverHandle - a previously opened serverHandle.
1257  *
1258  * IN processName - the process whose notifier we are retrieving.
1259  *
1260  * OUT notifier - upon successful completion contains the notifier.
1261  *
1262  * LOCKS
1263  *
1264  * No locks are obtained or released by this function
1265  *
1266  * RETURN CODES
1267  *
1268  * Returns != 0 upon successful completion.
1269  *
1270  */
1271
1272 int ADMINAPI
1273 bos_ProcessNotifierGet(const void *serverHandle, const char *processName,
1274                        char *notifier, afs_status_p st)
1275 {
1276     int rc = 0;
1277     afs_status_t tst = 0;
1278     bos_server_p b_handle = (bos_server_p) serverHandle;
1279
1280     if (!isValidServerHandle(b_handle, &tst)) {
1281         goto fail_bos_ProcessNotifierGet;
1282     }
1283
1284     if ((processName == NULL) || (*processName == 0)) {
1285         tst = ADMBOSPROCESSNAMENULL;
1286         goto fail_bos_ProcessNotifierGet;
1287     }
1288
1289     if (notifier == NULL) {
1290         tst = ADMBOSNOTIFIERNULL;
1291         goto fail_bos_ProcessNotifierGet;
1292     }
1293
1294     tst = BOZO_GetInstanceParm(b_handle->server, processName, 999, &notifier);
1295
1296     if (tst == 0) {
1297         rc = 1;
1298     }
1299
1300   fail_bos_ProcessNotifierGet:
1301
1302     if (st != NULL) {
1303         *st = tst;
1304     }
1305     return rc;
1306 }
1307
1308 /*
1309  * bos_ProcessRestart - restart a particular process.
1310  *
1311  * PARAMETERS
1312  *
1313  * IN serverHandle - a previously opened serverHandle.
1314  *
1315  * IN processName - the process to restart
1316  *
1317  * LOCKS
1318  *
1319  * No locks are obtained or released by this function
1320  *
1321  * RETURN CODES
1322  *
1323  * Returns != 0 upon successful completion.
1324  *
1325  */
1326
1327 int ADMINAPI
1328 bos_ProcessRestart(const void *serverHandle, const char *processName,
1329                    afs_status_p st)
1330 {
1331     int rc = 0;
1332     afs_status_t tst = 0;
1333     bos_server_p b_handle = (bos_server_p) serverHandle;
1334
1335     if (!isValidServerHandle(b_handle, &tst)) {
1336         goto fail_bos_ProcessRestart;
1337     }
1338
1339     if ((processName == NULL) || (*processName == 0)) {
1340         tst = ADMBOSPROCESSNAMENULL;
1341         goto fail_bos_ProcessRestart;
1342     }
1343
1344     tst = BOZO_Restart(b_handle->server, processName);
1345
1346     if (tst == 0) {
1347         rc = 1;
1348     }
1349
1350   fail_bos_ProcessRestart:
1351
1352     if (st != NULL) {
1353         *st = tst;
1354     }
1355     return rc;
1356 }
1357
1358 /*
1359  * bos_ProcessAllStop - stop all running processes at a server.
1360  *
1361  * PARAMETERS
1362  *
1363  * IN serverHandle - a previously opened serverHandle.
1364  *
1365  * LOCKS
1366  *
1367  * No locks are obtained or released by this function
1368  *
1369  * RETURN CODES
1370  *
1371  * Returns != 0 upon successful completion.
1372  *
1373  */
1374
1375 int ADMINAPI
1376 bos_ProcessAllStop(const void *serverHandle, afs_status_p st)
1377 {
1378     int rc = 0;
1379     afs_status_t tst = 0;
1380     bos_server_p b_handle = (bos_server_p) serverHandle;
1381
1382     if (!isValidServerHandle(b_handle, &tst)) {
1383         goto fail_bos_ProcessAllStop;
1384     }
1385
1386     tst = BOZO_ShutdownAll(b_handle->server);
1387
1388     if (tst == 0) {
1389         rc = 1;
1390     }
1391
1392   fail_bos_ProcessAllStop:
1393
1394     if (st != NULL) {
1395         *st = tst;
1396     }
1397     return rc;
1398 }
1399
1400 /*
1401  * bos_ProcessAllStart - start all processes that should be running at a
1402  * server.
1403  *
1404  * PARAMETERS
1405  *
1406  * IN serverHandle - a previously opened serverHandle.
1407  *
1408  * LOCKS
1409  *
1410  * No locks are obtained or released by this function
1411  *
1412  * RETURN CODES
1413  *
1414  * Returns != 0 upon successful completion.
1415  *
1416  */
1417
1418 int ADMINAPI
1419 bos_ProcessAllStart(const void *serverHandle, afs_status_p st)
1420 {
1421     int rc = 0;
1422     afs_status_t tst = 0;
1423     bos_server_p b_handle = (bos_server_p) serverHandle;
1424
1425     if (!isValidServerHandle(b_handle, &tst)) {
1426         goto fail_bos_ProcessAllStart;
1427     }
1428
1429     tst = BOZO_StartupAll(b_handle->server);
1430
1431     if (tst == 0) {
1432         rc = 1;
1433     }
1434
1435   fail_bos_ProcessAllStart:
1436
1437     if (st != NULL) {
1438         *st = tst;
1439     }
1440     return rc;
1441 }
1442
1443 /*
1444  * bos_ProcessAllWaitStop - stop all processes, and block until they have
1445  * exited.
1446  *
1447  * PARAMETERS
1448  *
1449  * IN serverHandle - a previously opened serverHandle.
1450  *
1451  * LOCKS
1452  *
1453  * No locks are obtained or released by this function
1454  *
1455  * RETURN CODES
1456  *
1457  * Returns != 0 upon successful completion.
1458  *
1459  */
1460
1461 int ADMINAPI
1462 bos_ProcessAllWaitStop(const void *serverHandle, afs_status_p st)
1463 {
1464     int rc = 0;
1465     afs_status_t tst = 0;
1466     bos_server_p b_handle = (bos_server_p) serverHandle;
1467
1468     if (!isValidServerHandle(b_handle, &tst)) {
1469         goto fail_bos_ProcessAllWaitStop;
1470     }
1471
1472     if (!bos_ProcessAllStop(serverHandle, &tst)) {
1473         goto fail_bos_ProcessAllWaitStop;
1474     }
1475
1476     tst = BOZO_WaitAll(b_handle->server);
1477
1478     if (tst == 0) {
1479         rc = 1;
1480     }
1481
1482   fail_bos_ProcessAllWaitStop:
1483
1484     if (st != NULL) {
1485         *st = tst;
1486     }
1487     return rc;
1488 }
1489
1490 /*
1491  * bos_ProcessAllWaitTransition - block until all processes at the bosserver
1492  * have reached their desired state.
1493  *
1494  * PARAMETERS
1495  *
1496  * IN serverHandle - a previously opened serverHandle.
1497  *
1498  * LOCKS
1499  *
1500  * No locks are obtained or released by this function
1501  *
1502  * RETURN CODES
1503  *
1504  * Returns != 0 upon successful completion.
1505  *
1506  */
1507
1508 int ADMINAPI
1509 bos_ProcessAllWaitTransition(const void *serverHandle, afs_status_p st)
1510 {
1511     int rc = 0;
1512     afs_status_t tst = 0;
1513     bos_server_p b_handle = (bos_server_p) serverHandle;
1514
1515     if (!isValidServerHandle(b_handle, &tst)) {
1516         goto fail_bos_ProcessAllWaitTransition;
1517     }
1518
1519     tst = BOZO_WaitAll(b_handle->server);
1520
1521     if (tst == 0) {
1522         rc = 1;
1523     }
1524
1525   fail_bos_ProcessAllWaitTransition:
1526
1527     if (st != NULL) {
1528         *st = tst;
1529     }
1530     return rc;
1531 }
1532
1533 /*
1534  * bos_ProcessAllStopAndRestart - stop all the running processes, restart
1535  * them, and optionally restart the bosserver itself.
1536  * exited.
1537  *
1538  * PARAMETERS
1539  *
1540  * IN serverHandle - a previously opened serverHandle.
1541  *
1542  * IN restartBosServer - flag to indicate whether to restart bosserver.
1543  *
1544  * LOCKS
1545  *
1546  * No locks are obtained or released by this function
1547  *
1548  * RETURN CODES
1549  *
1550  * Returns != 0 upon successful completion.
1551  *
1552  */
1553
1554 int ADMINAPI
1555 bos_ProcessAllStopAndRestart(const void *serverHandle,
1556                              bos_RestartBosServer_t restartBosServer,
1557                              afs_status_p st)
1558 {
1559     int rc = 0;
1560     afs_status_t tst = 0;
1561     bos_server_p b_handle = (bos_server_p) serverHandle;
1562
1563     if (!isValidServerHandle(b_handle, &tst)) {
1564         goto fail_bos_ProcessAllStopAndRestart;
1565     }
1566
1567     if (restartBosServer == BOS_RESTART_BOS_SERVER) {
1568         tst = BOZO_ReBozo(b_handle->server);
1569         if (tst != 0) {
1570             goto fail_bos_ProcessAllStopAndRestart;
1571         }
1572     }
1573
1574     tst = BOZO_RestartAll(b_handle->server);
1575
1576     if (tst == 0) {
1577         rc = 1;
1578     }
1579
1580   fail_bos_ProcessAllStopAndRestart:
1581
1582     if (st != NULL) {
1583         *st = tst;
1584     }
1585     return rc;
1586 }
1587
1588 /*
1589  * bos_AdminCreate - create a new admin.
1590  *
1591  * PARAMETERS
1592  *
1593  * IN serverHandle - a previously opened serverHandle.
1594  *
1595  * IN adminName - the new admin name.
1596  *
1597  * LOCKS
1598  *
1599  * No locks are obtained or released by this function
1600  *
1601  * RETURN CODES
1602  *
1603  * Returns != 0 upon successful completion.
1604  *
1605  */
1606
1607 int ADMINAPI
1608 bos_AdminCreate(const void *serverHandle, const char *adminName,
1609                 afs_status_p st)
1610 {
1611     int rc = 0;
1612     afs_status_t tst = 0;
1613     bos_server_p b_handle = (bos_server_p) serverHandle;
1614
1615     if (!isValidServerHandle(b_handle, &tst)) {
1616         goto fail_bos_AdminCreate;
1617     }
1618
1619     if ((adminName == NULL) || (*adminName == 0)) {
1620         tst = ADMBOSADMINNAMENULL;
1621         goto fail_bos_AdminCreate;
1622     }
1623
1624     tst = BOZO_AddSUser(b_handle->server, adminName);
1625
1626     if (tst == 0) {
1627         rc = 1;
1628     }
1629
1630   fail_bos_AdminCreate:
1631
1632     if (st != NULL) {
1633         *st = tst;
1634     }
1635     return rc;
1636 }
1637
1638 /*
1639  * bos_AdminDelete - delete a new admin.
1640  *
1641  * PARAMETERS
1642  *
1643  * IN serverHandle - a previously opened serverHandle.
1644  *
1645  * IN adminName - the admin name.
1646  *
1647  * LOCKS
1648  *
1649  * No locks are obtained or released by this function
1650  *
1651  * RETURN CODES
1652  *
1653  * Returns != 0 upon successful completion.
1654  *
1655  */
1656
1657 int ADMINAPI
1658 bos_AdminDelete(const void *serverHandle, const char *adminName,
1659                 afs_status_p st)
1660 {
1661     int rc = 0;
1662     afs_status_t tst = 0;
1663     bos_server_p b_handle = (bos_server_p) serverHandle;
1664
1665     if (!isValidServerHandle(b_handle, &tst)) {
1666         goto fail_bos_AdminDelete;
1667     }
1668
1669     if ((adminName == NULL) || (*adminName == 0)) {
1670         tst = ADMBOSADMINNAMENULL;
1671         goto fail_bos_AdminDelete;
1672     }
1673
1674     tst = BOZO_DeleteSUser(b_handle->server, adminName);
1675
1676     if (tst == 0) {
1677         rc = 1;
1678     }
1679
1680   fail_bos_AdminDelete:
1681
1682     if (st != NULL) {
1683         *st = tst;
1684     }
1685     return rc;
1686 }
1687
1688 /*
1689  * The iterator functions and data for the admin retrieval functions
1690  */
1691
1692 typedef struct admin_get {
1693     int next;
1694     struct rx_connection *server;
1695     char admin[CACHED_ITEMS][BOS_MAX_NAME_LEN];
1696 } admin_get_t, *admin_get_p;
1697
1698 static int
1699 GetAdminRPC(void *rpc_specific, int slot, int *last_item,
1700             int *last_item_contains_data, afs_status_p st)
1701 {
1702     int rc = 0;
1703     afs_status_t tst = 0;
1704     admin_get_p admin = (admin_get_p) rpc_specific;
1705     char *ptr = (char *)&admin->admin[slot];
1706
1707     tst = BOZO_ListSUsers(admin->server, admin->next++, &ptr);
1708
1709     /*
1710      * There's no way to tell the difference between an rpc failure
1711      * and the end of the list, so we assume that any error means the
1712      * end of the list
1713      */
1714
1715     if (tst != 0) {
1716         tst = 0;
1717         *last_item = 1;
1718         *last_item_contains_data = 0;
1719     }
1720     rc = 1;
1721
1722     if (st != NULL) {
1723         *st = tst;
1724     }
1725     return rc;
1726 }
1727
1728 static int
1729 GetAdminFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
1730 {
1731     int rc = 0;
1732     afs_status_t tst = 0;
1733     admin_get_p admin = (admin_get_p) rpc_specific;
1734
1735     strcpy((char *)dest, (char *)&admin->admin[slot]);
1736     rc = 1;
1737
1738     if (st != NULL) {
1739         *st = tst;
1740     }
1741     return rc;
1742 }
1743
1744 /*
1745  * bos_AdminGetBegin - begin iterating over the administrators.
1746  *
1747  * PARAMETERS
1748  *
1749  * IN serverHandle - a previously opened serverHandle.
1750  *
1751  * OUT iter - an iterator that can be passed to bos_AdminGetBegin
1752  * to retrieve the administrators.
1753  *
1754  * LOCKS
1755  *
1756  * No locks are obtained or released by this function
1757  *
1758  * RETURN CODES
1759  *
1760  * Returns != 0 upon successful completion.
1761  *
1762  */
1763
1764 int ADMINAPI
1765 bos_AdminGetBegin(const void *serverHandle, void **iterationIdP,
1766                   afs_status_p st)
1767 {
1768     int rc = 0;
1769     afs_status_t tst = 0;
1770     bos_server_p b_handle = (bos_server_p) serverHandle;
1771     afs_admin_iterator_p iter =
1772         (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1773     admin_get_p admin = (admin_get_p) malloc(sizeof(admin_get_t));
1774
1775     if (!isValidServerHandle(b_handle, &tst)) {
1776         goto fail_bos_AdminGetBegin;
1777     }
1778
1779     if (iterationIdP == NULL) {
1780         tst = ADMITERATIONIDPNULL;
1781         goto fail_bos_AdminGetBegin;
1782     }
1783
1784     if ((iter == NULL) || (admin == NULL)) {
1785         tst = ADMNOMEM;
1786         goto fail_bos_AdminGetBegin;
1787     }
1788
1789     admin->next = 0;
1790     admin->server = b_handle->server;
1791
1792     if (IteratorInit
1793         (iter, (void *)admin, GetAdminRPC, GetAdminFromCache, NULL, NULL,
1794          &tst)) {
1795         *iterationIdP = (void *)iter;
1796         rc = 1;
1797     }
1798
1799   fail_bos_AdminGetBegin:
1800
1801     if (rc == 0) {
1802         if (iter != NULL) {
1803             free(iter);
1804         }
1805         if (admin != NULL) {
1806             free(admin);
1807         }
1808     }
1809
1810     if (st != NULL) {
1811         *st = tst;
1812     }
1813     return rc;
1814 }
1815
1816 /*
1817  * bos_AdminGetNext - retrieve the next administrator 
1818  * from the bos server.
1819  *
1820  * PARAMETERS
1821  *
1822  * IN iterationId - an iterator previously returned by 
1823  * bos_AdminGetBegin
1824  *
1825  * OUT adminName - upon successful completion contains the next administrator
1826  * retrieved from the server.
1827  *
1828  * LOCKS
1829  *
1830  * No locks are obtained or released by this function
1831  *
1832  * RETURN CODES
1833  *
1834  * Returns != 0 upon successful completion.
1835  *
1836  */
1837
1838 int ADMINAPI
1839 bos_AdminGetNext(const void *iterationId, char *adminName, afs_status_p st)
1840 {
1841     int rc = 0;
1842     afs_status_t tst = 0;
1843     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1844
1845     if (iterationId == NULL) {
1846         tst = ADMITERATIONIDPNULL;
1847         goto fail_bos_AdminGetNext;
1848     }
1849
1850     if (adminName == NULL) {
1851         tst = ADMBOSADMINNAMENULL;
1852         goto fail_bos_AdminGetNext;
1853     }
1854
1855     rc = IteratorNext(iter, (void *)adminName, &tst);
1856
1857   fail_bos_AdminGetNext:
1858
1859     if (st != NULL) {
1860         *st = tst;
1861     }
1862     return rc;
1863 }
1864
1865 /*
1866  * bos_AdminGetDone - finish using a administrator iterator.
1867  *
1868  * PARAMETERS
1869  *
1870  * IN iterationId - an iterator previously returned by
1871  * bos_AdminGetBegin
1872  *
1873  * LOCKS
1874  *
1875  * No locks are obtained or released by this function
1876  *
1877  * RETURN CODES
1878  *
1879  * Returns != 0 upon successful completion.
1880  *
1881  */
1882
1883 int ADMINAPI
1884 bos_AdminGetDone(const void *iterationId, afs_status_p st)
1885 {
1886     int rc = 0;
1887     afs_status_t tst = 0;
1888     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1889
1890     if (iterationId == NULL) {
1891         tst = ADMITERATIONIDPNULL;
1892         goto fail_bos_AdminGetDone;
1893     }
1894
1895     rc = IteratorDone(iter, &tst);
1896
1897   fail_bos_AdminGetDone:
1898
1899     if (st != NULL) {
1900         *st = tst;
1901     }
1902     return rc;
1903 }
1904
1905 /*
1906  * bos_KeyCreate - add a new key to the keyfile.
1907  *
1908  * PARAMETERS
1909  *
1910  * IN serverHandle - a previously opened serverHandle.
1911  *
1912  * IN keyVersionNumber - the key version number.
1913  *
1914  * IN key -  the new key.
1915  *
1916  * LOCKS
1917  *
1918  * No locks are obtained or released by this function
1919  *
1920  * RETURN CODES
1921  *
1922  * Returns != 0 upon successful completion.
1923  *
1924  */
1925
1926 int ADMINAPI
1927 bos_KeyCreate(const void *serverHandle, int keyVersionNumber,
1928               const kas_encryptionKey_p key, afs_status_p st)
1929 {
1930     int rc = 0;
1931     afs_status_t tst = 0;
1932     bos_server_p b_handle = (bos_server_p) serverHandle;
1933
1934     if (!isValidServerHandle(b_handle, &tst)) {
1935         goto fail_bos_KeyCreate;
1936     }
1937
1938     if (key == NULL) {
1939         tst = ADMBOSKEYNULL;
1940         goto fail_bos_KeyCreate;
1941     }
1942
1943     tst = BOZO_AddKey(b_handle->server_encrypt, keyVersionNumber, key);
1944
1945     if (tst == 0) {
1946         rc = 1;
1947     }
1948
1949   fail_bos_KeyCreate:
1950
1951     if (st != NULL) {
1952         *st = tst;
1953     }
1954     return rc;
1955 }
1956
1957 /*
1958  * bos_KeyDelete - delete an existing key from the keyfile.
1959  *
1960  * PARAMETERS
1961  *
1962  * IN serverHandle - a previously opened serverHandle.
1963  *
1964  * IN keyVersionNumber - the key version number.
1965  *
1966  * LOCKS
1967  *
1968  * No locks are obtained or released by this function
1969  *
1970  * RETURN CODES
1971  *
1972  * Returns != 0 upon successful completion.
1973  *
1974  */
1975
1976 int ADMINAPI
1977 bos_KeyDelete(const void *serverHandle, int keyVersionNumber, afs_status_p st)
1978 {
1979     int rc = 0;
1980     afs_status_t tst = 0;
1981     bos_server_p b_handle = (bos_server_p) serverHandle;
1982
1983     if (!isValidServerHandle(b_handle, &tst)) {
1984         goto fail_bos_KeyDelete;
1985     }
1986
1987     tst = BOZO_DeleteKey(b_handle->server, keyVersionNumber);
1988
1989     if (tst == 0) {
1990         rc = 1;
1991     }
1992
1993   fail_bos_KeyDelete:
1994
1995     if (st != NULL) {
1996         *st = tst;
1997     }
1998     return rc;
1999 }
2000
2001 /*
2002  * The iterator functions and data for the key retrieval functions
2003  */
2004
2005 typedef struct key_get {
2006     int next;
2007     struct rx_connection *server;
2008     bos_KeyInfo_t key[CACHED_ITEMS];
2009 } key_get_t, *key_get_p;
2010
2011 static int
2012 GetKeyRPC(void *rpc_specific, int slot, int *last_item,
2013           int *last_item_contains_data, afs_status_p st)
2014 {
2015     int rc = 0;
2016     afs_status_t tst = 0;
2017     key_get_p key = (key_get_p) rpc_specific;
2018     struct bozo_keyInfo keyInfo;
2019
2020     tst =
2021         BOZO_ListKeys(key->server, key->next++,
2022                       &key->key[slot].keyVersionNumber, &key->key[slot].key,
2023                       &keyInfo);
2024
2025
2026     if (tst == 0) {
2027         key->key[slot].keyStatus.lastModificationDate = keyInfo.mod_sec;
2028         key->key[slot].keyStatus.lastModificationMicroSeconds =
2029             keyInfo.mod_usec;
2030         key->key[slot].keyStatus.checkSum = keyInfo.keyCheckSum;
2031         rc = 1;
2032     } else if (tst == BZDOM) {
2033         tst = 0;
2034         rc = 1;
2035         *last_item = 1;
2036         *last_item_contains_data = 0;
2037     }
2038
2039     if (st != NULL) {
2040         *st = tst;
2041     }
2042     return rc;
2043 }
2044
2045 static int
2046 GetKeyFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
2047 {
2048     int rc = 0;
2049     afs_status_t tst = 0;
2050     key_get_p key = (key_get_p) rpc_specific;
2051
2052     memcpy(dest, &key->key[slot], sizeof(bos_KeyInfo_t));
2053     rc = 1;
2054
2055     if (st != NULL) {
2056         *st = tst;
2057     }
2058     return rc;
2059 }
2060
2061 /*
2062  * bos_KeyGetBegin - begin iterating over the keys.
2063  *
2064  * PARAMETERS
2065  *
2066  * IN serverHandle - a previously opened serverHandle.
2067  *
2068  * OUT iter - an iterator that can be passed to bos_KeyGetNext
2069  * to retrieve the keys.
2070  *
2071  * LOCKS
2072  *
2073  * No locks are obtained or released by this function
2074  *
2075  * RETURN CODES
2076  *
2077  * Returns != 0 upon successful completion.
2078  *
2079  */
2080
2081 int ADMINAPI
2082 bos_KeyGetBegin(const void *serverHandle, void **iterationIdP,
2083                 afs_status_p st)
2084 {
2085     int rc = 0;
2086     afs_status_t tst = 0;
2087     bos_server_p b_handle = (bos_server_p) serverHandle;
2088     afs_admin_iterator_p iter =
2089         (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2090     key_get_p key = (key_get_p) malloc(sizeof(key_get_t));
2091
2092     if (!isValidServerHandle(b_handle, &tst)) {
2093         goto fail_bos_KeyGetBegin;
2094     }
2095
2096     if (iterationIdP == NULL) {
2097         tst = ADMITERATIONIDPNULL;
2098         goto fail_bos_KeyGetBegin;
2099     }
2100
2101     if ((iter == NULL) || (key == NULL)) {
2102         tst = ADMNOMEM;
2103         goto fail_bos_KeyGetBegin;
2104     }
2105
2106     key->next = 0;
2107     key->server = b_handle->server_encrypt;
2108
2109     if (IteratorInit
2110         (iter, (void *)key, GetKeyRPC, GetKeyFromCache, NULL, NULL, &tst)) {
2111         *iterationIdP = (void *)iter;
2112         rc = 1;
2113     }
2114
2115   fail_bos_KeyGetBegin:
2116
2117     if (rc == 0) {
2118         if (iter != NULL) {
2119             free(iter);
2120         }
2121         if (key != NULL) {
2122             free(key);
2123         }
2124     }
2125
2126     if (st != NULL) {
2127         *st = tst;
2128     }
2129     return rc;
2130 }
2131
2132 /*
2133  * bos_KeyGetNext - retrieve the next key 
2134  * from the bos server.
2135  *
2136  * PARAMETERS
2137  *
2138  * IN iterationId - an iterator previously returned by 
2139  * bos_KeyGetBegin
2140  *
2141  * OUT keyP - upon successful completion contains the next key
2142  * retrieved from the server.
2143  *
2144  * LOCKS
2145  *
2146  * No locks are obtained or released by this function
2147  *
2148  * RETURN CODES
2149  *
2150  * Returns != 0 upon successful completion.
2151  *
2152  */
2153
2154 int ADMINAPI
2155 bos_KeyGetNext(const void *iterationId, bos_KeyInfo_p keyP, afs_status_p st)
2156 {
2157     int rc = 0;
2158     afs_status_t tst = 0;
2159     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2160
2161     if (iterationId == NULL) {
2162         tst = ADMITERATIONIDPNULL;
2163         goto fail_bos_KeyGetNext;
2164     }
2165
2166     if (keyP == NULL) {
2167         tst = ADMBOSKEYPNULL;
2168         goto fail_bos_KeyGetNext;
2169     }
2170
2171     rc = IteratorNext(iter, (void *)keyP, &tst);
2172
2173   fail_bos_KeyGetNext:
2174
2175     if (st != NULL) {
2176         *st = tst;
2177     }
2178     return rc;
2179 }
2180
2181 /*
2182  * bos_KeyGetDone - finish using a key iterator.
2183  *
2184  * PARAMETERS
2185  *
2186  * IN iterationId - an iterator previously returned by
2187  * bos_KeyGetBegin
2188  *
2189  * LOCKS
2190  *
2191  * No locks are obtained or released by this function
2192  *
2193  * RETURN CODES
2194  *
2195  * Returns != 0 upon successful completion.
2196  *
2197  */
2198
2199 int ADMINAPI
2200 bos_KeyGetDone(const void *iterationId, afs_status_p st)
2201 {
2202     int rc = 0;
2203     afs_status_t tst = 0;
2204     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2205
2206     if (iterationId == NULL) {
2207         tst = ADMITERATIONIDPNULL;
2208         goto fail_bos_KeyGetDone;
2209     }
2210
2211     rc = IteratorDone(iter, &tst);
2212
2213   fail_bos_KeyGetDone:
2214
2215     if (st != NULL) {
2216         *st = tst;
2217     }
2218     return rc;
2219 }
2220
2221 /*
2222  * bos_CellSet - set the cell name at a bos server.
2223  *
2224  * PARAMETERS
2225  *
2226  * IN serverHandle - a previously opened serverHandle.
2227  *
2228  * IN cellName - the new cell name.
2229  *
2230  * LOCKS
2231  *
2232  * No locks are obtained or released by this function
2233  *
2234  * RETURN CODES
2235  *
2236  * Returns != 0 upon successful completion.
2237  */
2238
2239 int ADMINAPI
2240 bos_CellSet(const void *serverHandle, const char *cellName, afs_status_p st)
2241 {
2242     int rc = 0;
2243     afs_status_t tst = 0;
2244     bos_server_p b_handle = (bos_server_p) serverHandle;
2245
2246     if (!isValidServerHandle(b_handle, &tst)) {
2247         goto fail_bos_CellSet;
2248     }
2249
2250     if ((cellName == NULL) || (*cellName == 0)) {
2251         tst = ADMCLIENTCELLNAMENULL;
2252         goto fail_bos_CellSet;
2253     }
2254
2255     tst = BOZO_SetCellName(b_handle->server, cellName);
2256
2257     if (tst == 0) {
2258         rc = 1;
2259     }
2260
2261   fail_bos_CellSet:
2262
2263     if (st != NULL) {
2264         *st = tst;
2265     }
2266     return rc;
2267 }
2268
2269 /*
2270  * bos_CellGet - get the cell name at a bos server.
2271  *
2272  * PARAMETERS
2273  *
2274  * IN serverHandle - a previously opened serverHandle.
2275  *
2276  * OUT cellName - the cell name.
2277  *
2278  * LOCKS
2279  *
2280  * No locks are obtained or released by this function
2281  *
2282  * RETURN CODES
2283  *
2284  * Returns != 0 upon successful completion.
2285  */
2286
2287 int ADMINAPI
2288 bos_CellGet(const void *serverHandle, char *cellName, afs_status_p st)
2289 {
2290     int rc = 0;
2291     afs_status_t tst = 0;
2292     bos_server_p b_handle = (bos_server_p) serverHandle;
2293
2294     if (!isValidServerHandle(b_handle, &tst)) {
2295         goto fail_bos_CellGet;
2296     }
2297
2298     if (cellName == NULL) {
2299         tst = ADMCLIENTCELLNAMENULL;
2300         goto fail_bos_CellGet;
2301     }
2302
2303     tst = BOZO_GetCellName(b_handle->server, &cellName);
2304
2305     if (tst == 0) {
2306         rc = 1;
2307     }
2308
2309   fail_bos_CellGet:
2310
2311     if (st != NULL) {
2312         *st = tst;
2313     }
2314     return rc;
2315 }
2316
2317 /*
2318  * bos_HostCreate - add a new host to the cell.
2319  *
2320  * PARAMETERS
2321  *
2322  * IN serverHandle - a previously opened serverHandle.
2323  *
2324  * IN hostName - the new host.
2325  *
2326  * LOCKS
2327  *
2328  * No locks are obtained or released by this function
2329  *
2330  * RETURN CODES
2331  *
2332  * Returns != 0 upon successful completion.
2333  */
2334
2335 int ADMINAPI
2336 bos_HostCreate(const void *serverHandle, const char *hostName,
2337                afs_status_p st)
2338 {
2339     int rc = 0;
2340     afs_status_t tst = 0;
2341     bos_server_p b_handle = (bos_server_p) serverHandle;
2342
2343     if (!isValidServerHandle(b_handle, &tst)) {
2344         goto fail_bos_HostCreate;
2345     }
2346
2347     if ((hostName == NULL) || (*hostName == 0)) {
2348         tst = ADMBOSHOSTNAMENULL;
2349         goto fail_bos_HostCreate;
2350     }
2351
2352     tst = BOZO_AddCellHost(b_handle->server, hostName);
2353
2354     if (tst == 0) {
2355         rc = 1;
2356     }
2357
2358   fail_bos_HostCreate:
2359
2360     if (st != NULL) {
2361         *st = tst;
2362     }
2363     return rc;
2364 }
2365
2366 /*
2367  * bos_HostDelete - delete a host from the cell.
2368  *
2369  * PARAMETERS
2370  *
2371  * IN serverHandle - a previously opened serverHandle.
2372  *
2373  * IN hostName - the host.
2374  *
2375  * LOCKS
2376  *
2377  * No locks are obtained or released by this function
2378  *
2379  * RETURN CODES
2380  *
2381  * Returns != 0 upon successful completion.
2382  */
2383
2384 int ADMINAPI
2385 bos_HostDelete(const void *serverHandle, const char *hostName,
2386                afs_status_p st)
2387 {
2388     int rc = 0;
2389     afs_status_t tst = 0;
2390     bos_server_p b_handle = (bos_server_p) serverHandle;
2391
2392     if (!isValidServerHandle(b_handle, &tst)) {
2393         goto fail_bos_HostDelete;
2394     }
2395
2396     if ((hostName == NULL) || (*hostName == 0)) {
2397         tst = ADMBOSHOSTNAMENULL;
2398         goto fail_bos_HostDelete;
2399     }
2400
2401     tst = BOZO_DeleteCellHost(b_handle->server, hostName);
2402
2403     if (tst == 0) {
2404         rc = 1;
2405     }
2406
2407   fail_bos_HostDelete:
2408
2409     if (st != NULL) {
2410         *st = tst;
2411     }
2412     return rc;
2413 }
2414
2415 /*
2416  * The iterator functions and data for the host retrieval functions
2417  */
2418
2419 typedef struct host_get {
2420     int next;
2421     struct rx_connection *server;
2422     char host[CACHED_ITEMS][BOS_MAX_NAME_LEN];
2423 } host_get_t, *host_get_p;
2424
2425 static int
2426 GetHostRPC(void *rpc_specific, int slot, int *last_item,
2427            int *last_item_contains_data, afs_status_p st)
2428 {
2429     int rc = 0;
2430     afs_status_t tst = 0;
2431     host_get_p host = (host_get_p) rpc_specific;
2432     char *ptr = (char *)&host->host[slot];
2433
2434     tst = BOZO_GetCellHost(host->server, host->next++, &ptr);
2435
2436     if (tst == 0) {
2437         rc = 1;
2438     } else if (tst == BZDOM) {
2439         tst = 0;
2440         rc = 1;
2441         *last_item = 1;
2442         *last_item_contains_data = 0;
2443     }
2444
2445     if (st != NULL) {
2446         *st = tst;
2447     }
2448     return rc;
2449 }
2450
2451 static int
2452 GetHostFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
2453 {
2454     int rc = 0;
2455     afs_status_t tst = 0;
2456     host_get_p host = (host_get_p) rpc_specific;
2457
2458     strcpy((char *)dest, (char *)&host->host[slot]);
2459     rc = 1;
2460
2461     if (st != NULL) {
2462         *st = tst;
2463     }
2464     return rc;
2465 }
2466
2467 /*
2468  * bos_HostGetBegin - begin iterating over the hosts in a cell
2469  * at a particular bos server.
2470  *
2471  * PARAMETERS
2472  *
2473  * IN serverHandle - a previously opened serverHandle.
2474  *
2475  * OUT iter - an iterator that can be passed to bos_HostGetNext
2476  * to retrieve the process names.
2477  *
2478  * LOCKS
2479  *
2480  * No locks are obtained or released by this function
2481  *
2482  * RETURN CODES
2483  *
2484  * Returns != 0 upon successful completion.
2485  *
2486  */
2487
2488 int ADMINAPI
2489 bos_HostGetBegin(const void *serverHandle, void **iterationIdP,
2490                  afs_status_p st)
2491 {
2492     int rc = 0;
2493     afs_status_t tst = 0;
2494     bos_server_p b_handle = (bos_server_p) serverHandle;
2495     afs_admin_iterator_p iter =
2496         (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2497     host_get_p host = (host_get_p) malloc(sizeof(host_get_t));
2498
2499     if (!isValidServerHandle(b_handle, &tst)) {
2500         goto fail_bos_HostGetBegin;
2501     }
2502
2503     if (iterationIdP == NULL) {
2504         tst = ADMITERATIONIDPNULL;
2505         goto fail_bos_HostGetBegin;
2506     }
2507
2508     if ((iter == NULL) || (host == NULL)) {
2509         tst = ADMNOMEM;
2510         goto fail_bos_HostGetBegin;
2511     }
2512
2513     host->next = 0;
2514     host->server = b_handle->server;
2515
2516     if (IteratorInit
2517         (iter, (void *)host, GetHostRPC, GetHostFromCache, NULL, NULL,
2518          &tst)) {
2519         *iterationIdP = (void *)iter;
2520         rc = 1;
2521     }
2522
2523   fail_bos_HostGetBegin:
2524
2525     if (rc == 0) {
2526         if (iter != NULL) {
2527             free(iter);
2528         }
2529         if (host != NULL) {
2530             free(host);
2531         }
2532     }
2533
2534     if (st != NULL) {
2535         *st = tst;
2536     }
2537     return rc;
2538 }
2539
2540 /*
2541  * bos_HostGetNext - retrieve the next host 
2542  * from the bos server.
2543  *
2544  * PARAMETERS
2545  *
2546  * IN iterationId - an iterator previously returned by 
2547  * bos_HostGetBegin
2548  *
2549  * OUT hostName - upon successful completion contains the next host
2550  * retrieved from the server.
2551  *
2552  * LOCKS
2553  *
2554  * No locks are obtained or released by this function
2555  *
2556  * RETURN CODES
2557  *
2558  * Returns != 0 upon successful completion.
2559  *
2560  */
2561
2562 int ADMINAPI
2563 bos_HostGetNext(const void *iterationId, char *hostName, afs_status_p st)
2564 {
2565     int rc = 0;
2566     afs_status_t tst = 0;
2567     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2568
2569     if (iterationId == NULL) {
2570         tst = ADMITERATIONIDPNULL;
2571         goto fail_bos_HostGetNext;
2572     }
2573
2574     if (hostName == NULL) {
2575         tst = ADMBOSHOSTNAMENULL;
2576         goto fail_bos_HostGetNext;
2577     }
2578
2579     rc = IteratorNext(iter, (void *)hostName, &tst);
2580
2581   fail_bos_HostGetNext:
2582
2583     if (st != NULL) {
2584         *st = tst;
2585     }
2586     return rc;
2587 }
2588
2589 /*
2590  * bos_HostGetDone - finish using a host iterator.
2591  *
2592  * PARAMETERS
2593  *
2594  * IN iterationId - an iterator previously returned by
2595  * bos_HostGetBegin
2596  *
2597  * LOCKS
2598  *
2599  * No locks are obtained or released by this function
2600  *
2601  * RETURN CODES
2602  *
2603  * Returns != 0 upon successful completion.
2604  *
2605  */
2606
2607 int ADMINAPI
2608 bos_HostGetDone(const void *iterationId, afs_status_p st)
2609 {
2610     int rc = 0;
2611     afs_status_t tst = 0;
2612     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2613
2614     if (iterationId == NULL) {
2615         tst = ADMITERATIONIDPNULL;
2616         goto fail_bos_HostGetDone;
2617     }
2618
2619     rc = IteratorDone(iter, &tst);
2620
2621   fail_bos_HostGetDone:
2622
2623     if (st != NULL) {
2624         *st = tst;
2625     }
2626     return rc;
2627 }
2628
2629 /*
2630  * bos_ExecutableCreate - create a new executable at the bos server.
2631  *
2632  * PARAMETERS
2633  *
2634  * IN serverHandle - a previously opened serverHandle.
2635  *
2636  * IN sourceFile - the executable to install at the bos server.
2637  *
2638  * IN destFile - the location where the executable will be installed.
2639  *
2640  * LOCKS
2641  *
2642  * No locks are obtained or released by this function
2643  *
2644  * RETURN CODES
2645  *
2646  * Returns != 0 upon successful completion.
2647  *
2648  */
2649
2650 int ADMINAPI
2651 bos_ExecutableCreate(const void *serverHandle, const char *sourceFile,
2652                      const char *destFile, afs_status_p st)
2653 {
2654     int rc = 0;
2655     afs_status_t tst = 0;
2656     bos_server_p b_handle = (bos_server_p) serverHandle;
2657     int fd;
2658     struct stat estat;
2659     struct rx_call *tcall;
2660
2661     /*
2662      * Validate arguments
2663      */
2664
2665     if (!isValidServerHandle(b_handle, &tst)) {
2666         goto fail_bos_ExecutableCreate;
2667     }
2668
2669     if ((sourceFile == NULL) || (*sourceFile == 0)) {
2670         tst = ADMBOSSOURCEFILENULL;
2671         goto fail_bos_ExecutableCreate;
2672     }
2673
2674     if ((destFile == NULL) || (*destFile == 0)) {
2675         tst = ADMBOSDESTFILENULL;
2676         goto fail_bos_ExecutableCreate;
2677     }
2678
2679     /*
2680      * Open the file locally and compute its size
2681      */
2682
2683     fd = open(sourceFile, O_RDONLY);
2684
2685     if (fd < 0) {
2686         tst = ADMBOSCANTOPENSOURCEFILE;
2687         goto fail_bos_ExecutableCreate;
2688     }
2689
2690     if (fstat(fd, &estat)) {
2691         tst = ADMBOSCANTSTATSOURCEFILE;
2692         goto fail_bos_ExecutableCreate;
2693     }
2694
2695     /*
2696      * Start a split rpc to the bos server.
2697      */
2698
2699     tcall = rx_NewCall(b_handle->server);
2700
2701     tst =
2702         StartBOZO_Install(tcall, destFile, estat.st_size,
2703                           (afs_int32) estat.st_mode, estat.st_mtime);
2704
2705     if (tst) {
2706         rx_EndCall(tcall, tst);
2707         goto fail_bos_ExecutableCreate;
2708     }
2709
2710     /*
2711      * Copy the data to the server
2712      */
2713
2714     while (1) {
2715         char tbuffer[512];
2716         size_t len;
2717         len = read(fd, tbuffer, sizeof(tbuffer));
2718         if (len < 0) {
2719             tst = ADMBOSCANTREADSOURCEFILE;
2720             rx_EndCall(tcall, len);
2721             goto fail_bos_ExecutableCreate;
2722         }
2723         if (len == 0) {
2724             tst = 0;
2725             break;
2726         }
2727         tst = rx_Write(tcall, tbuffer, len);
2728         if (tst != len) {
2729             tst = ADMBOSSENDSOURCEFILE;
2730             rx_EndCall(tcall, tst);
2731             goto fail_bos_ExecutableCreate;
2732         }
2733     }
2734
2735     /*
2736      * Terminate the rpc to the server
2737      */
2738
2739     tst = rx_EndCall(tcall, tst);
2740
2741     if (tst == 0) {
2742         rc = 1;
2743     }
2744
2745   fail_bos_ExecutableCreate:
2746
2747     if (st != NULL) {
2748         *st = tst;
2749     }
2750     return rc;
2751 }
2752
2753 /*
2754  * bos_ExecutableRevert - revert an executable to a previous .BAK version.
2755  *
2756  * PARAMETERS
2757  *
2758  * IN serverHandle - a previously opened serverHandle.
2759  *
2760  * IN execFile - the executable to revert at the bos server.
2761  *
2762  * LOCKS
2763  *
2764  * No locks are obtained or released by this function
2765  *
2766  * RETURN CODES
2767  *
2768  * Returns != 0 upon successful completion.
2769  *
2770  */
2771
2772 int ADMINAPI
2773 bos_ExecutableRevert(const void *serverHandle, const char *execFile,
2774                      afs_status_p st)
2775 {
2776     int rc = 0;
2777     afs_status_t tst = 0;
2778     bos_server_p b_handle = (bos_server_p) serverHandle;
2779
2780     if (!isValidServerHandle(b_handle, &tst)) {
2781         goto fail_bos_ExecutableRevert;
2782     }
2783
2784     if ((execFile == NULL) || (*execFile == 0)) {
2785         tst = ADMBOSEXECFILENULL;
2786         goto fail_bos_ExecutableRevert;
2787     }
2788
2789     tst = BOZO_UnInstall(b_handle->server, execFile);
2790
2791     if (tst == 0) {
2792         rc = 1;
2793     }
2794
2795   fail_bos_ExecutableRevert:
2796
2797     if (st != NULL) {
2798         *st = tst;
2799     }
2800     return rc;
2801 }
2802
2803 /*
2804  * bos_ExecutableTimestampGet - get the last mod times for an executable,
2805  * the .BAK version of the executable, and the .OLD version of the
2806  * executable if they exist.
2807  *
2808  * PARAMETERS
2809  *
2810  * IN serverHandle - a previously opened serverHandle.
2811  *
2812  * IN execFile - the executable to revert at the bos server.
2813  *
2814  * LOCKS
2815  *
2816  * No locks are obtained or released by this function
2817  *
2818  * RETURN CODES
2819  *
2820  * Returns != 0 upon successful completion.
2821  *
2822  */
2823
2824 int ADMINAPI
2825 bos_ExecutableTimestampGet(const void *serverHandle, const char *execFile,
2826                            unsigned long *newTime, unsigned long *oldTime,
2827                            unsigned long *bakTime, afs_status_p st)
2828 {
2829     int rc = 0;
2830     afs_status_t tst = 0;
2831     bos_server_p b_handle = (bos_server_p) serverHandle;
2832
2833     if (!isValidServerHandle(b_handle, &tst)) {
2834         goto fail_bos_ExecutableTimestampGet;
2835     }
2836
2837     if ((execFile == NULL) || (*execFile == 0)) {
2838         tst = ADMBOSEXECFILENULL;
2839         goto fail_bos_ExecutableTimestampGet;
2840     }
2841
2842     if (newTime == NULL) {
2843         tst = ADMBOSNEWTIMENULL;
2844         goto fail_bos_ExecutableTimestampGet;
2845     }
2846
2847     if (oldTime == NULL) {
2848         tst = ADMBOSOLDTIMENULL;
2849         goto fail_bos_ExecutableTimestampGet;
2850     }
2851
2852     if (bakTime == NULL) {
2853         tst = ADMBOSBAKTIMENULL;
2854         goto fail_bos_ExecutableTimestampGet;
2855     }
2856
2857     tst =
2858         BOZO_GetDates(b_handle->server, execFile, newTime, bakTime, oldTime);
2859
2860     if (tst == 0) {
2861         rc = 1;
2862     }
2863
2864   fail_bos_ExecutableTimestampGet:
2865
2866     if (st != NULL) {
2867         *st = tst;
2868     }
2869     return rc;
2870 }
2871
2872 /*
2873  * bos_ExecutablePrune - prune the bak, old, and core files off a server
2874  * machine.
2875  *
2876  * PARAMETERS
2877  *
2878  * IN serverHandle - a previously opened serverHandle.
2879  *
2880  * IN oldFiles - prune .OLD files.
2881  *
2882  * IN bakFiles - prune .BAK files.
2883  *
2884  * IN coreFiles - prune core files.
2885  *
2886  * LOCKS
2887  *
2888  * No locks are obtained or released by this function
2889  *
2890  * RETURN CODES
2891  *
2892  * Returns != 0 upon successful completion.
2893  *
2894  */
2895
2896 int ADMINAPI
2897 bos_ExecutablePrune(const void *serverHandle, bos_Prune_t oldFiles,
2898                     bos_Prune_t bakFiles, bos_Prune_t coreFiles,
2899                     afs_status_p st)
2900 {
2901     int rc = 0;
2902     afs_status_t tst = 0;
2903     bos_server_p b_handle = (bos_server_p) serverHandle;
2904     afs_int32 flags = 0;
2905
2906     if (!isValidServerHandle(b_handle, &tst)) {
2907         goto fail_bos_ExecutablePrune;
2908     }
2909
2910     if (oldFiles == BOS_PRUNE) {
2911         flags |= BOZO_PRUNEOLD;
2912     }
2913
2914     if (bakFiles == BOS_PRUNE) {
2915         flags |= BOZO_PRUNEBAK;
2916     }
2917
2918     if (coreFiles == BOS_PRUNE) {
2919         flags |= BOZO_PRUNECORE;
2920     }
2921
2922     tst = BOZO_Prune(b_handle->server, flags);
2923
2924     if (tst == 0) {
2925         rc = 1;
2926     }
2927
2928   fail_bos_ExecutablePrune:
2929
2930     if (st != NULL) {
2931         *st = tst;
2932     }
2933     return rc;
2934 }
2935
2936 /*
2937  * bos_ExecutableRestartTimeSet - set the restart time of the bos server
2938  * machine.
2939  *
2940  * PARAMETERS
2941  *
2942  * IN serverHandle - a previously opened serverHandle.
2943  *
2944  * IN type - specifies either weekly restart or daily restart time.
2945  *
2946  * IN time - the time to begin restarts.
2947  *
2948  * LOCKS
2949  *
2950  * No locks are obtained or released by this function
2951  *
2952  * RETURN CODES
2953  *
2954  * Returns != 0 upon successful completion.
2955  *
2956  */
2957
2958 int ADMINAPI
2959 bos_ExecutableRestartTimeSet(const void *serverHandle, bos_Restart_t type,
2960                              bos_RestartTime_t time, afs_status_p st)
2961 {
2962     int rc = 0;
2963     afs_status_t tst = 0;
2964     bos_server_p b_handle = (bos_server_p) serverHandle;
2965     afs_int32 restartType = 0;
2966     struct ktime restartTime;
2967
2968     if (!isValidServerHandle(b_handle, &tst)) {
2969         goto fail_bos_ExecutableRestartTimeSet;
2970     }
2971
2972     if (type == BOS_RESTART_WEEKLY) {
2973         restartType = 1;
2974     } else {
2975         restartType = 2;
2976     }
2977
2978     if ((time.mask & BOS_RESTART_TIME_HOUR)
2979         && ((time.hour < 0) || (time.hour > 23))) {
2980         tst = ADMBOSHOURINVALID;
2981         goto fail_bos_ExecutableRestartTimeSet;
2982     }
2983
2984     if ((time.mask & BOS_RESTART_TIME_MINUTE)
2985         && ((time.min < 0) || (time.min > 60))) {
2986         tst = ADMBOSMINUTEINVALID;
2987         goto fail_bos_ExecutableRestartTimeSet;
2988     }
2989
2990     if ((time.mask & BOS_RESTART_TIME_SECOND)
2991         && ((time.sec < 0) || (time.sec > 60))) {
2992         tst = ADMBOSSECONDINVALID;
2993         goto fail_bos_ExecutableRestartTimeSet;
2994     }
2995
2996     if ((time.mask & BOS_RESTART_TIME_DAY)
2997         && ((time.day < 0) || (time.day > 6))) {
2998         tst = ADMBOSDAYINVALID;
2999         goto fail_bos_ExecutableRestartTimeSet;
3000     }
3001
3002     restartTime.mask = time.mask;
3003     restartTime.hour = time.hour;
3004     restartTime.min = time.min;
3005     restartTime.sec = time.sec;
3006     restartTime.day = time.day;
3007
3008     tst = BOZO_SetRestartTime(b_handle->server, restartType, &restartTime);
3009
3010     if (tst == 0) {
3011         rc = 1;
3012     }
3013
3014   fail_bos_ExecutableRestartTimeSet:
3015
3016     if (st != NULL) {
3017         *st = tst;
3018     }
3019     return rc;
3020 }
3021
3022 /*
3023  * bos_ExecutableRestartTimeGet - get the restart time of the bos server
3024  * machine.
3025  *
3026  * PARAMETERS
3027  *
3028  * IN serverHandle - a previously opened serverHandle.
3029  *
3030  * IN type - specifies either weekly restart or daily restart time.
3031  *
3032  * OUT timeP - the time to begin restarts.
3033  *
3034  * LOCKS
3035  *
3036  * No locks are obtained or released by this function
3037  *
3038  * RETURN CODES
3039  *
3040  * Returns != 0 upon successful completion.
3041  *
3042  */
3043
3044 int ADMINAPI
3045 bos_ExecutableRestartTimeGet(const void *serverHandle, bos_Restart_t type,
3046                              bos_RestartTime_p timeP, afs_status_p st)
3047 {
3048     int rc = 0;
3049     afs_status_t tst = 0;
3050     bos_server_p b_handle = (bos_server_p) serverHandle;
3051     afs_int32 restartType = 0;
3052     struct ktime restartTime;
3053
3054     if (!isValidServerHandle(b_handle, &tst)) {
3055         goto fail_bos_ExecutableRestartTimeGet;
3056     }
3057
3058     if (timeP == NULL) {
3059         tst = ADMBOSTIMEPNULL;
3060         goto fail_bos_ExecutableRestartTimeGet;
3061     }
3062
3063     if (type == BOS_RESTART_WEEKLY) {
3064         restartType = 1;
3065     } else {
3066         restartType = 2;
3067     }
3068
3069     tst = BOZO_GetRestartTime(b_handle->server, restartType, &restartTime);
3070
3071     if (tst != 0) {
3072         goto fail_bos_ExecutableRestartTimeGet;
3073     }
3074
3075     timeP->mask = restartTime.mask;
3076     timeP->hour = restartTime.hour;
3077     timeP->min = restartTime.min;
3078     timeP->sec = restartTime.sec;
3079     timeP->day = restartTime.day;
3080     rc = 1;
3081
3082   fail_bos_ExecutableRestartTimeGet:
3083
3084     if (st != NULL) {
3085         *st = tst;
3086     }
3087     return rc;
3088 }
3089
3090 /*
3091  * bos_LogGet - get a log file from the bos server machine.
3092  *
3093  * PARAMETERS
3094  *
3095  * IN serverHandle - a previously opened serverHandle.
3096  *
3097  * IN log - the log file to retrieve.
3098  *
3099  * IN/OUT logBufferSizeP - the length of the logData buffer on input,
3100  * and upon successful completion, the length of data stored in the buffer.
3101  *
3102  * OUT logData - the retrieved data upon successful completion.
3103  *
3104  * LOCKS
3105  *
3106  * No locks are obtained or released by this function
3107  *
3108  * RETURN CODES
3109  *
3110  * Returns != 0 upon successful completion.
3111  *
3112  */
3113
3114 int ADMINAPI
3115 bos_LogGet(const void *serverHandle, const char *log,
3116            unsigned long *logBufferSizeP, char *logData, afs_status_p st)
3117 {
3118     int rc = 0;
3119     afs_status_t tst = 0;
3120     bos_server_p b_handle = (bos_server_p) serverHandle;
3121     struct rx_call *tcall = NULL;
3122     afs_int32 error;
3123     char buffer;
3124     int have_call = 0;
3125     unsigned long bytes_read = 0;
3126
3127     /*
3128      * Validate parameters
3129      */
3130
3131     if (!isValidServerHandle(b_handle, &tst)) {
3132         goto fail_bos_LogGet;
3133     }
3134
3135     if ((log == NULL) || (*log == 0)) {
3136         tst = ADMBOSLOGNULL;
3137         goto fail_bos_LogGet;
3138     }
3139
3140     if (logBufferSizeP == NULL) {
3141         tst = ADMBOSLOGBUFFERSIZEPNULL;
3142         goto fail_bos_LogGet;
3143     }
3144
3145     if (logData == NULL) {
3146         tst = ADMBOSLOGDATANULL;
3147         goto fail_bos_LogGet;
3148     }
3149
3150     /*
3151      * Begin to retrieve the data
3152      */
3153
3154     tcall = rx_NewCall(b_handle->server);
3155     have_call = 1;
3156     tst = StartBOZO_GetLog(tcall, log);
3157
3158     if (tst != 0) {
3159         goto fail_bos_LogGet;
3160     }
3161
3162     /*
3163      * Read the log file data
3164      */
3165
3166     while (1) {
3167         error = rx_Read(tcall, &buffer, 1);
3168         if (error != 1) {
3169             tst = ADMBOSLOGFILEERROR;
3170             goto fail_bos_LogGet;
3171         }
3172
3173         /*
3174          * check for the end of the log
3175          */
3176
3177         if (buffer == 0) {
3178             *logBufferSizeP = bytes_read;
3179             break;
3180         }
3181
3182         /*
3183          * We've successfully read another byte, copy it to logData
3184          * if there's room
3185          */
3186
3187         bytes_read++;
3188         if (bytes_read <= *logBufferSizeP) {
3189             *logData++ = buffer;
3190         } else {
3191             tst = ADMMOREDATA;
3192         }
3193     }
3194     if (tst == 0) {
3195         rc = 1;
3196     }
3197
3198   fail_bos_LogGet:
3199
3200     if (have_call) {
3201         rx_EndCall(tcall, 0);
3202     }
3203
3204     if (st != NULL) {
3205         *st = tst;
3206     }
3207     return rc;
3208 }
3209
3210 /*
3211  * bos_AuthSet - set the authorization level required at the bos server.
3212  *
3213  * PARAMETERS
3214  *
3215  * IN serverHandle - a previously opened serverHandle.
3216  *
3217  * IN auth - specifies the new auth level.
3218  *
3219  * LOCKS
3220  *
3221  * No locks are obtained or released by this function
3222  *
3223  * RETURN CODES
3224  *
3225  * Returns != 0 upon successful completion.
3226  *
3227  */
3228
3229 int ADMINAPI
3230 bos_AuthSet(const void *serverHandle, bos_Auth_t auth, afs_status_p st)
3231 {
3232     int rc = 0;
3233     afs_status_t tst = 0;
3234     bos_server_p b_handle = (bos_server_p) serverHandle;
3235     afs_int32 level = 0;
3236
3237     if (!isValidServerHandle(b_handle, &tst)) {
3238         goto fail_bos_AuthSet;
3239     }
3240
3241     if (auth == BOS_AUTH_REQUIRED) {
3242         level = 0;
3243     } else {
3244         level = 1;
3245     }
3246
3247     tst = BOZO_SetNoAuthFlag(b_handle->server, level);
3248
3249     if (tst == 0) {
3250         rc = 1;
3251     }
3252
3253   fail_bos_AuthSet:
3254
3255     if (st != NULL) {
3256         *st = tst;
3257     }
3258     return rc;
3259 }
3260
3261 /*
3262  * bos_CommandExecute - execute a command at the bos server.
3263  *
3264  * PARAMETERS
3265  *
3266  * IN serverHandle - a previously opened serverHandle.
3267  *
3268  * IN command - the command to execute.
3269  *
3270  * LOCKS
3271  *
3272  * No locks are obtained or released by this function
3273  *
3274  * RETURN CODES
3275  *
3276  * Returns != 0 upon successful completion.
3277  *
3278  */
3279
3280 int ADMINAPI
3281 bos_CommandExecute(const void *serverHandle, const char *command,
3282                    afs_status_p st)
3283 {
3284     int rc = 0;
3285     afs_status_t tst = 0;
3286     bos_server_p b_handle = (bos_server_p) serverHandle;
3287
3288     if (!isValidServerHandle(b_handle, &tst)) {
3289         goto fail_bos_CommandExecute;
3290     }
3291
3292     if ((command == NULL) || (*command == 0)) {
3293         tst = ADMBOSCOMMANDNULL;
3294         goto fail_bos_CommandExecute;
3295     }
3296
3297     tst = BOZO_Exec(b_handle->server, command);
3298
3299     if (tst == 0) {
3300         rc = 1;
3301     }
3302
3303   fail_bos_CommandExecute:
3304
3305     if (st != NULL) {
3306         *st = tst;
3307     }
3308     return rc;
3309 }
3310
3311 /*
3312  * bos_Salvage - perform a remote salvage operation.
3313  *
3314  * PARAMETERS
3315  *
3316  * IN cellHandle - a previously opened cellHandle.
3317  *
3318  * IN serverHandle - a previously opened serverHandle.
3319  *
3320  * IN partitionName - the partition to salvage.  Can be null.
3321  *
3322  * IN volumeName - the volume to salvage.  Can be null, if non-null,
3323  * partitionName cannot be null.
3324  *
3325  * IN numSalvagers - the number of salvage processes to run in parallel.
3326  *
3327  * IN tmpDir - directory to place temporary files.  Can be null.
3328  *
3329  * IN logFile - file where salvage log will be written.  Can be null.
3330  *
3331  * IN force - sets salvager -force flag.
3332  *
3333  * IN salvageDamagedVolumes - sets salvager -oktozap flag.
3334  *
3335  * IN writeInodes - sets salvager -inodes flag.
3336  *
3337  * IN writeRootInodes - sets salvager -rootinodes flag.
3338  *
3339  * IN forceDirectory - sets salvager -salvagedirs flag.
3340  *
3341  * IN forceBlockRead - sets salvager -blockread flag.
3342  *
3343  * LOCKS
3344  *
3345  * No locks are obtained or released by this function
3346  *
3347  * RETURN CODES
3348  *
3349  * Returns != 0 upon successful completion.
3350  *
3351  */
3352
3353 #define INITIAL_LOG_LEN 4096
3354
3355 int ADMINAPI
3356 bos_Salvage(const void *cellHandle, const void *serverHandle,
3357             const char *partitionName, const char *volumeName,
3358             int numSalvagers, const char *tmpDir, const char *logFile,
3359             vos_force_t force,
3360             bos_SalvageDamagedVolumes_t salvageDamagedVolumes,
3361             bos_WriteInodes_t writeInodes,
3362             bos_WriteRootInodes_t writeRootInodes,
3363             bos_ForceDirectory_t forceDirectory,
3364             bos_ForceBlockRead_t forceBlockRead, afs_status_p st)
3365 {
3366     int rc = 0;
3367     afs_status_t tst = 0;
3368     bos_server_p b_handle = (bos_server_p) serverHandle;
3369     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
3370     int have_partition = 0;
3371     int have_volume = 0;
3372     unsigned int part = 0;
3373     int try_to_stop_fileserver = 0;
3374     bos_ProcessType_t procType;
3375     bos_ProcessInfo_t procInfo;
3376     FILE *log = NULL;
3377     char command[BOS_MAX_NAME_LEN];
3378     int command_len = 0;
3379     int poll_rc;
3380     char *logData = NULL;
3381     unsigned long logLen = INITIAL_LOG_LEN;
3382
3383     /*
3384      * Validate arguments
3385      */
3386
3387     if (!IsValidCellHandle(c_handle, &tst)) {
3388         goto fail_bos_Salvage;
3389     }
3390
3391     if (!isValidServerHandle(b_handle, &tst)) {
3392         goto fail_bos_Salvage;
3393     }
3394
3395     if (c_handle->vos_valid == 0) {
3396         tst = ADMBOSCELLHANDLENOVOS;
3397         goto fail_bos_Salvage;
3398     }
3399
3400     if ((partitionName != NULL) && (*partitionName != 0)) {
3401         if (!vos_PartitionNameToId(partitionName, &part, &tst)) {
3402             goto fail_bos_Salvage;
3403         }
3404         have_partition = 1;
3405     }
3406
3407     if ((volumeName != NULL) && (*volumeName != 0)) {
3408         if (!have_partition) {
3409             tst = ADMBOSSALVAGEVOLUME;
3410             goto fail_bos_Salvage;
3411         }
3412         have_volume = 1;
3413     }
3414
3415     if ((logFile != NULL) && (*logFile != 0)) {
3416         log = fopen(logFile, "w");
3417         if (!log) {
3418             tst = ADMBOSSALVAGEBADLOG;
3419             goto fail_bos_Salvage;
3420         }
3421     }
3422
3423     /*
3424      * If we are salvaging more than a single volume, stop the fileserver
3425      */
3426
3427     if (!have_volume) {
3428         try_to_stop_fileserver = 1;
3429     }
3430
3431     /*
3432      * Only try to stop the fileserver if it is running
3433      */
3434
3435     if (try_to_stop_fileserver) {
3436         if (bos_ProcessInfoGet
3437             (serverHandle, "fs", &procType, &procInfo, &tst)) {
3438             if (procInfo.processGoal != BOS_PROCESS_RUNNING) {
3439                 try_to_stop_fileserver = 0;
3440             }
3441         }
3442     }
3443
3444     /*
3445      * Make the call to stop the fileserver and wait for it to shutdown
3446      */
3447
3448     if (try_to_stop_fileserver) {
3449         if (!bos_ProcessExecutionStateSetTemporary
3450             (serverHandle, "fs", BOS_PROCESS_STOPPED, &tst)) {
3451             goto fail_bos_Salvage;
3452         }
3453         bos_ProcessAllWaitTransition(serverHandle, &tst);
3454     }
3455
3456     /*
3457      * Create the salvage command line arguments
3458      */
3459
3460     command_len =
3461         sprintf(command, "%s ", AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH);
3462     if (have_partition) {
3463         command_len +=
3464             sprintf(&command[command_len], "-partition %s ", partitionName);
3465     }
3466
3467     if (have_volume) {
3468         command_len +=
3469             sprintf(&command[command_len], "-volumeid %s ", volumeName);
3470     }
3471
3472     if (salvageDamagedVolumes == BOS_DONT_SALVAGE_DAMAGED_VOLUMES) {
3473         command_len += sprintf(&command[command_len], "-nowrite ");
3474     }
3475
3476     if (writeInodes == BOS_SALVAGE_WRITE_INODES) {
3477         command_len += sprintf(&command[command_len], "-inodes ");
3478     }
3479
3480     if (force == VOS_FORCE) {
3481         command_len += sprintf(&command[command_len], "-force ");
3482     }
3483
3484     if (writeRootInodes == BOS_SALVAGE_WRITE_ROOT_INODES) {
3485         command_len += sprintf(&command[command_len], "-rootinodes ");
3486     }
3487
3488     if (forceDirectory == BOS_SALVAGE_FORCE_DIRECTORIES) {
3489         command_len += sprintf(&command[command_len], "-salvagedirs ");
3490     }
3491
3492     if (forceBlockRead == BOS_SALVAGE_FORCE_BLOCK_READS) {
3493         command_len += sprintf(&command[command_len], "-blockreads ");
3494     }
3495
3496     command_len +=
3497         sprintf(&command[command_len], "-parallel %d ", numSalvagers);
3498
3499     if ((tmpDir != NULL) && (*tmpDir != 0)) {
3500         command_len += sprintf(&command[command_len], "-tmpdir %s ", tmpDir);
3501     }
3502
3503     if (command_len > BOS_MAX_NAME_LEN) {
3504         tst = ADMBOSSALVAGEBADOPTIONS;
3505         goto fail_bos_Salvage;
3506     }
3507
3508     /*
3509      * Create the process at the bosserver and wait until it completes
3510      */
3511
3512     if (!bos_ProcessCreate
3513         (serverHandle, "salvage-tmp", BOS_PROCESS_CRON, command, "now", 0,
3514          &tst)) {
3515         goto fail_bos_Salvage;
3516     }
3517
3518     while ((poll_rc =
3519             bos_ProcessInfoGet(serverHandle, "salvage-tmp", &procType,
3520                                &procInfo, &tst))) {
3521         sleep(5);
3522     }
3523
3524     if (tst != BZNOENT) {
3525         goto fail_bos_Salvage;
3526     }
3527
3528     /*
3529      * Print out the salvage log if required by the user
3530      */
3531
3532     if (log != NULL) {
3533
3534         logData = (char *)malloc(INITIAL_LOG_LEN);
3535         if (!logData) {
3536             tst = ADMNOMEM;
3537             goto fail_bos_Salvage;
3538         }
3539
3540         while (!bos_LogGet
3541                (serverHandle, AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH,
3542                 &logLen, logData, &tst)) {
3543             if (logLen > INITIAL_LOG_LEN) {
3544                 logData = (char *)realloc(logData, (logLen + (logLen / 10)));
3545                 if (logData == NULL) {
3546                     tst = ADMNOMEM;
3547                     goto fail_bos_Salvage;
3548                 }
3549             } else {
3550                 goto fail_bos_Salvage;
3551             }
3552         }
3553         fprintf(log, "SalvageLog:\n%s", logData);
3554     }
3555
3556     /*
3557      * Restart the fileserver if we had stopped it previously
3558      */
3559
3560     if (try_to_stop_fileserver) {
3561         try_to_stop_fileserver = 0;
3562         if (!bos_ProcessExecutionStateSetTemporary
3563             (serverHandle, "fs", BOS_PROCESS_RUNNING, &tst)) {
3564             goto fail_bos_Salvage;
3565         }
3566     }
3567     rc = 1;
3568
3569   fail_bos_Salvage:
3570
3571     if (log != NULL) {
3572         fclose(log);
3573     }
3574
3575     if (logData != NULL) {
3576         free(logData);
3577     }
3578
3579     if (try_to_stop_fileserver) {
3580         bos_ProcessExecutionStateSetTemporary(serverHandle, "fs",
3581                                               BOS_PROCESS_RUNNING, 0);
3582     }
3583
3584     if (st != NULL) {
3585         *st = tst;
3586     }
3587     return rc;
3588 }