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

📄 synctree.c

📁 minix软件源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
				arg0, Spath);			because();			return;		}		printf("Special file %s created\n", Spath);		break;#ifdef S_IFLNK	case S_IFLNK:		if (interact && !update) {			printf("Install %s -> %s", Spath, Slnkpth);			if (!ask('n')) { order(CANCEL); return; }		}		if (symlink(Slnkpth, Spath) < 0) {			fprintf(stderr, "%s: Can't create symlink %s",				arg0, Spath);			because();			return;		}		printf("%s %s -> %s\n",			forced_update ? "Updated:  " : "Installed:",			Spath, Slnkpth);		break;#endif	case S_IFREG:		if (interact && !update) {			printf("Install %s", Spath);			if (!ask('n')) { order(CANCEL); return; }		}		order(CAT);		if (answer() != DATA) return;		busy= 1;		if ((f= creat(Spath, backup ? 0644 : Sst.st_mode&07777)) < 0) {			busy= 0;			fprintf(stderr, "%s: Can't create %s", arg0, Spath);			because();		}		while ((n= receive(buf, sizeof(buf)))>0) {			if (f >= 0 && write(f, buf, n) != n) {				fprintf(stderr, "%s: Write error on %s",					arg0, Spath);				because();				close(f); f= -1;			}		}		if (n < 0) {			fprintf(stderr, "%s: Slave read err on %s\n",				arg0, Spath);		}		if (f >= 0) close(f);		if (n < 0 || f < 0) { makeold(); busy= 0; return; }		busy= 0;		printf("%s %s\n",			forced_update ?				Sst.st_mtime < st.st_mtime ? "Restored: " :					"Updated:  " :				"Installed:",			Spath		);		break;	default:		fprintf(stderr,			"%s: Won't add file with strange mode %05o: %s\n",			arg0, Sst.st_mode, Spath);		order(CANCEL);		return;	}	setmodes(1);}static int delete(update) int update;/* Delete path. */{	int forced_update= force && update;	if (S_ISDIR(st.st_mode)) {		if (install) return 0;		if (!force) {			printf("Delete dir %s", path);			if (!ask('n')) return 0;		}		if (!removedir(path)) { ex= 1; return 0; }		if (!forced_update) printf("Directory %s deleted.\n", path);		return 1;	}	if (install && !update) return 0;	if (!force) {		printf("Delete %s", path);		if (!ask((interact && !update) ? 'n' : 'y')) return 0;	}	if (unlink(path)<0) {		fprintf(stderr, "Can't delete %s", path);		because();		return 0;	}	cancellink();	if (!forced_update) printf("Deleted:   %s\n", path);	return 1;}static int different()/* Return true iff path and Spath are different. */{	if (! ( (linkpath == nil && Slinkpath == nil)		|| (linkpath != nil && Slinkpath != nil			&& strcmp(linkpath, Slinkpath) == 0)	)) {		linkpath= Slinkpath;		return 1;	}	if ((st.st_mode & S_IFMT) != (Sst.st_mode & S_IFMT)) return 1;	switch (st.st_mode & S_IFMT) {	case S_IFDIR:		return 0;	case S_IFBLK:	case S_IFCHR:		return st.st_rdev != Sst.st_rdev;	case S_IFREG:		if (install) return Sst.st_mtime > st.st_mtime;		return st.st_size != Sst.st_size			|| st.st_mtime != Sst.st_mtime;	case S_IFIFO:	return 0;#ifdef S_IFLNK	case S_IFLNK:	return strcmp(lnkpth, Slnkpth) != 0;#endif	default:	return 1;	}}static void compare()/* See if path and Spath are same. */{	if (different()) {		if (!force) {			printf("%sing %s (delete + add)\n",				Sst.st_mtime < st.st_mtime ? "Restor" : "Updat",				path);		}		if (delete(1)) add(1);	} else {		if (!install) setmodes(0);		if (S_ISDIR(st.st_mode)) {			order(ENTER);			enter();		}	}}static int done= 0, Sdone= 0;static enum action { ADD, COMPARE, DELETE } action()/* Look at path's of master and slave, compare them alphabetically to see * who is ahead of who, then tell what is to be done. */{	int c;	char *Sp, *p;	if (done) return ADD;		/* Slave still has names. */	if (Sdone) return DELETE;	/* Master has too many names. */	/* Compare paths.  Let "a/a" come before "a.a". */	Sp= Spath;	p= path;	while (*Sp == *p && *Sp != 0) { Sp++; p++; }	if (*Sp == '/') return ADD;	if (*p == '/') return DELETE;	return (c= strcmp(Sp, p)) == 0 ? COMPARE : c < 0 ? ADD : DELETE;}static void master()/* Synchronise file tree to that of its slave. */{	enum action a= COMPARE;	/* Trick first advances. */	umask(backup ? 0022 : 0000);	signal(SIGPIPE, SIG_IGN);	signal(SIGHUP, bail_out);	signal(SIGINT, bail_out);	signal(SIGTERM, bail_out);	while (!done || !Sdone) {		if (!Sdone && (a == ADD || a == COMPARE)) {			/* Slave advances. */			order(ADVANCE);			switch (answer()) {			case PATH:				Slinkpath= nil;				receive(Spath, sizeof(Spath));				recstat(&Sst);				break;			case LINK:				receive(Slnkpth, sizeof(Slnkpth));				Slinkpath= Slnkpth;				receive(Spath, sizeof(Spath));				recstat(&Sst);				break;			case SYMLINK:				Slinkpath= nil;				receive(Slnkpth, sizeof(Slnkpth));				receive(Spath, sizeof(Spath));				recstat(&Sst);				break;			case DONE:				Sdone= 1;				break;			default:				fprintf(stderr,					"%s: Strange answer from slave.\n",					arg0);				exit(1);			}		}		if (!done && (a == COMPARE || a == DELETE)) {			/* Master advances. */			if (!advance()) done= 1;		}		if (done && Sdone) break;		switch (a= action()) {		case ADD:	/* Spath exists, path doesn't, add? */			add(0);			break;		case COMPARE:	/* They both exist, are they the same? */			compare();			break;		case DELETE:	/* path exists, Spath doesn't, delete? */			delete(0);		}		fflush(stdout);	/* Don't keep user in suspense. */	}	order(ex == 0 ? DIE : DIE_BAD);}static void mediator()/* Sits at the local machine and passes orders from master to slave, both * on remote machines.  Only diagnostics and questions are handled. */{	enum orders req;	for (;;) {		switch (req= request()) {		case DIE_BAD:			ex= 1;			/*FALL THROUGH*/		case DIE:			order(DIE);			return;		case POSITIVE:			order(ask('y') ? PASS_YES : PASS_NO);			break;		case NEGATIVE:			order(ask('n') ? PASS_YES : PASS_NO);			break;		default:			order(req);		}	}}#define P_EXIT		1	/* Make sure process doesn't return. */#define P_SHADOW	2	/* Always use exec on 68000. */static void startprocess(proc, machine, path, p_flags)	void (*proc)(); char *machine, *path; int p_flags;{	char *argv[10], **argp= argv;	char flags[10], *pfl= flags;	if (machine != nil) {		char *u= machine, *m;		*argp++ = "rsh";		if ((m= strchr(machine, '@')) != nil) {			*m++ = 0;			*argp++ = "-l";			*argp++ = u;			machine= m;		}		*argp++ = machine;	} else	/* Without this check it would run like a pig on an non MMU 68000: */	if (!(USE_SHADOWING && p_flags & P_SHADOW)) {		if (chdir(path) < 0) {			if (proc != master || errno != ENOENT						|| mkdir(path, 0700) < 0)				perrx(path);			if (chdir(path) < 0) perrx(path);			printf("Destination directory %s created\n", path);		}		isvisible(path);		isbackup(proc == slave);		(*proc)();		if (p_flags & P_EXIT) exit(ex);		return;	}	*argp++ = SYNCNAME;	*pfl++ = '-';	if (interact) *pfl++ = 'i';	if (install) *pfl++ = 'u';	if (force) *pfl++ = 'f';	*pfl= 0;	*argp++ = flags;	*argp++ = proc == slave ? SLAVENAME : MASTERNAME;	*argp++ = path;	*argp++ = nil;#ifdef DEBUG	fprintf(stderr, "execlp(");	for (argp= argv; *argp != nil; argp++) fprintf(stderr, "%s, ", *argp);	fprintf(stderr, "nil);\n");#endif	execvp(argv[0], argv);	perrx(argv[0]);}void splitcolon(path, amach, adir) char *path, **amach, **adir;{	char *dir= path;	for (;;) {		if (*dir == ':') {			*dir++ = 0;			*amach= path;			*adir= dir;			break;		}		if (*dir == 0 || *dir == '/') {			*amach= nil;			*adir= path;			break;		}		dir++;	}}static void Usage(){	fprintf(stderr,	    "Usage: %s [-iuf] [[user@]machine:]dir1 [[user@]machine:]dir2\n",		arg0);	exit(1);}main(argc, argv) int argc; char **argv;{	char *s_mach, *s_dir;	char *m_mach, *m_dir;	int m2s[2], s2m[2], m2m[2];	int s_pid= 0, m_pid= 0;	int r;	if ((arg0= strrchr(argv[0], '/')) == nil) arg0= argv[0]; else arg0++;	while (argc>1 && argv[1][0] == '-') {		char *f= argv[1]+1;		while (*f != 0) {			switch (*f++) {			case 'i':	interact= 1; break;			case 'u':	install= 1; break;			case 'f':	force= 1; break;			default:	Usage();			}		}		argc--;		argv++;	}	if (argc != 3) Usage();	if (strcmp(argv[1], SLAVENAME) == 0) {		arg0= "Slave";		splitcolon(argv[2], &s_mach, &s_dir);		startprocess(slave, s_mach, s_dir, P_EXIT);	} else	if (strcmp(argv[1], MASTERNAME) == 0) {		arg0= "Master";		splitcolon(argv[2], &m_mach, &m_dir);		startprocess(master, m_mach, m_dir, P_EXIT);	}	splitcolon(argv[1], &s_mach, &s_dir);	splitcolon(argv[2], &m_mach, &m_dir);	/* How difficult can plumbing be? */	if (pipe(m2s) < 0 || pipe(s2m) < 0) perrx("pipe()");	if (m_mach == nil) {		/* synctree [machine:]dir1 dir2 */		switch (s_pid= fork()) {		case -1:			perrx("fork()");		case 0:			dup2(m2s[0], 0); close(m2s[0]); close(m2s[1]);			dup2(s2m[1], 1); close(s2m[0]); close(s2m[1]);			arg0= "Slave";			startprocess(slave, s_mach, s_dir, P_EXIT|P_SHADOW);		}		chan[0]= s2m[0]; close(s2m[1]);		chan[1]= m2s[1]; close(m2s[0]);		startprocess(master, m_mach, m_dir, 0);	} else	if (s_mach == nil) {		/* synctree dir1 machine:dir2 */		switch (m_pid= fork()) {		case -1:			perrx("fork()");		case 0:			dup2(s2m[0], 0); close(s2m[0]); close(s2m[1]);			dup2(m2s[1], 1); close(m2s[0]); close(m2s[1]);			arg0= "Master";			startprocess(master, m_mach, m_dir, P_EXIT|P_SHADOW);		}		chan[0]= m2s[0]; close(m2s[1]);		chan[1]= s2m[1]; close(s2m[0]);		startprocess(slave, s_mach, s_dir, 0);	} else {		/* synctree machine1:dir1 machine2:dir2 */		if (pipe(m2m) < 0) perrx(pipe);		switch (s_pid= fork()) {		case -1:			perrx("fork()");		case 0:			dup2(m2s[0], 0); close(m2s[0]); close(m2s[1]);			dup2(s2m[1], 1); close(s2m[0]); close(s2m[1]);			close(m2m[0]); close(m2m[1]);			arg0= "Slave";			startprocess(slave, s_mach, s_dir, P_EXIT|P_SHADOW);		}		switch (m_pid= fork()) {		case -1:			perrx("fork()");		case 0:			dup2(s2m[0], 0); close(s2m[0]); close(s2m[1]);			close(m2s[0]); close(m2s[1]);			dup2(m2m[1], 1); close(m2m[0]); close(m2m[1]);			arg0= "Master";			startprocess(master, m_mach, m_dir, P_EXIT|P_SHADOW);		}		close(s2m[0]); close(s2m[1]);		chan[0]= m2m[0]; close(m2m[1]);		chan[1]= m2s[1]; close(m2s[0]);		mediator();	}	close(chan[0]);	close(chan[1]);	alarm(15); /* Don't wait(2) forever. */	while (s_pid != 0 || m_pid != 0) {		if ((r= wait((int *) nil)) < 0) perrx("wait()");		if (r == s_pid) s_pid= 0;		if (r == m_pid) m_pid= 0;	}	exit(ex);}

⌨️ 快捷键说明

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