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
build_job(void)44 int build_job(void)
45 {
46 struct ndm_job_param* job = &the_job;
47 int i, rc, n_err;
48 char errbuf[100];
49
50 NDMOS_MACRO_ZEROFILL(job);
51
52 args_to_job();
53
54 ndma_job_auto_adjust(job);
55
56 if (o_rules) apply_rules(job, o_rules);
57
58 i = n_err = 0;
59 do {
60 rc = ndma_job_audit(job, errbuf, i);
61 if (rc > n_err || rc < 0) { ndmjob_log(0, "error: %s", errbuf); }
62 n_err = rc;
63 } while (i++ < n_err);
64
65 if (n_err) {
66 error_byebye("can't proceed");
67 /* no return */
68 }
69
70 return 0;
71 }
72
73
args_to_job(void)74 int args_to_job(void)
75 {
76 struct ndm_job_param* job = &the_job;
77 int i;
78
79 switch (the_mode) {
80 case NDM_JOB_OP_QUERY_AGENTS:
81 case NDM_JOB_OP_INIT_LABELS:
82 case NDM_JOB_OP_LIST_LABELS:
83 case NDM_JOB_OP_REMEDY_ROBOT:
84 case NDM_JOB_OP_TEST_TAPE:
85 case NDM_JOB_OP_TEST_MOVER:
86 case NDM_JOB_OP_TEST_DATA:
87 case NDM_JOB_OP_REWIND_TAPE:
88 case NDM_JOB_OP_EJECT_TAPE:
89 case NDM_JOB_OP_MOVE_TAPE:
90 case NDM_JOB_OP_IMPORT_TAPE:
91 case NDM_JOB_OP_EXPORT_TAPE:
92 case NDM_JOB_OP_LOAD_TAPE:
93 case NDM_JOB_OP_UNLOAD_TAPE:
94 case NDM_JOB_OP_INIT_ELEM_STATUS:
95 break;
96
97 case NDM_JOB_OP_BACKUP:
98 args_to_job_backup_env();
99 break;
100
101 case NDM_JOB_OP_TOC:
102 args_to_job_recover_env();
103 args_to_job_recover_nlist();
104 if (J_index_file) {
105 jndex_doit();
106 jndex_merge_environment();
107 }
108 break;
109
110 case NDM_JOB_OP_EXTRACT:
111 args_to_job_recover_env();
112 args_to_job_recover_nlist();
113 jndex_doit();
114 jndex_merge_environment();
115 break;
116
117 case 'D': /* -o daemon */
118 return 0;
119
120 default:
121 printf("mode -%c not implemented yet\n", the_mode);
122 break;
123 }
124 job->operation = the_mode;
125
126 /* DATA agent */
127 job->data_agent = D_data_agent;
128 job->bu_type = B_bu_type;
129 job->env_tab = E_environment;
130 if (the_mode == NDM_JOB_OP_EXTRACT || the_mode == NDM_JOB_OP_TOC) {
131 for (i = 0; i < n_file_arg; i++) {
132 ndma_store_nlist(&job->nlist_tab, &nlist[i]);
133 }
134 job->nlist_tab.n_nlist = n_file_arg;
135 }
136 job->index_log.deliver = ndmjob_ixlog_deliver;
137
138 /* TAPE agent */
139 job->tape_agent = T_tape_agent;
140 job->tape_device = f_tape_device;
141 job->record_size = b_bsize * 512;
142 job->tape_timeout = o_tape_timeout;
143 job->use_eject = o_use_eject;
144 job->tape_target = o_tape_scsi;
145 job->tape_tcp = o_tape_tcp;
146
147 /* ROBOT agent */
148 job->robot_agent = R_robot_agent;
149 job->robot_target = r_robot_target;
150 job->robot_timeout = o_robot_timeout;
151 if (o_tape_addr >= 0) {
152 job->drive_addr = o_tape_addr;
153 job->drive_addr_given = 1;
154 }
155 if (o_from_addr >= 0) {
156 job->from_addr = o_from_addr;
157 job->from_addr_given = 1;
158 }
159 if (o_to_addr >= 0) {
160 job->to_addr = o_to_addr;
161 job->to_addr_given = 1;
162 }
163 if (ROBOT_GIVEN()) job->have_robot = 1;
164
165 /* media */
166 job->media_tab = m_media;
167
168 return 0;
169 }
170
171
args_to_job_backup_env(void)172 int args_to_job_backup_env(void)
173 {
174 ndmp9_pval pv;
175 int i;
176
177 if (C_chdir) {
178 pv.name = "FILESYSTEM";
179 pv.value = C_chdir;
180 ndma_store_env_list(&E_environment, &pv);
181 }
182
183 pv.name = "HIST";
184 pv.value = I_index_file ? "y" : "n";
185 ndma_store_env_list(&E_environment, &pv);
186
187 pv.name = "TYPE";
188 pv.value = B_bu_type;
189 ndma_store_env_list(&E_environment, &pv);
190
191 if (U_user) {
192 pv.name = "USER";
193 pv.value = U_user;
194 ndma_store_env_list(&E_environment, &pv);
195 }
196
197 for (i = 0; (i < n_e_exclude_pattern); i++) {
198 pv.name = "EXCLUDE";
199 pv.value = e_exclude_pattern[i];
200 ndma_store_env_list(&E_environment, &pv);
201 }
202 for (i = 0; (i < n_file_arg); i++) {
203 pv.name = "FILES";
204 pv.value = file_arg[i];
205 ndma_store_env_list(&E_environment, &pv);
206 }
207
208 if (o_rules) {
209 pv.name = "RULES";
210 pv.value = o_rules;
211 ndma_store_env_list(&E_environment, &pv);
212 }
213
214 return E_environment.n_env;
215 }
216
args_to_job_recover_env(void)217 int args_to_job_recover_env(void)
218 {
219 ndmp9_pval pv;
220 int i;
221
222 if (C_chdir) {
223 pv.name = "PREFIX";
224 pv.value = C_chdir;
225 ndma_store_env_list(&E_environment, &pv);
226 }
227
228 pv.name = "HIST";
229 pv.value = I_index_file ? "y" : "n";
230 ndma_store_env_list(&E_environment, &pv);
231
232 pv.name = "TYPE";
233 pv.value = B_bu_type;
234 ndma_store_env_list(&E_environment, &pv);
235
236 if (U_user) {
237 pv.name = "USER";
238 pv.value = U_user;
239 ndma_store_env_list(&E_environment, &pv);
240 }
241
242 for (i = 0; i < n_e_exclude_pattern; i++) {
243 pv.name = "EXCLUDE";
244 pv.value = e_exclude_pattern[i];
245 ndma_store_env_list(&E_environment, &pv);
246 }
247
248 if (o_rules) {
249 pv.name = "RULES";
250 pv.value = o_rules;
251 ndma_store_env_list(&E_environment, &pv);
252 }
253
254 /* file_arg[]s are done in nlist[] */
255
256 jndex_merge_environment();
257
258 return E_environment.n_env;
259 }
260
normalize_name(char * name)261 void normalize_name(char* name)
262 {
263 char* p = name;
264
265 while (*p) {
266 if (*p == '/' && p[1] == '/') {
267 strcpy(p, p + 1);
268 continue;
269 }
270 if (p[0] == '/' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
271 strcpy(p, p + 2);
272 continue;
273 }
274
275 p++;
276 }
277 }
278
args_to_job_recover_nlist(void)279 int args_to_job_recover_nlist(void)
280 {
281 int not_found = 0;
282 int i, prefix_len, len;
283 char* dest;
284
285 if (C_chdir) {
286 prefix_len = strlen(C_chdir) + 2;
287 } else {
288 prefix_len = 0;
289 }
290
291 for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
292 if (file_arg_new[i]) {
293 len = strlen(file_arg_new[i]) + prefix_len + 1;
294
295 dest = NDMOS_API_MALLOC(len);
296 *dest = 0;
297 if (C_chdir) { strcpy(dest, C_chdir); }
298 if (file_arg_new[i][0] != '/') { strcat(dest, "/"); }
299 strcat(dest, file_arg_new[i]);
300
301 normalize_name(file_arg_new[i]);
302 normalize_name(file_arg[i]);
303 normalize_name(dest);
304
305 nlist[i].original_path = file_arg[i];
306 nlist[i].destination_path = dest;
307 nlist[i].name = "";
308 nlist[i].other_name = "";
309 nlist[i].node = NDMP_INVALID_U_QUAD;
310 } else {
311 len = strlen(file_arg[i]) + prefix_len + 1;
312
313 dest = NDMOS_API_MALLOC(len);
314 *dest = 0;
315 if (C_chdir) { strcpy(dest, C_chdir); }
316 if (file_arg[i][0] != '/') { strcat(dest, "/"); }
317
318 strcat(dest, file_arg[i]);
319
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 nlist[i].name = "";
326 nlist[i].other_name = "";
327 nlist[i].node = NDMP_INVALID_U_QUAD;
328 }
329 }
330
331 return not_found; /* should ALWAYS be 0 */
332 }
333
334
335 /*
336 * Index files are sequentially searched. They can be VERY big.
337 * There is a credible effort for efficiency here.
338 * Probably lots and lots and lots of room for improvement.
339 */
340
341 FILE* jndex_open(void);
342
343
jndex_doit(void)344 int jndex_doit(void)
345 {
346 FILE* fp;
347 int rc;
348
349 fp = jndex_open();
350 if (!fp) {
351 /* error messages already given */
352 return -1;
353 }
354
355 ndmjob_log(1, "Processing input index (-J%s)", J_index_file);
356
357 if (n_file_arg > 0) {
358 rc = ndmfhdb_add_fh_info_to_nlist(fp, nlist, n_file_arg);
359 if (rc < 0) { /* toast one way or another */
360 }
361 }
362
363 jndex_fetch_post_backup_data_env(fp);
364 jndex_fetch_post_backup_media(fp);
365
366 jndex_tattle();
367
368 if (jndex_audit_not_found()) {
369 ndmjob_log(1, "Warning: Missing index entries, valid file name(s)?");
370 }
371
372 jndex_merge_media();
373
374 fclose(fp);
375 return 0;
376 }
377
jndex_open(void)378 FILE* jndex_open(void)
379 {
380 char buf[256];
381 FILE* fp;
382
383 if (!J_index_file) {
384 /* Hmmm. */
385 ndmjob_log(1, "Warning: No -J input index?");
386 return 0;
387 }
388
389 ndmjob_log(1, "Reading input index (-I%s)", J_index_file);
390 fp = fopen(J_index_file, "r");
391 if (!fp) {
392 perror(J_index_file);
393 error_byebye("Can not open -J%s input index", J_index_file);
394 /* no return */
395 }
396
397 if (fgets(buf, sizeof buf, fp) == NULL) {
398 fclose(fp);
399 error_byebye("Failed read 1st line of -J%s", J_index_file);
400 /* no return */
401 }
402
403 if (strcmp(buf, "##ndmjob -I\n") != 0) {
404 fclose(fp);
405 error_byebye("Bad 1st line in -J%s", J_index_file);
406 /* no return */
407 }
408
409 if (fgets(buf, sizeof buf, fp) == NULL) {
410 fclose(fp);
411 error_byebye("Failed read 2nd line of -J%s", J_index_file);
412 /* no return */
413 }
414
415 if (strcmp(buf, "##ndmjob -J\n") != 0) {
416 fclose(fp);
417 error_byebye("Bad 2nd line in -J%s", J_index_file);
418 /* no return */
419 }
420
421 ndmjob_log(2, "Opened index (-J%s)", J_index_file);
422
423 return fp;
424 }
425
426
jndex_tattle(void)427 int jndex_tattle(void)
428 {
429 char buf[100];
430 struct ndmmedia* me;
431 struct ndm_env_entry* nev;
432 int i;
433
434 for (me = ji_media.head; me; me = me->next) {
435 ndmmedia_to_str(me, buf);
436 ndmjob_log(3, "ji me[%d] %s", i, buf);
437 }
438
439 for (nev = ji_environment.head; nev; nev = nev->next) {
440 ndmjob_log(3, "ji env[%d] %s=%s", i, nev->pval.name, nev->pval.value);
441 }
442
443 for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
444 if (nlist[i].fh_info.valid) {
445 ndmjob_log(3, "ji fil[%d] fi=%lld %s", i, nlist[i].fh_info.value,
446 file_arg[i]);
447 } else {
448 ndmjob_log(3, "ji fil[%d] not-found %s", i, file_arg[i]);
449 }
450 }
451
452 return 0;
453 }
454
jndex_merge_media(void)455 int jndex_merge_media(void)
456 {
457 struct ndmmedia* me;
458 struct ndmmedia* jme;
459 int i;
460
461 for (jme = ji_media.head; jme; jme = jme->next) {
462 if (!jme->valid_label) continue; /* can't match it up */
463
464 for (me = m_media.head; me; me = me->next) {
465 if (!me->valid_label) continue; /* can't match it up */
466
467 if (strcmp(jme->label, me->label) != 0) continue;
468
469 if (!jme->valid_slot && me->valid_slot) {
470 jme->slot_addr = me->slot_addr;
471 jme->valid_slot = 1;
472 }
473 }
474 }
475
476 ndmca_destroy_media_table(&m_media);
477 m_media = ji_media;
478
479 ndmjob_log(3, "After merging input -J index with -m entries");
480 i = 0;
481 for (me = m_media.head; me; me = me->next) {
482 char buf[40];
483
484 ndmmedia_to_str(me, buf);
485 ndmjob_log(3, "%d: -m %s", i + 1, buf);
486 i++;
487 }
488
489 return 0;
490 }
491
jndex_audit_not_found(void)492 int jndex_audit_not_found(void)
493 {
494 int i;
495 int not_found = 0;
496
497 for (i = 0; (i < n_file_arg) && (i < NDM_MAX_NLIST); i++) {
498 if (!nlist[i].fh_info.valid) {
499 ndmjob_log(0, "No index entry for %s", file_arg[i]);
500 not_found++;
501 }
502 }
503
504 return not_found;
505 }
506
jndex_merge_environment(void)507 int jndex_merge_environment(void)
508 {
509 struct ndm_env_entry* entry;
510
511 for (entry = ji_environment.head; entry; entry = entry->next) {
512 if (strcmp(entry->pval.name, "FILESYSTEM") != 0 &&
513 strcmp(entry->pval.name, "PREFIX") != 0 &&
514 strcmp(entry->pval.name, "HIST") != 0 &&
515 strcmp(entry->pval.name, "TYPE") != 0) {
516 ndma_store_env_list(&E_environment, &entry->pval);
517 }
518 }
519
520 return 0;
521 }
522
jndex_fetch_post_backup_data_env(FILE * fp)523 int jndex_fetch_post_backup_data_env(FILE* fp)
524 {
525 int rc;
526 char buf[512];
527 char* p;
528 char* q;
529 ndmp9_pval pv;
530
531 rc = ndmbstf_first(fp, "DE ", buf, sizeof buf);
532 if (rc <= 0) { return rc; /* error or not found */ }
533
534 /* DE HIST=Yes */
535 while (buf[0] == 'D' && buf[1] == 'E' && buf[2] == ' ') {
536 if (ji_environment.n_env >= NDM_MAX_ENV) { goto overflow; }
537
538 p = &buf[2];
539 while (*p == ' ') p++;
540
541 if (!strchr(p, '=')) { goto malformed; }
542
543 q = strchr(p, '=');
544 if (!q) { goto malformed; }
545 *q++ = 0;
546
547 pv.name = p;
548 pv.value = q;
549 ndma_store_env_list(&ji_environment, &pv);
550
551 rc = ndmbstf_getline(fp, buf, sizeof buf);
552 if (rc <= 0) { break; }
553 continue;
554
555 malformed:
556 ndmjob_log(1, "Malformed in -J%s: %s", J_index_file, buf);
557 continue;
558
559 overflow:
560 ndmjob_log(1, "Overflow in -J%s: %s", J_index_file, buf);
561 }
562
563 return 0;
564 }
565
jndex_fetch_post_backup_media(FILE * fp)566 int jndex_fetch_post_backup_media(FILE* fp)
567 {
568 int rc;
569 char buf[512];
570 struct ndmmedia me;
571
572 rc = ndmbstf_first(fp, "CM ", buf, sizeof buf);
573 if (rc <= 0) { return rc; /* error or not found */ }
574
575 /* CM 01 T103/10850K */
576 while (buf[0] == 'C' && buf[1] == 'M' && buf[2] == ' ') {
577 if (ji_media.n_media >= NDM_MAX_MEDIA) { goto overflow; }
578
579 if (ndmmedia_from_str(&me, &buf[6])) { goto malformed; }
580 ndma_clone_media_entry(&ji_media, &me);
581
582 rc = ndmbstf_getline(fp, buf, sizeof buf);
583 if (rc <= 0) { break; }
584 continue;
585
586 malformed:
587 ndmjob_log(1, "Malformed in -J%s: %s", J_index_file, buf);
588 continue;
589
590 overflow:
591 ndmjob_log(1, "Overflow in -J%s: %s", J_index_file, buf);
592 }
593
594 return 0;
595 }
596
597 #endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
598