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

📄 mkext.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <bio.h>enum{	LEN	= 8*1024,	NFLDS	= 6,		/* filename, modes, uid, gid, mtime, bytes */};int	selected(char*, int, char*[]);void	mkdirs(char*, char*);void	mkdir(char*, ulong, ulong, char*, char*);void	extract(char*, ulong, ulong, char*, char*, uvlong);void	seekpast(uvlong);void	error(char*, ...);void	warn(char*, ...);void	usage(void);#pragma varargck argpos warn 1#pragma varargck argpos error 1Biobufhdr bin;uchar	binbuf[2*LEN];char	linebuf[LEN];int	uflag;int	hflag;int	vflag;int	Tflag;voidmain(int argc, char **argv){	Biobuf bout;	char *fields[NFLDS], name[2*LEN], *p, *namep;	char *uid, *gid;	ulong mode, mtime;	uvlong bytes;	quotefmtinstall();	namep = name;	ARGBEGIN{	case 'd':		p = ARGF();		if(strlen(p) >= LEN)			error("destination fs name too long\n");		strcpy(name, p);		namep = name + strlen(name);		break;	case 'h':		hflag = 1;		Binit(&bout, 1, OWRITE);		break;	case 'u':		uflag = 1;		Tflag = 1;		break;	case 'T':		Tflag = 1;		break;	case 'v':		vflag = 1;		break;	default:		usage();	}ARGEND		Binits(&bin, 0, OREAD, binbuf, sizeof binbuf);	while(p = Brdline(&bin, '\n')){		p[Blinelen(&bin)-1] = '\0';		strcpy(linebuf, p);		p = linebuf;		if(strcmp(p, "end of archive") == 0){			Bterm(&bout);			fprint(2, "done\n");			exits(0);		}		if (gettokens(p, fields, NFLDS, " \t") != NFLDS){			warn("too few fields in file header");			continue;		}		p = unquotestrdup(fields[0]);		strcpy(namep, p);		free(p);		mode = strtoul(fields[1], 0, 8);		uid = fields[2];		gid = fields[3];		mtime = strtoul(fields[4], 0, 10);		bytes = strtoull(fields[5], 0, 10);		if(argc){			if(!selected(namep, argc, argv)){				if(bytes)					seekpast(bytes);				continue;			}			mkdirs(name, namep);		}		if(hflag){			Bprint(&bout, "%q %luo %q %q %lud %llud\n",				name, mode, uid, gid, mtime, bytes);			if(bytes)				seekpast(bytes);			continue;		}		if(mode & DMDIR)			mkdir(name, mode, mtime, uid, gid);		else			extract(name, mode, mtime, uid, gid, bytes);	}	fprint(2, "premature end of archive\n");	exits("premature end of archive");}intfileprefix(char *prefix, char *s){	while(*prefix)		if(*prefix++ != *s++)			return 0;	if(*s && *s != '/')		return 0;	return 1;}intselected(char *s, int argc, char *argv[]){	int i;	for(i=0; i<argc; i++)		if(fileprefix(argv[i], s))			return 1;	return 0;}voidmkdirs(char *name, char *namep){	char buf[2*LEN], *p;	int fd;	strcpy(buf, name);	for(p = &buf[namep - name]; p = utfrune(p, '/'); p++){		if(p[1] == '\0')			return;		*p = 0;		fd = create(buf, OREAD, 0775|DMDIR);		close(fd);		*p = '/';	}}voidmkdir(char *name, ulong mode, ulong mtime, char *uid, char *gid){	Dir *d, xd;	int fd;	char *p;	char olderr[256];	fd = create(name, OREAD, mode);	if(fd < 0){		rerrstr(olderr, sizeof(olderr));		if((d = dirstat(name)) == nil || !(d->mode & DMDIR)){			free(d);			warn("can't make directory %q, mode %luo: %s", name, mode, olderr);			return;		}		free(d);	}	close(fd);	d = &xd;	nulldir(d);	p = utfrrune(name, L'/');	if(p)		p++;	else		p = name;	d->name = p;	if(uflag){		d->uid = uid;		d->gid = gid;	}	if(Tflag)		d->mtime = mtime;	d->mode = mode;	if(dirwstat(name, d) < 0)		warn("can't set modes for %q: %r", name);	if(uflag||Tflag){		if((d = dirstat(name)) == nil){			warn("can't reread modes for %q: %r", name);			return;		}		if(Tflag && d->mtime != mtime)			warn("%q: time mismatch %lud %lud\n", name, mtime, d->mtime);		if(uflag && strcmp(uid, d->uid))			warn("%q: uid mismatch %q %q", name, uid, d->uid);		if(uflag && strcmp(gid, d->gid))			warn("%q: gid mismatch %q %q", name, gid, d->gid);	}}voidextract(char *name, ulong mode, ulong mtime, char *uid, char *gid, uvlong bytes){	Dir d, *nd;	Biobuf *b;	char buf[LEN];	char *p;	ulong n;	uvlong tot;	if(vflag)		print("x %q %llud bytes\n", name, bytes);	b = Bopen(name, OWRITE);	if(!b){		warn("can't make file %q: %r", name);		seekpast(bytes);		return;	}	for(tot = 0; tot < bytes; tot += n){		n = sizeof buf;		if(tot + n > bytes)			n = bytes - tot;		n = Bread(&bin, buf, n);		if(n <= 0)			error("premature eof reading %q", name);		if(Bwrite(b, buf, n) != n)			warn("error writing %q: %r", name);	}	nulldir(&d);	p = utfrrune(name, '/');	if(p)		p++;	else		p = name;	d.name = p;	if(uflag){		d.uid = uid;		d.gid = gid;	}	if(Tflag)		d.mtime = mtime;	d.mode = mode;	Bflush(b);	if(dirfwstat(Bfildes(b), &d) < 0)		warn("can't set modes for %q: %r", name);	if(uflag||Tflag){		if((nd = dirfstat(Bfildes(b))) == nil)			warn("can't reread modes for %q: %r", name);		else{			if(Tflag && nd->mtime != mtime)				warn("%q: time mismatch %lud %lud\n",					name, mtime, nd->mtime);			if(uflag && strcmp(uid, nd->uid))				warn("%q: uid mismatch %q %q",					name, uid, nd->uid);			if(uflag && strcmp(gid, nd->gid))				warn("%q: gid mismatch %q %q",					name, gid, nd->gid);			free(nd);		}	}	Bterm(b);}voidseekpast(uvlong bytes){	char buf[LEN];	ulong n;	uvlong tot;	for(tot = 0; tot < bytes; tot += n){		n = sizeof buf;		if(tot + n > bytes)			n = bytes - tot;		n = Bread(&bin, buf, n);		if(n < 0)			error("premature eof");	}}voiderror(char *fmt, ...){	char buf[1024];	va_list arg;	sprint(buf, "%q: ", argv0);	va_start(arg, fmt);	vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);	va_end(arg);	fprint(2, "%s\n", buf);	exits(0);}voidwarn(char *fmt, ...){	char buf[1024];	va_list arg;	sprint(buf, "%q: ", argv0);	va_start(arg, fmt);	vseprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg);	va_end(arg);	fprint(2, "%s\n", buf);}voidusage(void){	fprint(2, "usage: mkext [-h] [-u] [-v] [-d dest-fs] [file ...]\n");	exits("usage");}

⌨️ 快捷键说明

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