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