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 #define WRAP_INVALID_FHINFO (-1ull)
38 #define WRAP_MAX_PATH (1024 + 512)
39 #define WRAP_MAX_NAME 256
40 #define WRAP_MAX_ENV 100
41 #define WRAP_MAX_FILE 100
42 #define WRAP_MAX_COMMAND (20 * 1024)
43 #define WRAP_MAX_O_OPTION 100
44 
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48 
49 /* forward */
50 struct wrap_ccb;
51 
52 /*
53  * MAIN helpers
54  ****************************************************************
55  */
56 
57 extern int wrap_main(int ac, char* av[], struct wrap_ccb* wccb);
58 extern int wrap_main_start_index_file(struct wrap_ccb* wccb);
59 extern int wrap_main_start_image_file(struct wrap_ccb* wccb);
60 
61 extern void wrap_log(struct wrap_ccb* wccb, char* fmt, ...);
62 
63 extern int wrap_set_error(struct wrap_ccb* wccb, int error);
64 
65 
66 /*
67  * Command Execution
68  ****************************************************************
69  *
70  * This wrapper will spawn (fork/exec) a subprocess to do
71  * the real work. These help form the sh(1) command line,
72  * create the pipe fittings, and spawn the subprocess.
73  *
74  * The fdmap[3] corresponds to the subprocess stdin, stdout,
75  * and stderr. A value >= 0 is assumed to be an inherited
76  * file descriptor. A value < 0 is one of the special codes
77  * WRAP_FDMAP_xxx. On return, the _PIPE special codes are
78  * replaced with the file descriptor for the parent process
79  * end of the pipe.
80  */
81 
82 #define WRAP_FDMAP_INPUT_PIPE -2  /* input to child, parent writes */
83 #define WRAP_FDMAP_OUTPUT_PIPE -3 /* output from child, parent reads */
84 #define WRAP_FDMAP_DEV_NULL -4    /* /dev/null */
85 
86 extern int wrap_cmd_add_with_escapes(char* cmd, char* word, char* special);
87 extern int wrap_cmd_add_with_sh_escapes(char* cmd, char* word);
88 extern int wrap_cmd_add_allow_file_wildcards(char* cmd, char* word);
89 extern int wrap_pipe_fork_exec(char* cmd, int fdmap[3]);
90 
91 
92 /*
93  * CCB -- Command Control Block
94  ****************************************************************
95  *
96  * A digested form of command line arguments
97  */
98 
99 enum wrap_ccb_op
100 {
101   WRAP_CCB_OP_NONE = 0,
102   WRAP_CCB_OP_BACKUP = 1,          /* -c */
103   WRAP_CCB_OP_RECOVER = 2,         /* -x */
104   WRAP_CCB_OP_RECOVER_FILEHIST = 3 /* -t */
105 };
106 
107 struct wrap_env {
108   char* name;
109   char* value;
110 };
111 
112 struct wrap_file {
113   uint64_t fhinfo;
114   char* original_name; /* relative to backup root */
115   char* save_to_name;  /* relative to file system */
116 };
117 
118 struct wrap_ccb {
119   int error;
120   int log_seq_num;
121   char errmsg[WRAP_MAX_NAME];
122 
123   /* Raw arguments */
124   char* B_butype;                    /* -B TYPE */
125   int d_debug;                       /* -d N */
126   struct wrap_env env[WRAP_MAX_ENV]; /* -E NAME=VALUE */
127   int n_env;
128   char* f_file_name;                 /* -f FILE */
129   char* I_index_file_name;           /* -I FILE */
130   char* o_option[WRAP_MAX_O_OPTION]; /* -o OPTION */
131   int n_o_option;
132 
133   struct wrap_file file[WRAP_MAX_FILE]; /* recovery only */
134   int n_file;
135 
136   /* derived from arguments */
137   char* progname;
138   enum wrap_ccb_op op;
139   FILE* index_fp;
140   int data_conn_fd;
141 
142   /* Common interprettations of the env */
143   int hist_enable;
144   int direct_enable;
145   char* backup_root;
146 
147   /*
148    * Recovery variables.
149    *
150    * All offset/length pairs refer to a portion of the
151    * backup image.
152    *
153    * have               The portion currently in the buffer.
154    * want               The portion wanted by the formatter
155    *            (e.g. tar, dump).
156    * reading    The portion immediately after what we
157    *            "have" (in the buffer) still coming due
158    *            to the last NDMP_NOTIFY_DATA_READ.
159    * last_read  The portion requested by the last
160    *            NDMP_NOTIFY_DATA_READ.
161    * expect     Composite of have and reading.
162    */
163   char* iobuf;
164   uint32_t n_iobuf;
165 
166   char* have;
167   uint64_t have_offset;
168   uint32_t have_length; /* never bigger than iobuf */
169   uint64_t want_offset;
170   uint64_t want_length;
171   uint64_t reading_offset;
172   uint64_t reading_length;
173   uint64_t last_read_offset;
174   uint64_t last_read_length;
175   uint64_t expect_offset;
176   uint64_t expect_length;
177   int data_conn_mode;
178 };
179 
180 extern int wrap_process_args(int argc, char* argv[], struct wrap_ccb* wccb);
181 extern char* wrap_find_env(struct wrap_ccb* wccb, char* name);
182 
183 
184 extern int wrap_reco_seek(struct wrap_ccb* wccb,
185                           uint64_t want_offset,
186                           uint64_t want_length,
187                           uint32_t must_have_length);
188 extern int wrap_reco_must_have(struct wrap_ccb* wccb, uint32_t length);
189 extern int wrap_reco_pass(struct wrap_ccb* wccb,
190                           int write_fd,
191                           uint64_t length,
192                           unsigned write_bsize);
193 extern int wrap_reco_align_to_wanted(struct wrap_ccb* wccb);
194 extern int wrap_reco_receive(struct wrap_ccb* wccb);
195 extern int wrap_reco_consume(struct wrap_ccb* wccb, uint32_t length);
196 extern int wrap_reco_issue_read(struct wrap_ccb* wccb);
197 
198 
199 /*
200  * WRAP Messages
201  ****************************************************************
202  *
203  * A message is simply one text line following a format.
204  * These structures are used to buffer incoming messages.
205  */
206 
207 struct wrap_log_message { /* Lx */
208   char message[WRAP_MAX_PATH];
209 };
210 
211 enum wrap_ftype
212 {
213   WRAP_FTYPE_INVALID = 0,
214   WRAP_FTYPE_DIR = 1,      /* d */
215   WRAP_FTYPE_FIFO = 2,     /* p */
216   WRAP_FTYPE_CSPEC = 3,    /* c */
217   WRAP_FTYPE_BSPEC = 4,    /* b */
218   WRAP_FTYPE_REG = 5,      /* - */
219   WRAP_FTYPE_SLINK = 6,    /* l */
220   WRAP_FTYPE_SOCK = 7,     /* s */
221   WRAP_FTYPE_REGISTRY = 8, /* R */
222   WRAP_FTYPE_OTHER = 9     /* o */
223 };
224 
225 struct wrap_fstat {
226   uint32_t valid;
227 #define WRAP_FSTAT_VALID_FTYPE (1ul << 0u)
228 #define WRAP_FSTAT_VALID_MODE (1ul << 1u)
229 #define WRAP_FSTAT_VALID_LINKS (1ul << 2u)
230 #define WRAP_FSTAT_VALID_SIZE (1ul << 3u)
231 #define WRAP_FSTAT_VALID_UID (1ul << 4u)
232 #define WRAP_FSTAT_VALID_GID (1ul << 5u)
233 #define WRAP_FSTAT_VALID_ATIME (1ul << 6u)
234 #define WRAP_FSTAT_VALID_MTIME (1ul << 7u)
235 #define WRAP_FSTAT_VALID_CTIME (1ul << 8u)
236 #define WRAP_FSTAT_VALID_FILENO (1ul << 9u)
237 
238   enum wrap_ftype ftype; /* f%s */
239   uint16_t mode;         /* m%04o */
240   uint32_t links;        /* l%lu */
241   uint64_t size;         /* s%llu */
242   uint32_t uid;          /* u%lu */
243   uint32_t gid;          /* g%lu */
244   uint32_t atime;        /* ta%lu */
245   uint32_t mtime;        /* tm%lu */
246   uint32_t ctime;        /* tc%lu */
247   uint64_t fileno;       /* i%llu */
248 };
249 
250 /*
251  * HF path [@fhinfo] [stats]
252  *
253  * History File -- Corresponds to NDMPv?_FH_ADD_FILE
254  */
255 struct wrap_add_file {
256   uint64_t fhinfo; /* @%llu */
257   struct wrap_fstat fstat;
258   char path[WRAP_MAX_PATH];
259 };
260 
261 /*
262  * HD dir_fileno name fileno [@fhinfo]
263  *
264  * History Directory entry -- Corresponds to NDMPv?_FH_ADD_DIR
265  */
266 struct wrap_add_dirent {
267   uint64_t fhinfo;     /* @%llu */
268   uint64_t dir_fileno; /* %llu */
269   uint64_t fileno;     /* %llu */
270   char name[WRAP_MAX_NAME];
271 };
272 
273 /*
274  * HN [@fhinfo] [stats] -- iFILENO must be present
275  *
276  * History Node -- Corresponds to NDMPv?_FH_ADD_NODE
277  */
278 struct wrap_add_node { /* HN */
279   uint64_t fhinfo;     /* @%llu */
280   struct wrap_fstat fstat;
281 };
282 
283 /*
284  * DE name value
285  *
286  * Data Env -- Corresponds to NDMPv?_DATA_GET_ENV
287  * This is used for the post backup processing env[].
288  */
289 struct wrap_add_env {
290   char name[WRAP_MAX_NAME];
291   char value[WRAP_MAX_PATH];
292 };
293 
294 /*
295  * DR offset length
296  *
297  * Data Read -- Corresponds to NDMPv?_NOTIFY_DATA_READ
298  * This is used during recovery operations to retrieve
299  * portions of the backup image.
300  */
301 struct wrap_data_read { /* DR */
302   uint64_t offset;      /* %llu */
303   uint64_t length;      /* %llu */
304 };
305 
306 /*
307  * DS s{r|d|f} [wN] [etN] [ebN]
308  *
309  * Data Stats -- Supplemental info for NDMPv?_DATA_GET_STATE
310  * Sent periodically to update certain fields of the
311  * DATA_GET_STATE reply.
312  */
313 
314 enum wrap_data_status
315 {
316   WRAP_DS_INVALID = 0,
317   WRAP_DS_RUNNING = 1,    /* sr */
318   WRAP_DS_DONE_OK = 2,    /* sd */
319   WRAP_DS_DONE_FAILED = 3 /* sf */
320 };
321 
322 struct wrap_data_stats { /* DS */
323   uint32_t valid;
324 #define WRAP_DATASTATS_VALID_BYTES_WRITTEN (1ul << 0u)
325 #define WRAP_DATASTATS_VALID_EST_TIME_REMAINING (1ul << 1u)
326 #define WRAP_DATASTATS_VALID_EST_BYTES_REMAINING (1ul << 2u)
327 
328   enum wrap_data_status status; /* s{r|d|f} */
329   uint64_t bytes_written;       /* w%llu */
330   uint64_t est_time_remaining;  /* et%llu */
331   uint64_t est_bytes_remaining; /* eb%llu */
332 };
333 
334 /*
335  * RR errno path
336  *
337  * Recovery Result -- Corresponds to NDMPv?_LOG_FILE
338  * Sent during recovery operations to report the
339  * success or failure of recovery.
340  */
341 struct wrap_recovery_result { /* RR */
342   int rr_errno;               /* sys/errno.h */
343   char path[WRAP_MAX_PATH];
344 };
345 
346 enum wrap_msg_type
347 {
348   WRAP_MSGTYPE_LOG_MESSAGE = 1,
349   WRAP_MSGTYPE_ADD_FILE = 2,
350   WRAP_MSGTYPE_ADD_DIRENT = 3,
351   WRAP_MSGTYPE_ADD_NODE = 4,
352   WRAP_MSGTYPE_ADD_ENV = 5,
353   WRAP_MSGTYPE_DATA_READ = 6,
354   WRAP_MSGTYPE_DATA_STATS = 7,
355   WRAP_MSGTYPE_RECOVERY_RESULT = 8,
356 };
357 
358 struct wrap_msg_buf {
359   enum wrap_msg_type msg_type;
360   union {
361     struct wrap_log_message log_message;
362     struct wrap_add_file add_file;
363     struct wrap_add_dirent add_dirent;
364     struct wrap_add_node add_node;
365     struct wrap_add_env add_env;
366     struct wrap_data_read data_read;
367     struct wrap_data_stats data_stats;
368     struct wrap_recovery_result recovery_result;
369   } body;
370 };
371 
372 extern int wrap_parse_msg(char* buf, struct wrap_msg_buf* wmsg);
373 extern int wrap_parse_log_message_msg(char* buf, struct wrap_msg_buf* wmsg);
374 extern int wrap_send_log_message(FILE* fp, char* message);
375 extern int wrap_parse_add_file_msg(char* buf, struct wrap_msg_buf* wmsg);
376 extern int wrap_send_add_file(FILE* fp,
377                               char* path,
378                               uint64_t fhinfo,
379                               struct wrap_fstat* fstat);
380 extern int wrap_parse_add_dirent_msg(char* buf, struct wrap_msg_buf* wmsg);
381 extern int wrap_send_add_dirent(FILE* fp,
382                                 char* name,
383                                 uint64_t fhinfo,
384                                 uint64_t dir_fileno,
385                                 uint64_t fileno);
386 extern int wrap_parse_add_node_msg(char* buf, struct wrap_msg_buf* wmsg);
387 extern int wrap_send_add_node(FILE* fp,
388                               uint64_t fhinfo,
389                               struct wrap_fstat* fstat);
390 extern int wrap_parse_fstat_subr(char** scanp, struct wrap_fstat* fstat);
391 extern int wrap_send_fstat_subr(FILE* fp, struct wrap_fstat* fstat);
392 extern int wrap_parse_add_env_msg(char* buf, struct wrap_msg_buf* wmsg);
393 extern int wrap_send_add_env(FILE* fp, char* name, char* value);
394 extern int wrap_parse_data_read_msg(char* buf, struct wrap_msg_buf* wmsg);
395 extern int wrap_send_data_read(FILE* fp, uint64_t offset, uint64_t length);
396 
397 
398 /*
399  * Canonical strings
400  ****************************************************************
401  * Convert strings to/from HTTP-like canonical strings (%xx).
402  * Example "a b%c" --> "a%20b%25c"
403  */
404 
405 #define NDMCSTR_WARN '%'
406 extern int wrap_cstr_from_str(char* src, char* dst, unsigned dst_max);
407 extern int wrap_cstr_to_str(char* src, char* dst, unsigned dst_max);
408 extern int wrap_cstr_from_hex(int c);
409 
410 #ifdef __cplusplus
411 }
412 #endif
413