/**
nkchenz@gmail.com 2006.7.21
fslite
inode 的name长度固定为16字节,0表示字符串结束
紧接inode之后是nentrys个entry
endblock,endblock_offset方便新加项使用
每个block的首部2字节为block索引,指向nextblock,如果为0,则表示结束。
简化编程难度。
*/
#include
#include
/*计数*/
typedef unsigned short int atomic_t;
/*文件偏移*/
typedef unsigned short int loff_t;
/*读写字节数*/
typedef unsigned short int msize_t;
typedef unsigned char spinlock_t;
/*文件系统最小块大小, 为了保证能够存下一个inode,必须>=32*/
#define FSLITE_BLOCKSIZE 32
/*总块数*/
#define FSLITE_TOTAL_BLOCKS 1024 /*32K*/
/* 系统预留空间*/
#define FSLITE_EMERGENCY_BLOCKS 10
/*不算stdin,stdout,stderr,系统最多可以打开的文件数*/
#define FSLITE_MAX_OPENFILES 5
#define FSLITE_MAX_OPENDIRS 5
#define FSLITE_MAGICSTRING_LEN 6
#define FSLITE_MAGICSTRING “fSliTe”
#define FSLITE_SEPARATOR “/”
#define FSLITE_MAX_NAME_LEN 11
#define FSLITE_MAX_PATH_LEN 64
/*superblock中的state*/
#define FSLITE_STATE_R 0×01 //可读
#define FSLITE_STATE_RW 0×02 //可读写
#define FSLITE_STATE_INVALID 0×00 //不可用
#define FSLITE_FILE 0×01
#define FSLITE_DIR 0×02
#define FSLITE_LINK 0×04
/*通用错误代码*/
#define FSLITE_OK 0×0000
#define FSLITE_ERR -1
#define FSLITE_NOMEM 0×0002 /*空间不足*/
#define FSLITE_EOF 0×0003
#define FSLITE_NONEXIST 0×0004 /*文件不存在*/
/* 文件指针位置定义*/
#define FSLITE_SEEK_CUR 1
#define FSLITE_SEEK_END 2
#define FSLITE_SEEK_SET 0
/* fopen mode */
#define FSLITE_FOPEN_R 0×01 //可读
#define FSLITE_FOPEN_RW 0×02 //可读写
/*三个标注描述符*/
#define FSLITE_STDIN 0
#define FSLITE_STDOUT 1
#define FSLITE_STDERR 2
#define FSLITE_SIZEOFINODE sizeof(fslite_inode)
#define FSLITE_SIZEOFENTRY sizeof(atomic_t)
#define FSLITE_NEXTBLOCK(n) ( *(atomic_t *) &fslite_data[n][0] ) // 由block号码获得next指针地址
#define FSLITE_BLOCKADDR(n) ( &fslite_data[n][0] ) //由block号码获取block的地址
#define FSLITE_INODEADDR(n) ( (fslite_inode *) &fslite_data[n][0] ) // 由block号码获得inode指针地址
#define FSLITE_BLOCKNUMBER(p) ( ((atomic_t) (p) – (atomic_t) fslite_data) / FSLITE_BLOCKSIZE )
/* data structure *****************************************************
*/
/* 文件系统信息块superblock
*/
struct fslite_superblock
{
unsigned char magicstring[FSLITE_MAGICSTRING_LEN];
unsigned char version;
unsigned char state;
unsigned short int blocksize;
atomic_t used_blocks; /*总块数*/
atomic_t free_blocks; /*空闲块数*/
atomic_t first_freeblock;
atomic_t root_block; /*文件系统根节点所在块*/
spinlock_t lock;
};
/* 节点块
类型可以为file,dir,link等. 每个inode都位于block的开始
*/
struct fslite_inode
{
atomic_t next;
unsigned char mode;//该节点的权限
unsigned char type;//该节点的类型
atomic_t parentblock;
unsigned short int atime; /* last access time */
unsigned short int mtime; /* last modify time */
msize_t size; //文件的字节数
atomic_t nentry; //目录所含有的子项数
/* end始终指向最后一个子项
** nentry==0时,end为0
*/
atomic_t entry_endblock;
#if FSLITE_BLOCKSIZE > 255
atomic_t entry_endblock_offset;
#else
unsigned char entry_endblock_offset;
#endif
spinlock_t lock;//防止写冲突,防止使用过程中被删除
char name[FSLITE_MAX_NAME_LEN + 1]; //name字符串
};
typedef struct fslite_superblock fslite_superblock;
typedef struct fslite_inode fslite_inode;
/*文件的抽象结构*/
struct fslite_file
{
unsigned short int fd; /*文件描述符 stdin=0 stdout=1 stderr=2*/
unsigned char mode; /*打开方式*/
fslite_inode *inode;
fslite_superblock *sb;
loff_t fp; /*文件指针偏移*/
};
/*目录的抽象结构*/
struct fslite_dir
{
// unsigned short int fd; /*文件描述符 stdin=0 stdout=1 stderr=2*/
// unsigned char mode; /*打开方式*/
fslite_inode *inode;
fslite_superblock *sb;
loff_t dp; /*子项偏移*/
};
typedef struct fslite_file fslite_file;
typedef struct fslite_dir fslite_dir;
/* global declaration *****************************************************
*/
/*全局superblock指针*/
fslite_superblock * sb;
fslite_inode * root;
/* 虚拟ramfs映象 */
unsigned char fslite_data[FSLITE_TOTAL_BLOCKS][FSLITE_BLOCKSIZE];
/*全局打开文件数组*/
fslite_file files[FSLITE_MAX_OPENFILES + 3];
fslite_dir dirs[FSLITE_MAX_OPENDIRS ];
int nopenfiles;
int nopendirs;
/* spinlock **************************************************************
*/
int fslite_spin_lock(spinlock_t * lock)
{
return 0;
}
int fslite_spin_unlock(spinlock_t * lock)
{
return 0;
}
/* block **************************************************************
*/
/* 清零页面n
*/
int fslite_block_zero(atomic_t n)
{
memset(FSLITE_BLOCKADDR(n), 0, FSLITE_BLOCKSIZE);
return FSLITE_OK;
}
/* 从系统空闲列表获得一个空闲块, 不可能返回superblock 0,返回0表示错误
*/
atomic_t fslite_block_get()
{
atomic_t n;
if( sb->free_blocks lock);
n = sb->first_freeblock;
sb->first_freeblock = FSLITE_NEXTBLOCK(n);
sb-> used_blocks ++;
sb -> free_blocks –;
fslite_spin_unlock(&sb->lock);
fslite_block_zero(n);
printf(”block %d used\n”, n);
return n;
}
/* 释放块n
*/
int fslite_block_free(atomic_t n)
{
fslite_spin_lock(&sb->lock);
FSLITE_NEXTBLOCK(n) = sb->first_freeblock;
sb->first_freeblock = n;
//sb->last_freeblock = n;
sb-> used_blocks –;
sb-> free_blocks ++;
fslite_spin_unlock(&sb->lock);
printf(”block %d freed\n”, n);
return FSLITE_OK;
}
/* fs ***************************************************************
*/
/* 初始化文件系统
** superblock, block 号为0, fs的第一块
*/
int fslite_fs_init()
{
atomic_t i;
/* 设置superblock */
sb = (fslite_superblock * )FSLITE_BLOCKADDR(0);
//除了superblock,所有的都放入空闲列表
for(i=1; i magicstring, FSLITE_MAGICSTRING);
sb->version = 1;
sb->state = FSLITE_STATE_RW;
sb->blocksize = FSLITE_BLOCKSIZE;
sb->used_blocks = 0;
sb->free_blocks = FSLITE_TOTAL_BLOCKS – 1;
sb->first_freeblock = 1;
/* 设置rootblock */
sb->root_block = fslite_block_get();
root = FSLITE_INODEADDR( sb->root_block );
root->type = FSLITE_DIR;
root->parentblock = sb->root_block;
root->nentry = 0; // 含有0个子文件目录
strncpy(root->name, FSLITE_SEPARATOR, FSLITE_MAX_NAME_LEN);
printf(”blocks: %d/%d root: %d first_freeblock:%d\n”, sb->used_blocks, sb->free_blocks, sb->root_block, sb->first_freeblock);
printf(”inode size: %d\n”, FSLITE_SIZEOFINODE);
nopenfiles = 3;
nopendirs = 0;
return FSLITE_OK;
}
/* inode ***************************************************************
*/
/* 为node添加入口项 n
**
*/
int fslite_inode_addentry(atomic_t n, fslite_inode *p)
{
atomic_t tmp;
fslite_spin_lock(&p->lock);
if( p->nentry == 0) // 空目录
{
p->entry_endblock_offset = FSLITE_SIZEOFINODE;
p->entry_endblock = FSLITE_BLOCKNUMBER(p);
}else
p->entry_endblock_offset += FSLITE_SIZEOFENTRY;
/* 现在offset指向一个空的entry入口 */
if(p->entry_endblock_offset >= FSLITE_BLOCKSIZE) /*需要一个新block, offset此时应该等于 FSLITE_BLOCKSIZE*/
{
/* 需要一个新的block,只添加了一个entry,可知上一个block刚刚满 */
if((tmp=fslite_block_get()) == 0)
return FSLITE_ERR;
FSLITE_NEXTBLOCK(p->entry_endblock) = tmp;
p->entry_endblock = tmp;
p->entry_endblock_offset = FSLITE_SIZEOFENTRY;
// 新block的头部两个字节是 block索引,跳过
*(atomic_t *)(FSLITE_BLOCKADDR(tmp) + p->entry_endblock_offset) = n;
}else{ //原有block即可存下新加的这个入口
*(atomic_t *)(FSLITE_BLOCKADDR(p->entry_endblock) + p->entry_endblock_offset) = n;
}
p->nentry++;
fslite_spin_unlock(&p->lock);
return FSLITE_OK;
}
/* 获得node的第index个子项的值 */
atomic_t fslite_inode_getentry(atomic_t index, fslite_inode *p)
{
atomic_t nb, child;
unsigned char * start, *end;
int offset;
atomic_t nentry;
if( p->nentry == 0) // 空目录
return FSLITE_ERR;
nb = FSLITE_BLOCKNUMBER(p);
offset = FSLITE_SIZEOFINODE;
nentry = 0;
while(1)
{
start = (unsigned char * ) FSLITE_BLOCKADDR(nb) + offset;
if(nb == p->entry_endblock) // 最后一块
end = (unsigned char * ) FSLITE_BLOCKADDR(nb) + p->entry_endblock_offset;
else
end = (unsigned char * ) FSLITE_BLOCKADDR(nb) + FSLITE_BLOCKSIZE – FSLITE_SIZEOFENTRY;
while(1)
{
child = *(atomic_t*) start;
if(index == nentry)
return child;
nentry++;
// 处理完毕允许start==end,因为此时指向的也是有效元素,需要先进行处理
if(start==end) break;
start += FSLITE_SIZEOFENTRY;
}
// 如果刚刚处理的block是最后一个,则退出
if( nb == p->entry_endblock)
break;
// end指向的是 metablock索引 前的一个有效entry入口,所以要后移FSLITE_SIZEOFENTRY获得metablock索引
nb = FSLITE_NEXTBLOCK(nb);
offset = FSLITE_SIZEOFENTRY;
}
return 0;
}
/* 删除入口项 n
**
*/
int fslite_inode_delentry(atomic_t n, fslite_inode *p)
{
atomic_t nb, child, lastb;
unsigned char * start, *end;
int offset;
char shift;
char *v;
if( p->nentry == 0) // 空目录
return FSLITE_ERR;
fslite_spin_lock(&p->lock);
nb = FSLITE_BLOCKNUMBER(p);
offset = FSLITE_SIZEOFINODE;
shift=0;
lastb = nb;
while(1)
{
start = (unsigned char * ) FSLITE_BLOCKADDR(nb) + offset;
if(nb == p->entry_endblock) // 最后一块
end = (unsigned char * ) FSLITE_BLOCKADDR(nb) + p->entry_endblock_offset;
else
end = (unsigned char * ) FSLITE_BLOCKADDR(nb) + FSLITE_BLOCKSIZE – FSLITE_SIZEOFENTRY;
while(1)
{
child = *(atomic_t*) start;
if(shift)
{
*(atomic_t*)v = child;
v = start; //保存上一个的地址
}
if(child == n)
{
shift = 1;
v = start;
}
// 处理完毕允许start==end,因为此时指向的也是有效元素,需要先进行处理
if(start==end) break;
start += FSLITE_SIZEOFENTRY;
}
// 如果刚刚处理的block是最后一个,则退出
if( nb == p->entry_endblock)
break;
lastb = nb;
// end指向的是 metablock索引 前的一个有效entry入口,所以要后移FSLITE_SIZEOFENTRY获得metablock索引
nb = FSLITE_NEXTBLOCK(lastb);
offset = FSLITE_SIZEOFENTRY;
}
/* 没有找到?*/
if(shift==0)
{
fslite_spin_unlock(&p->lock);
return FSLITE_OK;
}
/* 最后一页只有一项,因此需要将其释放*/
if(p->entry_endblock_offset == FSLITE_SIZEOFENTRY)
{
fslite_block_free(nb);
/* 修改end指针,使其指向上一页的最后一个入口*/
p->entry_endblock_offset = FSLITE_BLOCKSIZE – FSLITE_SIZEOFENTRY;
p->entry_endblock = lastb;
FSLITE_NEXTBLOCK(p->entry_endblock) = 0;
}else
{
*(atomic_t *)(FSLITE_BLOCKADDR(nb) + p->entry_endblock_offset) = 0;
p->entry_endblock_offset -= FSLITE_SIZEOFENTRY;
}
p->nentry–;
fslite_spin_unlock(&p->lock);
return FSLITE_OK;
}
/* 在父目录parent下面创建名字为name的项,类型为type,返回新节点
** 如果parent不是目录,或者空间不够,则返回null
*/
fslite_inode *fslite_inode_createfile(char * name, fslite_inode *parent, unsigned char type)
{
fslite_inode *child;
atomic_t n;
if(parent == NULL || parent->type != FSLITE_DIR)
return NULL;
if(strcmp(name, “”)==0)
return NULL;
if((n=fslite_block_get()) == 0 )
return NULL;
child = FSLITE_INODEADDR(n);
fslite_spin_lock(&child->lock);
child->type=type;
child->parentblock = FSLITE_BLOCKNUMBER(parent);
strncpy(child->name, name, FSLITE_MAX_NAME_LEN);
fslite_spin_unlock(&child->lock);
if( fslite_inode_addentry(n, parent) != FSLITE_OK)
{
fslite_block_free(n);
return NULL;
}
return child;
}
/* 删除节点, 需要在父节点中删除相应入口
**
** 如果目录非空,不可删除
**
** 删除单个文件
**
** 目录删除可以在上层实现
*/
int fslite_inode_deletefile(fslite_inode *p)
{
atomic_t self;
atomic_t n, child, lastb;
int offset;
char *start, *end;
if(p == NULL)
return FSLITE_ERR;
if( p->type == FSLITE_DIR && p->nentry != 0)
return FSLITE_ERR;
self=FSLITE_BLOCKNUMBER(p);
if( p->parentblock == self) // root node can’t del
return FSLITE_ERR;
fslite_spin_lock(&p->lock);
/*释放文件数据占用的页面*/
if( p->type == FSLITE_FILE && p->nentry != 0 )
{
n = self;
lastb = n;
offset = FSLITE_SIZEOFINODE;
while(1)
{
start = (unsigned char * ) FSLITE_BLOCKADDR(n) + offset;
if(n == p->entry_endblock) // 最后一块
end = (unsigned char * ) FSLITE_BLOCKADDR(n) + p->entry_endblock_offset;
else
end = (unsigned char * ) FSLITE_BLOCKADDR(n) + FSLITE_BLOCKSIZE – FSLITE_SIZEOFENTRY;
while(1)
{
child = *(atomic_t*) start;
if(child)
fslite_block_free(child);
if(start==end) break;
start += FSLITE_SIZEOFENTRY;
}
// 如果刚刚处理的block是最后一个,则退出
if( n == p->entry_endblock){
if(n != self) // 不能多次释放同一个block,很危险^_^,那样的话freeblock list会存在回路
fslite_block_free(n);
break;
}
lastb = n;
// end指向的是 metablock索引 前的一个有效entry入口,所以要后移FSLITE_SIZEOFENTRY获得metablock索引
n = FSLITE_NEXTBLOCK(lastb);
offset = FSLITE_SIZEOFENTRY;
if(lastb != self)
fslite_block_free(lastb);
}
}
fslite_spin_unlock(&p->lock);
/* 在父目录中找到此项删除之*/
fslite_inode_delentry(self, FSLITE_INODEADDR(p->parentblock));
fslite_block_free(self);
return FSLITE_OK;
}
/* 从节点p中查找是否含有子项name
** 返回该子项的node指针,否则返回NULL
*/
fslite_inode * fslite_inode_findentry(char *name, fslite_inode *p)
{
atomic_t n;
unsigned char * start, *end;
int offset;
fslite_inode * child;
// 没有考虑 链接 link 的情况
if( p->type != FSLITE_DIR)
return NULL;
if( p->nentry == 0)
return NULL;
n = FSLITE_BLOCKNUMBER(p);
offset = FSLITE_SIZEOFINODE;
while(1)
{
start = (unsigned char * ) FSLITE_BLOCKADDR(n) + offset;
if(n == p->entry_endblock) // 最后一块
end = (unsigned char * ) FSLITE_BLOCKADDR(n) + p->entry_endblock_offset;
else
end = (unsigned char * ) FSLITE_BLOCKADDR(n) + FSLITE_BLOCKSIZE – FSLITE_SIZEOFENTRY;
while(1)
{
child = FSLITE_INODEADDR(*(atomic_t*) start);
/* 这里实现的方法是通过字符串比较,实际上可以先比较name的hash,速度应该更快 */
if(strcmp(child->name, name)==0)
return child;
// 处理完毕允许start==end,因为此时指向的也是有效元素,需要先进行处理
if(start==end) break;
start += FSLITE_SIZEOFENTRY;
}
// 如果刚刚处理的block是最后一个,则退出
if( n == p->entry_endblock)
break;
// end指向的是 metablock索引 前的一个有效entry入口,所以要后移FSLITE_SIZEOFENTRY获得metablock索引
n = FSLITE_NEXTBLOCK(n);
offset = FSLITE_SIZEOFENTRY;
}
return NULL;
}
/* name是相对路径,在节点parent下面查找name是否存在。
** 如果name存在,则返回本文件的对应的节点
** 如果parent不是目录或者是空目录,返回null
** 如果name为空,或者是绝对路径,则返回null
*/
fslite_inode *fslite_inode_findfile_relative(char *name, fslite_inode *parent)
{
char *p, *p1;
fslite_inode * node;
char buf[FSLITE_MAX_NAME_LEN+1];
if(parent == NULL || parent->type != FSLITE_DIR || parent->nentry == 0)
return NULL;
if(strcmp(name, “”)==0)
return NULL;
// 绝对路径
if(strncmp(name, FSLITE_SEPARATOR, strlen(FSLITE_SEPARATOR))==0)
return NULL;
p = name;
node = parent;
while(*p != 0)
{
memset(buf, 0, FSLITE_MAX_NAME_LEN+1);
p1 = strstr(p, FSLITE_SEPARATOR);
if(p1)
{
// 名字过长
if(p1 – p > FSLITE_MAX_NAME_LEN)
return NULL;
strncpy(buf, p, p1 – p);
p = p1 + 1;
}else
{
if(strlen(p) > FSLITE_MAX_NAME_LEN )
return NULL;
strcpy(buf, p);
p += strlen(p); // 将p指到字符串最后,结束循环
}
//printf(”%s\n”, buf);
// 在node下面查找 buf 子项
if((node=fslite_inode_findentry(buf, node)) == NULL)
return NULL;
}
return node;
}
/* fn 是绝对路径
** 如果fn存在,则返回本文件的对应的节点
** 如果fn不是绝对路径,返回null
** 如果fn是 “/”,则返回根节点
*/
fslite_inode *fslite_inode_findfile(char *name)
{
// 不是绝对路径
if(strncmp(name, FSLITE_SEPARATOR, strlen(FSLITE_SEPARATOR)))
return NULL;
if(strcmp(name, FSLITE_SEPARATOR)==0) // ‘/’
return root;
return fslite_inode_findfile_relative(name+1, root);
}
/* inode为一个文件, 从buf中读取,写入blocksize个字节到文件p位置offset处
** 如果不能分配新页面,空间不足,会尽力而为,复制到哪里算哪里
*/
int fslite_inode_write(void *buf, msize_t blocksize, loff_t offset, fslite_inode *p)
{
atomic_t startentry, endentry, n;
int startentry_offset, endentry_offset;
atomic_t ientry;
atomic_t old_nentry;
int windowstart, windowlen;
msize_t remainlen;
unsigned char * start;
if(offset p->size)
return FSLITE_ERR;
// 要写入的位置,第b个entry,块内偏移o
startentry = offset / FSLITE_BLOCKSIZE;
startentry_offset = offset % FSLITE_BLOCKSIZE;
// 写结束位置
endentry = (blocksize + offset) / FSLITE_BLOCKSIZE;
endentry_offset = (blocksize + offset) % FSLITE_BLOCKSIZE;
windowstart = startentry_offset;
windowlen = FSLITE_BLOCKSIZE – windowstart;
remainlen = blocksize;
old_nentry = p->nentry;
/* 特殊一定可以包含于一般之中,普遍地代码是适应的
** 只不过需要处理一下例外的情况,多几个if
*/
for(ientry=startentry; ientry = p->nentry )
{
n = fslite_block_get();
if(n = old_nentry )
p->size += remainlen;
memcpy(start, (unsigned char *)buf + blocksize – remainlen, remainlen);
break;
}
if(ientry >= old_nentry )
p->size += windowlen;
memcpy(start, (unsigned char *)buf + blocksize -remainlen, windowlen);
remainlen -= windowlen;
windowlen = FSLITE_BLOCKSIZE;
windowstart = 0;
}
return FSLITE_OK;
}
/* 从文件p 的位置offset开始读 blocksize大小一块数据到buf中
**
*/
int fslite_inode_read(void *buf, msize_t blocksize, loff_t offset, fslite_inode *p)
{
atomic_t startentry, endentry;
int startentry_offset, endentry_offset;
atomic_t ientry;
int windowstart, windowlen;
msize_t remainlen;
unsigned char * start;
if(offset p->size)
offset = p->size;
startentry = offset / FSLITE_BLOCKSIZE;
startentry_offset = offset % FSLITE_BLOCKSIZE;
endentry = (blocksize + offset) / FSLITE_BLOCKSIZE;
endentry_offset = (blocksize + offset) % FSLITE_BLOCKSIZE;
windowstart = startentry_offset;
windowlen = FSLITE_BLOCKSIZE – windowstart;
remainlen = blocksize;
for(ientry=startentry; ientry = FSLITE_MAX_OPENFILES)
{
printf(”ERR: you can’t open too much file together\n”);
return NULL;
}
// 文件如果不存在,就建立一个,但是父目录应该存在
if(strcmp(mode, “wb+”)==0)
{
sp = strrchr(name, FSLITE_SEPARATOR[0]);
if(sp == name)
p = root;
else
{
//path过长
if(sp -name > FSLITE_MAX_PATH_LEN )
return NULL;
memset(path, 0, FSLITE_MAX_PATH_LEN+1);
strncpy(path, name, sp-name);
printf(”path: %s file: %s\n”, path, sp+1);
p = fslite_inode_findfile(path);
}
if(p==NULL) //上级目录不存在
return NULL;
p = fslite_inode_createfile(sp+1, p, FSLITE_FILE);
if(p==NULL) // 创建失败
return NULL;
}else{
// wb , rb读模式,如果文件不存在则返回
if( (p=fslite_inode_findfile(name)) == NULL)
return NULL;
if(p->type!=FSLITE_FILE)
return NULL;
}
fp= &files[++nopenfiles];
fp->fd = nopenfiles;
fp->sb = sb;
fp->inode = p;
if(strcmp(mode, “rb”)==0)
{
fp->fp = 0;
fp->mode = FSLITE_FOPEN_R;
}
else
{ // wb wb+,写入
fp->fp = p->size;
fp->mode = FSLITE_FOPEN_RW;
}
return fp;
}
/*往fp中写入n个块,每块大小为blocksize*/
msize_t fslite_fwrite(void * buf, msize_t blocksize, msize_t n, fslite_file *fp)
{
int i;
if(fp==NULL)
return 0;
if(fp->mode==FSLITE_FOPEN_R)
return 0;
for(i=0; i fp, fp->inode) != FSLITE_OK)
break;
fp->fp +=blocksize;
}
return i;
}
/*往buf中读入n个块,每块大小为blocksize*/
msize_t fslite_fread(void * buf, msize_t blocksize, msize_t n, fslite_file *fp)
{
int i;
if(fp==NULL)
return 0;
for(i=0; i fp, fp->inode);
if(fp->fp >= fp->inode->size)
{
fp->fp = fp->inode->size;
break;
}
fp->fp +=blocksize;
}
return i;
}
int fslite_rewind(fslite_file *fp)
{
fp->fp = 0;
return FSLITE_OK;
}
int fslite_feof(fslite_file *fp)
{
if(fp->fp >= fp->inode->size)
return 1;
else
return 0;
}
int fslite_fclose(fslite_file *fp)
{
if(nopenfiles > 0)
nopenfiles — ;
return FSLITE_OK;
}
int fslite_fseek(fslite_file *fp, loff_t offset, int where)
{
if(where == FSLITE_SEEK_CUR)
{
fp->fp += offset;
}
if(where == FSLITE_SEEK_SET)
{
fp->fp = offset;
}
if(where == FSLITE_SEEK_END)
{
fp->fp = fp->inode->size + offset;
}
if(fp->fp fp=0;
if(fp->fp > fp->inode->size)
fp->fp=fp->inode->size;
return FSLITE_OK;
}
loff_t fslite_ftell(fslite_file *fp)
{
if(fp==NULL)
return 0;
else
return fp->fp;
}
fslite_dir * fslite_opendir(char *name)
{
fslite_inode *p;
fslite_dir *dp;
// 达到上限
if(nopendirs >= FSLITE_MAX_OPENDIRS)
{
printf(”ERR: you can’t open too much dir together\n”);
return NULL;
}
if( (p=fslite_inode_findfile(name)) == NULL)
return NULL;
if(p->type!=FSLITE_DIR)
return NULL;
dp = &dirs[nopendirs++];
//dp->fd = nopenfiles;
dp->sb = sb;
dp->inode = p;
dp->dp = 0;
return dp;
}
int fslite_closedir(fslite_dir *p)
{
if(nopendirs > 0)
nopendirs — ;
return FSLITE_OK;
}
char *fslite_readdir(fslite_dir *p)
{
fslite_inode *n;
if(p->dp
inode->nentry){
n = FSLITE_INODEADDR(fslite_inode_getentry(p->dp, p->inode));
p->dp++;
return n->name;
}
return NULL;
}
int fslite_rewinddir(fslite_dir *p)
{
p->dp = 0;
return FSLITE_OK;
}
int fslite_mkdir(char *name)
{
fslite_inode *p;
char * sp;
char path[FSLITE_MAX_PATH_LEN+1];
// 不是绝对路径
if(strncmp(name, FSLITE_SEPARATOR, strlen(FSLITE_SEPARATOR)))
return FSLITE_ERR;
sp = strrchr(name, FSLITE_SEPARATOR[0]);
if(sp == name)
p = root;
else
{
//path过长
if(sp -name > FSLITE_MAX_PATH_LEN )
return FSLITE_ERR;
memset(path, 0, FSLITE_MAX_PATH_LEN+1);
strncpy(path, name, sp-name);
printf(”path: %s file: %s\n”, path, sp+1);
p = fslite_inode_findfile(path);
}
if(p==NULL) //上级目录不存在
return FSLITE_ERR;
if(fslite_inode_createfile(sp+1, p, FSLITE_DIR)==NULL)
return FSLITE_ERR;
else
return FSLITE_OK;
}
/* main ***************************************************************
*/
main()
{
FILE *fp;
fslite_inode *p;
fslite_file *f;
fslite_dir *d;
char *n;
char *s=”/test/b/hello/world/this/is/a/what/are/you/doing”;
char *test=”This is the first text of the first file in the first fslite file system\nnkchenz@gmail.com”;
char buf[256];
fslite_fs_init();
fslite_mkdir(”/hello”);
fslite_mkdir(”/hello/1″);
fslite_mkdir(”/hello/2″);
fslite_mkdir(”/hello/3″);
d=fslite_opendir(”/hello”);
while(1)
{
n=fslite_readdir(d);
if(n==NULL) break;
printf(” %s\n”, n);
}
fslite_closedir(d);
if((f=fslite_fopen(”/test”, “wb+”))==NULL)
{
printf(”err\n”);
}
else{
printf(”ok\n”);
fslite_fwrite(test, strlen(test), 1, f);
fslite_fwrite(s, strlen(s), 1, f);
fslite_rewind(f);
fslite_fread(buf, 256, 1, f);
printf(”%s\n”, buf);
if(fslite_feof(f))
printf(”feof\n”);
fslite_fclose(f);
fslite_fdelete(”/test”);
}
/*
if(fslite_inode_createfile(”hello”, root, FSLITE_DIR))
printf(”CREATE: /hello\n”);
if(p=fslite_inode_createfile(”test”, root, FSLITE_FILE))
printf(”CREATE: /test\n”);
if(p2=fslite_inode_createfile(”test2″, root, FSLITE_DIR))
printf(”CREATE: /test2\n”);
if(fslite_inode_deletefile(p)!=FSLITE_OK)
printf(”del err”);
else
printf(”del ok”);
if(fslite_inode_deletefile(p2)!=FSLITE_OK)
printf(”del err”);
else
printf(”del ok”);
p=fslite_inode_findfile(”/hello”);
if(fslite_inode_createfile(”world”, p, FSLITE_DIR))
printf(”CREATE: /hello/world\n”);
*/
s=”/hello”;
if( (p=fslite_inode_findfile(s)) == NULL )
printf(”Not Found: %s \n”, s);
else
printf(”Found: %s \n”, s);
/*测试代码, 将文件系统映象输出到文件*/
fp=fopen(”fslite.img”, “wb+”);
fwrite(fslite_data, FSLITE_TOTAL_BLOCKS * FSLITE_BLOCKSIZE, 1, fp);
fclose(fp);
printf(”blocks: %d/%d root: %d first_freeblock:%d\n”, sb->used_blocks, sb->free_blocks, sb->root_block, sb->first_freeblock);
}

