[BACK]Return to extern.h CVS log [TXT][DIR] Up to [local] / src / usr.bin / rsync

File: [local] / src / usr.bin / rsync / extern.h (download)

Revision 1.40, Sun Aug 29 13:43:46 2021 UTC (2 years, 9 months ago) by claudio
Branch: MAIN
Changes since 1.39: +25 -1 lines

Implement --exclude/exclude-file and --include/include-file.
Currently only simple include and excludes work, the advanced filters
introduced later in rsync are not implemented. It is unclear if the per
directory filters are something we want to implement. This requires
more modern protocols which openrsync is not able to handle right now.

This adds a special matching function to allow the ** matching which behaves
mostly like rsyncs version with the exception of how bad [] patterns are
expanded. For bad patterns openrsync follows more how fnmatch behaves and
not the somewhat strange rsync behaviour.

Not perfect but committing now so people can test and provide feedback.

/*	$OpenBSD: extern.h,v 1.40 2021/08/29 13:43:46 claudio Exp $ */
/*
 * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#ifndef EXTERN_H
#define EXTERN_H

/*
 * This is the rsync protocol version that we support.
 */
#define	RSYNC_PROTOCOL	(27)

/*
 * Maximum amount of file data sent over the wire at once.
 */
#define MAX_CHUNK	(32 * 1024)

/*
 * This is the minimum size for a block of data not including those in
 * the remainder block.
 */
#define	BLOCK_SIZE_MIN  (700)

/*
 * The sender and receiver use a two-phase synchronisation process.
 * The first uses two-byte hashes; the second, 16-byte.
 * (The second must hold a full MD4 digest.)
 */
#define	CSUM_LENGTH_PHASE1 (2)
#define	CSUM_LENGTH_PHASE2 (16)

/*
 * Rsync error codes.
 */
#define ERR_SYNTAX	1
#define ERR_PROTOCOL	2
#define ERR_SOCK_IO	10
#define ERR_FILE_IO	11
#define ERR_WIREPROTO	12
#define ERR_IPC		14	/* catchall for any kind of syscall error */
#define ERR_TERMIMATED	16
#define ERR_WAITPID	21
#define ERR_NOMEM	22

/*
 * Use this for --timeout.
 * All poll events will use it and catch time-outs.
 */
extern int poll_timeout;

/*
 * Operating mode for a client or a server.
 * Sender means we synchronise local files with those from remote.
 * Receiver is the opposite.
 * This is relative to which host we're running on.
 */
enum	fmode {
	FARGS_SENDER,
	FARGS_RECEIVER
};

/*
 * File arguments given on the command line.
 * See struct opts.
 */
struct	fargs {
	char	  *host; /* hostname or NULL if local */
	char	 **sources; /* transfer source */
	size_t	   sourcesz; /* number of sources */
	char	  *sink; /* transfer endpoint */
	enum fmode mode; /* mode of operation */
	int	   remote; /* uses rsync:// or :: for remote */
	char	  *module; /* if rsync://, the module */
};

/*
 * The subset of stat(2) information that we need.
 * (There are some parts we don't use yet.)
 */
struct	flstat {
	mode_t		 mode;	/* mode */
	uid_t		 uid;	/* user */
	gid_t		 gid;	/* group */
	dev_t		 rdev;	/* device type */
	off_t		 size;	/* size */
	time_t		 mtime;	/* modification */
	unsigned int	 flags;
#define	FLSTAT_TOP_DIR	 0x01	/* a top-level directory */

};

/*
 * A list of files with their statistics.
 */
struct	flist {
	char		*path; /* path relative to root */
	const char	*wpath; /* "working" path for receiver */
	struct flstat	 st; /* file information */
	char		*link; /* symlink target or NULL */
};

/*
 * Options passed into the command line.
 * See struct fargs.
 */
struct	opts {
	int		 sender;		/* --sender */
	int		 server;		/* --server */
	int		 recursive;		/* -r */
	int		 dry_run;		/* -n */
	int		 preserve_times;	/* -t */
	int		 preserve_perms;	/* -p */
	int		 preserve_links;	/* -l */
	int		 preserve_gids;		/* -g */
	int		 preserve_uids;		/* -u */
	int		 del;			/* --delete */
	int		 devices;		/* --devices */
	int		 specials;		/* --specials */
	int		 no_motd;		/* --no-motd */
	int		 numeric_ids;		/* --numeric-ids */
	int		 one_file_system;	/* -x */
	int		 from0;			/* -0 */
	char		*rsync_path;		/* --rsync-path */
	char		*ssh_prog;		/* --rsh or -e */
	char		*port;			/* --port */
	char		*address;		/* --address */
};

enum rule_type {
	RULE_NONE,
	RULE_EXCLUDE,
	RULE_INCLUDE,
	RULE_CLEAR,
#ifdef NOTYET
	RULE_MERGE,
	RULE_DIR_MERGE,
	RULE_SHOW,
	RULE_HIDE,
	RULE_PROTECT,
	RULE_RISK,
#endif
};

/*
 * An individual block description for a file.
 * See struct blkset.
 */
struct	blk {
	off_t		 offs; /* offset in file */
	size_t		 idx; /* block index */
	size_t		 len; /* bytes in block */
	uint32_t	 chksum_short; /* fast checksum */
	unsigned char	 chksum_long[CSUM_LENGTH_PHASE2]; /* slow checksum */
};

enum	blkstatst {
	BLKSTAT_NONE = 0,
	BLKSTAT_NEXT,
	BLKSTAT_DATA,
	BLKSTAT_TOK,
	BLKSTAT_HASH,
	BLKSTAT_DONE,
	BLKSTAT_PHASE,
};

/*
 * Information for the sender updating receiver blocks reentrantly.
 */
struct	blkstat {
	off_t		 offs; /* position in sender file */
	off_t		 total; /* total amount processed */
	off_t		 dirty; /* total amount sent */
	size_t		 hint; /* optimisation: next probable match */
	void		*map; /* mapped file or MAP_FAILED otherwise */
	size_t		 mapsz; /* size of file or zero */
	int		 fd; /* descriptor girding the map */
	enum blkstatst	 curst; /* FSM for sending file blocks */
	off_t		 curpos; /* sending: position in file to send */
	off_t		 curlen; /* sending: length of send */
	int32_t		 curtok; /* sending: next matching token or zero */
	struct blktab	*blktab; /* hashtable of blocks */
	uint32_t	 s1; /* partial sum for computing fast hash */
	uint32_t	 s2; /* partial sum for computing fast hash */
};

/*
 * When transferring file contents, we break the file down into blocks
 * and work with those.
 */
struct	blkset {
	off_t		 size; /* file size */
	size_t		 rem; /* terminal block length if non-zero */
	size_t		 len; /* block length */
	size_t		 csum; /* checksum length */
	struct blk	*blks; /* all blocks */
	size_t		 blksz; /* number of blks */
};

/*
 * Values required during a communication session.
 */
struct	sess {
	const struct opts *opts; /* system options */
	int32_t		   seed; /* checksum seed */
	int32_t		   lver; /* local version */
	int32_t		   rver; /* remote version */
	uint64_t	   total_read; /* non-logging wire/reads */
	uint64_t	   total_size; /* total file size */
	uint64_t	   total_write; /* non-logging wire/writes */
	int		   mplex_reads; /* multiplexing reads? */
	size_t		   mplex_read_remain; /* remaining bytes */
	int		   mplex_writes; /* multiplexing writes? */
};

/*
 * Combination of name and numeric id for groups and users.
 */
struct	ident {
	int32_t	 id; /* the gid_t or uid_t */
	int32_t	 mapped; /* if receiving, the mapped gid */
	char	*name; /* resolved name */
};

typedef struct arglist arglist;
struct arglist {
	char	**list;
	u_int	num;
	u_int	nalloc;
};
void	addargs(arglist *, const char *, ...)
	    __attribute__((format(printf, 2, 3)));
void	freeargs(arglist *);

struct	download;
struct	upload;

extern int verbose;

#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))

#define LOG0(_fmt, ...) \
	rsync_log( -1, (_fmt), ##__VA_ARGS__)
#define LOG1(_fmt, ...) \
	rsync_log( 0, (_fmt), ##__VA_ARGS__)
#define LOG2(_fmt, ...) \
	rsync_log( 1, (_fmt), ##__VA_ARGS__)
#define LOG3(_fmt, ...) \
	rsync_log( 2, (_fmt), ##__VA_ARGS__)
#define LOG4(_fmt, ...) \
	rsync_log( 3, (_fmt), ##__VA_ARGS__)
#define ERRX1(_fmt, ...) \
	rsync_errx1( (_fmt), ##__VA_ARGS__)
#define WARNX(_fmt, ...) \
	rsync_warnx( (_fmt), ##__VA_ARGS__)
#define WARN(_fmt, ...) \
	rsync_warn(0,  (_fmt), ##__VA_ARGS__)
#define WARN1(_fmt, ...) \
	rsync_warn(1,  (_fmt), ##__VA_ARGS__)
#define WARN2(_fmt, ...) \
	rsync_warn(2,  (_fmt), ##__VA_ARGS__)
#define ERR(_fmt, ...) \
	rsync_err( (_fmt), ##__VA_ARGS__)
#define ERRX(_fmt, ...) \
	rsync_errx( (_fmt), ##__VA_ARGS__)

void	rsync_log(int, const char *, ...)
			__attribute__((format(printf, 2, 3)));
void	rsync_warnx1(const char *, ...)
			__attribute__((format(printf, 1, 2)));
void	rsync_warn(int, const char *, ...)
			__attribute__((format(printf, 2, 3)));
void	rsync_warnx(const char *, ...)
			__attribute__((format(printf, 1, 2)));
void	rsync_err(const char *, ...)
			__attribute__((format(printf, 1, 2)));
void	rsync_errx(const char *, ...)
			__attribute__((format(printf, 1, 2)));
void	rsync_errx1(const char *, ...)
			__attribute__((format(printf, 1, 2)));

int	flist_del(struct sess *, int, const struct flist *, size_t);
int	flist_gen(struct sess *, size_t, char **, struct flist **, size_t *);
int	flist_gen_local(struct sess *, const char *, struct flist **, size_t *);
void	flist_free(struct flist *, size_t);
int	flist_recv(struct sess *, int, struct flist **, size_t *);
int	flist_send(struct sess *, int, int, const struct flist *, size_t);
int	flist_gen_dels(struct sess *, const char *, struct flist **, size_t *,
	    const struct flist *, size_t);

char	**fargs_cmdline(struct sess *, const struct fargs *, size_t *);

int	io_read_buf(struct sess *, int, void *, size_t);
int	io_read_byte(struct sess *, int, uint8_t *);
int	io_read_check(int);
int	io_read_flush(struct sess *, int);
int	io_read_int(struct sess *, int, int32_t *);
int	io_read_uint(struct sess *, int, uint32_t *);
int	io_read_long(struct sess *, int, int64_t *);
int	io_read_size(struct sess *, int, size_t *);
int	io_read_ulong(struct sess *, int, uint64_t *);
int	io_write_buf(struct sess *, int, const void *, size_t);
int	io_write_byte(struct sess *, int, uint8_t);
int	io_write_int(struct sess *, int, int32_t);
int	io_write_uint(struct sess *, int, uint32_t);
int	io_write_line(struct sess *, int, const char *);
int	io_write_long(struct sess *, int, int64_t);
int	io_write_ulong(struct sess *, int, uint64_t);

int	io_lowbuffer_alloc(struct sess *, void **, size_t *, size_t *, size_t);
void	io_lowbuffer_int(struct sess *, void *, size_t *, size_t, int32_t);
void	io_lowbuffer_buf(struct sess *, void *, size_t *, size_t, const void *,
	    size_t);

void	io_buffer_int(void *, size_t *, size_t, int32_t);
void	io_buffer_buf(void *, size_t *, size_t, const void *, size_t);

void	io_unbuffer_int(const void *, size_t *, size_t, int32_t *);
int	io_unbuffer_size(const void *, size_t *, size_t, size_t *);
void	io_unbuffer_buf(const void *, size_t *, size_t, void *, size_t);

int	rsync_receiver(struct sess *, int, int, const char *);
int	rsync_sender(struct sess *, int, int, size_t, char **);
int	rsync_client(const struct opts *, int, const struct fargs *);
int	rsync_connect(const struct opts *, int *, const struct fargs *);
int	rsync_socket(const struct opts *, int, const struct fargs *);
int	rsync_server(const struct opts *, size_t, char *[]);
int	rsync_downloader(struct download *, struct sess *, int *);
int	rsync_set_metadata(struct sess *, int, int, const struct flist *,
	    const char *);
int	rsync_set_metadata_at(struct sess *, int, int, const struct flist *,
	    const char *);
int	rsync_uploader(struct upload *, int *, struct sess *, int *);
int	rsync_uploader_tail(struct upload *, struct sess *);

struct download	*download_alloc(struct sess *, int, const struct flist *,
		    size_t, int);
void		 download_free(struct download *);
struct upload	*upload_alloc(const char *, int, int, size_t,
		    const struct flist *, size_t, mode_t);
void		upload_free(struct upload *);

struct blktab	*blkhash_alloc(void);
int		 blkhash_set(struct blktab *, const struct blkset *);
void		 blkhash_free(struct blktab *);

struct blkset	*blk_recv(struct sess *, int, const char *);
void		 blk_recv_ack(char [20], const struct blkset *, int32_t);
void		 blk_match(struct sess *, const struct blkset *,
		    const char *, struct blkstat *);
int		 blk_send(struct sess *, int, size_t, const struct blkset *,
		    const char *);
int		 blk_send_ack(struct sess *, int, struct blkset *);

uint32_t	 hash_fast(const void *, size_t);
void		 hash_slow(const void *, size_t, unsigned char *,
		    const struct sess *);
void		 hash_file(const void *, size_t, unsigned char *,
		    const struct sess *);

int		 mkpath(char *);

int		 mkstempat(int, char *);
char		*mkstemplinkat(char*, int, char *);
char		*mkstempfifoat(int, char *);
char		*mkstempnodat(int, char *, mode_t, dev_t);
char		*mkstempsock(const char *, char *);
int		 mktemplate(char **, const char *, int);

int		 parse_rule(char *line, enum rule_type);
void		 parse_file(const char *, enum rule_type, int);
void		 send_rules(struct sess *, int);
void		 recv_rules(struct sess *, int);
int		 rules_match(const char *, int);

int		 rmatch(const char *, const char *, int);

char		*symlink_read(const char *);
char		*symlinkat_read(int, const char *);

int		 sess_stats_send(struct sess *, int);
int		 sess_stats_recv(struct sess *, int);

int		 idents_add(int, struct ident **, size_t *, int32_t);
void		 idents_assign_gid(struct sess *, struct flist *, size_t,
		    const struct ident *, size_t);
void		 idents_assign_uid(struct sess *, struct flist *, size_t,
		    const struct ident *, size_t);
void		 idents_free(struct ident *, size_t);
int		 idents_recv(struct sess *, int, struct ident **, size_t *);
void		 idents_remap(struct sess *, int, struct ident *, size_t);
int		 idents_send(struct sess *, int, const struct ident *, size_t);

#endif /*!EXTERN_H*/