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