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