void FileSystem::writeInodeEntry(PartitionEntry *partition, unsigned int inodeNumber) { InodeData inode = readInode(partition, lostFoundInode); InodeData inode_cur = readInode(partition, inodeNumber); int blockNumber = readDataBlocks(partition, lostFoundInode, (blockSize / SECTOR_SIZE_BYTES), inode.dataBlocksPointers, 0, 0, 2); if (blockNumber == -1) return; unsigned int blockSector = getBlockSector(partition, blockNumber); unsigned char buf[blockSize]; unsigned int i = 0; readSectors(blockSector, (blockSize / SECTOR_SIZE_BYTES), buf); while (i < blockSize - 1) { struct ext2_dir_entry_2 *fileEntry = (struct ext2_dir_entry_2 *) (buf + i); if (fileEntry->rec_len > ((((__u16 ) 8 + fileEntry->name_len) + 3) & ~0x03)) { fileEntry->rec_len = (((__u16 ) 8 + fileEntry->name_len) + 3) & ~0x03; i = i + fileEntry->rec_len; fileEntry = (struct ext2_dir_entry_2*) (buf + i); fileEntry->inode = inodeNumber; sprintf(fileEntry->name, "%d", inodeNumber); fileEntry->rec_len = (__u16)(blockSize - i); fileEntry->name_len = (__u8)(strlen(fileEntry->name)); if (!(inode_cur.fileType & EXT2_S_IFREG) == 0) fileEntry->file_type = 1; else if (!(inode_cur.fileType & EXT2_S_IFDIR) == 0) fileEntry->file_type = 2; writeSectors(blockSector, (blockSize / SECTOR_SIZE_BYTES), buf); return; } else { i = i + fileEntry->rec_len; } } }
struct ext2_inode getInode(int fd, int inode_num, struct ext2_group_desc *gds, int p_start, int inodes_per_group) { int x; int y; int remainder; int byte_offset; int group_num; int sector; int sector_offset; struct ext2_inode myinode; x = inode_num; y = inodes_per_group; group_num = x / y; remainder = fmod(x, y); x = remainder; y = 4; sector_offset = x / y; remainder = fmod(x, y); sector = gds[group_num].bg_inode_table * 2 + p_start + sector_offset; if (remainder > 0) { byte_offset = (remainder - 1) * 128; } else { byte_offset = 0; } myinode = readInode(fd, sector, byte_offset); return myinode; }
void Ext2FS::initFsRoot() { readSuperBlock(); _blockSize = 1024 << _sb->log_block_size; int i = (_sb->block_count / _sb->blocks_per_group) + ((_sb->block_count % _sb->blocks_per_group) ? 1 : 0); int j = (_sb->inodes_count / _sb->inodes_per_group) + ((_sb->inodes_count % _sb->inodes_per_group) ? 1 : 0); _groupNumber = (i > j) ? i : j; readGroupBlock(); struct file *rootFile = getRoot(); struct filePrivateData *data = (struct filePrivateData*)kmalloc(sizeof(struct filePrivateData)); rootFile->name = (char*)kmalloc(strlen("/") + 1); strcpy(rootFile->name, "/"); data->inum = EXT2_INUM_ROOT; data->inode = readInode(EXT2_INUM_ROOT); rootFile->content = 0; rootFile->privateData = (void*)data; rootFile->parent = rootFile; rootFile->leaf = getDirEntries(rootFile); rootFile->next = 0; rootFile->prev = 0; }
/** * Opens a binary file on the disk for storing data. */ fd_t* openf(char* name) { fd_t * temp = NULL; superBlock_t* spB; inode_t* nodep; readSuperBlock(spB); int i=0, j=0; while (i<(spB->_numberOfInodes)) { //printSupBlock(spB); readInode(nodep, j); if (name == nodep->_filename) //Exist !! open it!! { temp->inodeBlockNum = j; temp->fileptr = nodep; //returns file descriptor return temp; } else { i++; j++; } } //printInodesTest(nodep); // file not found, create one writeSuperBlock(spB); writeInode(nodep,spB->_firstBlockOfFreeList); return temp; }
bool Ext2FS::isDirectory(struct file *f) { struct filePrivateData *data = (struct filePrivateData*)f->privateData; if(!data->inode) data->inode = readInode(data->inum); return (data->inode->mode & EXT2_DIR); }
char* Ext2FS::readFile(const char *path) { struct file *f = 0; if((f = getFile(path))) { struct filePrivateData *data = (struct filePrivateData*)f->privateData; if(!data->inode) readInode(data->inum); f->size = data->inode->size; return readFile(f); } else return 0; }
/*----------------------------------------------------------------- Function: scanMinixSubDirectories Parameters: char *path - name of the subdirectory (with no prefix) struct dentry *tbl - pointer to a directory table (array of entries) struct minix_inode *inoPtr - pointer to memory to store inode int parentInoNum - for passing parent inode number to next iteration int *parentInoNum - for returning the parent inode number of leaf directory Returns: inode number where directory is stored and the parent inode number in *parentInoNum. Description: Recursive function that scans directory to find inode and contents of a directory. Fills in the memory pointed by dirTablePtr with the directory table named "path". Returns the inode number where the directory table is stored. -----------------------------------------------------------------*/ int scanMinixSubDirectories(char *path, struct dentry *tbl, int numrecords, struct minix_inode *inoPtr, int parentInoNum, int *retParentInoNum) { char subDirName[BUFSIZ]; // for loading in the subdirectory name char *pt=subDirName; // pointer to copy name int ix; // index for seaching through table int retcd = ERR1; // for return code struct minix_inode ino; struct dentry *nextTbl; // Get name to search in directory table (and remove from head of path) while(*path!='/' && *path!='\0') *pt++=*path++; *pt='\0'; // terminates string if(*path == '/') path++; // skips the '/' // Search for sub directory for(ix = 0 ; ix < numrecords ; ix++) { if((strncmp(subDirName, tbl[ix].name, strlen(subDirName)) == 0)) // found it { readInode(tbl[ix].ino, &ino); // get inode if(*path == '\0') // if at end of path, then found directory { memcpy(inoPtr, &ino, sizeof(struct minix_inode)); // Copy root inode *retParentInoNum = parentInoNum; retcd = tbl[ix].ino; } else // otherwise need to find next subdirectory in path { nextTbl = getMinixDirTable(&ino, &numrecords); // the following is a recursive function retcd = scanMinixSubDirectories(path, nextTbl, numrecords, inoPtr, tbl[ix].ino, retParentInoNum); free(nextTbl); // frees allocated memory } break; // leave the loop } } if(ix == numrecords) // did not find the name in the table { printf("Could not find subdirectory %s\n", subDirName); retcd = ERR1; } return(retcd); }
void deleteInode(disk_t disk, Inode* inode){ char * databuf = malloc(sizeof(char) * disk->block_size); readblock(disk,inode->block,databuf); int i; bool gotsize = false; bool gotpointers = false; bool gotlink = false; bool gotname = false; int numberbufIndex = 0; char * numberbuf = malloc(sizeof(char) * 16); for(i = 0; databuf[i] != '\0' && i < disk->block_size;i+=1){ if(!gotsize){ if(databuf[i] == '\n'){ gotsize = true; } }else if(!gotpointers){ if(databuf[i] == '\n'){ gotpointers = true; } }else if(!gotname){ if(databuf[i] == '\n'){ gotname = true; } }else{ gotlink = true; numberbuf[numberbufIndex] = databuf[i]; numberbufIndex +=1; } } int link; if(gotlink){ numberbuf[numberbufIndex] = '\0'; link = str2int(numberbuf); Inode * newinode = readInode(disk,link); deleteInode(disk,newinode); freeInode(newinode); } int * blockmap = read_block_map(disk); blockmap[inode->block] = 0; write_block_map(disk,blockmap); free(blockmap); free(databuf); free(numberbuf); }
/*----------------------------------------------------------------- Function: findInodeFromPath Parameters: char *path - full path name of directory/file struct minix_inode *inoPtr - pointer to location for loading inode int *parentInoNum - the inode number of the parent. Returns: Inode number or ERR1 when and error occurs. and sets *parentInoNum to the value of the parent inode number. Description: Finds the inode of dir/file and loads it into the struct minix_inode referenced by inoPtr. Retures OK if all went well and ERR1 upon detection of an error. If the directory is not the root directory, the recursive function scanMinixSubDirectories is called to find it. -----------------------------------------------------------------*/ int findInodeFromPath(char *path, struct minix_inode *inoPtr, int *parentInodeNum) { struct minix_inode ino; int inodeNum = 1; // set do root directory inode number int numrecords; struct dentry *rootdir; readInode(inodeNum, &ino); // get root inode if(strcmp(path, "/") == 0) { memcpy(inoPtr, &ino, sizeof(struct minix_inode)); // Copy root inode *parentInodeNum = 1; // root parent } else { if(*path == '/') path++; // skip over the initial / rootdir = getMinixDirTable(&ino, &numrecords); // the following is a recursive function inodeNum = scanMinixSubDirectories(path, rootdir, numrecords, inoPtr, 1, parentInodeNum); free(rootdir); // frees allocated memory } return(inodeNum); }
/** * A test program for testing file system operations. * * @param args - a list of arguments */ int main(int argc, char* argv[]) { int error; superBlock_t superBlock; superBlock_t* spB = &superBlock; inode_t node; inode_t* nodep = &node; initializeInode(nodep); char path[25] = "storageDisk"; if((error = format( 100000, path))) { printf("There was an error formatting the disk\n"); } printf("\nHello World\n"); //openDiskFile(path); readSuperBlock(spB); printSupBlock(spB); readInode(nodep, 1); printInodesTest(nodep); //closeDiskFile(); return 0; }
void FileSystem::readRootInode(PartitionEntry *partition) { unsigned int i; InodeData inode = readInode(partition, 2); blockSize = 1024 << super_block.s_log_block_size; firstRootBataBlock = inode.dataBlocksPointers[0]; readDataBlocks(partition, 2, 2, inode.dataBlocksPointers, 1, 1, 2); readDataBlocks(partition, 2, 2, inode.dataBlocksPointers, 2, 1, 2); for (i = 11; i <= super_block.s_inodes_count; i++) { InodeData in = readInode(partition, i); if (!(in.fileType & EXT2_S_IFDIR) == 0 && checkInodeBitmap(partition, i) == 1) { readDataBlocks(partition, i, -1, in.dataBlocksPointers, 0, 2, 2); } } for (i = 11; i <= super_block.s_inodes_count; i++) { unsigned int bitmapValue = checkInodeBitmap(partition, i); if (bitmapValue == 1 && inodeMap[i] == 0) { InodeData in = readInode(partition, i); if (in.fileType != 0) { QString tmpStr = QString("Inode ") + QString::number(i) + QString(" has invalid entry in inode bitmap. Bitmap value: ") + QString::number(bitmapValue) + QString(", collected value:") + QString::number(inodeMap[i]) + QString(".\n"); textBrowser->append(tmpStr); errorQt++; if (performRepair) { writeInodeEntry(partition, i); } } } } readDataBlocks(partition, 2, 2, inode.dataBlocksPointers, 1, 1, 2); readDataBlocks(partition, 2, 2, inode.dataBlocksPointers, 3, 1, 2); for (i = 1; i <= super_block.s_inodes_count; i++) { InodeData in = readInode(partition, i); if (inodeLinkCount[i] != in.hardLinksQt) { if (in.fileType != 0) { QString tmpStr = QString("Inode ") + QString::number(i) + QString( " has invalid inode count in inode entry. Current value : ") + QString::number(in.hardLinksQt) + QString(", collected value:") + QString::number(inodeLinkCount[i]) + QString(".\n"); textBrowser->append(tmpStr); errorQt++; } if (performRepair) { UpdateHardLinkCounter(partition, i, inodeLinkCount[i]); } } } readDataBlocks(partition, 2, 2, inode.dataBlocksPointers, 4, 1, 2); for (i = 1; i <= super_block.s_blocks_count; i++) { unsigned int bitmapValue = checkBlockBitmap(partition, i); if (i < firstRootBataBlock && checkBlockBitmap(partition, i) == 0) { QString tmpStr = QString("Block ") + i + QString( " has invalid entry in block bitmap. Bitmap value: 0, collected value: 1.\n"); textBrowser->append(tmpStr); errorQt++; if (performRepair) { setBlockBitmap(partition, i); } } if (blockMap[i] == 1 && bitmapValue != blockMap[i]) { QString tmpStr = QString("Block ") + QString::number(i) + QString(" has invalid entry in block bitmap. Bitmap value: ") + QString::number(bitmapValue) + QString(", collected value: ") + QString::number(blockMap[i]) + QString(".\n"); textBrowser->append(tmpStr); errorQt++; if (performRepair) { setBlockBitmap(partition, i); } } } }
unsigned int FileSystem::parseFilesystem(PartitionEntry *partition, unsigned int blockNumber, unsigned int passNumber, unsigned int currentInode, unsigned int parentInode, int performCheck) { unsigned char buf[blockSize]; unsigned int i = 0; struct ext2_dir_entry_2 *fileEntry; unsigned int blockSector = getBlockSector(partition, blockNumber); readSectors(blockSector, (blockSize / SECTOR_SIZE_BYTES), buf); while (i < blockSize - 1) { fileEntry = (struct ext2_dir_entry_2 *) (buf + i); if (fileEntry->inode == 0) return -1; if (currentInode == 2 && parentInode == 2 && (strcmp(fileEntry->name, "lost+found") == 0)) { lostFoundInode = fileEntry->inode; } if (passNumber == 1 && performCheck == 1) { if (fileEntry->inode != currentInode && (strcmp(fileEntry->name, ".") == 0)) { QString tmpStr = QString("Entry '.' has inode ") + QString::number(fileEntry->inode) + QString(" instead of ") + QString::number(currentInode) + QString(".\n"); textBrowser->append(tmpStr); errorQt++; fileEntry->inode = currentInode; writeSectors(blockSector, (blockSize / SECTOR_SIZE_BYTES), buf); } if (fileEntry->inode != parentInode && (!strcmp(fileEntry->name, ".."))) { QString tmpStr = QString("Entry '..' has inode ") + QString::number(fileEntry->inode) + QString(" instead of ") + QString::number(parentInode) + QString(".\n"); textBrowser->append(tmpStr); errorQt++; fileEntry->inode = parentInode; writeSectors(blockSector, (blockSize / SECTOR_SIZE_BYTES), buf); } } else if (passNumber == 2 && performCheck == 1) { inodeMap[fileEntry->inode] = 1; } else if (passNumber == 3 && performCheck == 1) { inodeLinkCount[fileEntry->inode] += 1; } else if (passNumber == 4 && performCheck == 1) { blockMap[blockNumber] = 1; } if (strcmp(fileEntry->name, ".") && strcmp(fileEntry->name, "..") && performCheck != 0) { if (performCheck == 2) { inodeMap[fileEntry->inode] = 1; } InodeData inode = readInode(partition, fileEntry->inode); if ((inode.fileType & 0xF000) == EXT2_S_IFREG && passNumber == 4) { readDataBlocks(partition, fileEntry->inode, currentInode, inode.dataBlocksPointers, passNumber, performCheck, 1); } else if (!(inode.fileType & EXT2_S_IFDIR) == 0) { readDataBlocks(partition, fileEntry->inode, currentInode, inode.dataBlocksPointers, passNumber, performCheck, 2); } } i = i + fileEntry->rec_len; } if (fileEntry != NULL && fileEntry->rec_len > 8 + fileEntry->name_len && (fileEntry->rec_len - 8 - fileEntry->name_len) > 16 && !performCheck) return blockNumber; return -1; }
struct file* Ext2FS::getFile(const char *filename) { char *name; const char *beg_p, *end_p; struct file *file; struct filePrivateData *data; // TODO: Faire le reste ! /*if(path[O] != '/') fp = current->pwd; else*/ file = getRoot(); beg_p = filename; while(*beg_p == '/') beg_p++; end_p = beg_p + 1; while(*beg_p != 0) { data = (struct filePrivateData*)file->privateData; if(!data->inode) data->inode = readInode(data->inum); if(!isDirectory(file)) return 0; while(*end_p != 0 && *end_p != '/') end_p++; name = (char*)kmalloc(end_p - beg_p + 1); memcpy(name, beg_p, end_p - beg_p); name[end_p - beg_p] = 0; if(strcmp("..", name) == 0) file = file->parent; else if(strcmp(".", name) == 0) {} else { //Screen::getScreen().printError("Filename : %s, dir : %s, inum %u", name, file->name, data->inum); //Screen::getScreen().printError("Data inode size : %u", data->inode->size); getDirEntries(file); //Screen::getScreen().printError("Filename : %s, dir : %s", name, file->name); if(!(file = isCachedLeaf(file, name))) { kfree(name); return 0; } } beg_p = end_p; while(*beg_p == '/') beg_p++; end_p = beg_p + 1; kfree(name); } return file; }
struct file* Ext2FS::getDirEntries(struct file *dir) { struct directory_entry *dentry; struct filePrivateData *data = (struct filePrivateData*)dir->privateData; struct file *firstLeaf, *leaf, *prevLeaf; u32 dsize; char *filename; bool fileToClose; if(!data->inode) data->inode = readInode(data->inum); //Screen::getScreen().printError("DirData : %d, %d", data->inode->size, data->inum); if(!isDirectory(dir)) { Screen::getScreen().printError("%s isn't a directory !", dir->name); return 0; } if(!dir->content) { dir->content = readFile(dir); fileToClose = true; } else fileToClose = false; dsize = data->inode->size; dentry = (struct directory_entry*) dir->content; firstLeaf = prevLeaf = dir->leaf; while(dentry->inode && dsize) { filename = (char*)kmalloc(dentry->name_len + 1); memcpy(filename, &(dentry->name), dentry->name_len); filename[dentry->name_len] = 0; if(strcmp(".", filename) && strcmp("..", filename)) { if(!(leaf = isCachedLeaf(dir, filename))) { struct filePrivateData *privData = (struct filePrivateData*)kmalloc(sizeof(struct filePrivateData)); leaf = (struct file*)kmalloc(sizeof(struct file)); leaf->name = (char*)kmalloc(dentry->name_len + 1); strcpy(leaf->name, filename); //Screen::getScreen().printDebug("Name : %s", filename); //Screen::getScreen().printDebug("Dentry : %x, %u, %c, %u, %u", dentry->file_type, dentry->inode, 'c', dentry->name_len, dentry->record_entry); privData->inum = dentry->inode; privData->inode = readInode(dentry->inode); leaf->size = privData->inode->size; leaf->content = 0; leaf->parent = dir; leaf->leaf = 0; leaf->privateData = privData; if(prevLeaf) { leaf->next = prevLeaf->next; if(prevLeaf->next) prevLeaf->next->prev = leaf; prevLeaf->next = leaf; leaf->prev = prevLeaf; } else { leaf->next = 0; leaf->prev = 0; firstLeaf = leaf; } } prevLeaf = leaf; } kfree(filename); dsize -= dentry->record_entry; dentry = (struct directory_entry*) ((char*) dentry + dentry->record_entry); } dir->leaf = firstLeaf; if(fileToClose) { kfree(dir->content); dir->content = 0; } return firstLeaf; }
Inode* readInode(disk_t disk, int block){ char * databuf = malloc(sizeof(char) * disk->block_size); readblock(disk,block,databuf); int size; int i,j; char * name; bool gotsize = false; bool gotpointers = false; bool gotlink = false; bool gotname = false; int numberbufIndex = 0; char * numberbuf = malloc(sizeof(char) * 16); int * pointers = malloc(sizeof(int) * disk->size); int pointersIndex = 0; for(i = 0; databuf[i] != '\0' && i < disk->block_size;i+=1){ if(!gotsize){ if(databuf[i] == '\n'){ numberbuf[numberbufIndex] = '\0'; size = str2int(numberbuf); numberbufIndex = 0; gotsize = true; }else{ numberbuf[numberbufIndex] = databuf[i]; numberbufIndex +=1; } }else if(!gotpointers){ if(databuf[i] == '\n'){ gotpointers = true; numberbuf[0] = '\0'; numberbufIndex = 0; }else{ if(databuf[i] == ','){ numberbuf[numberbufIndex] = '\0'; pointers[pointersIndex] = str2int(numberbuf); numberbufIndex = 0; pointersIndex +=1; }else{ numberbuf[numberbufIndex] = databuf[i]; numberbufIndex +=1; } } }else if(!gotname){ if(databuf[i] == '\n'){ name = malloc(sizeof(char) * (numberbufIndex+1)); for(j = 0; j < numberbufIndex; j+=1){ name[j] = numberbuf[j]; } name[j] = '\0'; gotname = true; numberbufIndex = 0; }else{ numberbuf[numberbufIndex]= databuf[i]; numberbufIndex +=1; } } else{ gotlink = true; numberbuf[numberbufIndex] = databuf[i]; numberbufIndex +=1; } } int link; if(gotlink){ numberbuf[numberbufIndex] = '\0'; link = str2int(numberbuf); Inode * newinode = readInode(disk,link); for(i = 0; newinode->pointers[i] != '\0';i+=1){ pointers[pointersIndex] = newinode->pointers[i]; pointersIndex+=1; } freeInode(newinode); } int * pointersSmall = malloc(sizeof(int) * (pointersIndex+1)); for(i = 0; i < pointersIndex;i+=1){ pointersSmall[i] = pointers[i]; } pointersSmall[i] = '\0'; Inode * node = createInode(size,pointersSmall,(size ==0)? true : false, block,name); free(numberbuf); free(databuf); free(pointers); //free(pointersSmall); return node; }