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