1 /* $OpenBSD: fargs.c,v 1.20 2021/10/22 11:10:34 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 const char * 30 alt_base_mode(int mode) 31 { 32 switch(mode) { 33 case BASE_MODE_COMPARE: 34 return "--compare-dest"; 35 case BASE_MODE_COPY: 36 return "--copy-dest"; 37 case BASE_MODE_LINK: 38 return "--link-dest"; 39 default: 40 errx(1, "unknown base mode %d", mode); 41 } 42 } 43 44 char ** 45 fargs_cmdline(struct sess *sess, const struct fargs *f, size_t *skip) 46 { 47 arglist args; 48 size_t j; 49 char *rsync_path, *ap, *arg; 50 51 memset(&args, 0, sizeof args); 52 53 assert(f != NULL); 54 assert(f->sourcesz > 0); 55 56 if ((rsync_path = sess->opts->rsync_path) == NULL) 57 rsync_path = RSYNC_PATH; 58 59 if (f->host != NULL) { 60 /* 61 * Splice arguments from -e "foo bar baz" into array 62 * elements required for execve(2). 63 * This doesn't do anything fancy: it splits along 64 * whitespace into the array. 65 */ 66 67 if (sess->opts->ssh_prog) { 68 ap = strdup(sess->opts->ssh_prog); 69 if (ap == NULL) 70 err(ERR_NOMEM, NULL); 71 72 while ((arg = strsep(&ap, " \t")) != NULL) { 73 if (arg[0] == '\0') { 74 ap++; /* skip seperators */ 75 continue; 76 } 77 78 addargs(&args, "%s", arg); 79 } 80 } else 81 addargs(&args, "ssh"); 82 83 addargs(&args, "%s", f->host); 84 addargs(&args, "%s", rsync_path); 85 if (skip) 86 *skip = args.num; 87 addargs(&args, "--server"); 88 if (f->mode == FARGS_RECEIVER) 89 addargs(&args, "--sender"); 90 } else { 91 addargs(&args, "%s", rsync_path); 92 addargs(&args, "--server"); 93 } 94 95 /* Shared arguments. */ 96 97 if (sess->opts->del) 98 addargs(&args, "--delete"); 99 if (sess->opts->numeric_ids) 100 addargs(&args, "--numeric-ids"); 101 if (sess->opts->preserve_gids) 102 addargs(&args, "-g"); 103 if (sess->opts->preserve_links) 104 addargs(&args, "-l"); 105 if (sess->opts->dry_run) 106 addargs(&args, "-n"); 107 if (sess->opts->preserve_uids) 108 addargs(&args, "-o"); 109 if (sess->opts->preserve_perms) 110 addargs(&args, "-p"); 111 if (sess->opts->devices) 112 addargs(&args, "-D"); 113 if (sess->opts->recursive) 114 addargs(&args, "-r"); 115 if (sess->opts->preserve_times) 116 addargs(&args, "-t"); 117 if (verbose > 3) 118 addargs(&args, "-v"); 119 if (verbose > 2) 120 addargs(&args, "-v"); 121 if (verbose > 1) 122 addargs(&args, "-v"); 123 if (verbose > 0) 124 addargs(&args, "-v"); 125 if (sess->opts->one_file_system > 1) 126 addargs(&args, "-x"); 127 if (sess->opts->one_file_system > 0) 128 addargs(&args, "-x"); 129 if (sess->opts->specials && !sess->opts->devices) 130 addargs(&args, "--specials"); 131 if (!sess->opts->specials && sess->opts->devices) 132 /* --devices is sent as -D --no-specials */ 133 addargs(&args, "--no-specials"); 134 135 /* only add --compare-dest, etc if this is the sender */ 136 if (sess->opts->alt_base_mode != 0 && 137 f->mode == FARGS_SENDER) { 138 for (j = 0; j < MAX_BASEDIR; j++) { 139 if (sess->opts->basedir[j] == NULL) 140 break; 141 addargs(&args, "%s=%s", 142 alt_base_mode(sess->opts->alt_base_mode), 143 sess->opts->basedir[j]); 144 } 145 } 146 147 /* Terminate with a full-stop for reasons unknown. */ 148 149 addargs(&args, "."); 150 151 if (f->mode == FARGS_RECEIVER) { 152 for (j = 0; j < f->sourcesz; j++) 153 addargs(&args, "%s", f->sources[j]); 154 } else 155 addargs(&args, "%s", f->sink); 156 157 return args.list; 158 } 159