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