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