Tweak an older NEWS item to be a bit clearer.
[rsync.git] / usage.c
blobf346385f4015cfdd4a02695994ae027ab50bb4c8
1 /*
2 * Some usage & version related functions.
4 * Copyright (C) 2002-2022 Wayne Davison
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, visit the http://fsf.org website.
20 #include "rsync.h"
21 #include "version.h"
22 #include "latest-year.h"
23 #include "git-version.h"
24 #include "default-cvsignore.h"
25 #include "itypes.h"
27 extern struct name_num_obj valid_checksums, valid_compressions, valid_auth_checksums;
29 static char *istring(const char *fmt, int val)
31 char *str;
32 if (asprintf(&str, fmt, val) < 0)
33 out_of_memory("istring");
34 return str;
37 static void print_info_flags(enum logcode f)
39 STRUCT_STAT *dumstat;
40 BOOL as_json = f == FNONE ? 1 : 0; /* We use 1 == first attribute, 2 == need closing array */
41 char line_buf[75], item_buf[32];
42 int line_len, j;
43 char *info_flags[] = {
45 "*Capabilities",
47 istring("%d-bit files", (int)(sizeof (OFF_T) * 8)),
48 istring("%d-bit inums", (int)(sizeof dumstat->st_ino * 8)), /* Don't check ino_t! */
49 istring("%d-bit timestamps", (int)(sizeof (time_t) * 8)),
50 istring("%d-bit long ints", (int)(sizeof (int64) * 8)),
52 #ifndef HAVE_SOCKETPAIR
53 "no "
54 #endif
55 "socketpairs",
57 #ifndef SUPPORT_LINKS
58 "no "
59 #endif
60 "symlinks",
62 #ifndef CAN_SET_SYMLINK_TIMES
63 "no "
64 #endif
65 "symtimes",
67 #ifndef SUPPORT_HARD_LINKS
68 "no "
69 #endif
70 "hardlinks",
72 #ifndef CAN_HARDLINK_SPECIAL
73 "no "
74 #endif
75 "hardlink-specials",
77 #ifndef CAN_HARDLINK_SYMLINK
78 "no "
79 #endif
80 "hardlink-symlinks",
82 #ifndef INET6
83 "no "
84 #endif
85 "IPv6",
87 #ifndef SUPPORT_ATIMES
88 "no "
89 #endif
90 "atimes",
92 "batchfiles",
94 #ifndef HAVE_FTRUNCATE
95 "no "
96 #endif
97 "inplace",
99 #ifndef HAVE_FTRUNCATE
100 "no "
101 #endif
102 "append",
104 #ifndef SUPPORT_ACLS
105 "no "
106 #endif
107 "ACLs",
109 #ifndef SUPPORT_XATTRS
110 "no "
111 #endif
112 "xattrs",
114 #ifdef RSYNC_USE_SECLUDED_ARGS
115 "default "
116 #else
117 "optional "
118 #endif
119 "secluded-args",
121 #ifndef ICONV_OPTION
122 "no "
123 #endif
124 "iconv",
126 #ifndef SUPPORT_PREALLOCATION
127 "no "
128 #endif
129 "prealloc",
131 #ifndef HAVE_MKTIME
132 "no "
133 #endif
134 "stop-at",
136 #ifndef SUPPORT_CRTIMES
137 "no "
138 #endif
139 "crtimes",
141 "*Optimizations",
143 #ifndef USE_ROLL_SIMD
144 "no "
145 #endif
146 "SIMD-roll",
148 #ifndef USE_ROLL_ASM
149 "no "
150 #endif
151 "asm-roll",
153 #ifndef USE_OPENSSL
154 "no "
155 #endif
156 "openssl-crypto",
158 #ifndef USE_MD5_ASM
159 "no "
160 #endif
161 "asm-MD5",
163 NULL
166 for (line_len = 0, j = 0; ; j++) {
167 char *str = info_flags[j], *next_nfo = str ? info_flags[j+1] : NULL;
168 int need_comma = next_nfo && *next_nfo != '*' ? 1 : 0;
169 int item_len;
170 if (!str || *str == '*')
171 item_len = 1000;
172 else if (as_json) {
173 char *space = strchr(str, ' ');
174 int is_no = space && strncmp(str, "no ", 3) == 0;
175 int is_bits = space && isDigit(str);
176 char *quot = space && !is_no && !is_bits ? "\"" : "";
177 char *item = space ? space + 1 : str;
178 char *val = !space ? "true" : is_no ? "false" : str;
179 int val_len = !space ? 4 : is_no ? 5 : space - str;
180 if (is_bits && (space = strchr(val, '-')) != NULL)
181 val_len = space - str;
182 item_len = snprintf(item_buf, sizeof item_buf,
183 " \"%s%s\": %s%.*s%s%s", item, is_bits ? "bits" : "",
184 quot, val_len, val, quot, need_comma ? "," : "");
185 if (is_bits)
186 item_buf[strlen(item)+2-1] = '_'; /* Turn the 's' into a '_' */
187 for (space = item; (space = strpbrk(space, " -")) != NULL; space++)
188 item_buf[space - item + 2] = '_';
189 } else
190 item_len = snprintf(item_buf, sizeof item_buf, " %s%s", str, need_comma ? "," : "");
191 if (line_len && line_len + item_len >= (int)sizeof line_buf) {
192 if (as_json)
193 printf(" %s\n", line_buf);
194 else
195 rprintf(f, " %s\n", line_buf);
196 line_len = 0;
198 if (!str)
199 break;
200 if (*str == '*') {
201 if (as_json) {
202 if (as_json == 2)
203 printf(" }");
204 else
205 as_json = 2;
206 printf(",\n \"%c%s\": {\n", toLower(str+1), str+2);
207 } else
208 rprintf(f, "%s:\n", str+1);
209 } else {
210 strlcpy(line_buf + line_len, item_buf, sizeof line_buf - line_len);
211 line_len += item_len;
214 if (as_json == 2)
215 printf(" }");
218 static void output_nno_list(enum logcode f, const char *name, struct name_num_obj *nno)
220 char namebuf[64], tmpbuf[256];
221 char *tok, *next_tok, *comma = ",";
222 char *cp;
224 /* Using '(' ensures that we get a trailing "none" but also includes aliases. */
225 get_default_nno_list(nno, tmpbuf, sizeof tmpbuf - 1, '(');
226 if (f != FNONE) {
227 rprintf(f, "%s:\n", name);
228 rprintf(f, " %s\n", tmpbuf);
229 return;
232 strlcpy(namebuf, name, sizeof namebuf);
233 for (cp = namebuf; *cp; cp++) {
234 if (*cp == ' ')
235 *cp = '_';
236 else if (isUpper(cp))
237 *cp = toLower(cp);
240 printf(",\n \"%s\": [\n ", namebuf);
242 for (tok = strtok(tmpbuf, " "); tok; tok = next_tok) {
243 next_tok = strtok(NULL, " ");
244 if (*tok != '(') /* Ignore the alises in the JSON output */
245 printf(" \"%s\"%s", tok, comma + (next_tok ? 0 : 1));
248 printf("\n ]");
251 /* A request of f == FNONE wants json on stdout. */
252 void print_rsync_version(enum logcode f)
254 char copyright[] = "(C) 1996-" LATEST_YEAR " by Andrew Tridgell, Wayne Davison, and others.";
255 char url[] = "https://rsync.samba.org/";
256 BOOL first_line = 1;
258 #define json_line(name, value) \
259 do { \
260 printf("%c\n \"%s\": \"%s\"", first_line ? '{' : ',', name, value); \
261 first_line = 0; \
262 } while (0)
264 if (f == FNONE) {
265 char verbuf[32];
266 json_line("program", RSYNC_NAME);
267 json_line("version", rsync_version());
268 (void)snprintf(verbuf, sizeof verbuf, "%d.%d", PROTOCOL_VERSION, SUBPROTOCOL_VERSION);
269 json_line("protocol", verbuf);
270 json_line("copyright", copyright);
271 json_line("url", url);
272 } else {
273 #if SUBPROTOCOL_VERSION != 0
274 char *subprotocol = istring(".PR%d", SUBPROTOCOL_VERSION);
275 #else
276 char *subprotocol = "";
277 #endif
278 rprintf(f, "%s version %s protocol version %d%s\n",
279 RSYNC_NAME, rsync_version(), PROTOCOL_VERSION, subprotocol);
280 rprintf(f, "Copyright %s\n", copyright);
281 rprintf(f, "Web site: %s\n", url);
284 print_info_flags(f);
286 init_checksum_choices();
288 output_nno_list(f, "Checksum list", &valid_checksums);
289 output_nno_list(f, "Compress list", &valid_compressions);
290 output_nno_list(f, "Daemon auth list", &valid_auth_checksums);
292 if (f == FNONE) {
293 json_line("license", "GPLv3");
294 json_line("caveat", "rsync comes with ABSOLUTELY NO WARRANTY");
295 printf("\n}\n");
296 fflush(stdout);
297 return;
300 #ifdef MAINTAINER_MODE
301 rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
302 #endif
304 #if SIZEOF_INT64 < 8
305 rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
306 #endif
307 if (sizeof (int64) != SIZEOF_INT64) {
308 rprintf(f,
309 "WARNING: size mismatch in SIZEOF_INT64 define (%d != %d)\n",
310 (int) SIZEOF_INT64, (int) sizeof (int64));
313 rprintf(f,"\n");
314 rprintf(f,"rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you\n");
315 rprintf(f,"are welcome to redistribute it under certain conditions. See the GNU\n");
316 rprintf(f,"General Public Licence for details.\n");
319 void usage(enum logcode F)
321 print_rsync_version(F);
323 rprintf(F,"\n");
324 rprintf(F,"rsync is a file transfer program capable of efficient remote update\n");
325 rprintf(F,"via a fast differencing algorithm.\n");
327 rprintf(F,"\n");
328 rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... DEST\n");
329 rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");
330 rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");
331 rprintf(F," or rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST\n");
332 rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC [DEST]\n");
333 rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC [DEST]\n");
334 rprintf(F," or rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]\n");
335 rprintf(F,"The ':' usages connect via remote shell, while '::' & 'rsync://' usages connect\n");
336 rprintf(F,"to an rsync daemon, and require SRC or DEST to start with a module name.\n");
337 rprintf(F,"\n");
338 rprintf(F,"Options\n");
339 #include "help-rsync.h"
340 rprintf(F,"\n");
341 rprintf(F,"Use \"rsync --daemon --help\" to see the daemon-mode command-line options.\n");
342 rprintf(F,"Please see the rsync(1) and rsyncd.conf(5) manpages for full documentation.\n");
343 rprintf(F,"See https://rsync.samba.org/ for updates, bug reports, and answers\n");
346 void daemon_usage(enum logcode F)
348 print_rsync_version(F);
350 rprintf(F,"\n");
351 rprintf(F,"Usage: rsync --daemon [OPTION]...\n");
352 #include "help-rsyncd.h"
353 rprintf(F,"\n");
354 rprintf(F,"If you were not trying to invoke rsync as a daemon, avoid using any of the\n");
355 rprintf(F,"daemon-specific rsync options. See also the rsyncd.conf(5) manpage.\n");
358 const char *rsync_version(void)
360 char *ver;
361 #ifdef RSYNC_GITVER
362 ver = RSYNC_GITVER;
363 #else
364 ver = RSYNC_VERSION;
365 #endif
366 return *ver == 'v' ? ver+1 : ver;
369 const char *default_cvsignore(void)
371 return DEFAULT_CVSIGNORE;