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