xref: /openbsd-src/usr.bin/rsync/fargs.c (revision f1dd7b858388b4a23f4f67a4957ec5ff656ebbe8)
1 /*	$Id: fargs.c,v 1.18 2021/05/17 12:02:58 claudio Exp $ */
2 /*
3  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 #include <sys/stat.h>
18 
19 #include <assert.h>
20 #include <err.h>
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include "extern.h"
26 
27 #define	RSYNC_PATH	"rsync"
28 
29 char **
30 fargs_cmdline(struct sess *sess, const struct fargs *f, size_t *skip)
31 {
32 	arglist		 args;
33 	size_t		 j;
34 	char		*rsync_path, *ap, *arg;
35 
36 	memset(&args, 0, sizeof args);
37 
38 	assert(f != NULL);
39 	assert(f->sourcesz > 0);
40 
41 	if ((rsync_path = sess->opts->rsync_path) == NULL)
42 		rsync_path = RSYNC_PATH;
43 
44 	if (f->host != NULL) {
45 		/*
46 		 * Splice arguments from -e "foo bar baz" into array
47 		 * elements required for execve(2).
48 		 * This doesn't do anything fancy: it splits along
49 		 * whitespace into the array.
50 		 */
51 
52 		if (sess->opts->ssh_prog) {
53 			ap = strdup(sess->opts->ssh_prog);
54 			if (ap == NULL)
55 				err(ERR_NOMEM, NULL);
56 
57 			while ((arg = strsep(&ap, " \t")) != NULL) {
58 				if (arg[0] == '\0') {
59 					ap++;	/* skip seperators */
60 					continue;
61 				}
62 
63 				addargs(&args, "%s", arg);
64 			}
65 		} else
66 			addargs(&args, "ssh");
67 
68 		addargs(&args, "%s", f->host);
69 		addargs(&args, "%s", rsync_path);
70 		if (skip)
71 			*skip = args.num;
72 		addargs(&args, "--server");
73 		if (f->mode == FARGS_RECEIVER)
74 			addargs(&args, "--sender");
75 	} else {
76 		addargs(&args, "%s", rsync_path);
77 		addargs(&args, "--server");
78 	}
79 
80 	/* Shared arguments. */
81 
82 	if (sess->opts->del)
83 		addargs(&args, "--delete");
84 	if (sess->opts->numeric_ids)
85 		addargs(&args, "--numeric-ids");
86 	if (sess->opts->preserve_gids)
87 		addargs(&args, "-g");
88 	if (sess->opts->preserve_links)
89 		addargs(&args, "-l");
90 	if (sess->opts->dry_run)
91 		addargs(&args, "-n");
92 	if (sess->opts->preserve_uids)
93 		addargs(&args, "-o");
94 	if (sess->opts->preserve_perms)
95 		addargs(&args, "-p");
96 	if (sess->opts->devices)
97 		addargs(&args, "-D");
98 	if (sess->opts->recursive)
99 		addargs(&args, "-r");
100 	if (sess->opts->preserve_times)
101 		addargs(&args, "-t");
102 	if (verbose > 3)
103 		addargs(&args, "-v");
104 	if (verbose > 2)
105 		addargs(&args, "-v");
106 	if (verbose > 1)
107 		addargs(&args, "-v");
108 	if (verbose > 0)
109 		addargs(&args, "-v");
110 	if (sess->opts->one_file_system > 1)
111 		addargs(&args, "-x");
112 	if (sess->opts->one_file_system > 0)
113 		addargs(&args, "-x");
114 	if (sess->opts->specials && !sess->opts->devices)
115 		addargs(&args, "--specials");
116 	if (!sess->opts->specials && sess->opts->devices)
117 		/* --devices is sent as -D --no-specials */
118 		addargs(&args, "--no-specials");
119 
120 	/* Terminate with a full-stop for reasons unknown. */
121 
122 	addargs(&args, ".");
123 
124 	if (f->mode == FARGS_RECEIVER) {
125 		for (j = 0; j < f->sourcesz; j++)
126 			addargs(&args, "%s", f->sources[j]);
127 	} else
128 		addargs(&args, "%s", f->sink);
129 
130 	return args.list;
131 }
132