xref: /openbsd/usr.bin/rsync/fargs.c (revision 3cab2bb3)
1 /*	$Id: fargs.c,v 1.17 2019/05/08 20:00:25 benno 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 <stdint.h>
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "extern.h"
25 
26 #define	RSYNC_PATH	"rsync"
27 
28 char **
29 fargs_cmdline(struct sess *sess, const struct fargs *f, size_t *skip)
30 {
31 	arglist		 args;
32 	size_t		 j;
33 	char		*rsync_path, *ap, *arg;
34 
35 	memset(&args, 0, sizeof args);
36 
37 	assert(f != NULL);
38 	assert(f->sourcesz > 0);
39 
40 	if ((rsync_path = sess->opts->rsync_path) == NULL)
41 		rsync_path = RSYNC_PATH;
42 
43 	if (f->host != NULL) {
44 		/*
45 		 * Splice arguments from -e "foo bar baz" into array
46 		 * elements required for execve(2).
47 		 * This doesn't do anything fancy: it splits along
48 		 * whitespace into the array.
49 		 */
50 
51 		if (sess->opts->ssh_prog) {
52 			ap = strdup(sess->opts->ssh_prog);
53 			if (ap == NULL)
54 				goto out;
55 
56 			while ((arg = strsep(&ap, " \t")) != NULL) {
57 				if (arg[0] == '\0') {
58 					ap++;	/* skip seperators */
59 					continue;
60 				}
61 
62 				addargs(&args, "%s", arg);
63 			}
64 		} else
65 			addargs(&args, "ssh");
66 
67 		addargs(&args, "%s", f->host);
68 		addargs(&args, "%s", rsync_path);
69 		if (skip)
70 			*skip = args.num;
71 		addargs(&args, "--server");
72 		if (f->mode == FARGS_RECEIVER)
73 			addargs(&args, "--sender");
74 	} else {
75 		addargs(&args, "%s", rsync_path);
76 		addargs(&args, "--server");
77 	}
78 
79 	/* Shared arguments. */
80 
81 	if (sess->opts->del)
82 		addargs(&args, "--delete");
83 	if (sess->opts->numeric_ids)
84 		addargs(&args, "--numeric-ids");
85 	if (sess->opts->preserve_gids)
86 		addargs(&args, "-g");
87 	if (sess->opts->preserve_links)
88 		addargs(&args, "-l");
89 	if (sess->opts->dry_run)
90 		addargs(&args, "-n");
91 	if (sess->opts->preserve_uids)
92 		addargs(&args, "-o");
93 	if (sess->opts->preserve_perms)
94 		addargs(&args, "-p");
95 	if (sess->opts->devices)
96 		addargs(&args, "-D");
97 	if (sess->opts->recursive)
98 		addargs(&args, "-r");
99 	if (sess->opts->preserve_times)
100 		addargs(&args, "-t");
101 	if (verbose > 3)
102 		addargs(&args, "-v");
103 	if (verbose > 2)
104 		addargs(&args, "-v");
105 	if (verbose > 1)
106 		addargs(&args, "-v");
107 	if (verbose > 0)
108 		addargs(&args, "-v");
109 	if (sess->opts->one_file_system > 1)
110 		addargs(&args, "-x");
111 	if (sess->opts->one_file_system > 0)
112 		addargs(&args, "-x");
113 	if (sess->opts->specials && !sess->opts->devices)
114 		addargs(&args, "--specials");
115 	if (!sess->opts->specials && sess->opts->devices)
116 		/* --devices is sent as -D --no-specials */
117 		addargs(&args, "--no-specials");
118 
119 	/* Terminate with a full-stop for reasons unknown. */
120 
121 	addargs(&args, ".");
122 
123 	if (f->mode == FARGS_RECEIVER) {
124 		for (j = 0; j < f->sourcesz; j++)
125 			addargs(&args, "%s", f->sources[j]);
126 	} else
127 		addargs(&args, "%s", f->sink);
128 
129 	return args.list;
130 out:
131 	freeargs(&args);
132 	ERR("calloc");
133 	return NULL;
134 }
135