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 "ndmagents.h"
39 #include "wraplib.h"
40
41 #ifndef NDMOS_OPTION_NO_DATA_AGENT
42
43
44
45 /*
46 * Initialization and Cleanup
47 ****************************************************************
48 */
49
50 /* Initialize -- Set data structure to know value, ignore current value */
51 int
ndmda_initialize(struct ndm_session * sess)52 ndmda_initialize (struct ndm_session *sess)
53 {
54 struct ndm_data_agent * da = &sess->data_acb;
55
56 NDMOS_MACRO_ZEROFILL (da);
57 da->data_state.state = NDMP9_DATA_STATE_IDLE;
58 ndmchan_initialize (&da->formatter_error, "dfp-error");
59 ndmchan_initialize (&da->formatter_wrap, "dfp-wrap");
60 ndmchan_initialize (&da->formatter_image, "dfp-image");
61 ndmda_fh_initialize (sess);
62
63 return 0;
64 }
65
66 /* Commission -- Get agent ready. Entire session has been initialize()d */
67 int
ndmda_commission(struct ndm_session * sess)68 ndmda_commission (struct ndm_session *sess)
69 {
70 struct ndm_data_agent * da = &sess->data_acb;
71
72 da->data_state.state = NDMP9_DATA_STATE_IDLE;
73 ndmda_fh_commission (sess);
74
75 return 0;
76 }
77
78 /* Decommission -- Discard agent */
79 int
ndmda_decommission(struct ndm_session * sess)80 ndmda_decommission (struct ndm_session *sess)
81 {
82 ndmis_data_close (sess);
83 ndmda_purge_environment (sess);
84 ndmda_purge_nlist (sess);
85 ndmda_fh_decommission (sess);
86 NDMOS_API_BZERO (sess->data_acb.bu_type,sizeof sess->data_acb.bu_type);
87
88 ndmda_commission (sess);
89
90 return 0;
91 }
92
93 /* Belay -- Cancel partially issued activation/start */
94 int
ndmda_belay(struct ndm_session * sess)95 ndmda_belay (struct ndm_session *sess)
96 {
97 ndmda_fh_belay (sess);
98 return ndmda_decommission (sess);
99 }
100
101
102
103
104 /*
105 * Semantic actions -- called from ndma_dispatch()
106 ****************************************************************
107 */
108
109 static int
add_env(struct ndm_env_table * envtab,char * cmd)110 add_env (struct ndm_env_table *envtab, char *cmd)
111 {
112 char buf[1024];
113 int i;
114
115 for (i = 0; i < envtab->n_env; i++) {
116 strcpy (buf, envtab->env[i].name);
117 strcat (buf, "=");
118 strcat (buf, envtab->env[i].value);
119 ndmda_add_to_cmd (cmd, "-E");
120 ndmda_add_to_cmd (cmd, buf);
121 }
122
123 return 0;
124 }
125
126 static int
add_nlist(struct ndm_nlist_table * nlisttab,char * cmd)127 add_nlist (struct ndm_nlist_table *nlisttab, char *cmd)
128 {
129 char buf[32];
130 int i;
131
132 for (i = 0; i < nlisttab->n_nlist; i++) {
133 ndmp9_name * nl = &nlisttab->nlist[i];
134
135 ndmda_add_to_cmd (cmd, nl->original_path);
136 if (nl->fh_info.valid == NDMP9_VALIDITY_VALID) {
137 sprintf (buf, "@%llu", nl->fh_info.value);
138 ndmda_add_to_cmd (cmd, buf);
139 } else {
140 ndmda_add_to_cmd (cmd, "@-");
141 }
142 ndmda_add_to_cmd (cmd, nl->destination_path);
143 }
144
145 return 0;
146 }
147
148
149 ndmp9_error
ndmda_data_start_backup(struct ndm_session * sess)150 ndmda_data_start_backup (struct ndm_session *sess)
151 {
152 struct ndm_data_agent * da = &sess->data_acb;
153 ndmp9_error error = NDMP9_NO_ERR;
154 char cmd[NDMDA_MAX_CMD];
155
156 strcpy (cmd, "/amanda/h1/linux-3.3/libexec/amanda/application/wrap_");
157 strcat (cmd, da->bu_type);
158
159 if (sess->param.log_level > 0) {
160 char tmpbuf[40];
161 sprintf(tmpbuf, "-d%d", sess->param.log_level);
162 ndmda_add_to_cmd (cmd, tmpbuf);
163 }
164
165 ndmda_add_to_cmd (cmd, "-c");
166 ndmda_add_to_cmd (cmd, "-I#3");
167 add_env (&da->env_tab, cmd);
168
169 ndma_send_logmsg (sess, NDMP9_LOG_DEBUG, sess->plumb.data,
170 "CMD: %s", cmd);
171
172 if (ndmda_pipe_fork_exec (sess, cmd, 1) < 0) {
173 return NDMP9_UNDEFINED_ERR;
174 }
175
176 ndmis_data_start (sess, NDMCHAN_MODE_WRITE);
177
178 da->data_state.state = NDMP9_DATA_STATE_ACTIVE;
179 da->data_state.operation = NDMP9_DATA_OP_BACKUP;
180
181 return error;
182 }
183
184 ndmp9_error
ndmda_data_start_recover(struct ndm_session * sess)185 ndmda_data_start_recover (struct ndm_session *sess)
186 {
187 struct ndm_data_agent * da = &sess->data_acb;
188 ndmp9_error error = NDMP9_NO_ERR;
189 char cmd[NDMDA_MAX_CMD];
190
191 strcpy (cmd, "/amanda/h1/linux-3.3/libexec/amanda/application/wrap_");
192 strcat (cmd, da->bu_type);
193
194 if (sess->param.log_level > 0) {
195 char tmpbuf[40];
196 sprintf(tmpbuf, "-d%d", sess->param.log_level);
197 ndmda_add_to_cmd (cmd, tmpbuf);
198 }
199
200 ndmda_add_to_cmd (cmd, "-x");
201 ndmda_add_to_cmd (cmd, "-I#3");
202 add_env (&da->env_tab, cmd);
203 add_nlist (&da->nlist_tab, cmd);
204
205 ndma_send_logmsg (sess, NDMP9_LOG_DEBUG, sess->plumb.data,
206 "CMD: %s", cmd);
207
208 if (ndmda_pipe_fork_exec (sess, cmd, 0) < 0) {
209 return NDMP9_UNDEFINED_ERR;
210 }
211
212 ndmis_data_start (sess, NDMCHAN_MODE_READ);
213
214 da->data_state.state = NDMP9_DATA_STATE_ACTIVE;
215 da->data_state.operation = NDMP9_DATA_OP_RECOVER;
216
217 return error;
218 }
219
220 ndmp9_error
ndmda_data_start_recover_fh(struct ndm_session * sess)221 ndmda_data_start_recover_fh (struct ndm_session *sess)
222 {
223 struct ndm_data_agent * da = &sess->data_acb;
224 ndmp9_error error = NDMP9_NO_ERR;
225 char cmd[NDMDA_MAX_CMD];
226
227 strcpy (cmd, "/amanda/h1/linux-3.3/libexec/amanda/application/wrap_");
228 strcat (cmd, da->bu_type);
229 ndmda_add_to_cmd (cmd, "-t");
230 ndmda_add_to_cmd (cmd, "-I#3");
231 add_env (&da->env_tab, cmd);
232 add_nlist (&da->nlist_tab, cmd);
233
234 ndma_send_logmsg (sess, NDMP9_LOG_DEBUG, sess->plumb.data,
235 "CMD: %s", cmd);
236
237 if (ndmda_pipe_fork_exec (sess, cmd, 0) < 0) {
238 return NDMP9_UNDEFINED_ERR;
239 }
240
241 ndmis_data_start (sess, NDMCHAN_MODE_READ);
242
243 da->data_state.state = NDMP9_DATA_STATE_ACTIVE;
244 da->data_state.operation = NDMP9_DATA_OP_RECOVER_FILEHIST;
245
246 return error;
247 }
248
249 void
ndmda_sync_state(struct ndm_session * sess)250 ndmda_sync_state (struct ndm_session *sess)
251 {
252 /* no-op, always accurate */
253 }
254
255 void
ndmda_data_abort(struct ndm_session * sess)256 ndmda_data_abort (struct ndm_session *sess)
257 {
258 ndmda_data_halt (sess, NDMP9_DATA_HALT_ABORTED);
259 }
260
261 void
ndmda_sync_environment(struct ndm_session * sess)262 ndmda_sync_environment (struct ndm_session *sess)
263 {
264 /* no-op, always accurate */
265 }
266
267 ndmp9_error
ndmda_data_listen(struct ndm_session * sess)268 ndmda_data_listen (struct ndm_session *sess)
269 {
270 struct ndm_data_agent * da = &sess->data_acb;
271
272 da->data_state.state = NDMP9_DATA_STATE_LISTEN;
273 da->data_state.halt_reason = NDMP9_DATA_HALT_NA;
274
275 return NDMP9_NO_ERR;
276 }
277
278 ndmp9_error
ndmda_data_connect(struct ndm_session * sess)279 ndmda_data_connect (struct ndm_session *sess)
280 {
281 struct ndm_data_agent * da = &sess->data_acb;
282
283 da->data_state.state = NDMP9_DATA_STATE_CONNECTED;
284 da->data_state.halt_reason = NDMP9_DATA_HALT_NA;
285
286 return NDMP9_NO_ERR;
287 }
288
289 void
ndmda_data_halt(struct ndm_session * sess,ndmp9_data_halt_reason reason)290 ndmda_data_halt (struct ndm_session *sess, ndmp9_data_halt_reason reason)
291 {
292 struct ndm_data_agent * da = &sess->data_acb;
293
294 da->data_state.state = NDMP9_DATA_STATE_HALTED;
295 da->data_state.halt_reason = reason;
296 da->data_notify_pending = 1;
297
298 ndmda_fh_flush (sess);
299
300 ndmis_data_close (sess);
301
302 ndmchan_cleanup (&da->formatter_image);
303 ndmchan_cleanup (&da->formatter_error);
304 ndmchan_cleanup (&da->formatter_wrap);
305
306 /* this needs to be better */
307 if (da->formatter_pid) {
308 sleep (1); /* give gtar a chance to stop by itself */
309 kill (da->formatter_pid, SIGTERM);
310 }
311 }
312
313 void
ndmda_data_stop(struct ndm_session * sess)314 ndmda_data_stop (struct ndm_session *sess)
315 {
316 ndmda_decommission (sess);
317 }
318
319
320
321
322 /*
323 * Quantum -- get a bit of work done
324 ****************************************************************
325 */
326
327 int
ndmda_quantum(struct ndm_session * sess)328 ndmda_quantum (struct ndm_session *sess)
329 {
330 struct ndm_data_agent * da = &sess->data_acb;
331 int did_something = 0; /* did nothing */
332
333
334 switch (da->data_state.state) {
335 default:
336 ndmalogf (sess, 0, 0, "BOTCH data state");
337 return -1;
338
339 case NDMP9_DATA_STATE_IDLE:
340 case NDMP9_DATA_STATE_HALTED:
341 case NDMP9_DATA_STATE_CONNECTED:
342 break;
343
344 case NDMP9_DATA_STATE_LISTEN:
345 switch (sess->plumb.image_stream.data_ep.connect_status) {
346 case NDMIS_CONN_LISTEN: /* no connection yet */
347 break;
348
349 case NDMIS_CONN_ACCEPTED: /* we're in business */
350 /* drum roll please... */
351 da->data_state.state = NDMP9_DATA_STATE_CONNECTED;
352 /* tah-dah */
353 did_something++; /* did something */
354 break;
355
356 case NDMIS_CONN_BOTCHED: /* accept() went south */
357 default: /* ain't suppose to happen */
358 ndmda_data_halt (sess, NDMP9_DATA_HALT_CONNECT_ERROR);
359 did_something++; /* did something */
360 break;
361 }
362 break;
363
364 case NDMP9_DATA_STATE_ACTIVE:
365 did_something |= ndmda_quantum_stderr (sess);
366 did_something |= ndmda_quantum_wrap (sess);
367 did_something |= ndmda_quantum_image (sess);
368 break;
369 }
370
371 ndmda_send_notice (sess);
372
373 return did_something;
374 }
375
376 int
ndmda_quantum_stderr(struct ndm_session * sess)377 ndmda_quantum_stderr (struct ndm_session *sess)
378 {
379 struct ndm_data_agent * da = &sess->data_acb;
380 struct ndmchan * ch = &da->formatter_error;
381 int did_something = 0;
382 char * p;
383 char * data;
384 char * pend;
385 unsigned n_ready;
386
387 again:
388 n_ready = ndmchan_n_ready (ch);
389 if (n_ready == 0)
390 return did_something;
391
392 data = p = &ch->data[ch->beg_ix];
393 pend = p + n_ready;
394
395 while (p < pend && *p != '\n') p++;
396
397
398 if (p < pend && *p == '\n') {
399 *p++ = 0;
400 ndma_send_logmsg (sess, NDMP9_LOG_NORMAL, sess->plumb.data,
401 "%s", data);
402 ch->beg_ix += p - data;
403 did_something++;
404 goto again;
405 }
406
407 if (!ch->eof)
408 return did_something;
409
410 /* content w/o newline, and EOF */
411 /* p == pend */
412 if (ch->end_ix >= ch->data_size) {
413 if (data != ch->data) {
414 ndmchan_compress (ch);
415 goto again;
416 }
417 /* that's one huge message */
418 p--; /* lose last byte */
419 }
420
421 ch->data[ch->end_ix++] = '\n';
422 did_something++;
423 goto again;
424 }
425
426 int
ndmda_quantum_wrap(struct ndm_session * sess)427 ndmda_quantum_wrap (struct ndm_session *sess)
428 {
429 struct ndm_data_agent * da = &sess->data_acb;
430 struct ndmchan * ch = &da->formatter_wrap;
431 int did_something = 0;
432 char * p;
433 char * data;
434 char * pend;
435 unsigned n_ready;
436 int is_recover = 0;
437
438 switch (da->data_state.operation) {
439 default:
440 assert (0);
441 break;
442
443 case NDMP9_DATA_OP_BACKUP:
444 break;
445
446 case NDMP9_DATA_OP_RECOVER:
447 case NDMP9_DATA_OP_RECOVER_FILEHIST:
448 is_recover = 1;
449 break;
450 }
451
452 again:
453 n_ready = ndmchan_n_ready (ch);
454 if (n_ready == 0) {
455 if (ch->eof && is_recover) {
456 ndmda_data_halt (sess, NDMP9_DATA_HALT_SUCCESSFUL);
457 }
458 return did_something;
459 }
460 data = p = &ch->data[ch->beg_ix];
461 pend = p + n_ready;
462
463 while (p < pend && *p != '\n') p++;
464
465
466 if (p < pend && *p == '\n') {
467 *p++ = 0;
468 ndmda_wrap_in (sess, data);
469 ch->beg_ix += p - data;
470 did_something++;
471 goto again;
472 }
473
474 if (!ch->eof)
475 return did_something;
476
477 /* content w/o newline, and EOF */
478 /* p == pend */
479 if (ch->end_ix >= ch->data_size) {
480 if (data != ch->data) {
481 ndmchan_compress (ch);
482 goto again;
483 }
484 /* that's one huge message */
485 p--; /* lose last byte */
486 }
487
488 ch->data[ch->end_ix++] = '\n';
489 did_something++;
490 goto again;
491 }
492
493
494
495 int
ndmda_quantum_image(struct ndm_session * sess)496 ndmda_quantum_image (struct ndm_session *sess)
497 {
498 struct ndm_data_agent * da = &sess->data_acb;
499 struct ndmchan * from_chan;
500 struct ndmchan * to_chan;
501 unsigned n_ready, n_avail, n_copy;
502 int is_backup = 0;
503
504 switch (da->data_state.operation) {
505 default:
506 assert (0);
507 from_chan = 0;
508 to_chan = 0;
509 break;
510
511 case NDMP9_DATA_OP_BACKUP:
512 from_chan = &da->formatter_image;
513 to_chan = &sess->plumb.image_stream.chan;
514 is_backup = 1;
515 break;
516
517 case NDMP9_DATA_OP_RECOVER:
518 case NDMP9_DATA_OP_RECOVER_FILEHIST:
519 from_chan = &sess->plumb.image_stream.chan;
520 to_chan = &da->formatter_image;
521 break;
522 }
523
524 again:
525 n_copy = n_ready = ndmchan_n_ready (from_chan);
526 if (n_ready == 0) {
527 if (from_chan->eof) {
528 to_chan->eof = 1;
529 if (ndmchan_n_ready (to_chan) == 0) {
530 if (is_backup) {
531 ndmda_data_halt (sess,
532 NDMP9_DATA_HALT_SUCCESSFUL);
533 }
534 }
535 }
536 return 0; /* data blocked */
537 }
538
539 n_avail = ndmchan_n_avail (to_chan);
540 if (n_copy > n_avail)
541 n_copy = n_avail;
542
543 if (da->enable_hist) {
544 if (n_copy > da->pass_resid)
545 n_copy = da->pass_resid;
546 }
547
548 if (n_copy > 0) {
549 bcopy (&from_chan->data[from_chan->beg_ix],
550 &to_chan->data[to_chan->end_ix],
551 n_copy);
552 from_chan->beg_ix += n_copy;
553 to_chan->end_ix += n_copy;
554 da->data_state.bytes_processed += n_copy;
555 da->pass_resid -= n_copy;
556 goto again; /* do as much as possible */
557 }
558
559 return 0;
560
561 }
562
563
564
565
566 /*
567 * Process WRAP messages from the formatter. Called from
568 * ndmda_quantum_wrap(). The formatter sends one line text
569 * messages via the WRAP pipe (fd=3 on formatter).
570 * The WRAP message contain log messages, file history,
571 * status updates, etc, etc, etc.
572 *
573 * Here the messages are parsed and directed to the
574 * right NDMP interface toward the Control Agent.
575 */
576
577 void ndmp9_fstat_from_wrap_fstat (ndmp9_file_stat *fstat9,
578 struct wrap_fstat *fstatw);
579
580 int
ndmda_wrap_in(struct ndm_session * sess,char * wrap_line)581 ndmda_wrap_in (struct ndm_session *sess, char *wrap_line)
582 {
583 struct wrap_msg_buf _wmsg, *wmsg = &_wmsg;
584 int rc;
585 ndmp9_file_stat fstat9;
586
587 NDMOS_MACRO_ZEROFILL (wmsg);
588
589 rc = wrap_parse_msg (wrap_line, wmsg);
590 if (rc != 0) {
591 ndmalogf (sess, 0, 2, "Malformed wrap: %s", wrap_line);
592 return -1;
593 }
594
595 switch (wmsg->msg_type) {
596 case WRAP_MSGTYPE_LOG_MESSAGE:
597 ndmalogf (sess, "WRAP", 2, "%s",
598 wmsg->body.log_message.message);
599 ndma_send_logmsg (sess, NDMP9_LOG_NORMAL, sess->plumb.data,
600 "WRAP: %s", wmsg->body.log_message.message);
601 break;
602
603 case WRAP_MSGTYPE_ADD_FILE:
604 ndmp9_fstat_from_wrap_fstat (&fstat9,
605 &wmsg->body.add_file.fstat);
606 fstat9.fh_info.valid = NDMP9_VALIDITY_VALID;
607 fstat9.fh_info.value = wmsg->body.add_file.fhinfo;
608 ndmda_fh_add_file (sess, &fstat9, wmsg->body.add_file.path);
609 break;
610
611 case WRAP_MSGTYPE_ADD_DIRENT:
612 ndmda_fh_add_dir (sess,
613 wmsg->body.add_dirent.dir_fileno,
614 wmsg->body.add_dirent.name,
615 wmsg->body.add_dirent.fileno);
616 break;
617
618 case WRAP_MSGTYPE_ADD_NODE:
619 ndmp9_fstat_from_wrap_fstat (&fstat9,
620 &wmsg->body.add_node.fstat);
621 fstat9.fh_info.valid = NDMP9_VALIDITY_VALID;
622 fstat9.fh_info.value = wmsg->body.add_node.fhinfo;
623 ndmda_fh_add_node (sess, &fstat9);
624 break;
625
626 case WRAP_MSGTYPE_DATA_READ:
627 ndmda_send_data_read (sess,
628 wmsg->body.data_read.offset,
629 wmsg->body.data_read.length);
630 break;
631
632 case WRAP_MSGTYPE_ADD_ENV:
633 case WRAP_MSGTYPE_DATA_STATS:
634 case WRAP_MSGTYPE_RECOVERY_RESULT:
635 ndmalogf (sess, 0, 2, "Unimplemented wrap: %s", wrap_line);
636 break;
637 }
638
639 return 0;
640 }
641
642 void
ndmp9_fstat_from_wrap_fstat(ndmp9_file_stat * fstat9,struct wrap_fstat * fstatw)643 ndmp9_fstat_from_wrap_fstat (ndmp9_file_stat *fstat9,
644 struct wrap_fstat *fstatw)
645 {
646 NDMOS_MACRO_ZEROFILL (fstat9);
647
648 switch (fstatw->ftype) {
649 default:
650 case WRAP_FTYPE_INVALID:fstat9->ftype = NDMP9_FILE_OTHER; break;
651 case WRAP_FTYPE_DIR: fstat9->ftype = NDMP9_FILE_DIR; break;
652 case WRAP_FTYPE_FIFO: fstat9->ftype = NDMP9_FILE_FIFO; break;
653 case WRAP_FTYPE_CSPEC: fstat9->ftype = NDMP9_FILE_CSPEC; break;
654 case WRAP_FTYPE_BSPEC: fstat9->ftype = NDMP9_FILE_BSPEC; break;
655 case WRAP_FTYPE_REG: fstat9->ftype = NDMP9_FILE_REG; break;
656 case WRAP_FTYPE_SLINK: fstat9->ftype = NDMP9_FILE_SLINK; break;
657 case WRAP_FTYPE_SOCK: fstat9->ftype = NDMP9_FILE_SOCK; break;
658 case WRAP_FTYPE_REGISTRY:fstat9->ftype = NDMP9_FILE_REGISTRY; break;
659 case WRAP_FTYPE_OTHER: fstat9->ftype = NDMP9_FILE_OTHER; break;
660 }
661
662 if (fstatw->valid & WRAP_FSTAT_VALID_FTYPE) {
663 }
664
665 if (fstatw->valid & WRAP_FSTAT_VALID_MODE) {
666 fstat9->mode.valid = NDMP9_VALIDITY_VALID;
667 fstat9->mode.value = fstatw->mode;
668 }
669
670 if (fstatw->valid & WRAP_FSTAT_VALID_SIZE) {
671 fstat9->size.valid = NDMP9_VALIDITY_VALID;
672 fstat9->size.value = fstatw->size;
673 }
674
675 if (fstatw->valid & WRAP_FSTAT_VALID_LINKS) {
676 fstat9->links.valid = NDMP9_VALIDITY_VALID;
677 fstat9->links.value = fstatw->size;
678 }
679
680 if (fstatw->valid & WRAP_FSTAT_VALID_UID) {
681 fstat9->uid.valid = NDMP9_VALIDITY_VALID;
682 fstat9->uid.value = fstatw->uid;
683 }
684
685 if (fstatw->valid & WRAP_FSTAT_VALID_GID) {
686 fstat9->gid.valid = NDMP9_VALIDITY_VALID;
687 fstat9->gid.value = fstatw->gid;
688 }
689
690 if (fstatw->valid & WRAP_FSTAT_VALID_ATIME) {
691 fstat9->atime.valid = NDMP9_VALIDITY_VALID;
692 fstat9->atime.value = fstatw->atime;
693 }
694
695 if (fstatw->valid & WRAP_FSTAT_VALID_MTIME) {
696 fstat9->mtime.valid = NDMP9_VALIDITY_VALID;
697 fstat9->mtime.value = fstatw->mtime;
698 }
699
700 if (fstatw->valid & WRAP_FSTAT_VALID_CTIME) {
701 fstat9->ctime.valid = NDMP9_VALIDITY_VALID;
702 fstat9->ctime.value = fstatw->ctime;
703 }
704
705 if (fstatw->valid & WRAP_FSTAT_VALID_FILENO) {
706 fstat9->node.valid = NDMP9_VALIDITY_VALID;
707 fstat9->node.value = fstatw->fileno;
708 }
709
710
711
712
713 }
714
715
716
717
718 /*
719 * Send LOG and NOTIFY messages
720 ****************************************************************
721 */
722
723 #if 0
724 void
725 ndmda_send_logmsg (struct ndm_session *sess, char *fmt, ...)
726 {
727 struct ndmconn * conn = sess->plumb.control;
728 char buf[4096];
729 va_list ap;
730
731 va_start (ap, fmt);
732 vsnprintf (buf, sizeof(buf), fmt, ap);
733 va_end (ap);
734
735 // we don't handle our own messages so don't send them....
736 if (conn->conn_type == NDMCONN_TYPE_RESIDENT) {
737 ndmalogf(sess, 0, 2, "RESIDENT AGENT LOGMSG: %s", buf);
738 return;
739 }
740
741 ndma_send_logmsg (sess, buf, conn);
742 }
743 #endif
744
745 void
ndmda_send_notice(struct ndm_session * sess)746 ndmda_send_notice (struct ndm_session *sess)
747 {
748 struct ndm_data_agent * da = &sess->data_acb;
749
750 if (!da->data_notify_pending)
751 return;
752
753 da->data_notify_pending = 0;
754
755 switch (da->data_state.state) {
756 case NDMP9_DATA_STATE_HALTED:
757 ndma_notify_data_halted (sess);
758 break;
759
760 default:
761 /* Hmm. Why are we here. Race? */
762 break;
763 }
764 }
765
766 void
ndmda_send_data_read(struct ndm_session * sess,unsigned long long offset,unsigned long long length)767 ndmda_send_data_read (struct ndm_session *sess,
768 unsigned long long offset, unsigned long long length)
769 {
770 struct ndm_data_agent * da = &sess->data_acb;
771 ndmp9_addr_type addr_type;
772
773 addr_type = da->data_state.data_connection_addr.addr_type;
774 #if 0
775 da->reco_read_offset = offset;
776 da->reco_read_length = length;
777 #endif
778
779 if (NDMP9_ADDR_LOCAL == addr_type) {
780 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
781 if (ndmta_local_mover_read (sess, offset, length) != 0) {
782 ndma_send_logmsg (sess, NDMP9_LOG_ERROR,
783 sess->plumb.data,
784 "local_mover_read failed");
785 ndmda_data_halt (sess, NDMP9_DATA_HALT_INTERNAL_ERROR);
786 }
787 #else /* !NDMOS_OPTION_NO_TAPE_AGENT */
788 ndma_send_logmsg (sess, NDMP9_LOG_ERROR,
789 sess->plumb.data,
790 "local_mover_read not configured");
791 ndmda_data_halt (sess, NDMP9_DATA_HALT_INTERNAL_ERROR);
792 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
793 return;
794 }
795
796 switch (addr_type) {
797 case NDMP9_ADDR_TCP:
798 ndma_notify_data_read (sess, offset, length);
799 break;
800
801 default:
802 ndma_send_logmsg (sess, NDMP9_LOG_ERROR, sess->plumb.data,
803 "bogus mover.addr_type");
804 ndmda_data_halt (sess, NDMP9_DATA_HALT_INTERNAL_ERROR);
805 break;
806 }
807 }
808
809
810
811
812 /*
813 * Misc -- env[] and nlist[] subroutines, etc
814 ****************************************************************
815 */
816
817 int
ndmda_copy_environment(struct ndm_session * sess,ndmp9_pval * env,unsigned n_env)818 ndmda_copy_environment (struct ndm_session *sess,
819 ndmp9_pval *env, unsigned n_env)
820 {
821 struct ndm_data_agent * da = &sess->data_acb;
822 int i;
823 unsigned int j;
824 ndmp9_pval * src_pv;
825 ndmp9_pval * dst_pv;
826
827 for (j = 0; j < n_env; j++) {
828 src_pv = &env[j];
829 dst_pv = &da->env_tab.env[da->env_tab.n_env];
830
831 dst_pv->name = NDMOS_API_STRDUP (src_pv->name);
832 dst_pv->value = NDMOS_API_STRDUP (src_pv->value);
833
834 if (!dst_pv->name || !dst_pv->value)
835 goto fail;
836
837 da->env_tab.n_env++;
838 }
839
840 return 0;
841
842 fail:
843 for (i = 0; i < da->env_tab.n_env; i++) {
844 char * p;
845
846 dst_pv = &da->env_tab.env[da->env_tab.n_env];
847
848 if ((p = dst_pv->name) != 0)
849 NDMOS_API_FREE (p);
850
851 if ((p = dst_pv->value) != 0)
852 NDMOS_API_FREE (p);
853 }
854 da->env_tab.n_env = 0;
855
856 return -1;
857 }
858
859 struct ndmp9_pval *
ndmda_find_env(struct ndm_session * sess,char * name)860 ndmda_find_env (struct ndm_session *sess, char *name)
861 {
862 struct ndm_data_agent * da = &sess->data_acb;
863 int i;
864 struct ndmp9_pval * pv;
865
866 for (i = 0; i < da->env_tab.n_env; i++) {
867 pv = &da->env_tab.env[i];
868 if (strcmp (pv->name, name) == 0)
869 return pv;
870 }
871
872 return 0;
873 }
874
875
876 int
ndmda_interpret_boolean_value(char * value_str,int default_value)877 ndmda_interpret_boolean_value (char *value_str, int default_value)
878 {
879 if (strcasecmp (value_str, "y") == 0
880 || strcasecmp (value_str, "yes") == 0
881 || strcasecmp (value_str, "t") == 0
882 || strcasecmp (value_str, "true") == 0
883 || strcasecmp (value_str, "1") == 0)
884 return 1;
885
886 if (strcasecmp (value_str, "n") == 0
887 || strcasecmp (value_str, "no") == 0
888 || strcasecmp (value_str, "f") == 0
889 || strcasecmp (value_str, "false") == 0
890 || strcasecmp (value_str, "0") == 0)
891 return 0;
892
893 return default_value;
894 }
895
896 void
ndmda_purge_environment(struct ndm_session * sess)897 ndmda_purge_environment (struct ndm_session *sess)
898 {
899 struct ndm_data_agent * da = &sess->data_acb;
900 int i;
901 struct ndmp9_pval * pv;
902
903 for (i = 0; i < da->env_tab.n_env; i++) {
904 pv = &da->env_tab.env[i];
905
906 if (pv->name) NDMOS_API_FREE (pv->name);
907 if (pv->value) NDMOS_API_FREE (pv->value);
908 pv->name = 0;
909 pv->value = 0;
910 }
911 da->env_tab.n_env = 0;
912 }
913
914
915 int
ndmda_copy_nlist(struct ndm_session * sess,ndmp9_name * nlist,unsigned n_nlist)916 ndmda_copy_nlist (struct ndm_session *sess,
917 ndmp9_name *nlist, unsigned n_nlist)
918 {
919 struct ndm_data_agent * da = &sess->data_acb;
920 unsigned int i;
921 int j;
922 ndmp9_name * src_nl;
923 ndmp9_name * dst_nl;
924
925 for (i = 0; i < n_nlist; i++) {
926 j = da->nlist_tab.n_nlist;
927 src_nl = &nlist[i];
928 dst_nl = &da->nlist_tab.nlist[j];
929
930 dst_nl->original_path =
931 NDMOS_API_STRDUP (src_nl->original_path);
932 dst_nl->destination_path =
933 NDMOS_API_STRDUP (src_nl->destination_path);
934 dst_nl->fh_info = src_nl->fh_info;
935 da->nlist_tab.result_err[j] = NDMP9_UNDEFINED_ERR;
936 da->nlist_tab.result_count[j] = 0;
937
938 if (!dst_nl->original_path || !dst_nl->destination_path)
939 return -1; /* no mem */
940
941 da->nlist_tab.n_nlist++;
942 }
943
944 /* TODO: sort */
945
946 return 0;
947 }
948
949 void
ndmda_purge_nlist(struct ndm_session * sess)950 ndmda_purge_nlist (struct ndm_session *sess)
951 {
952 struct ndm_data_agent * da = &sess->data_acb;
953 int i;
954 struct ndmp9_name * nl;
955
956 for (i = 0; i < da->nlist_tab.n_nlist; i++) {
957 nl = &da->nlist_tab.nlist[i];
958
959 if (nl->original_path) {
960 NDMOS_API_FREE (nl->original_path);
961 }
962 if (nl->destination_path) {
963 NDMOS_API_FREE (nl->destination_path);
964 }
965
966 nl->original_path = 0;
967 nl->destination_path = 0;
968 }
969 da->nlist_tab.n_nlist = 0;
970 }
971
972 int
ndmda_count_invalid_fh_info(struct ndm_session * sess)973 ndmda_count_invalid_fh_info (struct ndm_session *sess)
974 {
975 struct ndm_data_agent * da = &sess->data_acb;
976 int i, count;
977 struct ndmp9_name * nl;
978
979 count = 0;
980 for (i = 0; i < da->nlist_tab.n_nlist; i++) {
981 nl = &da->nlist_tab.nlist[i];
982
983 if (nl->fh_info.valid != NDMP9_VALIDITY_VALID)
984 count++;
985 }
986
987 return count;
988 }
989
990 int
ndmda_count_invalid_fh_info_pending(struct ndm_session * sess)991 ndmda_count_invalid_fh_info_pending (struct ndm_session *sess)
992 {
993 struct ndm_data_agent * da = &sess->data_acb;
994 int i, count;
995 struct ndmp9_name * nl;
996
997 count = 0;
998 for (i = 0; i < da->nlist_tab.n_nlist; i++) {
999 nl = &da->nlist_tab.nlist[i];
1000
1001 if (da->nlist_tab.result_err[i] == NDMP9_UNDEFINED_ERR
1002 && nl->fh_info.valid != NDMP9_VALIDITY_VALID) {
1003 count++;
1004 }
1005 }
1006
1007 return count;
1008 }
1009
1010 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */
1011