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

📄 file.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include "cformat.h"#include "lru.h"#include "bcache.h"#include "disk.h"#include "inode.h"#include "file.h"/* *  merge data with that which already exists in a block * *  we allow only one range per block, always use the new *  data if the ranges don't overlap. */voidfmerge(Dptr *p, char *to, char *from, int start, int len){	int end;	end = start + len;	memmove(to+start, from, end-start);	/*	 *  if ranges do not overlap...	 */	if(start>p->end || p->start>end){		/*		 *  just use the new data		 */		p->start = start;		p->end = end;	} else {		/*		 *  merge ranges		 */		if(start < p->start)			p->start = start;		if(end > p->end)			p->end = end;	}}/* *  write a block (or less) of data onto a disk, follow it with any necessary *  pointer writes. * *	N.B. ordering is everything */intfbwrite(Icache *ic, Ibuf *b, char *a, ulong off, int len){	Bbuf *dbb;	/* data block */	Bbuf *ibb;	/* indirect block */	Dptr *p;	Dptr t;	ulong fbno;	int wrinode;	fbno = off / ic->bsize;	p = &b->inode.ptr;	ibb = 0;	wrinode = 0;	/*	 *  are there any pages for this inode?	 */	if(p->bno == Notabno){		wrinode = 1;		goto dowrite;	}		/* 	 *  is it an indirect block?	 */	if(p->bno & Indbno){		ibb = bcread(ic, p->bno);		if(ibb == 0)			return -1;		p = (Dptr*)ibb->data;		p += fbno % ic->p2b;		goto dowrite;	}	/* 	 *  is it the wrong direct block?	 */	if((p->fbno%ic->p2b) != (fbno%ic->p2b)){		/*		 *  yes, make an indirect block		 */		t = *p;		dpalloc(ic, p);		if(p->bno == Notabno){			*p = t;			return -1;		}		ibb = bcalloc(ic, p->bno);		if(ibb == 0){			*p = t;			return -1;		}		p = (Dptr*)ibb->data;		p += t.fbno % ic->p2b;		*p = t;		p = (Dptr*)ibb->data;		p += fbno % ic->p2b;	}	wrinode = 1;dowrite:	/*	 *  get the data block into the block cache	 */	if(p->bno == Notabno){		/*		 *  create a new block		 */		dalloc(ic, p);		if(p->bno == Notabno)			return -1;		/* no blocks left (maybe) */		dbb = bcalloc(ic, p->bno);	} else {		/*		 *  use what's there		 */		dbb = bcread(ic, p->bno);	}	if(dbb == 0)		return -1;	/*	 *  merge in the new data	 */	if(p->fbno != fbno){		p->start = p->end = 0;		p->fbno = fbno;	}	fmerge(p, dbb->data, a, off % ic->bsize, len);	/*	 *  write changed blocks back in the	 *  correct order	 */	bcmark(ic, dbb);	if(ibb){		bcmark(ic, ibb);	}	if(wrinode){		if(iwrite(ic, b) < 0)			return -1;	}	return len;}/* *  write `n' bytes to the cache * *  return number of bytes written */longfwrite(Icache *ic, Ibuf *b, char *a, ulong off, long n){	int len;	long sofar;	for(sofar = 0; sofar < n; sofar += len){		len = ic->bsize - ((off+sofar)%ic->bsize);		if(len > n - sofar)			len = n - sofar;		if(fbwrite(ic, b, a+sofar, off+sofar, len) < 0)			return sofar;	}	return sofar;}/* *  get a pointer to the next valid data at or after `off' */Dptr *fpget(Icache *ic, Ibuf *b, ulong off){	Bbuf *ibb;	/* indirect block */	ulong fbno;	long doff;	Dptr *p;	Dptr *p0;	Dptr *pf;	fbno = off / ic->bsize;	p = &b->inode.ptr;	/*	 *  are there any pages for this inode?	 */	if(p->bno == Notabno)		return 0;		/* 	 *  if it's a direct block, life is easy?	 */	if(!(p->bno & Indbno)){		/*		 *  a direct block, return p if it's at least past what we want		 */		if(p->fbno > fbno)			return p;		if(p->fbno < fbno)			return 0;		doff = off % ic->bsize;		if(doff>=p->start && doff<p->end)			return p;		else			return 0;	}	/*	 *  read the indirect block	 */	ibb = bcread(ic, p->bno);	if(ibb == 0)		return 0;	/*	 *  find the next valid pointer	 */	p0 = (Dptr*)ibb->data;	pf = p0 + (fbno % ic->p2b);	if(pf->bno!=Notabno && pf->fbno==fbno){		doff = off % ic->bsize;		if(doff<pf->end)			return pf;	}	for(p = pf+1 ;p < p0 + ic->p2b; p++){		fbno++;		if(p->fbno==fbno && p->bno!=Notabno && p->start<p->end)			return p;	}	for(p = p0 ;p < pf; p++){		fbno++;		if(p->fbno==fbno && p->bno!=Notabno && p->start<p->end)			return p;	}	return 0;}/* *  read `n' bytes from the cache. * *  if we hit a gap and we've read something, *  return number of bytes read so far. * *  if we start with a gap, return minus the number of bytes *  to the next data. * *  if there are no bytes cached, return 0. */longfread(Icache *ic, Ibuf *b, char *a, ulong off, long n){	int len;	Dptr *p;	Bbuf *bb;	long sofar;	long gap;	int start;	for(sofar = 0; sofar < n; sofar += len, off += len){		/*		 *  get pointer to next data		 */		len = n - sofar;		p = fpget(ic, b, off);		/*		 *  if no more data, return what we have so far		 */		if(p == 0)			return sofar;		/*		 *  if there's a gap, return the size of the gap		 */		gap = (ic->bsize*p->fbno + p->start) - off;		if(gap>0){			if(sofar == 0)				return -gap;			else				return sofar;		}		/*		 *  return what we have		 */		bb = bcread(ic, p->bno);		if(bb == 0)			return sofar;		start = p->start - gap;		if(p->end - start < len)			len = p->end - start;		memmove(a + sofar, bb->data + start, len);	}	return sofar;}

⌨️ 快捷键说明

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