代码备份

/* * Note. 根据一个block号可以计算出他所表示的地址来,这就行了。 */ #ifndef _SIMULFS_OBJECTS_H_ #define _SIMULFS_OBJECTS_H_ #include "simulfs_marcos.h" typedef struct _simulfs_Dev { __u32 devId:4; int devTags; // 仅仅是一个标记而已,有待扩充,可以用配置文件扩充,其实就是一块内存 simulfs_Block* blockChain; // 该设备中所有的block队列 simulfs_CheckPoint dev_cp; }simulfs_Dev; typedef struct _simulfs_Block { __u32 devId:4; __u32 blockId:16; // 块号 simulfs_BlockState currentState; // 块当前状态 __u32 nextChunkId:12; // 块内当前可以分配的页号 simulfs_Chunk* chunkChain; // 该block中所有chunk的链表s } simulfs_Block; typedef struct _simulfs_Chunk { __u32 devId:4; __u32 blockId:16; // 所属块号 __u32 chunkId:12; // 页号 /* 下面几个属性是在上层中被改写的 */ __u32 objectId:10; // 该页内存储的对象号 __u32 chunIdinObj:12; // 该chunk在对象内的表示 __u32 offset:10; // 该页共存储了多少比特,这个很重要,不论是那个chunk在文件中,只要偏移是0,就表示这个块已经不用了 // 所以一般应该先检查偏移 __u8 isDirty:1; // 是否是脏页?需要回写 __u8 needEarse:1; // 是否是新页?一点东西都没有 __u32 lowestLevelWriteNextChunk:12; // 底层写的时候下一个分配的块,没有下一个的时候就是 // }simulfs_Chunk; typedef enum _simulfs_ECCResult { SIMULFS_ECC_RESULT_UNKNOWN, SIMULFS_ECC_RESULT_NO_ERROR, SIMULFS_ECC_RESULT_FIXED, SIMULFS_ECC_RESULT_UNFIXED } simulfs_ECCResult; typedef enum _simulfs_ObjectType { SIMULFS_OBJECT_TYPE_UNKNOWN, SIMULFS_OBJECT_TYPE_FILE, SIMULFS_OBJECT_TYPE_SYMLINK, SIMULFS_OBJECT_TYPE_DIRECTORY, SIMULFS_OBJECT_TYPE_HARDLINK, SIMULFS_OBJECT_TYPE_SPECIAL } simulfs_ObjectType; /* * 块状态有个状态转换图,可以借鉴一下 */ typedef enum _simulfs_BlockState { SIMULFS_BLOCK_STATE_UNKNOWN = 0, SIMULFS_BLOCK_STATE_SCANNING, SIMULFS_BLOCK_STATE_NEEDS_SCANNING, /* The block might have something on it (ie it is allocating or full, perhaps empty) * but it needs to be scanned to determine its true state. * This state is only valid during yaffs_Scan. * NB We tolerate empty because the pre-scanner might be incapable of deciding * However, if this state is returned on a YAFFS2 device, then we expect a sequence number */ SIMULFS_BLOCK_STATE_EMPTY, /* This block is empty */ SIMULFS_BLOCK_STATE_ALLOCATING, /* This block is partially allocated. * At least one page holds valid data. * This is the one currently being used for page * allocation. Should never be more than one of these */ SIMULFS_BLOCK_STATE_FULL, /* All the pages in this block have been allocated. */ SIMULFS_BLOCK_STATE_DIRTY, /* All pages have been allocated and deleted. * Erase me, reuse me. */ SIMULFS_BLOCK_STATE_CHECKPOINT, /* This block is assigned to holding checkpoint data. */ SIMULFS_BLOCK_STATE_COLLECTING, /* This block is being garbage collected */ SIMULFS_BLOCK_STATE_DEAD /* This block has failed and is not in use */ } simulfs_BlockState; /* typedef struct _simulfs_CheckPoint{ simulfs_MixedId checkIds; // 检查点把当前页面地址传过来 }simulfs_CheckPoint; */ /* * 这里是ID的整合,即:设备ID,blockId,chunkId,来确定一个地址 * Note. 位数都比可能用到的要多,便于以后扩展 */ typedef struct _simulfs_MixedId { __u32 devId:4; __u32 blockId:16; // 所属块号 __u32 chunkId:12; // 页号 }simulfs_MixedId; /* * 这是一个检查点,检查点也是地址,就用chunk做地址行吗? * 否则怎么找到这个结点唉?? */ typedef simulfs_MixedId simulfs_CheckPoint; /* * 文件系统初始化,形成文件系统内存分配格局 */ int simulfs_mount(void* Space_ROOT); simulfs_MixedId simulfs_AllocBlock(simulfs_Dev* myDev); // 扫描寻找一个新块 simulfs_MixedId simulfs_AllocChunk(simulfs_Dev* myDev); int simulfs_PortChunk(simulfs_Dev* myDev, const simulfs_MixedId Ids); // 怎样通过bId和cId索引该chunk?? int simulfs_ScanningBlock(void); int simulfs_EarseBlock(simulfs_Block blk); int simulfs_GarbageCollection(simulfs_Dev* myDev); int simulfs_WritePerChunk(simulfs_Dev* myDev, void* buf, __u32 size); int simulfs_Write(simulfs_Dev* myDev, void* buf, __u32 size); int simulfs_ReadPerChunk(simulfs_Dev* myDev, simulfs_MixedId thisChunk, void* buf, __u32 size); int simulfs_Read(simulfs_Dev* myDev, void* buf, __u32 size); /* * Id 和 地址 之间相互转换的函数,写成宏比较好。 * Id号神马的都是从零开始的。 * such as: * devId = 0; * blockId = 0; * chunkId = 3; * * point = 3*512; */ __inline__ void* simulfs_IdtoPoint(simulfs_MixedId suchId) { void* resPoint = 0; resPoint += suchId.devId*SIMULFS_MAX_DEV_SIZE + suchId.blockId*SIMULFS_CHUNKS_PER_BLOCK + suchId.chunkId*SIMULFS_BYTES_PER_CHUNK + SIMULFS_DATA_OFFSET; return resPoint; } __inline__ simulfs_MixedId simulfs_PointtoId(void* point) { simulfs_MixedId resMixedId; resMixedId.devId = point/SIMULFS_MAX_DEV_SIZE; resMixedId.blockId = ((point%SIMULFS_MAX_DEV_SIZE)-SIMULFS_DATA_OFFSET)/SIMULFS_BYTES_PER_BLOCK; resMixedId.chunkId = ((point%SIMULFS_MAX_DEV_SIZE)-SIMULFS_DATA_OFFSET)%SIMULFS_BYTES_PER_BLOCK; return resMixedId; } __inline__ void SetMixedIdInvailed(simulfs_MixedId* myId) { myId->blockId = SIMULFS_UNUSED_BLOCK_ID; myId->chunkId = SIMULFS_UNUSED_CHUNK_ID; myId->devId = SIMULFS_UNUSED_DEV_ID; } /* * return * 0 Id is valid * 1 Id's DEV Id is invalid * 2 Id's BLOCK Id is invalid * 3 Id's CHUNK Id is invalid */ __inline__ int IsMixedIdInvailed(simulfs_MixedId myId) { if(myId.blockId == SIMULFS_UNUSED_BLOCK_ID) return 2; if(myId.chunkId == SIMULFS_UNUSED_CHUNK_ID) return 3; if(myId.devId == SIMULFS_UNUSED_DEV_ID) return 1; return 0; } #endif //_SIMULFS_OBJECTS_H_  

 

#include "simulfs_objects.h" #include <sys/mman.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> /* * This is the first function of simulfs, we use it to build a formatted * RAM memory structure. */ simulfs_Dev ControlInformationInitilization(void) { int i = 0, j = 0; simulfs_Dev myDev; // I am on this device now myDev.devId = 0; myDev.devTags = 0; myDev.dev_cp.blockId = 0; myDev.dev_cp.chunkId = 0; myDev.dev_cp.devId = myDev.devId; /* * 整个DEV信息的空间申请以及初始化。 * 如果没有指定,就是这种方式生成。 * 如果指定了,就按照原有的方式不变或者按照指定的方式生成 * 这个RAM信息最终是要放到flash中 */ myDev.blockChain = (simulfs_Block*)calloc(SIMULFS_MAX_BLOCK_COUNT,sizeof(simulfs_Block)); for(i=0; i<=SIMULFS_MAX_BLOCK_ID; ++i) { myDev.blockChain[i]->blockId = i; myDev.blockChain[i]->chunkId = 0; myDev.blockChain[i]->currentState = SIMULFS_BLOCK_STATE_EMPTY; myDev.blockChain[i]->chunkChain = (simulfs_Chunk*)calloc(SIMULFS_MAX_CHUNK_COUNT,sizeof(simulfs_Chunk)); for(j=0; j<=SIMULFS_MAX_CHUNK_ID; ++j) { myDev.blockChain[i]->chunkChain[j]->blockId = myDev.blockChain[i].blockId; myDev.blockChain[i]->chunkChain[j]->chunkId = j; myDev.blockChain[i]->chunkChain[j]->isDirty = 0; myDev.blockChain[i]->chunkChain[j]->needEarse = 0; myDev.blockChain[i]->chunkChain[j]->objectId = SIMULFS_UNUSED_OBJECT_ID; myDev.blockChain[i]->chunkChain[j]->offset = 0; } } return myDev; } /* * It is just like mount command in Linux. * I can use a shell to wrapper it later. */ int simulfs_mount(void* Space_ROOT) { /* * 0. 读取配置文件 打开相应的映射文件 */ int config_fd = open("simulfs.config", O_READ); int mem_fd = open("simulfs.testMemory",O_RDWR | O_CERATE, 00700); if(mem_fd == -1) perror("open Memory File failed! Please check your system./n"); exit(1); /* * 1. 申请内存空间 */ // mmap Space_ROOT = mmap(NULL,SIMULFS_BYTES_INITIAL,PROT_READ | PORT_WRITE, MAP_SHARED,mem_fd,0); /* * 2. 初始化顶部控制区 */ // 无配置文件,查看第一个bit,0 ==》直接运行0填充; 1 ==》 不改动原内存映射。 if(config_fd == -1) { bzero(Space_ROOT, SIMULFS_BYTES_INITIAL); simulfs_Dev myDev = ControlInformationInitilization(); } else { // 有配置文件,直接按配置文件决定初始化方式。 } /* * 3. 读取文件系统顶部的控制数据到内存,决定文件分配等信息 */ } /* * Similar, unmount here * Note. 写回我们的数据 * 释放分配的空间 */ int simulfs_unmount() { } /* * This function is used to Allocate a new chunk for an object. * If success , return the Ids. * */ simulfs_MixedId simulfs_AllocChunk(simulfs_Dev* myDev) { simulfs_MixedId resIds = SIMULFS_FAIL; // 如果chunk达到最大值,在这里设置块的信息 if(myDev->dev_cp.chunkId == SIMULFS_MAX_CHUNK_ID) { myDev->blockChain[myDev->dev_cp.blockId]->currentState = SIMULFS_BLOCK_STATE_FULL; if(simulfs_AllocBlock(myDev) == SIMULFS_FAIL) { return SIMULFS_FAIL; // 如果没有新的block可以分配了,就返回错误,没有空间了。 } } /* * Note. Chunk地址的计算方式要注意 */ resIds.blockId = (*myDev).dev_cp.blockId; resIds.chunkId = ++(*myDev).dev_cp.chunkId; resIds.devId = (*myDev).dev_cp.devId; return resIds; } /* * This function is used to searching a new block to use. * If search failed, call garbage collection return a new one. * If failed, failed too. * Note. checkpoint will be changed, attention! */ simulfs_MixedId simulfs_AllocBlock(simulfs_Dev* myDev) { int i = (*myDev).dev_cp.blockId; int j = i; /* * Note. 搜索的时候先向后搜,后向前搜 */ for(i; i<SIMULFS_MAX_BLOCK_COUNT; ++i) { if((*myDev).blockChain[i]->currentState == SIMULFS_BLOCK_STATE_EMPTY) { (*myDev).dev_cp.blockId = i; myDev->dev_cp.chunkId = 0; return SIMULFS_OK; } } for(i=0; i<j; ++i) { if((*myDev).blockChain[i]->currentState == SIMULFS_BLOCK_STATE_EMPTY) { (*myDev).dev_cp.blockId = i; myDev->dev_cp.chunkId = 0; return SIMULFS_OK; } } // 上两步都搜不到合适的块,那就调用垃圾回收器 if(simulfs_GarbageCollection(myDev) == SIMULFS_FAIL) return SIMULFS_FAIL; return SIMULFS_OK; } /* * This function is used to collecting garbage, free some block to use. * I ignored the efficiency. ^_^, it is just a simula file system. */ int simulfs_GarbageCollection(simulfs_Dev* myDev) { int i=0; for(i; i<SIMULFS_MAX_BLOCK_COUNT; ++i) { if(myDev->blockChain[i]->currentState == SIMULFS_BLOCK_STATE_DIRTY) { // do garbage collection simulfs_MixedId Ids; Ids.blockId = myDev->blockChain[i]->blockId; Ids.chunkId = 0; Ids.devId = myDev.devId; simulfs_EarseBlock(myDev, Ids); myDev->dev_cp.blockId = i; myDev->dev_cp.chunkId = 0; } return SIMULFS_OK; } return SIMULFS_FAIL; } /* * This function is used to scanning all blocks and set some values. * I don't whether it goes well or not, but I really need it. * But now , it just used for setting flag --->> * SIMULFS_BLOCK_STATE_DIRTY */ int DEV_Scanning(simulfs_Dev* myDev) { int i=0,j=0; int sum = 0; for(i; i<SIMULFS_MAX_BLOCK_COUNT; ++i) { sum = 0; for(j; j<SIMULFS_MAX_CHUNK_COUNT; ++j) { sum += myDev->blockChain[i]->chunkChain[j]->needEarse; } if(sum == SIMULFS_MAX_CHUNK_COUNT) myDev->blockChain[i]->currentState = SIMULFS_BLOCK_STATE_DIRTY; } } /* * This function is used to port data of a chunk to another. * Of course, they are on the different blocks. */ int simulfs_PortChunk(simulfs_Dev* myDev, const simulfs_MixedId Ids) { if(simulfs_AllocChunk(myDev) == SIMULFS_FAIL) return SIMULFS_FAIL; // 通过这个函数,当前的检查点中存的已经是新申请到的chunk了。 // 下面的内容是chunk之间的数据转移 memcpy(simulfs_IdtoPoint(myDev->dev_cp), simulfs_IdtoPoint(Ids), SIMULFS_BYTES_PER_CHUNK); // 原chunk设置 myDev->blockChain[myDev->dev_cp.blockId]-> chunkChain[myDev->dev_cp.chunkId]->needEarse = 1; // 检查点更新 if(myDev->dev_cp.chunkId == SIMULFS_MAX_CHUNK_ID) { myDev->blockChain[myDev->dev_cp.blockId]->currentState = SIMULFS_BLOCK_STATE_FULL; simulfs_AllocBlock(myDev); // 分配新块,分完后cp已经是设置好的了。 } else { myDev->dev_cp.chunkId++; } } /* * This function is used to erase a block * @param: * simulfs_MixedId to implicitly store address */ int simulfs_EarseBlock(simulfs_Dev* myDev, simulfs_MixedId blk) { // 1. 清除空间 void* point = simulfs_IdtoPoint(blk); bzero(point,SIMULFS_BYTES_PER_BLOCK); // 2. 设置相关值 myDev->blockChain[blk.blockId]->currentState = SIMULFS_BLOCK_STATE_EMPTY; myDev->blockChain[blk.blockId]->nextChunkId = 0; int i=0; for(i=0; i<SIMULFS_CHUNKS_PER_BLOCK; ++i) { myDev->blockChain[blk.blockId]->chunkChain[i]->isDirty = 0; myDev->blockChain[blk.blockId]->chunkChain[i]->needEarse = 0; myDev->blockChain[blk.blockId]->chunkChain[i]->objectId = SIMULFS_UNUSED_OBJECT_ID; myDev->blockChain[blk.blockId]->chunkChain[i]->offset = 0; } return SIMULFS_OK; } /* * This function is used to set chunk-info, * Now just used in the above function. */ void SetChunkAttrAfterWrite(simulfs_Dev* myDev, simulfs_MixedId chkIds, __u32 offset) { myDev->blockChain[chkIds.blockId]->chunkChain[chkIds.chunkId]->isDirty = 1; myDev->blockChain[chkIds.blockId]->chunkChain[chkIds.chunkId]->offset = offset; /* * ObjectID 由高层函数来管理,暂时不知到这个项目填什么。 */ //myDev->blockChain[chkIds.blockId]->chunkChain[chkIds.chunkId]->objectId = ??? } /* * 更新ckp,可能会有很多函数用到 * 返回值为旧的ckp * 传入值为新的ckp */ simulfs_MixedId ResetCheckPoint(simulfs_Dev* myDev, simulfs_MixedId newChkPoint) { myDev->dev_cp.blockId = newChkPoint.blockId; myDev->dev_cp.chunkId = newChkPoint.chunkId; myDev->dev_cp.devId = newChkPoint.devId; } void SetNextLowestLevelWriteChunk(simulfs_Dev* myDev, simulfs_MixedId newChkPoint) { myDev->blockChain[myDev->dev_cp.blockId]-> chunkChain[myDev->dev_cp.chunkId]->lowestLevelWriteNextChunk = chkIds; } // 该函数设置下一个无用。唉~这里就能看出OOB的好处了,但是这里用的还是面向过程的语言 void SetNextLowestLevelWriteChunkZero(simulfs_Dev* myDev) { simulfs_MixedId zeroChunk; /* * 其他的不用管了,只要这个devId不合法,就判断出来了。 */ zeroChunk.devId = SIMULFS_UNUSED_DEV_ID; myDev->blockChain[myDev->dev_cp.blockId]-> chunkChain[myDev->dev_cp.chunkId]->lowestLevelWriteNextChunk = zeroChunk; } /* * --------------------------------------------------------------------------------------------------------- * -------------------An array functions of write----------------------------------------------------------- */ /* * This function is used to write data in the lowest mode. * Every other like-write function call this one. * If a chunk is not enough, it will call for a new one. * Note. 相应的数据结构会被修改 * 默认情况下是只开放下一个函数的,这个函数是系统使用的。 * 这里只用普通链表的方法链接吧,在高层的函数中就会有二叉树的链接方式了。 */ int WriteLowestLevelPerChunk(simulfs_Dev* myDev, simulfs_MixedId chkIds, void* buf, __u32 size) { // 相当于重新设置checkpoint,不推荐直接使用。 ResetCheckPoint(myDev, chkIds); // 转换地址 void* dest = simulfs_IdtoPoint(chkIds); memcpy(dest,buf,size<SIMULFS_BYTES_PER_CHUNK?size:SIMULFS_BYTES_PER_CHUNK); SetChunkAttrAfterWrite(myDev, chukIds,size<SIMULFS_BYTES_PER_CHUNK?size:SIMULFS_BYTES_PER_CHUNK); SetNextLowestLevelWriteChunkZero(myDev); /* * 为什么这里不用重新设置ckp了?因为我的ckp代表的是当前正写着东西的那一页,上面已经修改过了,所以这里不用修改了。 */ } int simulfs_WritePerChunk(simulfs_Dev* myDev, void* buf, __u32 size) { return WriteLowestLevelPerChunk(myDev, myDev->dev_cp,buf,size); } // 这个函数在高层可能没有必要 int WriteLowestLevel(simulfs_Dev* myDev, simulfs_MixedId chkIds, void* buf, __u32 size) { // 转换地址 void* dest = simulfs_IdtoPoint(chkIds); // 直接写开始 int i=0; do { ResetCheckPoint(myDev, chkIds); if(size > SIMULFS_BYTES_PER_CHUNK) { memcpy(dest+i*SIMULFS_BYTES_PER_CHUNK, buf+i*SIMULFS_BYTES_PER_CHUNK, SIMULFS_BYTES_PER_CHUNK); // 设置相应的chunk信息 SetChunkAttrAfterWrite(myDev, chukIds, SIMULFS_BYTES_PER_CHUNK); // 该chunk使用完毕 申请一个新的chunk if((chkIds = simulfs_AllocChunk(myDev)) == SIMULFS_FAIL) { // 分配失败 perror("Error occur, AllocChunk failed!" "in function simulfs_AllocChunk()" "in function WriteLowestLevel()."); } else { // 分配新的chunk成功 SetNextLowestLevelWriteChunk(myDev, chkIds); dest = simulfs_IdtoPoint(chkIds); } } else { memcpy(dest+i*SIMULFS_BYTES_PER_CHUNK, buf+i*SIMULFS_BYTES_PER_CHUNK, size); // 设置相应的chunk信息 SetChunkAttrAfterWrite(myDev, chukIds, size); SetNextLowestLevelWriteChunkZero(myDev); break; } size -= SIMULFS_BYTES_PER_CHUNK; ++i; }while(1); return SIMULFS_OK; } int simulfs_Write(simulfs_Dev* myDev, void* buf, __u32 size) { return WriteLowestLevel(myDev, myDev->dev_cp,buf,size); } /* * --------------------------------------------------------------------------------------------------------- * -------------------An array functions of read----------------------------------------------------------- */ /* * This is the READ function in the lowest level,like the above function. * The buffer should be calloced in user's application, not in me. * Note. 底层的读函数不同于写函数,只能按chunk读,没有ObjectID,东西是连不在一起的。只能根据chunk中的链表查找 * 为什么高层函数会比底层函数块呢??囧啊~ * 读的时候注意检查size是否在合适的范围内,否则拒绝返回 */ // 用户自己要保证传入的缓冲内存是够大的,否则会溢出 int ReadLowestLevelPerChunk(simulfs_Dev* myDev, simulfs_MixedId thisChunk, void* buf, __u32 size) { // 1. 判断size大小是否合适 if(myDev->blockChain[thisChunk.blockId]->chunkChain[thisChunk.chunkId]->offset >= size) { const void* src = simulfs_IdtoPoint(thisChunk); memcpy(buf, src, size); return SIMULFS_OK; } else { perror("Size are ambition, I think you should change a function, such as simulfs_Read" "Error occur in simulfs_ReadPerChunk()" "in ReadLowestLevelPerChunk()"); return SIMULFS_FAIL; } } int simulfs_ReadPerChunk(simulfs_Dev* myDev, simulfs_MixedId thisChunk, void* buf, __u32 size) { return ReadLowestLevelPerChunk(myDev, thisChunk, buf, size); } int ReadLowestLevel(simulfs_Dev* myDev, simulfs_MixedId startChunk, void* buf, __u32 size) { } int simulfs_Read(simulfs_Dev* myDev, void* buf, __u32 size) { return WriteLowestLevel(myDev, buf, size); }  

 

/* * This page is designed to implement a double link. * The structure is used in simulfs_fs.h/.c to implement a * high level object manipulation. * Copyright @ Xusen Yin, Dep. IS, BISTU */ #ifndef _SIMULFS_DLINK_H_ #define _SIMULFS_DLINK_H_ #include "simulfs_objects.h" #include "simulfs_marcos.h" /* * Dir 00000001 0x01 * File 00000010 0x02 * Symlnk 00000100 0x04 * hrdlnk 00001000 0x08 * special 00010000 0x10 * unknow 00100000 0x20 */ typedef struct _similfs_Flags{ __u8 isDir:1; __u8 isFile:1; __u8 isSymlnk:1; __u8 isHrdlnk:1; __u8 isSpecial:1; __u8 isUnknow:1; __u8 alignData:1; // 最后两个数据是用来填充用的 __u8 alignData:1; }similfs_Flags; typedef struct _simulfs_ListNode { void* dataPtr; // 这个可以传入simulfs_FileTree的指针。 int objectNumber; // 如果是目录,记录他的对象个数 similfs_Flags thisFlag; simulfs_MixedId thisId; simulfs_Object obj; struct _simulfs_ListNode* priorSlibing; struct _simulfs_ListNode* nextSlibing; struct _simulfs_ListNode* leftChild; struct _simulfs_ListNode* parent; }simulfs_ListNode,*simulfs_List; /* 下面这个函数可能是用不到的 */ /* int simulfs_CreateList(); */ int simulfs_TraverseList(simulfs_List lst, int (*Visit)(simulfs_List lst)); int simulfs_DestoryList(simulfs_List lst); simulfs_List simulfs_PriorSlibing(simulfs_List lst); simulfs_List simulfs_NextSlibing(simulfs_List lst); simulfs_List simulfs_LeftChild(simulfs_List lst); simulfs_List simulfs_Parent(simulfs_List lst); /* * 在lstLeft下面的结点插入 */ int simulfs_InsertListNodeAfter(simulfs_List lstLeft, simulfs_List lstSrc); /* * 在lstRight之前插入 */ int simulfs_InsertListNodeBefore(simulfs_List lstRight, simulfs_List lstSrc); /* * 在头上插入 */ int simulfs_InsertListNodeonBegin(simulfs_List lstSrc); /* * 在尾部插入 */ int simulfs_InsertListNodeonEnd(simulfs_List lstSrc); int simulfs_DeleteListNode(simulfs_List lst); #endif //_SIMULFS_DLINK_H_  

 

/* * Maybe it will be used later */ #include "simulfs_dlink.h" #include "simulfs_fs.h" #include "simulfs_FileTree.h" /* * Dir 00000001 0x01 * File 00000010 0x02 * Symlnk 00000100 0x04 * hrdlnk 00001000 0x08 * special 00010000 0x10 * unknow 00100000 0x20 */ int VisitAndDestoryAllLinkNode(simulfs_List lst) { if((lst->thisFlag)&(0x01)) { /* * 如果是文件夹的释放,要先释放其下的各个文件夹,然后再释放它自己 */ simulfs_DestoryList(lst->leftChild); } else if((lst->thisFlag)&(0x02)) { /* * 如果是文件,则要调用文件删除函数 */ 啊啊啊啊 FileDelete(lst->dataPtr); // 这里的dataPtr指向的就是Tree Node } else if((lst->thisFlag)&(0x04)) { /* * 如果是软链接,就只是一个字符串,搞掉它!! */ free(((simulfs_SymLinkStructure*)lst->dataPtr)->alias); } else if((lst->thisFlag)&(0x08)) { /* * 如果是硬链接 */ free(((simulfs_HardLinkStructure*)lst->dataPtr)->equivalentObject); } else if((lst->thisFlag)&(0x10)) { /* * 如果是特殊设备,我也不知道怎么办 */ // UnDO. } else if((lst->thisFlag)&(0x20)) { /* * 如果是未知文件 */ //UnDO. } else { } free(lst); } int simulfs_TraverseList(simulfs_List lst, int (*Visit)(simulfs_List lst)) { // 怎么走呢? 先向后走,再向前走 simulfs_List lstTmp = lst->priorSlibing; int res = SIMULFS_OK; while(lst->nextSlibing != NULL) { res = Visit(lst); lst = lst->nextSlibing; } while(lstTmp->priorSlibing != NULL) { res = Visit(lstTmp); lstTmp = lstTmp->priorSlibing; } return res; } /* * 只要给出这条链子的一个点,就能全部删除之,注意中途出现的其他Dir */ int simulfs_DestoryList(simulfs_List lst) { return simulfs_TraverseList(lst, VisitAndDestoryAllLinkNode(lst)); } /* * 返回之前的那个兄弟结点 */ simulfs_List simulfs_PriorSlibing(simulfs_List lst) { return lst->priorSlibing; } simulfs_List simulfs_NextSlibing(simulfs_List lst) { return lst->nextSlibing; } simulfs_List simulfs_LeftChild(simulfs_List lst) { return lst->leftChild; } simulfs_List simulfs_Parent(simulfs_List lst) { return lst->parent; } /* * 在lstLeft后面的结点插入,记得记录目录中对象的个数 */ int simulfs_InsertListNodeAfter(simulfs_List lstLeft, simulfs_List lstSrc) { if(lstSrc == NULL || lstLeft == NULL) { return SIMULFS_FAIL; } lstSrc->parent = lstLeft->parent; if(lstLeft->nextSlibing == NULL) { lstLeft->nextSlibing = lstSrc; lstSrc->priorSlibing = lstLeft; lstSrc->nextSlibing = NULL; } else { lstSrc->priorSlibing = lstLeft; lstSrc->nextSlibing = lstLeft->nextSlibing; lstLeft->nextSlibing->priorSlibing = lstSrc; lstLeft->nextSlibing = lstSrc; } ++lstSrc->parent->objectNumber; return SIMULFS_OK; } /* * 在lstRight之前插入 */ int simulfs_InsertListNodeBefore(simulfs_List lstRight, simulfs_List lstSrc) { if(lstSrc == NULL || lstRight == NULL) { return SIMULFS_FAIL; } lstSrc->parent = lstRight->parent; if(lstRight->priorSlibing == NULL) { lstSrc->nextSlibing = lstRight; lstSrc->priorSlibing = NULL; lstRight->priorSlibing = lstSrc; } else { lstSrc->nextSlibing = lstRight; lstSrc->priorSlibing = lstRight->priorSlibing; lstRight->priorSlibing->nextSlibing = lstSrc; lstRight->priorSlibing = lstSrc; } ++lstSrc->parent->objectNumber; return SIMULFS_OK; } /* * 在头上插入,只要提供这条连上任意一个结点就行 */ int simulfs_InsertListNodeonBegin(simulfs_List lst, simulfs_List lstSrc) { while(lst->priorSlibing != NULL) lst = lst->priorSlibing; return simulfs_InsertListNodeBefore(lst, lstSrc); } /* * 在尾部插入 */ int simulfs_InsertListNodeonEnd(simulfs_List lst, simulfs_List lstSrc) { while(lst->nextSlibing != NULL) lst = lst->nextSlibing; return simulfs_InsertListNodeAfter(lst, lstSrc); } int simulfs_DeleteListNode(simulfs_List lst) { return VisitAndDestoryAllLinkNode(lst); }  

 

#ifndef _SIMULFS_TREE_H_ #define _SIMULFS_TREE_H_ #include "simulfs_marcos.h" #include "simulfs_dlink.h" // 该树是父亲——兄弟树,因为文件夹的存储方式吗^_^ typedef struct _simulfs_CSNode { simulfs_ListNode ln; }simulfs_CSNode, *simulfs_CSTree; int simulfs_InitCSTreeNode(simulfs_CSNode* CSNode); int simulfs_CreateCSTreeNode(simulfs_CSNode** CSNode, similfs_Flags thisFlag); int simulfs_CreateCSTree(simulfs_CSTree* CSTreeROOT); int simulfs_DestoryCSTree(simulfs_CSTree CSTreeROOT); #endif // _SIMULFS_TREE_H_  

 

a/* * This file is used to realize a parent-slibing tree * to record the directory structure. */ #include "simulfs_CSTree.h" #include <stdlib.h> #include "simulfs_objects.h" #include "simulfs_dlink.h" /* * 想要修改CSTreeROOT指向的那个结点,所以要传入他的指针 * 但是估计到我们要生成一个指针,所以传入指针的指针是不错的选择 */ int simulfs_InitCSTreeNode(simulfs_CSNode* CSNode) { CSNode->ln.dataPtr = NULL; CSNode->ln.leftChild = NULL; CSNode->ln.nextSlibing = NULL; CSNode->ln.parent = NULL; CSNode->ln.priorSlibing = NULL; CSNode->ln.thisFlag = 0x20; // 预设为UNKNOW CSNode->ln.objectNumber = 0; SetMixedIdInvailed(&(CSNode->ln.thisId)); } // 初始化普通的结点要根据标记创建成不同的结点 int simulfs_CreateCSTreeNode(simulfs_CSNode** CSNode, similfs_Flags thisFlag) { *CSNode = (simulfs_CSNode*)calloc(1, sizeof(simulfs_CSNode)); simulfs_InitCSTreeNode(*CSNode); *CSNode->ln.thisFlag = thisFlag; } int simulfs_CreateCSTree(simulfs_CSTree* CSTreeROOT) { // 开始定义它为文件夹,创建了一棵树,必须是主目录啊。 simulfs_CreateCSTreeNode(CSTreeROOT, 0x01); } int simulfs_DestoryCSTree(simulfs_CSTree CSTreeROOT) { return simulfs_DestoryList(CSTreeROOT->ln); }  

 

/* * This file is used to record the file tree. * File tree is different from the directory. * It used some levels and slots to store file contents. * The first chunk stored file meta data. * Copyright @ Xusen Yin, Dept. IS, BISTU. * Note. union 的作用是指向统同一个内存地址的两个不同类型的变量 */ #ifndef _SIMULFS_FILETREE_H_ #define _SIMULFS_FILETREE_H_ #include "simulfs_objects.h" #include "simulfs_marcos.h" /* * 下面两个是每层不同的槽数目,为了索引用的。性能不好的时候可以修改。 * 随着文件的增长,树的结点增加。当这些结点已经不够用的时候,层次增加。 * 文件的修改要反映到树的变化中。文件的截断,增长,修改要反映到树中。 * Note. 只有最后一层叶子结点才有资格带文件数据 */ #define SIMULFS_FILETREE_SLOTS_ON_ABOVE_LEVEL_ONE 8 #define SIMULFS_FILETREE_SLOTS_ON_LEVEL_ZERO 16 typedef struct _simulfs_FileNode { /* 树深,叶子结点是level 0,其他的根据需要调整*/ int level; /* nextChild 主要用途是指向非叶结点的指针 */ struct _simulfs_FileNode* nextChild[SIMULFS_FILETREE_SLOTS_ON_ABOVE_LEVEL_ONE]; /* Ids主要用途是指向各个chunk,这种情况下就是上面的是NULL,这就是叶结点 */ simulfs_MixedId Ids[SIMULFS_FILETREE_SLOTS_ON_LEVEL_ZERO]; struct _simulfs_FileNode* parent; /* 下面这个是给非叶结点用的,来判断它已经分配了哪些槽了。 */ int nextTobeAllocateNumber; // 下一个在父结点中的位置(数组的位置),如果这个位置已经超出上限 // SIMULFS_FILETREE_SLOTS_ON_ABOVE_LEVEL_ONE // 那就申请新结点,注意上溯到爷爷结点 // 如果有叶子结点,那就是挂满8个叶子结点的,不会少 }simulfs_FileNode; typedef struct { simulfs_FileNode* fileTreeROOTNode; // 指向根结点 int nextChunkIdinObject; // 下一个可以用的chunkID,也是chunk计数 }simulfs_FileTree; /* * 这个不用传递指针的指针 * 传递指针的指针只存在一种情况:你要修改这个指针的值,但是不方便把修改后的指针的值当成结果返回 * 如果值修改指针指向的内容,那就只传指针就行了。 * 这个Create函数存在两种情况: * 1. 这个fileTreeROOT已经有内容让他指向了,这样就传指针 * 2. 这个fileTreeROOT只是一个指针,还没有让他指向任何东西,那就传递指针的指针 * 我先在存在第二种情况,嘿嘿~ */ int simulfs_CreateFileNode(simulfs_FileTree* fileTreeNode); int simulfs_CreateFileTree(simulfs_FileTree* fileTreeROOT); int simulfs_TraverseFileTree(simulfs_FileTree thisROOT, int (*Visit)(simulfs_FileNode* csnode)); int simulfs_DestoryFileTree(simulfs_FileTree thisROOT); int simulfs_InsertFileNode(simulfs_FileTree fileTreeROOT, simulfs_FileNode* myNode); int simulfs_DeleteFileNode(simulfs_FileTree fileTreeROOT, simulfs_FileNode* myNode); #endif //_SIMULFS_FILETREE_H_  

 

/* * This file is used to record the file tree. * File tree is different from the directory. * It used some levels and slots to store file contents. * The first chunk stored file meta data. * Copyright @ Xusen Yin, Dept. IS, BISTU. * Note. union 的作用是指向统同一个内存地址的两个不同类型的变量 */ /* * 关键问题是怎样分配chunk * 要不每次一层增加时,把所有的非叶结点都申请了算了,省得麻烦,可以提高效率,缺点就是浪费点空间 * */ #include "simulfs_FileTree.h" #include "simulfs_objects.h" #include "simulfs_marcos.h" #include <stdlib.h> const int maxNumberofTree[SIMULFS_MAX_POS_ARRAY] = { 0x0010, 0x0080, 0x0400, 0x2000, 0x10000, 0x80000, 0x400000, 0x2000000 }; /* * 一个函数只干一件事,不能多干,才好管理 */ simulfs_FileNode* simulfs_CreateFileNode(void) { simulfs_FileNode* fileTreeNode = (simulfs_FileNode*)calloc(1, sizeof(simulfs_FileNode)); return fileTreeNode; } /* * 初始化内部迭代结点 * Note. 传入的时候必须保证fileTreeNode不是NULL * arguments: * 1. 要初始化结点的双亲结点 * 2. 自身结点的指针 * 3. 自身的层次=双亲结点层次-1 */ int simulfs_InitIteralFileNode(simulfs_FileNode* parent, simulfs_FileNode* fileTreeNode, int level) { if(fileTreeNode == NULL) { return SIMULFS_FAIL; } int i = 0; fileTreeNode->parent = parent; for(i = 0; i<SIMULFS_FILETREE_SLOTS_ON_LEVEL_ZERO; ++i) { SetMixedIdInvailed(&(fileTreeNode->Ids[i])); } for(i = 0; i<SIMULFS_FILETREE_SLOTS_ON_ABOVE_LEVEL_ONE; ++i) { fileTreeNode->nextChild[i] == NULL; } fileTreeNode->level = level; fileTreeNode->nextTobeAllocateNumber = 0; return SIMULFS_OK; } /* * 初始化叶子结点,注意初始化叶子结点的时候不用申请新的可用的结点,暂时当作没用就可以了, * 申请真正的结点可以稍后进行 * 每个叶子结点都有16个槽呢,边用边申请得了 * arguments: * 1. 要初始化结点的双亲结点 * 2. 自身结点的指针 */ int simulfs_InitFileLeafNode(simulfs_FileNode* parent, simulfs_FileNode* fileTreeNode) { return simulfs_InitIteralFileNode(parent, fileTreeNode, 0); } /* * 要求传入预设的chunk的个数,默认的情况下每个文件暂时分配8个chunk * If only level 0 8*512B * level 1 4*8*512B * level 2 4*4*8*512B * level 3 4*4*4*8*512B * ... ... * How to create the tree??? * 这样把,create只做建立初始化树这样的事情,其他的事情交给resize函数去做 * Note. 每次分配都是8个,都是满的,不要搞错 */ /* * 不用传入参数,直接申请一个新的树就行了 * return: * 树根的值(注意不是指针) * 树根和普通的结点不同,封装了一些东西 * Note. 如果创建失败,那么返回的值中的树结点的指针就是空就可以了 */ simulfs_FileTree simulfs_CreateFileTree(void) { simulfs_FileTree fileTreeROOT; fileTreeROOT.fileTreeROOTNode = simulfs_CreateFileNode(); simulfs_InitFileLeafNode(NULL, simulfs_InitFileLeafNode); fileTreeROOT.nextChunkIdinObject = 0; return fileTreeROOT; } /* int simulfs_CreateFileTree(simulfs_Dev* myDev, simulfs_FileTree* fileTreeROOT) { if(simulfs_CreateFileNode(&(fileTreeROOT->fileTreeROOTNode)) == SIMULFS_FAIL) return SIMULFS_FAIL; int i = 0; simulfs_InitFileLeafNode(myDev, fileTreeROOT->fileTreeROOTNode); fileTreeROOT->totalChunkNumber = SIMULFS_DEFAULT_FILE_CHUNK; fileTreeROOT->remainChunkNumber = SIMULFS_DEFAULT_FILE_CHUNK; // 树建立后,文件参数要做部分修改 // 不过不在这里修改,是树的部分,就只管树的情况,每次只考虑一层 return SIMULFS_OK; } */ /* * 根据postion寻找某个槽的指针,嘿嘿,精华所在啊 * 返回一个simulfs_MixedId* * 自己收拾去吧。 * Note. 原始的那个chunk要有所标记奥 */ simulfs_MixedId* simulfs_seekAddrofASlot(simulfs_Dev* myDev, simulfs_FileTree* fileTreeROOT, int pos) { simulfs_MixedId* resId = NULL; int pos_ary[SIMULFS_MAX_POS_ARRAY] = {0}; int i=0; for(i=0; (i<SIMULFS_MAX_POS_ARRAY)&&(pos!=0) ;++i) { if(i==0) { // 第一次的偏移是4bit pos_ary[i] = pos >> 4; pos >>= 4; }else { pos_ary[i] = pos >> 3; pos >>=3; } } simulfs_FileNode* iteral = NULL; iteral = fileTreeROOT->fileTreeROOTNode; if(iteral == NULL) { perror("No tree is found, please create tree first" "Error found in simulfs_FileTree.c" "in function simulfs_skCrtAddrofASlot()"); return resId; } while(iteral->level > 0) { iteral = iteral->nextChild[pos_ary[iteral->level]]; // 说明pos有误,立即返回 if(iteral == NULL) { perror("Position is error" "Please check your input" "Error found in simulfs_seekAddrofASlot()"); return resId; } } // 如果原来有chunk设在里面,那就把它设为待擦除 if((resId->blockId != SIMULFS_UNUSED_BLOCK_ID)&& (resId->chunkId != SIMULFS_UNUSED_CHUNK_ID)&& (resId->devId != SIMULFS_UNUSED_DEV_ID)) { myDev->blockChain[resId->blockId]->chunkChain[resId->chunkId]->needEarse = 1; } resId = &(iteral->Ids[pos_ary[0]]); return resId; } /* * 向特定的位置加入一个chunk,当然,这个特定位置必须是当前树形结构中已经有了的 * 所以不存在树形结构的拓展 * pos 的值需要用户自行注意,否则会出现大问题,嘿嘿 * 最好不要直接使用这个函数 */ int simulfs_PutAChunkInTreeSlot(simulfs_Dev* myDev, simulfs_FileTree* fileTreeROOT, int pos) { // 1. 找到那个位置 simulfs_MixedId* thisId = simulfs_seekAddrofASlot(fileTreeROOT,pos); // 2. 分配空间 *thisId = simulfs_AllocChunk(myDev); return SIMULFS_OK; } /* * 该死的树形大结构 * 只有零层: 0x0010 * 1 0x0080 * 2 0x0400 * 3 0x2000 * 4 0x10000 * 5 0x80000 * 6 0x400000 * 7 0x2000000 * 8 0x10000000 * 9 0x80000000 * 10 ==! 已经算不出来了 * 看来把最大树深改为8即可,模拟,模拟 */ simulfs_MixedId* simulfs_skCrtAddrofASlot(simulfs_FileTree* fileTreeROOT, int pos) { int i=0; for(i=0; i<SIMULFS_MAX_POS_ARRAY;++i) { // 如果有相等的,需要调整树深 if(pos == maxNumberofTree[i]) { simulfs_FileNode* newRoot = simulfs_CreateFileNode(); simulfs_InitIteralFileNode(NULL, newRoot, fileTreeROOT->fileTreeROOTNode->level+1); fileTreeROOT->fileTreeROOTNode->parent = newRoot; fileTreeROOT->fileTreeROOTNode = newRoot; break; } else if(pos < maxNumberofTree[i]) { break; } } simulfs_MixedId* resId = NULL; int pos_ary[SIMULFS_MAX_POS_ARRAY] = {0}; for(i=0; (i<SIMULFS_MAX_POS_ARRAY)&&(pos!=0) ;++i) { if(i==0) { // 第一次的偏移是4bit pos_ary[i] = pos >> 4; pos >>= 4; }else { pos_ary[i] = pos >> 3; pos >>=3; } } simulfs_FileNode *iteral = NULL, *iteral_parent = NULL; iteral = fileTreeROOT->fileTreeROOTNode; if(iteral == NULL) { perror("No tree is found, please create tree first" "Error found in simulfs_FileTree.c" "in function simulfs_skCrtAddrofASlot()"); return resId; } while(iteral->level > 0) { iteral_parent = iteral; iteral = iteral->nextChild[pos_ary[iteral->level]]; // 如果发现迭代器变成了NULL,那么就说明要创建新的结点 嗯嗯 if(iteral == NULL) { simulfs_FileNode* newNode = simulfs_CreateFileNode(); simulfs_InitIteralFileNode(iteral_parent, newNode, iteral_parent->level-1); iteral_parent->nextChild[pos_ary[iteral_parent->level]] = newNode; } } resId = &(iteral->Ids[pos_ary[0]]); return resId; } /* * 向当前位置插入一个结点 * 这样的话,当前位置要做+1运算 */ int simulfs_PutAChunkInCurTreeSlot(simulfs_Dev* myDev, simulfs_FileTree* fileTreeROOT) { // 1. 找到那个位置,这回的找到和上次的不同了 // 这次如果找不到就是要创建的了 simulfs_MixedId* thisId = simulfs_skCrtAddrofASlot(fileTreeROOT, fileTreeROOT->nextChunkIdinObject++); // 2. 分配空间 *thisId = simulfs_AllocChunk(myDev); return SIMULFS_OK; } /* * 遍历所有结点,调用visit函数 * 这个,遍历Interal结点恐怕没什么作用啊 * 就先写个遍历叶子结点的吧 * 那个以后用到了再说。 * Note. 这玩意儿遍历还得用个队列,要不真麻烦 */ int simulfs_TraverseFileTree(simulfs_FileTree thisROOT, int (*Visit)(simulfs_FileNode* csnode)) { 123 } /* * 删除一个文件的时候,擦除所有的结点,释放所有的chunk去擦除 */ int simulfs_DestoryFileTree(simulfs_FileTree thisROOT) { } /* * 从某结点开始到level1 自动生成 * 唉,不知到这个递归能不能顺利进行??? * 真是郁闷,写的不好,到时候再改吧。 */ int InitParentAndChildrenToLeaf(simulfs_FileNode* myNode) { if(myNode->level <= 1) { return SIMULFS_FAIL; } else { simulfs_FileNode* newNodes[SIMULFS_FILETREE_SLOTS_ON_ABOVE_LEVEL_ONE]; int i=0; for(i=0; i< SIMULFS_FILETREE_SLOTS_ON_ABOVE_LEVEL_ONE; ++i) { // 1. 创建4个结点 simulfs_CreateFileNode(&newNodes[i]); // 2. 初始化4个结点 simulfs_InitFileNode(newNodes[i]); // 3. 挂载到当前结点上 newNodes[i]->parent = myNode; myNode->nextChild[i] = newNodes[i]; // 4. 做一些设置 newNodes[i]->level = myNode->level -1; InitParentAndChildrenToLeaf(newNodes[i]); } return SIMULFS_OK; } } /* * 主要用于找不到新的可用的叶子结点时,扩大树的深度,深度一次增一 * Note. 不改变原树的结构,原树现在成为一支,我们重新申请一个根结点,把原树挂上就行了 * 记得生成其他树level1(包含)以上的结点 */ int simulfs_ResizeFileTreeDepth(simulfs_FileTree fileTreeROOT) { simulfs_FileNode* newRootNode; simulfs_CreateFileNode(&newRootNode); simulfs_InitFileNode(newRootNode); newRootNode->level = fileTreeROOT.fileTreeROOTNode->level+1; newRootNode->nextChild[0] = fileTreeROOT.fileTreeROOTNode; // 挂载新根 fileTreeROOT.fileTreeROOTNode = newRootNode; // 生成其他结点 simulfs_FileNode* newNodes[SIMULFS_FILETREE_SLOTS_ON_ABOVE_LEVEL_ONE-1]; int i=0; for(i=0; i< SIMULFS_FILETREE_SLOTS_ON_ABOVE_LEVEL_ONE-1; ++i) { // 1. 创建3个结点 simulfs_CreateFileNode(&newNodes[i]); // 2. 初始化3个结点 simulfs_InitFileNode(newNodes[i]); // 3. 挂载到当前结点上 newNodes[i]->parent = newRootNode; newRootNode->nextChild[i] = newNodes[i]; // 4. 做一些设置 newNodes[i]->level = newRootNode->level -1; InitParentAndChildrenToLeaf(newNodes[i]); } return SIMULFS_OK; } /* * 主要用于申请更多的chunk数目时,在一定的树深度下寻找新的可用叶子结点。 * 可不可以做到透明的调整树的形状??? */ int simulfs_ResizeFileTreeGrowth(simulfs_Dev* myDev, simulfs_FileTree fileTreeROOT, int ChunkNumber) { /* 如果剩余的块数还够,就不用再申请了 */ if(ChunkNumber <= fileTreeROOT.remainChunkNumber) return SIMULFS_AMBIGOUS; do { if(fileTreeROOT.currentLevelOneNode->nextTobeAllocateNumber == SIMULFS_FILETREE_SLOTS_ON_ABOVE_LEVEL_ONE) { // 如果中间一步出错还要考虑原来步骤撤销的事情,暂时没考虑写这部分回滚代码 if(fileTreeROOT.currentLevelOneNode->parent->nextTobeAllocateNumber == SIMULFS_FILETREE_SLOTS_ON_ABOVE_LEVEL_ONE) { // 这步如果出错了,就要考虑增加树深了。 return SIMULFS_FILETREENEEDMOREDEEP; } // 1. 把当前结点改到下一个 fileTreeROOT.currentLevelOneNode = fileTreeROOT.currentLevelOneNode->parent-> nextChild[fileTreeROOT.currentLevelOneNode->parent->nextTobeAllocateNumber++]; } // 1. 申请8个当前chunk,即把这八个新的结点初始化 if(simulfs_InitFileLeafNode(myDev, fileTreeROOT.currentLevelOneNode-> nextChild[fileTreeROOT.currentLevelOneNode->nextTobeAllocateNumber++]) == SIMULFS_FAIL) { // 如果这步不成功,那就是真的错了。 return SIMULFS_FAIL; } // 2. 下面可用的chunk大小加 8 fileTreeROOT.remainChunkNumber += SIMULFS_FILETREE_SLOTS_ON_LEVEL_ZERO; fileTreeROOT.totalChunkNumber += SIMULFS_FILETREE_SLOTS_ON_LEVEL_ZERO; chunkNumber %= SIMULFS_DEFAULT_FILE_CHUNK; } while(chunkNumber%SIMULFS_DEFAULT_FILE_CHUNK != 0); return SIMULFS_OK; }  

 

#ifndef _SIMULFS_FS_H_ #define _SIMULFS_FS_H_ #include "simulfs_objects.h" #include "simulfs_dlink.h" /* -------------------------- Object structure -------------------------------*/ /* object header ,used on RAM to search etc.*/ /* 这是用来在RAM上搜索的,暂时不用了 */ typedef struct _simulfs_ObjectHeader { __u32 objectId; // 原来的代码中怎么没有objectId呢?很是不解 simulfs_ObjectType type; /* Apply to everything */ int parentObjectId; char name[SIMULFS_MAX_NAME_LENGTH + 1]; __u32 simulfs_object_tags; /* File size applies to files only */ int fileSize; } simulfs_ObjectHeader; /*------------------------ Object -----------------------------*/ /* An object can be one of: * - a directory (no data, has children links * - a regular file (data.... not prunes :->). * - a symlink [symbolic link] (the alias). * - a hard link */ typedef struct _simulfs_FileStructure { __u32 fileSize; int topLevel; // 文件的树形结构头层次 simulfs_FileTree top; // 指向头的指针 } simulfs_FileStructure; /* * 使用一个双端链表存储文件夹内容 */ typedef struct _simulfs_DirectoryStructure { simulfs_List children; /* 链表中首个孩子结点,这个链表应该是既能连目录也能文件 */ } simulfs_DirectoryStructure; typedef struct _simulfs_SymLinkStructure { char *alias; } simulfs_SymLinkStructure; typedef struct _simulfs_HardLinkStructure { struct simulfs_ObjectStruct *equivalentObject; __u32 equivalentObjectId; } simulfs_HardLinkStructure; typedef union _simulfs_ObjectVariant { simulfs_FileStructure fileVariant; simulfs_DirectoryStructure directoryVariant; simulfs_SymLinkStructure symLinkVariant; simulfs_HardLinkStructure hardLinkVariant; } simulfs_ObjectVariant; struct simulfs_ObjectStruct { __u8 dirty:1; /* the object needs to be written to flash */ /* Where's my object header in NAND? */ int chunkId; int nDataChunks; /* Number of data chunks attached to the file. */ __u32 objectId; /* the object id value */ simulfs_ObjectType variantType; simulfs_ObjectVariant variant; __u8 hasNewChunk:1; // 是否已经分配了新的chunk simulfs_Chunk newChunk; }; typedef struct simulfs_ObjectStruct simulfs_Object; /* * 这是文件句柄,返回的时候返回文件句柄 * 文件句柄存着很多东西 */ typedef struct _simulfs_fileHandler { simulfs_MixedId Ids; __u32 offset; // 利用Ids和offset找到文件当前偏移位置 simulfs_FileStructure* fileStructure; }simulfs_fileHandler; /* * ------------------------------------------------------------------------------------ * next are file system core interfaces * 1. directory * ----------------------------------------------------------------------------------- */ int directory_create(); int directory_parent(); int directory_child(); int directory_this(); int directory_retry(); int directory_delete(); /* * ------------------------------------------------------------------------------- * 2. file * ------------------------------------------------------------------------------- */ int file_create(); int file_truncate(); int file_increase(); int file_read(); int file_write(); int file_delete(); /* * ------------------------------------------------------------------------------- * 3. Symbol link * ------------------------------------------------------------------------------ */ int symlink_create(); int symlink_link(); int symlink_relink(); int symlink_delete(); /* * ---------------------------------------------------------------------------------- * 4. Hard link * --------------------------------------------------------------------------------- */ int hardlink_create(); int hardlink_link(); int hardlink_relink(); int hardlink_delete(); #endif //_SIMULFS_FS_H_  

 

/* * This file is the core implementation of the file system. * main : * 1. file * 2. directory */ #include <stdlib.h> #include <string.h> #include "simulfs_fs.h" #include "simulfs_dlink.h" #include "simulfs_CSTree.h" #include "simulfs_FileTree.h" #include "simulfs_objects.h" #include "simulfs_marcos.h" /* * ------------------------------------------------------------------------------------ * next are file system core interfaces * 1. directory * ----------------------------------------------------------------------------------- */ // 传入的是当前目录,要得到的值是在这个目录下的一个新目录的指针 // 整个文件系统初始化的时候应该自动建立一个根目录 simulfs_DirectoryStructure* directory_create(simulfs_DirectoryStructure* thisDir) { simulfs_DirectoryStructure* newDir = (simulfs_DirectoryStructure*)calloc(1, sizeof(simulfs_DirectoryStructure)); // 设置新目录属性 newDir->children->dataPtr = NULL; newDir->children->leftChild = NULL; newDir->children->nextSlibing = NULL; newDir->children->parent = thisDir->children; newDir->children->priorSlibing = NULL; newDir->children->thisFlag = 0x01; newDir->children->objectNumber = 0; SetMixedIdInvailed(newDir->children->thisId); // 设置当前目录属性 simulfs_InsertListNodeonEnd(thisDir->children, newDir->children); // 返回新目录 return newDir; } // 寻找其父目录 simulfs_DirectoryStructure* directory_parent(simulfs_DirectoryStructure* thisDir) { simulfs_DirectoryStructure* newDir = (simulfs_DirectoryStructure*)calloc(1,sizeof(simulfs_DirectoryStructure)); newDir->children = thisDir->children; return newDir; } // 列出其孩子 simulfs_DirectoryStructure** directory_child(simulfs_DirectoryStructure* thisDir) { simulfs_DirectoryStructure** newObjs = (simulfs_DirectoryStructure**) calloc(thisDir->children->objectNumber,sizeof(simulfs_DirectoryStructure*)); simulfs_ListNode* newLND; newLND = thisDir->children->leftChild; // 指向了他的左孩子 int i = 0; for(i=0; i< thisDir->children->objectNumber; ++i) { newObjs[i] = (simulfs_DirectoryStructure*)calloc(1,sizeof(simulfs_DirectoryStructure)); newObjs[i]->children = newLND; newLND = newLND->nextSlibing; } return newObjs; } // 检索目录,这个应该递归到各个目录直至底层 int directory_retry(simulfs_DirectoryStructure* thisDir, int (*Visit)(simulfs_DirectoryStructure* dir)) { simulfs_ListNode* newLnd = thisDir->children->leftChild; simulfs_DirectoryStructure ADir; while(newLnd != NULL) { if(newLnd->obj.variantType == SIMULFS_OBJECT_TYPE_DIRECTORY) { ADir.children = newLnd; directory_retry(&ADir, Visit(simulfs_DirectoryStructure* dir)); } else { // 检测到一个文件呢 具体要做什么么? } } } // 删除掉这个目录,既要删除这个目录的所有东西 // 先删除该目录的其他文件、文件夹,最后再删除该文件加自身 int directory_delete(simulfs_DirectoryStructure* thisDir) { // 1. 删除掉该文件夹的其他部分,可以使用retry函数吗?先不用了 simulfs_ListNode* newLnd = thisDir->children->leftChild; simulfs_ListNode* newLndTmp = NULL; simulfs_DirectoryStructure ADir; while(newLnd != NULL) { if(newLnd->obj.variantType == SIMULFS_OBJECT_TYPE_DIRECTORY) { ADir.children = newLnd; // 1.1 递归下去删除 directory_delete(&ADir); // 1.2 删除自身 newLndTmp = newLnd->nextSlibing; free(newLnd); newLnd = newLndTmp; } else { // 检测到一个文件 删除之 simulfs_DestoryFileTree(*((simulfs_FileTree*)newLnd->dataPtr)); newLndTmp = newLnd->nextSlibing; free(newLnd); newLnd = newLndTmp; } } } /* * ------------------------------------------------------------------------------- * 2. file * ------------------------------------------------------------------------------- */ /* * 创建文件,很简单,就是申请一个相应的文件结构,挂载到目录下就行了。char* path * 这里的路径就先不用字符串了,直接用这个指针不就行了。 * 干脆就不要文件名了 */ int file_create(simulfs_DirectoryStructure* path) { simulfs_FileStructure* newFile = (simulfs_FileStructure*)calloc(1, sizeof(simulfs_FileStructure)); newFile->topLevel = 0; newFile->fileSize = 0; return simulfs_CreateFileTree(&(newFile->top)); } /* * 打开函数应该是最终要的,但是是否要再创建一个句柄结构? * 返回值应该是一个句柄,打开就先用句柄模拟吧 */ simulfs_fileHandler file_open(simulfs_DirectoryStructure* path,__u32 objectId) { simulfs_fileHandler resHandle; resHandle.Ids = 0; resHandle.fileStructure = NULL; resHandle.offset = 0; simulfs_List* next = path->children->leftChild; while(next != NULL) { // 如果找到这样一个文件,制造并返回句柄 if(next->obj.objectId == objectId) { resHandle.Ids = next->obj.chunkId; // 这个chunkId是元数据所在的id resHandle.fileStructure = &(next->obj.variant.fileVariant); resHandle.offset = 0; // 首个偏移位置设为0 return resHandle; } next = next->nextSlibing; } return resHandle; // 如果查找失败,就返回一个空句柄 } /* * 截断的这个很难做,不知道到底要做成什么样子的 * 要不就只留出接口来吧,其他的再说。 */ int file_truncate(char* path, char* filename) { } /* * 同上 不知道怎么入手 */ int file_increase(char* path, char* filename) { } /* * 文件读操作,当然是直接写到缓冲区内,大小要分配出来 * 传入的buf要由应用程序保证空间区域的可靠,大小要大于等于size */ int file_read(simulfs_fileHandler fHandle, void* buf, __u32 size) { if(buf == NULL || fHandle.fileStructure == NULL) return SIMULFS_FAIL; simulfs_ReadPerChunk()使用这个函数 需要的filetree提供下一个块的函数,即nextChunk } /* * 文件的写操作,传入的也是句柄 */ int file_write(simulfs_fileHandler fHandle, void* buf, __u32 size) { } /* * 文件的删除,其实在simulfs_DestoryFileTree() 函数中已经有了,这里直接调用就可以 */ int file_delete(simulfs_fileHandler fHandle) { } /* * ------------------------------------------------------------------------------- * 3. Symbol link * ------------------------------------------------------------------------------ */ int symlink_create(); int symlink_link(); int symlink_relink(); int symlink_delete(); /* * ---------------------------------------------------------------------------------- * 4. Hard link * --------------------------------------------------------------------------------- */ int hardlink_create(); int hardlink_link(); int hardlink_relink(); int hardlink_delete();  

你可能感兴趣的:(list,object,struct,File,null,symlink)