ᴄʜʀɪsᴛᴏᴘʜᴇʀ ᴍᴇɴɢAdd IDN support (#986)f0177d82 months agoHistory
395 lines · 9.8 KB · C
RawDownload
/* * Some usage & version related functions. * * Copyright (C) 2002-2022 Wayne Davison * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, visit the http://fsf.org website. */ #include "rsync.h"#include "version.h"#include "latest-year.h"#include "git-version.h"#include "default-cvsignore.h"#include "itypes.h"#include "lib/acl.h" extern struct name_num_obj valid_checksums, valid_compressions, valid_auth_checksums; static char *istring(const char *fmt, int val){	char *str;	if (asprintf(&str, fmt, val) < 0)		out_of_memory("istring");	return str;} static void print_info_flags(enum logcode f){	STRUCT_STAT *dumstat;	BOOL as_json = f == FNONE ? 1 : 0; /* We use 1 == first attribute, 2 == need closing array */	char line_buf[75], item_buf[32];	int line_len, j;	char *info_flags[] = { 	"*Capabilities", 		istring("%d-bit files", (int)(sizeof (OFF_T) * 8)),		istring("%d-bit inums", (int)(sizeof dumstat->st_ino * 8)), /* Don't check ino_t! */		istring("%d-bit timestamps", (int)(sizeof (time_t) * 8)),		istring("%d-bit long ints", (int)(sizeof (int64) * 8)), #ifndef HAVE_SOCKETPAIR		"no "#endif			"socketpairs", #ifndef SUPPORT_LINKS		"no "#endif			"symlinks", #ifndef CAN_SET_SYMLINK_TIMES		"no "#endif			"symtimes", #ifndef SUPPORT_HARD_LINKS		"no "#endif			"hardlinks", #ifndef CAN_HARDLINK_SPECIAL		"no "#endif			"hardlink-specials", #ifndef CAN_HARDLINK_SYMLINK		"no "#endif			"hardlink-symlinks", #ifndef INET6		"no "#endif			"IPv6", #ifndef SUPPORT_ATIMES		"no "#endif			"atimes", 		"batchfiles", #ifndef HAVE_FTRUNCATE		"no "#endif			"inplace", #ifndef HAVE_FTRUNCATE		"no "#endif			"append", #ifndef SUPPORT_ACLS		"no "#endif			"ACLs", #ifdef SUPPORT_ACL_FD#ifdef HAVE_LIBACL_AT		/* The patched libacl *_at calls apply received ACLs race-safely		 * on every Linux kernel (compat layer below 6.13).  Emit ACL-at (true, so		 * the JSON "ACL_at": true lets acl-symlink-race assert) plus a		 * distinguishing libacl token. */		"ACL-at",		"ACL-libacl-at",#else		/* Runtime: are the *xattrat syscalls usable, so a received ACL is		 * applied race-safely (dirfd+leaf, AT_SYMLINK_NOFOLLOW) even when the		 * leaf can't be pinned?  False => ACLs are applied via the path on an		 * un-pinnable leaf, which carries the parent-symlink-race exposure. */		xacl_at_available() ? "ACL-at" : "no ACL-at",#endif#endif #ifndef SUPPORT_XATTRS		"no "#endif			"xattrs", #ifdef RSYNC_USE_SECLUDED_ARGS		"default "#else		"optional "#endif			"secluded-args", #ifndef ICONV_OPTION		"no "#endif			"iconv", #ifndef SUPPORT_PREALLOCATION		"no "#endif			"prealloc", #ifndef HAVE_MKTIME		"no "#endif			"stop-at", #ifndef SUPPORT_CRTIMES		"no "#endif			"crtimes", #ifndef SUPPORT_IDN		"no "#endif			"IDN", 	"*Optimizations", #ifndef USE_ROLL_SIMD		"no "#endif			"SIMD-roll", #ifndef USE_ROLL_ASM		"no "#endif			"asm-roll", #ifndef USE_OPENSSL		"no "#endif			"openssl-crypto", #ifndef USE_MD5_ASM		"no "#endif			"asm-MD5", 		NULL	}; 	for (line_len = 0, j = 0; ; j++) {		char *str = info_flags[j], *next_nfo = str ? info_flags[j+1] : NULL;		int need_comma = next_nfo && *next_nfo != '*' ? 1 : 0;		int item_len;		if (!str || *str == '*')			item_len = 1000;		else if (as_json) {			char *space = strchr(str, ' ');			int is_no = space && strncmp(str, "no ", 3) == 0;			int is_bits = space && isDigit(str);			char *quot = space && !is_no && !is_bits ? "\"" : "";			char *item = space ? space + 1 : str;			char *val = !space ? "true" : is_no ? "false" : str;			int val_len = !space ? 4 : is_no ? 5 : space - str;			if (is_bits && (space = strchr(val, '-')) != NULL)			    val_len = space - str;			item_len = snprintf(item_buf, sizeof item_buf,					   " \"%s%s\": %s%.*s%s%s", item, is_bits ? "bits" : "",					   quot, val_len, val, quot, need_comma ? "," : "");			if (is_bits)				item_buf[strlen(item)+2-1] = '_'; /* Turn the 's' into a '_' */			for (space = item; (space = strpbrk(space, " -")) != NULL; space++)				item_buf[space - item + 2] = '_';		} else			item_len = snprintf(item_buf, sizeof item_buf, " %s%s", str, need_comma ? "," : "");		if (line_len && line_len + item_len >= (int)sizeof line_buf) {			if (as_json)				printf("   %s\n", line_buf);			else				rprintf(f, "   %s\n", line_buf);			line_len = 0;		}		if (!str)			break;		if (*str == '*') {			if (as_json) {				if (as_json == 2)					printf("  }");				else					as_json = 2;				printf(",\n  \"%c%s\": {\n", toLower(str+1), str+2);			} else				rprintf(f, "%s:\n", str+1);		} else {			strlcpy(line_buf + line_len, item_buf, sizeof line_buf - line_len);			line_len += item_len;		}	}	if (as_json == 2)		printf("  }");} static void output_nno_list(enum logcode f, const char *name, struct name_num_obj *nno){	char namebuf[64], tmpbuf[256];	char *tok, *next_tok, *comma = ",";	char *cp; 	/* Using '(' ensures that we get a trailing "none" but also includes aliases. */	get_default_nno_list(nno, tmpbuf, sizeof tmpbuf - 1, '(');	if (f != FNONE) {		rprintf(f, "%s:\n", name);		rprintf(f, "    %s\n", tmpbuf);		return;	} 	strlcpy(namebuf, name, sizeof namebuf);	for (cp = namebuf; *cp; cp++) {		if (*cp == ' ')			*cp = '_';		else if (isUpper(cp))			*cp = toLower(cp);	} 	printf(",\n  \"%s\": [\n   ", namebuf); 	for (tok = strtok(tmpbuf, " "); tok; tok = next_tok) {		next_tok = strtok(NULL, " ");		if (*tok != '(') /* Ignore the alises in the JSON output */			printf(" \"%s\"%s", tok, comma + (next_tok ? 0 : 1));	} 	printf("\n  ]");} /* A request of f == FNONE wants json on stdout. */void print_rsync_version(enum logcode f){	char copyright[] = "(C) 1996-" LATEST_YEAR " by Andrew Tridgell, Wayne Davison, and others.";	char url[] = "https://rsync.samba.org/";	BOOL first_line = 1; #define json_line(name, value) \	do { \		printf("%c\n  \"%s\": \"%s\"", first_line ? '{' : ',', name, value); \		first_line = 0; \	} while (0) 	if (f == FNONE) {		char verbuf[32];		json_line("program", RSYNC_NAME);		json_line("version", rsync_version());		(void)snprintf(verbuf, sizeof verbuf, "%d.%d", PROTOCOL_VERSION, SUBPROTOCOL_VERSION);		json_line("protocol", verbuf);		json_line("copyright", copyright);		json_line("url", url);	} else {#if SUBPROTOCOL_VERSION != 0		char *subprotocol = istring(".PR%d", SUBPROTOCOL_VERSION);#else		char *subprotocol = "";#endif		rprintf(f, "%s  version %s  protocol version %d%s\n",			RSYNC_NAME, rsync_version(), PROTOCOL_VERSION, subprotocol);		rprintf(f, "Copyright %s\n", copyright);		rprintf(f, "Web site: %s\n", url);	} 	print_info_flags(f); 	init_checksum_choices(); 	output_nno_list(f, "Checksum list", &valid_checksums);	output_nno_list(f, "Compress list", &valid_compressions);	output_nno_list(f, "Daemon auth list", &valid_auth_checksums); 	if (f == FNONE) {		json_line("license", "GPLv3");		json_line("caveat", "rsync comes with ABSOLUTELY NO WARRANTY");		printf("\n}\n");		fflush(stdout);		return;	} #ifdef MAINTAINER_MODE	rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());#endif #if SIZEOF_INT64 < 8	rprintf(f, "WARNING: no 64-bit integers on this platform!\n");#endif	if (sizeof (int64) != SIZEOF_INT64) {		rprintf(f,			"WARNING: size mismatch in SIZEOF_INT64 define (%d != %d)\n",			(int) SIZEOF_INT64, (int) sizeof (int64));	} 	rprintf(f,"\n");	rprintf(f,"rsync comes with ABSOLUTELY NO WARRANTY.  This is free software, and you\n");	rprintf(f,"are welcome to redistribute it under certain conditions.  See the GNU\n");	rprintf(f,"General Public Licence for details.\n");} void usage(enum logcode F){  print_rsync_version(F);   rprintf(F,"\n");  rprintf(F,"rsync is a file transfer program capable of efficient remote update\n");  rprintf(F,"via a fast differencing algorithm.\n");   rprintf(F,"\n");  rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... DEST\n");  rprintf(F,"  or   rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");  rprintf(F,"  or   rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");  rprintf(F,"  or   rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST\n");  rprintf(F,"  or   rsync [OPTION]... [USER@]HOST:SRC [DEST]\n");  rprintf(F,"  or   rsync [OPTION]... [USER@]HOST::SRC [DEST]\n");  rprintf(F,"  or   rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]\n");  rprintf(F,"The ':' usages connect via remote shell, while '::' & 'rsync://' usages connect\n");  rprintf(F,"to an rsync daemon, and require SRC or DEST to start with a module name.\n");  rprintf(F,"\n");  rprintf(F,"Options\n");#include "help-rsync.h"  rprintf(F,"\n");  rprintf(F,"Use \"rsync --daemon --help\" to see the daemon-mode command-line options.\n");  rprintf(F,"Please see the rsync(1) and rsyncd.conf(5) manpages for full documentation.\n");  rprintf(F,"See https://rsync.samba.org/ for updates, bug reports, and answers\n");} void daemon_usage(enum logcode F){  print_rsync_version(F);   rprintf(F,"\n");  rprintf(F,"Usage: rsync --daemon [OPTION]...\n");#include "help-rsyncd.h"  rprintf(F,"\n");  rprintf(F,"If you were not trying to invoke rsync as a daemon, avoid using any of the\n");  rprintf(F,"daemon-specific rsync options.  See also the rsyncd.conf(5) manpage.\n");} const char *rsync_version(void){	char *ver;#ifdef RSYNC_GITVER	ver = RSYNC_GITVER;#else	ver = RSYNC_VERSION;#endif	return *ver == 'v' ? ver+1 : ver;} const char *default_cvsignore(void){	return DEFAULT_CVSIGNORE;}