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