⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 remsync.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		fprintf(difffp, " d%03o %u %u\n",			(unsigned) new->mode,			(unsigned) new->uid, (unsigned) new->gid);		if (vflag) fprintf(stderr, "mkdir %s\n", new->path);		break;	case F_FILE:		path_init(&file);		path_add(&file, tree);		path_add(&file, new->path);		if ((f= open(path_name(&file), O_RDONLY)) < 0) {			report(path_name(&file));			path_drop(&file);			fprintf(difffp, " ignore\n");			break;		}		fprintf(difffp, " %03o %u %u %lu %lu\n",			(unsigned) new->mode,			(unsigned) new->uid, (unsigned) new->gid,			(unsigned long) new->size,			(unsigned long) new->mtime);		checkdiff();		if (!cat(f, new->size)) {			int err= errno;			report(path_name(&file));			fprintf(difffp, "old ");			checkdiff();			print_name(difffp, err == EINVAL				? "File changed when copied" : strerror(err));			fputc('\n', difffp);			checkdiff();		} else {			if (vflag) {				fprintf(stderr, "%s %s\n",					old == nil ? "add" :						old->mtime > new->mtime ?							"restore" : "update",					new->path);			}		}		close(f);		path_drop(&file);		break;	case F_BLK:	case F_CHR:		fprintf(difffp, " %c%03o %u %u %lx\n",			new->type == F_BLK ? 'b' : 'c',			(unsigned) new->mode,			(unsigned) new->uid, (unsigned) new->gid,			(unsigned long) new->rdev);		if (vflag) fprintf(stderr, "mknod %s\n", new->path);		break;	case F_PIPE:		fprintf(difffp, " p%03o %u %u\n",			(unsigned) new->mode,			(unsigned) new->uid, (unsigned) new->gid);		if (vflag) fprintf(stderr, "mkfifo %s\n", new->path);		break;	case F_LINK:		fprintf(difffp, " -> ");		checkdiff();		(void) print_name(difffp, new->link);		checkdiff();		fputc('\n', difffp);		if (vflag) {			fprintf(stderr, "ln -s %s %s\n", new->link, new->path);		}		break;	}	checkdiff();}void mkdifferences(void){	entry_t *remote;	entry_t *local;	remote= readstate();	local= traverse();	while (remote != nil || local != nil) {		switch (compare(remote, local)) {		case DELETE:			/* Remove the remote file. */			delete(remote);			remote->ignore= 1;			remote= readstate();			break;		case REPLACE:			/* Replace the remote file with the local one. */			if (remote->type == F_FILE && local->type == F_FILE							&& !local->linked) {				/* Don't overwrite, remove first. */				delete(remote);			}			/*FALL THROUGH*/		case COPY:			/* Overwrite the remote file with the local one. */			add(remote, local);			remote->ignore= 1;			goto skip2;		case SIMILAR:			/* About the same, but the attributes need changing. */			change_modes(remote, local);			goto skip2;		case EQUAL:		skip2:			/* Skip two files. */			remote= readstate();			local= traverse();			break;		case ADD:			/* Add the local file. */			add(nil, local);			local= traverse();			break;		}	}	fprintf(difffp, "end\n");	fflush(difffp);	checkdiff();}void apply_remove(pathname_t *pp)/* Remove an obsolete file. */{	struct stat st;	if (lstat(path_name(pp), &st) < 0) {		if (errno != ENOENT) report(path_name(pp));		return;	}	if (S_ISDIR(st.st_mode)) {		/* Recursively delete directories. */		size_t len;		namelist_t *entries;		if ((entries= collect(path_name(pp))) == nil && errno != 0) {			report(path_name(pp));			return;		}		len= path_length(pp);		while (entries != nil) {			path_add(pp, pop_name(&entries));			apply_remove(pp);			path_trunc(pp, len);		}		if (rmdir(path_name(pp)) < 0) {			report(path_name(pp));			return;		}		if (vflag) fprintf(stderr, "rmdir %s\n", path_name(pp));	} else {		/* Some other type of file. */		if (unlink(path_name(pp)) < 0) {			report(path_name(pp));			return;		}		if (vflag) fprintf(stderr, "rm %s\n", path_name(pp));	}}void apply_mkold(const char *file, const char *err)/* Make a file very old.  (An error occurred when it was added.) */{	struct utimbuf utb;	utb.actime= utb.modtime= 0;	if (utime(file, &utb) < 0) {		report(file);		return;	}	fprintf(stderr, "made %s look old", file);	fprintf(stderr, err == nil ? "\n" : " due to a remote problem: %s\n",								err);}void apply_chmod(const char *file, mode_t mode, uid_t uid, gid_t gid, int talk)/* Change mode and ownership. */{	struct stat st;	if (lstat(file, &st) < 0) {		report(file);		return;	}	if ((st.st_mode & 07777) != mode) {		if (chmod(file, mode) < 0) {			report(file);			return;		}		if (vflag && talk) {			fprintf(stderr, "chmod %03o %s\n",						(unsigned) mode, file);		}	}	if (st.st_uid != uid || st.st_gid != gid) {		if (chown(file, uid, gid) < 0) {			if (errno != EPERM) report(file);			return;		}		if (vflag && talk) {			fprintf(stderr, "chown %u:%u %s\n",				(unsigned) uid, (unsigned) gid, file);		}	}}void apply_add(pathname_t *pp, entry_t *entry)/* Add or replace a file. */{	const char *file;	off_t size;	int f;	unsigned char buf[1024 << sizeof(int)];	unsigned char *p;	int c;	int dirty;	struct stat st;	struct utimbuf utb;	if (entry->ignore) return;	if (lstat(path_name(pp), &st) >= 0 && (entry->type != F_FILE					|| !S_ISREG(st.st_mode))) {		apply_remove(pp);	}	file= path_name(pp);	switch (entry->type) {	case F_DIR:		if (mkdir(file, entry->mode) < 0) {			report(file);			return;		}		if (vflag) fprintf(stderr, "mkdir %s\n", file);		break;	case F_FILE:		size= entry->size;		f= -1;		st.st_mode= 0;		if (lstat(file, &st) < 0 || S_ISREG(st.st_mode)) {			f= open(file, O_WRONLY | O_CREAT | O_TRUNC,						entry->mode);			if (f < 0) {				(void) chmod(file, entry->mode | 0200);				f= open(file, O_WRONLY | O_CREAT | O_TRUNC,						entry->mode);			}			if (f < 0) {				(void) unlink(file);				f= open(file, O_WRONLY | O_CREAT | O_TRUNC,						entry->mode);			}			if (f < 0) report(file);		}		dirty= (f >= 0);		p= buf;		while (size > 0 && (c= getc(difffp)) != EOF) {			size--;			*p++= c;			if (p == arraylimit(buf) || size == 0) {				if (f >= 0 && write(f, buf, p - buf) < 0) {					report(file);					close(f);					f= -1;				}				p= buf;			}		}		if (size > 0) {			if (ferror(difffp)) report(diff_file);			if (feof(difffp)) {				fprintf(stderr, "remspec: %s: premature EOF\n",					diff_file);			}			if (dirty) apply_mkold(file, nil);			exit(1);		}		if (f < 0) {			if (dirty) apply_mkold(file, nil);			return;		}		close(f);		if (vflag) {			fprintf(stderr, st.st_mode == 0 ? "add %s\n"				: entry->mtime >= st.st_mtime					? "update %s\n" : "restore %s\n", file);		}		utb.actime= time(nil);		utb.modtime= entry->mtime;		if (utime(file, &utb) < 0) report(file);		break;	case F_BLK:		if (mknod(file, S_IFBLK | entry->mode, entry->rdev) < 0) {			report(file);			return;		}		if (vflag) {			fprintf(stderr, "mknod %s b %d %d\n", file,				major(entry->rdev), minor(entry->rdev));		}		break;	case F_CHR:		if (mknod(file, S_IFCHR | entry->mode, entry->rdev) < 0) {			report(file);			return;		}		if (vflag) {			fprintf(stderr, "mknod %s c %d %d\n", file,				major(entry->rdev), minor(entry->rdev));		}		break;	case F_PIPE:		if (mknod(file, S_IFIFO | entry->mode, 0) < 0) {			report(file);			return;		}		if (vflag) fprintf(stderr, "mknod %s p\n", file);		break;	case F_LINK:		if (symlink(entry->link, file) < 0) {			report(file);			return;		}		if (vflag) fprintf(stderr, "ln -s %s %s\n", entry->link, file);		return;	}	apply_chmod(file, entry->mode, entry->uid, entry->gid, 0);}void apply_link(const char *file, pathname_t *pp)/* Hard link *pp to file. */{	struct stat st1, st2;	if (lstat(file, &st1) < 0) {		report(file);		return;	}	if (lstat(path_name(pp), &st2) >= 0) {		if (st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev)			return;		apply_remove(pp);		if (lstat(path_name(pp), &st2) >= 0) return;	}	if (link(file, path_name(pp)) < 0) {		fprintf(stderr, "remsync: ln %s %s: %s\n", file, path_name(pp),			strerror(errno));		excode= 1;		return;	}	if (vflag) fprintf(stderr, "ln %s %s\n", file, path_name(pp));}void diff_syntax(const char *line){	fprintf(stderr, "remsync: %s: syntax error on this line: %s\n",		diff_file, line);	exit(1);}void apply_differences(void)/* Update a tree to a list of differences derived from a remote tree. */{	char *line;	char **argv;	size_t argc;	pathname_t path, link;	size_t trunc;	path_init(&path);	path_init(&link);	path_add(&path, tree);	path_add(&link, tree);	trunc= path_length(&path);	while (!feof(difffp) && (line= read1line(difffp)) != nil) {		splitline(line, &argv, &argc);		if (argc == 0) diff_syntax(line);		path_trunc(&path, trunc);		if (strcmp(argv[0], "add") == 0) {			entry_t entry;			if (argc < 3) diff_syntax(line);			path_add(&path, argv[1]);			entry.ignore= (strcmp(argv[2], "ignore") == 0);			if (!entry.ignore && !getattributes(&entry,							argc - 2, argv + 2))				diff_syntax(line);			apply_add(&path, &entry);		} else		if (strcmp(argv[0], "rm") == 0) {			if (argc != 2) diff_syntax(line);			path_add(&path, argv[1]);			apply_remove(&path);		} else		if (strcmp(argv[0], "ln") == 0) {			if (argc != 3) diff_syntax(line);			path_trunc(&link, trunc);			path_add(&link, argv[1]);			path_add(&path, argv[2]);			apply_link(path_name(&link), &path);		} else		if (strcmp(argv[0], "chmod") == 0) {			if (argc != 5) diff_syntax(line);			path_add(&path, argv[1]);			apply_chmod(path_name(&path),				strtoul(argv[2], nil, 010),				strtoul(argv[3], nil, 10),				strtoul(argv[4], nil, 10),				1);		} else		if (strcmp(argv[0], "old") == 0) {			if (argc != 3) diff_syntax(line);			path_add(&path, argv[1]);			apply_mkold(path_name(&path), argv[2]);		} else		if (strcmp(argv[0], "end") == 0) {			if (argc != 1) diff_syntax(line);			break;		} else {			diff_syntax(line);		}	}	checkdiff();}void usage(void){    fprintf(stderr, "Usage: remsync -sxv tree [state-file]\n");    fprintf(stderr, "       remsync -duxvD tree [state-file [diff-file]]\n");    fprintf(stderr, "       remsync [-xv] tree [diff-file]\n");    exit(1);}int main(int argc, char **argv){	int i;	for (i= 1; i < argc && argv[i][0] == '-'; i++) {		char *p= argv[i] + 1;		if (p[0] == '-' && p[1] == 0) { i++; break; }		while (*p != 0) {			switch (*p++) {			case 's':	sflag= 1; break;			case 'd':	dflag= 1; break;			case 'u':	uflag= 1; break;			case 'x':	xflag= 1; break;			case 'D':	Dflag= 1; break;			case 'v':	vflag= 1; break;			default:	usage();			}		}	}	if (sflag && dflag) usage();	if (sflag && uflag) usage();	if (!sflag && !dflag && uflag) usage();	if (!dflag && Dflag) usage();	if (i == argc) usage();	tree= argv[i++];	if (sflag) {		/* Make a state file. */		state_file= i < argc ? argv[i++] : "-";		if (i != argc) usage();		statefp= stdout;		if (strcmp(state_file, "-") != 0) {			if ((statefp= fopen(state_file, "w")) == nil)				fatal(state_file);		}		mkstatefile();	} else	if (dflag) {		/* Make a file of differences. */		state_file= i < argc ? argv[i++] : "-";		diff_file= i < argc ? argv[i++] : "-";		if (i != argc) usage();		statefp= stdin;		if (strcmp(state_file, "-") != 0) {			if ((statefp= fopen(state_file, "r")) == nil)				fatal(state_file);		}		difffp= stdout;		if (strcmp(diff_file, "-") != 0) {			if ((difffp= fopen(diff_file, "w")) == nil)				fatal(diff_file);		}		mkdifferences();	} else {		/* Apply a file of differences. */		diff_file= i < argc ? argv[i++] : "-";		if (i != argc) usage();		difffp= stdin;		if (strcmp(diff_file, "-") != 0) {			if ((difffp= fopen(diff_file, "r")) == nil)				fatal(diff_file);		}		apply_differences();	}	exit(excode);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -