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