File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / batch.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Fri Feb 17 15:09:30 2012 UTC (12 years, 4 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    1: /*
    2:  * Support for the batch-file options.
    3:  *
    4:  * Copyright (C) 1999 Weiss
    5:  * Copyright (C) 2004 Chris Shoemaker
    6:  * Copyright (C) 2004-2009 Wayne Davison
    7:  *
    8:  * This program is free software; you can redistribute it and/or modify
    9:  * it under the terms of the GNU General Public License as published by
   10:  * the Free Software Foundation; either version 3 of the License, or
   11:  * (at your option) any later version.
   12:  *
   13:  * This program is distributed in the hope that it will be useful,
   14:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:  * GNU General Public License for more details.
   17:  *
   18:  * You should have received a copy of the GNU General Public License along
   19:  * with this program; if not, visit the http://fsf.org website.
   20:  */
   21: 
   22: #include "rsync.h"
   23: #include "zlib/zlib.h"
   24: #include <time.h>
   25: 
   26: extern int eol_nulls;
   27: extern int recurse;
   28: extern int xfer_dirs;
   29: extern int preserve_links;
   30: extern int preserve_hard_links;
   31: extern int preserve_devices;
   32: extern int preserve_uid;
   33: extern int preserve_gid;
   34: extern int preserve_acls;
   35: extern int preserve_xattrs;
   36: extern int always_checksum;
   37: extern int do_compression;
   38: extern int inplace;
   39: extern int append_mode;
   40: extern int protocol_version;
   41: extern char *batch_name;
   42: #ifdef ICONV_OPTION
   43: extern char *iconv_opt;
   44: #endif
   45: 
   46: extern struct filter_list_struct filter_list;
   47: 
   48: int batch_stream_flags;
   49: 
   50: static int tweaked_append;
   51: static int tweaked_append_verify;
   52: static int tweaked_iconv;
   53: 
   54: static int *flag_ptr[] = {
   55: 	&recurse,		/* 0 */
   56: 	&preserve_uid,		/* 1 */
   57: 	&preserve_gid,		/* 2 */
   58: 	&preserve_links,	/* 3 */
   59: 	&preserve_devices,	/* 4 */
   60: 	&preserve_hard_links,	/* 5 */
   61: 	&always_checksum,	/* 6 */
   62: 	&xfer_dirs,		/* 7 (protocol 29) */
   63: 	&do_compression,	/* 8 (protocol 29) */
   64: 	&tweaked_iconv,		/* 9  (protocol 30) */
   65: 	&preserve_acls,		/* 10 (protocol 30) */
   66: 	&preserve_xattrs,	/* 11 (protocol 30) */
   67: 	&inplace,		/* 12 (protocol 30) */
   68: 	&tweaked_append,	/* 13 (protocol 30) */
   69: 	&tweaked_append_verify,	/* 14 (protocol 30) */
   70: 	NULL
   71: };
   72: 
   73: static char *flag_name[] = {
   74: 	"--recurse (-r)",
   75: 	"--owner (-o)",
   76: 	"--group (-g)",
   77: 	"--links (-l)",
   78: 	"--devices (-D)",
   79: 	"--hard-links (-H)",
   80: 	"--checksum (-c)",
   81: 	"--dirs (-d)",
   82: 	"--compress (-z)",
   83: 	"--iconv",
   84: 	"--acls (-A)",
   85: 	"--xattrs (-X)",
   86: 	"--inplace",
   87: 	"--append",
   88: 	"--append-verify",
   89: 	NULL
   90: };
   91: 
   92: void write_stream_flags(int fd)
   93: {
   94: 	int i, flags;
   95: 
   96: 	tweaked_append = append_mode == 1;
   97: 	tweaked_append_verify = append_mode == 2;
   98: #ifdef ICONV_OPTION
   99: 	tweaked_iconv = iconv_opt != NULL;
  100: #endif
  101: 
  102: 	/* Start the batch file with a bitmap of data-stream-affecting
  103: 	 * flags. */
  104: 	for (i = 0, flags = 0; flag_ptr[i]; i++) {
  105: 		if (*flag_ptr[i])
  106: 			flags |= 1 << i;
  107: 	}
  108: 	write_int(fd, flags);
  109: }
  110: 
  111: void read_stream_flags(int fd)
  112: {
  113: 	batch_stream_flags = read_int(fd);
  114: }
  115: 
  116: void check_batch_flags(void)
  117: {
  118: 	int i;
  119: 
  120: 	if (protocol_version < 29)
  121: 		flag_ptr[7] = NULL;
  122: 	else if (protocol_version < 30)
  123: 		flag_ptr[9] = NULL;
  124: 	tweaked_append = append_mode == 1;
  125: 	tweaked_append_verify = append_mode == 2;
  126: #ifdef ICONV_OPTION
  127: 	tweaked_iconv = iconv_opt != NULL;
  128: #endif
  129: 	for (i = 0; flag_ptr[i]; i++) {
  130: 		int set = batch_stream_flags & (1 << i) ? 1 : 0;
  131: 		if (*flag_ptr[i] != set) {
  132: 			if (i == 9) {
  133: 				rprintf(FERROR,
  134: 					"%s specify the --iconv option to use this batch file.\n",
  135: 					set ? "Please" : "Do not");
  136: 				exit_cleanup(RERR_SYNTAX);
  137: 			}
  138: 			if (verbose) {
  139: 				rprintf(FINFO,
  140: 					"%sing the %s option to match the batchfile.\n",
  141: 					set ? "Sett" : "Clear", flag_name[i]);
  142: 			}
  143: 			*flag_ptr[i] = set;
  144: 		}
  145: 	}
  146: 	if (protocol_version < 29) {
  147: 		if (recurse)
  148: 			xfer_dirs |= 1;
  149: 		else if (xfer_dirs < 2)
  150: 			xfer_dirs = 0;
  151: 	}
  152: 
  153: 	if (tweaked_append)
  154: 		append_mode = 1;
  155: 	else if (tweaked_append_verify)
  156: 		append_mode = 2;
  157: }
  158: 
  159: static int write_arg(int fd, char *arg)
  160: {
  161: 	char *x, *s;
  162: 	int len, ret = 0;
  163: 
  164: 	if (*arg == '-' && (x = strchr(arg, '=')) != NULL) {
  165: 		if (write(fd, arg, x - arg + 1) != x - arg + 1)
  166: 			ret = -1;
  167: 		arg += x - arg + 1;
  168: 	}
  169: 
  170: 	if (strpbrk(arg, " \"'&;|[]()$#!*?^\\") != NULL) {
  171: 		if (write(fd, "'", 1) != 1)
  172: 			ret = -1;
  173: 		for (s = arg; (x = strchr(s, '\'')) != NULL; s = x + 1) {
  174: 			if (write(fd, s, x - s + 1) != x - s + 1
  175: 			 || write(fd, "'", 1) != 1)
  176: 				ret = -1;
  177: 		}
  178: 		len = strlen(s);
  179: 		if (write(fd, s, len) != len
  180: 		 || write(fd, "'", 1) != 1)
  181: 			ret = -1;
  182: 		return ret;
  183: 	}
  184: 
  185: 	len = strlen(arg);
  186: 	if (write(fd, arg, len) != len)
  187: 		ret = -1;
  188: 
  189: 	return ret;
  190: }
  191: 
  192: static void write_filter_rules(int fd)
  193: {
  194: 	struct filter_struct *ent;
  195: 
  196: 	write_sbuf(fd, " <<'#E#'\n");
  197: 	for (ent = filter_list.head; ent; ent = ent->next) {
  198: 		unsigned int plen;
  199: 		char *p = get_rule_prefix(ent->match_flags, "- ", 0, &plen);
  200: 		write_buf(fd, p, plen);
  201: 		write_sbuf(fd, ent->pattern);
  202: 		if (ent->match_flags & MATCHFLG_DIRECTORY)
  203: 			write_byte(fd, '/');
  204: 		write_byte(fd, eol_nulls ? 0 : '\n');
  205: 	}
  206: 	if (eol_nulls)
  207: 		write_sbuf(fd, ";\n");
  208: 	write_sbuf(fd, "#E#");
  209: }
  210: 
  211: /* This routine tries to write out an equivalent --read-batch command
  212:  * given the user's --write-batch args.  However, it doesn't really
  213:  * understand most of the options, so it uses some overly simple
  214:  * heuristics to munge the command line into something that will
  215:  * (hopefully) work. */
  216: void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
  217: {
  218: 	int fd, i, len, err = 0;
  219: 	char *p, filename[MAXPATHLEN];
  220: 
  221: 	stringjoin(filename, sizeof filename,
  222: 		   batch_name, ".sh", NULL);
  223: 	fd = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
  224: 		     S_IRUSR | S_IWUSR | S_IEXEC);
  225: 	if (fd < 0) {
  226: 		rsyserr(FERROR, errno, "Batch file %s open error",
  227: 			filename);
  228: 		exit_cleanup(RERR_FILESELECT);
  229: 	}
  230: 
  231: 	/* Write argvs info to BATCH.sh file */
  232: 	if (write_arg(fd, argv[0]) < 0)
  233: 		err = 1;
  234: 	if (filter_list.head) {
  235: 		if (protocol_version >= 29)
  236: 			write_sbuf(fd, " --filter=._-");
  237: 		else
  238: 			write_sbuf(fd, " --exclude-from=-");
  239: 	}
  240: 	for (i = 1; i < argc - file_arg_cnt; i++) {
  241: 		p = argv[i];
  242: 		if (strncmp(p, "--files-from", 12) == 0
  243: 		    || strncmp(p, "--filter", 8) == 0
  244: 		    || strncmp(p, "--include", 9) == 0
  245: 		    || strncmp(p, "--exclude", 9) == 0) {
  246: 			if (strchr(p, '=') == NULL)
  247: 				i++;
  248: 			continue;
  249: 		}
  250: 		if (strcmp(p, "-f") == 0) {
  251: 			i++;
  252: 			continue;
  253: 		}
  254: 		if (write(fd, " ", 1) != 1)
  255: 			err = 1;
  256: 		if (strncmp(p, "--write-batch", len = 13) == 0
  257: 		 || strncmp(p, "--only-write-batch", len = 18) == 0) {
  258: 			if (write(fd, "--read-batch", 12) != 12)
  259: 				err = 1;
  260: 			if (p[len] == '=') {
  261: 				if (write(fd, "=", 1) != 1
  262: 				 || write_arg(fd, p + len + 1) < 0)
  263: 					err = 1;
  264: 			}
  265: 		} else {
  266: 			if (write_arg(fd, p) < 0)
  267: 				err = 1;
  268: 		}
  269: 	}
  270: 	if (!(p = check_for_hostspec(argv[argc - 1], &p, &i)))
  271: 		p = argv[argc - 1];
  272: 	if (write(fd, " ${1:-", 6) != 6
  273: 	 || write_arg(fd, p) < 0)
  274: 		err = 1;
  275: 	write_byte(fd, '}');
  276: 	if (filter_list.head)
  277: 		write_filter_rules(fd);
  278: 	if (write(fd, "\n", 1) != 1 || close(fd) < 0 || err) {
  279: 		rsyserr(FERROR, errno, "Batch file %s write error",
  280: 			filename);
  281: 		exit_cleanup(RERR_FILEIO);
  282: 	}
  283: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>