f5299f9e3518044c8732ff02860438f0ab4e5750
[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 = (char *)malloc(strlen(tcdiPtr->dumpPath) + 1);
230     strcpy(newNode->dumpName, tcdiPtr->dumpPath);
231
232     newNode->volumeSetName =
233         (char *)malloc(strlen(tcdiPtr->volumeSetName) + 1);
234     strcpy(newNode->volumeSetName, tcdiPtr->volumeSetName);
235
236     CopyTapeSetDesc(&(newNode->tapeSetDesc), &tcdiPtr->tapeSet);
237
238     newNode->dumps = (struct tc_dumpDesc *)
239         malloc(sizeof(struct tc_dumpDesc) *
240                tc_dumpArrayPtr->tc_dumpArray_len);
241     newNode->arraySize = tc_dumpArrayPtr->tc_dumpArray_len;
242     CopyDumpDesc(newNode->dumps, tc_dumpArrayPtr);
243
244     newNode->parent = tcdiPtr->parentDumpId;
245     newNode->level = tcdiPtr->dumpLevel;
246     newNode->doAppend = tcdiPtr->doAppend;
247 #ifdef xbsa
248     if (CONF_XBSA)
249         newNode->doAppend = 0;  /* Append flag is ignored if talking to XBSA */
250 #endif
251
252     /* create the status node */
253     statusPtr = createStatusNode();
254     if (!statusPtr)
255         ERROR_EXIT(TC_INTERNALERROR);
256
257     lock_Status();
258     statusPtr->taskId = newNode->taskID;
259     statusPtr->lastPolled = time(0);
260     statusPtr->flags &= ~STARTING;      /* ok to examine */
261     strncpy(statusPtr->taskName, "Dump", sizeof(statusPtr->taskName));
262     unlock_Status();
263
264     newNode->statusNodePtr = statusPtr;
265
266     /* create the LWP to do the real work behind the scenes */
267 #ifdef AFS_PTHREAD_ENV
268     code = pthread_attr_init(&tattr);
269     if (code)
270         ERROR_EXIT(code);
271
272     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
273     if (code)
274         ERROR_EXIT(code);
275
276     AFS_SIGSET_CLEAR();
277     code = pthread_create(&pid, &tattr, Dumper, newNode);
278     AFS_SIGSET_RESTORE();
279 #else
280     code =
281         LWP_CreateProcess(Dumper, 32768, 1, (void *)newNode, "dumper process",
282                           &pid);
283 #endif
284     if (code)
285         ERROR_EXIT(code);
286
287     *taskId = newNode->taskID;
288
289   error_exit:
290     if (code) {
291         if (statusPtr)
292             deleteStatusNode(statusPtr);
293         FreeNode(newNode->taskID);      /*  failed to create LWP to do the dump. */
294     }
295
296     return (code);
297 }
298
299 afs_int32
300 STC_PerformRestore(struct rx_call *acid, char *dumpSetName, tc_restoreArray *arestores, afs_int32 *taskID)
301 {
302     struct dumpNode *newNode;
303     statusP statusPtr;
304     afs_int32 code = 0;
305 #ifdef AFS_PTHREAD_ENV
306     pthread_t pid;
307     pthread_attr_t tattr;
308     AFS_SIGSET_DECL;
309 #else
310     PROCESS pid;
311 #endif
312
313     if (callPermitted(acid) == 0)
314         return (TC_NOTPERMITTED);
315
316     /* should  verify parameter validity */
317
318     /* this creates a node in list, alots an id for it and prepares it for locking */
319     CreateNode(&newNode);
320
321     newNode->restores = (struct tc_restoreDesc *)
322         malloc(sizeof(struct tc_restoreDesc) *
323                arestores->tc_restoreArray_len);
324     newNode->arraySize = arestores->tc_restoreArray_len;
325     CopyRestoreDesc(newNode->restores, arestores);
326     *taskID = newNode->taskID;
327
328     /* should log the intent */
329
330     /* create the status node */
331     statusPtr = createStatusNode();
332     if (!statusPtr)
333         ERROR_EXIT(TC_INTERNALERROR);
334
335     lock_Status();
336     statusPtr->taskId = newNode->taskID;
337     statusPtr->flags &= ~STARTING;      /* ok to examine */
338     statusPtr->lastPolled = time(0);
339     strncpy(statusPtr->taskName, "Restore", sizeof(statusPtr->taskName));
340     unlock_Status();
341
342     newNode->statusNodePtr = statusPtr;
343
344     /* create the LWP to do the real work behind the scenes */
345 #ifdef AFS_PTHREAD_ENV
346     code = pthread_attr_init(&tattr);
347     if (code)
348         ERROR_EXIT(code);
349
350     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
351     if (code)
352         ERROR_EXIT(code);
353
354     AFS_SIGSET_CLEAR();
355     code = pthread_create(&pid, &tattr, Restorer, newNode);
356     AFS_SIGSET_RESTORE();
357 #else
358     code =
359         LWP_CreateProcess(Restorer, 65368, 1, (void *)newNode,
360                           "restorer process", &pid);
361 #endif
362
363   error_exit:
364     if (code) {
365         if (statusPtr)
366             deleteStatusNode(statusPtr);
367         FreeNode(newNode->taskID);      /*  failed to create LWP to do the dump. */
368     }
369
370     return (code);
371 }
372
373 afs_int32
374 STC_ReadLabel(struct rx_call *acid, struct tc_tapeLabel *label, afs_uint32 *taskId)
375 {
376     afs_int32 code;
377
378 #ifdef xbsa
379     if (CONF_XBSA)
380         return (TC_BADTASK);    /* ReadLabel does not apply if XBSA */
381 #endif
382
383     if (callPermitted(acid) == 0)
384         return (TC_NOTPERMITTED);
385
386     code = ReadLabel(label);    /* Synchronous */
387     return code;
388 }
389
390 /* STC_RestoreDb
391  *      restore the backup database from tape
392  */
393
394 afs_int32
395 STC_RestoreDb(struct rx_call *rxCall, afs_uint32 *taskId)
396 {
397 #ifdef AFS_PTHREAD_ENV
398     pthread_t pid;
399     pthread_attr_t tattr;
400     AFS_SIGSET_DECL;
401 #else
402     PROCESS pid;
403 #endif
404     statusP statusPtr;
405     afs_int32 code = 0;
406
407 #ifdef xbsa
408     if (CONF_XBSA)
409         return (TC_BADTASK);    /* LabelTape does not apply if XBSA */
410 #endif
411
412     if (callPermitted(rxCall) == 0)
413         return (TC_NOTPERMITTED);
414
415     *taskId = allocTaskId();
416
417     /* create the status node */
418     statusPtr = createStatusNode();
419     if (!statusPtr)
420         ERROR_EXIT(TC_INTERNALERROR);
421
422     lock_Status();
423     statusPtr->taskId = *taskId;
424     statusPtr->flags &= ~STARTING;      /* ok to examine */
425     statusPtr->lastPolled = time(0);
426     strncpy(statusPtr->taskName, "RestoreDb", sizeof(statusPtr->taskName));
427     unlock_Status();
428
429 #ifdef AFS_PTHREAD_ENV
430     code = pthread_attr_init(&tattr);
431     if (code)
432         ERROR_EXIT(code);
433
434     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
435     if (code)
436         ERROR_EXIT(code);
437
438     AFS_SIGSET_CLEAR();
439     code = pthread_create(&pid, &tattr, restoreDbFromTape, (void *)(intptr_t)*taskId);
440     AFS_SIGSET_RESTORE();
441 #else
442     code =
443         LWP_CreateProcess(restoreDbFromTape, 32768, 1, (void *)(intptr_t)*taskId,
444                           "Db restore", &pid);
445 #endif
446
447   error_exit:
448     if (code) {
449         if (statusPtr)
450             deleteStatusNode(statusPtr);
451     }
452
453     return (code);
454 }
455
456 /* STC_SaveDb
457  *      restore the backup database from tape
458  */
459
460 afs_int32
461 STC_SaveDb(struct rx_call *rxCall, Date archiveTime, afs_uint32 *taskId)
462 {
463 #ifdef AFS_PTHREAD_ENV
464     pthread_t pid;
465     pthread_attr_t tattr;
466     AFS_SIGSET_DECL;
467 #else
468     PROCESS pid;
469 #endif
470     statusP statusPtr = NULL;
471     afs_int32 code = 0;
472     struct saveDbIf *ptr;
473
474 #ifdef xbsa
475     if (CONF_XBSA)
476         return (TC_BADTASK);    /* LabelTape does not apply if XBSA */
477 #endif
478
479     if (callPermitted(rxCall) == 0)
480         return (TC_NOTPERMITTED);
481
482     *taskId = allocTaskId();
483
484     ptr = (struct saveDbIf *)malloc(sizeof(struct saveDbIf));
485     if (!ptr)
486         ERROR_EXIT(TC_NOMEMORY);
487     ptr->archiveTime = archiveTime;
488     ptr->taskId = *taskId;
489
490     /* create the status node */
491     statusPtr = createStatusNode();
492     if (!statusPtr)
493         ERROR_EXIT(TC_INTERNALERROR);
494
495     lock_Status();
496     statusPtr->taskId = *taskId;
497     statusPtr->lastPolled = time(0);
498     statusPtr->flags &= ~STARTING;      /* ok to examine */
499     strncpy(statusPtr->taskName, "SaveDb", sizeof(statusPtr->taskName));
500     unlock_Status();
501
502     ptr->statusPtr = statusPtr;
503
504 #ifdef AFS_PTHREAD_ENV
505     code = pthread_attr_init(&tattr);
506     if (code)
507         ERROR_EXIT(code);
508
509     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
510     if (code)
511         ERROR_EXIT(code);
512
513     AFS_SIGSET_CLEAR();
514     code = pthread_create(&pid, &tattr, saveDbToTape, ptr);
515     AFS_SIGSET_RESTORE();
516 #else
517     code = LWP_CreateProcess(saveDbToTape, 32768, 1, ptr, "Db save", &pid);
518 #endif
519
520   error_exit:
521     if (code) {
522         if (statusPtr)
523             deleteStatusNode(statusPtr);
524         if (ptr)
525             free(ptr);
526     }
527
528     return (code);
529 }
530
531
532 /* STC_ScanDumps
533  *      read a dump (maybe more than one tape), and print out a summary
534  *      of its contents. If the flag is set, add to the database.
535  * entry:
536  *      addDbFlag - if set, the information will be added to the database
537  */
538
539 afs_int32
540 STC_ScanDumps(struct rx_call *acid, afs_int32 addDbFlag, afs_uint32 *taskId)
541 {
542 #ifdef AFS_PTHREAD_ENV
543     pthread_t pid;
544     pthread_attr_t tattr;
545     AFS_SIGSET_DECL;
546 #else
547     PROCESS pid;
548 #endif
549     struct scanTapeIf *ptr;
550     statusP statusPtr = NULL;
551     afs_int32 code = 0;
552
553 #ifdef xbsa
554     if (CONF_XBSA)
555         return (TC_BADTASK);    /* ScanDumps does not apply if XBSA */
556 #endif
557
558     if (callPermitted(acid) == 0)
559         return (TC_NOTPERMITTED);
560
561     *taskId = allocTaskId();
562
563     ptr = (struct scanTapeIf *)malloc(sizeof(*ptr));
564     if (!ptr)
565         ERROR_EXIT(TC_NOMEMORY);
566     ptr->addDbFlag = addDbFlag;
567     ptr->taskId = *taskId;
568
569     /* create the status node */
570     statusPtr = createStatusNode();
571     if (!statusPtr)
572         ERROR_EXIT(TC_INTERNALERROR);
573
574     lock_Status();
575     statusPtr->taskId = *taskId;
576     statusPtr->lastPolled = time(0);
577     statusPtr->flags &= ~STARTING;      /* ok to examine */
578     strncpy(statusPtr->taskName, "Scantape", sizeof(statusPtr->taskName));
579     unlock_Status();
580
581 #ifdef AFS_PTHREAD_ENV
582     code = pthread_attr_init(&tattr);
583     if (code)
584         ERROR_EXIT(code);
585
586     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
587     if (code)
588         ERROR_EXIT(code);
589
590     AFS_SIGSET_CLEAR();
591     code = pthread_create(&pid, &tattr, ScanDumps, ptr);
592     AFS_SIGSET_RESTORE();
593 #else
594     code =
595         LWP_CreateProcess(ScanDumps, 32768, 1, ptr, "scandump process", &pid);
596 #endif
597
598   error_exit:
599     if (code) {
600         if (statusPtr)
601             deleteStatusNode(statusPtr);
602         if (ptr)
603             free(ptr);
604     }
605
606     return code;
607 }
608
609 /* STC_TCInfo
610  *      return information about the tape coordinator. Currently this
611  *      is just the version number of the interface
612  */
613
614 afs_int32
615 STC_TCInfo(struct rx_call *acid, struct tc_tcInfo *tciptr)
616 {
617     if (callPermitted(acid) == 0)
618         return (TC_NOTPERMITTED);
619
620     tciptr->tcVersion = CUR_BUTC_VERSION;
621     return (0);
622 }
623
624 /* STC_DeleteDump
625  */
626 afs_int32
627 STC_DeleteDump(struct rx_call *acid, afs_uint32 dumpID, afs_uint32 *taskId)
628 {
629     afs_int32 code = TC_BADTASK;        /* If not compiled -Dxbsa then fail */
630 #ifdef xbsa
631     struct deleteDumpIf *ptr = 0;
632     statusP statusPtr = 0;
633 #ifdef AFS_PTHREAD_ENV
634     pthread_t pid;
635     pthread_attr_t tattr;
636     AFS_SIGSET_DECL;
637 #else
638     PROCESS pid;
639 #endif
640 #endif
641
642     *taskId = 0;
643     if (!CONF_XBSA)
644         return (TC_BADTASK);    /* Only do if butc is started as XBSA */
645
646 #ifdef xbsa
647     code = 0;
648     if (callPermitted(acid) == 0)
649         return (TC_NOTPERMITTED);
650
651     ptr = (struct deleteDumpIf *)malloc(sizeof(*ptr));
652     if (!ptr)
653         ERROR_EXIT(TC_NOMEMORY);
654
655     *taskId = allocTaskId();
656     ptr->dumpID = dumpID;
657     ptr->taskId = *taskId;
658
659     statusPtr = createStatusNode();
660     if (!statusPtr)
661         ERROR_EXIT(TC_INTERNALERROR);
662
663     lock_Status();
664     statusPtr->taskId = *taskId;
665     statusPtr->lastPolled = time(0);
666     statusPtr->flags &= ~STARTING;
667     strncpy(statusPtr->taskName, "DeleteDump", sizeof(statusPtr->taskName));
668     unlock_Status();
669
670 #ifdef AFS_PTHREAD_ENV
671     code = pthread_attr_init(&tattr);
672     if (code)
673         ERROR_EXIT(code);
674
675     code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
676     if (code)
677         ERROR_EXIT(code);
678
679     AFS_SIGSET_CLEAR();
680     code = pthread_create(&pid, &tattr, DeleteDump, ptr);
681     AFS_SIGSET_RESTORE();
682 #else
683     code =
684         LWP_CreateProcess(DeleteDump, 32768, 1, ptr, "deletedump process",
685                           &pid);
686 #endif
687
688   error_exit:
689     if (code) {
690         if (statusPtr)
691             deleteStatusNode(statusPtr);
692         if (ptr)
693             free(ptr);
694     }
695 #endif /* xbsa */
696
697     return (code);
698 }
699