44be450cbe68a4cd0ff9453899ac8a44b7df7160
[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
14 #include <stdio.h>
15 #include <afs/stds.h>
16 #include <rx/rx.h>
17 #include <rx/rxstat.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, char *processName,
326                   bos_ProcessType_t processType, char *process,
327                   char *cronTime, 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, char *processName,
406                     char *fileserverPath, char *volserverPath,
407                     char *salvagerPath, 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, 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                              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 *, 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, (char *)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                              const 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                                       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, 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, (char *)processName,
1295                                999, &notifier);
1296
1297     if (tst == 0) {
1298         rc = 1;
1299     }
1300
1301   fail_bos_ProcessNotifierGet:
1302
1303     if (st != NULL) {
1304         *st = tst;
1305     }
1306     return rc;
1307 }
1308
1309 /*
1310  * bos_ProcessRestart - restart a particular process.
1311  *
1312  * PARAMETERS
1313  *
1314  * IN serverHandle - a previously opened serverHandle.
1315  *
1316  * IN processName - the process to restart
1317  *
1318  * LOCKS
1319  *
1320  * No locks are obtained or released by this function
1321  *
1322  * RETURN CODES
1323  *
1324  * Returns != 0 upon successful completion.
1325  *
1326  */
1327
1328 int ADMINAPI
1329 bos_ProcessRestart(const void *serverHandle, const char *processName,
1330                    afs_status_p st)
1331 {
1332     int rc = 0;
1333     afs_status_t tst = 0;
1334     bos_server_p b_handle = (bos_server_p) serverHandle;
1335
1336     if (!isValidServerHandle(b_handle, &tst)) {
1337         goto fail_bos_ProcessRestart;
1338     }
1339
1340     if ((processName == NULL) || (*processName == 0)) {
1341         tst = ADMBOSPROCESSNAMENULL;
1342         goto fail_bos_ProcessRestart;
1343     }
1344
1345     tst = BOZO_Restart(b_handle->server, (char *)processName);
1346
1347     if (tst == 0) {
1348         rc = 1;
1349     }
1350
1351   fail_bos_ProcessRestart:
1352
1353     if (st != NULL) {
1354         *st = tst;
1355     }
1356     return rc;
1357 }
1358
1359 /*
1360  * bos_ProcessAllStop - stop all running processes at a server.
1361  *
1362  * PARAMETERS
1363  *
1364  * IN serverHandle - a previously opened serverHandle.
1365  *
1366  * LOCKS
1367  *
1368  * No locks are obtained or released by this function
1369  *
1370  * RETURN CODES
1371  *
1372  * Returns != 0 upon successful completion.
1373  *
1374  */
1375
1376 int ADMINAPI
1377 bos_ProcessAllStop(const void *serverHandle, afs_status_p st)
1378 {
1379     int rc = 0;
1380     afs_status_t tst = 0;
1381     bos_server_p b_handle = (bos_server_p) serverHandle;
1382
1383     if (!isValidServerHandle(b_handle, &tst)) {
1384         goto fail_bos_ProcessAllStop;
1385     }
1386
1387     tst = BOZO_ShutdownAll(b_handle->server);
1388
1389     if (tst == 0) {
1390         rc = 1;
1391     }
1392
1393   fail_bos_ProcessAllStop:
1394
1395     if (st != NULL) {
1396         *st = tst;
1397     }
1398     return rc;
1399 }
1400
1401 /*
1402  * bos_ProcessAllStart - start all processes that should be running at a
1403  * server.
1404  *
1405  * PARAMETERS
1406  *
1407  * IN serverHandle - a previously opened serverHandle.
1408  *
1409  * LOCKS
1410  *
1411  * No locks are obtained or released by this function
1412  *
1413  * RETURN CODES
1414  *
1415  * Returns != 0 upon successful completion.
1416  *
1417  */
1418
1419 int ADMINAPI
1420 bos_ProcessAllStart(const void *serverHandle, afs_status_p st)
1421 {
1422     int rc = 0;
1423     afs_status_t tst = 0;
1424     bos_server_p b_handle = (bos_server_p) serverHandle;
1425
1426     if (!isValidServerHandle(b_handle, &tst)) {
1427         goto fail_bos_ProcessAllStart;
1428     }
1429
1430     tst = BOZO_StartupAll(b_handle->server);
1431
1432     if (tst == 0) {
1433         rc = 1;
1434     }
1435
1436   fail_bos_ProcessAllStart:
1437
1438     if (st != NULL) {
1439         *st = tst;
1440     }
1441     return rc;
1442 }
1443
1444 /*
1445  * bos_ProcessAllWaitStop - stop all processes, and block until they have
1446  * exited.
1447  *
1448  * PARAMETERS
1449  *
1450  * IN serverHandle - a previously opened serverHandle.
1451  *
1452  * LOCKS
1453  *
1454  * No locks are obtained or released by this function
1455  *
1456  * RETURN CODES
1457  *
1458  * Returns != 0 upon successful completion.
1459  *
1460  */
1461
1462 int ADMINAPI
1463 bos_ProcessAllWaitStop(const void *serverHandle, afs_status_p st)
1464 {
1465     int rc = 0;
1466     afs_status_t tst = 0;
1467     bos_server_p b_handle = (bos_server_p) serverHandle;
1468
1469     if (!isValidServerHandle(b_handle, &tst)) {
1470         goto fail_bos_ProcessAllWaitStop;
1471     }
1472
1473     if (!bos_ProcessAllStop(serverHandle, &tst)) {
1474         goto fail_bos_ProcessAllWaitStop;
1475     }
1476
1477     tst = BOZO_WaitAll(b_handle->server);
1478
1479     if (tst == 0) {
1480         rc = 1;
1481     }
1482
1483   fail_bos_ProcessAllWaitStop:
1484
1485     if (st != NULL) {
1486         *st = tst;
1487     }
1488     return rc;
1489 }
1490
1491 /*
1492  * bos_ProcessAllWaitTransition - block until all processes at the bosserver
1493  * have reached their desired state.
1494  *
1495  * PARAMETERS
1496  *
1497  * IN serverHandle - a previously opened serverHandle.
1498  *
1499  * LOCKS
1500  *
1501  * No locks are obtained or released by this function
1502  *
1503  * RETURN CODES
1504  *
1505  * Returns != 0 upon successful completion.
1506  *
1507  */
1508
1509 int ADMINAPI
1510 bos_ProcessAllWaitTransition(const void *serverHandle, afs_status_p st)
1511 {
1512     int rc = 0;
1513     afs_status_t tst = 0;
1514     bos_server_p b_handle = (bos_server_p) serverHandle;
1515
1516     if (!isValidServerHandle(b_handle, &tst)) {
1517         goto fail_bos_ProcessAllWaitTransition;
1518     }
1519
1520     tst = BOZO_WaitAll(b_handle->server);
1521
1522     if (tst == 0) {
1523         rc = 1;
1524     }
1525
1526   fail_bos_ProcessAllWaitTransition:
1527
1528     if (st != NULL) {
1529         *st = tst;
1530     }
1531     return rc;
1532 }
1533
1534 /*
1535  * bos_ProcessAllStopAndRestart - stop all the running processes, restart
1536  * them, and optionally restart the bosserver itself.
1537  * exited.
1538  *
1539  * PARAMETERS
1540  *
1541  * IN serverHandle - a previously opened serverHandle.
1542  *
1543  * IN restartBosServer - flag to indicate whether to restart bosserver.
1544  *
1545  * LOCKS
1546  *
1547  * No locks are obtained or released by this function
1548  *
1549  * RETURN CODES
1550  *
1551  * Returns != 0 upon successful completion.
1552  *
1553  */
1554
1555 int ADMINAPI
1556 bos_ProcessAllStopAndRestart(const void *serverHandle,
1557                              bos_RestartBosServer_t restartBosServer,
1558                              afs_status_p st)
1559 {
1560     int rc = 0;
1561     afs_status_t tst = 0;
1562     bos_server_p b_handle = (bos_server_p) serverHandle;
1563
1564     if (!isValidServerHandle(b_handle, &tst)) {
1565         goto fail_bos_ProcessAllStopAndRestart;
1566     }
1567
1568     if (restartBosServer == BOS_RESTART_BOS_SERVER) {
1569         tst = BOZO_ReBozo(b_handle->server);
1570         if (tst != 0) {
1571             goto fail_bos_ProcessAllStopAndRestart;
1572         }
1573     }
1574
1575     tst = BOZO_RestartAll(b_handle->server);
1576
1577     if (tst == 0) {
1578         rc = 1;
1579     }
1580
1581   fail_bos_ProcessAllStopAndRestart:
1582
1583     if (st != NULL) {
1584         *st = tst;
1585     }
1586     return rc;
1587 }
1588
1589 /*
1590  * bos_AdminCreate - create a new admin.
1591  *
1592  * PARAMETERS
1593  *
1594  * IN serverHandle - a previously opened serverHandle.
1595  *
1596  * IN adminName - the new admin name.
1597  *
1598  * LOCKS
1599  *
1600  * No locks are obtained or released by this function
1601  *
1602  * RETURN CODES
1603  *
1604  * Returns != 0 upon successful completion.
1605  *
1606  */
1607
1608 int ADMINAPI
1609 bos_AdminCreate(const void *serverHandle, const char *adminName,
1610                 afs_status_p st)
1611 {
1612     int rc = 0;
1613     afs_status_t tst = 0;
1614     bos_server_p b_handle = (bos_server_p) serverHandle;
1615
1616     if (!isValidServerHandle(b_handle, &tst)) {
1617         goto fail_bos_AdminCreate;
1618     }
1619
1620     if ((adminName == NULL) || (*adminName == 0)) {
1621         tst = ADMBOSADMINNAMENULL;
1622         goto fail_bos_AdminCreate;
1623     }
1624
1625     tst = BOZO_AddSUser(b_handle->server, (char *)adminName);
1626
1627     if (tst == 0) {
1628         rc = 1;
1629     }
1630
1631   fail_bos_AdminCreate:
1632
1633     if (st != NULL) {
1634         *st = tst;
1635     }
1636     return rc;
1637 }
1638
1639 /*
1640  * bos_AdminDelete - delete a new admin.
1641  *
1642  * PARAMETERS
1643  *
1644  * IN serverHandle - a previously opened serverHandle.
1645  *
1646  * IN adminName - the admin name.
1647  *
1648  * LOCKS
1649  *
1650  * No locks are obtained or released by this function
1651  *
1652  * RETURN CODES
1653  *
1654  * Returns != 0 upon successful completion.
1655  *
1656  */
1657
1658 int ADMINAPI
1659 bos_AdminDelete(const void *serverHandle, const char *adminName,
1660                 afs_status_p st)
1661 {
1662     int rc = 0;
1663     afs_status_t tst = 0;
1664     bos_server_p b_handle = (bos_server_p) serverHandle;
1665
1666     if (!isValidServerHandle(b_handle, &tst)) {
1667         goto fail_bos_AdminDelete;
1668     }
1669
1670     if ((adminName == NULL) || (*adminName == 0)) {
1671         tst = ADMBOSADMINNAMENULL;
1672         goto fail_bos_AdminDelete;
1673     }
1674
1675     tst = BOZO_DeleteSUser(b_handle->server, (char *)adminName);
1676
1677     if (tst == 0) {
1678         rc = 1;
1679     }
1680
1681   fail_bos_AdminDelete:
1682
1683     if (st != NULL) {
1684         *st = tst;
1685     }
1686     return rc;
1687 }
1688
1689 /*
1690  * The iterator functions and data for the admin retrieval functions
1691  */
1692
1693 typedef struct admin_get {
1694     int next;
1695     struct rx_connection *server;
1696     char admin[CACHED_ITEMS][BOS_MAX_NAME_LEN];
1697 } admin_get_t, *admin_get_p;
1698
1699 static int
1700 GetAdminRPC(void *rpc_specific, int slot, int *last_item,
1701             int *last_item_contains_data, afs_status_p st)
1702 {
1703     int rc = 0;
1704     afs_status_t tst = 0;
1705     admin_get_p admin = (admin_get_p) rpc_specific;
1706     char *ptr = (char *)&admin->admin[slot];
1707
1708     tst = BOZO_ListSUsers(admin->server, admin->next++, &ptr);
1709
1710     /*
1711      * There's no way to tell the difference between an rpc failure
1712      * and the end of the list, so we assume that any error means the
1713      * end of the list
1714      */
1715
1716     if (tst != 0) {
1717         tst = 0;
1718         *last_item = 1;
1719         *last_item_contains_data = 0;
1720     }
1721     rc = 1;
1722
1723     if (st != NULL) {
1724         *st = tst;
1725     }
1726     return rc;
1727 }
1728
1729 static int
1730 GetAdminFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
1731 {
1732     int rc = 0;
1733     afs_status_t tst = 0;
1734     admin_get_p admin = (admin_get_p) rpc_specific;
1735
1736     strcpy((char *)dest, (char *)&admin->admin[slot]);
1737     rc = 1;
1738
1739     if (st != NULL) {
1740         *st = tst;
1741     }
1742     return rc;
1743 }
1744
1745 /*
1746  * bos_AdminGetBegin - begin iterating over the administrators.
1747  *
1748  * PARAMETERS
1749  *
1750  * IN serverHandle - a previously opened serverHandle.
1751  *
1752  * OUT iter - an iterator that can be passed to bos_AdminGetBegin
1753  * to retrieve the administrators.
1754  *
1755  * LOCKS
1756  *
1757  * No locks are obtained or released by this function
1758  *
1759  * RETURN CODES
1760  *
1761  * Returns != 0 upon successful completion.
1762  *
1763  */
1764
1765 int ADMINAPI
1766 bos_AdminGetBegin(const void *serverHandle, void **iterationIdP,
1767                   afs_status_p st)
1768 {
1769     int rc = 0;
1770     afs_status_t tst = 0;
1771     bos_server_p b_handle = (bos_server_p) serverHandle;
1772     afs_admin_iterator_p iter =
1773         (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1774     admin_get_p admin = (admin_get_p) malloc(sizeof(admin_get_t));
1775
1776     if (!isValidServerHandle(b_handle, &tst)) {
1777         goto fail_bos_AdminGetBegin;
1778     }
1779
1780     if (iterationIdP == NULL) {
1781         tst = ADMITERATIONIDPNULL;
1782         goto fail_bos_AdminGetBegin;
1783     }
1784
1785     if ((iter == NULL) || (admin == NULL)) {
1786         tst = ADMNOMEM;
1787         goto fail_bos_AdminGetBegin;
1788     }
1789
1790     admin->next = 0;
1791     admin->server = b_handle->server;
1792
1793     if (IteratorInit
1794         (iter, (void *)admin, GetAdminRPC, GetAdminFromCache, NULL, NULL,
1795          &tst)) {
1796         *iterationIdP = (void *)iter;
1797         rc = 1;
1798     }
1799
1800   fail_bos_AdminGetBegin:
1801
1802     if (rc == 0) {
1803         if (iter != NULL) {
1804             free(iter);
1805         }
1806         if (admin != NULL) {
1807             free(admin);
1808         }
1809     }
1810
1811     if (st != NULL) {
1812         *st = tst;
1813     }
1814     return rc;
1815 }
1816
1817 /*
1818  * bos_AdminGetNext - retrieve the next administrator 
1819  * from the bos server.
1820  *
1821  * PARAMETERS
1822  *
1823  * IN iterationId - an iterator previously returned by 
1824  * bos_AdminGetBegin
1825  *
1826  * OUT adminName - upon successful completion contains the next administrator
1827  * retrieved from the server.
1828  *
1829  * LOCKS
1830  *
1831  * No locks are obtained or released by this function
1832  *
1833  * RETURN CODES
1834  *
1835  * Returns != 0 upon successful completion.
1836  *
1837  */
1838
1839 int ADMINAPI
1840 bos_AdminGetNext(const void *iterationId, char *adminName, afs_status_p st)
1841 {
1842     int rc = 0;
1843     afs_status_t tst = 0;
1844     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1845
1846     if (iterationId == NULL) {
1847         tst = ADMITERATIONIDPNULL;
1848         goto fail_bos_AdminGetNext;
1849     }
1850
1851     if (adminName == NULL) {
1852         tst = ADMBOSADMINNAMENULL;
1853         goto fail_bos_AdminGetNext;
1854     }
1855
1856     rc = IteratorNext(iter, (void *)adminName, &tst);
1857
1858   fail_bos_AdminGetNext:
1859
1860     if (st != NULL) {
1861         *st = tst;
1862     }
1863     return rc;
1864 }
1865
1866 /*
1867  * bos_AdminGetDone - finish using a administrator iterator.
1868  *
1869  * PARAMETERS
1870  *
1871  * IN iterationId - an iterator previously returned by
1872  * bos_AdminGetBegin
1873  *
1874  * LOCKS
1875  *
1876  * No locks are obtained or released by this function
1877  *
1878  * RETURN CODES
1879  *
1880  * Returns != 0 upon successful completion.
1881  *
1882  */
1883
1884 int ADMINAPI
1885 bos_AdminGetDone(const void *iterationId, afs_status_p st)
1886 {
1887     int rc = 0;
1888     afs_status_t tst = 0;
1889     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1890
1891     if (iterationId == NULL) {
1892         tst = ADMITERATIONIDPNULL;
1893         goto fail_bos_AdminGetDone;
1894     }
1895
1896     rc = IteratorDone(iter, &tst);
1897
1898   fail_bos_AdminGetDone:
1899
1900     if (st != NULL) {
1901         *st = tst;
1902     }
1903     return rc;
1904 }
1905
1906 /*
1907  * bos_KeyCreate - add a new key to the keyfile.
1908  *
1909  * PARAMETERS
1910  *
1911  * IN serverHandle - a previously opened serverHandle.
1912  *
1913  * IN keyVersionNumber - the key version number.
1914  *
1915  * IN key -  the new key.
1916  *
1917  * LOCKS
1918  *
1919  * No locks are obtained or released by this function
1920  *
1921  * RETURN CODES
1922  *
1923  * Returns != 0 upon successful completion.
1924  *
1925  */
1926
1927 int ADMINAPI
1928 bos_KeyCreate(const void *serverHandle, int keyVersionNumber,
1929               const kas_encryptionKey_p key, afs_status_p st)
1930 {
1931     int rc = 0;
1932     afs_status_t tst = 0;
1933     bos_server_p b_handle = (bos_server_p) serverHandle;
1934
1935     if (!isValidServerHandle(b_handle, &tst)) {
1936         goto fail_bos_KeyCreate;
1937     }
1938
1939     if (key == NULL) {
1940         tst = ADMBOSKEYNULL;
1941         goto fail_bos_KeyCreate;
1942     }
1943
1944     tst = BOZO_AddKey(b_handle->server_encrypt, keyVersionNumber, key);
1945
1946     if (tst == 0) {
1947         rc = 1;
1948     }
1949
1950   fail_bos_KeyCreate:
1951
1952     if (st != NULL) {
1953         *st = tst;
1954     }
1955     return rc;
1956 }
1957
1958 /*
1959  * bos_KeyDelete - delete an existing key from the keyfile.
1960  *
1961  * PARAMETERS
1962  *
1963  * IN serverHandle - a previously opened serverHandle.
1964  *
1965  * IN keyVersionNumber - the key version number.
1966  *
1967  * LOCKS
1968  *
1969  * No locks are obtained or released by this function
1970  *
1971  * RETURN CODES
1972  *
1973  * Returns != 0 upon successful completion.
1974  *
1975  */
1976
1977 int ADMINAPI
1978 bos_KeyDelete(const void *serverHandle, int keyVersionNumber, afs_status_p st)
1979 {
1980     int rc = 0;
1981     afs_status_t tst = 0;
1982     bos_server_p b_handle = (bos_server_p) serverHandle;
1983
1984     if (!isValidServerHandle(b_handle, &tst)) {
1985         goto fail_bos_KeyDelete;
1986     }
1987
1988     tst = BOZO_DeleteKey(b_handle->server, keyVersionNumber);
1989
1990     if (tst == 0) {
1991         rc = 1;
1992     }
1993
1994   fail_bos_KeyDelete:
1995
1996     if (st != NULL) {
1997         *st = tst;
1998     }
1999     return rc;
2000 }
2001
2002 /*
2003  * The iterator functions and data for the key retrieval functions
2004  */
2005
2006 typedef struct key_get {
2007     int next;
2008     struct rx_connection *server;
2009     bos_KeyInfo_t key[CACHED_ITEMS];
2010 } key_get_t, *key_get_p;
2011
2012 static int
2013 GetKeyRPC(void *rpc_specific, int slot, int *last_item,
2014           int *last_item_contains_data, afs_status_p st)
2015 {
2016     int rc = 0;
2017     afs_status_t tst = 0;
2018     key_get_p key = (key_get_p) rpc_specific;
2019     struct bozo_keyInfo keyInfo;
2020
2021     tst =
2022         BOZO_ListKeys(key->server, key->next++,
2023                       &key->key[slot].keyVersionNumber, &key->key[slot].key,
2024                       &keyInfo);
2025
2026
2027     if (tst == 0) {
2028         key->key[slot].keyStatus.lastModificationDate = keyInfo.mod_sec;
2029         key->key[slot].keyStatus.lastModificationMicroSeconds =
2030             keyInfo.mod_usec;
2031         key->key[slot].keyStatus.checkSum = keyInfo.keyCheckSum;
2032         rc = 1;
2033     } else if (tst == BZDOM) {
2034         tst = 0;
2035         rc = 1;
2036         *last_item = 1;
2037         *last_item_contains_data = 0;
2038     }
2039
2040     if (st != NULL) {
2041         *st = tst;
2042     }
2043     return rc;
2044 }
2045
2046 static int
2047 GetKeyFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
2048 {
2049     int rc = 0;
2050     afs_status_t tst = 0;
2051     key_get_p key = (key_get_p) rpc_specific;
2052
2053     memcpy(dest, &key->key[slot], sizeof(bos_KeyInfo_t));
2054     rc = 1;
2055
2056     if (st != NULL) {
2057         *st = tst;
2058     }
2059     return rc;
2060 }
2061
2062 /*
2063  * bos_KeyGetBegin - begin iterating over the keys.
2064  *
2065  * PARAMETERS
2066  *
2067  * IN serverHandle - a previously opened serverHandle.
2068  *
2069  * OUT iter - an iterator that can be passed to bos_KeyGetNext
2070  * to retrieve the keys.
2071  *
2072  * LOCKS
2073  *
2074  * No locks are obtained or released by this function
2075  *
2076  * RETURN CODES
2077  *
2078  * Returns != 0 upon successful completion.
2079  *
2080  */
2081
2082 int ADMINAPI
2083 bos_KeyGetBegin(const void *serverHandle, void **iterationIdP,
2084                 afs_status_p st)
2085 {
2086     int rc = 0;
2087     afs_status_t tst = 0;
2088     bos_server_p b_handle = (bos_server_p) serverHandle;
2089     afs_admin_iterator_p iter =
2090         (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2091     key_get_p key = (key_get_p) malloc(sizeof(key_get_t));
2092
2093     if (!isValidServerHandle(b_handle, &tst)) {
2094         goto fail_bos_KeyGetBegin;
2095     }
2096
2097     if (iterationIdP == NULL) {
2098         tst = ADMITERATIONIDPNULL;
2099         goto fail_bos_KeyGetBegin;
2100     }
2101
2102     if ((iter == NULL) || (key == NULL)) {
2103         tst = ADMNOMEM;
2104         goto fail_bos_KeyGetBegin;
2105     }
2106
2107     key->next = 0;
2108     key->server = b_handle->server_encrypt;
2109
2110     if (IteratorInit
2111         (iter, (void *)key, GetKeyRPC, GetKeyFromCache, NULL, NULL, &tst)) {
2112         *iterationIdP = (void *)iter;
2113         rc = 1;
2114     }
2115
2116   fail_bos_KeyGetBegin:
2117
2118     if (rc == 0) {
2119         if (iter != NULL) {
2120             free(iter);
2121         }
2122         if (key != NULL) {
2123             free(key);
2124         }
2125     }
2126
2127     if (st != NULL) {
2128         *st = tst;
2129     }
2130     return rc;
2131 }
2132
2133 /*
2134  * bos_KeyGetNext - retrieve the next key 
2135  * from the bos server.
2136  *
2137  * PARAMETERS
2138  *
2139  * IN iterationId - an iterator previously returned by 
2140  * bos_KeyGetBegin
2141  *
2142  * OUT keyP - upon successful completion contains the next key
2143  * retrieved from the server.
2144  *
2145  * LOCKS
2146  *
2147  * No locks are obtained or released by this function
2148  *
2149  * RETURN CODES
2150  *
2151  * Returns != 0 upon successful completion.
2152  *
2153  */
2154
2155 int ADMINAPI
2156 bos_KeyGetNext(const void *iterationId, bos_KeyInfo_p keyP, afs_status_p st)
2157 {
2158     int rc = 0;
2159     afs_status_t tst = 0;
2160     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2161
2162     if (iterationId == NULL) {
2163         tst = ADMITERATIONIDPNULL;
2164         goto fail_bos_KeyGetNext;
2165     }
2166
2167     if (keyP == NULL) {
2168         tst = ADMBOSKEYPNULL;
2169         goto fail_bos_KeyGetNext;
2170     }
2171
2172     rc = IteratorNext(iter, (void *)keyP, &tst);
2173
2174   fail_bos_KeyGetNext:
2175
2176     if (st != NULL) {
2177         *st = tst;
2178     }
2179     return rc;
2180 }
2181
2182 /*
2183  * bos_KeyGetDone - finish using a key iterator.
2184  *
2185  * PARAMETERS
2186  *
2187  * IN iterationId - an iterator previously returned by
2188  * bos_KeyGetBegin
2189  *
2190  * LOCKS
2191  *
2192  * No locks are obtained or released by this function
2193  *
2194  * RETURN CODES
2195  *
2196  * Returns != 0 upon successful completion.
2197  *
2198  */
2199
2200 int ADMINAPI
2201 bos_KeyGetDone(const void *iterationId, afs_status_p st)
2202 {
2203     int rc = 0;
2204     afs_status_t tst = 0;
2205     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2206
2207     if (iterationId == NULL) {
2208         tst = ADMITERATIONIDPNULL;
2209         goto fail_bos_KeyGetDone;
2210     }
2211
2212     rc = IteratorDone(iter, &tst);
2213
2214   fail_bos_KeyGetDone:
2215
2216     if (st != NULL) {
2217         *st = tst;
2218     }
2219     return rc;
2220 }
2221
2222 /*
2223  * bos_CellSet - set the cell name at a bos server.
2224  *
2225  * PARAMETERS
2226  *
2227  * IN serverHandle - a previously opened serverHandle.
2228  *
2229  * IN cellName - the new cell name.
2230  *
2231  * LOCKS
2232  *
2233  * No locks are obtained or released by this function
2234  *
2235  * RETURN CODES
2236  *
2237  * Returns != 0 upon successful completion.
2238  */
2239
2240 int ADMINAPI
2241 bos_CellSet(const void *serverHandle, const char *cellName, afs_status_p st)
2242 {
2243     int rc = 0;
2244     afs_status_t tst = 0;
2245     bos_server_p b_handle = (bos_server_p) serverHandle;
2246
2247     if (!isValidServerHandle(b_handle, &tst)) {
2248         goto fail_bos_CellSet;
2249     }
2250
2251     if ((cellName == NULL) || (*cellName == 0)) {
2252         tst = ADMCLIENTCELLNAMENULL;
2253         goto fail_bos_CellSet;
2254     }
2255
2256     tst = BOZO_SetCellName(b_handle->server, (char *)cellName);
2257
2258     if (tst == 0) {
2259         rc = 1;
2260     }
2261
2262   fail_bos_CellSet:
2263
2264     if (st != NULL) {
2265         *st = tst;
2266     }
2267     return rc;
2268 }
2269
2270 /*
2271  * bos_CellGet - get the cell name at a bos server.
2272  *
2273  * PARAMETERS
2274  *
2275  * IN serverHandle - a previously opened serverHandle.
2276  *
2277  * OUT cellName - the cell name.
2278  *
2279  * LOCKS
2280  *
2281  * No locks are obtained or released by this function
2282  *
2283  * RETURN CODES
2284  *
2285  * Returns != 0 upon successful completion.
2286  */
2287
2288 int ADMINAPI
2289 bos_CellGet(const void *serverHandle, char *cellName, afs_status_p st)
2290 {
2291     int rc = 0;
2292     afs_status_t tst = 0;
2293     bos_server_p b_handle = (bos_server_p) serverHandle;
2294
2295     if (!isValidServerHandle(b_handle, &tst)) {
2296         goto fail_bos_CellGet;
2297     }
2298
2299     if (cellName == NULL) {
2300         tst = ADMCLIENTCELLNAMENULL;
2301         goto fail_bos_CellGet;
2302     }
2303
2304     tst = BOZO_GetCellName(b_handle->server, &cellName);
2305
2306     if (tst == 0) {
2307         rc = 1;
2308     }
2309
2310   fail_bos_CellGet:
2311
2312     if (st != NULL) {
2313         *st = tst;
2314     }
2315     return rc;
2316 }
2317
2318 /*
2319  * bos_HostCreate - add a new host to the cell.
2320  *
2321  * PARAMETERS
2322  *
2323  * IN serverHandle - a previously opened serverHandle.
2324  *
2325  * IN hostName - the new host.
2326  *
2327  * LOCKS
2328  *
2329  * No locks are obtained or released by this function
2330  *
2331  * RETURN CODES
2332  *
2333  * Returns != 0 upon successful completion.
2334  */
2335
2336 int ADMINAPI
2337 bos_HostCreate(const void *serverHandle, const char *hostName,
2338                afs_status_p st)
2339 {
2340     int rc = 0;
2341     afs_status_t tst = 0;
2342     bos_server_p b_handle = (bos_server_p) serverHandle;
2343
2344     if (!isValidServerHandle(b_handle, &tst)) {
2345         goto fail_bos_HostCreate;
2346     }
2347
2348     if ((hostName == NULL) || (*hostName == 0)) {
2349         tst = ADMBOSHOSTNAMENULL;
2350         goto fail_bos_HostCreate;
2351     }
2352
2353     tst = BOZO_AddCellHost(b_handle->server, (char *)hostName);
2354
2355     if (tst == 0) {
2356         rc = 1;
2357     }
2358
2359   fail_bos_HostCreate:
2360
2361     if (st != NULL) {
2362         *st = tst;
2363     }
2364     return rc;
2365 }
2366
2367 /*
2368  * bos_HostDelete - delete a host from the cell.
2369  *
2370  * PARAMETERS
2371  *
2372  * IN serverHandle - a previously opened serverHandle.
2373  *
2374  * IN hostName - the host.
2375  *
2376  * LOCKS
2377  *
2378  * No locks are obtained or released by this function
2379  *
2380  * RETURN CODES
2381  *
2382  * Returns != 0 upon successful completion.
2383  */
2384
2385 int ADMINAPI
2386 bos_HostDelete(const void *serverHandle, const char *hostName,
2387                afs_status_p st)
2388 {
2389     int rc = 0;
2390     afs_status_t tst = 0;
2391     bos_server_p b_handle = (bos_server_p) serverHandle;
2392
2393     if (!isValidServerHandle(b_handle, &tst)) {
2394         goto fail_bos_HostDelete;
2395     }
2396
2397     if ((hostName == NULL) || (*hostName == 0)) {
2398         tst = ADMBOSHOSTNAMENULL;
2399         goto fail_bos_HostDelete;
2400     }
2401
2402     tst = BOZO_DeleteCellHost(b_handle->server, (char *)hostName);
2403
2404     if (tst == 0) {
2405         rc = 1;
2406     }
2407
2408   fail_bos_HostDelete:
2409
2410     if (st != NULL) {
2411         *st = tst;
2412     }
2413     return rc;
2414 }
2415
2416 /*
2417  * The iterator functions and data for the host retrieval functions
2418  */
2419
2420 typedef struct host_get {
2421     int next;
2422     struct rx_connection *server;
2423     char host[CACHED_ITEMS][BOS_MAX_NAME_LEN];
2424 } host_get_t, *host_get_p;
2425
2426 static int
2427 GetHostRPC(void *rpc_specific, int slot, int *last_item,
2428            int *last_item_contains_data, afs_status_p st)
2429 {
2430     int rc = 0;
2431     afs_status_t tst = 0;
2432     host_get_p host = (host_get_p) rpc_specific;
2433     char *ptr = (char *)&host->host[slot];
2434
2435     tst = BOZO_GetCellHost(host->server, host->next++, &ptr);
2436
2437     if (tst == 0) {
2438         rc = 1;
2439     } else if (tst == BZDOM) {
2440         tst = 0;
2441         rc = 1;
2442         *last_item = 1;
2443         *last_item_contains_data = 0;
2444     }
2445
2446     if (st != NULL) {
2447         *st = tst;
2448     }
2449     return rc;
2450 }
2451
2452 static int
2453 GetHostFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
2454 {
2455     int rc = 0;
2456     afs_status_t tst = 0;
2457     host_get_p host = (host_get_p) rpc_specific;
2458
2459     strcpy((char *)dest, (char *)&host->host[slot]);
2460     rc = 1;
2461
2462     if (st != NULL) {
2463         *st = tst;
2464     }
2465     return rc;
2466 }
2467
2468 /*
2469  * bos_HostGetBegin - begin iterating over the hosts in a cell
2470  * at a particular bos server.
2471  *
2472  * PARAMETERS
2473  *
2474  * IN serverHandle - a previously opened serverHandle.
2475  *
2476  * OUT iter - an iterator that can be passed to bos_HostGetNext
2477  * to retrieve the process names.
2478  *
2479  * LOCKS
2480  *
2481  * No locks are obtained or released by this function
2482  *
2483  * RETURN CODES
2484  *
2485  * Returns != 0 upon successful completion.
2486  *
2487  */
2488
2489 int ADMINAPI
2490 bos_HostGetBegin(const void *serverHandle, void **iterationIdP,
2491                  afs_status_p st)
2492 {
2493     int rc = 0;
2494     afs_status_t tst = 0;
2495     bos_server_p b_handle = (bos_server_p) serverHandle;
2496     afs_admin_iterator_p iter =
2497         (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2498     host_get_p host = (host_get_p) malloc(sizeof(host_get_t));
2499
2500     if (!isValidServerHandle(b_handle, &tst)) {
2501         goto fail_bos_HostGetBegin;
2502     }
2503
2504     if (iterationIdP == NULL) {
2505         tst = ADMITERATIONIDPNULL;
2506         goto fail_bos_HostGetBegin;
2507     }
2508
2509     if ((iter == NULL) || (host == NULL)) {
2510         tst = ADMNOMEM;
2511         goto fail_bos_HostGetBegin;
2512     }
2513
2514     host->next = 0;
2515     host->server = b_handle->server;
2516
2517     if (IteratorInit
2518         (iter, (void *)host, GetHostRPC, GetHostFromCache, NULL, NULL,
2519          &tst)) {
2520         *iterationIdP = (void *)iter;
2521         rc = 1;
2522     }
2523
2524   fail_bos_HostGetBegin:
2525
2526     if (rc == 0) {
2527         if (iter != NULL) {
2528             free(iter);
2529         }
2530         if (host != NULL) {
2531             free(host);
2532         }
2533     }
2534
2535     if (st != NULL) {
2536         *st = tst;
2537     }
2538     return rc;
2539 }
2540
2541 /*
2542  * bos_HostGetNext - retrieve the next host 
2543  * from the bos server.
2544  *
2545  * PARAMETERS
2546  *
2547  * IN iterationId - an iterator previously returned by 
2548  * bos_HostGetBegin
2549  *
2550  * OUT hostName - upon successful completion contains the next host
2551  * retrieved from the server.
2552  *
2553  * LOCKS
2554  *
2555  * No locks are obtained or released by this function
2556  *
2557  * RETURN CODES
2558  *
2559  * Returns != 0 upon successful completion.
2560  *
2561  */
2562
2563 int ADMINAPI
2564 bos_HostGetNext(const void *iterationId, char *hostName, afs_status_p st)
2565 {
2566     int rc = 0;
2567     afs_status_t tst = 0;
2568     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2569
2570     if (iterationId == NULL) {
2571         tst = ADMITERATIONIDPNULL;
2572         goto fail_bos_HostGetNext;
2573     }
2574
2575     if (hostName == NULL) {
2576         tst = ADMBOSHOSTNAMENULL;
2577         goto fail_bos_HostGetNext;
2578     }
2579
2580     rc = IteratorNext(iter, (void *)hostName, &tst);
2581
2582   fail_bos_HostGetNext:
2583
2584     if (st != NULL) {
2585         *st = tst;
2586     }
2587     return rc;
2588 }
2589
2590 /*
2591  * bos_HostGetDone - finish using a host iterator.
2592  *
2593  * PARAMETERS
2594  *
2595  * IN iterationId - an iterator previously returned by
2596  * bos_HostGetBegin
2597  *
2598  * LOCKS
2599  *
2600  * No locks are obtained or released by this function
2601  *
2602  * RETURN CODES
2603  *
2604  * Returns != 0 upon successful completion.
2605  *
2606  */
2607
2608 int ADMINAPI
2609 bos_HostGetDone(const void *iterationId, afs_status_p st)
2610 {
2611     int rc = 0;
2612     afs_status_t tst = 0;
2613     afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2614
2615     if (iterationId == NULL) {
2616         tst = ADMITERATIONIDPNULL;
2617         goto fail_bos_HostGetDone;
2618     }
2619
2620     rc = IteratorDone(iter, &tst);
2621
2622   fail_bos_HostGetDone:
2623
2624     if (st != NULL) {
2625         *st = tst;
2626     }
2627     return rc;
2628 }
2629
2630 /*
2631  * bos_ExecutableCreate - create a new executable at the bos server.
2632  *
2633  * PARAMETERS
2634  *
2635  * IN serverHandle - a previously opened serverHandle.
2636  *
2637  * IN sourceFile - the executable to install at the bos server.
2638  *
2639  * IN destFile - the location where the executable will be installed.
2640  *
2641  * LOCKS
2642  *
2643  * No locks are obtained or released by this function
2644  *
2645  * RETURN CODES
2646  *
2647  * Returns != 0 upon successful completion.
2648  *
2649  */
2650
2651 int ADMINAPI
2652 bos_ExecutableCreate(const void *serverHandle, const char *sourceFile,
2653                      const char *destFile, afs_status_p st)
2654 {
2655     int rc = 0;
2656     afs_status_t tst = 0;
2657     bos_server_p b_handle = (bos_server_p) serverHandle;
2658     int fd;
2659     struct stat estat;
2660     struct rx_call *tcall;
2661
2662     /*
2663      * Validate arguments
2664      */
2665
2666     if (!isValidServerHandle(b_handle, &tst)) {
2667         goto fail_bos_ExecutableCreate;
2668     }
2669
2670     if ((sourceFile == NULL) || (*sourceFile == 0)) {
2671         tst = ADMBOSSOURCEFILENULL;
2672         goto fail_bos_ExecutableCreate;
2673     }
2674
2675     if ((destFile == NULL) || (*destFile == 0)) {
2676         tst = ADMBOSDESTFILENULL;
2677         goto fail_bos_ExecutableCreate;
2678     }
2679
2680     /*
2681      * Open the file locally and compute its size
2682      */
2683
2684     fd = open(sourceFile, O_RDONLY);
2685
2686     if (fd < 0) {
2687         tst = ADMBOSCANTOPENSOURCEFILE;
2688         goto fail_bos_ExecutableCreate;
2689     }
2690
2691     if (fstat(fd, &estat)) {
2692         tst = ADMBOSCANTSTATSOURCEFILE;
2693         goto fail_bos_ExecutableCreate;
2694     }
2695
2696     /*
2697      * Start a split rpc to the bos server.
2698      */
2699
2700     tcall = rx_NewCall(b_handle->server);
2701
2702     tst =
2703         StartBOZO_Install(tcall, (char *)destFile, estat.st_size,
2704                           (afs_int32) estat.st_mode, estat.st_mtime);
2705
2706     if (tst) {
2707         rx_EndCall(tcall, tst);
2708         goto fail_bos_ExecutableCreate;
2709     }
2710
2711     /*
2712      * Copy the data to the server
2713      */
2714
2715     while (1) {
2716         char tbuffer[512];
2717         size_t len;
2718         len = read(fd, tbuffer, sizeof(tbuffer));
2719         if (len < 0) {
2720             tst = ADMBOSCANTREADSOURCEFILE;
2721             rx_EndCall(tcall, len);
2722             goto fail_bos_ExecutableCreate;
2723         }
2724         if (len == 0) {
2725             tst = 0;
2726             break;
2727         }
2728         tst = rx_Write(tcall, tbuffer, len);
2729         if (tst != len) {
2730             tst = ADMBOSSENDSOURCEFILE;
2731             rx_EndCall(tcall, tst);
2732             goto fail_bos_ExecutableCreate;
2733         }
2734     }
2735
2736     /*
2737      * Terminate the rpc to the server
2738      */
2739
2740     tst = rx_EndCall(tcall, tst);
2741
2742     if (tst == 0) {
2743         rc = 1;
2744     }
2745
2746   fail_bos_ExecutableCreate:
2747
2748     if (st != NULL) {
2749         *st = tst;
2750     }
2751     return rc;
2752 }
2753
2754 /*
2755  * bos_ExecutableRevert - revert an executable to a previous .BAK version.
2756  *
2757  * PARAMETERS
2758  *
2759  * IN serverHandle - a previously opened serverHandle.
2760  *
2761  * IN execFile - the executable to revert at the bos server.
2762  *
2763  * LOCKS
2764  *
2765  * No locks are obtained or released by this function
2766  *
2767  * RETURN CODES
2768  *
2769  * Returns != 0 upon successful completion.
2770  *
2771  */
2772
2773 int ADMINAPI
2774 bos_ExecutableRevert(const void *serverHandle, const char *execFile,
2775                      afs_status_p st)
2776 {
2777     int rc = 0;
2778     afs_status_t tst = 0;
2779     bos_server_p b_handle = (bos_server_p) serverHandle;
2780
2781     if (!isValidServerHandle(b_handle, &tst)) {
2782         goto fail_bos_ExecutableRevert;
2783     }
2784
2785     if ((execFile == NULL) || (*execFile == 0)) {
2786         tst = ADMBOSEXECFILENULL;
2787         goto fail_bos_ExecutableRevert;
2788     }
2789
2790     tst = BOZO_UnInstall(b_handle->server, (char *)execFile);
2791
2792     if (tst == 0) {
2793         rc = 1;
2794     }
2795
2796   fail_bos_ExecutableRevert:
2797
2798     if (st != NULL) {
2799         *st = tst;
2800     }
2801     return rc;
2802 }
2803
2804 /*
2805  * bos_ExecutableTimestampGet - get the last mod times for an executable,
2806  * the .BAK version of the executable, and the .OLD version of the
2807  * executable if they exist.
2808  *
2809  * PARAMETERS
2810  *
2811  * IN serverHandle - a previously opened serverHandle.
2812  *
2813  * IN execFile - the executable to revert at the bos server.
2814  *
2815  * LOCKS
2816  *
2817  * No locks are obtained or released by this function
2818  *
2819  * RETURN CODES
2820  *
2821  * Returns != 0 upon successful completion.
2822  *
2823  */
2824
2825 int ADMINAPI
2826 bos_ExecutableTimestampGet(const void *serverHandle, const char *execFile,
2827                            unsigned long *newTime, unsigned long *oldTime,
2828                            unsigned long *bakTime, afs_status_p st)
2829 {
2830     int rc = 0;
2831     afs_status_t tst = 0;
2832     bos_server_p b_handle = (bos_server_p) serverHandle;
2833
2834     if (!isValidServerHandle(b_handle, &tst)) {
2835         goto fail_bos_ExecutableTimestampGet;
2836     }
2837
2838     if ((execFile == NULL) || (*execFile == 0)) {
2839         tst = ADMBOSEXECFILENULL;
2840         goto fail_bos_ExecutableTimestampGet;
2841     }
2842
2843     if (newTime == NULL) {
2844         tst = ADMBOSNEWTIMENULL;
2845         goto fail_bos_ExecutableTimestampGet;
2846     }
2847
2848     if (oldTime == NULL) {
2849         tst = ADMBOSOLDTIMENULL;
2850         goto fail_bos_ExecutableTimestampGet;
2851     }
2852
2853     if (bakTime == NULL) {
2854         tst = ADMBOSBAKTIMENULL;
2855         goto fail_bos_ExecutableTimestampGet;
2856     }
2857
2858     tst =
2859         BOZO_GetDates(b_handle->server, (char *)execFile, newTime, bakTime, oldTime);
2860
2861     if (tst == 0) {
2862         rc = 1;
2863     }
2864
2865   fail_bos_ExecutableTimestampGet:
2866
2867     if (st != NULL) {
2868         *st = tst;
2869     }
2870     return rc;
2871 }
2872
2873 /*
2874  * bos_ExecutablePrune - prune the bak, old, and core files off a server
2875  * machine.
2876  *
2877  * PARAMETERS
2878  *
2879  * IN serverHandle - a previously opened serverHandle.
2880  *
2881  * IN oldFiles - prune .OLD files.
2882  *
2883  * IN bakFiles - prune .BAK files.
2884  *
2885  * IN coreFiles - prune core files.
2886  *
2887  * LOCKS
2888  *
2889  * No locks are obtained or released by this function
2890  *
2891  * RETURN CODES
2892  *
2893  * Returns != 0 upon successful completion.
2894  *
2895  */
2896
2897 int ADMINAPI
2898 bos_ExecutablePrune(const void *serverHandle, bos_Prune_t oldFiles,
2899                     bos_Prune_t bakFiles, bos_Prune_t coreFiles,
2900                     afs_status_p st)
2901 {
2902     int rc = 0;
2903     afs_status_t tst = 0;
2904     bos_server_p b_handle = (bos_server_p) serverHandle;
2905     afs_int32 flags = 0;
2906
2907     if (!isValidServerHandle(b_handle, &tst)) {
2908         goto fail_bos_ExecutablePrune;
2909     }
2910
2911     if (oldFiles == BOS_PRUNE) {
2912         flags |= BOZO_PRUNEOLD;
2913     }
2914
2915     if (bakFiles == BOS_PRUNE) {
2916         flags |= BOZO_PRUNEBAK;
2917     }
2918
2919     if (coreFiles == BOS_PRUNE) {
2920         flags |= BOZO_PRUNECORE;
2921     }
2922
2923     tst = BOZO_Prune(b_handle->server, flags);
2924
2925     if (tst == 0) {
2926         rc = 1;
2927     }
2928
2929   fail_bos_ExecutablePrune:
2930
2931     if (st != NULL) {
2932         *st = tst;
2933     }
2934     return rc;
2935 }
2936
2937 /*
2938  * bos_ExecutableRestartTimeSet - set the restart time of the bos server
2939  * machine.
2940  *
2941  * PARAMETERS
2942  *
2943  * IN serverHandle - a previously opened serverHandle.
2944  *
2945  * IN type - specifies either weekly restart or daily restart time.
2946  *
2947  * IN time - the time to begin restarts.
2948  *
2949  * LOCKS
2950  *
2951  * No locks are obtained or released by this function
2952  *
2953  * RETURN CODES
2954  *
2955  * Returns != 0 upon successful completion.
2956  *
2957  */
2958
2959 int ADMINAPI
2960 bos_ExecutableRestartTimeSet(const void *serverHandle, bos_Restart_t type,
2961                              bos_RestartTime_t time, afs_status_p st)
2962 {
2963     int rc = 0;
2964     afs_status_t tst = 0;
2965     bos_server_p b_handle = (bos_server_p) serverHandle;
2966     afs_int32 restartType = 0;
2967     struct ktime restartTime;
2968
2969     if (!isValidServerHandle(b_handle, &tst)) {
2970         goto fail_bos_ExecutableRestartTimeSet;
2971     }
2972
2973     if (type == BOS_RESTART_WEEKLY) {
2974         restartType = 1;
2975     } else {
2976         restartType = 2;
2977     }
2978
2979     if ((time.mask & BOS_RESTART_TIME_HOUR)
2980         && ((time.hour < 0) || (time.hour > 23))) {
2981         tst = ADMBOSHOURINVALID;
2982         goto fail_bos_ExecutableRestartTimeSet;
2983     }
2984
2985     if ((time.mask & BOS_RESTART_TIME_MINUTE)
2986         && ((time.min < 0) || (time.min > 60))) {
2987         tst = ADMBOSMINUTEINVALID;
2988         goto fail_bos_ExecutableRestartTimeSet;
2989     }
2990
2991     if ((time.mask & BOS_RESTART_TIME_SECOND)
2992         && ((time.sec < 0) || (time.sec > 60))) {
2993         tst = ADMBOSSECONDINVALID;
2994         goto fail_bos_ExecutableRestartTimeSet;
2995     }
2996
2997     if ((time.mask & BOS_RESTART_TIME_DAY)
2998         && ((time.day < 0) || (time.day > 6))) {
2999         tst = ADMBOSDAYINVALID;
3000         goto fail_bos_ExecutableRestartTimeSet;
3001     }
3002
3003     restartTime.mask = time.mask;
3004     restartTime.hour = time.hour;
3005     restartTime.min = time.min;
3006     restartTime.sec = time.sec;
3007     restartTime.day = time.day;
3008
3009     tst = BOZO_SetRestartTime(b_handle->server, restartType, &restartTime);
3010
3011     if (tst == 0) {
3012         rc = 1;
3013     }
3014
3015   fail_bos_ExecutableRestartTimeSet:
3016
3017     if (st != NULL) {
3018         *st = tst;
3019     }
3020     return rc;
3021 }
3022
3023 /*
3024  * bos_ExecutableRestartTimeGet - get the restart time of the bos server
3025  * machine.
3026  *
3027  * PARAMETERS
3028  *
3029  * IN serverHandle - a previously opened serverHandle.
3030  *
3031  * IN type - specifies either weekly restart or daily restart time.
3032  *
3033  * OUT timeP - the time to begin restarts.
3034  *
3035  * LOCKS
3036  *
3037  * No locks are obtained or released by this function
3038  *
3039  * RETURN CODES
3040  *
3041  * Returns != 0 upon successful completion.
3042  *
3043  */
3044
3045 int ADMINAPI
3046 bos_ExecutableRestartTimeGet(const void *serverHandle, bos_Restart_t type,
3047                              bos_RestartTime_p timeP, afs_status_p st)
3048 {
3049     int rc = 0;
3050     afs_status_t tst = 0;
3051     bos_server_p b_handle = (bos_server_p) serverHandle;
3052     afs_int32 restartType = 0;
3053     struct ktime restartTime;
3054
3055     if (!isValidServerHandle(b_handle, &tst)) {
3056         goto fail_bos_ExecutableRestartTimeGet;
3057     }
3058
3059     if (timeP == NULL) {
3060         tst = ADMBOSTIMEPNULL;
3061         goto fail_bos_ExecutableRestartTimeGet;
3062     }
3063
3064     if (type == BOS_RESTART_WEEKLY) {
3065         restartType = 1;
3066     } else {
3067         restartType = 2;
3068     }
3069
3070     tst = BOZO_GetRestartTime(b_handle->server, restartType, &restartTime);
3071
3072     if (tst != 0) {
3073         goto fail_bos_ExecutableRestartTimeGet;
3074     }
3075
3076     timeP->mask = restartTime.mask;
3077     timeP->hour = restartTime.hour;
3078     timeP->min = restartTime.min;
3079     timeP->sec = restartTime.sec;
3080     timeP->day = restartTime.day;
3081     rc = 1;
3082
3083   fail_bos_ExecutableRestartTimeGet:
3084
3085     if (st != NULL) {
3086         *st = tst;
3087     }
3088     return rc;
3089 }
3090
3091 /*
3092  * bos_LogGet - get a log file from the bos server machine.
3093  *
3094  * PARAMETERS
3095  *
3096  * IN serverHandle - a previously opened serverHandle.
3097  *
3098  * IN log - the log file to retrieve.
3099  *
3100  * IN/OUT logBufferSizeP - the length of the logData buffer on input,
3101  * and upon successful completion, the length of data stored in the buffer.
3102  *
3103  * OUT logData - the retrieved data upon successful completion.
3104  *
3105  * LOCKS
3106  *
3107  * No locks are obtained or released by this function
3108  *
3109  * RETURN CODES
3110  *
3111  * Returns != 0 upon successful completion.
3112  *
3113  */
3114
3115 int ADMINAPI
3116 bos_LogGet(const void *serverHandle, const char *log,
3117            unsigned long *logBufferSizeP, char *logData, afs_status_p st)
3118 {
3119     int rc = 0;
3120     afs_status_t tst = 0;
3121     bos_server_p b_handle = (bos_server_p) serverHandle;
3122     struct rx_call *tcall = NULL;
3123     afs_int32 error;
3124     char buffer;
3125     int have_call = 0;
3126     unsigned long bytes_read = 0;
3127
3128     /*
3129      * Validate parameters
3130      */
3131
3132     if (!isValidServerHandle(b_handle, &tst)) {
3133         goto fail_bos_LogGet;
3134     }
3135
3136     if ((log == NULL) || (*log == 0)) {
3137         tst = ADMBOSLOGNULL;
3138         goto fail_bos_LogGet;
3139     }
3140
3141     if (logBufferSizeP == NULL) {
3142         tst = ADMBOSLOGBUFFERSIZEPNULL;
3143         goto fail_bos_LogGet;
3144     }
3145
3146     if (logData == NULL) {
3147         tst = ADMBOSLOGDATANULL;
3148         goto fail_bos_LogGet;
3149     }
3150
3151     /*
3152      * Begin to retrieve the data
3153      */
3154
3155     tcall = rx_NewCall(b_handle->server);
3156     have_call = 1;
3157     tst = StartBOZO_GetLog(tcall, log);
3158
3159     if (tst != 0) {
3160         goto fail_bos_LogGet;
3161     }
3162
3163     /*
3164      * Read the log file data
3165      */
3166
3167     while (1) {
3168         error = rx_Read(tcall, &buffer, 1);
3169         if (error != 1) {
3170             tst = ADMBOSLOGFILEERROR;
3171             goto fail_bos_LogGet;
3172         }
3173
3174         /*
3175          * check for the end of the log
3176          */
3177
3178         if (buffer == 0) {
3179             *logBufferSizeP = bytes_read;
3180             break;
3181         }
3182
3183         /*
3184          * We've successfully read another byte, copy it to logData
3185          * if there's room
3186          */
3187
3188         bytes_read++;
3189         if (bytes_read <= *logBufferSizeP) {
3190             *logData++ = buffer;
3191         } else {
3192             tst = ADMMOREDATA;
3193         }
3194     }
3195     if (tst == 0) {
3196         rc = 1;
3197     }
3198
3199   fail_bos_LogGet:
3200
3201     if (have_call) {
3202         rx_EndCall(tcall, 0);
3203     }
3204
3205     if (st != NULL) {
3206         *st = tst;
3207     }
3208     return rc;
3209 }
3210
3211 /*
3212  * bos_AuthSet - set the authorization level required at the bos server.
3213  *
3214  * PARAMETERS
3215  *
3216  * IN serverHandle - a previously opened serverHandle.
3217  *
3218  * IN auth - specifies the new auth level.
3219  *
3220  * LOCKS
3221  *
3222  * No locks are obtained or released by this function
3223  *
3224  * RETURN CODES
3225  *
3226  * Returns != 0 upon successful completion.
3227  *
3228  */
3229
3230 int ADMINAPI
3231 bos_AuthSet(const void *serverHandle, bos_Auth_t auth, afs_status_p st)
3232 {
3233     int rc = 0;
3234     afs_status_t tst = 0;
3235     bos_server_p b_handle = (bos_server_p) serverHandle;
3236     afs_int32 level = 0;
3237
3238     if (!isValidServerHandle(b_handle, &tst)) {
3239         goto fail_bos_AuthSet;
3240     }
3241
3242     if (auth == BOS_AUTH_REQUIRED) {
3243         level = 0;
3244     } else {
3245         level = 1;
3246     }
3247
3248     tst = BOZO_SetNoAuthFlag(b_handle->server, level);
3249
3250     if (tst == 0) {
3251         rc = 1;
3252     }
3253
3254   fail_bos_AuthSet:
3255
3256     if (st != NULL) {
3257         *st = tst;
3258     }
3259     return rc;
3260 }
3261
3262 /*
3263  * bos_CommandExecute - execute a command at the bos server.
3264  *
3265  * PARAMETERS
3266  *
3267  * IN serverHandle - a previously opened serverHandle.
3268  *
3269  * IN command - the command to execute.
3270  *
3271  * LOCKS
3272  *
3273  * No locks are obtained or released by this function
3274  *
3275  * RETURN CODES
3276  *
3277  * Returns != 0 upon successful completion.
3278  *
3279  */
3280
3281 int ADMINAPI
3282 bos_CommandExecute(const void *serverHandle, const char *command,
3283                    afs_status_p st)
3284 {
3285     int rc = 0;
3286     afs_status_t tst = 0;
3287     bos_server_p b_handle = (bos_server_p) serverHandle;
3288
3289     if (!isValidServerHandle(b_handle, &tst)) {
3290         goto fail_bos_CommandExecute;
3291     }
3292
3293     if ((command == NULL) || (*command == 0)) {
3294         tst = ADMBOSCOMMANDNULL;
3295         goto fail_bos_CommandExecute;
3296     }
3297
3298     tst = BOZO_Exec(b_handle->server, command);
3299
3300     if (tst == 0) {
3301         rc = 1;
3302     }
3303
3304   fail_bos_CommandExecute:
3305
3306     if (st != NULL) {
3307         *st = tst;
3308     }
3309     return rc;
3310 }
3311
3312 /*
3313  * bos_Salvage - perform a remote salvage operation.
3314  *
3315  * PARAMETERS
3316  *
3317  * IN cellHandle - a previously opened cellHandle.
3318  *
3319  * IN serverHandle - a previously opened serverHandle.
3320  *
3321  * IN partitionName - the partition to salvage.  Can be null.
3322  *
3323  * IN volumeName - the volume to salvage.  Can be null, if non-null,
3324  * partitionName cannot be null.
3325  *
3326  * IN numSalvagers - the number of salvage processes to run in parallel.
3327  *
3328  * IN tmpDir - directory to place temporary files.  Can be null.
3329  *
3330  * IN logFile - file where salvage log will be written.  Can be null.
3331  *
3332  * IN force - sets salvager -force flag.
3333  *
3334  * IN salvageDamagedVolumes - sets salvager -oktozap flag.
3335  *
3336  * IN writeInodes - sets salvager -inodes flag.
3337  *
3338  * IN writeRootInodes - sets salvager -rootinodes flag.
3339  *
3340  * IN forceDirectory - sets salvager -salvagedirs flag.
3341  *
3342  * IN forceBlockRead - sets salvager -blockread flag.
3343  *
3344  * LOCKS
3345  *
3346  * No locks are obtained or released by this function
3347  *
3348  * RETURN CODES
3349  *
3350  * Returns != 0 upon successful completion.
3351  *
3352  */
3353
3354 #define INITIAL_LOG_LEN 4096
3355
3356 int ADMINAPI
3357 bos_Salvage(const void *cellHandle, const void *serverHandle,
3358             const char *partitionName, const char *volumeName,
3359             int numSalvagers, const char *tmpDir, const char *logFile,
3360             vos_force_t force,
3361             bos_SalvageDamagedVolumes_t salvageDamagedVolumes,
3362             bos_WriteInodes_t writeInodes,
3363             bos_WriteRootInodes_t writeRootInodes,
3364             bos_ForceDirectory_t forceDirectory,
3365             bos_ForceBlockRead_t forceBlockRead, afs_status_p st)
3366 {
3367     int rc = 0;
3368     afs_status_t tst = 0;
3369     bos_server_p b_handle = (bos_server_p) serverHandle;
3370     afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
3371     int have_partition = 0;
3372     int have_volume = 0;
3373     unsigned int part = 0;
3374     int try_to_stop_fileserver = 0;
3375     bos_ProcessType_t procType;
3376     bos_ProcessInfo_t procInfo;
3377     FILE *log = NULL;
3378     char command[BOS_MAX_NAME_LEN];
3379     int command_len = 0;
3380     int poll_rc;
3381     char *logData = NULL;
3382     unsigned long logLen = INITIAL_LOG_LEN;
3383
3384     /*
3385      * Validate arguments
3386      */
3387
3388     if (!IsValidCellHandle(c_handle, &tst)) {
3389         goto fail_bos_Salvage;
3390     }
3391
3392     if (!isValidServerHandle(b_handle, &tst)) {
3393         goto fail_bos_Salvage;
3394     }
3395
3396     if (c_handle->vos_valid == 0) {
3397         tst = ADMBOSCELLHANDLENOVOS;
3398         goto fail_bos_Salvage;
3399     }
3400
3401     if ((partitionName != NULL) && (*partitionName != 0)) {
3402         if (!vos_PartitionNameToId(partitionName, &part, &tst)) {
3403             goto fail_bos_Salvage;
3404         }
3405         have_partition = 1;
3406     }
3407
3408     if ((volumeName != NULL) && (*volumeName != 0)) {
3409         if (!have_partition) {
3410             tst = ADMBOSSALVAGEVOLUME;
3411             goto fail_bos_Salvage;
3412         }
3413         have_volume = 1;
3414     }
3415
3416     if ((logFile != NULL) && (*logFile != 0)) {
3417         log = fopen(logFile, "w");
3418         if (!log) {
3419             tst = ADMBOSSALVAGEBADLOG;
3420             goto fail_bos_Salvage;
3421         }
3422     }
3423
3424     /*
3425      * If we are salvaging more than a single volume, stop the fileserver
3426      */
3427
3428     if (!have_volume) {
3429         try_to_stop_fileserver = 1;
3430     }
3431
3432     /*
3433      * Only try to stop the fileserver if it is running
3434      */
3435
3436     if (try_to_stop_fileserver) {
3437         if (bos_ProcessInfoGet
3438             (serverHandle, "fs", &procType, &procInfo, &tst)) {
3439             if (procInfo.processGoal != BOS_PROCESS_RUNNING) {
3440                 try_to_stop_fileserver = 0;
3441             }
3442         }
3443     }
3444
3445     /*
3446      * Make the call to stop the fileserver and wait for it to shutdown
3447      */
3448
3449     if (try_to_stop_fileserver) {
3450         if (!bos_ProcessExecutionStateSetTemporary
3451             (serverHandle, "fs", BOS_PROCESS_STOPPED, &tst)) {
3452             goto fail_bos_Salvage;
3453         }
3454         bos_ProcessAllWaitTransition(serverHandle, &tst);
3455     }
3456
3457     /*
3458      * Create the salvage command line arguments
3459      */
3460
3461     command_len =
3462         sprintf(command, "%s ", AFSDIR_CANONICAL_SERVER_SALVAGER_FILEPATH);
3463     if (have_partition) {
3464         command_len +=
3465             sprintf(&command[command_len], "-partition %s ", partitionName);
3466     }
3467
3468     if (have_volume) {
3469         command_len +=
3470             sprintf(&command[command_len], "-volumeid %s ", volumeName);
3471     }
3472
3473     if (salvageDamagedVolumes == BOS_DONT_SALVAGE_DAMAGED_VOLUMES) {
3474         command_len += sprintf(&command[command_len], "-nowrite ");
3475     }
3476
3477     if (writeInodes == BOS_SALVAGE_WRITE_INODES) {
3478         command_len += sprintf(&command[command_len], "-inodes ");
3479     }
3480
3481     if (force == VOS_FORCE) {
3482         command_len += sprintf(&command[command_len], "-force ");
3483     }
3484
3485     if (writeRootInodes == BOS_SALVAGE_WRITE_ROOT_INODES) {
3486         command_len += sprintf(&command[command_len], "-rootinodes ");
3487     }
3488
3489     if (forceDirectory == BOS_SALVAGE_FORCE_DIRECTORIES) {
3490         command_len += sprintf(&command[command_len], "-salvagedirs ");
3491     }
3492
3493     if (forceBlockRead == BOS_SALVAGE_FORCE_BLOCK_READS) {
3494         command_len += sprintf(&command[command_len], "-blockreads ");
3495     }
3496
3497     command_len +=
3498         sprintf(&command[command_len], "-parallel %d ", numSalvagers);
3499
3500     if ((tmpDir != NULL) && (*tmpDir != 0)) {
3501         command_len += sprintf(&command[command_len], "-tmpdir %s ", tmpDir);
3502     }
3503
3504     if (command_len > BOS_MAX_NAME_LEN) {
3505         tst = ADMBOSSALVAGEBADOPTIONS;
3506         goto fail_bos_Salvage;
3507     }
3508
3509     /*
3510      * Create the process at the bosserver and wait until it completes
3511      */
3512
3513     if (!bos_ProcessCreate
3514         (serverHandle, "salvage-tmp", BOS_PROCESS_CRON, command, "now", 0,
3515          &tst)) {
3516         goto fail_bos_Salvage;
3517     }
3518
3519     while ((poll_rc =
3520             bos_ProcessInfoGet(serverHandle, "salvage-tmp", &procType,
3521                                &procInfo, &tst))) {
3522         sleep(5);
3523     }
3524
3525     if (tst != BZNOENT) {
3526         goto fail_bos_Salvage;
3527     }
3528
3529     /*
3530      * Print out the salvage log if required by the user
3531      */
3532
3533     if (log != NULL) {
3534
3535         logData = (char *)malloc(INITIAL_LOG_LEN);
3536         if (!logData) {
3537             tst = ADMNOMEM;
3538             goto fail_bos_Salvage;
3539         }
3540
3541         while (!bos_LogGet
3542                (serverHandle, AFSDIR_CANONICAL_SERVER_SLVGLOG_FILEPATH,
3543                 &logLen, logData, &tst)) {
3544             if (logLen > INITIAL_LOG_LEN) {
3545                 logData = (char *)realloc(logData, (logLen + (logLen / 10)));
3546                 if (logData == NULL) {
3547                     tst = ADMNOMEM;
3548                     goto fail_bos_Salvage;
3549                 }
3550             } else {
3551                 goto fail_bos_Salvage;
3552             }
3553         }
3554         fprintf(log, "SalvageLog:\n%s", logData);
3555     }
3556
3557     /*
3558      * Restart the fileserver if we had stopped it previously
3559      */
3560
3561     if (try_to_stop_fileserver) {
3562         try_to_stop_fileserver = 0;
3563         if (!bos_ProcessExecutionStateSetTemporary
3564             (serverHandle, "fs", BOS_PROCESS_RUNNING, &tst)) {
3565             goto fail_bos_Salvage;
3566         }
3567     }
3568     rc = 1;
3569
3570   fail_bos_Salvage:
3571
3572     if (log != NULL) {
3573         fclose(log);
3574     }
3575
3576     if (logData != NULL) {
3577         free(logData);
3578     }
3579
3580     if (try_to_stop_fileserver) {
3581         bos_ProcessExecutionStateSetTemporary(serverHandle, "fs",
3582                                               BOS_PROCESS_RUNNING, 0);
3583     }
3584
3585     if (st != NULL) {
3586         *st = tst;
3587     }
3588     return rc;
3589 }