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 for (i = 0; i < nn_E_environment; i++)
135 job->env_tab.env[i] = E_environment[i];
136 job->env_tab.n_env = nn_E_environment;
137 if (the_mode == NDM_JOB_OP_EXTRACT || the_mode == NDM_JOB_OP_TOC) {
138 for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
139 job->nlist_tab.nlist[i] = nlist[i];
140 job->nlist_tab.nlist_new[i] = nlist_new[i];
141 job->nlist_tab.n_nlist = i + 1;
142 }
143 }
144 job->index_log.deliver = ndmjob_ixlog_deliver;
145
146 /* TAPE agent */
147 job->tape_agent = T_tape_agent;
148 job->tape_device = f_tape_device;
149 job->record_size = b_bsize * 512;
150 job->tape_timeout = o_tape_timeout;
151 job->use_eject = o_use_eject;
152 job->tape_target = o_tape_scsi;
153 job->tape_tcp = o_tape_tcp;
154
155 /* ROBOT agent */
156 job->robot_agent = R_robot_agent;
157 job->robot_target = r_robot_target;
158 job->robot_timeout = o_robot_timeout;
159 if (o_tape_addr >= 0) {
160 job->drive_addr = o_tape_addr;
161 job->drive_addr_given = 1;
162 }
163 if (o_from_addr >= 0) {
164 job->from_addr = o_from_addr;
165 job->from_addr_given = 1;
166 }
167 if (o_to_addr >= 0) {
168 job->to_addr = o_to_addr;
169 job->to_addr_given = 1;
170 }
171 if (ROBOT_GIVEN())
172 job->have_robot = 1;
173
174 /* media */
175 for (i = 0; i < n_m_media; i++)
176 job->media_tab.media[i] = m_media[i];
177 job->media_tab.n_media = n_m_media;
178
179 return 0;
180 }
181
182
183 int
args_to_job_backup_env(void)184 args_to_job_backup_env (void)
185 {
186 int n_env = n_E_environment;
187 int i;
188
189 if (C_chdir) {
190 E_environment[n_env].name = "FILESYSTEM";
191 E_environment[n_env].value = C_chdir;
192 n_env++;
193 }
194
195 E_environment[n_env].name = "HIST";
196 E_environment[n_env].value = I_index_file ? "y" : "n";
197 n_env++;
198
199 E_environment[n_env].name = "TYPE";
200 E_environment[n_env].value = B_bu_type;
201 n_env++;
202
203 if (U_user) {
204 E_environment[n_env].name = "USER";
205 E_environment[n_env].value = U_user;
206 n_env++;
207 }
208
209 for (i = 0; (i < n_e_exclude_pattern) && (n_env < NDM_MAX_ENV-2); i++) {
210 E_environment[n_env].name = "EXCLUDE";
211 E_environment[n_env].value = e_exclude_pattern[i];
212 n_env++;
213 }
214 for (i = 0; (i < n_file_arg) && (n_env < NDM_MAX_ENV-1); i++) {
215 E_environment[n_env].name = "FILES";
216 E_environment[n_env].value = file_arg[i];
217 n_env++;
218 }
219
220 if (o_rules) {
221 E_environment[n_env].name = "RULES";
222 E_environment[n_env].value = o_rules;
223 }
224
225 nn_E_environment = n_env;
226
227 return n_env;
228 }
229
230 int
args_to_job_recover_env(void)231 args_to_job_recover_env (void)
232 {
233 int n_env = n_E_environment;
234 int i;
235
236 if (C_chdir) {
237 E_environment[n_env].name = "PREFIX";
238 E_environment[n_env].value = C_chdir;
239 n_env++;
240 }
241
242 E_environment[n_env].name = "HIST";
243 E_environment[n_env].value = I_index_file ? "y" : "n";
244 n_env++;
245
246 E_environment[n_env].name = "TYPE";
247 E_environment[n_env].value = B_bu_type;
248 n_env++;
249
250 if (U_user) {
251 E_environment[n_env].name = "USER";
252 E_environment[n_env].value = U_user;
253 n_env++;
254 }
255
256 for (i = 0; i < n_e_exclude_pattern; i++) {
257 E_environment[n_env].name = "EXCLUDE";
258 E_environment[n_env].value = e_exclude_pattern[i];
259 n_env++;
260 }
261
262 if (o_rules) {
263 E_environment[n_env].name = "RULES";
264 E_environment[n_env].value = o_rules;
265 }
266
267 nn_E_environment = n_env;
268
269 /* file_arg[]s are done in nlist[] */
270
271 jndex_merge_environment ();
272
273 return nn_E_environment;
274 }
275
276 void
normalize_name(char * name)277 normalize_name (char *name)
278 {
279 char * p = name;
280
281 while (*p) {
282 if (*p == '/' && p[1] == '/') {
283 strcpy (p, p+1);
284 continue;
285 }
286 if (p[0] == '/' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
287 strcpy (p, p+2);
288 continue;
289 }
290
291 p++;
292 }
293 }
294
295 int
args_to_job_recover_nlist(void)296 args_to_job_recover_nlist (void)
297 {
298 int not_found = 0;
299 int i, prefix_len, len;
300 char * dest;
301
302 if (C_chdir) {
303 prefix_len = strlen (C_chdir) + 2;
304 } else {
305 prefix_len = 0;
306 }
307
308 for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
309 if (file_arg_new[i]) {
310 len = strlen (file_arg_new[i]) + prefix_len + 1;
311
312 dest = NDMOS_API_MALLOC (len);
313 *dest = 0;
314 if (C_chdir) {
315 strcpy (dest, C_chdir);
316 }
317 if (file_arg_new[i][0] != '/') {
318 strcat (dest, "/");
319 }
320 strcat (dest, file_arg_new[i]);
321
322 normalize_name (file_arg_new[i]);
323 normalize_name (file_arg[i]);
324 normalize_name (dest);
325
326 nlist[i].original_path = file_arg[i];
327 nlist[i].destination_path = dest;
328 } else {
329 len = strlen (file_arg[i]) + prefix_len + 1;
330
331 dest = NDMOS_API_MALLOC (len);
332 *dest = 0;
333 if (C_chdir) {
334 strcpy (dest, C_chdir);
335 }
336 if (file_arg[i][0] != '/') {
337 strcat (dest, "/");
338 }
339
340 strcat (dest, file_arg[i]);
341
342 normalize_name (file_arg[i]);
343 normalize_name (dest);
344
345 nlist[i].original_path = file_arg[i];
346 nlist[i].destination_path = dest;
347 }
348 }
349
350 return not_found; /* should ALWAYS be 0 */
351 }
352
353
354 /*
355 * Index files are sequentially searched. They can be VERY big.
356 * There is a credible effort for efficiency here.
357 * Probably lots and lots and lots of room for improvement.
358 */
359
360 FILE * jndex_open (void);
361
362
363 int
jndex_doit(void)364 jndex_doit (void)
365 {
366 FILE * fp;
367 int rc;
368
369 fp = jndex_open();
370 if (!fp) {
371 /* error messages already given */
372 return -1;
373 }
374
375 ndmjob_log (1, "Processing input index (-J%s)", J_index_file);
376
377 if (n_file_arg > 0) {
378 rc = ndmfhdb_add_fh_info_to_nlist (fp, nlist, n_file_arg);
379 if (rc < 0) {
380 /* toast one way or another */
381 }
382 }
383
384 jndex_fetch_post_backup_data_env(fp);
385 jndex_fetch_post_backup_media(fp);
386
387 jndex_tattle();
388
389 if (jndex_audit_not_found ()) {
390 ndmjob_log (1,
391 "Warning: Missing index entries, valid file name(s)?");
392 }
393
394 jndex_merge_media ();
395
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 int i;
454
455 for (i = 0; i < n_ji_media; i++) {
456 struct ndmmedia * me = &ji_media[i];
457
458 ndmmedia_to_str (me, buf);
459 ndmjob_log (3, "ji me[%d] %s", i, buf);
460 }
461
462 for (i = 0; i < n_ji_environment; i++) {
463 ndmp9_pval * pv = &ji_environment[i];
464
465 ndmjob_log (3, "ji env[%d] %s=%s", i, pv->name, pv->value);
466 }
467
468 for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
469 if (nlist[i].fh_info.valid) {
470 ndmjob_log (3, "ji fil[%d] fi=%lld %s",
471 i, nlist[i].fh_info.value, file_arg[i]);
472 } else {
473 ndmjob_log (3, "ji fil[%d] not-found %s",
474 i, file_arg[i]);
475 }
476 }
477
478 return 0;
479 }
480
481 int
jndex_merge_media(void)482 jndex_merge_media (void)
483 {
484 struct ndmmedia * me;
485 struct ndmmedia * jme;
486 int i, j;
487
488 for (j = 0; j < n_ji_media; j++) {
489 jme = &ji_media[j];
490
491 if (! jme->valid_label)
492 continue; /* can't match it up */
493
494 for (i = 0; i < n_m_media; i++) {
495 me = &m_media[i];
496
497 if (! me->valid_label)
498 continue; /* can't match it up */
499
500 if (strcmp (jme->label, me->label) != 0)
501 continue;
502
503 if (!jme->valid_slot && me->valid_slot) {
504 jme->slot_addr = me->slot_addr;
505 jme->valid_slot = 1;
506 }
507 }
508 }
509
510 for (i = 0; i < n_ji_media; i++) {
511 m_media[i] = ji_media[i];
512 }
513 n_m_media = i;
514
515 ndmjob_log (3, "After merging input -J index with -m entries");
516 for (i = 0; i < n_m_media; i++) {
517 char buf[40];
518
519 me = &m_media[i];
520 ndmmedia_to_str (me, buf);
521 ndmjob_log (3, "%d: -m %s", i+1, buf);
522 }
523
524 return 0;
525 }
526
527 int
jndex_audit_not_found(void)528 jndex_audit_not_found (void)
529 {
530 int i;
531 int not_found = 0;
532
533 for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
534 if (!nlist[i].fh_info.valid) {
535 ndmjob_log (0, "No index entry for %s", file_arg[i]);
536 not_found++;
537 }
538 }
539
540 return not_found;
541 }
542
543 int
jndex_merge_environment(void)544 jndex_merge_environment (void)
545 {
546 int i;
547
548 for (i = 0; i < n_ji_environment; i++) {
549 if (strcmp(ji_environment[i].name, "FILESYSTEM") != 0 &&
550 strcmp(ji_environment[i].name, "PREFIX") != 0 &&
551 strcmp(ji_environment[i].name, "HIST") != 0 &&
552 strcmp(ji_environment[i].name, "TYPE") != 0) {
553 E_environment[nn_E_environment++] = ji_environment[i];
554 }
555 }
556
557 return 0;
558 }
559
560 int
jndex_fetch_post_backup_data_env(FILE * fp)561 jndex_fetch_post_backup_data_env (FILE *fp)
562 {
563 int rc;
564 char buf[512];
565 char * p;
566 char * q;
567
568 rc = ndmbstf_first (fp, "DE ", buf, sizeof buf);
569 if (rc <= 0) {
570 return rc; /* error or not found */
571 }
572
573 /* DE HIST=Yes */
574 while (buf[0] == 'D' && buf[1] == 'E' && buf[2] == ' ') {
575 if (n_ji_environment >= NDM_MAX_ENV) {
576 goto overflow;
577 }
578
579 p = &buf[2];
580 while (*p == ' ') p++;
581
582 if (!strchr (p, '=')) {
583 goto malformed;
584 }
585
586 p = NDMOS_API_STRDUP (p);
587 q = strchr (p, '=');
588 *q++ = 0;
589
590 ji_environment[n_ji_environment].name = p;
591 ji_environment[n_ji_environment].value = q;
592
593 n_ji_environment++;
594
595 rc = ndmbstf_getline (fp, buf, sizeof buf);
596 if (rc <= 0) {
597 break;
598 }
599 continue;
600
601 malformed:
602 ndmjob_log (1, "Malformed in -J%s: %s", J_index_file, buf);
603 continue;
604
605 overflow:
606 ndmjob_log (1, "Overflow in -J%s: %s", J_index_file, buf);
607 }
608
609 return 0;
610 }
611
612 int
jndex_fetch_post_backup_media(FILE * fp)613 jndex_fetch_post_backup_media (FILE *fp)
614 {
615 int rc;
616 char buf[512];
617
618 rc = ndmbstf_first (fp, "CM ", buf, sizeof buf);
619 if (rc <= 0) {
620 return rc; /* error or not found */
621 }
622
623 /* CM 01 T103/10850K */
624 while (buf[0] == 'C' && buf[1] == 'M' && buf[2] == ' ') {
625 struct ndmmedia * me;
626
627 if (n_ji_media >= NDM_MAX_MEDIA) {
628 goto overflow;
629 }
630
631 me = &ji_media[n_ji_media];
632 if (ndmmedia_from_str (me, &buf[6])) {
633 goto malformed;
634 }
635 n_ji_media++;
636
637 rc = ndmbstf_getline (fp, buf, sizeof buf);
638 if (rc <= 0) {
639 break;
640 }
641 continue;
642
643 malformed:
644 ndmjob_log (1, "Malformed in -J%s: %s", J_index_file, buf);
645 continue;
646
647 overflow:
648 ndmjob_log (1, "Overflow in -J%s: %s", J_index_file, buf);
649 }
650
651 return 0;
652 }
653
654 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
655