Remove dead code
[openafs.git] / src / bucoord / dump.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 /*
11  * ALL RIGHTS RESERVED
12  */
13
14 #include <afsconfig.h>
15 #include <afs/param.h>
16
17 #include <roken.h>
18
19 #include <afs/cmd.h>
20 #include <afs/cellconfig.h>
21 #include <lwp.h>
22 #include <rx/rx.h>
23 #include <afs/bubasics.h>
24 #include <afs/butc.h>
25 #include <afs/com_err.h>
26 #include <lock.h>               /* for checking TC_ABORTFAILED. PA */
27 #include <afs/tcdata.h>         /* for checking TC_ABORTFAILED. PA */
28 #include <afs/butc.h>
29
30 #include "bc.h"
31 #include "error_macros.h"
32 #include "bucoord_internal.h"
33 #include "bucoord_prototypes.h"
34
35 struct bc_dumpTask bc_dumpTasks[BC_MAXSIMDUMPS];
36
37 extern char *whoami;
38
39 extern afs_int32 lastTaskCode;
40
41 #define HOSTADDR(sockaddr) (sockaddr)->sin_addr.s_addr
42
43 /* bc_Dumper
44  *      called (indirectly) to make a dump
45  * entry:
46  *      aindex - index into dumpTask array, contains all the information
47  *               relevant to the dump
48  */
49 int
50 bc_Dumper(int aindex)
51 {
52     struct rx_connection *tconn;
53     struct bc_volumeDump *tde;
54     afs_int32 count, port;
55     struct tc_dumpDesc *volDesc = NULL;
56     struct tc_dumpArray volArray;
57     char *baseNamePtr;
58     statusP statusPtr;
59
60     struct tc_dumpInterface dumpInterface;
61     struct tc_dumpInterface *tcdiPtr = &dumpInterface;
62     struct bc_dumpTask *dumpTaskPtr;
63
64     afs_int32 code = 0;
65
66     dumpTaskPtr = &bc_dumpTasks[aindex];
67
68     if (!dumpTaskPtr->portOffset || (dumpTaskPtr->portCount == 0))
69         port = 0;
70     else
71         port = dumpTaskPtr->portOffset[0];
72
73     code = ConnectButc(dumpTaskPtr->config, port, &tconn);
74     if (code)
75         return (code);
76
77     /* count number of volumes to be dumped and
78      * build array of volumes to be sent to backup system
79      */
80     for (count = 0, tde = dumpTaskPtr->volumes; tde;
81          tde = tde->next, count++);
82
83     /* Nothing to dump, so just return success */
84     if (count == 0)
85         goto error_exit;
86
87     volDesc = malloc(count * sizeof(struct tc_dumpDesc));
88     if (!volDesc) {
89         afs_com_err(whoami, BC_NOMEM, NULL);
90         ERROR(BC_NOMEM);
91     }
92
93     for (count = 0, tde = dumpTaskPtr->volumes; tde; tde = tde->next, count++) {
94         strcpy(volDesc[count].name, tde->name);
95         volDesc[count].vid = tde->vid;
96         volDesc[count].vtype = tde->volType;
97         volDesc[count].partition = tde->partition;
98         volDesc[count].hostAddr = HOSTADDR(&tde->server);       /* the internet address */
99         volDesc[count].date = tde->date;
100         volDesc[count].cloneDate = tde->cloneDate;      /* Not yet known */
101     }
102
103     volArray.tc_dumpArray_len = count;  /* element count */
104     volArray.tc_dumpArray_val = volDesc;        /* and data */
105
106     baseNamePtr = tailCompPtr(dumpTaskPtr->dumpName);
107
108     /* setup the interface structure */
109     memset(tcdiPtr, 0, sizeof(*tcdiPtr));
110
111     /* general */
112     strcpy(tcdiPtr->dumpPath, dumpTaskPtr->dumpName);
113     strcpy(tcdiPtr->volumeSetName, dumpTaskPtr->volSetName);
114
115     /* tapeset */
116     strcpy(tcdiPtr->tapeSet.format, dumpTaskPtr->volSetName);
117     strcat(tcdiPtr->tapeSet.format, ".");
118     strcat(tcdiPtr->tapeSet.format, baseNamePtr);
119     strcat(tcdiPtr->tapeSet.format, ".%d");
120     tcdiPtr->tapeSet.a = 1;
121     tcdiPtr->tapeSet.b = 1;
122     tcdiPtr->tapeSet.maxTapes = 1000000000;
123     tcdiPtr->tapeSet.expDate = dumpTaskPtr->expDate;    /* PA */
124     tcdiPtr->tapeSet.expType = dumpTaskPtr->expType;
125
126     /* construct dump set name */
127     strcpy(tcdiPtr->dumpName, dumpTaskPtr->volSetName);
128     strcat(tcdiPtr->dumpName, ".");
129     strcat(tcdiPtr->dumpName, baseNamePtr);
130
131     tcdiPtr->parentDumpId = dumpTaskPtr->parentDumpID;
132     tcdiPtr->dumpLevel = dumpTaskPtr->dumpLevel;
133     tcdiPtr->doAppend = dumpTaskPtr->doAppend;
134
135     /* start the dump on the tape coordinator */
136     printf("Starting dump\n");
137     code = TC_PerformDump(tconn, tcdiPtr, &volArray, &dumpTaskPtr->dumpID);
138     if (code) {
139         afs_com_err(whoami, code, "; Failed to start dump");
140         ERROR(code);
141     }
142
143     afs_com_err(whoami, 0, "Task %u: Dump (%s)", dumpTaskPtr->dumpID,
144             tcdiPtr->dumpName);
145
146     /* create status monitor block */
147     statusPtr = createStatusNode();
148     lock_Status();
149     statusPtr->taskId = dumpTaskPtr->dumpID;
150     statusPtr->port = port;
151     statusPtr->jobNumber = bc_jobNumber();
152     statusPtr->volsTotal = volArray.tc_dumpArray_len;
153     statusPtr->flags &= ~STARTING;
154     sprintf(statusPtr->taskName, "Dump (%s.%s)", dumpTaskPtr->volSetName,
155             baseNamePtr);
156     unlock_Status();
157
158   error_exit:
159     /* locally allocated resources */
160     if (volDesc)
161         free(volDesc);
162
163     if (tconn)
164         rx_DestroyConnection(tconn);
165
166     return (code);
167 }
168
169 /* freeDumpTaskVolumeList
170  *      free the list of volumes used for dumps
171  */
172
173 void
174 freeDumpTaskVolumeList(struct bc_volumeDump *vdptr)
175 {
176     struct bc_volumeDump *nextVdPtr;
177
178     while (vdptr != 0) {
179         nextVdPtr = vdptr->next;
180
181         if (vdptr->name)
182             free(vdptr->name);
183         free(vdptr);
184
185         vdptr = nextVdPtr;
186     }
187 }
188
189 /* bc_DmpRstStart
190  *     The other half of the dump/restore create process call. In bc_StartDmpRst,
191  *     we allocated a dumpTask entry. Here we do the task and then free the entry.
192  */
193 void *
194 bc_DmpRstStart(void *param)
195 {
196     afs_int32 aindex = (intptr_t)param;
197     struct bc_dumpTask *tdump;
198     afs_int32 code;
199
200     tdump = &bc_dumpTasks[aindex];
201
202     code = (tdump->callProc) (aindex);
203     if (code)
204         lastTaskCode = code;
205
206     /* Cleanup allocated data structures */
207     freeDumpTaskVolumeList(tdump->volumes);
208     tdump->dumpID = 0;
209     if (tdump->dumpName)
210         free(tdump->dumpName);
211     if (tdump->newExt)
212         free(tdump->newExt);
213     if (tdump->volSetName)
214         free(tdump->volSetName);
215     if (tdump->portOffset)
216         free(tdump->portOffset);
217     tdump->flags &= ~BC_DI_INUSE;
218
219     return (void *)(intptr_t)code;
220 }
221
222 /* bc_StartDmpRst
223  *      function to start dump running. Packages the relevant information
224  *      (from params) into any free dumpTask structure (globally allocated),
225  *      and then invokes bc_DmpRstStart to do the work, passing it a single
226  *      parameter, the index into the dumpTask array.
227  *
228  * entry:
229  *      aconfig - normally is bc_globalConfig
230  *      aproc - bc_Dumper for doing dumps
231  *              bc_Restorer for doing restores
232  */
233
234 int
235 bc_StartDmpRst(struct bc_config *aconfig, char *adname, char *avname,
236                struct bc_volumeDump *avolsToDump,
237                struct sockaddr_in *adestServer,
238                afs_int32 adestPartition, afs_int32 afromDate, char *anewExt,
239                int aoldFlag, afs_int32 aparent, afs_int32 alevel,
240                int (*aproc) (int), afs_int32 *ports, afs_int32 portCount,
241                struct bc_dumpSchedule *dsptr, int append, int dontExecute)
242 {
243     int i;
244     afs_int32 code;
245     PROCESS junk;
246
247     for (i = 0; i < BC_MAXSIMDUMPS; i++)
248         if (!(bc_dumpTasks[i].flags & BC_DI_INUSE))
249             break;
250
251     if (i >= BC_MAXSIMDUMPS) {
252         afs_com_err(whoami, BC_NOTLOCKED,
253                 "All of the dump/restore slots are in use, try again later");
254         return (BC_NOTLOCKED);
255     }
256
257     memset(&bc_dumpTasks[i], 0, sizeof(struct bc_dumpTask));
258     bc_dumpTasks[i].callProc = aproc;
259     bc_dumpTasks[i].config = aconfig;
260     bc_dumpTasks[i].volumes = avolsToDump;
261     bc_dumpTasks[i].flags = BC_DI_INUSE;
262     bc_dumpTasks[i].dumpName = bc_CopyString(adname);
263     bc_dumpTasks[i].volSetName = bc_CopyString(avname);
264     bc_dumpTasks[i].newExt = bc_CopyString(anewExt);
265     bc_dumpTasks[i].dumpLevel = alevel;
266     bc_dumpTasks[i].parentDumpID = aparent;
267     bc_dumpTasks[i].oldFlag = aoldFlag;
268     bc_dumpTasks[i].fromDate = afromDate;
269     bc_dumpTasks[i].destPartition = adestPartition;
270     bc_dumpTasks[i].portOffset = ports;
271     bc_dumpTasks[i].portCount = portCount;
272     bc_dumpTasks[i].doAppend = append;
273     bc_dumpTasks[i].dontExecute = dontExecute;
274
275     if (dsptr) {
276         /* This should be specified for dumps, but will be 0 for restores */
277         bc_dumpTasks[i].expDate = dsptr->expDate;
278         bc_dumpTasks[i].expType = dsptr->expType;
279     }
280     if (adestServer)
281         memcpy(&bc_dumpTasks[i].destServer, adestServer,
282                sizeof(struct sockaddr_in));
283     else
284         memset(&bc_dumpTasks[i].destServer, 0, sizeof(struct sockaddr_in));
285
286     code =
287         LWP_CreateProcess(bc_DmpRstStart, 20480, LWP_NORMAL_PRIORITY,
288                           (void *)(intptr_t)i, "helper", &junk);
289     if (code) {
290         bc_HandleMisc(code);
291         afs_com_err(whoami, code, "; Can't start thread");
292
293         /* Cleanup allocated data structures */
294         freeDumpTaskVolumeList(bc_dumpTasks[i].volumes);
295         bc_dumpTasks[i].dumpID = 0;
296         if (bc_dumpTasks[i].dumpName)
297             free(bc_dumpTasks[i].dumpName);
298         if (bc_dumpTasks[i].newExt)
299             free(bc_dumpTasks[i].newExt);
300         if (bc_dumpTasks[i].volSetName)
301             free(bc_dumpTasks[i].volSetName);
302         if (bc_dumpTasks[i].portOffset)
303             free(bc_dumpTasks[i].portOffset);
304         bc_dumpTasks[i].flags &= ~BC_DI_INUSE;
305         return (code);
306     }
307
308     return 0;
309 }
310
311 /* bc_LabelTape
312  *      opens a connection to the tape coordinator and requests that it
313  *      label a tape
314  */
315
316 int
317 bc_LabelTape(char *afsname, char *pname, afs_int32 size,
318              struct bc_config *config, afs_int32 port)
319 {
320     struct rx_connection *tconn;
321     afs_int32 code = 0;
322     struct tc_tapeLabel label;
323     statusP statusPtr;
324     afs_uint32 taskId;
325
326     code = ConnectButc(config, port, &tconn);
327     if (code)
328         return (code);
329
330     memset(&label, 0, sizeof(label));
331     if (afsname)
332         strcpy(label.afsname, afsname);
333     if (pname)
334         strcpy(label.pname, (strcmp(pname, "") ? pname : "<NULL>"));
335     label.size = size;
336
337     code = TC_LabelTape(tconn, &label, &taskId);
338     if (code) {
339         afs_com_err(whoami, code, "; Failed to start labeltape");
340         return (code);
341     }
342
343     /* create status monitor block */
344     statusPtr = createStatusNode();
345     lock_Status();
346     statusPtr->taskId = taskId;
347     statusPtr->port = port;
348     statusPtr->jobNumber = bc_jobNumber();
349     /* statusPtr->flags    |= SILENT; *//* don't report termination */
350     statusPtr->flags &= ~STARTING;      /* ok to examine */
351
352     sprintf(statusPtr->taskName, "Labeltape (%s)",
353             (pname ? pname : (afsname ? afsname : "<NULL>")));
354     unlock_Status();
355
356     return 0;
357 }
358
359 /* bc_ReadLabel
360  *      open a connection to the tape coordinator and read the label on
361  *      a tape
362  */
363
364 int
365 bc_ReadLabel(struct bc_config *config, afs_int32 port)
366 {
367     struct rx_connection *tconn;
368     struct tc_tapeLabel label;
369     afs_uint32 taskId;
370     afs_int32 code = 0;
371     char *tname = 0;
372
373     code = ConnectButc(config, port, &tconn);
374     if (code)
375         return (code);
376
377     memset(&label, 0, sizeof(label));
378     code = TC_ReadLabel(tconn, &label, &taskId);
379     if (code) {
380         if (code == BUTM_NOLABEL) {
381             printf("Tape read was unlabelled\n");
382             return 0;
383         }
384         afs_com_err(whoami, code, "; Failed to start readlabel");
385         return (code);
386     }
387
388     if (strcmp(label.pname, ""))
389         tname = label.pname;
390     else if (strcmp(label.afsname, ""))
391         tname = label.afsname;
392
393     if (!tname) {
394         printf("Tape read was labelled : <NULL>  size : %u\n", label.size);
395     } else if (!label.tapeId) {
396         printf("Tape read was labelled : %s size : %lu Kbytes\n", tname,
397                (long unsigned int) label.size);
398     } else {
399         printf("Tape read was labelled : %s (%lu) size : %lu Kbytes\n", tname,
400                (long unsigned int) label.tapeId, (long unsigned int) label.size);
401     }
402
403     return 0;
404 }
405
406 int
407 bc_ScanDumps(struct bc_config *config, afs_int32 dbAddFlag, afs_int32 port)
408 {
409     struct rx_connection *tconn;
410     statusP statusPtr;
411     afs_uint32 taskId;
412     afs_int32 code = 0;
413
414     code = ConnectButc(config, port, &tconn);
415     if (code)
416         return (code);
417
418     code = TC_ScanDumps(tconn, dbAddFlag, &taskId);
419     if (code) {
420         afs_com_err(whoami, code, "; Failed to start scantape");
421         return (code);
422     }
423
424     /* create status monitor block */
425     statusPtr = createStatusNode();
426     lock_Status();
427     statusPtr->taskId = taskId;
428     statusPtr->port = port;
429     statusPtr->jobNumber = bc_jobNumber();
430     statusPtr->flags &= ~STARTING;      /* ok to examine */
431     sprintf(statusPtr->taskName, "Scantape");
432     unlock_Status();
433
434     return (0);
435 }
436
437 /*************/
438 /* utilities */
439 /*************/
440
441 /* get a connection to the tape controller */
442 afs_int32
443 bc_GetConn(struct bc_config *aconfig, afs_int32 aport,
444            struct rx_connection **tconn)
445 {
446     afs_uint32 host;
447     afs_int32 code;
448     unsigned short port;
449     static struct rx_securityClass *rxsc;
450     static afs_int32 scIndex;
451     struct bc_hostEntry *te;
452
453     *tconn = (struct rx_connection *)0;
454
455     /* use non-secure connections to butc */
456     if (!rxsc) {
457         struct afsconf_dir *dir;
458         afsconf_secflags flags = AFSCONF_SECOPTS_FALLBACK_NULL;
459         char *cname;
460
461         if (nobutcauth)
462             flags |= AFSCONF_SECOPTS_NOAUTH;
463         if (localauth) {
464             flags |= AFSCONF_SECOPTS_LOCALAUTH;
465             dir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
466         } else {
467             dir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
468         }
469         if (tcell[0] == '\0')
470             cname = NULL;
471         else
472             cname = tcell;
473         /* No need for cell info since butc is not a registered service */
474         code = afsconf_PickClientSecObj(dir, flags, NULL, cname, &rxsc, &scIndex,
475                                         NULL);
476         if (dir)
477             afsconf_Close(dir);
478         if (code)
479             return -1;
480     }
481     if (!rxsc || !aconfig)
482         return (-1);
483
484     for (te = aconfig->tapeHosts; te; te = te->next) {
485         if (te->portOffset == aport) {
486             /* found the right port */
487             host = te->addr.sin_addr.s_addr;
488             if (!host)
489                 return (BC_NOHOSTENTRY);        /* gethostbyname in bc_ParseHosts failed */
490
491             port = htons(BC_TAPEPORT + aport);
492
493             /* servers is 1 */
494             *tconn = rx_NewConnection(host, port, 1, rxsc, scIndex);
495             return ((*tconn ? 0 : -1));
496         }
497     }
498     return (BC_NOHOSTENTRY);
499 }
500
501 /* CheckTCVersion
502  *      make sure we are talking to a compatible butc process.
503  * exit:
504  *      0 - ok
505  *      -1 - not compatible
506  */
507
508 int
509 CheckTCVersion(struct rx_connection *tconn)
510 {
511     struct tc_tcInfo tci;
512     afs_int32 code;
513
514     code = TC_TCInfo(tconn, &tci);
515     if (code)
516         return (code);
517
518     if (tci.tcVersion != CUR_BUTC_VERSION)
519         return (BC_VERSIONFAIL);
520
521     return 0;
522 }
523
524 int
525 ConnectButc(struct bc_config *config, afs_int32 port,
526             struct rx_connection **tconn)
527 {
528     afs_int32 code;
529
530     code = bc_GetConn(config, port, tconn);
531     if (code) {
532         afs_com_err(whoami, code,
533                 "; Can't connect to tape coordinator at port %d", port);
534         return (code);
535     }
536
537     code = CheckTCVersion(*tconn);
538     if (code) {
539         rx_DestroyConnection(*tconn);
540
541         if (code == BC_VERSIONFAIL)
542             afs_com_err(whoami, code,
543                     "; Backup and butc are not the same version");
544         else
545             afs_com_err(whoami, code,
546                     "; Can't access tape coordinator at port %d", port);
547
548         return (code);
549     }
550
551     return (0);
552 }