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