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