henesyinit from p9fce6d0435 years agoHistory
771 lines · 12.7 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <auth.h>#include <bio.h> enum{	LEN	= 8*1024,	HUNKS	= 128, 	/*	 * types of destination file sytems	 */	Kfs = 0,	Fs,	Archive,}; typedef struct File	File; struct File{	char	*new;	char	*elem;	char	*old;	char	uid[NAMELEN];	char	gid[NAMELEN];	ulong	mode;}; void	arch(Dir*);void	copy(Dir*);int	copyfile(File*, Dir*, int);void*	emalloc(ulong);void	error(char *, ...);void	freefile(File*);File*	getfile(File*);char*	getmode(char*, ulong*);char*	getname(char*, char*, int);char*	getpath(char*);void	kfscmd(char *);void	mkdir(Dir*);int	mkfile(File*);void	mkfs(File*, int);char*	mkpath(char*, char*);void	mktree(File*, int);void	mountkfs(char*);void	printfile(File*);void	setnames(File*);void	setusers(void);void	skipdir(void);char*	strdup(char*);int	uptodate(Dir*, char*);void	usage(void);void	warn(char *, ...); Biobuf	*b;Biobufhdr bout;			/* stdout when writing archive */uchar	boutbuf[2*LEN];char	newfile[LEN];char	oldfile[LEN];char	*proto;char	*cputype;char	*users;char	*oldroot;char	*newroot;char	*prog = "mkfs";int	lineno;char	*buf;char	*zbuf;int	buflen = 1024-8;int	indent;int	verb;int	modes;int	ream;int	debug;int	xflag;int	sfd;int	fskind;			/* Kfs, Fs, Archive */char	*user; voidmain(int argc, char **argv){	File file;	char name[NAMELEN];	int i, errs; 	user = getuser();	name[0] = '\0';	memset(&file, 0, sizeof file);	file.new = "";	file.old = 0;	oldroot = "";	newroot = "/n/kfs";	users = 0;	fskind = Kfs;	ARGBEGIN{	case 'a':		fskind = Archive;		newroot = "";		Binits(&bout, 1, OWRITE, boutbuf, sizeof boutbuf);		break;	case 'd':		fskind = Fs;		newroot = ARGF();		break;	case 'D':		debug = 1;		break;	case 'n':		strncpy(name, ARGF(), NAMELEN - 1);		name[NAMELEN - 1] = '\0';		break;	case 'p':		modes = 1;		break;	case 'r':		ream = 1;		break;	case 's':		oldroot = ARGF();		break;	case 'u':		users = ARGF();		break;	case 'v':		verb = 1;		break;	case 'x':		xflag = 1;		break;	case 'z':		buflen = atoi(ARGF())-8;		break;	default:		usage();	}ARGEND 	if(!argc)			usage(); 	buf = emalloc(buflen);	zbuf = emalloc(buflen);	memset(zbuf, 0, buflen); 	mountkfs(name);	kfscmd("allow");	proto = "users";	setusers();	cputype = getenv("cputype");	if(cputype == 0)		cputype = "68020"; 	errs = 0;	for(i = 0; i < argc; i++){		proto = argv[i];		fprint(2, "processing %s\n", proto); 		b = Bopen(proto, OREAD);		if(!b){			fprint(2, "%s: can't open %s: skipping\n", prog, proto);			errs++;			continue;		} 		lineno = 0;		indent = 0;		mkfs(&file, -1);		Bterm(b);	}	fprint(2, "file system made\n");	kfscmd("disallow");	kfscmd("sync");	if(errs)		exits("skipped protos");	if(fskind == Archive){		Bprint(&bout, "end of archive\n");		Bterm(&bout);	}	exits(0);} voidmkfs(File *me, int level){	File *child;	int rec; 	child = getfile(me);	if(!child)		return;	if((child->elem[0] == '+' || child->elem[0] == '*') && child->elem[1] == '\0'){		rec = child->elem[0] == '+';		free(child->new);		child->new = strdup(me->new);		setnames(child);		mktree(child, rec);		freefile(child);		child = getfile(me);	}	while(child && indent > level){		if(mkfile(child))			mkfs(child, indent);		freefile(child);		child = getfile(me);	}	if(child){		freefile(child);		Bseek(b, -Blinelen(b), 1);		lineno--;	}} voidmktree(File *me, int rec){	File child;	Dir d[HUNKS];	int i, n, fd; 	fd = open(oldfile, OREAD);	if(fd < 0){		warn("can't open %s: %r", oldfile);		return;	} 	child = *me;	while((n = dirread(fd, d, sizeof d)) > 0){		n /= DIRLEN;		for(i = 0; i < n; i++){			child.new = mkpath(me->new, d[i].name);			if(me->old)				child.old = mkpath(me->old, d[i].name);			child.elem = d[i].name;			setnames(&child);			if(copyfile(&child, &d[i], 1) && rec)				mktree(&child, rec);			free(child.new);			if(child.old)				free(child.old);		}	}	close(fd);} intmkfile(File *f){	Dir dir; 	if(dirstat(oldfile, &dir) < 0){		warn("can't stat file %s: %r", oldfile);		skipdir();		return 0;	}	return copyfile(f, &dir, 0);} intcopyfile(File *f, Dir *d, int permonly){	ulong mode; 	if(xflag){		Bprint(&bout, "%s\t%ld\t%d\n", f->new, d->mtime, d->length);		return (d->mode & CHDIR) != 0;	}	if(verb)		fprint(2, "%s\n", f->new);	memmove(d->name, f->elem, NAMELEN);	if(d->type != 'M'){		strncpy(d->uid, "sys", NAMELEN);		strncpy(d->gid, "sys", NAMELEN);		mode = (d->mode >> 6) & 7;		d->mode |= mode | (mode << 3);	}	if(strcmp(f->uid, "-") != 0)		strncpy(d->uid, f->uid, NAMELEN);	if(strcmp(f->gid, "-") != 0)		strncpy(d->gid, f->gid, NAMELEN);	if(fskind == Fs){		strncpy(d->uid, user, NAMELEN);		strncpy(d->gid, user, NAMELEN);	}	if(f->mode != ~0){		if(permonly)			d->mode = (d->mode & ~0666) | (f->mode & 0666);		else if((d->mode&CHDIR) != (f->mode&CHDIR))			warn("inconsistent mode for %s", f->new);		else			d->mode = f->mode;	}	if(!uptodate(d, newfile)){		if(d->mode & CHDIR)			mkdir(d);		else			copy(d);	}else if(modes && dirwstat(newfile, d) < 0)		warn("can't set modes for %s: %r", f->new);	return (d->mode & CHDIR) != 0;} /* * check if file to is up to date with * respect to the file represented by df */intuptodate(Dir *df, char *to){	Dir dt; 	if(fskind == Archive || ream || dirstat(to, &dt) < 0)		return 0;	return dt.mtime >= df->mtime;} voidcopy(Dir *d){	char cptmp[LEN], *p;	long tot;	int f, t, n; 	f = open(oldfile, OREAD);	if(f < 0){		warn("can't open %s: %r", oldfile);		return;	}	t = -1;	if(fskind == Archive)		arch(d);	else{		strcpy(cptmp, newfile);		p = utfrrune(cptmp, L'/');		if(!p)			error("internal temporary file error");		strcpy(p+1, "__mkfstmp");		t = create(cptmp, OWRITE, 0666);		if(t < 0){			warn("can't create %s: %r", newfile);			close(f);			return;		}	} 	for(tot = 0;; tot += n){		n = read(f, buf, buflen);		if(n < 0){			warn("can't read %s: %r", oldfile);			break;		}		if(n == 0)			break;		if(fskind == Archive){			if(Bwrite(&bout, buf, n) != n)				error("write error: %r");		}else if(memcmp(buf, zbuf, buflen) == 0){			if(seek(t, buflen, 1) < 0)				error("can't write zeros to %s: %r", newfile);		}else if(write(t, buf, n) < n)			error("can't write %s: %r", newfile);	}	close(f);	if(tot != d->length){		warn("wrong number bytes written to %s (was %d should be %d)\n",			newfile, tot, d->length);		if(fskind == Archive){			warn("seeking to proper position\n");			Bseek(&bout, d->length - tot, 1);		}	}	if(fskind == Archive)		return;	remove(newfile);	if(dirfwstat(t, d) < 0)		error("can't move tmp file to %s: %r", newfile);	close(t);} voidmkdir(Dir *d){	Dir d1;	int fd; 	if(fskind == Archive){		arch(d);		return;	}	fd = create(newfile, OREAD, d->mode);	if(fd < 0){		if(dirstat(newfile, &d1) < 0 || !(d1.mode & CHDIR))			error("can't create %s", newfile);		if(dirwstat(newfile, d) < 0)			warn("can't set modes for %s: %r", newfile);		return;	}	if(dirfwstat(fd, d) < 0)		warn("can't set modes for %s: %r", newfile);	close(fd);} voidarch(Dir *d){	Bprint(&bout, "%s %luo %s %s %lud %d\n",		newfile, d->mode, d->uid, d->gid, d->mtime, d->length);} char *mkpath(char *prefix, char *elem){	char *p;	int n; 	n = strlen(prefix) + strlen(elem) + 2;	p = emalloc(n);	sprint(p, "%s/%s", prefix, elem);	return p;} char *strdup(char *s){	char *t; 	t = emalloc(strlen(s) + 1);	return strcpy(t, s);} voidsetnames(File *f){	sprint(newfile, "%s%s", newroot, f->new);	if(f->old){		if(f->old[0] == '/')			sprint(oldfile, "%s%s", oldroot, f->old);		else			strcpy(oldfile, f->old);	}else		sprint(oldfile, "%s%s", oldroot, f->new);	if(strlen(newfile) >= sizeof newfile 	|| strlen(oldfile) >= sizeof oldfile)		error("name overfile");} voidfreefile(File *f){	if(f->old)		free(f->old);	if(f->new)		free(f->new);	free(f);} /* * skip all files in the proto that * could be in the current dir */voidskipdir(void){	char *p, c;	int level; 	if(indent < 0)		return;	level = indent;	for(;;){		indent = 0;		p = Brdline(b, '\n');		lineno++;		if(!p){			indent = -1;			return;		}		while((c = *p++) != '\n')			if(c == ' ')				indent++;			else if(c == '\t')				indent += 8;			else				break;		if(indent <= level){			Bseek(b, -Blinelen(b), 1);			lineno--;			return;		}	}} File*getfile(File *old){	File *f;	char elem[NAMELEN];	char *p;	int c; 	if(indent < 0)

Lines 1–500 of 771.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t