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