butc: Initialize RPC outputs at top of function
[openafs.git] / src / butc / tcprocs.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 /* procedures invoked by the rpc stub */
11
12 #include <afsconfig.h>
13 #include <afs/param.h>
14
15 #include <afs/procmgmt.h>
16 #include <roken.h>
17
18 #include <afs/opr.h>
19 #include <rx/rx.h>
20 #include <afs/afsint.h>
21 #include <afs/prs_fs.h>
22 #include <afs/nfs.h>
23 #include <lwp.h>
24 #include <lock.h>
25 #include <afs/cellconfig.h>
26 #include <afs/keys.h>
27 #include <ubik.h>
28 #include <afs/tcdata.h>
29 #include <afs/budb_client.h>
30 #include <afs/bucoord_prototypes.h>
31
32 #include "error_macros.h"
33 #include "butc_xbsa.h"
34 #include "butc_prototypes.h"
35 #include "butc_internal.h"
36 #include "afs/audit.h"
37
38 static int CopyDumpDesc(struct tc_dumpDesc *, tc_dumpArray *);
39 static int CopyRestoreDesc(struct tc_restoreDesc *, tc_restoreArray *);
40 static int CopyTapeSetDesc(struct tc_tapeSet *, struct tc_tapeSet *);
41
42 /* Helpers implementing RPC backends */
43 static afs_int32 SLabelTape(struct rx_call *acid, struct tc_tapeLabel *label,
44                             afs_uint32 *taskId);
45 static afs_int32 SPerformDump(struct rx_call *rxCallId,
46                               struct tc_dumpInterface *tcdiPtr,
47                               tc_dumpArray *tc_dumpArrayPtr, afs_int32 *taskId);
48 static afs_int32 SPerformRestore(struct rx_call *acid, char *dumpSetName,
49                                  tc_restoreArray *arestores, afs_int32 *taskId);
50 static afs_int32 SReadLabel(struct rx_call *acid, struct tc_tapeLabel *label,
51                             afs_uint32 *taskId);
52 static afs_int32 SRestoreDb(struct rx_call *rxCall, afs_uint32 *taskId);
53 static afs_int32 SSaveDb(struct rx_call *rxCall, Date archiveTime,
54                          afs_uint32 *taskId);
55 static afs_int32 SScanDumps(struct rx_call *acid, afs_int32 addDbFlag,
56                             afs_uint32 *taskId);
57 static afs_int32 STCInfo(struct rx_call *acid, struct tc_tcInfo *tciptr);
58 static afs_int32 SDeleteDump(struct rx_call *acid, afs_uint32 dumpID,
59                              afs_uint32 *taskId);
60
61 int
62 callPermitted(struct rx_call *call)
63 {
64     /*
65      * If in backwards compat mode, allow anyone; otherwise, only
66      * superusers are allowed.
67      */
68     if (allow_unauth)
69         return 1;
70     return afsconf_SuperIdentity(butc_confdir, call, NULL);
71 }
72
73 /* -----------------------------
74  * misc. routines
75  * -----------------------------
76  */
77
78 static int
79 CopyDumpDesc(struct tc_dumpDesc *toDump, tc_dumpArray *fromDump)
80 {
81     struct tc_dumpDesc *toPtr, *fromPtr;
82     int i;
83
84     toPtr = toDump;
85     fromPtr = fromDump->tc_dumpArray_val;
86     for (i = 0; i < fromDump->tc_dumpArray_len; i++) {
87         toPtr->vid = fromPtr->vid;
88         toPtr->vtype = fromPtr->vtype;
89         toPtr->partition = fromPtr->partition;
90         toPtr->date = fromPtr->date;
91         toPtr->cloneDate = fromPtr->cloneDate;
92         toPtr->hostAddr = fromPtr->hostAddr;
93         strcpy(toPtr->name, fromPtr->name);
94         fromPtr++;
95         toPtr++;
96     }
97     return 0;
98 }
99
100
101 static int
102 CopyRestoreDesc(struct tc_restoreDesc *toRestore, tc_restoreArray *fromRestore)
103 {
104     struct tc_restoreDesc *toPtr, *fromPtr;
105     int i;
106
107     toPtr = toRestore;
108     fromPtr = fromRestore->tc_restoreArray_val;
109     for (i = 0; i < fromRestore->tc_restoreArray_len; i++) {
110         toPtr->flags = fromPtr->flags;
111         toPtr->position = fromPtr->position;
112         strcpy(toPtr->tapeName, fromPtr->tapeName);
113         toPtr->dbDumpId = fromPtr->dbDumpId;
114         toPtr->initialDumpId = fromPtr->initialDumpId;
115         toPtr->origVid = fromPtr->origVid;
116         toPtr->vid = fromPtr->vid;
117         toPtr->partition = fromPtr->partition;
118         toPtr->dumpLevel = fromPtr->dumpLevel;
119         toPtr->hostAddr = fromPtr->hostAddr;
120         strcpy(toPtr->newName, fromPtr->newName);
121         strcpy(toPtr->oldName, fromPtr->oldName);
122         fromPtr++;
123         toPtr++;
124
125     }
126     return 0;
127 }
128
129 static int
130 CopyTapeSetDesc(struct tc_tapeSet *toPtr, struct tc_tapeSet *fromPtr)
131 {
132
133     toPtr->id = fromPtr->id;
134     toPtr->maxTapes = fromPtr->maxTapes;
135     toPtr->a = fromPtr->a;
136     toPtr->b = fromPtr->b;
137     strcpy(toPtr->tapeServer, fromPtr->tapeServer);
138     strcpy(toPtr->format, fromPtr->format);
139
140     toPtr->expDate = fromPtr->expDate;
141     toPtr->expType = fromPtr->expType;
142     return 0;
143 }
144
145 /* -------------------------
146  * butc - interface routines - alphabetic order
147  * -------------------------
148  */
149
150 afs_int32
151 STC_LabelTape(struct rx_call *acid, struct tc_tapeLabel *label, afs_uint32 *taskId)
152 {
153     afs_int32 code;
154
155     code = SLabelTape(acid, label, taskId);
156     osi_auditU(acid, TC_LabelTapeEvent, code,
157                AUD_TLBL, label, AUD_INT, *taskId, AUD_END);
158     return code;
159 }
160
161 static afs_int32
162 SLabelTape(struct rx_call *acid, struct tc_tapeLabel *label, afs_uint32 *taskId)
163 {
164 #ifdef AFS_PTHREAD_ENV
165     pthread_t pid;
166     pthread_attr_t tattr;
167     AFS_SIGSET_DECL;
168 #else
169     PROCESS pid;
170 #endif
171     struct labelTapeIf *ptr;
172     statusP statusPtr = NULL;
173     afs_int32 code;
174
175     *taskId = 0;
176 #ifdef xbsa
177     if (CONF_XBSA)
178         return (TC_BADTASK);    /* LabelTape does not apply if XBSA */
179 #endif
180
181     if (callPermitted(acid) == 0)
182         return (TC_NOTPERMITTED);
183
184     ptr = malloc(sizeof(*ptr));
185     if (!ptr)
186         ERROR_EXIT(TC_NOMEMORY);
187     memcpy(&ptr->label, label, sizeof(ptr->label));
188
189     /* set up the status node */
190     *taskId = allocTaskId();    /* for bucoord */
191     ptr->taskId = *taskId;
192
193     statusPtr = createStatusNode();
194     if (!statusPtr)
195         ERROR_EXIT(TC_INTERNALERROR);
196
197     lock_Status();
198     statusPtr->taskId = *taskId;
199     statusPtr->lastPolled = time(0);
200     statusPtr->flags &= ~STARTING;      /* ok to examine */
201     strncpy(statusPtr->taskName, "Labeltape", sizeof(statusPtr->taskName));
202     unlock_Status();
203
204     /* create the LWP to do the real work behind the scenes */
205 #ifdef AFS_PTHREAD_ENV
206     code = pthread_attr_init(&tattr);
207     if (code)
208         ERROR_EXIT(code);
209
210     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
211     if (code)
212         ERROR_EXIT(code);
213
214     AFS_SIGSET_CLEAR();
215     code = pthread_create(&pid, &tattr, Labeller, ptr);
216     AFS_SIGSET_RESTORE();
217 #else
218     code =
219         LWP_CreateProcess(Labeller, 32768, 1, (void *)ptr, "labeller process",
220                           &pid);
221 #endif
222
223   error_exit:
224     if (code) {
225         if (statusPtr)
226             deleteStatusNode(statusPtr);
227         if (ptr)
228             free(ptr);
229     }
230
231     return (code);
232 }
233
234 /* STC_PerformDump
235  *      Tape coordinator server routine to do a dump
236  */
237
238 afs_int32
239 STC_PerformDump(struct rx_call *call, struct tc_dumpInterface *di,
240                 tc_dumpArray *da, afs_int32 *taskId)
241 {
242     afs_int32 code;
243
244     code = SPerformDump(call, di, da, taskId);
245     osi_auditU(call, TC_PerformDumpEvent, code,
246                AUD_TDI, di, AUD_TDA, da, AUD_INT, *taskId, AUD_END);
247     return code;
248 }
249
250 static afs_int32
251 SPerformDump(struct rx_call *rxCallId, struct tc_dumpInterface *tcdiPtr,
252              tc_dumpArray *tc_dumpArrayPtr, afs_int32 *taskId)
253 {
254     struct dumpNode *newNode = 0;
255     statusP statusPtr = 0;
256 #ifdef AFS_PTHREAD_ENV
257     pthread_t pid;
258     pthread_attr_t tattr;
259     AFS_SIGSET_DECL;
260 #else
261     PROCESS pid;
262 #endif
263     afs_int32 code = 0;
264
265     /* should be verifying parameter validity */
266     *taskId = 0;
267
268     if (callPermitted(rxCallId) == 0)
269         return (TC_NOTPERMITTED);
270
271     /* this creates a node in list, alots an id for it and prepares it for locking */
272     CreateNode(&newNode);
273
274     /*set up the parameters in the node, to be used by LWP */
275     strcpy(newNode->dumpSetName, tcdiPtr->dumpName);
276
277     newNode->dumpName = strdup(tcdiPtr->dumpPath);
278     newNode->volumeSetName = strdup(tcdiPtr->volumeSetName);
279
280     CopyTapeSetDesc(&(newNode->tapeSetDesc), &tcdiPtr->tapeSet);
281
282     newNode->dumps = malloc(sizeof(struct tc_dumpDesc) *
283                             tc_dumpArrayPtr->tc_dumpArray_len);
284     newNode->arraySize = tc_dumpArrayPtr->tc_dumpArray_len;
285     CopyDumpDesc(newNode->dumps, tc_dumpArrayPtr);
286
287     newNode->parent = tcdiPtr->parentDumpId;
288     newNode->level = tcdiPtr->dumpLevel;
289     newNode->doAppend = tcdiPtr->doAppend;
290 #ifdef xbsa
291     if (CONF_XBSA)
292         newNode->doAppend = 0;  /* Append flag is ignored if talking to XBSA */
293 #endif
294
295     /* create the status node */
296     statusPtr = createStatusNode();
297     if (!statusPtr)
298         ERROR_EXIT(TC_INTERNALERROR);
299
300     lock_Status();
301     statusPtr->taskId = newNode->taskID;
302     statusPtr->lastPolled = time(0);
303     statusPtr->flags &= ~STARTING;      /* ok to examine */
304     strncpy(statusPtr->taskName, "Dump", sizeof(statusPtr->taskName));
305     unlock_Status();
306
307     newNode->statusNodePtr = statusPtr;
308
309     /* create the LWP to do the real work behind the scenes */
310 #ifdef AFS_PTHREAD_ENV
311     code = pthread_attr_init(&tattr);
312     if (code)
313         ERROR_EXIT(code);
314
315     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
316     if (code)
317         ERROR_EXIT(code);
318
319     AFS_SIGSET_CLEAR();
320     code = pthread_create(&pid, &tattr, Dumper, newNode);
321     AFS_SIGSET_RESTORE();
322 #else
323     code =
324         LWP_CreateProcess(Dumper, 32768, 1, (void *)newNode, "dumper process",
325                           &pid);
326 #endif
327     if (code)
328         ERROR_EXIT(code);
329
330     *taskId = newNode->taskID;
331
332   error_exit:
333     if (code) {
334         if (statusPtr)
335             deleteStatusNode(statusPtr);
336         FreeNode(newNode->taskID);      /*  failed to create LWP to do the dump. */
337     }
338
339     return (code);
340 }
341
342 afs_int32
343 STC_PerformRestore(struct rx_call *call, char *dumpSetName,
344                    tc_restoreArray *ra, afs_int32 *taskId)
345 {
346     afs_int32 code;
347
348     code = SPerformRestore(call, dumpSetName, ra, taskId);
349     osi_auditU(call, TC_PerformRestoreEvent, code,
350                AUD_STR, dumpSetName, AUD_TRA, ra, AUD_INT, *taskId, AUD_END);
351     return code;
352 }
353
354 static afs_int32
355 SPerformRestore(struct rx_call *acid, char *dumpSetName,
356                 tc_restoreArray *arestores, afs_int32 *taskID)
357 {
358     struct dumpNode *newNode;
359     statusP statusPtr;
360     afs_int32 code = 0;
361 #ifdef AFS_PTHREAD_ENV
362     pthread_t pid;
363     pthread_attr_t tattr;
364     AFS_SIGSET_DECL;
365 #else
366     PROCESS pid;
367 #endif
368
369     *taskID = 0;
370
371     if (callPermitted(acid) == 0)
372         return (TC_NOTPERMITTED);
373
374     /* should  verify parameter validity */
375
376     /* this creates a node in list, alots an id for it and prepares it for locking */
377     CreateNode(&newNode);
378
379     newNode->restores = malloc(sizeof(struct tc_restoreDesc) *
380                                arestores->tc_restoreArray_len);
381     newNode->arraySize = arestores->tc_restoreArray_len;
382     CopyRestoreDesc(newNode->restores, arestores);
383     *taskID = newNode->taskID;
384
385     /* should log the intent */
386
387     /* create the status node */
388     statusPtr = createStatusNode();
389     if (!statusPtr)
390         ERROR_EXIT(TC_INTERNALERROR);
391
392     lock_Status();
393     statusPtr->taskId = newNode->taskID;
394     statusPtr->flags &= ~STARTING;      /* ok to examine */
395     statusPtr->lastPolled = time(0);
396     strncpy(statusPtr->taskName, "Restore", sizeof(statusPtr->taskName));
397     unlock_Status();
398
399     newNode->statusNodePtr = statusPtr;
400
401     /* create the LWP to do the real work behind the scenes */
402 #ifdef AFS_PTHREAD_ENV
403     code = pthread_attr_init(&tattr);
404     if (code)
405         ERROR_EXIT(code);
406
407     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
408     if (code)
409         ERROR_EXIT(code);
410
411     AFS_SIGSET_CLEAR();
412     code = pthread_create(&pid, &tattr, Restorer, newNode);
413     AFS_SIGSET_RESTORE();
414 #else
415     code =
416         LWP_CreateProcess(Restorer, 65368, 1, (void *)newNode,
417                           "restorer process", &pid);
418 #endif
419
420   error_exit:
421     if (code) {
422         if (statusPtr)
423             deleteStatusNode(statusPtr);
424         FreeNode(newNode->taskID);      /*  failed to create LWP to do the dump. */
425     }
426
427     return (code);
428 }
429
430 afs_int32
431 STC_ReadLabel(struct rx_call *call, struct tc_tapeLabel *label, afs_uint32 *taskId)
432 {
433     afs_int32 code;
434
435     code = SReadLabel(call, label, taskId);
436     osi_auditU(call, TC_ReadLabelEvent, code,
437                AUD_TLBL, label, AUD_INT, *taskId, AUD_END);
438     return code;
439 }
440
441 static afs_int32
442 SReadLabel(struct rx_call *acid, struct tc_tapeLabel *label, afs_uint32 *taskId)
443 {
444     afs_int32 code;
445
446     memset(label, 0, sizeof(*label));
447     /* Synchronous, so no "real" ID; don't send stack garbage on the wire */
448     *taskId = 0;
449 #ifdef xbsa
450     if (CONF_XBSA)
451         return (TC_BADTASK);    /* ReadLabel does not apply if XBSA */
452 #endif
453
454     if (callPermitted(acid) == 0)
455         return (TC_NOTPERMITTED);
456
457     code = ReadLabel(label);    /* Synchronous */
458     return code;
459 }
460
461 /* STC_RestoreDb
462  *      restore the backup database from tape
463  */
464
465 afs_int32
466 STC_RestoreDb(struct rx_call *call, afs_uint32 *taskId)
467 {
468     afs_int32 code;
469
470     code = SRestoreDb(call, taskId);
471     osi_auditU(call, TC_RestoreDbEvent, code, AUD_INT, *taskId, AUD_END);
472     return code;
473 }
474
475 static afs_int32
476 SRestoreDb(struct rx_call *rxCall, afs_uint32 *taskId)
477 {
478 #ifdef AFS_PTHREAD_ENV
479     pthread_t pid;
480     pthread_attr_t tattr;
481     AFS_SIGSET_DECL;
482 #else
483     PROCESS pid;
484 #endif
485     statusP statusPtr;
486     afs_int32 code = 0;
487
488     *taskId = 0;
489
490 #ifdef xbsa
491     if (CONF_XBSA)
492         return (TC_BADTASK);    /* LabelTape does not apply if XBSA */
493 #endif
494
495     if (callPermitted(rxCall) == 0)
496         return (TC_NOTPERMITTED);
497
498     *taskId = allocTaskId();
499
500     /* create the status node */
501     statusPtr = createStatusNode();
502     if (!statusPtr)
503         ERROR_EXIT(TC_INTERNALERROR);
504
505     lock_Status();
506     statusPtr->taskId = *taskId;
507     statusPtr->flags &= ~STARTING;      /* ok to examine */
508     statusPtr->lastPolled = time(0);
509     strncpy(statusPtr->taskName, "RestoreDb", sizeof(statusPtr->taskName));
510     unlock_Status();
511
512 #ifdef AFS_PTHREAD_ENV
513     code = pthread_attr_init(&tattr);
514     if (code)
515         ERROR_EXIT(code);
516
517     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
518     if (code)
519         ERROR_EXIT(code);
520
521     AFS_SIGSET_CLEAR();
522     code = pthread_create(&pid, &tattr, restoreDbFromTape, (void *)(intptr_t)*taskId);
523     AFS_SIGSET_RESTORE();
524 #else
525     code =
526         LWP_CreateProcess(restoreDbFromTape, 32768, 1, (void *)(intptr_t)*taskId,
527                           "Db restore", &pid);
528 #endif
529
530   error_exit:
531     if (code) {
532         if (statusPtr)
533             deleteStatusNode(statusPtr);
534     }
535
536     return (code);
537 }
538
539 /* STC_SaveDb
540  *      restore the backup database from tape
541  */
542
543 afs_int32
544 STC_SaveDb(struct rx_call *call, Date archiveTime, afs_uint32 *taskId)
545 {
546     afs_int32 code;
547
548     code = SSaveDb(call, archiveTime, taskId);
549     osi_auditU(call, TC_SaveDbEvent, code,
550                AUD_DATE, archiveTime, AUD_INT, *taskId, AUD_END);
551     return code;
552 }
553
554 static afs_int32
555 SSaveDb(struct rx_call *rxCall, Date archiveTime, afs_uint32 *taskId)
556 {
557 #ifdef AFS_PTHREAD_ENV
558     pthread_t pid;
559     pthread_attr_t tattr;
560     AFS_SIGSET_DECL;
561 #else
562     PROCESS pid;
563 #endif
564     statusP statusPtr = NULL;
565     afs_int32 code = 0;
566     struct saveDbIf *ptr;
567
568     *taskId = 0;
569
570 #ifdef xbsa
571     if (CONF_XBSA)
572         return (TC_BADTASK);    /* LabelTape does not apply if XBSA */
573 #endif
574
575     if (callPermitted(rxCall) == 0)
576         return (TC_NOTPERMITTED);
577
578     *taskId = allocTaskId();
579
580     ptr = malloc(sizeof(struct saveDbIf));
581     if (!ptr)
582         ERROR_EXIT(TC_NOMEMORY);
583     ptr->archiveTime = archiveTime;
584     ptr->taskId = *taskId;
585
586     /* create the status node */
587     statusPtr = createStatusNode();
588     if (!statusPtr)
589         ERROR_EXIT(TC_INTERNALERROR);
590
591     lock_Status();
592     statusPtr->taskId = *taskId;
593     statusPtr->lastPolled = time(0);
594     statusPtr->flags &= ~STARTING;      /* ok to examine */
595     strncpy(statusPtr->taskName, "SaveDb", sizeof(statusPtr->taskName));
596     unlock_Status();
597
598     ptr->statusPtr = statusPtr;
599
600 #ifdef AFS_PTHREAD_ENV
601     code = pthread_attr_init(&tattr);
602     if (code)
603         ERROR_EXIT(code);
604
605     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
606     if (code)
607         ERROR_EXIT(code);
608
609     AFS_SIGSET_CLEAR();
610     code = pthread_create(&pid, &tattr, saveDbToTape, ptr);
611     AFS_SIGSET_RESTORE();
612 #else
613     code = LWP_CreateProcess(saveDbToTape, 32768, 1, ptr, "Db save", &pid);
614 #endif
615
616   error_exit:
617     if (code) {
618         if (statusPtr)
619             deleteStatusNode(statusPtr);
620         if (ptr)
621             free(ptr);
622     }
623
624     return (code);
625 }
626
627
628 /* STC_ScanDumps
629  *      read a dump (maybe more than one tape), and print out a summary
630  *      of its contents. If the flag is set, add to the database.
631  * entry:
632  *      addDbFlag - if set, the information will be added to the database
633  */
634
635 afs_int32
636 STC_ScanDumps(struct rx_call *call, afs_int32 addDbFlag, afs_uint32 *taskId)
637 {
638     afs_int32 code;
639
640     code = SScanDumps(call, addDbFlag, taskId);
641     osi_auditU(call, TC_ScanDumpsEvent, code,
642                AUD_INT, addDbFlag, AUD_INT, *taskId, AUD_END);
643     return code;
644 }
645
646 static afs_int32
647 SScanDumps(struct rx_call *acid, afs_int32 addDbFlag, afs_uint32 *taskId)
648 {
649 #ifdef AFS_PTHREAD_ENV
650     pthread_t pid;
651     pthread_attr_t tattr;
652     AFS_SIGSET_DECL;
653 #else
654     PROCESS pid;
655 #endif
656     struct scanTapeIf *ptr;
657     statusP statusPtr = NULL;
658     afs_int32 code = 0;
659
660     *taskId = 0;
661
662 #ifdef xbsa
663     if (CONF_XBSA)
664         return (TC_BADTASK);    /* ScanDumps does not apply if XBSA */
665 #endif
666
667     if (callPermitted(acid) == 0)
668         return (TC_NOTPERMITTED);
669
670     *taskId = allocTaskId();
671
672     ptr = malloc(sizeof(*ptr));
673     if (!ptr)
674         ERROR_EXIT(TC_NOMEMORY);
675     ptr->addDbFlag = addDbFlag;
676     ptr->taskId = *taskId;
677
678     /* create the status node */
679     statusPtr = createStatusNode();
680     if (!statusPtr)
681         ERROR_EXIT(TC_INTERNALERROR);
682
683     lock_Status();
684     statusPtr->taskId = *taskId;
685     statusPtr->lastPolled = time(0);
686     statusPtr->flags &= ~STARTING;      /* ok to examine */
687     strncpy(statusPtr->taskName, "Scantape", sizeof(statusPtr->taskName));
688     unlock_Status();
689
690 #ifdef AFS_PTHREAD_ENV
691     code = pthread_attr_init(&tattr);
692     if (code)
693         ERROR_EXIT(code);
694
695     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
696     if (code)
697         ERROR_EXIT(code);
698
699     AFS_SIGSET_CLEAR();
700     code = pthread_create(&pid, &tattr, ScanDumps, ptr);
701     AFS_SIGSET_RESTORE();
702 #else
703     code =
704         LWP_CreateProcess(ScanDumps, 32768, 1, ptr, "scandump process", &pid);
705 #endif
706
707   error_exit:
708     if (code) {
709         if (statusPtr)
710             deleteStatusNode(statusPtr);
711         if (ptr)
712             free(ptr);
713     }
714
715     return code;
716 }
717
718 /* STC_TCInfo
719  *      return information about the tape coordinator. Currently this
720  *      is just the version number of the interface
721  */
722
723 afs_int32
724 STC_TCInfo(struct rx_call *call, struct tc_tcInfo *ti)
725 {
726     afs_int32 code;
727
728     code = STCInfo(call, ti);
729     osi_auditU(call, TC_TCInfoEvent, code, AUD_INT, ti->tcVersion, AUD_END);
730     return code;
731 }
732
733 static afs_int32
734 STCInfo(struct rx_call *acid, struct tc_tcInfo *tciptr)
735 {
736     memset(tciptr, 0, sizeof(*tciptr));
737
738     if (callPermitted(acid) == 0)
739         return (TC_NOTPERMITTED);
740
741     tciptr->tcVersion = CUR_BUTC_VERSION;
742     return (0);
743 }
744
745 /* STC_DeleteDump
746  */
747 afs_int32
748 STC_DeleteDump(struct rx_call *call, afs_uint32 dumpID, afs_uint32 *taskId)
749 {
750     afs_int32 code;
751
752     code = SDeleteDump(call, dumpID, taskId);
753     osi_auditU(call, TC_DeleteDumpEvent, code,
754                AUD_DATE, dumpID, AUD_INT, *taskId, AUD_END);
755     return code;
756 }
757
758 static afs_int32
759 SDeleteDump(struct rx_call *acid, afs_uint32 dumpID, afs_uint32 *taskId)
760 {
761     afs_int32 code = TC_BADTASK;        /* If not compiled -Dxbsa then fail */
762 #ifdef xbsa
763     struct deleteDumpIf *ptr = 0;
764     statusP statusPtr = 0;
765 #ifdef AFS_PTHREAD_ENV
766     pthread_t pid;
767     pthread_attr_t tattr;
768     AFS_SIGSET_DECL;
769 #else
770     PROCESS pid;
771 #endif
772 #endif
773
774     *taskId = 0;
775
776     if (!CONF_XBSA)
777         return (TC_BADTASK);    /* Only do if butc is started as XBSA */
778
779 #ifdef xbsa
780     code = 0;
781     if (callPermitted(acid) == 0)
782         return (TC_NOTPERMITTED);
783
784     ptr = malloc(sizeof(*ptr));
785     if (!ptr)
786         ERROR_EXIT(TC_NOMEMORY);
787
788     *taskId = allocTaskId();
789     ptr->dumpID = dumpID;
790     ptr->taskId = *taskId;
791
792     statusPtr = createStatusNode();
793     if (!statusPtr)
794         ERROR_EXIT(TC_INTERNALERROR);
795
796     lock_Status();
797     statusPtr->taskId = *taskId;
798     statusPtr->lastPolled = time(0);
799     statusPtr->flags &= ~STARTING;
800     strncpy(statusPtr->taskName, "DeleteDump", sizeof(statusPtr->taskName));
801     unlock_Status();
802
803 #ifdef AFS_PTHREAD_ENV
804     code = pthread_attr_init(&tattr);
805     if (code)
806         ERROR_EXIT(code);
807
808     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
809     if (code)
810         ERROR_EXIT(code);
811
812     AFS_SIGSET_CLEAR();
813     code = pthread_create(&pid, &tattr, DeleteDump, ptr);
814     AFS_SIGSET_RESTORE();
815 #else
816     code =
817         LWP_CreateProcess(DeleteDump, 32768, 1, ptr, "deletedump process",
818                           &pid);
819 #endif
820
821   error_exit:
822     if (code) {
823         if (statusPtr)
824             deleteStatusNode(statusPtr);
825         if (ptr)
826             free(ptr);
827     }
828 #endif /* xbsa */
829
830     return (code);
831 }
832