Imported Upstream version 3.1.0
[debian/amanda] / ndmp-src / ndmjob_job.c
1 /*
2  * Copyright (c) 1998,1999,2000
3  *      Traakan, Inc., Los Altos, CA
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice unmodified, this list of conditions, and the following
11  *    disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 /*
30  * Project:  NDMJOB
31  * Ident:    $Id: $
32  *
33  * Description:
34  *
35  */
36
37
38 #include "ndmjob.h"
39
40
41 #ifndef NDMOS_OPTION_NO_CONTROL_AGENT
42
43
44 int
45 build_job (void)
46 {
47         struct ndm_job_param *  job = &the_job;
48         int                     i, rc, n_err;
49         char                    errbuf[100];
50
51         NDMOS_MACRO_ZEROFILL(job);
52
53         args_to_job ();
54
55         ndma_job_auto_adjust (job);
56
57         if (o_rules)
58                 apply_rules (job, o_rules);
59
60         i = n_err = 0;
61         do {
62                 rc = ndma_job_audit (job, errbuf, i);
63                 if (rc > n_err || rc < 0) {
64                         ndmjob_log (0, "error: %s", errbuf);
65                 }
66                 n_err = rc;
67         } while (i++ < n_err);
68
69         if (n_err) {
70                 error_byebye ("can't proceed");
71                 /* no return */
72         }
73
74         return 0;
75 }
76
77
78 int
79 args_to_job (void)
80 {
81         struct ndm_job_param *  job = &the_job;
82         int                     i;
83
84         switch (the_mode) {
85         case NDM_JOB_OP_QUERY_AGENTS:
86         case NDM_JOB_OP_INIT_LABELS:
87         case NDM_JOB_OP_LIST_LABELS:
88         case NDM_JOB_OP_REMEDY_ROBOT:
89         case NDM_JOB_OP_TEST_TAPE:
90         case NDM_JOB_OP_TEST_MOVER:
91         case NDM_JOB_OP_TEST_DATA:
92         case NDM_JOB_OP_REWIND_TAPE:
93         case NDM_JOB_OP_EJECT_TAPE:
94         case NDM_JOB_OP_MOVE_TAPE:
95         case NDM_JOB_OP_IMPORT_TAPE:
96         case NDM_JOB_OP_EXPORT_TAPE:
97         case NDM_JOB_OP_LOAD_TAPE:
98         case NDM_JOB_OP_UNLOAD_TAPE:
99         case NDM_JOB_OP_INIT_ELEM_STATUS:
100                 break;
101
102         case NDM_JOB_OP_BACKUP:
103                 args_to_job_backup_env();
104                 break;
105
106         case NDM_JOB_OP_TOC:
107                 args_to_job_recover_env();
108                 args_to_job_recover_nlist();
109                 if (J_index_file)
110                         jndex_doit();
111                 break;
112
113         case NDM_JOB_OP_EXTRACT:
114                 args_to_job_recover_env();
115                 args_to_job_recover_nlist();
116                 jndex_doit();
117                 break;
118
119         case 'D':               /* -o daemon */
120                 return 0;
121
122         default:
123                 printf ("mode -%c not implemented yet\n", the_mode);
124                 break;
125         }
126         job->operation = the_mode;
127
128         /* DATA agent */
129         job->data_agent  = D_data_agent;
130         job->bu_type = B_bu_type;
131         for (i = 0; i < nn_E_environment; i++)
132                 job->env_tab.env[i] = E_environment[i];
133         job->env_tab.n_env = nn_E_environment;
134         if (the_mode == NDM_JOB_OP_EXTRACT || the_mode == NDM_JOB_OP_TOC) {
135                 for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
136                         job->nlist_tab.nlist[i] = nlist[i];
137                         job->nlist_tab.nlist_new[i] = nlist_new[i];
138                         job->nlist_tab.n_nlist = i + 1;
139                 }
140         }
141         job->index_log.deliver = ndmjob_ixlog_deliver;
142
143         /* TAPE agent */
144         job->tape_agent  = T_tape_agent;
145         job->tape_device = f_tape_device;
146         job->record_size = b_bsize * 512;
147         job->tape_timeout = o_tape_timeout;
148         job->use_eject = o_use_eject;
149         job->tape_target = o_tape_scsi;
150         job->tape_tcp = o_tape_tcp;
151
152         /* ROBOT agent */
153         job->robot_agent = R_robot_agent;
154         job->robot_target = r_robot_target;
155         job->robot_timeout = o_robot_timeout;
156         if (o_tape_addr >= 0) {
157                 job->drive_addr = o_tape_addr;
158                 job->drive_addr_given = 1;
159         }
160         if (o_from_addr >= 0) {
161                 job->from_addr = o_from_addr;
162                 job->from_addr_given = 1;
163         }
164         if (o_to_addr >= 0) {
165                 job->to_addr = o_to_addr;
166                 job->to_addr_given = 1;
167         }
168         if (ROBOT_GIVEN())
169                 job->have_robot = 1;
170
171         /* media */
172         for (i = 0; i < n_m_media; i++)
173                 job->media_tab.media[i] = m_media[i];
174         job->media_tab.n_media = n_m_media;
175
176         return 0;
177 }
178
179
180 int
181 args_to_job_backup_env (void)
182 {
183         int             n_env = n_E_environment;
184         int             i;
185
186         if (C_chdir) {
187                 E_environment[n_env].name = "FILESYSTEM";
188                 E_environment[n_env].value = C_chdir;
189                 n_env++;
190         }
191
192         E_environment[n_env].name = "HIST";
193         E_environment[n_env].value = I_index_file ? "y" : "n";
194         n_env++;
195
196         E_environment[n_env].name = "TYPE";
197         E_environment[n_env].value = B_bu_type;
198         n_env++;
199
200         if (U_user) {
201                 E_environment[n_env].name = "USER";
202                 E_environment[n_env].value = U_user;
203                 n_env++;
204         }
205
206         for (i = 0; (i < n_e_exclude_pattern) && (n_env < NDM_MAX_ENV-2); i++) {
207                 E_environment[n_env].name = "EXCLUDE";
208                 E_environment[n_env].value = e_exclude_pattern[i];
209                 n_env++;
210         }
211         for (i = 0; (i < n_file_arg) && (n_env < NDM_MAX_ENV-1); i++) {
212                 E_environment[n_env].name = "FILES";
213                 E_environment[n_env].value = file_arg[i];
214                 n_env++;
215         }
216
217         if (o_rules) {
218                 E_environment[n_env].name = "RULES";
219                 E_environment[n_env].value = o_rules;
220         }
221
222         nn_E_environment = n_env;
223
224         return n_env;
225 }
226
227 int
228 args_to_job_recover_env (void)
229 {
230         int             n_env = n_E_environment;
231         int             i;
232
233         if (C_chdir) {
234                 E_environment[n_env].name = "PREFIX";
235                 E_environment[n_env].value = C_chdir;
236                 n_env++;
237         }
238
239         E_environment[n_env].name = "HIST";
240         E_environment[n_env].value = I_index_file ? "y" : "n";
241         n_env++;
242
243         E_environment[n_env].name = "TYPE";
244         E_environment[n_env].value = B_bu_type;
245         n_env++;
246
247         if (U_user) {
248                 E_environment[n_env].name = "USER";
249                 E_environment[n_env].value = U_user;
250                 n_env++;
251         }
252
253         for (i = 0; i < n_e_exclude_pattern; i++) {
254                 E_environment[n_env].name = "EXCLUDE";
255                 E_environment[n_env].value = e_exclude_pattern[i];
256                 n_env++;
257         }
258
259         if (o_rules) {
260                 E_environment[n_env].name = "RULES";
261                 E_environment[n_env].value = o_rules;
262         }
263
264         nn_E_environment = n_env;
265
266         /* file_arg[]s are done in nlist[] */
267
268         jndex_merge_environment ();
269
270         return nn_E_environment;
271 }
272
273 void
274 normalize_name (char *name)
275 {
276         char *          p = name;
277
278         while (*p) {
279                 if (*p == '/' && p[1] == '/') {
280                         strcpy (p, p+1);
281                         continue;
282                 }
283                 if (p[0] == '/' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
284                         strcpy (p, p+2);
285                         continue;
286                 }
287
288                 p++;
289         }
290 }
291
292 int
293 args_to_job_recover_nlist (void)
294 {
295         int             not_found = 0;
296         int             i, prefix_len, len;
297         char *          dest;
298
299         if (C_chdir) {
300                 prefix_len = strlen (C_chdir) + 2;
301         } else {
302                 prefix_len = 0;
303         }
304
305         for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
306             if (file_arg_new[i]) {
307                 len = strlen (file_arg_new[i]) + prefix_len + 1;
308
309                 dest = NDMOS_API_MALLOC (len);
310                 *dest = 0;
311                 if (C_chdir) {
312                         strcpy (dest, C_chdir);
313                 }
314                 if (file_arg_new[i][0] != '/') {
315                         strcat (dest, "/");
316                 }
317                 strcat (dest, file_arg_new[i]);
318
319                 normalize_name (file_arg_new[i]);
320                 normalize_name (file_arg[i]);
321                 normalize_name (dest);
322
323                 nlist[i].original_path = file_arg[i];
324                 nlist[i].destination_path = dest;
325             } else {
326                 len = strlen (file_arg[i]) + prefix_len + 1;
327
328                 dest = NDMOS_API_MALLOC (len);
329                 *dest = 0;
330                 if (C_chdir) {
331                         strcpy (dest, C_chdir);
332                 }
333                 if (file_arg[i][0] != '/') {
334                         strcat (dest, "/");
335                 }
336
337                 strcat (dest, file_arg[i]);
338
339                 normalize_name (file_arg[i]);
340                 normalize_name (dest);
341
342                 nlist[i].original_path = file_arg[i];
343                 nlist[i].destination_path = dest;
344             }
345         }
346
347         return not_found;       /* should ALWAYS be 0 */
348 }
349
350
351 /*
352  * Index files are sequentially searched. They can be VERY big.
353  * There is a credible effort for efficiency here.
354  * Probably lots and lots and lots of room for improvement.
355  */
356
357 FILE *          jndex_open (void);
358
359
360 int
361 jndex_doit (void)
362 {
363         FILE *          fp;
364         int             rc;
365
366         fp = jndex_open();
367         if (!fp) {
368                 /* error messages already given */
369                 return -1;
370         }
371
372         ndmjob_log (1, "Processing input index (-J%s)", J_index_file);
373
374         if (n_file_arg > 0) {
375                 rc = ndmfhdb_add_fh_info_to_nlist (fp, nlist, n_file_arg);
376                 if (rc < 0) {
377                         /* toast one way or another */
378                 }
379         }
380
381         jndex_fetch_post_backup_data_env(fp);
382         jndex_fetch_post_backup_media(fp);
383
384         jndex_tattle();
385
386         if (jndex_audit_not_found ()) {
387                 ndmjob_log (1,
388                         "Warning: Missing index entries, valid file name(s)?");
389         }
390
391         jndex_merge_media ();
392
393         return 0;
394 }
395
396 FILE *
397 jndex_open (void)
398 {
399         char            buf[256];
400         FILE *          fp;
401
402         if (!J_index_file) {
403                 /* Hmmm. */
404                 ndmjob_log (1, "Warning: No -J input index?");
405                 return 0;
406         }
407
408         ndmjob_log (1, "Reading input index (-I%s)", J_index_file);
409         fp = fopen(J_index_file, "r");
410         if (!fp) {
411                 perror (J_index_file);
412                 error_byebye ("Can not open -J%s input index", J_index_file);
413                 /* no return */
414         }
415
416         if (fgets (buf, sizeof buf, fp) == NULL) {
417                 fclose (fp);
418                 error_byebye ("Failed read 1st line of -J%s", J_index_file);
419                 /* no return */
420         }
421
422         if (strcmp (buf, "##ndmjob -I\n") != 0) {
423                 fclose (fp);
424                 error_byebye ("Bad 1st line in -J%s", J_index_file);
425                 /* no return */
426         }
427
428         if (fgets (buf, sizeof buf, fp) == NULL) {
429                 fclose (fp);
430                 error_byebye ("Failed read 2nd line of -J%s", J_index_file);
431                 /* no return */
432         }
433
434         if (strcmp (buf, "##ndmjob -J\n") != 0) {
435                 fclose (fp);
436                 error_byebye ("Bad 2nd line in -J%s", J_index_file);
437                 /* no return */
438         }
439
440         ndmjob_log (2, "Opened index (-J%s)", J_index_file);
441
442         return fp;
443 }
444
445
446 int
447 jndex_tattle (void)
448 {
449         char            buf[100];
450         int             i;
451
452         for (i = 0; i < n_ji_media; i++) {
453                 struct ndmmedia *       me = &ji_media[i];
454
455                 ndmmedia_to_str (me, buf);
456                 ndmjob_log (3, "ji me[%d] %s", i, buf);
457         }
458
459         for (i = 0; i < n_ji_environment; i++) {
460                 ndmp9_pval *            pv = &ji_environment[i];
461
462                 ndmjob_log (3, "ji env[%d] %s=%s", i, pv->name, pv->value);
463         }
464
465         for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
466                 if (nlist[i].fh_info.valid) {
467                         ndmjob_log (3, "ji fil[%d] fi=%lld %s",
468                                 i, nlist[i].fh_info.value, file_arg[i]);
469                 } else {
470                         ndmjob_log (3, "ji fil[%d] not-found %s",
471                                 i, file_arg[i]);
472                 }
473         }
474
475         return 0;
476 }
477
478 int
479 jndex_merge_media (void)
480 {
481         struct ndmmedia *       me;
482         struct ndmmedia *       jme;
483         int                     i, j;
484
485         for (j = 0; j < n_ji_media; j++) {
486                 jme = &ji_media[j];
487
488                 if (! jme->valid_label)
489                         continue;       /* can't match it up */
490
491                 for (i = 0; i < n_m_media; i++) {
492                         me = &m_media[i];
493
494                         if (! me->valid_label)
495                                 continue;       /* can't match it up */
496
497                         if (strcmp (jme->label, me->label) != 0)
498                                 continue;
499
500                         if (!jme->valid_slot &&  me->valid_slot) {
501                                 jme->slot_addr = me->slot_addr;
502                                 jme->valid_slot = 1;
503                         }
504                 }
505         }
506
507         for (i = 0; i < n_ji_media; i++) {
508                 m_media[i] = ji_media[i];
509         }
510         n_m_media = i;
511
512         ndmjob_log (3, "After merging input -J index with -m entries");
513         for (i = 0; i < n_m_media; i++) {
514                 char            buf[40];
515
516                 me = &m_media[i];
517                 ndmmedia_to_str (me, buf);
518                 ndmjob_log (3, "%d: -m %s", i+1, buf);
519         }
520
521         return 0;
522 }
523
524 int
525 jndex_audit_not_found (void)
526 {
527         int             i;
528         int             not_found = 0;
529
530         for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
531                 if (!nlist[i].fh_info.valid) {
532                         ndmjob_log (0, "No index entry for %s", file_arg[i]);
533                         not_found++;
534                 }
535         }
536
537         return not_found;
538 }
539
540 int
541 jndex_merge_environment (void)
542 {
543         int             i;
544
545         for (i = 0; i < n_ji_environment; i++) {
546                 E_environment[nn_E_environment++] = ji_environment[i];
547         }
548
549         return 0;
550 }
551
552 int
553 jndex_fetch_post_backup_data_env (FILE *fp)
554 {
555         int             rc;
556         char            buf[512];
557         char *          p;
558         char *          q;
559
560         rc = ndmbstf_first (fp, "DE ", buf, sizeof buf);
561         if (rc <= 0) {
562                 return rc;      /* error or not found */
563         }
564
565         /* DE HIST=Yes */
566         while (buf[0] == 'D' && buf[1] == 'E' && buf[2] == ' ') {
567                 if (n_ji_environment >= NDM_MAX_ENV) {
568                         goto overflow;
569                 }
570
571                 p = &buf[2];
572                 while (*p == ' ') p++;
573
574                 if (!strchr (p, '=')) {
575                         goto malformed;
576                 }
577
578                 p = NDMOS_API_STRDUP (p);
579                 q = strchr (p, '=');
580                 *q++ = 0;
581
582                 ji_environment[n_ji_environment].name = p;
583                 ji_environment[n_ji_environment].value = q;
584
585                 n_ji_environment++;
586
587                 rc = ndmbstf_getline (fp, buf, sizeof buf);
588                 if (rc <= 0) {
589                         break;
590                 }
591                 continue;
592
593   malformed:
594                 ndmjob_log (1, "Malformed in -J%s: %s", J_index_file, buf);
595                 continue;
596
597   overflow:
598                 ndmjob_log (1, "Overflow in -J%s: %s", J_index_file, buf);
599         }
600
601         return 0;
602 }
603
604 int
605 jndex_fetch_post_backup_media (FILE *fp)
606 {
607         int             rc;
608         char            buf[512];
609
610         rc = ndmbstf_first (fp, "CM ", buf, sizeof buf);
611         if (rc <= 0) {
612                 return rc;      /* error or not found */
613         }
614
615         /* CM 01 T103/10850K */
616         while (buf[0] == 'C' && buf[1] == 'M' && buf[2] == ' ') {
617                 struct ndmmedia *       me;
618
619                 if (n_ji_media >= NDM_MAX_MEDIA) {
620                         goto overflow;
621                 }
622
623                 me = &ji_media[n_ji_media];
624                 if (ndmmedia_from_str (me, &buf[6])) {
625                         goto malformed;
626                 }
627                 n_ji_media++;
628
629                 rc = ndmbstf_getline (fp, buf, sizeof buf);
630                 if (rc <= 0) {
631                         break;
632                 }
633                 continue;
634
635   malformed:
636                 ndmjob_log (1, "Malformed in -J%s: %s", J_index_file, buf);
637                 continue;
638
639   overflow:
640                 ndmjob_log (1, "Overflow in -J%s: %s", J_index_file, buf);
641         }
642
643         return 0;
644 }
645
646 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */