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

📄 cdrdwr.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <libsec.h>#include "iso9660.h"static int readisodesc(Cdimg*, Voldesc*);static int readjolietdesc(Cdimg*, Voldesc*);/* * It's not strictly conforming; instead it's enough to * get us up and running; presumably the real CD writing * will take care of being conforming. * * Things not conforming include: *	- no path table *	- root directories are of length zero */Cdimg*createcd(char *file, Cdinfo info){	int fd, xfd;	Cdimg *cd;	if(access(file, AEXIST) == 0){		werrstr("file already exists");		return nil;	}	if((fd = create(file, ORDWR, 0666)) < 0)		return nil;	cd = emalloc(sizeof *cd);	cd->file = atom(file);	Binit(&cd->brd, fd, OREAD);	if((xfd = open(file, ORDWR)) < 0)		sysfatal("can't open file again: %r");	Binit(&cd->bwr, xfd, OWRITE);	Crepeat(cd, 0, 16*Blocksize);	Cputisopvd(cd, info);	if(info.flags & CDbootable){		cd->bootimage = info.bootimage;		cd->flags |= CDbootable;		Cputbootvol(cd);	}	if(readisodesc(cd, &cd->iso) < 0)		assert(0);	if(info.flags & CDplan9)		cd->flags |= CDplan9;	else if(info.flags & CDrockridge)		cd->flags |= CDrockridge;	if(info.flags & CDjoliet) {		Cputjolietsvd(cd, info);		if(readjolietdesc(cd, &cd->joliet) < 0)			assert(0);		cd->flags |= CDjoliet;	}	Cputendvd(cd);	if(info.flags & CDdump){		cd->nulldump = Cputdumpblock(cd);		cd->flags |= CDdump;	}	if(cd->flags & CDbootable){		Cputbootcat(cd);		Cupdatebootvol(cd);	}	if(info.flags & CDconform)		cd->flags |= CDconform;	cd->flags |= CDnew;	cd->nextblock = Cwoffset(cd) / Blocksize;	assert(cd->nextblock != 0);	return cd;}Cdimg*opencd(char *file, Cdinfo info){	int fd, xfd;	Cdimg *cd;	Dir *d;	if((fd = open(file, ORDWR)) < 0) {		if(access(file, AEXIST) == 0)			return nil;		return createcd(file, info);	}	if((d = dirfstat(fd)) == nil) {		close(fd);		return nil;	}	if(d->length == 0 || d->length % Blocksize) {		werrstr("bad length %lld", d->length);		close(fd);		free(d);		return nil;	}	cd = emalloc(sizeof *cd);	cd->file = atom(file);	cd->nextblock = d->length / Blocksize;	assert(cd->nextblock != 0);	free(d);	Binit(&cd->brd, fd, OREAD);	if((xfd = open(file, ORDWR)) < 0)		sysfatal("can't open file again: %r");	Binit(&cd->bwr, xfd, OWRITE);	if(readisodesc(cd, &cd->iso) < 0) {		free(cd);		close(fd);		close(xfd);		return nil;	}	/* lowercase because of isostring */	if(strstr(cd->iso.systemid, "iso9660") == nil 	&& strstr(cd->iso.systemid, "utf8") == nil) {		werrstr("unknown systemid %s", cd->iso.systemid);		free(cd);		close(fd);		close(xfd);		return nil;	}		if(strstr(cd->iso.systemid, "plan 9"))		cd->flags |= CDplan9;	if(strstr(cd->iso.systemid, "iso9660"))		cd->flags |= CDconform;	if(strstr(cd->iso.systemid, "rrip"))		cd->flags |= CDrockridge;	if(strstr(cd->iso.systemid, "boot"))		cd->flags |= CDbootable;	if(readjolietdesc(cd, &cd->joliet) == 0)		cd->flags |= CDjoliet;	if(hasdump(cd))		cd->flags |= CDdump;	return cd;}ulongbig(void *a, int n){	uchar *p;	ulong v;	int i;	p = a;	v = 0;	for(i=0; i<n; i++)		v = (v<<8) | *p++;	return v;}ulonglittle(void *a, int n){	uchar *p;	ulong v;	int i;	p = a;	v = 0;	for(i=0; i<n; i++)		v |= (*p++<<(i*8));	return v;}voidCreadblock(Cdimg *cd, void *buf, ulong block, ulong len){	assert(block != 0);	/* nothing useful there */	Bflush(&cd->bwr);	if(Bseek(&cd->brd, block*Blocksize, 0) != block*Blocksize)		sysfatal("error seeking to block %lud", block);	if(Bread(&cd->brd, buf, len) != len)		sysfatal("error reading %lud bytes at block %lud: %r %lld", len, block, Bseek(&cd->brd, 0, 2));}intparsedir(Cdimg *cd, Direc *d, uchar *buf, int len, char *(*cvtname)(uchar*, int)){	enum { NAMELEN = 28 };	char name[NAMELEN];	uchar *p;	Cdir *c;	memset(d, 0, sizeof *d);	c = (Cdir*)buf;	if(c->len > len) {		werrstr("buffer too small");		return -1;	}	if(c->namelen == 1 && c->name[0] == '\0')		d->name = atom(".");	else if(c->namelen == 1 && c->name[0] == '\001')		d->name = atom("..");	else if(cvtname)		d->name = cvtname(c->name, c->namelen);	d->block = little(c->dloc, 4);	d->length = little(c->dlen, 4);	if(c->flags & 2)		d->mode |= DMDIR;/*BUG: do we really need to parse the plan 9 fields? */	/* plan 9 use fields */	if((cd->flags & CDplan9) && cvtname == isostring	&& (c->namelen != 1 || c->name[0] > 1)) {		p = buf+33+c->namelen;		if((p-buf)&1)			p++;		assert(p < buf+c->len);		assert(*p < NAMELEN);		if(*p != 0) {			memmove(name, p+1, *p);			name[*p] = '\0';			d->confname = d->name;			d->name = atom(name);		}		p += *p+1;		assert(*p < NAMELEN);		memmove(name, p+1, *p);		name[*p] = '\0';		d->uid = atom(name);		p += *p+1;		assert(*p < NAMELEN);		memmove(name, p+1, *p);		name[*p] = '\0';		d->gid = atom(name);		p += *p+1;		if((p-buf)&1)			p++;		d->mode = little(p, 4);	}	// BUG: rock ridge extensions	return 0;}voidsetroot(Cdimg *cd, ulong block, ulong dloc, ulong dlen){	assert(block != 0);	Cwseek(cd, block*Blocksize+offsetof(Cvoldesc, rootdir[0])+offsetof(Cdir, dloc[0]));	Cputn(cd, dloc, 4);	Cputn(cd, dlen, 4);}voidsetvolsize(Cdimg *cd, ulong block, ulong size){	assert(block != 0);	Cwseek(cd, block*Blocksize+offsetof(Cvoldesc, volsize[0]));	Cputn(cd, size, 4);}voidsetpathtable(Cdimg *cd, ulong block, ulong sz, ulong lloc, ulong bloc){	assert(block != 0);	Cwseek(cd, block*Blocksize+offsetof(Cvoldesc, pathsize[0]));	Cputn(cd, sz, 4);	Cputnl(cd, lloc, 4);	Cputnl(cd, 0, 4);	Cputnm(cd, bloc, 4);	Cputnm(cd, 0, 4);	assert(Cwoffset(cd) == block*Blocksize+offsetof(Cvoldesc, rootdir[0]));}static voidparsedesc(Voldesc *v, Cvoldesc *cv, char *(*string)(uchar*, int)){	v->systemid = string(cv->systemid, sizeof cv->systemid);	v->pathsize = little(cv->pathsize, 4);	v->lpathloc = little(cv->lpathloc, 4);	v->mpathloc = little(cv->mpathloc, 4);	v->volumeset = string(cv->volumeset, sizeof cv->volumeset);	v->publisher = string(cv->publisher, sizeof cv->publisher);	v->preparer = string(cv->preparer, sizeof cv->preparer);	v->application = string(cv->application, sizeof cv->application);	v->abstract = string(cv->abstract, sizeof cv->abstract);	v->biblio = string(cv->biblio, sizeof cv->biblio);	v->notice = string(cv->notice, sizeof cv->notice);}	static intreadisodesc(Cdimg *cd, Voldesc *v){	static uchar magic[] = { 0x01, 'C', 'D', '0', '0', '1', 0x01, 0x00 };	Cvoldesc cv;	memset(v, 0, sizeof *v);	Creadblock(cd, &cv, 16, sizeof cv);	if(memcmp(cv.magic, magic, sizeof magic) != 0) {		werrstr("bad pvd magic");		return -1;	}	if(little(cv.blocksize, 2) != Blocksize) {		werrstr("block size not %d", Blocksize);		return -1;	}	cd->iso9660pvd = 16;	parsedesc(v, &cv, isostring);	return parsedir(cd, &v->root, cv.rootdir, sizeof cv.rootdir, isostring);}static intreadjolietdesc(Cdimg *cd, Voldesc *v){	int i;	static uchar magic[] = { 0x02, 'C', 'D', '0', '0', '1', 0x01, 0x00 };	Cvoldesc cv;	memset(v, 0, sizeof *v);	for(i=16; i<24; i++) {		Creadblock(cd, &cv, i, sizeof cv);		if(memcmp(cv.magic, magic, sizeof magic) != 0)			continue;		if(cv.charset[0] != 0x25 || cv.charset[1] != 0x2F		|| (cv.charset[2] != 0x40 && cv.charset[2] != 0x43 && cv.charset[2] != 0x45))			continue;		break;	}	if(i==24) {		werrstr("could not find Joliet SVD");		return -1;	}	if(little(cv.blocksize, 2) != Blocksize) {		werrstr("block size not %d", Blocksize);		return -1;	}	cd->jolietsvd = i;	parsedesc(v, &cv, jolietstring);	return parsedir(cd, &v->root, cv.rootdir, sizeof cv.rootdir, jolietstring);}/* * CD image buffering routines. */voidCputc(Cdimg *cd, int c){	assert(Boffset(&cd->bwr) >= 16*Blocksize || c == 0);if(Boffset(&cd->bwr) == 0x9962)if(c >= 256) abort();	if(Bputc(&cd->bwr, c) < 0)		sysfatal("Bputc: %r");	Bflush(&cd->brd);}voidCputnl(Cdimg *cd, ulong val, int size){	switch(size) {	default:		sysfatal("bad size %d in bputnl", size);	case 2:		Cputc(cd, val);		Cputc(cd, val>>8);		break;	case 4:		Cputc(cd, val);		Cputc(cd, val>>8);		Cputc(cd, val>>16);		Cputc(cd, val>>24);		break;	}}voidCputnm(Cdimg *cd, ulong val, int size){	switch(size) {	default:		sysfatal("bad size %d in bputnl", size);	case 2:		Cputc(cd, val>>8);		Cputc(cd, val);		break;	case 4:		Cputc(cd, val>>24);		Cputc(cd, val>>16);		Cputc(cd, val>>8);		Cputc(cd, val);		break;	}}voidCputn(Cdimg *cd, long val, int size){	Cputnl(cd, val, size);	Cputnm(cd, val, size);}/* * ASCII/UTF string writing */voidCrepeat(Cdimg *cd, int c, int n){	while(n-- > 0)		Cputc(cd, c);}voidCputs(Cdimg *cd, char *s, int size){	int n;	if(s == nil) {		Crepeat(cd, ' ', size);		return;	}	for(n=0; n<size && *s; n++)		Cputc(cd, *s++);	if(n<size)		Crepeat(cd, ' ', size-n);}voidCwrite(Cdimg *cd, void *buf, int n){	assert(Boffset(&cd->bwr) >= 16*Blocksize);	if(Bwrite(&cd->bwr, buf, n) != n)		sysfatal("Bwrite: %r");	Bflush(&cd->brd);}voidCputr(Cdimg *cd, Rune r){	Cputc(cd, r>>8);	Cputc(cd, r);}voidCrepeatr(Cdimg *cd, Rune r, int n){	int i;	for(i=0; i<n; i++)		Cputr(cd, r);}voidCputrs(Cdimg *cd, Rune *s, int osize){	int n, size;	size = osize/2;	if(s == nil)		Crepeatr(cd, (Rune)' ', size);	else {		for(n=0; *s && n<size; n++)			Cputr(cd, *s++);		if(n<size)			Crepeatr(cd, ' ', size-n);	}	if(osize&1)		Cputc(cd, 0);	/* what else can we do? */}voidCputrscvt(Cdimg *cd, char *s, int size){	Rune r[256];	strtorune(r, s);	Cputrs(cd, strtorune(r, s), size);}voidCpadblock(Cdimg *cd){	int n;	ulong nb;	n = Blocksize - (Boffset(&cd->bwr) % Blocksize);	if(n != Blocksize)		Crepeat(cd, 0, n);	nb = Boffset(&cd->bwr)/Blocksize;	assert(nb != 0);	if(nb > cd->nextblock)		cd->nextblock = nb;}voidCputdate(Cdimg *cd, ulong ust){	Tm *tm;	if(ust == 0) {		Crepeat(cd, 0, 7);		return;	}	tm = gmtime(ust);	Cputc(cd, tm->year);	Cputc(cd, tm->mon+1);	Cputc(cd, tm->mday);	Cputc(cd, tm->hour);	Cputc(cd, tm->min);	Cputc(cd, tm->sec);	Cputc(cd, 0);}voidCputdate1(Cdimg *cd, ulong ust){	Tm *tm;	char str[20];	if(ust == 0) {		Crepeat(cd, '0', 16);		Cputc(cd, 0);		return;	}	tm = gmtime(ust);	sprint(str, "%.4d%.2d%.2d%.2d%.2d%.4d",		tm->year+1900,		tm->mon+1,		tm->mday,		tm->hour,		tm->min,		tm->sec*100);	Cputs(cd, str, 16);	Cputc(cd, 0);}voidCwseek(Cdimg *cd, ulong offset){	Bseek(&cd->bwr, offset, 0);}ulongCwoffset(Cdimg *cd){	return Boffset(&cd->bwr);}voidCwflush(Cdimg *cd){	Bflush(&cd->bwr);}ulongCroffset(Cdimg *cd){	return Boffset(&cd->brd);}voidCrseek(Cdimg *cd, ulong offset){	Bseek(&cd->brd, offset, 0);}intCgetc(Cdimg *cd){	int c;	Cwflush(cd);	if((c = Bgetc(&cd->brd)) == Beof) {		fprint(2, "getc at %lud\n", Croffset(cd));		assert(0);		//sysfatal("Bgetc: %r");	}	return c;}voidCread(Cdimg *cd, void *buf, int n){	Cwflush(cd);	if(Bread(&cd->brd, buf, n) != n)		sysfatal("Bread: %r");}char*Crdline(Cdimg *cd, int c){	Cwflush(cd);	return Brdline(&cd->brd, c);}intClinelen(Cdimg *cd){	return Blinelen(&cd->brd);}

⌨️ 快捷键说明

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