--- /dev/null
+
+
+#define WRAP_INVALID_FHINFO (-1ull)
+#define WRAP_MAX_PATH (1024+512)
+#define WRAP_MAX_NAME 256
+#define WRAP_MAX_ENV 100
+#define WRAP_MAX_FILE 100
+#define WRAP_MAX_COMMAND (20*1024)
+#define WRAP_MAX_O_OPTION 100
+
+
+/* forward */
+struct wrap_ccb;
+
+/*
+ * MAIN helpers
+ ****************************************************************
+ */
+
+extern int wrap_main (int ac, char *av[], struct wrap_ccb *wccb);
+extern int wrap_main_start_index_file (struct wrap_ccb *wccb);
+extern int wrap_main_start_image_file (struct wrap_ccb *wccb);
+
+extern void wrap_log (struct wrap_ccb *wccb, char *fmt, ...);
+
+extern int wrap_set_error (struct wrap_ccb *wccb, int error);
+
+
+
+
+/*
+ * Command Execution
+ ****************************************************************
+ *
+ * This wrapper will spawn (fork/exec) a subprocess to do
+ * the real work. These help form the sh(1) command line,
+ * create the pipe fittings, and spawn the subprocess.
+ *
+ * The fdmap[3] corresponds to the subprocess stdin, stdout,
+ * and stderr. A value >= 0 is assumed to be an inherited
+ * file descriptor. A value < 0 is one of the special codes
+ * WRAP_FDMAP_xxx. On return, the _PIPE special codes are
+ * replaced with the file descriptor for the parent process
+ * end of the pipe.
+ */
+
+#define WRAP_FDMAP_INPUT_PIPE -2 /* input to child, parent writes */
+#define WRAP_FDMAP_OUTPUT_PIPE -3 /* output from child, parent reads */
+#define WRAP_FDMAP_DEV_NULL -4 /* /dev/null */
+
+extern int wrap_cmd_add_with_escapes (char *cmd, char *word,
+ char *special);
+extern int wrap_cmd_add_with_sh_escapes (char *cmd, char *word);
+extern int wrap_cmd_add_allow_file_wildcards (char *cmd, char *word);
+extern int wrap_pipe_fork_exec (char *cmd, int fdmap[3]);
+
+
+
+
+/*
+ * CCB -- Command Control Block
+ ****************************************************************
+ *
+ * A digested form of command line arguments
+ */
+
+enum wrap_ccb_op {
+ WRAP_CCB_OP_NONE = 0,
+ WRAP_CCB_OP_BACKUP = 1, /* -c */
+ WRAP_CCB_OP_RECOVER = 2, /* -x */
+ WRAP_CCB_OP_RECOVER_FILEHIST = 3 /* -t */
+};
+
+struct wrap_env {
+ char * name;
+ char * value;
+};
+
+struct wrap_file {
+ unsigned long long fhinfo;
+ char * original_name; /* relative to backup root */
+ char * save_to_name; /* relative to file system */
+};
+
+struct wrap_ccb {
+ int error;
+ int log_seq_num;
+ char errmsg[WRAP_MAX_NAME];
+
+ /* Raw arguments */
+ char * B_butype; /* -B TYPE */
+ int d_debug; /* -d N */
+ struct wrap_env env[WRAP_MAX_ENV]; /* -E NAME=VALUE */
+ int n_env;
+ char * f_file_name; /* -f FILE */
+ char * I_index_file_name; /* -I FILE */
+ char * o_option[WRAP_MAX_O_OPTION]; /* -o OPTION */
+ int n_o_option;
+
+ struct wrap_file file[WRAP_MAX_FILE]; /* recovery only */
+ int n_file;
+
+ /* derived from arguments */
+ char * progname;
+ enum wrap_ccb_op op;
+ FILE * index_fp;
+ int data_conn_fd;
+
+ /* Common interprettations of the env */
+ int hist_enable;
+ int direct_enable;
+ char * backup_root;
+
+ /*
+ * Recovery variables.
+ *
+ * All offset/length pairs refer to a portion of the
+ * backup image.
+ *
+ * have The portion currently in the buffer.
+ * want The portion wanted by the formatter
+ * (e.g. tar, dump).
+ * reading The portion immediately after what we
+ * "have" (in the buffer) still coming due
+ * to the last NDMP_NOTIFY_DATA_READ.
+ * last_read The portion requested by the last
+ * NDMP_NOTIFY_DATA_READ.
+ * expect Composite of have and reading.
+ */
+ char * iobuf;
+ unsigned long n_iobuf;
+
+ char * have;
+ unsigned long long have_offset;
+ unsigned long have_length; /* never bigger than iobuf */
+ unsigned long long want_offset;
+ unsigned long long want_length;
+ unsigned long long reading_offset;
+ unsigned long long reading_length;
+ unsigned long long last_read_offset;
+ unsigned long long last_read_length;
+ unsigned long long expect_offset;
+ unsigned long long expect_length;
+ int data_conn_mode;
+};
+
+extern int wrap_process_args (int argc, char *argv[],
+ struct wrap_ccb *wccb);
+extern char * wrap_find_env (struct wrap_ccb *wccb, char *name);
+
+
+extern int wrap_reco_seek (struct wrap_ccb *wccb,
+ unsigned long long want_offset,
+ unsigned long long want_length,
+ unsigned long must_have_length);
+extern int wrap_reco_must_have (struct wrap_ccb *wccb,
+ unsigned long length);
+extern int wrap_reco_pass (struct wrap_ccb *wccb, int write_fd,
+ unsigned long long length, unsigned write_bsize);
+extern int wrap_reco_align_to_wanted (struct wrap_ccb *wccb);
+extern int wrap_reco_receive (struct wrap_ccb *wccb);
+extern int wrap_reco_consume (struct wrap_ccb *wccb,
+ unsigned long length);
+extern int wrap_reco_issue_read (struct wrap_ccb *wccb);
+
+
+
+
+
+/*
+ * WRAP Messages
+ ****************************************************************
+ *
+ * A message is simply one text line following a format.
+ * These structures are used to buffer incoming messages.
+ */
+
+struct wrap_log_message { /* Lx */
+ char message[WRAP_MAX_PATH];
+};
+
+enum wrap_ftype {
+ WRAP_FTYPE_INVALID = 0,
+ WRAP_FTYPE_DIR = 1, /* d */
+ WRAP_FTYPE_FIFO = 2, /* p */
+ WRAP_FTYPE_CSPEC = 3, /* c */
+ WRAP_FTYPE_BSPEC = 4, /* b */
+ WRAP_FTYPE_REG = 5, /* - */
+ WRAP_FTYPE_SLINK = 6, /* l */
+ WRAP_FTYPE_SOCK = 7, /* s */
+ WRAP_FTYPE_REGISTRY = 8, /* R */
+ WRAP_FTYPE_OTHER = 9 /* o */
+};
+
+struct wrap_fstat {
+ unsigned long valid;
+#define WRAP_FSTAT_VALID_FTYPE (1ul<<0u)
+#define WRAP_FSTAT_VALID_MODE (1ul<<1u)
+#define WRAP_FSTAT_VALID_LINKS (1ul<<2u)
+#define WRAP_FSTAT_VALID_SIZE (1ul<<3u)
+#define WRAP_FSTAT_VALID_UID (1ul<<4u)
+#define WRAP_FSTAT_VALID_GID (1ul<<5u)
+#define WRAP_FSTAT_VALID_ATIME (1ul<<6u)
+#define WRAP_FSTAT_VALID_MTIME (1ul<<7u)
+#define WRAP_FSTAT_VALID_CTIME (1ul<<8u)
+#define WRAP_FSTAT_VALID_FILENO (1ul<<9u)
+
+ enum wrap_ftype ftype; /* f%s */
+ unsigned short mode; /* m%04o */
+ unsigned long links; /* l%lu */
+ unsigned long long size; /* s%llu */
+ unsigned long uid; /* u%lu */
+ unsigned long gid; /* g%lu */
+ unsigned long atime; /* ta%lu */
+ unsigned long mtime; /* tm%lu */
+ unsigned long ctime; /* tc%lu */
+ unsigned long long fileno; /* i%llu */
+};
+
+/*
+ * HF path [@fhinfo] [stats]
+ *
+ * History File -- Corresponds to NDMPv?_FH_ADD_FILE
+ */
+struct wrap_add_file {
+ unsigned long long fhinfo; /* @%llu */
+ struct wrap_fstat fstat;
+ char path[WRAP_MAX_PATH];
+};
+
+/*
+ * HD dir_fileno name fileno [@fhinfo]
+ *
+ * History Directory entry -- Corresponds to NDMPv?_FH_ADD_DIR
+ */
+struct wrap_add_dirent {
+ unsigned long long fhinfo; /* @%llu */
+ unsigned long long dir_fileno; /* %llu */
+ unsigned long long fileno; /* %llu */
+ char name[WRAP_MAX_NAME];
+};
+
+/*
+ * HN [@fhinfo] [stats] -- iFILENO must be present
+ *
+ * History Node -- Corresponds to NDMPv?_FH_ADD_NODE
+ */
+struct wrap_add_node { /* HN */
+ unsigned long long fhinfo; /* @%llu */
+ struct wrap_fstat fstat;
+};
+
+/*
+ * DE name value
+ *
+ * Data Env -- Corresponds to NDMPv?_DATA_GET_ENV
+ * This is used for the post backup processing env[].
+ */
+struct wrap_add_env {
+ char name[WRAP_MAX_NAME];
+ char value[WRAP_MAX_PATH];
+};
+
+/*
+ * DR offset length
+ *
+ * Data Read -- Corresponds to NDMPv?_NOTIFY_DATA_READ
+ * This is used during recovery operations to retrieve
+ * portions of the backup image.
+ */
+struct wrap_data_read { /* DR */
+ unsigned long long offset; /* %llu */
+ unsigned long long length; /* %llu */
+};
+
+/*
+ * DS s{r|d|f} [wN] [etN] [ebN]
+ *
+ * Data Stats -- Supplemental info for NDMPv?_DATA_GET_STATE
+ * Sent periodically to update certain fields of the
+ * DATA_GET_STATE reply.
+ */
+
+enum wrap_data_status {
+ WRAP_DS_INVALID = 0,
+ WRAP_DS_RUNNING = 1, /* sr */
+ WRAP_DS_DONE_OK = 2, /* sd */
+ WRAP_DS_DONE_FAILED = 3 /* sf */
+};
+
+struct wrap_data_stats { /* DS */
+ unsigned long valid;
+#define WRAP_DATASTATS_VALID_BYTES_WRITTEN (1ul<<0u)
+#define WRAP_DATASTATS_VALID_EST_TIME_REMAINING (1ul<<1u)
+#define WRAP_DATASTATS_VALID_EST_BYTES_REMAINING (1ul<<2u)
+
+ enum wrap_data_status status; /* s{r|d|f} */
+ unsigned long long bytes_written; /* w%llu */
+ unsigned long long est_time_remaining; /* et%llu */
+ unsigned long long est_bytes_remaining; /* eb%llu */
+};
+
+/*
+ * RR errno path
+ *
+ * Recovery Result -- Corresponds to NDMPv?_LOG_FILE
+ * Sent during recovery operations to report the
+ * success or failure of recovery.
+ */
+struct wrap_recovery_result { /* RR */
+ int rr_errno; /* sys/errno.h */
+ char path[WRAP_MAX_PATH];
+};
+
+enum wrap_msg_type {
+ WRAP_MSGTYPE_LOG_MESSAGE = 1,
+ WRAP_MSGTYPE_ADD_FILE = 2,
+ WRAP_MSGTYPE_ADD_DIRENT = 3,
+ WRAP_MSGTYPE_ADD_NODE = 4,
+ WRAP_MSGTYPE_ADD_ENV = 5,
+ WRAP_MSGTYPE_DATA_READ = 6,
+ WRAP_MSGTYPE_DATA_STATS = 7,
+ WRAP_MSGTYPE_RECOVERY_RESULT = 8,
+};
+
+struct wrap_msg_buf {
+ enum wrap_msg_type msg_type;
+ union {
+ struct wrap_log_message log_message;
+ struct wrap_add_file add_file;
+ struct wrap_add_dirent add_dirent;
+ struct wrap_add_node add_node;
+ struct wrap_add_env add_env;
+ struct wrap_data_read data_read;
+ struct wrap_data_stats data_stats;
+ struct wrap_recovery_result recovery_result;
+ } body;
+};
+
+extern int wrap_parse_msg (char *buf, struct wrap_msg_buf *wmsg);
+extern int wrap_parse_log_message_msg (char *buf, struct wrap_msg_buf *wmsg);
+extern int wrap_send_log_message (FILE *fp, char *message);
+extern int wrap_parse_add_file_msg (char *buf, struct wrap_msg_buf *wmsg);
+extern int wrap_send_add_file (FILE *fp, char *path, unsigned long long fhinfo,
+ struct wrap_fstat *fstat);
+extern int wrap_parse_add_dirent_msg (char *buf, struct wrap_msg_buf *wmsg);
+extern int wrap_send_add_dirent (FILE *fp, char *name,
+ unsigned long long fhinfo,
+ unsigned long long dir_fileno,
+ unsigned long long fileno);
+extern int wrap_parse_add_node_msg (char *buf, struct wrap_msg_buf *wmsg);
+extern int wrap_send_add_node (FILE *fp, unsigned long long fhinfo,
+ struct wrap_fstat *fstat);
+extern int wrap_parse_fstat_subr (char **scanp, struct wrap_fstat *fstat);
+extern int wrap_send_fstat_subr (FILE *fp, struct wrap_fstat *fstat);
+extern int wrap_parse_add_env_msg (char *buf, struct wrap_msg_buf *wmsg);
+extern int wrap_send_add_env (FILE *fp, char *name, char *value);
+extern int wrap_parse_data_read_msg (char *buf, struct wrap_msg_buf *wmsg);
+extern int wrap_send_data_read (FILE *fp, unsigned long long offset,
+ unsigned long long length);
+
+
+
+
+/*
+ * Canonical strings
+ ****************************************************************
+ * Convert strings to/from HTTP-like canonical strings (%xx).
+ * Example "a b%c" --> "a%20b%25c"
+ */
+
+#define NDMCSTR_WARN '%'
+extern int wrap_cstr_from_str (char *src, char *dst, unsigned dst_max);
+extern int wrap_cstr_to_str (char *src, char *dst, unsigned dst_max);
+extern int wrap_cstr_from_hex (int c);