/*
 * Copyright (c) 1998,1999,2000
 *	Traakan, Inc., Los Altos, CA
 *	All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice unmodified, this list of conditions, and the following
 *    disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Project:  NDMJOB
 * Ident:    $Id: $
 *
 * Description:
 *
 ********************************************************************
 *
 * NDMP Elements of a backup/restore session
 *
 *                   +-----+     ###########
 *                   | Job |----># CONTROL #      +----------------+
 *                   +-----+     #  Agent  #<---->|FILE/MEDIA INDEX|
 *                               #         #      +----------------+
 *                               ###########
 *                                 |  |  |
 *                +----------------+  |  +---------------------+
 *                |           control | connections            |
 *                V                   V                        V
 *           ############        ############  +-------+   #########
 *           #  DATA    #        #  TAPE    #  |       |   # ROBOT #
 *           #  Agent   #        #  Agent   #  | ROBOT |<-># Agent #
 *  +-----+  # +------+ # image  # +------+ #  |+-----+|   #       #
 *  |FILES|====|butype|============|mover |=====|DRIVE||   #       #
 *  +-----+  # +------+ # stream # +------+ #  |+-----+|   #       #
 *           ############        ############  +-------+   #########
 *
 *
 ********************************************************************
 *
 * NDMAGENTS components overview
 *
 *
 *    "job" -> ndma_client_session()    ndma_server_session()
 *                   |                           |
 *     /-------------/                           Q
 *     |                                         v
 *     |       +------------------------------------+      +-----------+
 *     |    /->|           SESSION QUANTUM          |----->| disp conn |
 *     |    |  +------------------------------------+ \    +-----------+
 *     |    Q   Q       Q         Q       Q        Q  |         v    |
 *     |    |   |       |         |       |        |  | +----------+ |
 *     |  /-----|----+--|----+----|----+--|----+---|----| dispatch | |
 *     |  | |   |    |  |    |    |    |  |    |   |  | | request  | |
 *     |  v |   v    v  v    v    v    v  v    v   v  | +----------+ |
 *     | +-------+  +----+  +------+  +----+  +-----+ |      ^       |
 *     +>|CONTROL|  |DATA|  |IMAGE |  |TAPE|  |ROBOT| |      |       |
 *       |       |  |    |->|STREAM|<-|    |  |     | |      |       |
 *       |       |  |   *====*    *====*   |  |     | |      |  ndmconn_recv()
 *       | ndmca |  ndmda|  |ndmis |  ndmta|  |ndmra| |      |       |
 *       +-------+  +----+  +------+  +----+  +-----+ |      |resi   |
 *              |     | |    |    |       |           |   +------+   |
 *              \-----|-+----|----+-------+-------------->| call |   |
 *                    |      |                        |   +------+   |
 *           formatter|      |image_stream            |      |remo   |
 *                    v      v                        |      v       v
 *                   +---------+<---ndmchan_poll()----/     +---------+
 *                   | ndmchan |<---------------------------| ndmconn |
 *                   +---------+                            +---------+
 *                 non-blocking I/O                         XDR wrapper
 *
 *   -----> caller/callee
 *   --Q--> quantum (CPU scheduling)
 *   ====== image stream shared data structures
 *
 ********************************************************************
 */


#include "ndmlib.h"



/*
 * VERSION AND RELEASE CONSTANTS -- KEEPER ONLY
 ****************************************************************
 *
 * Revision constants for the source code. These may only be
 * changed by the keeper of these sources. Contact ndmp-tech@ndmp.org
 * for a pointer to the latest sources and the current keeper.
 *
 * The Version increases every time there is a significant
 * design change. Significant means new functionality,
 * reorganization of key data structures, etc. The Release
 * increases every time the keeper releases an update to
 * the current version, such as bug fixes or integration
 * of new contributions.
 *
 * There are provisions for a free-form string for revisions
 * of the O/S specific portions (NDMOS_CONST_NDMOS_REVISION)
 * and for local revisions (NDMOS_CONST_NDMJOBLIB_REVISION)
 * which reflect in-house change levels.
 */
#define NDMJOBLIB_VERSION	1
#define NDMJOBLIB_RELEASE	2




struct ndm_session;		/* forward decl */




/*
 * NDM_ENV_TABLE and NDM_NLIST_TABLE
 ****************************************************************
 * Used by DATA and CONTROL agents
 */
#ifndef NDM_MAX_ENV
#define NDM_MAX_ENV		1024
#endif
struct ndm_env_table {
	int			n_env;
	ndmp9_pval		env[NDM_MAX_ENV];
};

#ifndef NDM_MAX_NLIST
#define NDM_MAX_NLIST		10240
#endif
struct ndm_nlist_table {
	int			n_nlist;
	ndmp9_name		nlist[NDM_MAX_NLIST];
	ndmp9_name		nlist_new[NDM_MAX_NLIST];
	ndmp9_error		result_err[NDM_MAX_NLIST];
	unsigned		result_count[NDM_MAX_NLIST];
};




#ifndef NDMOS_OPTION_NO_CONTROL_AGENT
/*
 * CONTROL AGENT
 ****************************************************************
 */

#include "smc.h"		/* SCSI Media Changer */


#ifndef NDM_MAX_MEDIA
#define NDM_MAX_MEDIA		40
#endif

struct ndm_media_table {
	int			n_media;
	struct ndmmedia		media[NDM_MAX_MEDIA];
};


#define NDM_JOB_OP_BACKUP	(0x100 | 'c')
#define NDM_JOB_OP_EXTRACT	(0x100 | 'x')
#define NDM_JOB_OP_TOC		(0x100 | 't')
#define NDM_JOB_OP_QUERY_AGENTS	(0x100 | 'q')
#define NDM_JOB_OP_INIT_LABELS	(0x100 | 'I')
#define NDM_JOB_OP_LIST_LABELS	(0x100 | 'L')
#define NDM_JOB_OP_REMEDY_ROBOT	(0x100 | 'Z')

/* test operations */
#define NDM_JOB_OP_TEST_TAPE	(0x200 | 'T')
#define NDM_JOB_OP_TEST_MOVER	(0x200 | 'M')
#define NDM_JOB_OP_TEST_DATA	(0x200 | 'D')

/* tape handling operations */
#define NDM_JOB_OP_REWIND_TAPE	(0x300 | 'r')
#define NDM_JOB_OP_EJECT_TAPE	(0x300 | 'j')
#define NDM_JOB_OP_MOVE_TAPE	(0x300 | 'm')
#define NDM_JOB_OP_LOAD_TAPE	(0x300 | 'l')
#define NDM_JOB_OP_UNLOAD_TAPE	(0x300 | 'u')
#define NDM_JOB_OP_IMPORT_TAPE	(0x300 | 'i')
#define NDM_JOB_OP_EXPORT_TAPE	(0x300 | 'e')
#define NDM_JOB_OP_INIT_ELEM_STATUS (0x300 | 'I')

/* daemon operations */
#define NDM_JOB_OP_DAEMON 'd'
#define NDM_JOB_OP_TEST_DAEMON 'D'

struct ndm_job_param {
	int			operation;	/* NDM_JOB_OP_... */
        int                     time_limit;	/* command timeout, 0 is off */

	struct ndmagent		data_agent;	/* DATA AGENT host/pw */
	char *			bu_type;	/* e.g. "tar" */
	struct ndm_env_table	env_tab;	/* for BACKUP+RECOVER ops */
	struct ndm_nlist_table	nlist_tab;	/* for RECOVER ops */
	struct ndm_env_table	result_env_tab;	/* after BACKUP */
	struct ndmlog		index_log;	/* to log NDMP_FH_ADD_... */

	struct ndmagent		tape_agent;	/* TAPE AGENT host/pw */
	char *			tape_device;	/* eg "/dev/rmt0" */
	unsigned		tape_timeout;	/* secs total to retry open */
	unsigned		record_size;	/* in bytes, 10k typical */
        unsigned long long	last_w_offset;	/* last window offset sent */
	struct ndmscsi_target	tape_target;	/* unused for now */
	char *			tape_tcp;	/* tcp direct */
	NDM_FLAG_DECL(use_eject)		/* eject upon close (unload) */

	struct ndmagent		robot_agent;	/* ROBOT AGENT host/pw */
	struct ndmscsi_target	robot_target;	/* SCSI coord of robot */
	unsigned		robot_timeout;	/* secs total to retry move */
	NDM_FLAG_DECL(have_robot)		/* yes, we have robot, today */
	NDM_FLAG_DECL(auto_remedy)		/* if drive loaded, unload */
	NDM_FLAG_DECL(remedy_all)		/* OP_REMEDY, all drives */
	NDM_FLAG_DECL(drive_addr_given)
	NDM_FLAG_DECL(from_addr_given)
	NDM_FLAG_DECL(to_addr_given)
	unsigned		drive_addr;	/* 0->first, !0->elem addr */
	unsigned		from_addr;	/* for MOVE and EXPORT */
	unsigned		to_addr;	/* for MOVE and IMPORT */
						/* use move for many I/E */

	struct ndm_media_table	media_tab;	/* media to use, params */
	struct ndm_media_table	result_media_tab; /* results after job */

	unsigned long		n_file_entry;
	unsigned long		n_dir_entry;
	unsigned long		n_node_entry;
	unsigned long long	root_node;
};

/* ndma_job.c */
extern int	ndma_job_audit (struct ndm_job_param *job,
				char *errbuf, int errskip);
extern int	ndma_job_media_audit (struct ndm_job_param *job,
				char *errbuf, int errskip);
extern void	ndma_job_auto_adjust (struct ndm_job_param *job);


struct ndm_control_agent {
	/* The JOB, see immediately above */
	struct ndm_job_param	job;
	NDM_FLAG_DECL(swap_connect)
	NDM_FLAG_DECL(has_tcp_addr)
	NDM_FLAG_DECL(has_local_addr)

	/* DATA agent */
	ndmp9_data_operation	data_op;
	ndmp9_data_get_state_reply data_state;
	NDM_FLAG_DECL(pending_notify_data_read)
	NDM_FLAG_DECL(pending_notify_data_halted)
	ndmp9_notify_data_read_request last_notify_data_read;
	ndmp9_addr		data_addr;
	int			recover_log_file_count;
	int			recover_log_file_ok;
	int			recover_log_file_error;

	/* Image stream */
	ndmp9_addr		mover_addr;
	ndmp9_mover_mode	mover_mode;

	/* TAPE Agent */
	ndmp9_mover_get_state_reply mover_state;
	NDM_FLAG_DECL(pending_notify_mover_paused)
	NDM_FLAG_DECL(pending_notify_mover_halted)
	ndmp9_notify_mover_paused_request last_notify_mover_paused;

	ndmp9_tape_open_mode	tape_mode;
	ndmp9_tape_get_state_reply tape_state;

	/* Media management, media_table inside of job */
	int			cur_media_ix;
	NDM_FLAG_DECL(media_is_loaded)
	NDM_FLAG_DECL(is_label_op)

	/* ROBOT Agent */
	struct smc_ctrl_block	smc_cb;
	unsigned		drive_addr;

	/* when testing */
	char *			active_test;		/* name of test or 0 if no test */
	char *			active_test_failed;	/* active test failed */
	char *			active_test_warned;	/* active test warned */

	char *			test_phase;		/* name of sub-series test phase */
	int			test_step;		/* test sequence number */

	int			n_step_pass;		/* per phase test stats */
	int			n_step_fail;
	int			n_step_warn;
	int			n_step_tests;

	int			total_n_step_pass;	/* total test stats */
	int			total_n_step_fail;
	int			total_n_step_warn;
	int			total_n_step_tests;

#ifdef NDMOS_MACRO_CONTROL_AGENT_ADDITIONS
	NDMOS_MACRO_CONTROL_AGENT_ADDITIONS
#endif /* NDMOS_MACRO_CONTROL_AGENT_ADDITIONS */
};


/* ndma_control.c */
extern int	ndmca_control_agent (struct ndm_session *sess);

/* ndma_cops_backreco.c */
extern int	ndmca_op_create_backup (struct ndm_session *sess);
extern int	ndmca_op_recover_files (struct ndm_session *sess);
extern int	ndmca_op_recover_fh (struct ndm_session *sess);
extern int	ndmca_monitor_backup (struct ndm_session *sess);
extern int	ndmca_monitor_get_post_backup_env (struct ndm_session *sess);
extern int	ndmca_monitor_recover (struct ndm_session *sess);
extern int	ndmca_backreco_startup (struct ndm_session *sess);
extern int	ndmca_monitor_startup (struct ndm_session *sess);
extern int	ndmca_monitor_shutdown (struct ndm_session *sess);
extern int	ndmca_monitor_get_states (struct ndm_session *sess);
extern int	ndmca_monitor_load_next (struct ndm_session *sess);
extern int	ndmca_monitor_seek_tape (struct ndm_session *sess);
extern int	ndmca_monitor_unload_last_tape (struct ndm_session *sess);
extern int	ndmca_mon_wait_for_something (struct ndm_session *sess,
			int max_delay_secs);

/* ndma_cops_labels.c */
extern int	ndmca_op_init_labels (struct ndm_session *sess);
extern int	ndmca_op_list_labels (struct ndm_session *sess);


/* ndma_cops_query.c */
extern int	ndmca_op_query (struct ndm_session *sess);
extern int	ndmca_opq_data (struct ndm_session *sess);
extern int	ndmca_opq_tape (struct ndm_session *sess);
extern int	ndmca_opq_robot (struct ndm_session *sess);
extern int	ndmca_opq_host_info (struct ndm_session *sess,
			struct ndmconn *conn);
extern int	ndmca_opq_get_mover_type (struct ndm_session *sess,
			struct ndmconn *conn);
extern int	ndmca_opq_get_butype_attr (struct ndm_session *sess,
			struct ndmconn *conn);
extern int	ndmca_opq_get_fs_info (struct ndm_session *sess,
			struct ndmconn *conn);
extern int	ndmca_opq_get_tape_info (struct ndm_session *sess,
			struct ndmconn *conn);
extern int	ndmca_opq_get_scsi_info (struct ndm_session *sess,
			struct ndmconn *conn);
extern void	ndmalogqr (struct ndm_session *sess, char *fmt, ...);


/* ndma_cops_robot.c */
extern int	ndmca_op_robot_remedy (struct ndm_session *sess);
extern int	ndmca_op_robot_startup (struct ndm_session *sess,
			int verify_media_flag);
extern int	ndmca_op_init_elem_status (struct ndm_session *sess);
extern int	ndmca_op_rewind_tape (struct ndm_session *sess);
extern int	ndmca_op_eject_tape (struct ndm_session *sess);
extern int	ndmca_op_mtio (struct ndm_session *sess,
			ndmp9_tape_mtio_op mtio_op);

extern int	ndmca_op_move_tape (struct ndm_session *sess);
extern int	ndmca_op_import_tape (struct ndm_session *sess);
extern int	ndmca_op_export_tape (struct ndm_session *sess);
extern int	ndmca_op_load_tape (struct ndm_session *sess);
extern int	ndmca_op_unload_tape (struct ndm_session *sess);


/* ndma_ctrl_calls.c */
extern int	ndmca_data_get_state (struct ndm_session *sess);
extern int	ndmca_data_connect (struct ndm_session *sess);
extern int	ndmca_data_listen (struct ndm_session *sess);
extern int	ndmca_data_start_backup (struct ndm_session *sess);
extern int	ndmca_data_start_recover (struct ndm_session *sess);
extern int	ndmca_data_start_recover_filehist (struct ndm_session *sess);
extern int	ndmca_data_abort (struct ndm_session *sess);
extern int	ndmca_data_get_env (struct ndm_session *sess);
extern int	ndmca_data_stop (struct ndm_session *sess);
extern int	ndmca_tape_open (struct ndm_session *sess);
extern int	ndmca_tape_close (struct ndm_session *sess);
extern int	ndmca_tape_get_state (struct ndm_session *sess);
extern int	ndmca_tape_get_state_no_tattle (struct ndm_session *sess);
extern int	ndmca_tape_mtio (struct ndm_session *sess,
			ndmp9_tape_mtio_op op, u_long count, u_long *resid);
extern int	ndmca_tape_write (struct ndm_session *sess,
			char *buf, unsigned count);
extern int	ndmca_tape_read (struct ndm_session *sess,
			char *buf, unsigned count);
extern int	ndmca_mover_get_state (struct ndm_session *sess);
extern int	ndmca_mover_listen (struct ndm_session *sess);
extern int	ndmca_mover_connect (struct ndm_session *sess);
extern int	ndmca_mover_continue (struct ndm_session *sess);
extern int	ndmca_mover_abort (struct ndm_session *sess);
extern int	ndmca_mover_stop (struct ndm_session *sess);
extern int	ndmca_mover_set_window (struct ndm_session *sess,
			unsigned long long offset, unsigned long long length);
extern int	ndmca_mover_read (struct ndm_session *sess,
			unsigned long long offset, unsigned long long length);
extern int	ndmca_mover_close (struct ndm_session *sess);
extern int	ndmca_mover_set_record_size (struct ndm_session *sess);


/* ndma_ctrl_media.c */
extern int	ndmca_media_load_first (struct ndm_session *sess);
extern int	ndmca_media_load_next (struct ndm_session *sess);
extern int	ndmca_media_unload_last (struct ndm_session *sess);
extern int	ndmca_media_change (struct ndm_session *sess);
extern int	ndmca_media_load_seek (struct ndm_session *sess,
			unsigned long long pos);
extern int	ndmca_media_load_current (struct ndm_session *sess);
extern int	ndmca_media_unload_current (struct ndm_session *sess);
extern int	ndmca_media_unload_best_effort (struct ndm_session *sess);
extern int	ndmca_media_open_tape (struct ndm_session *sess);
extern int	ndmca_media_close_tape (struct ndm_session *sess);
extern int	ndmca_media_mtio_tape (struct ndm_session *sess,
			ndmp9_tape_mtio_op op, u_long count, u_long *resid);
extern int	ndmca_media_write_filemarks (struct ndm_session *sess);
extern int	ndmca_media_read_label (struct ndm_session *sess,
			char labbuf[]);
extern int	ndmca_media_write_label (struct ndm_session *sess,
			int type, char labbuf[]);
extern int	ndmca_media_check_label (struct ndm_session *sess,
			int type, char labbuf[]);
extern int	ndmca_media_verify (struct ndm_session *sess);
extern int	ndmca_media_tattle (struct ndm_session *sess);
extern unsigned long long
		ndmca_media_capture_tape_offset (struct ndm_session *sess);
extern int	ndmca_media_capture_mover_window (struct ndm_session *sess);
extern int	ndmca_media_calculate_windows (struct ndm_session *sess);
extern int	ndmca_media_calculate_offsets (struct ndm_session *sess);
extern int	ndmca_media_set_window_current (struct ndm_session *sess);


/* ndma_ctrl_robot.c */
extern int	ndmca_robot_issue_scsi_req (struct smc_ctrl_block *smc);
extern int	ndmca_robot_prep_target (struct ndm_session *sess);
extern int	ndmca_robot_obtain_info (struct ndm_session *sess);
extern int	ndmca_robot_init_elem_status (struct ndm_session *sess);
extern int	ndmca_robot_startup (struct ndm_session *sess);
extern int	ndmca_robot_move (struct ndm_session *sess,
			int src_addr, int dst_addr);
extern int	ndmca_robot_load (struct ndm_session *sess, int slot_addr);
extern int	ndmca_robot_unload (struct ndm_session *sess, int slot_addr);
extern struct smc_element_descriptor *
			ndmca_robot_find_element (struct ndm_session *sess,
							int element_address);
extern int	ndmca_robot_check_ready (struct ndm_session *sess);
extern int	ndmca_robot_remedy_ready (struct ndm_session *sess);
extern int	ndmca_robot_query (struct ndm_session *sess);
extern int	ndmca_robot_verify_media (struct ndm_session *sess);
extern int	ndmca_robot_synthesize_media (struct ndm_session *sess);


/* ndma_ctrl_conn.c */
extern int	ndmca_connect_xxx_agent (struct ndm_session *sess,
			struct ndmconn **connp, char *prefix,
			struct ndmagent *agent);
extern int	ndmca_connect_data_agent (struct ndm_session *sess);
extern int	ndmca_connect_tape_agent (struct ndm_session *sess);
extern int	ndmca_connect_robot_agent (struct ndm_session *sess);
extern int	ndmca_connect_control_agent (struct ndm_session *sess);



/* ndma_ctst_tape.c */
extern int	ndmca_op_test_tape (struct ndm_session *sess);

/* ndma_ctst_mover.c */
extern int	ndmca_op_test_mover (struct ndm_session *sess);

/* ndma_ctst_data.c */
extern int	ndmca_op_test_data (struct ndm_session *sess);

/* ndma_ctst_subr.c */
extern int	ndmca_test_query_conn_types (struct ndm_session *sess,
					     struct ndmconn *ref_conn);
extern int	ndmca_test_load_tape (struct ndm_session *sess);
extern int	ndmca_test_unload_tape (struct ndm_session *sess);
extern int	ndmca_test_call (struct ndmconn *conn,
			struct ndmp_xa_buf *xa, ndmp9_error expect_err);
extern int	ndmca_test_check_expect_errs (struct ndmconn *conn,
			int rc, ndmp9_error expect_errs[]);
extern int	ndmca_test_check_expect (struct ndmconn *conn,
			int rc, ndmp9_error expect_err);
extern int	ndmca_test_check_expect_no_err (struct ndmconn *conn,
			int rc);
extern int	ndmca_test_check_expect_illegal_state (struct ndmconn *conn,
			int rc);
extern int	ndmca_test_check_expect_illegal_args (struct ndmconn *conn,
			int rc);
extern void	ndmca_test_phase (struct ndm_session *sess,
			char *test_phase, char *desc);
extern void	ndmca_test_log_step (struct ndm_session *sess,
			int level, char *msg);
extern void	ndmca_test_log_note (struct ndm_session *sess,
			int level, char *msg);
extern void	ndmca_test_done_phase (struct ndm_session *sess);
extern void	ndmca_test_done_series (struct ndm_session *sess,
			char *series_name);
extern void	ndmca_test_open (struct ndm_session *sess,
				 char *test_name,
				 char *sub_test_name);
extern void	ndmca_test_warn (struct ndm_session *sess, char *warn_msg);
extern void	ndmca_test_fail (struct ndm_session *sess, char *fail_msg);
extern void	ndmca_test_close (struct ndm_session *sess);


extern void	ndmca_test_fill_data (char *buf, int bufsize,
			int recno, int fileno);

#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */




#ifndef NDMOS_OPTION_NO_DATA_AGENT
/*
 * DATA AGENT
 ****************************************************************
 *
 * NDMP Elements of Data Agent (backup)
 *
 *  +-----------+stderr
 *  | bu_type   |--------formatter_err---------NDMP_LOG-------> to CONTROL
 *  | formatter |
 *  | process   |========formatter_data=+=====================> to image stream
 *  +-----------+stdout                 |
 *                                  +-------+
 *                                  | snoop |--NDMP_FH_ADD_x--> to CONTROL
 *                                  +-------+
 *
 ****************************************************************
 *
 * NDMP Elements of Data Agent (recover)
 *
 *  +-----------+stderr
 *  | bu_type   |--------formatter_err---------NDMP_LOG-------> to CONTROL
 *  | formatter |                 +--------+
 *  | process   |<=======fmt_data=| direct |==================< from image str
 *  +-----------+stdin            |        |-NOTIFY_DATA_READ-> to CONTROL
 *                                | snoop  |
 *                                +--------+
 *
 ****************************************************************
 *
 * NDMP Elements of Data Agent (recover filehist)
 *
 *                                +--------+
 *                                | direct |==================< from image str
 *                                |        |-NOTIFY_DATA_READ-> to CONTROL
 *                                | snoop  |--NDMP_FH_ADD_x---> to CONTROL
 *                                +--------+
 *
 ****************************************************************
 */



#ifndef NDMDA_N_FMT_IMAGE_BUF
#define NDMDA_N_FMT_IMAGE_BUF	(8*1024)
#endif
#ifndef NDMDA_N_FHH_BUF
#define NDMDA_N_FHH_BUF		(8*1024)
#endif
#ifndef NDMDA_N_FMT_ERROR_BUF
#define NDMDA_N_FMT_ERROR_BUF	(8*1024)
#endif
#ifndef NDMDA_N_FMT_WRAP_BUF
#define NDMDA_N_FMT_WRAP_BUF	(4*1024)
#endif
#ifndef NDMDA_MAX_CMD
#define NDMDA_MAX_CMD		(4*1024)
#endif



#ifndef NDMOS_OPTION_NO_GTAR_BUTYPE
extern int	ndmda_butype_gtar_config_get_attrs (struct ndm_session *sess,
					u_long *attrs_p, int protocol_version);

extern int	ndmda_butype_gtar_config_get_default_env (
					struct ndm_session *sess,
					ndmp9_pval **env_p, int *n_env_p,
					int protocol_version);
extern int	ndmda_butype_gtar_attach (struct ndm_session *sess);
#endif
#ifndef NDMOS_OPTION_NO_DUMP_BUTYPE
extern int	ndmda_butype_dump_config_get_attrs (struct ndm_session *sess,
					u_long *attrs_p, int protocol_version);

extern int	ndmda_butype_dump_config_get_default_env (
					struct ndm_session *sess,
					ndmp9_pval **env_p, int *n_env_p,
					int protocol_version);
extern int	ndmda_butype_dump_attach (struct ndm_session *sess);
#endif




struct ndm_data_recovery_interval {
	ndmp9_u_quad	offset;
	ndmp9_u_quad	length;
};

enum ndm_data_recovery_access_method {
	NDMDA_RECO_ACCESS_SEQUENTIAL = 1,
	NDMDA_RECO_ACCESS_DIRECT,
	NDMDA_RECO_ACCESS_SEMI_DIRECT,
	NDMDA_RECO_ACCESS_SEMI_DIRECT_PENDING,
};

enum ndm_data_recovery_state {
	NDMDA_RECO_STATE_START = 1,
	NDMDA_RECO_STATE_PASS_THRU,
	NDMDA_RECO_STATE_CHOOSE_NLENT,
	NDMDA_RECO_STATE_ACQUIRE,
	NDMDA_RECO_STATE_DISPOSE,
	NDMDA_RECO_STATE_FINISH_NLENT,
	NDMDA_RECO_STATE_ALL_DONE,
};

enum ndm_data_recovery_acquire_mode {
	NDMDA_RECO_ACQUIRE_EVERYTHING = 1,
	NDMDA_RECO_ACQUIRE_SEARCHING,
	NDMDA_RECO_ACQUIRE_MATCHING,
};

enum ndm_data_recovery_disposition {
	NDMDA_RECO_DISPOSITION_PASS = 1,
	NDMDA_RECO_DISPOSITION_DISCARD,
};


struct ndm_data_agent {
	int			protocol_version;

	char			bu_type[32];
	struct ndm_env_table	env_tab;
	struct ndm_nlist_table	nlist_tab;

	NDM_FLAG_DECL(enable_hist)
	unsigned long long	pass_resid;

	ndmp9_data_get_state_reply data_state;
	int			data_notify_pending;

	struct ndmchan		formatter_image;	/* stdin/out */
	struct ndmchan		formatter_error;	/* stderr */
	struct ndmchan		formatter_wrap;		/* fd=3 */
	int			formatter_pid;

	char			fmt_image_buf[NDMDA_N_FMT_IMAGE_BUF];
	char			fmt_error_buf[NDMDA_N_FMT_ERROR_BUF];
	char			fmt_wrap_buf[NDMDA_N_FMT_WRAP_BUF];

	struct ndmfhheap	fhh;
	unsigned long		fhh_buf[NDMDA_N_FHH_BUF];

#ifdef NDMOS_MACRO_DATA_AGENT_ADDITIONS
	NDMOS_MACRO_DATA_AGENT_ADDITIONS
#endif /* NDMOS_MACRO_DATA_AGENT_ADDITIONS */
};



/* ndma_data.c */
extern int		ndmda_initialize (struct ndm_session *sess);
extern int		ndmda_commission (struct ndm_session *sess);
extern int		ndmda_decommission (struct ndm_session *sess);
extern int		ndmda_belay (struct ndm_session *sess);

extern ndmp9_error	ndmda_data_start_backup (struct ndm_session *sess);
extern ndmp9_error	ndmda_data_start_recover (struct ndm_session *sess);
extern ndmp9_error	ndmda_data_start_recover_fh (struct ndm_session *sess);

extern void		ndmda_sync_state (struct ndm_session *sess);
extern ndmp9_error	ndmda_data_listen (struct ndm_session *sess);
extern ndmp9_error	ndmda_data_connect (struct ndm_session *sess);
extern void		ndmda_data_abort (struct ndm_session *sess);
extern void		ndmda_sync_environment (struct ndm_session *sess);
extern void		ndmda_data_halt (struct ndm_session *sess,
				ndmp9_data_halt_reason reason);
extern void		ndmda_data_stop (struct ndm_session *sess);

extern int		ndmda_quantum (struct ndm_session *sess);
extern int		ndmda_quantum_image (struct ndm_session *sess);
extern int		ndmda_quantum_stderr (struct ndm_session *sess);
extern int		ndmda_quantum_wrap (struct ndm_session *sess);

extern int		ndmda_wrap_in (struct ndm_session *sess,
				char *wrap_line);

extern void		ndmda_send_logmsg (struct ndm_session *sess,
				char *fmt, ...);

extern void		ndmda_send_notice (struct ndm_session *sess);
extern void		ndmda_send_data_read (struct ndm_session *sess,
				unsigned long long offset,
				unsigned long long length);

extern int		ndmda_copy_environment (struct ndm_session *sess,
				ndmp9_pval *env, unsigned n_env);
extern struct ndmp9_pval *ndmda_find_env (struct ndm_session *sess,
				char *name);

extern int		ndmda_interpret_boolean_value (char *value_str,
				int default_value);

extern void		ndmda_purge_environment (struct ndm_session *sess);

extern int		ndmda_copy_nlist (struct ndm_session *sess,
				ndmp9_name *nlist, unsigned n_nlist);
extern void		ndmda_purge_nlist (struct ndm_session *sess);
extern int		ndmda_count_invalid_fh_info (struct ndm_session *sess);
extern int		ndmda_count_invalid_fh_info_pending
						(struct ndm_session *sess);

/* in ndma_data_recover.c */
extern int	ndmda_quantum_recover_common (struct ndm_session *sess);
extern int	ndmda_reco_state_start (struct ndm_session *sess);
extern int	ndmda_reco_pass_thru (struct ndm_session *sess);
extern int	ndmda_reco_state_pass_thru (struct ndm_session *sess);
extern int	ndmda_reco_state_choose_nlent (struct ndm_session *sess);
extern int	ndmda_reco_state_acquire (struct ndm_session *sess);
extern int	ndmda_reco_state_dispose (struct ndm_session *sess);
extern int	ndmda_reco_state_finish_nlent (struct ndm_session *sess);
extern int	ndmda_reco_state_all_done (struct ndm_session *sess);
extern int	ndmda_reco_assess_channels (struct ndm_session *sess);
extern int	ndmda_reco_assess_intervals (struct ndm_session *sess);
extern int	ndmda_reco_align_to_wanted (struct ndm_session *sess);
extern int	ndmda_reco_obtain_wanted (struct ndm_session *sess);
extern int	ndmda_reco_send_data_read (struct ndm_session *sess,
						unsigned long long offset,
						unsigned long long length);
extern int	ndmda_reco_internal_error (struct ndm_session *sess,
						char *why);

/* ndma_data_fh.c */
extern int		ndmda_fh_initialize (struct ndm_session *sess);
extern int		ndmda_fh_commission (struct ndm_session *sess);
extern int		ndmda_fh_decommission (struct ndm_session *sess);
extern int		ndmda_fh_belay (struct ndm_session *sess);
extern void		ndmda_fh_add_file (struct ndm_session *sess,
				ndmp9_file_stat *filestat, char *name);
extern void		ndmda_fh_add_dir (struct ndm_session *sess,
				unsigned long long dir_fileno,
				char *name,
				unsigned long long fileno);
extern void		ndmda_fh_add_node (struct ndm_session *sess,
				ndmp9_file_stat *filestat);

extern int		ndmda_fh_prepare (struct ndm_session *sess,
				  int vers, int msg, int entry_size,
				  unsigned n_item,
				  unsigned total_size_of_items);
extern void		ndmda_fh_flush (struct ndm_session *sess);


/* ndma_data_gtar.c */
extern ndmp9_error	ndmda_gtar_start_backup (struct ndm_session *sess);
extern ndmp9_error	ndmda_gtar_start_recover (struct ndm_session *sess);
extern ndmp9_error	ndmda_gtar_start_recover_fh (struct ndm_session *sess);
extern int		ndmda_gtar_snoop (struct ndm_session *sess,
				struct ndmchan *ch);
struct tar_digest_hdr;
extern void		ndmda_gtar_fh_add (struct ndm_session *sess,
				struct tar_digest_hdr *tdh);


/* ndma_data_pfe.c (pipe-fork-exec) */
extern int		ndmda_pipe_fork_exec (struct ndm_session *sess,
				char *cmd, int is_backup);
extern int		ndmda_add_to_cmd_with_escapes (char *cmd,
				char *word, char *special);
extern int		ndmda_add_to_cmd (char *cmd, char *word);
extern int		ndmda_add_to_cmd_allow_file_wildcards (char *cmd,
				char *word);

#endif /* !NDMOS_OPTION_NO_DATA_AGENT */




#ifndef NDMOS_OPTION_NO_TAPE_AGENT
/*
 * TAPE AGENT
 ****************************************************************
 */

struct ndm_tape_agent {
	int			protocol_version;

	/* TAPE */
	ndmp9_tape_get_state_reply tape_state;

	/* MOVER */
	ndmp9_mover_get_state_reply mover_state;
	u_long			mover_window_first_blockno;
	unsigned long long	mover_window_end;
	unsigned long long	mover_want_pos;
	int			mover_notify_pending;

	int			pending_change_after_drain;
	ndmp9_mover_state	pending_mover_state;
	ndmp9_mover_halt_reason	pending_mover_halt_reason;
	ndmp9_mover_pause_reason pending_mover_pause_reason;

	char			tape_buffer[NDMOS_CONST_TAPE_REC_MAX];
	unsigned long		tb_blockno;

#ifdef NDMOS_MACRO_TAPE_AGENT_ADDITIONS
	NDMOS_MACRO_TAPE_AGENT_ADDITIONS
#endif /* NDMOS_MACRO_DATA_AGENT_ADDITIONS */
};

#define NDMTA_TAPE_IS_WRITABLE(TA) \
	(   (TA)->tape_state.open_mode == NDMP9_TAPE_RDWR_MODE \
	 || (TA)->tape_state.open_mode == NDMP9_TAPE_RAW_MODE)

extern int		ndmta_initialize (struct ndm_session *sess);
extern int		ndmta_commission (struct ndm_session *sess);
extern int		ndmta_decommission (struct ndm_session *sess);
extern int		ndmta_init_mover_state (struct ndm_session *sess);

extern void		ndmta_mover_sync_state (struct ndm_session *sess);
ndmp9_error		ndmta_mover_listen (struct ndm_session *sess,
				ndmp9_mover_mode mover_mode);
ndmp9_error		ndmta_mover_connect (struct ndm_session *sess,
				ndmp9_mover_mode mover_mode);
extern void		ndmta_mover_halt (struct ndm_session *sess,
				ndmp9_mover_halt_reason reason);
extern void		ndmta_mover_pause (struct ndm_session *sess,
				ndmp9_mover_pause_reason reason);
extern void		ndmta_mover_active (struct ndm_session *sess);
extern void		ndmta_mover_start_active (struct ndm_session *sess);
extern void		ndmta_mover_stop (struct ndm_session *sess);
extern void		ndmta_mover_abort (struct ndm_session *sess);
extern void		ndmta_mover_continue (struct ndm_session *sess);
extern void		ndmta_mover_close (struct ndm_session *sess);
extern void		ndmta_mover_read (struct ndm_session *sess,
				unsigned long long offset,
				unsigned long long length);

extern int		ndmta_quantum (struct ndm_session *sess);
extern int		ndmta_read_quantum (struct ndm_session *sess);
extern int		ndmta_write_quantum (struct ndm_session *sess);
extern void		ndmta_mover_send_notice (struct ndm_session *sess);

#endif /* !NDMOS_OPTION_NO_TAPE_AGENT */




#ifndef NDMOS_OPTION_NO_ROBOT_AGENT
/*
 * ROBOT AGENT
 ****************************************************************
 */

struct ndm_robot_agent {
	int			protocol_version;

	ndmp9_scsi_get_state_reply scsi_state;

#ifdef NDMOS_MACRO_ROBOT_AGENT_ADDITIONS
	NDMOS_MACRO_ROBOT_AGENT_ADDITIONS
#endif /* NDMOS_MACRO_ROBOT_AGENT_ADDITIONS */
};

extern int		ndmra_initialize (struct ndm_session *sess);
extern int		ndmra_commission (struct ndm_session *sess);
extern int		ndmra_decommission (struct ndm_session *sess);

/* all semantic operations are done directly to the ndmos_scsi layer */
#endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */




/*
 * IMAGE STREAM
 ****************************************************************
 */

#ifndef NDM_N_IMAGE_STREAM_BUF
#define NDM_N_IMAGE_STREAM_BUF	(100*1024)
#endif

enum ndmis_connect_status {
	NDMIS_CONN_IDLE = 0,
	NDMIS_CONN_LISTEN,
	NDMIS_CONN_ACCEPTED,
	NDMIS_CONN_CONNECTED,
	NDMIS_CONN_DISCONNECTED,
	NDMIS_CONN_CLOSED,
	NDMIS_CONN_BOTCHED,
	NDMIS_CONN_REMOTE,
	NDMIS_CONN_EXCLUDE,
};
typedef enum ndmis_connect_status	ndmis_connect_status;

struct ndmis_end_point {
	char *			name;
	ndmis_connect_status	connect_status;
	int			transfer_mode;
	ndmp9_addr_type		addr_type;
};

struct ndmis_remote {
	ndmis_connect_status	connect_status;
	int			transfer_mode;
	ndmp9_addr		local_addr;
	ndmp9_addr		peer_addr;
	ndmp9_addr		listen_addr;
	struct ndmchan		listen_chan;
	struct ndmchan		sanity_chan;
};

struct ndm_image_stream {
	struct ndmis_end_point	data_ep;
	struct ndmis_end_point	tape_ep;

	struct ndmis_remote	remote;

	/* transfer stuff */
	int			transfer_mode;
	struct ndmchan		chan;
	char			buf[NDM_N_IMAGE_STREAM_BUF];
};

extern int		ndmis_initialize (struct ndm_session *sess);
extern int		ndmis_commission (struct ndm_session *sess);
extern int		ndmis_decommission (struct ndm_session *sess);
extern int		ndmis_belay (struct ndm_session *sess);

extern int		ndmis_quantum (struct ndm_session *sess);

extern ndmp9_error	ndmis_data_listen (struct ndm_session *sess,
			  ndmp9_addr_type addr_type, ndmp9_addr *ret_addr,
			  char *reason);
extern ndmp9_error	ndmis_tape_listen (struct ndm_session *sess,
			  ndmp9_addr_type addr_type, ndmp9_addr *ret_addr,
			  char *reason);
extern ndmp9_error	ndmis_data_connect (struct ndm_session *sess,
			  ndmp9_addr *addr, char *reason);
extern ndmp9_error	ndmis_tape_connect (struct ndm_session *sess,
			  ndmp9_addr *addr, char *reason);
extern int
ndmis_data_start (struct ndm_session *sess, int chan_mode);
extern int
ndmis_tape_start (struct ndm_session *sess, int chan_mode);
extern int
ndmis_data_close (struct ndm_session *sess);
extern int
ndmis_tape_close (struct ndm_session *sess);


extern ndmp9_error	ndmis_audit_data_listen (struct ndm_session *sess,
			  ndmp9_addr_type addr_type, char *reason);
extern ndmp9_error	ndmis_audit_tape_listen (struct ndm_session *sess,
			  ndmp9_addr_type addr_type, char *reason);
extern ndmp9_error	ndmis_audit_data_connect (struct ndm_session *sess,
			  ndmp9_addr_type addr_type, char *reason);
extern ndmp9_error	ndmis_audit_tape_connect (struct ndm_session *sess,
			  ndmp9_addr_type addr_type, char *reason);

extern ndmp9_error	ndmis_audit_ep_listen (
			  struct ndm_session *sess,
			  ndmp9_addr_type addr_type,
			  char *reason,
			  struct ndmis_end_point *mine_ep,
			  struct ndmis_end_point *peer_ep);

extern ndmp9_error	ndmis_audit_ep_connect (
			  struct ndm_session *sess,
			  ndmp9_addr_type addr_type,
			  char *reason,
			  struct ndmis_end_point *mine_ep,
			  struct ndmis_end_point *peer_ep);

extern ndmp9_error	ndmis_ep_listen (
			  struct ndm_session *sess,
			  ndmp9_addr_type addr_type,
			  ndmp9_addr *ret_addr,
			  char *reason,
			  struct ndmis_end_point *mine_ep,
			  struct ndmis_end_point *peer_ep);

extern ndmp9_error	ndmis_ep_connect (
			  struct ndm_session *sess,
			  ndmp9_addr *addr,
			  char *reason,
			  struct ndmis_end_point *mine_ep,
			  struct ndmis_end_point *peer_ep);

extern int		ndmis_ep_close (
			  struct ndm_session *sess,
			  struct ndmis_end_point *mine_ep,
			  struct ndmis_end_point *peer_ep);

extern int		ndmis_tcp_listen (struct ndm_session *sess,
			  struct ndmp9_addr *listen_addr);
extern int		ndmis_tcp_accept (struct ndm_session *sess);
extern int		ndmis_tcp_connect (struct ndm_session *sess,
			  struct ndmp9_addr *connect_addr);
extern int		ndmis_tcp_close (struct ndm_session *sess);

extern int		ndmis_tcp_get_local_and_peer_addrs (
			  struct ndm_session *sess);
extern int		ndmis_tcp_green_light (struct ndm_session *sess,
			  int sock, ndmis_connect_status new_status);



/*
 * PLUMBING
 ****************************************************************
 */

struct ndm_plumbing {
	struct ndmconn *	control;
	struct ndmconn *	data;
	struct ndmconn *	tape;
	struct ndmconn *	robot;

	struct ndm_image_stream image_stream;
};




/*
 * SESSION
 ****************************************************************
 */

struct ndm_session_param {
	struct ndmlog		log;
	char *			log_tag;
	int			log_level;
	char *			config_file_name;
};

struct ndm_session {
#ifndef NDMOS_OPTION_NO_CONTROL_AGENT
	struct ndm_control_agent control_acb;
#endif /* !NDMOS_OPTION_NO_CONTROL_AGENT */
#ifndef NDMOS_OPTION_NO_DATA_AGENT
	struct ndm_data_agent	data_acb;
#endif /* !NDMOS_OPTION_NO_DATA_AGENT */
#ifndef NDMOS_OPTION_NO_TAPE_AGENT
	struct ndm_tape_agent	tape_acb;
#endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
#ifndef NDMOS_OPTION_NO_ROBOT_AGENT
	struct ndm_robot_agent	robot_acb;
#endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */

	struct ndm_plumbing	plumb;

	struct ndm_session_param param;

	/* scratch pad stuff */
	ndmp9_config_info	config_info;
	char			md5_challenge[64]; /* CONNECT_AUTH MD5 */

	NDM_FLAG_DECL(conn_open)
	NDM_FLAG_DECL(conn_authorized)
	NDM_FLAG_DECL(md5_challenge_valid)

	int			connect_status;

#ifdef NDMOS_MACRO_SESSION_ADDITIONS
	NDMOS_MACRO_SESSION_ADDITIONS
#endif /* NDMOS_MACRO_SESSION_ADDITIONS */
};


/* ndma_session.c */
extern int	ndma_client_session (struct ndm_session *sess);
extern int	ndma_server_session (struct ndm_session *sess,
			int control_sock);
extern int	ndma_daemon_session (struct ndm_session *sess, int port, int is_test_daemon);
extern int	ndma_session_quantum (struct ndm_session *sess,
			int max_delay_secs);
extern int	ndma_session_initialize (struct ndm_session *sess);
extern int	ndma_session_commission (struct ndm_session *sess);
extern int	ndma_session_decommission (struct ndm_session *sess);
extern gpointer	exit_on_stdin_eof_thread(gpointer data G_GNUC_UNUSED);




/* ndma_comm_subr.c */
extern void	ndmalogf (struct ndm_session *sess, char *tag,
					int level, char *fmt, ...);
extern void	ndmalogfv (struct ndm_session *sess, char *tag,
					int level, char *fmt, va_list ap);




/*
 * Dispatch Version/Reqeust Tables (DVT, DRT)
 ****************************************************************
 */

struct ndm_dispatch_request_table {
	unsigned short	message;
	unsigned short	flags;
	int		(*dispatch_request) (	/* "dr" for short */
				struct ndm_session *sess,
				struct ndmp_xa_buf *xa,
				struct ndmconn *ref_conn);
};

struct ndm_dispatch_version_table {
	int					protocol_version;
	struct ndm_dispatch_request_table *	dispatch_request_table;
};

#define NDM_DRT_FLAG_OK_NOT_CONNECTED		0x0001
#define NDM_DRT_FLAG_OK_NOT_AUTHORIZED		0x0002


/* ndma_comm_dispatch.c */
extern int	ndma_dispatch_request (struct ndm_session *sess,
			struct ndmp_xa_buf *xa, struct ndmconn *ref_conn);
extern int	ndma_dispatch_raise_error (struct ndm_session *sess,
			struct ndmp_xa_buf *xa, struct ndmconn *ref_conn,
			ndmp9_error error, char *errstr);
extern int	ndma_dispatch_conn (struct ndm_session *sess,
			struct ndmconn *conn);
extern void	ndma_dispatch_ctrl_unexpected (struct ndmconn *conn,
			struct ndmp_msg_buf *nmb);
extern int	ndmta_local_mover_read (struct ndm_session *sess,
			unsigned long long offset,
			unsigned long long length);
extern int	ndma_call_no_tattle (struct ndmconn *conn,
			struct ndmp_xa_buf *xa);
extern int	ndma_call (struct ndmconn *conn, struct ndmp_xa_buf *xa);
extern int	ndma_send_to_control (struct ndm_session *sess,
			struct ndmp_xa_buf *xa,
			struct ndmconn *from_conn);
extern int	ndma_tattle (struct ndmconn *conn,
			struct ndmp_xa_buf *xa, int rc);
extern struct ndm_dispatch_request_table *
		ndma_drt_lookup (struct ndm_dispatch_version_table *dvt,
			unsigned protocol_version, unsigned message);

#define NDMADR_RAISE(ERROR,ERRSTR) \
	   return ndma_dispatch_raise_error (sess, xa, ref_conn, ERROR, ERRSTR)

#define NDMADR_RAISE_ILLEGAL_ARGS(ERRSTR) \
			NDMADR_RAISE(NDMP9_ILLEGAL_ARGS_ERR, ERRSTR)
#define NDMADR_RAISE_ILLEGAL_STATE(ERRSTR) \
			NDMADR_RAISE(NDMP9_ILLEGAL_STATE_ERR, ERRSTR)




#define NDMADR_UNIMPLEMENTED_MESSAGE	(-1)	/* aka "TODO" */
#define NDMADR_UNSPECIFIED_MESSAGE	(-123)	/* no such per specs */
#define NDMADR_UNIMPLEMENTED_VERSION	(-1234)	/* implementation error */




/*
 * Operating System Specific
 ****************************************************************
 * Must be implemented in ndmos_xxx.c
 */

/* from ndma_dispatch_request() in ndma_dispatch.c */
extern int		ndmos_dispatch_request (struct ndm_session *sess,
				struct ndmp_xa_buf *xa,
				struct ndmconn *ref_conn);

/* from ndmadr_connect_client_auth() in ndma_dispatch.c */
extern int		ndmos_ok_name_password (struct ndm_session *sess,
				char *name, char *pass);
extern int		ndmos_get_md5_challenge (struct ndm_session *sess);
extern int		ndmos_ok_name_md5_digest (struct ndm_session *sess,
				char *name, char digest[16]);

/* from ndmadr_config_get_{host,server}_info() in ndma_dispatch.c */
extern void		ndmos_sync_config_info (struct ndm_session *sess);

/* from ndma_image_stream.c and ndma_ctrl_conn.c and others */
extern void		ndmos_condition_pipe_fd (struct ndm_session *sess,
				int fd);
extern void		ndmos_condition_listen_socket (
				struct ndm_session *sess, int sock);
extern void		ndmos_condition_control_socket (
				struct ndm_session *sess, int sock);
extern void		ndmos_condition_image_stream_socket (
				struct ndm_session *sess, int sock);

#ifndef NDMOS_OPTION_NO_TAPE_AGENT
extern int		ndmos_tape_initialize (struct ndm_session *sess);
extern ndmp9_error	ndmos_tape_open (struct ndm_session *sess,
				char *drive_name, int will_write);
extern ndmp9_error	ndmos_tape_close (struct ndm_session *sess);
extern void		ndmos_tape_sync_state (struct ndm_session *sess);
extern ndmp9_error	ndmos_tape_mtio (struct ndm_session *sess,
				ndmp9_tape_mtio_op op,
				u_long count, u_long *resid);
extern ndmp9_error	ndmos_tape_write (struct ndm_session *sess,
				char *buf,
				u_long count, u_long *done_count);
extern ndmp9_error	ndmos_tape_wfm (struct ndm_session *sess);
extern ndmp9_error	ndmos_tape_read (struct ndm_session *sess,
				char *buf,
				u_long count, u_long *done_count);
extern ndmp9_error	ndmos_tape_execute_cdb (struct ndm_session *sess,
				ndmp9_execute_cdb_request *request,
				ndmp9_execute_cdb_reply *reply);
#endif /* !NDMOS_OPTION_NO_TAPE_AGENT */

#ifndef NDMOS_OPTION_NO_ROBOT_AGENT
extern int		ndmos_scsi_initialize (struct ndm_session *sess);
extern void		ndmos_scsi_sync_state (struct ndm_session *sess);
extern void		ndmos_scsi_sync_config_info (struct ndm_session *sess);
ndmp9_error		ndmos_scsi_open (struct ndm_session *sess, char *name);
ndmp9_error		ndmos_scsi_close (struct ndm_session *sess);
ndmp9_error		ndmos_scsi_set_target (struct ndm_session *sess);
ndmp9_error		ndmos_scsi_reset_device (struct ndm_session *sess);
ndmp9_error		ndmos_scsi_reset_bus (struct ndm_session *sess);
ndmp9_error		ndmos_scsi_execute_cdb (struct ndm_session *sess,
				ndmp9_execute_cdb_request *request,
				ndmp9_execute_cdb_reply *reply);
#endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */


/* ndma_noti_calls.c */
#ifndef NDMOS_OPTION_NO_DATA_AGENT
extern int	ndma_notify_data_halted (struct ndm_session *sess);
extern int	ndma_notify_data_read (struct ndm_session *sess,
			unsigned long long offset,
			unsigned long long length);
#endif /* !NDMOS_OPTION_NO_DATA_AGENT */
#ifndef NDMOS_OPTION_NO_TAPE_AGENT
extern int	ndma_notify_mover_halted (struct ndm_session *sess);
extern int	ndma_notify_mover_paused (struct ndm_session *sess);
#endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
#ifndef NDMOS_EFFECT_NO_SERVER_AGENTS
extern void	ndma_send_logmsg (struct ndm_session *sess,
			ndmp9_log_type ltype, struct ndmconn *from_conn,
			char *fmt, ...);
#endif /* !NDMOS_EFFECT_NO_SERVER_AGENTS */
