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
build_job(void)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
args_to_job(void)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 jndex_merge_environment();
112 }
113 break;
114
115 case NDM_JOB_OP_EXTRACT:
116 args_to_job_recover_env();
117 args_to_job_recover_nlist();
118 jndex_doit();
119 jndex_merge_environment();
120 break;
121
122 case 'D': /* -o daemon */
123 return 0;
124
125 default:
126 printf ("mode -%c not implemented yet\n", the_mode);
127 break;
128 }
129 job->operation = the_mode;
130
131 /* DATA agent */
132 job->data_agent = D_data_agent;
133 job->bu_type = B_bu_type;
134 job->env_tab = E_environment;
135 if (the_mode == NDM_JOB_OP_EXTRACT || the_mode == NDM_JOB_OP_TOC) {
136 for (i = 0; i < n_file_arg; i++) {
137 ndma_store_nlist (&job->nlist_tab, &nlist[i]);
138 }
139 job->nlist_tab.n_nlist = n_file_arg;
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 job->media_tab = m_media;
173
174 return 0;
175 }
176
177
178 int
args_to_job_backup_env(void)179 args_to_job_backup_env (void)
180 {
181 ndmp9_pval pv;
182 int i;
183
184 if (C_chdir) {
185 pv.name = "FILESYSTEM";
186 pv.value = C_chdir;
187 ndma_store_env_list (&E_environment, &pv);
188 }
189
190 pv.name = "HIST";
191 pv.value = I_index_file ? "y" : "n";
192 ndma_store_env_list (&E_environment, &pv);
193
194 pv.name = "TYPE";
195 pv.value = B_bu_type;
196 ndma_store_env_list (&E_environment, &pv);
197
198 if (U_user) {
199 pv.name = "USER";
200 pv.value = U_user;
201 ndma_store_env_list (&E_environment, &pv);
202 }
203
204 for (i = 0; (i < n_e_exclude_pattern); i++) {
205 pv.name = "EXCLUDE";
206 pv.value = e_exclude_pattern[i];
207 ndma_store_env_list (&E_environment, &pv);
208 }
209 for (i = 0; (i < n_file_arg); i++) {
210 pv.name = "FILES";
211 pv.value = file_arg[i];
212 ndma_store_env_list (&E_environment, &pv);
213 }
214
215 if (o_rules) {
216 pv.name = "RULES";
217 pv.value = o_rules;
218 ndma_store_env_list (&E_environment, &pv);
219 }
220
221 return E_environment.n_env;
222 }
223
224 int
args_to_job_recover_env(void)225 args_to_job_recover_env (void)
226 {
227 ndmp9_pval pv;
228 int i;
229
230 if (C_chdir) {
231 pv.name = "PREFIX";
232 pv.value = C_chdir;
233 ndma_store_env_list (&E_environment, &pv);
234 }
235
236 pv.name = "HIST";
237 pv.value = I_index_file ? "y" : "n";
238 ndma_store_env_list (&E_environment, &pv);
239
240 pv.name = "TYPE";
241 pv.value = B_bu_type;
242 ndma_store_env_list (&E_environment, &pv);
243
244 if (U_user) {
245 pv.name = "USER";
246 pv.value = U_user;
247 ndma_store_env_list (&E_environment, &pv);
248 }
249
250 for (i = 0; i < n_e_exclude_pattern; i++) {
251 pv.name = "EXCLUDE";
252 pv.value = e_exclude_pattern[i];
253 ndma_store_env_list (&E_environment, &pv);
254 }
255
256 if (o_rules) {
257 pv.name = "RULES";
258 pv.value = o_rules;
259 ndma_store_env_list (&E_environment, &pv);
260 }
261
262 /* file_arg[]s are done in nlist[] */
263
264 jndex_merge_environment ();
265
266 return E_environment.n_env;
267 }
268
269 void
normalize_name(char * name)270 normalize_name (char *name)
271 {
272 char * p = name;
273
274 while (*p) {
275 if (*p == '/' && p[1] == '/') {
276 strcpy (p, p+1);
277 continue;
278 }
279 if (p[0] == '/' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
280 strcpy (p, p+2);
281 continue;
282 }
283
284 p++;
285 }
286 }
287
288 int
args_to_job_recover_nlist(void)289 args_to_job_recover_nlist (void)
290 {
291 int not_found = 0;
292 int i, prefix_len, len;
293 char * dest;
294
295 if (C_chdir) {
296 prefix_len = strlen (C_chdir) + 2;
297 } else {
298 prefix_len = 0;
299 }
300
301 for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
302 if (file_arg_new[i]) {
303 len = strlen (file_arg_new[i]) + prefix_len + 1;
304
305 dest = NDMOS_API_MALLOC (len);
306 *dest = 0;
307 if (C_chdir) {
308 strcpy (dest, C_chdir);
309 }
310 if (file_arg_new[i][0] != '/') {
311 strcat (dest, "/");
312 }
313 strcat (dest, file_arg_new[i]);
314
315 normalize_name (file_arg_new[i]);
316 normalize_name (file_arg[i]);
317 normalize_name (dest);
318
319 nlist[i].original_path = file_arg[i];
320 nlist[i].destination_path = dest;
321 nlist[i].name = "";
322 nlist[i].other_name = "";
323 nlist[i].node = NDMP_INVALID_U_QUAD;
324 } else {
325 len = strlen (file_arg[i]) + prefix_len + 1;
326
327 dest = NDMOS_API_MALLOC (len);
328 *dest = 0;
329 if (C_chdir) {
330 strcpy (dest, C_chdir);
331 }
332 if (file_arg[i][0] != '/') {
333 strcat (dest, "/");
334 }
335
336 strcat (dest, file_arg[i]);
337
338 normalize_name (file_arg[i]);
339 normalize_name (dest);
340
341 nlist[i].original_path = file_arg[i];
342 nlist[i].destination_path = dest;
343 nlist[i].name = "";
344 nlist[i].other_name = "";
345 nlist[i].node = NDMP_INVALID_U_QUAD;
346 }
347 }
348
349 return not_found; /* should ALWAYS be 0 */
350 }
351
352
353 /*
354 * Index files are sequentially searched. They can be VERY big.
355 * There is a credible effort for efficiency here.
356 * Probably lots and lots and lots of room for improvement.
357 */
358
359 FILE * jndex_open (void);
360
361
362 int
jndex_doit(void)363 jndex_doit (void)
364 {
365 FILE * fp;
366 int rc;
367
368 fp = jndex_open();
369 if (!fp) {
370 /* error messages already given */
371 return -1;
372 }
373
374 ndmjob_log (1, "Processing input index (-J%s)", J_index_file);
375
376 if (n_file_arg > 0) {
377 rc = ndmfhdb_add_fh_info_to_nlist (fp, nlist, n_file_arg);
378 if (rc < 0) {
379 /* toast one way or another */
380 }
381 }
382
383 jndex_fetch_post_backup_data_env(fp);
384 jndex_fetch_post_backup_media(fp);
385
386 jndex_tattle();
387
388 if (jndex_audit_not_found ()) {
389 ndmjob_log (1,
390 "Warning: Missing index entries, valid file name(s)?");
391 }
392
393 jndex_merge_media ();
394
395 fclose(fp);
396 return 0;
397 }
398
399 FILE *
jndex_open(void)400 jndex_open (void)
401 {
402 char buf[256];
403 FILE * fp;
404
405 if (!J_index_file) {
406 /* Hmmm. */
407 ndmjob_log (1, "Warning: No -J input index?");
408 return 0;
409 }
410
411 ndmjob_log (1, "Reading input index (-I%s)", J_index_file);
412 fp = fopen(J_index_file, "r");
413 if (!fp) {
414 perror (J_index_file);
415 error_byebye ("Can not open -J%s input index", J_index_file);
416 /* no return */
417 }
418
419 if (fgets (buf, sizeof buf, fp) == NULL) {
420 fclose (fp);
421 error_byebye ("Failed read 1st line of -J%s", J_index_file);
422 /* no return */
423 }
424
425 if (strcmp (buf, "##ndmjob -I\n") != 0) {
426 fclose (fp);
427 error_byebye ("Bad 1st line in -J%s", J_index_file);
428 /* no return */
429 }
430
431 if (fgets (buf, sizeof buf, fp) == NULL) {
432 fclose (fp);
433 error_byebye ("Failed read 2nd line of -J%s", J_index_file);
434 /* no return */
435 }
436
437 if (strcmp (buf, "##ndmjob -J\n") != 0) {
438 fclose (fp);
439 error_byebye ("Bad 2nd line in -J%s", J_index_file);
440 /* no return */
441 }
442
443 ndmjob_log (2, "Opened index (-J%s)", J_index_file);
444
445 return fp;
446 }
447
448
449 int
jndex_tattle(void)450 jndex_tattle (void)
451 {
452 char buf[100];
453 struct ndmmedia * me;
454 struct ndm_env_entry * nev;
455 int i;
456
457 for (me = ji_media.head; me; me = me->next) {
458 ndmmedia_to_str (me, buf);
459 ndmjob_log (3, "ji me[%d] %s", i, buf);
460 }
461
462 for (nev = ji_environment.head; nev; nev = nev->next) {
463 ndmjob_log (3, "ji env[%d] %s=%s", i, nev->pval.name, nev->pval.value);
464 }
465
466 for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
467 if (nlist[i].fh_info.valid) {
468 ndmjob_log (3, "ji fil[%d] fi=%lld %s",
469 i, nlist[i].fh_info.value, file_arg[i]);
470 } else {
471 ndmjob_log (3, "ji fil[%d] not-found %s",
472 i, file_arg[i]);
473 }
474 }
475
476 return 0;
477 }
478
479 int
jndex_merge_media(void)480 jndex_merge_media (void)
481 {
482 struct ndmmedia * me;
483 struct ndmmedia * jme;
484 int i;
485
486 for (jme = ji_media.head; jme; jme = jme->next) {
487 if (! jme->valid_label)
488 continue; /* can't match it up */
489
490 for (me = m_media.head; me; me = me->next) {
491 if (! me->valid_label)
492 continue; /* can't match it up */
493
494 if (strcmp (jme->label, me->label) != 0)
495 continue;
496
497 if (!jme->valid_slot && me->valid_slot) {
498 jme->slot_addr = me->slot_addr;
499 jme->valid_slot = 1;
500 }
501 }
502 }
503
504 ndmca_destroy_media_table (&m_media);
505 m_media = ji_media;
506
507 ndmjob_log (3, "After merging input -J index with -m entries");
508 i = 0;
509 for (me = m_media.head; me; me = me->next) {
510 char buf[40];
511
512 ndmmedia_to_str (me, buf);
513 ndmjob_log (3, "%d: -m %s", i + 1, buf);
514 i++;
515 }
516
517 return 0;
518 }
519
520 int
jndex_audit_not_found(void)521 jndex_audit_not_found (void)
522 {
523 int i;
524 int not_found = 0;
525
526 for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
527 if (!nlist[i].fh_info.valid) {
528 ndmjob_log (0, "No index entry for %s", file_arg[i]);
529 not_found++;
530 }
531 }
532
533 return not_found;
534 }
535
536 int
jndex_merge_environment(void)537 jndex_merge_environment (void)
538 {
539 struct ndm_env_entry * entry;
540
541 for (entry = ji_environment.head; entry; entry = entry->next) {
542 if (strcmp(entry->pval.name, "FILESYSTEM") != 0 &&
543 strcmp(entry->pval.name, "PREFIX") != 0 &&
544 strcmp(entry->pval.name, "HIST") != 0 &&
545 strcmp(entry->pval.name, "TYPE") != 0) {
546 ndma_store_env_list (&E_environment, &entry->pval);
547 }
548 }
549
550 return 0;
551 }
552
553 int
jndex_fetch_post_backup_data_env(FILE * fp)554 jndex_fetch_post_backup_data_env (FILE *fp)
555 {
556 int rc;
557 char buf[512];
558 char * p;
559 char * q;
560 ndmp9_pval pv;
561
562 rc = ndmbstf_first (fp, "DE ", buf, sizeof buf);
563 if (rc <= 0) {
564 return rc; /* error or not found */
565 }
566
567 /* DE HIST=Yes */
568 while (buf[0] == 'D' && buf[1] == 'E' && buf[2] == ' ') {
569 if (ji_environment.n_env >= NDM_MAX_ENV) {
570 goto overflow;
571 }
572
573 p = &buf[2];
574 while (*p == ' ') p++;
575
576 if (!strchr (p, '=')) {
577 goto malformed;
578 }
579
580 q = strchr (p, '=');
581 if (!q) {
582 goto malformed;
583 }
584 *q++ = 0;
585
586 pv.name = p;
587 pv.value = q;
588 ndma_store_env_list (&ji_environment, &pv);
589
590 rc = ndmbstf_getline (fp, buf, sizeof buf);
591 if (rc <= 0) {
592 break;
593 }
594 continue;
595
596 malformed:
597 ndmjob_log (1, "Malformed in -J%s: %s", J_index_file, buf);
598 continue;
599
600 overflow:
601 ndmjob_log (1, "Overflow in -J%s: %s", J_index_file, buf);
602 }
603
604 return 0;
605 }
606
607 int
jndex_fetch_post_backup_media(FILE * fp)608 jndex_fetch_post_backup_media (FILE *fp)
609 {
610 int rc;
611 char buf[512];
612 struct ndmmedia me;
613
614 rc = ndmbstf_first (fp, "CM ", buf, sizeof buf);
615 if (rc <= 0) {
616 return rc; /* error or not found */
617 }
618
619 /* CM 01 T103/10850K */
620 while (buf[0] == 'C' && buf[1] == 'M' && buf[2] == ' ') {
621
622 if (ji_media.n_media >= NDM_MAX_MEDIA) {
623 goto overflow;
624 }
625
626 if (ndmmedia_from_str (&me, &buf[6])) {
627 goto malformed;
628 }
629 ndma_clone_media_entry (&ji_media, &me);
630
631 rc = ndmbstf_getline (fp, buf, sizeof buf);
632 if (rc <= 0) {
633 break;
634 }
635 continue;
636
637 malformed:
638 ndmjob_log (1, "Malformed in -J%s: %s", J_index_file, buf);
639 continue;
640
641 overflow:
642 ndmjob_log (1, "Overflow in -J%s: %s", J_index_file, buf);
643 }
644
645 return 0;
646 }
647
648 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
649