2 * Copyright (c) 1998,1999,2000
3 * Traakan, Inc., Los Altos, CA
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
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.
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
38 #include "ndmagents.h"
41 #ifndef NDMOS_OPTION_NO_DATA_AGENT
46 * Initialization and Cleanup
47 ****************************************************************
50 /* Initialize -- Set data structure to know value, ignore current value */
52 ndmda_initialize (struct ndm_session *sess)
54 struct ndm_data_agent * da = &sess->data_acb;
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);
66 /* Commission -- Get agent ready. Entire session has been initialize()d */
68 ndmda_commission (struct ndm_session *sess)
70 struct ndm_data_agent * da = &sess->data_acb;
72 da->data_state.state = NDMP9_DATA_STATE_IDLE;
73 ndmda_fh_commission (sess);
78 /* Decommission -- Discard agent */
80 ndmda_decommission (struct ndm_session *sess)
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);
88 ndmda_commission (sess);
93 /* Belay -- Cancel partially issued activation/start */
95 ndmda_belay (struct ndm_session *sess)
97 ndmda_fh_belay (sess);
98 return ndmda_decommission (sess);
105 * Semantic actions -- called from ndma_dispatch()
106 ****************************************************************
110 add_env (struct ndm_env_table *envtab, char *cmd)
115 for (i = 0; i < envtab->n_env; i++) {
116 strcpy (buf, envtab->env[i].name);
118 strcat (buf, envtab->env[i].value);
119 ndmda_add_to_cmd (cmd, "-E");
120 ndmda_add_to_cmd (cmd, buf);
127 add_nlist (struct ndm_nlist_table *nlisttab, char *cmd)
132 for (i = 0; i < nlisttab->n_nlist; i++) {
133 ndmp9_name * nl = &nlisttab->nlist[i];
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);
140 ndmda_add_to_cmd (cmd, "@-");
142 ndmda_add_to_cmd (cmd, nl->destination_path);
150 ndmda_data_start_backup (struct ndm_session *sess)
152 struct ndm_data_agent * da = &sess->data_acb;
153 ndmp9_error error = NDMP9_NO_ERR;
154 char cmd[NDMDA_MAX_CMD];
156 strcpy (cmd, "wrap_");
157 strcat (cmd, da->bu_type);
159 if (sess->param.log_level > 0) {
161 sprintf(tmpbuf, "-d%d", sess->param.log_level);
162 ndmda_add_to_cmd (cmd, tmpbuf);
165 ndmda_add_to_cmd (cmd, "-c");
166 ndmda_add_to_cmd (cmd, "-I#3");
167 add_env (&da->env_tab, cmd);
169 ndma_send_logmsg (sess, NDMP9_LOG_DEBUG, sess->plumb.data,
172 if (ndmda_pipe_fork_exec (sess, cmd, 1) < 0) {
173 return NDMP9_UNDEFINED_ERR;
176 ndmis_data_start (sess, NDMCHAN_MODE_WRITE);
178 da->data_state.state = NDMP9_DATA_STATE_ACTIVE;
179 da->data_state.operation = NDMP9_DATA_OP_BACKUP;
185 ndmda_data_start_recover (struct ndm_session *sess)
187 struct ndm_data_agent * da = &sess->data_acb;
188 ndmp9_error error = NDMP9_NO_ERR;
189 char cmd[NDMDA_MAX_CMD];
191 strcpy (cmd, "wrap_");
192 strcat (cmd, da->bu_type);
194 if (sess->param.log_level > 0) {
196 sprintf(tmpbuf, "-d%d", sess->param.log_level);
197 ndmda_add_to_cmd (cmd, tmpbuf);
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);
205 ndma_send_logmsg (sess, NDMP9_LOG_DEBUG, sess->plumb.data,
208 if (ndmda_pipe_fork_exec (sess, cmd, 0) < 0) {
209 return NDMP9_UNDEFINED_ERR;
212 ndmis_data_start (sess, NDMCHAN_MODE_READ);
214 da->data_state.state = NDMP9_DATA_STATE_ACTIVE;
215 da->data_state.operation = NDMP9_DATA_OP_RECOVER;
221 ndmda_data_start_recover_fh (struct ndm_session *sess)
223 struct ndm_data_agent * da = &sess->data_acb;
224 ndmp9_error error = NDMP9_NO_ERR;
225 char cmd[NDMDA_MAX_CMD];
227 strcpy (cmd, "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);
234 ndma_send_logmsg (sess, NDMP9_LOG_DEBUG, sess->plumb.data,
237 if (ndmda_pipe_fork_exec (sess, cmd, 0) < 0) {
238 return NDMP9_UNDEFINED_ERR;
241 ndmis_data_start (sess, NDMCHAN_MODE_READ);
243 da->data_state.state = NDMP9_DATA_STATE_ACTIVE;
244 da->data_state.operation = NDMP9_DATA_OP_RECOVER_FILEHIST;
250 ndmda_sync_state (struct ndm_session *sess)
252 /* no-op, always accurate */
256 ndmda_data_abort (struct ndm_session *sess)
258 ndmda_data_halt (sess, NDMP9_DATA_HALT_ABORTED);
262 ndmda_sync_environment (struct ndm_session *sess)
264 /* no-op, always accurate */
268 ndmda_data_listen (struct ndm_session *sess)
270 struct ndm_data_agent * da = &sess->data_acb;
272 da->data_state.state = NDMP9_DATA_STATE_LISTEN;
273 da->data_state.halt_reason = NDMP9_DATA_HALT_NA;
279 ndmda_data_connect (struct ndm_session *sess)
281 struct ndm_data_agent * da = &sess->data_acb;
283 da->data_state.state = NDMP9_DATA_STATE_CONNECTED;
284 da->data_state.halt_reason = NDMP9_DATA_HALT_NA;
290 ndmda_data_halt (struct ndm_session *sess, ndmp9_data_halt_reason reason)
292 struct ndm_data_agent * da = &sess->data_acb;
294 da->data_state.state = NDMP9_DATA_STATE_HALTED;
295 da->data_state.halt_reason = reason;
296 da->data_notify_pending = 1;
298 ndmda_fh_flush (sess);
300 ndmis_data_close (sess);
302 ndmchan_cleanup (&da->formatter_image);
303 ndmchan_cleanup (&da->formatter_error);
304 ndmchan_cleanup (&da->formatter_wrap);
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);
314 ndmda_data_stop (struct ndm_session *sess)
316 ndmda_decommission (sess);
323 * Quantum -- get a bit of work done
324 ****************************************************************
328 ndmda_quantum (struct ndm_session *sess)
330 struct ndm_data_agent * da = &sess->data_acb;
331 int did_something = 0; /* did nothing */
334 switch (da->data_state.state) {
336 ndmalogf (sess, 0, 0, "BOTCH data state");
339 case NDMP9_DATA_STATE_IDLE:
340 case NDMP9_DATA_STATE_HALTED:
341 case NDMP9_DATA_STATE_CONNECTED:
344 case NDMP9_DATA_STATE_LISTEN:
345 switch (sess->plumb.image_stream.data_ep.connect_status) {
346 case NDMIS_CONN_LISTEN: /* no connection yet */
349 case NDMIS_CONN_ACCEPTED: /* we're in business */
350 /* drum roll please... */
351 da->data_state.state = NDMP9_DATA_STATE_CONNECTED;
353 did_something++; /* did something */
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 */
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);
371 ndmda_send_notice (sess);
373 return did_something;
377 ndmda_quantum_stderr (struct ndm_session *sess)
379 struct ndm_data_agent * da = &sess->data_acb;
380 struct ndmchan * ch = &da->formatter_error;
381 int did_something = 0;
388 n_ready = ndmchan_n_ready (ch);
390 return did_something;
392 data = p = &ch->data[ch->beg_ix];
395 while (p < pend && *p != '\n') p++;
398 if (p < pend && *p == '\n') {
400 ndma_send_logmsg (sess, NDMP9_LOG_NORMAL, sess->plumb.data,
402 ch->beg_ix += p - data;
408 return did_something;
410 /* content w/o newline, and EOF */
412 if (ch->end_ix >= ch->data_size) {
413 if (data != ch->data) {
414 ndmchan_compress (ch);
417 /* that's one huge message */
418 p--; /* lose last byte */
421 ch->data[ch->end_ix++] = '\n';
427 ndmda_quantum_wrap (struct ndm_session *sess)
429 struct ndm_data_agent * da = &sess->data_acb;
430 struct ndmchan * ch = &da->formatter_wrap;
431 int did_something = 0;
438 switch (da->data_state.operation) {
443 case NDMP9_DATA_OP_BACKUP:
446 case NDMP9_DATA_OP_RECOVER:
447 case NDMP9_DATA_OP_RECOVER_FILEHIST:
453 n_ready = ndmchan_n_ready (ch);
455 if (ch->eof && is_recover) {
456 ndmda_data_halt (sess, NDMP9_DATA_HALT_SUCCESSFUL);
458 return did_something;
460 data = p = &ch->data[ch->beg_ix];
463 while (p < pend && *p != '\n') p++;
466 if (p < pend && *p == '\n') {
468 ndmda_wrap_in (sess, data);
469 ch->beg_ix += p - data;
475 return did_something;
477 /* content w/o newline, and EOF */
479 if (ch->end_ix >= ch->data_size) {
480 if (data != ch->data) {
481 ndmchan_compress (ch);
484 /* that's one huge message */
485 p--; /* lose last byte */
488 ch->data[ch->end_ix++] = '\n';
496 ndmda_quantum_image (struct ndm_session *sess)
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;
504 switch (da->data_state.operation) {
511 case NDMP9_DATA_OP_BACKUP:
512 from_chan = &da->formatter_image;
513 to_chan = &sess->plumb.image_stream.chan;
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;
525 n_copy = n_ready = ndmchan_n_ready (from_chan);
527 if (from_chan->eof) {
529 if (ndmchan_n_ready (to_chan) == 0) {
531 ndmda_data_halt (sess,
532 NDMP9_DATA_HALT_SUCCESSFUL);
536 return 0; /* data blocked */
539 n_avail = ndmchan_n_avail (to_chan);
540 if (n_copy > n_avail)
543 if (da->enable_hist) {
544 if (n_copy > da->pass_resid)
545 n_copy = da->pass_resid;
549 bcopy (&from_chan->data[from_chan->beg_ix],
550 &to_chan->data[to_chan->end_ix],
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 */
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.
573 * Here the messages are parsed and directed to the
574 * right NDMP interface toward the Control Agent.
577 void ndmp9_fstat_from_wrap_fstat (ndmp9_file_stat *fstat9,
578 struct wrap_fstat *fstatw);
581 ndmda_wrap_in (struct ndm_session *sess, char *wrap_line)
583 struct wrap_msg_buf _wmsg, *wmsg = &_wmsg;
585 ndmp9_file_stat fstat9;
587 NDMOS_MACRO_ZEROFILL (wmsg);
589 rc = wrap_parse_msg (wrap_line, wmsg);
591 ndmalogf (sess, 0, 2, "Malformed wrap: %s", wrap_line);
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);
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);
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);
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);
626 case WRAP_MSGTYPE_DATA_READ:
627 ndmda_send_data_read (sess,
628 wmsg->body.data_read.offset,
629 wmsg->body.data_read.length);
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);
643 ndmp9_fstat_from_wrap_fstat (ndmp9_file_stat *fstat9,
644 struct wrap_fstat *fstatw)
646 NDMOS_MACRO_ZEROFILL (fstat9);
648 switch (fstatw->ftype) {
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;
662 if (fstatw->valid & WRAP_FSTAT_VALID_FTYPE) {
665 if (fstatw->valid & WRAP_FSTAT_VALID_MODE) {
666 fstat9->mode.valid = NDMP9_VALIDITY_VALID;
667 fstat9->mode.value = fstatw->mode;
670 if (fstatw->valid & WRAP_FSTAT_VALID_SIZE) {
671 fstat9->size.valid = NDMP9_VALIDITY_VALID;
672 fstat9->size.value = fstatw->size;
675 if (fstatw->valid & WRAP_FSTAT_VALID_LINKS) {
676 fstat9->links.valid = NDMP9_VALIDITY_VALID;
677 fstat9->links.value = fstatw->size;
680 if (fstatw->valid & WRAP_FSTAT_VALID_UID) {
681 fstat9->uid.valid = NDMP9_VALIDITY_VALID;
682 fstat9->uid.value = fstatw->uid;
685 if (fstatw->valid & WRAP_FSTAT_VALID_GID) {
686 fstat9->gid.valid = NDMP9_VALIDITY_VALID;
687 fstat9->gid.value = fstatw->gid;
690 if (fstatw->valid & WRAP_FSTAT_VALID_ATIME) {
691 fstat9->atime.valid = NDMP9_VALIDITY_VALID;
692 fstat9->atime.value = fstatw->atime;
695 if (fstatw->valid & WRAP_FSTAT_VALID_MTIME) {
696 fstat9->mtime.valid = NDMP9_VALIDITY_VALID;
697 fstat9->mtime.value = fstatw->mtime;
700 if (fstatw->valid & WRAP_FSTAT_VALID_CTIME) {
701 fstat9->ctime.valid = NDMP9_VALIDITY_VALID;
702 fstat9->ctime.value = fstatw->ctime;
705 if (fstatw->valid & WRAP_FSTAT_VALID_FILENO) {
706 fstat9->node.valid = NDMP9_VALIDITY_VALID;
707 fstat9->node.value = fstatw->fileno;
719 * Send LOG and NOTIFY messages
720 ****************************************************************
725 ndmda_send_logmsg (struct ndm_session *sess, char *fmt, ...)
727 struct ndmconn * conn = sess->plumb.control;
732 vsnprintf (buf, sizeof(buf), fmt, ap);
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);
741 ndma_send_logmsg (sess, buf, conn);
746 ndmda_send_notice (struct ndm_session *sess)
748 struct ndm_data_agent * da = &sess->data_acb;
750 if (!da->data_notify_pending)
753 da->data_notify_pending = 0;
755 switch (da->data_state.state) {
756 case NDMP9_DATA_STATE_HALTED:
757 ndma_notify_data_halted (sess);
761 /* Hmm. Why are we here. Race? */
767 ndmda_send_data_read (struct ndm_session *sess,
768 unsigned long long offset, unsigned long long length)
770 struct ndm_data_agent * da = &sess->data_acb;
771 ndmp9_addr_type addr_type;
773 addr_type = da->data_state.data_connection_addr.addr_type;
775 da->reco_read_offset = offset;
776 da->reco_read_length = length;
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,
784 "local_mover_read failed");
785 ndmda_data_halt (sess, NDMP9_DATA_HALT_INTERNAL_ERROR);
787 #else /* !NDMOS_OPTION_NO_TAPE_AGENT */
788 ndma_send_logmsg (sess, NDMP9_LOG_ERROR,
790 "local_mover_read not configured");
791 ndmda_data_halt (sess, NDMP9_DATA_HALT_INTERNAL_ERROR);
792 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
798 ndma_notify_data_read (sess, offset, length);
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);
813 * Misc -- env[] and nlist[] subroutines, etc
814 ****************************************************************
818 ndmda_copy_environment (struct ndm_session *sess,
819 ndmp9_pval *env, unsigned n_env)
821 struct ndm_data_agent * da = &sess->data_acb;
827 for (j = 0; j < n_env; j++) {
829 dst_pv = &da->env_tab.env[da->env_tab.n_env];
831 dst_pv->name = NDMOS_API_STRDUP (src_pv->name);
832 dst_pv->value = NDMOS_API_STRDUP (src_pv->value);
834 if (!dst_pv->name || !dst_pv->value)
843 for (i = 0; i < da->env_tab.n_env; i++) {
846 dst_pv = &da->env_tab.env[da->env_tab.n_env];
848 if ((p = dst_pv->name) != 0)
851 if ((p = dst_pv->value) != 0)
854 da->env_tab.n_env = 0;
860 ndmda_find_env (struct ndm_session *sess, char *name)
862 struct ndm_data_agent * da = &sess->data_acb;
864 struct ndmp9_pval * pv;
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)
877 ndmda_interpret_boolean_value (char *value_str, int default_value)
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)
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)
893 return default_value;
897 ndmda_purge_environment (struct ndm_session *sess)
899 struct ndm_data_agent * da = &sess->data_acb;
901 struct ndmp9_pval * pv;
903 for (i = 0; i < da->env_tab.n_env; i++) {
904 pv = &da->env_tab.env[i];
906 if (pv->name) NDMOS_API_FREE (pv->name);
907 if (pv->value) NDMOS_API_FREE (pv->value);
911 da->env_tab.n_env = 0;
916 ndmda_copy_nlist (struct ndm_session *sess,
917 ndmp9_name *nlist, unsigned n_nlist)
919 struct ndm_data_agent * da = &sess->data_acb;
925 for (i = 0; i < n_nlist; i++) {
926 j = da->nlist_tab.n_nlist;
928 dst_nl = &da->nlist_tab.nlist[j];
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;
938 if (!dst_nl->original_path || !dst_nl->destination_path)
939 return -1; /* no mem */
941 da->nlist_tab.n_nlist++;
950 ndmda_purge_nlist (struct ndm_session *sess)
952 struct ndm_data_agent * da = &sess->data_acb;
954 struct ndmp9_name * nl;
956 for (i = 0; i < da->nlist_tab.n_nlist; i++) {
957 nl = &da->nlist_tab.nlist[i];
959 if (nl->original_path) {
960 NDMOS_API_FREE (nl->original_path);
962 if (nl->destination_path) {
963 NDMOS_API_FREE (nl->destination_path);
966 nl->original_path = 0;
967 nl->destination_path = 0;
969 da->nlist_tab.n_nlist = 0;
973 ndmda_count_invalid_fh_info (struct ndm_session *sess)
975 struct ndm_data_agent * da = &sess->data_acb;
977 struct ndmp9_name * nl;
980 for (i = 0; i < da->nlist_tab.n_nlist; i++) {
981 nl = &da->nlist_tab.nlist[i];
983 if (nl->fh_info.valid != NDMP9_VALIDITY_VALID)
991 ndmda_count_invalid_fh_info_pending (struct ndm_session *sess)
993 struct ndm_data_agent * da = &sess->data_acb;
995 struct ndmp9_name * nl;
998 for (i = 0; i < da->nlist_tab.n_nlist; i++) {
999 nl = &da->nlist_tab.nlist[i];
1001 if (da->nlist_tab.result_err[i] == NDMP9_UNDEFINED_ERR
1002 && nl->fh_info.valid != NDMP9_VALIDITY_VALID) {
1010 #endif /* !NDMOS_OPTION_NO_DATA_AGENT */