int tiny_open(const char *path, struct fuse_file_info *fi) { tiny_inode i_tmp; tiny_dentry *pDentry; char *token; char *path_copy; char *dir_name; char *base_name; int ino; int ret = 0; if (strcmp(path, "/") == 0) { return 0; } /* Get inode of the parent directory */ path_copy = (char*)malloc(strlen(path) + 1); strcpy(path_copy, path); dir_name = dirname(path_copy); token = strtok(dir_name, "/"); ReadInode(&i_tmp, tiny_superblk.s_rdirino); while (token) { pDentry = __find_dentry(&i_tmp, token); if (!pDentry || pDentry->type == FILE_TYPE_FILE) { ret = -ENOTDIR; goto err; } ReadInode(&i_tmp, pDentry->inodeNum); token = strtok(NULL, "/"); } /* Get dentry of the target */ free(path_copy); path_copy = (char*)malloc(strlen(path) + 1); strcpy(path_copy, path); base_name = basename(path_copy); pDentry = __find_dentry(&i_tmp, base_name); /* There is no such file */ if (pDentry == NULL) { ret = -ENOENT; goto err; } /* Path indicates a directory */ if (pDentry->type == FILE_TYPE_DIR) { ret = 0; goto err; } /* Get inode number of the target */ fi->fh = (uint64_t)pDentry->inodeNum; err: free(path_copy); return ret; }
int tiny_create(const char *path, mode_t mode, struct fuse_file_info *fi) { tiny_inode i_tmp; int target_inodeno; tiny_dentry *pDentry; char *token; char *path_copy; char *dir_name; char *base_name; int ino; int ret = 0; /* Get inode of the parent directory */ path_copy = (char*)malloc(strlen(path) + 1); strcpy(path_copy, path); dir_name = dirname(path_copy); token = strtok(dir_name, "/"); ReadInode(&i_tmp, tiny_superblk.s_rdirino); while (token) { pDentry = __find_dentry(&i_tmp, token); if (!pDentry || pDentry->type == FILE_TYPE_FILE) { ret = -ENOTDIR; goto err; } ReadInode(&i_tmp, pDentry->inodeNum); token = strtok(NULL, "/"); } /* Get dentry of the target */ free(path_copy); path_copy = (char*)malloc(strlen(path) + 1); strcpy(path_copy, path); base_name = basename(path_copy); if (strlen(base_name) > NAME_LEN_MAX - 1) { ret = -ENAMETOOLONG; goto err; } pDentry = __find_dentry(&i_tmp, base_name); /* There is no such file */ if (pDentry == NULL) { target_inodeno = __create_file(&i_tmp, base_name); if (target_inodeno < 0) { ret = -EDQUOT; goto err; } fi->fh = (uint64_t)target_inodeno; } else { ret = -EEXIST; goto err; } err: free(path_copy); return ret; }
int tiny_unlink(const char *path) { tiny_inode i_tmp; tiny_inode target; tiny_dentry *pDentry; char *token; char *path_copy; char *dir_name; char *base_name; int target_inodeno; int ret = 0; int i, j; /* Get inode of the parent directory */ path_copy = (char*)malloc(strlen(path) + 1); strcpy(path_copy, path); dir_name = dirname(path_copy); token = strtok(dir_name, "/"); ReadInode(&i_tmp, tiny_superblk.s_rdirino); while (token) { pDentry = __find_dentry(&i_tmp, token); if (!pDentry || pDentry->type == FILE_TYPE_FILE) { ret = -ENOTDIR; goto err; } ReadInode(&i_tmp, pDentry->inodeNum); token = strtok(NULL, "/"); } /* Get dentry of the target */ free(path_copy); path_copy = (char*)malloc(strlen(path) + 1); strcpy(path_copy, path); base_name = basename(path_copy); target_inodeno = __find_dentry_and_remove(&target, &i_tmp, base_name); if (target_inodeno < 0) { ret = -ENOENT; goto err; } for ( i = 0 ; i < target.i_nblk ; i++ ) { SetBlockAllocToFree(target.i_block[i]); } SetInodeAllocToFree(target_inodeno); err: free(path_copy); return ret; }
initrd_inode_t* GetInode(int fd, initrd_superblock_t* sb, uint32_t ino) { initrd_inode_t* inode = (initrd_inode_t*) malloc(sizeof(initrd_inode_t)); if ( !inode ) { return NULL; } if ( !ReadInode(fd, sb, ino, inode) ) { free(inode); return NULL; } return inode; }
Partition::Partition(uint64_t size, uint64_t offset, int ssize, HANDLE phandle) { int ret; total_sectors = size; relative_sect = offset; handle = phandle; sect_size = ssize; onview = false; inode_buffer = NULL; buffercache.setMaxCost(MAX_CACHE_SIZE); ret = Mount(); if(ret < 0) { is_valid = false; return; } root = ReadInode(EXT2_ROOT_INO); if(!root) { is_valid = false; LOG("Cannot read the root of %s \n", linux_name.c_str()); return; } root->file_name = linux_name; root->file_type = 0x02; is_valid = true; }
int WriteDir(int dirhandle, struct DirEntry *dent) { if (dirhandle<0||dirhandle>=10) return -1; struct INode inode; int dev=0; ReadInode(dev,dir_table[dirhandle]->d_entry.d_ino, &inode); int dentries_in_one_block = BLKSIZE / (sizeof (struct OnDiskDirEntry)); int blk_count= dir_table[dirhandle]->d_offset / dentries_in_one_block; char buf [BLKSIZE]; ReadBlock(dev,DATA_BLK_STARTS_AT+inode.i_blks[blk_count],buf); struct OnDiskDirEntry* dp= (struct OnDiskDirEntry*) buf; dp += dir_table[dirhandle]->d_offset % dentries_in_one_block; my_memcpy( dp, &dent->d_entry, sizeof (struct OnDiskDirEntry) ); WriteBlock(dev,DATA_BLK_STARTS_AT+inode.i_blks[blk_count],buf); dir_table[dirhandle]->d_offset++; return 0 ;// success }
long UFSGetDirEntry( CICell ih, char * dirPath, long long * dirIndex, char ** name, long * flags, long * time, FinderInfo * finderInfo, long * infoValid) { long ret, fileInodeNum, dirFlags; Inode tmpInode; if (UFSInitPartition(ih) == -1) return -1; if (infoValid) *infoValid = 0; // Skip a leading '/' if present if (*dirPath == '/') dirPath++; if (*dirPath == '/') dirPath++; ret = ResolvePathToInode(dirPath, &dirFlags, gFileInodePtr, gRootInodePtr); if ((ret == -1) || ((dirFlags & kFileTypeMask) != kFileTypeDirectory)) return -1; ret = ReadDirEntry(gFileInodePtr, &fileInodeNum, dirIndex, name); if (ret != 0) return ret; ReadInode(fileInodeNum, &tmpInode, flags, time); return 0; }
int FreeInode(int dev, int ino) { char buf[BLKSIZE * 2]; ReadBlock(dev,SUP_BLK_STARTS_AT,buf); ReadBlock( dev,SUP_BLK_STARTS_AT+1,buf+BLKSIZE); struct SupBlock* sptr= (struct SupBlock*) buf; sptr->sb_nfreeino++; if (sptr->sb_freeinoindex !=0 ) // if inode list is not full { sptr->sb_freeinoindex--; sptr->sb_freeinos[sptr->sb_freeinoindex]= ino; } writeSuper(dev,sptr); struct INode inode; ReadInode(dev,ino,&inode); inode.i_lnk=0; WriteInode(dev,ino,&inode); //return success return 0; }
// Delete directory (if itis empty) int RmDir(int pardir, char *dname) { struct DirEntry* parent = dir_table[pardir]; struct INode inode; ReadInode(0,parent->d_entry.d_ino,&inode); char buf[BLKSIZE]; struct OnDiskDirEntry* dp; int data_blks_allocated_to_dir= inode.i_size/BLKSIZE + (inode.i_size % BLKSIZE)==0?0:1 ; int i=0,done=0; int blkno; while (done==0&&i<data_blks_allocated_to_dir) // assuming dirctory-file is small(no need to look in indirect,double indirect.) { blkno=inode.i_blks[i]; ReadBlock(dev,DATA_BLK_STARTS_AT+blkno,buf); dp= (struct OnDiskDirEntry*) buf; int j=0; while (done==0 && j<BLKSIZE/sizeof (struct OnDiskDirEntry)) { if (strcmp (dp->d_name,dname)==0) { done = 1; continue; } j++;dp++; } i++; } struct INode inode_of_dir_to_be_remove; ReadInode (dev,dp->d_ino,&inode_of_dir_to_be_remove); if (inode_of_dir_to_be_remove.i_size>0) { printf("directory is not empty\n"); return -1; } FreeInode(dev,dp->d_ino); //remove dir entry from parent directory dp->d_ino=0; WriteBlock(dev,blkno,buf); return 0; }
long Ext2InitPartition(CICell ih) { long cnt, gdPerBlock; if (ih == gCurrentIH) return 0; printf("Ext2InitPartition: %x\n", ih); gCurrentIH = 0; // Read for the Super Block. Seek(ih, SBOFF); Read(ih, (long)gFSBuf, SBSIZE); gFS = (struct m_ext2fs *)gFSBuf; e2fs_sb_bswap(&gFS->e2fs, &gFS->e2fs); if (gFS->e2fs.e2fs_magic != E2FS_MAGIC) return -1; // Calculate the block size and set up the block cache. gBlockSize = 1024 << gFS->e2fs.e2fs_log_bsize; if (gBlockSizeOld <= gBlockSize) { gTempBlock = AllocateBootXMemory(gBlockSize); } CacheInit(ih, gBlockSize); gBlockSizeOld = gBlockSize; gCurrentIH = ih; gdPerBlock = gBlockSize / sizeof(struct ext2_gd); // Fill in the in memory super block fields. gFS->e2fs_bsize = 1024 << gFS->e2fs.e2fs_log_bsize; gFS->e2fs_bshift = LOG_MINBSIZE + gFS->e2fs.e2fs_log_bsize; gFS->e2fs_qbmask = gFS->e2fs_bsize - 1; gFS->e2fs_bmask = ~gFS->e2fs_qbmask; gFS->e2fs_fsbtodb = gFS->e2fs.e2fs_log_bsize + 1; gFS->e2fs_ncg = HowMany(gFS->e2fs.e2fs_bcount - gFS->e2fs.e2fs_first_dblock, gFS->e2fs.e2fs_bpg); gFS->e2fs_ngdb = HowMany(gFS->e2fs_ncg, gdPerBlock); gFS->e2fs_ipb = gFS->e2fs_bsize / EXT2_DINODE_SIZE; gFS->e2fs_itpg = gFS->e2fs.e2fs_ipg / gFS->e2fs_ipb; gFS->e2fs_gd = AllocateBootXMemory(gFS->e2fs_ngdb * gFS->e2fs_bsize); // Read the summary information from disk. for (cnt = 0; cnt < gFS->e2fs_ngdb; cnt++) { ReadBlock(((gBlockSize > 1024) ? 0 : 1) + cnt + 1, 0, gBlockSize, (char *)&gFS->e2fs_gd[gdPerBlock * cnt], 0); e2fs_cg_bswap(&gFS->e2fs_gd[gdPerBlock * cnt], &gFS->e2fs_gd[gdPerBlock * cnt], gBlockSize); } // Read the Root Inode ReadInode(EXT2_ROOTINO, &gRootInode, 0, 0); return 0; }
int RemoveDirentry(InodeInfo* inodeInfo, char* dirname) { /* * precondition : inodeInfo != NULL, dirname != NULL * postcondition : dirname은 삭제를 원하는 디렉토리명이며, * inodeInfo는 dirname을 가지고 있을 것으로 추정되는 inode이다. * 성공시 0, 실패시 -1 리턴 */ int block = 0, index = 0; int parent_inodeno = 0; int current_inodeno = 0; int ret_value = 0; int i = 0; InodeInfo delInodeInfo; InodeInfo nullinode; DirBlock dirBlock; DirBlock nullblock; memset(&nullinode, 0, sizeof(InodeInfo)); memset(&nullblock, 0, sizeof(DirBlock)); ReadDirBlock(&dirBlock, inodeInfo->i_block[0]); current_inodeno = dirBlock.dirEntries[0].inodeNum; parent_inodeno = dirBlock.dirEntries[1].inodeNum; for ( block = 0 ; block < inodeInfo->blocks ; block++ ) { ReadDirBlock(&dirBlock, inodeInfo->i_block[block]); for ( index = 0 ; index < MAX_INDEX_OF_DIRBLK ; index++ ) { if(strcmp(dirBlock.dirEntries[index].name, dirname) == 0 && dirBlock.dirEntries[index].type == FILE_TYPE_DIR) {// 지울 디렉토리명을 찾으면 ReadInode(&delInodeInfo, dirBlock.dirEntries[index].inodeNum); if ( (ret_value = DirIsEmpty(&delInodeInfo)) == WRONG_VALUE ) { fprintf(stderr, "dirname is not a DIRECTORY!\n"); fprintf(stderr, "DirIsEmpty() Error!\n"); } if ( ret_value == TRUE ) {// 디렉토리가 비어있다. ==> 삭제 for ( i = 0 ; i < delInodeInfo.blocks ; i++ ) { WriteDirBlock(&nullblock, delInodeInfo.i_block[i]); SetBlockAllocToFree(delInodeInfo.i_block[i]); } WriteInode(&nullinode, dirBlock.dirEntries[index].inodeNum); SetInodeAllocToFree(dirBlock.dirEntries[index].inodeNum); dirBlock.dirEntries[index].inodeNum = 0; strcpy(dirBlock.dirEntries[index].name, ""); // DirBlock과 InodeInfo 갱신하기 WriteDirBlock(&dirBlock, inodeInfo->i_block[block]); return 0; } } } } return -1; }
static int __find_dentry_and_remove(tiny_inode* out_inode, tiny_inode *parent_inode, const char *entry_name) { int qid = OpenMQ(5000); tiny_dirblk *dirblk; tiny_dentry *dentry; Buf *buf; int i, j; int isEmpty = 1; int find = 0; int dirblkno; int parent_inodeno; int target_inodeno; for (i = 0; i < parent_inode->i_nblk; i++) { buf = BufRead(parent_inode->i_block[i]); dirblk = __get_dirblk_from_buf(buf); dirblkno = parent_inode->i_block[i]; isEmpty = 1; for (j = 0; j < NUM_OF_DIRENT_IN_1BLK; j++) { dentry = &dirblk->dirEntries[j]; if ( i == 0 && j == 0 ) { parent_inodeno = dentry[0].inodeNum; } if (strncmp(entry_name, dentry->name, NAME_LEN_MAX) == 0) { ReadInode(out_inode, dentry->inodeNum); strncpy(dentry->name, "", NAME_LEN_MAX); target_inodeno = dentry->inodeNum; find = 1; } else if (strncmp(dentry->name, "", NAME_LEN_MAX) != 0) { isEmpty = 0; } } if (find) { if (isEmpty) { SetBlockAllocToFree(dirblkno); parent_inode->i_block[i] = parent_inode->i_block[--parent_inode->i_nblk]; WriteInode(parent_inode, parent_inodeno); } else { WriteDirBlock(dirblk, dirblkno); } return target_inodeno; } } return -1; }
int ext2::Open(FileDescriptorBase *fileDescriptor, const string &file, const int flags) { // FIX ME (void)flags; FileDescriptor *fd = reinterpret_cast<FileDescriptor*>(fileDescriptor); int inode = FindInodeByPath(string(file)); if(inode < 0) { printf("COULDN'T FIND INODE\n"); return(-1); } fd->inodeNumber = inode; // set the inode number ReadInode(inode, &fd->fileInode); // read in the inode /* printf("SIZE: %d\n", fd->fileInode.size); printf("OWNER ID: %d\n", fd->fileInode.ownerUID); printf("FILE MODE: %d\n", fd->fileInode.fileMode); printf("BLOCK COUNT: %d\n", fd->fileInode.blockCount); printf("FILE FLAGS: %d\n", fd->fileInode.fileFlags); */ if(!(fd->fileInode.fileMode & FILE_FILE_MODE)) { // Panic::PrintMessage("Not a file\n"); printf("Not a file\n"); return(-2); } // read in the first data block if(fd->fileInode.size > 0) { fd->blockData = new uchar[blockSize]; // make the memory // Read in the first data block ReadDataBlock(0, fd->fileInode.blockPointers, fd->blockData); } else fd->blockData = NULL; // zero the block number and positions fd->blockNumber = fd->filePosition = fd->blockPosition = 0; return(0); }
// Write into a file already opened, nbytes from buf int WriteFile(int fhandle, char buf[], int nbytes) { // implementation of writefile is same as above readfile function, just direction of flow of data is reverse if (fhandle<0||ofo_table[fhandle]==NULL) { return -1;//error } struct INode inode; ReadInode( dev,ofo_table[fhandle]->ofo_inode->ic_ino,&inode); int nblks_to_be_read= (nbytes-1)/BLKSIZE +1; int nblk_to_be_skipped= (ofo_table[fhandle]->ofo_curpos -1) / BLKSIZE; int first_blkno_tobe_read= inode.i_blks[nblk_to_be_skipped]; int byte_to_be_skipped= (ofo_table[fhandle]->ofo_curpos-1) % BLKSIZE; char tempbuf [BLKSIZE]; ReadBlock(ofo_table[fhandle]->ofo_inode->ic_dev, first_blkno_tobe_read, tempbuf); int bytes_tobe_read= BLKSIZE - byte_to_be_skipped; my_memcpy(tempbuf+byte_to_be_skipped, buf, bytes_tobe_read ); char* buf_ptr=buf+bytes_tobe_read; //now read remaining blks int i=nblk_to_be_skipped +1; for (;i<nblks_to_be_read;i++) { ReadBlock(dev,DATA_BLK_STARTS_AT+inode.i_blks[i],tempbuf); int bytes_to_transfer; if (nbytes>(i+1)*BLKSIZE) bytes_to_transfer=BLKSIZE; else bytes_to_transfer= nbytes-i*BLKSIZE; my_memcpy(tempbuf, buf_ptr, bytes_to_transfer); buf_ptr += BLKSIZE; } // advance the cursor ofo_table[fhandle]->ofo_curpos += nbytes; return nbytes; // return bytes read }
static long FindFileInDir( char * fileName, long * flags, InodePtr fileInode, InodePtr dirInode ) { long ret, inodeNum, index = 0; char *name; while (1) { ret = ReadDirEntry(dirInode, &inodeNum, &index, &name); if (ret == -1) return -1; if (strcmp(fileName, name) == 0) break; } ReadInode(inodeNum, fileInode, flags, 0); return 0; }
int OpenDir(int pardir, char *dname) { struct DirEntry* parent = dir_table[pardir]; struct INode inode; ReadInode(0,parent->d_entry.d_ino,&inode); char buf[BLKSIZE]; struct OnDiskDirEntry* dp; int data_blks_allocated_to_dir= inode.i_size/BLKSIZE + (inode.i_size % BLKSIZE)==0?0:1 ; int i=0,done=0; while (done==0&&i<data_blks_allocated_to_dir) // assuming dirctory-file is small(no need to look in indirect,double indirect.) { int blkno=inode.i_blks[i]; ReadBlock(dev,DATA_BLK_STARTS_AT+blkno,buf); dp= (struct OnDiskDirEntry*) buf; int j=0; while (done==0 && j<BLKSIZE/sizeof (struct OnDiskDirEntry)) { if (strcmp (dp->d_name,dname)==0) { done = 1; continue; } j++;dp++; } i++; } //get a free entry in dir table i=0; while (dir_table[i]!=NULL&&i<10) i++; if (i>=10) { printf("can't open more than 10 directories\n"); return -1; } dir_table[i]= (struct DirEntry*) malloc(sizeof(struct DirEntry)); dir_table[i]->d_offset=0; my_memcpy(&dir_table[i]->d_entry, dp,sizeof (struct OnDiskDirEntry)); return i; }
// Move the file pointer to required position int SeekFile(int fhandle, int pos, int whence) { if (ofo_table[fhandle]==NULL) return -1; if (whence==SEEK_SET) { ofo_table[fhandle]->ofo_curpos = pos; } else if (whence==SEEK_CUR) { ofo_table[fhandle]->ofo_curpos += pos; } else if(whence==SEEK_END) { struct INode inode; ReadInode(dev,ofo_table[fhandle]->ofo_inode->ic_ino, &inode); ofo_table[fhandle]->ofo_curpos = inode.i_size+pos; } return ofo_table[fhandle]->ofo_curpos; }
long Ext2GetDirEntry(CICell ih, char *dirPath, long *dirIndex, char **name, long *flags, long *time) { long ret, fileInodeNum, dirFlags; Inode tmpInode; if (Ext2InitPartition(ih) == -1) return -1; // Skip a leading '\' if present if (dirPath[0] == '\\') dirPath++; ret = ResolvePathToInode(dirPath, &dirFlags, &gFileInode, &gRootInode); if ((ret == -1) || ((dirFlags & kFileTypeMask) != kFileTypeDirectory)) return -1; ret = ReadDirEntry(&gFileInode, &fileInodeNum, dirIndex, name); if (ret != 0) return ret; ReadInode(fileInodeNum, &tmpInode, flags, time); return 0; }
long UFSInitPartition(CICell ih) { if (ih == gCurrentIH) return 0; printf("UFSInitPartition: %x\n", ih); gCurrentIH = 0; // Assume there is no Disk Label gPartitionBase = 0; // Look for the Super Block Seek(ih, gPartitionBase + SBOFF); Read(ih, (long)gFSBuf, SBSIZE); gFS = (struct fs *)gFSBuf; if (gFS->fs_magic != FS_MAGIC) { return -1; } // Calculate the block size and set up the block cache. gBlockSize = gFS->fs_bsize; gFragSize = gFS->fs_fsize; gFragsPerBlock = gBlockSize / gFragSize; if (gBlockSizeOld <= gBlockSize) { gTempBlock = AllocateBootXMemory(gBlockSize); } CacheInit(ih, gBlockSize); gBlockSizeOld = gBlockSize; gCurrentIH = ih; // Read the Root Inode ReadInode(ROOTINO, &gRootInode, 0, 0); return 0; }
int ReadFile(int fileDesc, char* pBuffer, int length) { /* * precondition : usage) ReadFile(fileDesc, pBuffer, length); * fileDesc : file descriptor * pBuffer : 저장할 데이터를 포함하는 메모리의 주소 * length : 저장될 데이터의 길이 * postcondition : open된 파일에서 데이터를 읽는다. * 성공하면 읽은 데이터의 길이 값을 리턴한다. 실패 했을때는 -1을 리턴한다. */ int i = 0, j = 0; int block = fileDescTable.file[fileDesc].offset / BLOCK_SIZE; int offset = fileDescTable.file[fileDesc].offset % BLOCK_SIZE; int exsist = 0; int wrote = length; Buf* pBuf = NULL; InodeInfo inodeInfo; DirBlock dirBlock; ReadInode(&inodeInfo, fileDescTable.file[fileDesc].inodeNo); // 첫번째 블락에서 data 읽고 pBuffer에 적재 pBuf = BufRead(inodeInfo.i_block[block]); memcpy(pBuffer, (char*)pBuf->pMem + offset, BLOCK_SIZE - offset); wrote = length < BLOCK_SIZE - offset ? length : BLOCK_SIZE - offset ; fileDescTable.file[fileDesc].offset = wrote; if ( length <= 512 ) return wrote; // 두번째 블락부터 data 읽고 pBuffer에 적재 for ( j = block + 1 ; j < (length / BLOCK_SIZE) + block ; j++ ) { if (NUM_OF_INDIRECT_BLOCK == j) return wrote; // indirect block 12개가 모두 사용중이면 write한 만큼만 리턴 pBuf = BufRead(inodeInfo.i_block[j]); memcpy(pBuffer + BLOCK_SIZE * ((j - (block + 1)) + 1), pBuf->pMem, length - wrote > BLOCK_SIZE ? BLOCK_SIZE : length - wrote); wrote = wrote + (length - wrote > BLOCK_SIZE ? BLOCK_SIZE : length - wrote); fileDescTable.file[fileDesc].offset = wrote; if ( wrote == length ) return wrote; } }
int SeekDir(int dirhandle, int pos, int whence) { if (dir_table[dirhandle]==NULL) return -1; if (whence==SEEK_SET) { dir_table[dirhandle]->d_offset = pos; } else if (whence==SEEK_CUR) { dir_table[dirhandle]->d_offset += pos; } else if(whence==SEEK_END) { struct INode inode; int dev=0; ReadInode(dev,dir_table[dirhandle]->d_entry.d_ino, &inode); dir_table[dirhandle]->d_offset = inode.i_size+pos; } return dir_table[dirhandle]->d_offset; }
long UFSInitPartition( CICell ih ) { #if !BOOT1 long ret; #endif if (ih == gCurrentIH) { #ifdef __i386__ CacheInit(ih, gBlockSize); #endif return 0; } #if !BOOT1 verbose("UFSInitPartition: %x\n", ih); #endif gCurrentIH = 0; #ifdef __i386__ if (!gULBuf) gULBuf = (char *) malloc(UFS_LABEL_SIZE); if (!gFSBuf) gFSBuf = (char *) malloc(SBSIZE); if (!gTempName) gTempName = (char *) malloc(MAXNAMLEN + 1); if (!gTempName2) gTempName2 = (char *) malloc(MAXNAMLEN + 1); if (!gRootInodePtr) gRootInodePtr = (InodePtr) malloc(sizeof(Inode)); if (!gFileInodePtr) gFileInodePtr = (InodePtr) malloc(sizeof(Inode)); if (!gULBuf || !gFSBuf || !gTempName || !gTempName2 || !gRootInodePtr || !gFileInodePtr) return -1; #endif // Assume there is no Disk Label gPartitionBase = 0; #if !BOOT1 // read the disk label to get the UUID // (rumor has it that UFS headers can be either-endian on disk; hopefully // that isn't true for this UUID field). Seek(ih, gPartitionBase + UFS_LABEL_OFFSET); ret = Read(ih, (long)&gUFSLabel, UFS_LABEL_SIZE); if(ret != 0) bzero(&gUFSLabel, UFS_LABEL_SIZE); #endif /* !BOOT1 */ // Look for the Super Block Seek(ih, gPartitionBase + SBOFF); Read(ih, (long)gFSBuf, SBSIZE); gFS = (struct fs *)gFSBuf; byte_swap_superblock(gFS); if (gFS->fs_magic != FS_MAGIC) { return -1; } ih->modTime = gFS->fs_time; // Calculate the block size and set up the block cache. gBlockSize = gFS->fs_bsize; gFragSize = gFS->fs_fsize; gFragsPerBlock = gBlockSize / gFragSize; if (gTempBlock != 0) free(gTempBlock); gTempBlock = malloc(gBlockSize); CacheInit(ih, gBlockSize); gCurrentIH = ih; // Read the Root Inode ReadInode(ROOTINO, gRootInodePtr, 0, 0); return 0; }
int EnumerateDirStatus(const char* pDirName, DirEntry* pDirEntry, int dirEntries) { /* * precondition : usage ) EnumerateDirStatus(pDirName, pDirEntry, dirEntries); * postcondition : 디렉토리에 포함된 파일 또는 디렉토리 정보를 얻어낸다. * 이 함수는 해당 디렉토리를 구성하고 있는 디렉토리 엔트리들의 * 묶음을 리턴한다. * 성공하면 읽어진 디렉토리 엔트리 개수를 리턴한다. 예로, 임의의 디렉토리의 전체 * 디렉토리 엔트리 개수가 40이지만, dirEntries가 60으로 입력됬을때, 리턴되는 값은 * 유효한 디렉토리 엔트리 개수인 40을 리턴해야 한다. 또한, 40개의 디렉토리 엔트리 * 내용을 pDirEntry 배열로 전달해야 한다. 또한, 전체 디렉토리 엔트리 개수가 40이지만 * dirEntry가 20으로 입력되었을 때, 리턴되는 값은 20이며, 20개의 디렉토리 엔트리의 * 내용이 pDirEntry로 리턴되어야 한다. 에러 발생시 -1을 리턴한다. */ char dirname[NAME_LEN_MAX] = {NULL,}; char* abspath = malloc(strlen(pDirName) + 1); char* ptr = abspath; DirEntry* dirEntry = pDirEntry; InodeInfo inodeInfo; DirBlock dirBlock; int i = 0, j = 0; int found = 0; int cnt = 0; memcpy(abspath, pDirName, strlen(pDirName) + 1); GetEntryName(dirname, abspath); // dirname 최종 디렉토리명 ReadInode(&inodeInfo, fileSysInfo.rootInodeNum); ptr = strtok(abspath, "/"); if (ptr == NULL && strcmp(dirname,"") == 0) // root directory 일때 { for ( i = 0 ; i < inodeInfo.blocks ; i++ ) { ReadDirBlock(&dirBlock, inodeInfo.i_block[i]); for ( j = 0 ; j < MAX_INDEX_OF_DIRBLK ; j++) { if ( strcmp(dirBlock.dirEntries[j].name, "") != 0) { memcpy(dirEntry, &dirBlock.dirEntries[j], sizeof(DirEntry)); dirEntry++; cnt++; } if ( cnt == dirEntries ) { free(abspath); return cnt; } } } free(abspath); return cnt; } while(ptr) { // root 내부로 들어감 for ( i = 0 ; i < inodeInfo.blocks ; i++ ) { ReadDirBlock(&dirBlock, inodeInfo.i_block[i]); for ( j = 0 ; j < MAX_INDEX_OF_DIRBLK ; j++ ) { if( strcmp(ptr, dirBlock.dirEntries[j].name) == 0 && dirBlock.dirEntries[j].type == FILE_TYPE_DIR) { ReadInode(&inodeInfo, dirBlock.dirEntries[j].inodeNum); found++; break; } } if( found == 1 ) { found = 0; break; } } ptr = strtok(NULL, "/"); } // 찾는 디렉토리가 없음 if ( j == MAX_INDEX_OF_DIRBLK ) return WRONG_VALUE; for ( i = 0 ; i < inodeInfo.blocks ; i++ ) { ReadDirBlock(&dirBlock, inodeInfo.i_block[i]); for ( j = 0 ; j < MAX_INDEX_OF_DIRBLK ; j++) { // if ( strcmp(dirBlock.dirEntries[j].name, "") != 0) if ( strcmp(dirBlock.dirEntries[j].name, "") != 0 && strcmp(dirBlock.dirEntries[j].name, ".") != 0 && strcmp(dirBlock.dirEntries[j].name, "..") != 0) { memcpy(dirEntry, &dirBlock.dirEntries[j], sizeof(DirEntry)); dirEntry++; cnt++; } if ( cnt == dirEntries ) { free(abspath); return cnt; } } } free(abspath); return cnt; }
int RemoveDir(const char* pDirName) { /* * precondition : usage ) RemoveDir(pDirName); * postcondition : 디렉토리를 제거한다. 단, 리눅스 파일 시스템처럼 빈 디렉토리만 제거가 가능하다. * 성공하면 0을 리턴한다. 실패 했을 때는 -1을 리턴한다. * 실패 원인은 다음과 같다. * 1) 디렉토리에 파일 또는 하위 디렉토리가 존재 할 경우 * 2) 제거하고자 하는 디렉토리가 없을 경우 */ char dirname[NAME_LEN_MAX] = {NULL,}; char* abspath = malloc(strlen(pDirName) + 1); char* ptr = abspath; InodeInfo inodeInfo; DirBlock dirBlock; int i = 0, j = 0; int found = 0; memcpy(abspath, pDirName, strlen(pDirName) + 1); GetEntryName(dirname, abspath); // dirname 최종 디렉토리명 GetEntryPath(abspath, dirname); // abspath는 dirname을 제외한 path ReadInode(&inodeInfo, fileSysInfo.rootInodeNum); ptr = strtok(abspath, "/"); if (ptr == NULL && strcmp(dirname, "") == 0) // root directory block에서 지울때 { if ( RemoveDirentry(&inodeInfo, dirname) == WRONG_VALUE ) { fprintf(stderr, "* RemoveDirentry() error!\n"); return WRONG_VALUE; } free(abspath); return 0; } while(ptr) { // root 내부로 들어감 for ( i = 0 ; i < inodeInfo.blocks ; i++ ) { ReadDirBlock(&dirBlock, inodeInfo.i_block[i]); for ( j = 0 ; j < MAX_INDEX_OF_DIRBLK ; j++ ) { if( strcmp(ptr, dirBlock.dirEntries[j].name) == 0 && dirBlock.dirEntries[j].type == FILE_TYPE_DIR) { ReadInode(&inodeInfo, dirBlock.dirEntries[j].inodeNum); found++; break; } } if( found == 1 ) { found = 0; break; } } ptr = strtok(NULL, "/"); } // 찾는 디렉토리가 없음 if ( j == MAX_INDEX_OF_DIRBLK ) return WRONG_VALUE; if ( RemoveDirentry(&inodeInfo, dirname) == WRONG_VALUE) { free(abspath); return WRONG_VALUE; } free(abspath); return 0; }
int MakeDir(const char* pDirName) { /* * precondition : usage ) MakeFir(pDirName); * postcondition : 디렉토리를 생성한다. * 성공하면 0을 리턴한다. 실패 했을 때는 -1을 리턴한다. * 실패 원인은 생성하고자 하는 디렉토리의 이름과 * 동일한 디렉토리 또는 파일이 존재할 경우이다. */ char dirname[NAME_LEN_MAX] = {NULL,}; char* abspath = malloc(strlen(pDirName) + 1); char* ptr = abspath; InodeInfo inodeInfo; DirBlock dirBlock; int i = 0, j = 0; int found = 0; memcpy(abspath, pDirName, strlen(pDirName) + 1); GetEntryName(dirname, abspath); // dirname 최종 디렉토리명 GetEntryPath(abspath, dirname); // abspath는 dirname을 제외한 path ReadInode(&inodeInfo, fileSysInfo.rootInodeNum); ptr = strtok(abspath, "/"); if (!ptr) // root directory block에 생성할때 { if ( MakeDirentry(&inodeInfo, dirname) == WRONG_VALUE ) { fprintf(stderr, "* MakeDirentry() error!\n"); return WRONG_VALUE; } free(abspath); return 0; } while(ptr) { // root directory block에 생성하지 않고 더 내부로 들어감 for ( i = 0 ; i < inodeInfo.blocks ; i++ ) { ReadDirBlock(&dirBlock, inodeInfo.i_block[i]); for ( j = 0 ; j < MAX_INDEX_OF_DIRBLK ; j++ ) { if( strcmp(ptr, dirBlock.dirEntries[j].name) == 0 && dirBlock.dirEntries[j].type == FILE_TYPE_DIR) { ReadInode(&inodeInfo, dirBlock.dirEntries[j].inodeNum); found++; break; } } if( found == 1 ) { found = 0; break; } } ptr = strtok(NULL, "/"); } if ( j == MAX_INDEX_OF_DIRBLK ) return WRONG_VALUE; if ( MakeDirentry(&inodeInfo, dirname) == WRONG_VALUE) { free(abspath); return WRONG_VALUE; } free(abspath); return 0; }
int RemoveFile(const char* pFileName) { /* * precondition : usage ) RemoveFile(pFileName); * postcondition : 파일을 제거한다. 단, open된 파일을 제거 할 수 없다. * 성공하면 0을 리턴한다. 실패 했을 때는 -1을 리턴한다. * 실패 원인은 다음과 같다. * 1) 제거할 파일 이름이 없을 경우 * 2) 제거될 파일이 open 되어 있을 경우 */ char filename[NAME_LEN_MAX] = {NULL,}; char* abspath = malloc(strlen(pFileName) + 1); char* ptr = abspath; InodeInfo inodeInfo; DirBlock dirBlock; int i = 0, j = 0; int found = 0; int parent_blockno = 0; memcpy(abspath, pFileName, strlen(pFileName) + 1); GetEntryName(filename, abspath); // dirname 최종 디렉토리명 // GetEntryPath(abspath, filename); // abspath는 dirname을 제외한 path ReadInode(&inodeInfo, fileSysInfo.rootInodeNum); ptr = strtok(abspath, "/"); while(ptr) { // root 내부로 들어감 for ( i = 0 ; i < inodeInfo.blocks ; i++ ) { ReadDirBlock(&dirBlock, inodeInfo.i_block[i]); for ( j = 0 ; j < MAX_INDEX_OF_DIRBLK ; j++ ) { if( strcmp(ptr, dirBlock.dirEntries[j].name) == 0 && dirBlock.dirEntries[j].type == FILE_TYPE_DIR ) { parent_blockno = inodeInfo.i_block[i]; ReadInode(&inodeInfo, dirBlock.dirEntries[j].inodeNum); found++; break; } else if ( strcmp(filename, dirBlock.dirEntries[j].name) == 0 && dirBlock.dirEntries[j].type == FILE_TYPE_FILE) { parent_blockno = inodeInfo.i_block[i]; ReadInode(&inodeInfo, dirBlock.dirEntries[j].inodeNum); found++; break; } } if( found == 1 ) { found = 0; break; } } ptr = strtok(NULL, "/"); } // 찾는 중간 디렉토리가 없음 if ( j == MAX_INDEX_OF_DIRBLK ) return WRONG_VALUE; /////////////////////////////////////////////////// // 여기부터 해당 파일 삭제 // 사용중인 block 해제 for ( i = 0 ; i < inodeInfo.blocks ; i++ ) { if(SetBlockAllocToFree(inodeInfo.i_block[i]) == WRONG_VALUE) { fprintf(stderr, "* RemoveFile() Error!\n"); return WRONG_VALUE; } } // 사용중인 inode 삭제 for ( i = 0 ; i < MAX_INDEX_OF_DIRBLK ; i++ ) { if ( strcmp(dirBlock.dirEntries[i].name, filename) == 0 ) { if( SetInodeAllocToFree(dirBlock.dirEntries[i].inodeNum) == WRONG_VALUE) { fprintf(stderr, "* RemoveFile() Error!\n"); return WRONG_VALUE; } strcpy(dirBlock.dirEntries[i].name, ""); WriteDirBlock(&dirBlock, parent_blockno); break; } } // /////////////////////////////////////////////////// }
int WriteFile(int fileDesc, char* pBuffer, int length) { /* * precondition : usage) WriteFile(fileDesc, pBuffer, length); * fileDesc : file descriptor * pBuffer : 저장할 데이터를 포함하는 메모리의 주소 * length : 저장될 데이터의 길이 * postcondition : open된 파일에 데이터를 저장한다. * 성공하면 저장된 데이터의 길이 값을 리턴한다. 실패 했을때는 -1을 리턴한다. */ int i = 0, j = 0; int block = fileDescTable.file[fileDesc].offset / BLOCK_SIZE; int offset = fileDescTable.file[fileDesc].offset % BLOCK_SIZE; int exsist = 0; int remain = length; char buf[BLOCK_SIZE] = {NULL,}; Buf* pBuf = NULL; InodeInfo inodeInfo; DirBlock dirBlock; if ( fileDescTable.file[fileDesc].valid_bit != 1 ) return WRONG_VALUE; ReadInode(&inodeInfo, fileDescTable.file[fileDesc].inodeNo); // lseek 함수가 없기 때문에 inode에 저장된 indirect block 갯수보다 // 위에서 계산된 block(fd[].offset / BLOCK_SIZE)이 클수가 없음 // 따라서 예외처리 안해도 됨 // 첫번째 블락에 pBuffer 쓰기 pBuf = BufRead(inodeInfo.i_block[block]); memcpy(&buf, pBuf->pMem, BLOCK_SIZE); memcpy(&buf + offset, pBuffer, (remain + offset >= BLOCK_SIZE) ? BLOCK_SIZE - offset : remain); BufWrite(pBuf, &buf, BLOCK_SIZE); if ( inodeInfo.size < (remain - offset) ) inodeInfo.size = remain - offset; fileDescTable.file[fileDesc].offset += (remain + offset >= BLOCK_SIZE) ? BLOCK_SIZE - offset : remain; remain -= (BLOCK_SIZE - offset); if ( remain <= 0 ) return length; // 두번째 블락부터 pBuffer 쓰기 for ( j = block + 1 ; j < (length / BLOCK_SIZE + 1) + block ; j++ ) { // inodeInfo.blocks가 모자르면 새로 할당해줘야함 if ( j == inodeInfo.blocks && inodeInfo.blocks < NUM_OF_INDIRECT_BLOCK ) { inodeInfo.i_block[inodeInfo.blocks++] = GetFreeBlock(); SetBlockFreeToAlloc(); } if ( j == NUM_OF_INDIRECT_BLOCK ) { // indirect block 부족으로 쓰기 실패 WriteInode(&inodeInfo, fileDescTable.file[fileDesc].inodeNo); return length - remain; } pBuf = BufRead(inodeInfo.i_block[j]); BufWrite(pBuf, pBuffer + BLOCK_SIZE * ((j - (block + 1) + 1)), remain > BLOCK_SIZE ? BLOCK_SIZE : remain); fileDescTable.file[fileDesc].offset += (remain > BLOCK_SIZE ? BLOCK_SIZE : remain); remain = remain - BLOCK_SIZE; if ( remain <= 0 ) { inodeInfo.size += BLOCK_SIZE + remain; WriteInode(&inodeInfo, fileDescTable.file[fileDesc].inodeNo); return length; } else inodeInfo.size += BLOCK_SIZE; } return 0; }
int OpenFile(const char* pFileName, OpenFlag flag) { /* * precondition : usage) OpenFile(absfilepath, flag); * pFileName은 오픈할 파일의 이름. 단, 파일 이름은 절대경로이다. * flag는 OPEN_FLAG_READWRITE, OPEN_FLAG_CREATE가 있다. * postcondition : 파일을 open한다. * 성공하면, file descriptor를 리턴한다. * 이 file descriptor는 file descriptor table의 entry의 index값으로 정의된다. * 실패했을때는 -1을 리턴한다. */ InodeInfo inodeInfo, newInode; DirBlock dirBlock; char* abspath = malloc(strlen(pFileName) + 1); char* ptr = malloc(strlen(pFileName) + 1); char filename[NAME_LEN_MAX]; int i = 0, j = 0; int found = 0; int fd = 0; int parent_inodeno = 0; int current_inodeno = 0; strcpy(abspath, pFileName); strcpy(ptr, pFileName); memset(&newInode, 0, sizeof(InodeInfo)); if (*ptr != '/') // 절대경로의 시작이 '/'가 아닐때 { free(abspath); free(ptr); return -1; } // root inode와 block을 읽음 // filename에 파일 경로를 얻어냄 if ( GetEntryName(filename, abspath) == WRONG_VALUE) { fprintf(stderr, "* GetEntryName error!\n"); fprintf(stderr, "* filename is too long!\n"); } GetEntryPath(abspath, filename); ReadInode(&inodeInfo, fileSysInfo.rootInodeNum); abspath = strtok(abspath, "/"); while(abspath) { for ( i = 0 ; i < inodeInfo.blocks ; i++ ) { if( inodeInfo.type == FILE_TYPE_DIR ) { ReadDirBlock(&dirBlock, inodeInfo.i_block[i]); for ( j = 0 ; j < MAX_INDEX_OF_DIRBLK ; j++ ) { if ( strcmp(dirBlock.dirEntries[j].name, abspath) == 0 && dirBlock.dirEntries[j].type == FILE_TYPE_DIR) {// 마지막 상위 디렉토리(찾는 파일 또는 디렉토리의 ..)를 찾으면 ReadInode(&inodeInfo, dirBlock.dirEntries[j].inodeNum); parent_inodeno = dirBlock.dirEntries[j].inodeNum; found++; break; } } if ( found == 1 ) { found = 0; break; } } } abspath = strtok(NULL, "/"); } if ( strcmp(filename, "") == 0) // 파일명이 없으면 실패리턴 { if( i == inodeInfo.blocks ) { free(abspath); free(ptr); return WRONG_VALUE; // 블록 전부를 검색했지만 일치하는 결과가 없으므로 실패 } if( found == 0) { free(abspath); free(ptr); return WRONG_VALUE; // dir을 못찾았을 } } // 여기까지 왔으면 해당 디렉토리 찾은 것 switch(flag) { case OPEN_FLAG_READWRITE: // 파일명 찾고 permission readwrite로 for ( i = 0 ; i < inodeInfo.blocks ; i++ ) { if( inodeInfo.type == FILE_TYPE_DIR ) ReadDirBlock(&dirBlock, inodeInfo.i_block[i]); for ( j = 0 ; j < MAX_INDEX_OF_DIRBLK ; j++ ) { if ( strcmp(dirBlock.dirEntries[j].name, filename) == 0 && dirBlock.dirEntries[j].type == FILE_TYPE_FILE) {// 파일명 찾으면 // permission read로 ReadInode(&inodeInfo, dirBlock.dirEntries[j].inodeNum); inodeInfo.mode = FILE_MODE_READWRITE; for ( fd = 0 ; fd < FS_INODE_COUNT ; fd++ ) {// 이미 open 했던 경우 if ( fileDescTable.file[fd].inodeNo == dirBlock.dirEntries[j].inodeNum ) { fileDescTable.file[fd].offset = 0; free(abspath); free(ptr); return fd; } } for ( fd = 0 ; fd < FS_INODE_COUNT ; fd++ ) {// 처음 open 하는 경우 if ( fileDescTable.file[fd].valid_bit == 0 ) { fileDescTable.file[fd].inodeNo = dirBlock.dirEntries[j].inodeNum; fileDescTable.file[fd].offset = 0; fileDescTable.file[fd].valid_bit = 1; free(abspath); free(ptr); return fd; } } } } } break; case OPEN_FLAG_CREATE: // 파일명 찾고 있으면 덮어쓰고 없으면 생성 // 파일명 찾고 permission readonly로 // 파일이 존재할 경우 for ( i = 0 ; i < inodeInfo.blocks ; i++ ) { if( inodeInfo.type == FILE_TYPE_DIR ) ReadDirBlock(&dirBlock, inodeInfo.i_block[i]); for ( j = 0 ; j < MAX_INDEX_OF_DIRBLK ; j++ ) { if ( strcmp(dirBlock.dirEntries[j].name, filename) == 0 && dirBlock.dirEntries[j].type == FILE_TYPE_FILE) {// 파일명 찾으면 // permission readwrite로 ReadInode(&inodeInfo, dirBlock.dirEntries[j].inodeNum); inodeInfo.mode = FILE_MODE_READWRITE; for ( fd = 0 ; fd < FS_INODE_COUNT ; fd++ ) {// 이미 open 했던 경우 if ( fileDescTable.file[fd].inodeNo == dirBlock.dirEntries[j].inodeNum ) { fileDescTable.file[fd].offset = 0; free(abspath); free(ptr); return fd; } } for ( fd = 0 ; fd < FS_INODE_COUNT ; fd++ ) {// 처음 open 하는 경우 if ( fileDescTable.file[fd].valid_bit == 0 ) { fileDescTable.file[fd].inodeNo = dirBlock.dirEntries[j].inodeNum; fileDescTable.file[fd].offset = 0; fileDescTable.file[fd].valid_bit = 1; free(abspath); free(ptr); return fd; } } } } } // 파일이 없어서 생성해야 하는 경우 for ( i = 0 ; i < inodeInfo.blocks ; i++ ) { if( inodeInfo.type == FILE_TYPE_DIR ) ReadDirBlock(&dirBlock, inodeInfo.i_block[i]); for ( j = 0 ; j < MAX_INDEX_OF_DIRBLK ; j++ ) { if ( strcmp(dirBlock.dirEntries[j].name,"") == 0 ) {// 엔트리가 비어있으면 strcpy(dirBlock.dirEntries[j].name, filename); dirBlock.dirEntries[j].type = FILE_TYPE_FILE; dirBlock.dirEntries[j].inodeNum = GetFreeInode(); WriteDirBlock(&dirBlock, inodeInfo.i_block[i]); // 변경된 상위디렉토리의 dirBlock 갱신 newInode.size = 0; newInode.type = FILE_TYPE_FILE; newInode.mode = FILE_MODE_READWRITE; newInode.blocks = 1; newInode.i_block[0] = GetFreeBlock(); WriteInode(&newInode, dirBlock.dirEntries[j].inodeNum); SetInodeFreeToAlloc(); SetBlockFreeToAlloc(); for ( fd = 0 ; fd < FS_INODE_COUNT ; fd++ ) {// 파일 디스크립터 생성 if ( fileDescTable.file[fd].valid_bit == 0 ) { fileDescTable.file[fd].inodeNo = dirBlock.dirEntries[j].inodeNum; fileDescTable.file[fd].valid_bit = 1; free(abspath); free(ptr); return fd; } } } } } // 사용 가능한 다이렉트블락이 없다 -> 실패리턴 if ( inodeInfo.blocks != NUM_OF_INDIRECT_BLOCK ) { // 사용 가능한 다이렉트블락이 있다 -> 진행 inodeInfo.blocks++; inodeInfo.i_block[inodeInfo.blocks-1] = GetFreeBlock(); SetBlockFreeToAlloc(); WriteInode(&inodeInfo, parent_inodeno); ////////////////////////////////////////////////////////////// // 생성한 directory block 초기화 ReadDirBlock(&dirBlock, inodeInfo.i_block[inodeInfo.blocks-1]); strcpy(dirBlock.dirEntries[0].name, filename); dirBlock.dirEntries[0].inodeNum = GetFreeInode(); SetInodeFreeToAlloc(); dirBlock.dirEntries[0].type = FILE_TYPE_FILE; WriteDirBlock(&dirBlock, inodeInfo.i_block[inodeInfo.blocks-1]); return 0; // ////////////////////////////////////////////////////////////// } break; } // 여기까지 왔으면 못찾은것임 free(abspath); free(ptr); return WRONG_VALUE; }
ExtFile *Partition::ReadDirectory(EXT2DIRENT *dirent) { string filename; ExtFile *newEntry; char *pos; int ret; if(!dirent) return NULL; if(!dirent->dirbuf) { dirent->dirbuf = (EXT2_DIR_ENTRY *) new char[blocksize]; if(!dirent->dirbuf) return NULL; ret = ReadDataBlock(&dirent->parent->inode, dirent->next_block, dirent->dirbuf); if(ret < 0) return NULL; dirent->next_block++; } again: if(!dirent->next) dirent->next = dirent->dirbuf; else { pos = (char *) dirent->next; dirent->next = (EXT2_DIR_ENTRY *)(pos + dirent->next->rec_len); if(IS_BUFFER_END(dirent->next, dirent->dirbuf, blocksize)) { dirent->next = NULL; if(dirent->read_bytes < dirent->parent->file_size) { ret = ReadDataBlock(&dirent->parent->inode, dirent->next_block, dirent->dirbuf); if(ret < 0) return NULL; dirent->next_block++; goto again; } return NULL; } } dirent->read_bytes += dirent->next->rec_len; filename.assign(dirent->next->name, dirent->next->name_len); if((filename.compare(".") == 0) || (filename.compare("..") == 0)) goto again; newEntry = ReadInode(dirent->next->inode); if(!newEntry) { LOG("Помилка читання Inode %d батьківський inode %d.\n", dirent->next->inode, dirent->parent->inode_num); return NULL; } newEntry->file_type = dirent->next->filetype; newEntry->file_name = filename; return newEntry; }
int tiny_unlink(const char *path) { tiny_inode i_tmp; tiny_inode target; tiny_dentry *pDentry; char *token; char *path_copy; char *dir_name; char *base_name; int target_inodeno; int ret = 0; int i, j; /* Get inode of the parent directory */ path_copy = (char*)malloc(strlen(path) + 1); strcpy(path_copy, path); dir_name = dirname(path_copy); token = strtok(dir_name, "/"); ReadInode(&i_tmp, tiny_superblk.s_rdirino); while (token) { pDentry = __find_dentry(&i_tmp, token); if (!pDentry || pDentry->type == FILE_TYPE_FILE) { ret = -ENOTDIR; goto err; } ReadInode(&i_tmp, pDentry->inodeNum); token = strtok(NULL, "/"); } /* Get dentry of the target */ free(path_copy); path_copy = (char*)malloc(strlen(path) + 1); strcpy(path_copy, path); base_name = basename(path_copy); target_inodeno = __find_dentry_and_remove(&target, &i_tmp, base_name); if (target_inodeno < 0) { ret = -ENOENT; goto err; } for ( i = 0 ; i < target.i_nblk ; i++ ) { SetBlockAllocToFree(target.i_block[i]); } SetInodeAllocToFree(target_inodeno); err: free(path_copy); int qid = OpenMQ(5000); if(qid < 0) { printf("q open fail\n"); return ; } SuperBlk_t sb; sb.fsi = tiny_superblk; if(SendMQ(qid, MSG_SUPER_BLOCK, &sb) < 0) { printf("superblk send fail\n"); return ; } InodeBitmap_t ibm; ibm.size = tiny_superblk.s_ninode / 8; /*byte*/ memcpy(ibm.s_ibitmap_ptr, tiny_superblk.s_ibitmap_ptr, ibm.size); if(SendMQ(qid, MSG_INODE_BITMAP, &ibm) < 0) { printf("ibm send fail\n"); return ; } BlockBitmap_t bbm; bbm.size = tiny_superblk.s_datablk_size / 8; /*byte*/ memcpy(bbm.s_dbitmap_ptr, tiny_superblk.s_dbitmap_ptr, bbm.size); if(SendMQ(qid, MSG_BLOCK_BITMAP, &bbm) < 0) { printf("bbm send fail\n"); return ; } FileIO_t fio; memcpy(&fio.inode, &target, sizeof(tiny_inode)); fio.dentry.inodeNum = target_inodeno; fio.flag = 'd'; if(SendMQ(qid, MSG_FILEIO, &fio) < 0) { printf("fio send fail\n"); return ; } return ret; }