7f0e40c86e8d6b9d45f8dff546dd40e5bbf3da59
[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      * Before this code can be used, the rx connection, on the bucoord side,
66      * must be changed so that it will set up for token passing instead of
67      * using a simple rx connection that, below, returns a value of
68      * RX_SECIDX_NULL from rx_SecurityClassOf.
69      */
70     return 1;
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 #ifdef xbsa
176     if (CONF_XBSA)
177         return (TC_BADTASK);    /* LabelTape does not apply if XBSA */
178 #endif
179
180     if (callPermitted(acid) == 0)
181         return (TC_NOTPERMITTED);
182
183     ptr = malloc(sizeof(*ptr));
184     if (!ptr)
185         ERROR_EXIT(TC_NOMEMORY);
186     memcpy(&ptr->label, label, sizeof(ptr->label));
187
188     /* set up the status node */
189     *taskId = allocTaskId();    /* for bucoord */
190     ptr->taskId = *taskId;
191
192     statusPtr = createStatusNode();
193     if (!statusPtr)
194         ERROR_EXIT(TC_INTERNALERROR);
195
196     lock_Status();
197     statusPtr->taskId = *taskId;
198     statusPtr->lastPolled = time(0);
199     statusPtr->flags &= ~STARTING;      /* ok to examine */
200     strncpy(statusPtr->taskName, "Labeltape", sizeof(statusPtr->taskName));
201     unlock_Status();
202
203     /* create the LWP to do the real work behind the scenes */
204 #ifdef AFS_PTHREAD_ENV
205     code = pthread_attr_init(&tattr);
206     if (code)
207         ERROR_EXIT(code);
208
209     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
210     if (code)
211         ERROR_EXIT(code);
212
213     AFS_SIGSET_CLEAR();
214     code = pthread_create(&pid, &tattr, Labeller, ptr);
215     AFS_SIGSET_RESTORE();
216 #else
217     code =
218         LWP_CreateProcess(Labeller, 32768, 1, (void *)ptr, "labeller process",
219                           &pid);
220 #endif
221
222   error_exit:
223     if (code) {
224         if (statusPtr)
225             deleteStatusNode(statusPtr);
226         if (ptr)
227             free(ptr);
228     }
229
230     return (code);
231 }
232
233 /* STC_PerformDump
234  *      Tape coordinator server routine to do a dump
235  */
236
237 afs_int32
238 STC_PerformDump(struct rx_call *call, struct tc_dumpInterface *di,
239                 tc_dumpArray *da, afs_int32 *taskId)
240 {
241     afs_int32 code;
242
243     code = SPerformDump(call, di, da, taskId);
244     osi_auditU(call, TC_PerformDumpEvent, code,
245                AUD_TDI, di, AUD_TDA, da, AUD_INT, *taskId, AUD_END);
246     return code;
247 }
248
249 static afs_int32
250 SPerformDump(struct rx_call *rxCallId, struct tc_dumpInterface *tcdiPtr,
251              tc_dumpArray *tc_dumpArrayPtr, afs_int32 *taskId)
252 {
253     struct dumpNode *newNode = 0;
254     statusP statusPtr = 0;
255 #ifdef AFS_PTHREAD_ENV
256     pthread_t pid;
257     pthread_attr_t tattr;
258     AFS_SIGSET_DECL;
259 #else
260     PROCESS pid;
261 #endif
262     afs_int32 code = 0;
263
264     if (callPermitted(rxCallId) == 0)
265         return (TC_NOTPERMITTED);
266
267     /* should be verifying parameter validity */
268     *taskId = 0;
269
270     /* this creates a node in list, alots an id for it and prepares it for locking */
271     CreateNode(&newNode);
272
273     /*set up the parameters in the node, to be used by LWP */
274     strcpy(newNode->dumpSetName, tcdiPtr->dumpName);
275
276     newNode->dumpName = strdup(tcdiPtr->dumpPath);
277     newNode->volumeSetName = strdup(tcdiPtr->volumeSetName);
278
279     CopyTapeSetDesc(&(newNode->tapeSetDesc), &tcdiPtr->tapeSet);
280
281     newNode->dumps = malloc(sizeof(struct tc_dumpDesc) *
282                             tc_dumpArrayPtr->tc_dumpArray_len);
283     newNode->arraySize = tc_dumpArrayPtr->tc_dumpArray_len;
284     CopyDumpDesc(newNode->dumps, tc_dumpArrayPtr);
285
286     newNode->parent = tcdiPtr->parentDumpId;
287     newNode->level = tcdiPtr->dumpLevel;
288     newNode->doAppend = tcdiPtr->doAppend;
289 #ifdef xbsa
290     if (CONF_XBSA)
291         newNode->doAppend = 0;  /* Append flag is ignored if talking to XBSA */
292 #endif
293
294     /* create the status node */
295     statusPtr = createStatusNode();
296     if (!statusPtr)
297         ERROR_EXIT(TC_INTERNALERROR);
298
299     lock_Status();
300     statusPtr->taskId = newNode->taskID;
301     statusPtr->lastPolled = time(0);
302     statusPtr->flags &= ~STARTING;      /* ok to examine */
303     strncpy(statusPtr->taskName, "Dump", sizeof(statusPtr->taskName));
304     unlock_Status();
305
306     newNode->statusNodePtr = statusPtr;
307
308     /* create the LWP to do the real work behind the scenes */
309 #ifdef AFS_PTHREAD_ENV
310     code = pthread_attr_init(&tattr);
311     if (code)
312         ERROR_EXIT(code);
313
314     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
315     if (code)
316         ERROR_EXIT(code);
317
318     AFS_SIGSET_CLEAR();
319     code = pthread_create(&pid, &tattr, Dumper, newNode);
320     AFS_SIGSET_RESTORE();
321 #else
322     code =
323         LWP_CreateProcess(Dumper, 32768, 1, (void *)newNode, "dumper process",
324                           &pid);
325 #endif
326     if (code)
327         ERROR_EXIT(code);
328
329     *taskId = newNode->taskID;
330
331   error_exit:
332     if (code) {
333         if (statusPtr)
334             deleteStatusNode(statusPtr);
335         FreeNode(newNode->taskID);      /*  failed to create LWP to do the dump. */
336     }
337
338     return (code);
339 }
340
341 afs_int32
342 STC_PerformRestore(struct rx_call *call, char *dumpSetName,
343                    tc_restoreArray *ra, afs_int32 *taskId)
344 {
345     afs_int32 code;
346
347     code = SPerformRestore(call, dumpSetName, ra, taskId);
348     osi_auditU(call, TC_PerformRestoreEvent, code,
349                AUD_STR, dumpSetName, AUD_TRA, ra, AUD_INT, *taskId, AUD_END);
350     return code;
351 }
352
353 static afs_int32
354 SPerformRestore(struct rx_call *acid, char *dumpSetName,
355                 tc_restoreArray *arestores, afs_int32 *taskID)
356 {
357     struct dumpNode *newNode;
358     statusP statusPtr;
359     afs_int32 code = 0;
360 #ifdef AFS_PTHREAD_ENV
361     pthread_t pid;
362     pthread_attr_t tattr;
363     AFS_SIGSET_DECL;
364 #else
365     PROCESS pid;
366 #endif
367
368     if (callPermitted(acid) == 0)
369         return (TC_NOTPERMITTED);
370
371     /* should  verify parameter validity */
372
373     /* this creates a node in list, alots an id for it and prepares it for locking */
374     CreateNode(&newNode);
375
376     newNode->restores = malloc(sizeof(struct tc_restoreDesc) *
377                                arestores->tc_restoreArray_len);
378     newNode->arraySize = arestores->tc_restoreArray_len;
379     CopyRestoreDesc(newNode->restores, arestores);
380     *taskID = newNode->taskID;
381
382     /* should log the intent */
383
384     /* create the status node */
385     statusPtr = createStatusNode();
386     if (!statusPtr)
387         ERROR_EXIT(TC_INTERNALERROR);
388
389     lock_Status();
390     statusPtr->taskId = newNode->taskID;
391     statusPtr->flags &= ~STARTING;      /* ok to examine */
392     statusPtr->lastPolled = time(0);
393     strncpy(statusPtr->taskName, "Restore", sizeof(statusPtr->taskName));
394     unlock_Status();
395
396     newNode->statusNodePtr = statusPtr;
397
398     /* create the LWP to do the real work behind the scenes */
399 #ifdef AFS_PTHREAD_ENV
400     code = pthread_attr_init(&tattr);
401     if (code)
402         ERROR_EXIT(code);
403
404     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
405     if (code)
406         ERROR_EXIT(code);
407
408     AFS_SIGSET_CLEAR();
409     code = pthread_create(&pid, &tattr, Restorer, newNode);
410     AFS_SIGSET_RESTORE();
411 #else
412     code =
413         LWP_CreateProcess(Restorer, 65368, 1, (void *)newNode,
414                           "restorer process", &pid);
415 #endif
416
417   error_exit:
418     if (code) {
419         if (statusPtr)
420             deleteStatusNode(statusPtr);
421         FreeNode(newNode->taskID);      /*  failed to create LWP to do the dump. */
422     }
423
424     return (code);
425 }
426
427 afs_int32
428 STC_ReadLabel(struct rx_call *call, struct tc_tapeLabel *label, afs_uint32 *taskId)
429 {
430     afs_int32 code;
431
432     code = SReadLabel(call, label, taskId);
433     osi_auditU(call, TC_ReadLabelEvent, code,
434                AUD_TLBL, label, AUD_INT, *taskId, AUD_END);
435     return code;
436 }
437
438 static afs_int32
439 SReadLabel(struct rx_call *acid, struct tc_tapeLabel *label, afs_uint32 *taskId)
440 {
441     afs_int32 code;
442
443     memset(label, 0, sizeof(*label));
444     /* Synchronous, so no "real" ID; don't send stack garbage on the wire */
445     *taskId = 0;
446 #ifdef xbsa
447     if (CONF_XBSA)
448         return (TC_BADTASK);    /* ReadLabel does not apply if XBSA */
449 #endif
450
451     if (callPermitted(acid) == 0)
452         return (TC_NOTPERMITTED);
453
454     code = ReadLabel(label);    /* Synchronous */
455     return code;
456 }
457
458 /* STC_RestoreDb
459  *      restore the backup database from tape
460  */
461
462 afs_int32
463 STC_RestoreDb(struct rx_call *call, afs_uint32 *taskId)
464 {
465     afs_int32 code;
466
467     code = SRestoreDb(call, taskId);
468     osi_auditU(call, TC_RestoreDbEvent, code, AUD_INT, *taskId, AUD_END);
469     return code;
470 }
471
472 static afs_int32
473 SRestoreDb(struct rx_call *rxCall, afs_uint32 *taskId)
474 {
475 #ifdef AFS_PTHREAD_ENV
476     pthread_t pid;
477     pthread_attr_t tattr;
478     AFS_SIGSET_DECL;
479 #else
480     PROCESS pid;
481 #endif
482     statusP statusPtr;
483     afs_int32 code = 0;
484
485 #ifdef xbsa
486     if (CONF_XBSA)
487         return (TC_BADTASK);    /* LabelTape does not apply if XBSA */
488 #endif
489
490     if (callPermitted(rxCall) == 0)
491         return (TC_NOTPERMITTED);
492
493     *taskId = allocTaskId();
494
495     /* create the status node */
496     statusPtr = createStatusNode();
497     if (!statusPtr)
498         ERROR_EXIT(TC_INTERNALERROR);
499
500     lock_Status();
501     statusPtr->taskId = *taskId;
502     statusPtr->flags &= ~STARTING;      /* ok to examine */
503     statusPtr->lastPolled = time(0);
504     strncpy(statusPtr->taskName, "RestoreDb", sizeof(statusPtr->taskName));
505     unlock_Status();
506
507 #ifdef AFS_PTHREAD_ENV
508     code = pthread_attr_init(&tattr);
509     if (code)
510         ERROR_EXIT(code);
511
512     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
513     if (code)
514         ERROR_EXIT(code);
515
516     AFS_SIGSET_CLEAR();
517     code = pthread_create(&pid, &tattr, restoreDbFromTape, (void *)(intptr_t)*taskId);
518     AFS_SIGSET_RESTORE();
519 #else
520     code =
521         LWP_CreateProcess(restoreDbFromTape, 32768, 1, (void *)(intptr_t)*taskId,
522                           "Db restore", &pid);
523 #endif
524
525   error_exit:
526     if (code) {
527         if (statusPtr)
528             deleteStatusNode(statusPtr);
529     }
530
531     return (code);
532 }
533
534 /* STC_SaveDb
535  *      restore the backup database from tape
536  */
537
538 afs_int32
539 STC_SaveDb(struct rx_call *call, Date archiveTime, afs_uint32 *taskId)
540 {
541     afs_int32 code;
542
543     code = SSaveDb(call, archiveTime, taskId);
544     osi_auditU(call, TC_SaveDbEvent, code,
545                AUD_DATE, archiveTime, AUD_INT, *taskId, AUD_END);
546     return code;
547 }
548
549 static afs_int32
550 SSaveDb(struct rx_call *rxCall, Date archiveTime, afs_uint32 *taskId)
551 {
552 #ifdef AFS_PTHREAD_ENV
553     pthread_t pid;
554     pthread_attr_t tattr;
555     AFS_SIGSET_DECL;
556 #else
557     PROCESS pid;
558 #endif
559     statusP statusPtr = NULL;
560     afs_int32 code = 0;
561     struct saveDbIf *ptr;
562
563 #ifdef xbsa
564     if (CONF_XBSA)
565         return (TC_BADTASK);    /* LabelTape does not apply if XBSA */
566 #endif
567
568     if (callPermitted(rxCall) == 0)
569         return (TC_NOTPERMITTED);
570
571     *taskId = allocTaskId();
572
573     ptr = malloc(sizeof(struct saveDbIf));
574     if (!ptr)
575         ERROR_EXIT(TC_NOMEMORY);
576     ptr->archiveTime = archiveTime;
577     ptr->taskId = *taskId;
578
579     /* create the status node */
580     statusPtr = createStatusNode();
581     if (!statusPtr)
582         ERROR_EXIT(TC_INTERNALERROR);
583
584     lock_Status();
585     statusPtr->taskId = *taskId;
586     statusPtr->lastPolled = time(0);
587     statusPtr->flags &= ~STARTING;      /* ok to examine */
588     strncpy(statusPtr->taskName, "SaveDb", sizeof(statusPtr->taskName));
589     unlock_Status();
590
591     ptr->statusPtr = statusPtr;
592
593 #ifdef AFS_PTHREAD_ENV
594     code = pthread_attr_init(&tattr);
595     if (code)
596         ERROR_EXIT(code);
597
598     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
599     if (code)
600         ERROR_EXIT(code);
601
602     AFS_SIGSET_CLEAR();
603     code = pthread_create(&pid, &tattr, saveDbToTape, ptr);
604     AFS_SIGSET_RESTORE();
605 #else
606     code = LWP_CreateProcess(saveDbToTape, 32768, 1, ptr, "Db save", &pid);
607 #endif
608
609   error_exit:
610     if (code) {
611         if (statusPtr)
612             deleteStatusNode(statusPtr);
613         if (ptr)
614             free(ptr);
615     }
616
617     return (code);
618 }
619
620
621 /* STC_ScanDumps
622  *      read a dump (maybe more than one tape), and print out a summary
623  *      of its contents. If the flag is set, add to the database.
624  * entry:
625  *      addDbFlag - if set, the information will be added to the database
626  */
627
628 afs_int32
629 STC_ScanDumps(struct rx_call *call, afs_int32 addDbFlag, afs_uint32 *taskId)
630 {
631     afs_int32 code;
632
633     code = SScanDumps(call, addDbFlag, taskId);
634     osi_auditU(call, TC_ScanDumpsEvent, code,
635                AUD_INT, addDbFlag, AUD_INT, *taskId, AUD_END);
636     return code;
637 }
638
639 static afs_int32
640 SScanDumps(struct rx_call *acid, afs_int32 addDbFlag, afs_uint32 *taskId)
641 {
642 #ifdef AFS_PTHREAD_ENV
643     pthread_t pid;
644     pthread_attr_t tattr;
645     AFS_SIGSET_DECL;
646 #else
647     PROCESS pid;
648 #endif
649     struct scanTapeIf *ptr;
650     statusP statusPtr = NULL;
651     afs_int32 code = 0;
652
653 #ifdef xbsa
654     if (CONF_XBSA)
655         return (TC_BADTASK);    /* ScanDumps does not apply if XBSA */
656 #endif
657
658     if (callPermitted(acid) == 0)
659         return (TC_NOTPERMITTED);
660
661     *taskId = allocTaskId();
662
663     ptr = malloc(sizeof(*ptr));
664     if (!ptr)
665         ERROR_EXIT(TC_NOMEMORY);
666     ptr->addDbFlag = addDbFlag;
667     ptr->taskId = *taskId;
668
669     /* create the status node */
670     statusPtr = createStatusNode();
671     if (!statusPtr)
672         ERROR_EXIT(TC_INTERNALERROR);
673
674     lock_Status();
675     statusPtr->taskId = *taskId;
676     statusPtr->lastPolled = time(0);
677     statusPtr->flags &= ~STARTING;      /* ok to examine */
678     strncpy(statusPtr->taskName, "Scantape", sizeof(statusPtr->taskName));
679     unlock_Status();
680
681 #ifdef AFS_PTHREAD_ENV
682     code = pthread_attr_init(&tattr);
683     if (code)
684         ERROR_EXIT(code);
685
686     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
687     if (code)
688         ERROR_EXIT(code);
689
690     AFS_SIGSET_CLEAR();
691     code = pthread_create(&pid, &tattr, ScanDumps, ptr);
692     AFS_SIGSET_RESTORE();
693 #else
694     code =
695         LWP_CreateProcess(ScanDumps, 32768, 1, ptr, "scandump process", &pid);
696 #endif
697
698   error_exit:
699     if (code) {
700         if (statusPtr)
701             deleteStatusNode(statusPtr);
702         if (ptr)
703             free(ptr);
704     }
705
706     return code;
707 }
708
709 /* STC_TCInfo
710  *      return information about the tape coordinator. Currently this
711  *      is just the version number of the interface
712  */
713
714 afs_int32
715 STC_TCInfo(struct rx_call *call, struct tc_tcInfo *ti)
716 {
717     afs_int32 code;
718
719     code = STCInfo(call, ti);
720     osi_auditU(call, TC_TCInfoEvent, code, AUD_INT, ti->tcVersion, AUD_END);
721     return code;
722 }
723
724 static afs_int32
725 STCInfo(struct rx_call *acid, struct tc_tcInfo *tciptr)
726 {
727     if (callPermitted(acid) == 0)
728         return (TC_NOTPERMITTED);
729
730     tciptr->tcVersion = CUR_BUTC_VERSION;
731     return (0);
732 }
733
734 /* STC_DeleteDump
735  */
736 afs_int32
737 STC_DeleteDump(struct rx_call *call, afs_uint32 dumpID, afs_uint32 *taskId)
738 {
739     afs_int32 code;
740
741     code = SDeleteDump(call, dumpID, taskId);
742     osi_auditU(call, TC_DeleteDumpEvent, code,
743                AUD_DATE, dumpID, AUD_INT, *taskId, AUD_END);
744     return code;
745 }
746
747 static afs_int32
748 SDeleteDump(struct rx_call *acid, afs_uint32 dumpID, afs_uint32 *taskId)
749 {
750     afs_int32 code = TC_BADTASK;        /* If not compiled -Dxbsa then fail */
751 #ifdef xbsa
752     struct deleteDumpIf *ptr = 0;
753     statusP statusPtr = 0;
754 #ifdef AFS_PTHREAD_ENV
755     pthread_t pid;
756     pthread_attr_t tattr;
757     AFS_SIGSET_DECL;
758 #else
759     PROCESS pid;
760 #endif
761 #endif
762
763     *taskId = 0;
764     if (!CONF_XBSA)
765         return (TC_BADTASK);    /* Only do if butc is started as XBSA */
766
767 #ifdef xbsa
768     code = 0;
769     if (callPermitted(acid) == 0)
770         return (TC_NOTPERMITTED);
771
772     ptr = malloc(sizeof(*ptr));
773     if (!ptr)
774         ERROR_EXIT(TC_NOMEMORY);
775
776     *taskId = allocTaskId();
777     ptr->dumpID = dumpID;
778     ptr->taskId = *taskId;
779
780     statusPtr = createStatusNode();
781     if (!statusPtr)
782         ERROR_EXIT(TC_INTERNALERROR);
783
784     lock_Status();
785     statusPtr->taskId = *taskId;
786     statusPtr->lastPolled = time(0);
787     statusPtr->flags &= ~STARTING;
788     strncpy(statusPtr->taskName, "DeleteDump", sizeof(statusPtr->taskName));
789     unlock_Status();
790
791 #ifdef AFS_PTHREAD_ENV
792     code = pthread_attr_init(&tattr);
793     if (code)
794         ERROR_EXIT(code);
795
796     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
797     if (code)
798         ERROR_EXIT(code);
799
800     AFS_SIGSET_CLEAR();
801     code = pthread_create(&pid, &tattr, DeleteDump, ptr);
802     AFS_SIGSET_RESTORE();
803 #else
804     code =
805         LWP_CreateProcess(DeleteDump, 32768, 1, ptr, "deletedump process",
806                           &pid);
807 #endif
808
809   error_exit:
810     if (code) {
811         if (statusPtr)
812             deleteStatusNode(statusPtr);
813         if (ptr)
814             free(ptr);
815     }
816 #endif /* xbsa */
817
818     return (code);
819 }
820