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

📄 remsync.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	const char *p;	int c;	for (p= name; (c= (unsigned char) *p) != 0; p++) {		if (c <= ' ' || c == '\\') {			fprintf(fp, "\\%03o", c);			if (ferror(fp)) return 0;		} else {			if (putc(c, fp) == EOF) return 0;		}	}	return 1;}void mkstatefile(void)/* Make a state file out of the directory tree. */{	entry_t *entry;	while ((entry= traverse()) != nil) {		indent(entry->depth);		if (!print_name(statefp, entry->name)) checkstate();		if (entry->ignore) {			fprintf(statefp, "\tignore (%s)\n",				strerror(entry->ignore));			checkstate();			continue;		}		switch (entry->type) {		case F_DIR:			fprintf(statefp, "\td%03o %u %u",				(unsigned) entry->mode,				(unsigned) entry->uid, (unsigned) entry->gid);			break;		case F_FILE:			fprintf(statefp, "\t%03o %u %u %lu %lu",				(unsigned) entry->mode,				(unsigned) entry->uid, (unsigned) entry->gid,				(unsigned long) entry->size,				(unsigned long) entry->mtime);			break;		case F_BLK:		case F_CHR:			fprintf(statefp, "\t%c%03o %u %u %x",				entry->type == F_BLK ? 'b' : 'c',				(unsigned) entry->mode,				(unsigned) entry->uid, (unsigned) entry->gid,				(unsigned) entry->rdev);			break;		case F_PIPE:			fprintf(statefp, "\tp%03o %u %u",				(unsigned) entry->mode,				(unsigned) entry->uid, (unsigned) entry->gid);			break;		case F_LINK:			fprintf(statefp, "\t-> ");			checkstate();			(void) print_name(statefp, entry->link);			break;		}		checkstate();		if (entry->fake_ino != 0)			fprintf(statefp, " %lu", entry->fake_ino);		if (entry->lastlink)			fprintf(statefp, " last");		if (fputc('\n', statefp) == EOF) checkstate();	}	fflush(statefp);	checkstate();}char *read1line(FILE *fp)/* Read one line from a file.  Return null on EOF or error. */{	static char *line;	static size_t len;	size_t idx;	int c;	if (len == 0) line= allocate(nil, (len= 16) * sizeof(line[0]));	idx= 0;	while ((c= getc(fp)) != EOF && c != '\n') {		if (c < '\t') {			/* Control characters are not possible. */			fprintf(stderr,				"remsync: control character in data file!\n");			exit(1);		}		line[idx++]= c;		if (idx == len) {			line= allocate(line, (len*= 2) * sizeof(line[0]));		}	}	if (c == EOF) {		if (ferror(fp)) return nil;		if (idx == 0) return nil;	}	line[idx]= 0;	return line;}void getword(char **pline, char **parg, size_t *plen)/* Get one word from a line, interpret octal escapes. */{	char *line= *pline;	char *arg= *parg;	size_t len= *plen;	int i;	int c;	size_t idx;	idx= 0;	while ((c= *line) != 0 && c != ' ' && c != '\t') {		line++;		if (c == '\\') {			c= 0;			for (i= 0; i < 3; i++) {				if ((unsigned) (*line - '0') >= 010) break;				c= (c << 3) | (*line - '0');				line++;			}		}		arg[idx++]= c;		if (idx == len) arg= allocate(arg, (len*= 2) * sizeof(arg[0]));	}	arg[idx]= 0;	*pline= line;	*parg= arg;	*plen= len;}void splitline(char *line, char ***pargv, size_t *pargc)/* Split a line into an array of words. */{	static char **argv;	static size_t *lenv;	static size_t len;	size_t idx;	idx= 0;	for (;;) {		while (*line == ' ' || *line == '\t') line++;		if (*line == 0) break;		if (idx == len) {			len++;			argv= allocate(argv, len * sizeof(argv[0]));			lenv= allocate(lenv, len * sizeof(lenv[0]));			argv[idx]= allocate(nil, 16 * sizeof(argv[idx][0]));			lenv[idx]= 16;		}		getword(&line, &argv[idx], &lenv[idx]);		idx++;	}	*pargv= argv;	*pargc= idx;}int getattributes(entry_t *entry, int argc, char **argv)/* Convert state or difference file info into file attributes. */{	int i;	int attr;#define A_MODE1		0x01	/* Some of these attributes follow the name */#define A_MODE		0x02#define	A_OWNER		0x04#define A_SIZETIME	0x08#define A_DEV		0x10#define A_LINK		0x20	switch (argv[0][0]) {	case 'd':		/* Directory. */		entry->type= F_DIR;		attr= A_MODE1 | A_OWNER;		break;	case 'b':		/* Block device. */		entry->type= F_BLK;		attr= A_MODE1 | A_OWNER | A_DEV;		break;	case 'c':		/* Character device. */		entry->type= F_CHR;		attr= A_MODE1 | A_OWNER | A_DEV;		break;	case 'p':		/* Named pipe. */		entry->type= F_PIPE;		attr= A_MODE1 | A_OWNER;		break;	case '-':		/* Symlink. */		entry->type= F_LINK;		attr= A_LINK;		break;	default:		/* Normal file. */		entry->type= F_FILE;		attr= A_MODE | A_OWNER | A_SIZETIME;	}	if (attr & (A_MODE | A_MODE1)) {		entry->mode= strtoul(argv[0] + (attr & A_MODE1), nil, 010);	}	i= 1;	if (attr & A_OWNER) {		if (i + 2 > argc) return 0;		entry->uid= strtoul(argv[i++], nil, 10);		entry->gid= strtoul(argv[i++], nil, 10);	}	if (attr & A_SIZETIME) {		if (i + 2 > argc) return 0;		entry->size= strtoul(argv[i++], nil, 10);		entry->mtime= strtoul(argv[i++], nil, 10);	}	if (attr & A_DEV) {		if (i + 1 > argc) return 0;		entry->rdev= strtoul(argv[i++], nil, 0x10);	}	if (attr & A_LINK) {		if (i + 1 > argc) return 0;		entry->link= argv[i++];	}	entry->linked= entry->lastlink= 0;	if (i < argc) {		/* It has a fake inode number, so it is a hard link. */		static struct links {	/* List of hard links. */			struct links	*next;			unsigned long	fake_ino;			char		*path;		} *links[1024];		struct links **plp, *lp;		unsigned long fake_ino;		fake_ino= strtoul(argv[i++], nil, 10);		plp= &links[fake_ino % arraysize(links)];		while ((lp= *plp) != nil && lp->fake_ino != fake_ino)			plp= &lp->next;		if (lp == nil) {			/* New link. */			*plp= lp= allocate(nil, sizeof(*lp));			lp->next= nil;			lp->fake_ino= fake_ino;			lp->path= copystr(entry->path);		} else {			/* Linked to. */			entry->link= lp->path;			entry->linked= 1;		}		if (i < argc) {			if (strcmp(argv[i++], "last") != 0) return 0;			/* Last hard link of a file. */			forget(lp->path);			*plp= lp->next;			deallocate(lp);			entry->lastlink= 1;		}	}	if (i != argc) return 0;	return 1;}void state_syntax(off_t line){	fprintf(stderr, "remsync: %s: syntax error on line %lu\n",		state_file, (unsigned long) line);	exit(1);}entry_t *readstate(void)/* Read one entry from the state file. */{	static entry_t entry;	static pathname_t path;	static size_t *trunc;	static size_t trunc_len;	static base_indent;	char *line;	char **argv;	size_t argc;	static off_t lineno;	int indent, depth;recurse:	keep= KEEP_STATE;	if (feof(statefp) || (line= read1line(statefp)) == nil) {		checkstate();		return nil;	}	lineno++;	/* How far is this entry indented? */	indent= 0;	while (*line != 0) {		if (*line == ' ') indent++;		else		if (*line == '\t') indent= (indent + 8) & ~7;		else			break;		line++;	}	if (indent > 0 && base_indent == 0) base_indent= indent;	depth= (base_indent == 0 ? 0 : indent / base_indent) + 1;	if (entry.ignore && depth > entry.depth) {		/* If the old directory is ignored, then so are its entries. */		goto recurse;	}	entry.depth= depth;	splitline(line, &argv, &argc);	if (argc < 2) state_syntax(lineno);	if (trunc == nil) {		/* The root of the tree, initialize path. */		if (argv[0][0] != '/') state_syntax(lineno);		path_init(&path);		path_add(&path, "/");		trunc= allocate(nil, (trunc_len= 16) * sizeof(trunc[0]));		/* The root has depth 0. */		entry.depth= 0;		trunc[0]= 0;	} else {		if (entry.depth > trunc_len) {			trunc= allocate(trunc,					(trunc_len*= 2) * sizeof(trunc[0]));		}		path_trunc(&path, trunc[entry.depth - 1]);		path_add(&path, argv[0]);		trunc[entry.depth]= path_length(&path);	}	entry.path= path_name(&path);	entry.name= argv[0];	entry.link= nil;	if ((entry.ignore= strcmp(argv[1], "ignore") == 0)) {		return &entry;	}	if (!getattributes(&entry, argc - 1, argv + 1)) state_syntax(lineno);	return &entry;}void checkdiff(void){	if (ferror(difffp)) fatal(diff_file);}enum { DELETE, REPLACE, COPY, SIMILAR, EQUAL, ADD }compare(entry_t *remote, entry_t *local)/* Compare the local and remote entries and tell what need to be done. */{	int cmp;	/* Surplus entries? */	if (local == nil) return DELETE;	if (remote == nil) return ADD;	/* Extra directory entries? */	if (remote->depth > local->depth) return DELETE;	if (local->depth > remote->depth) return ADD;	/* Compare names. */	cmp= strcmp(remote->name, local->name);	if (cmp < 0) return DELETE;	if (cmp > 0) return ADD;	/* The files have the same name.  Ignore one, ignore the other. */	if (remote->ignore || local->ignore) {		remote->ignore= local->ignore= 1;		return EQUAL;	}	/* Reasons for replacement? */	if (remote->type != local->type) return REPLACE;	/* Should be hard linked to the same file. */	if (remote->linked || local->linked) {		if (!remote->linked || !local->linked) return REPLACE;		if (strcmp(remote->link, local->link) != 0) return REPLACE;	}	switch (remote->type) {	case F_FILE:		if (uflag) {			if (remote->mtime < local->mtime) return COPY;		} else {			if (remote->size != local->size					|| remote->mtime != local->mtime)				return COPY;		}		goto check_modes;	case F_BLK:	case F_CHR:		if (remote->rdev != local->rdev) return REPLACE;		goto check_modes;	case F_DIR:	case F_PIPE:	check_modes:		if (remote->mode != local->mode			|| remote->uid != local->uid			|| remote->gid != local->gid) return SIMILAR;		break;	case F_LINK:		if (strcmp(remote->link, local->link) != 0) return REPLACE;		break;	}	return EQUAL;}void delete(entry_t *old)/* Emit an instruction to remove an entry. */{	if (old->ignore) return;	if (uflag) return;	fprintf(difffp, "rm ");	checkdiff();	if (!print_name(difffp, old->path)) checkdiff();	if (putc('\n', difffp) == EOF) checkdiff();	if (vflag) fprintf(stderr, "rm %s\n", old->path);}void change_modes(entry_t *old, entry_t *new)/* Emit an instruction to change the attributes of an entry. */{	if (new->ignore) return;	fprintf(difffp, "chmod ");	checkdiff();	if (!print_name(difffp, new->path)) checkdiff();	fprintf(difffp, " %03o %u %u\n",		(unsigned) new->mode,		(unsigned) new->uid, (unsigned) new->gid);	checkdiff();	if (vflag && old->mode != new->mode) {		fprintf(stderr, "chmod %s %03o %u %u\n",			new->path,			(unsigned) new->mode,			(unsigned) new->uid, (unsigned) new->gid);	}}int cat(int f, off_t size)/* Include the contents of a file in the differences file. */{	ssize_t n;	unsigned char buf[1024 << sizeof(int)];	unsigned char *p;	int c;	if (Dflag) return 1;	/* Debug: Don't need the file contents. */	while ((n= read(f, buf, sizeof(buf))) > 0) {		p= buf;		do {			if (size == 0) {				/* File suddenly larger. */				errno= EINVAL;				return 0;			}			c= *p++;			if (putc(c, difffp) == EOF) checkdiff();			size--;		} while (--n != 0);	}	if (size > 0) {		int err= errno;		/* File somehow shrunk, pad it out. */		do {			if (putc(0, difffp) == EOF) checkdiff();		} while (--size != 0);		errno= n == 0 ? EINVAL : err;		n= -1;	}	return n == 0;}void add(entry_t *old, entry_t *new)/* Emit an instruction to add an entry. */{	pathname_t file;	int f;	if (new->ignore) return;	if (new->linked) {		/* This file is to be a hard link to an existing file. */		fprintf(difffp, "ln ");		checkdiff();		if (!print_name(difffp, new->link)) checkdiff();		if (fputc(' ', difffp) == EOF) checkdiff();		if (!print_name(difffp, new->path)) checkdiff();		if (fputc('\n', difffp) == EOF) checkdiff();		if (vflag) {			fprintf(stderr, "ln %s %s\n", new->link, new->path);		}		return;	}	/* Add some other type of file. */	fprintf(difffp, "add ");	checkdiff();	if (!print_name(difffp, new->path)) checkdiff();	switch (new->type) {	case F_DIR:

⌨️ 快捷键说明

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