int bd_create(const char *pFilename) { char directory[PATH_SIZE]; if (GetDirFromPath(pFilename, directory) == 0) return -1; char filename[PATH_SIZE]; if (GetFilenameFromPath(pFilename, filename) == 0 || strlen(filename) > FILENAME_SIZE) return -1; iNodeEntry *pInodeDir = alloca(sizeof(*pInodeDir)); if (GetINodeFromPath(directory, &pInodeDir) == -1) return -1; iNodeEntry *pInodeFile = alloca(sizeof(*pInodeFile)); if (GetINodeFromPath(pFilename, &pInodeFile) != -1) return -2; if (GetFreeINode(&pInodeFile) != -1) { pInodeFile->iNodeStat.st_mode |= G_IRWXU | G_IRWXG | G_IFREG; pInodeFile->iNodeStat.st_nlink = 1; if (AddINodeToINode(filename, pInodeFile, pInodeDir) != -1) return WriteINodeToDisk(pInodeFile); } return -1; }
int bd_read(const char *pFilename, char *buffer, int offset, int numbytes) { iNodeEntry *pInode = alloca(sizeof(*pInode)); const int inode = GetINodeFromPath(pFilename, &pInode); if (inode == -1) { printf("Le fichier %s est inexistant!\n", pFilename); return -1; } if (pInode->iNodeStat.st_mode & G_IFDIR) { printf("Le fichier %s est un repertoire!\n", pFilename); return -2; } if (pInode->iNodeStat.st_size < offset) { return 0; } const size_t firstBlock = offset / BLOCK_SIZE; const size_t offsetFirstBlock = offset % BLOCK_SIZE; const size_t sizeToRead = min(pInode->iNodeStat.st_size - offset, numbytes); const size_t lastBlock = (sizeToRead + offset) / BLOCK_SIZE; const size_t offsetLastBlock = (sizeToRead + offset) % BLOCK_SIZE; size_t length[N_BLOCK_PER_INODE] = {[0 ... N_BLOCK_PER_INODE - 1] = BLOCK_SIZE}; length[lastBlock] = offsetLastBlock; length[firstBlock] = min(BLOCK_SIZE - offsetFirstBlock, sizeToRead); size_t readOffset[N_BLOCK_PER_INODE] = {[0 ... N_BLOCK_PER_INODE - 1] = 0}; readOffset[firstBlock] = offsetFirstBlock; size_t i, writeOffset = 0; for (i = firstBlock; (i <= lastBlock) && (i < N_BLOCK_PER_INODE); ++i) { char *dataBlock = alloca(BLOCK_SIZE); if (ReadBlock(pInode->Block[i], dataBlock) == -1) return -1; memcpy(&buffer[writeOffset], &dataBlock[readOffset[i]], length[i]); writeOffset += length[i]; } return sizeToRead; } int bd_write(const char *pFilename, const char *buffer, int offset, int numbytes) { iNodeEntry *pInode = alloca(sizeof(*pInode)); const int inode = GetINodeFromPath(pFilename, &pInode); if (inode == -1) { printf("Le fichier %s est inexistant!\n", pFilename); return -1; } if (pInode->iNodeStat.st_mode & G_IFDIR) { printf("Le fichier %s est un repertoire!\n", pFilename); return -2; } if (offset > pInode->iNodeStat.st_size) { printf("L'offset demande est trop grand!\n"); return -3; } const size_t maxFileSize = N_BLOCK_PER_INODE * BLOCK_SIZE; if (offset >= maxFileSize) { printf("Taille trop grande (offset=%ld) pour le fichier %s!\n", maxFileSize, pFilename); return -4; } if ((numbytes + offset) > maxFileSize) { printf("Le fichier %s deviendra trop gros!\n", pFilename); } const size_t firstBlock = offset / BLOCK_SIZE; const size_t offsetFirstBlock = offset % BLOCK_SIZE; const size_t sizeToWrite = min(numbytes, maxFileSize - offset); const size_t lastBlock = (sizeToWrite + offset) / BLOCK_SIZE; const size_t offsetLastBlock = (sizeToWrite + offset) % BLOCK_SIZE; size_t length[N_BLOCK_PER_INODE] = {[0 ... N_BLOCK_PER_INODE - 1] = BLOCK_SIZE}; length[lastBlock] = offsetLastBlock; length[firstBlock] = min(BLOCK_SIZE - offsetFirstBlock, sizeToWrite); size_t writeOffset[N_BLOCK_PER_INODE] = {[0 ... N_BLOCK_PER_INODE - 1] = 0}; writeOffset[firstBlock] = offsetFirstBlock; size_t i, readOffset = 0; for (i = firstBlock; (i <= lastBlock) && (i < N_BLOCK_PER_INODE); ++i) { if (i >= pInode->iNodeStat.st_blocks) { int block = 0; if ((block = GetFreeBlock()) == -1) return -1; pInode->Block[i] = block; pInode->iNodeStat.st_blocks++; } char *dataBlock = alloca(BLOCK_SIZE); if (ReadBlock(pInode->Block[i], dataBlock) == -1) return -1; memcpy(&dataBlock[writeOffset[i]], &buffer[readOffset], length[i]); if (WriteBlock(pInode->Block[i], dataBlock) == -1) return -1; readOffset += length[i]; } pInode->iNodeStat.st_size = max(pInode->iNodeStat.st_size, offset + sizeToWrite); if (WriteINodeToDisk(pInode) == -1) return -1; return sizeToWrite; } int bd_mkdir(const char *pDirName) { char pathOfDir[PATH_SIZE]; if (GetDirFromPath(pDirName, pathOfDir) == 0) return -1; char dirName[PATH_SIZE]; if (GetFilenameFromPath(pDirName, dirName) == 0 || strlen(dirName) > FILENAME_SIZE) return -1; iNodeEntry *pDirInode = alloca(sizeof(*pDirInode)); if (GetINodeFromPath(pathOfDir, &pDirInode) == -1 || pDirInode->iNodeStat.st_mode & G_IFREG) return -1; const size_t nDir = NumberofDirEntry(pDirInode->iNodeStat.st_size); if (((nDir + 1) * sizeof(DirEntry)) > BLOCK_SIZE) return -1; iNodeEntry *pChildInode = alloca(sizeof(*pChildInode)); if (GetINodeFromPath(pDirName, &pChildInode) != -1) return -2; if (GetFreeINode(&pChildInode) == -1) return -1; char dataBlock[BLOCK_SIZE]; DirEntry *pDirEntry = (DirEntry*)dataBlock; strcpy(pDirEntry[0].Filename, "."); strcpy(pDirEntry[1].Filename, ".."); pDirEntry[0].iNode = pChildInode->iNodeStat.st_ino; pDirEntry[1].iNode = pDirInode->iNodeStat.st_ino; const int idBlocDir = GetFreeBlock(); if (idBlocDir == -1) { ReleaseINodeFromDisk(pChildInode->iNodeStat.st_ino); return -1; } if (WriteBlock(idBlocDir, dataBlock) == -1) { ReleaseINodeFromDisk(pChildInode->iNodeStat.st_ino); ReleaseBlockFromDisk(idBlocDir); return -1; } pChildInode->iNodeStat.st_mode |= G_IFDIR | G_IRWXU | G_IRWXG; pChildInode->iNodeStat.st_nlink = 2; pChildInode->iNodeStat.st_size = 2 * sizeof(DirEntry); pChildInode->iNodeStat.st_blocks = 1; pChildInode->Block[0] = idBlocDir; if (WriteINodeToDisk(pChildInode) == -1) { ReleaseINodeFromDisk(pChildInode->iNodeStat.st_ino); ReleaseBlockFromDisk(idBlocDir); return -1; } pDirInode->iNodeStat.st_nlink++; if (AddINodeToINode(dirName, pChildInode, pDirInode) == -1) { ReleaseINodeFromDisk(pChildInode->iNodeStat.st_ino); ReleaseBlockFromDisk(idBlocDir); return -1; } return 0; }
//==================================================== // Create a new file. entry for a file of type type // Returns an FCB on success or a negative error code //==================================================== struct FCB *CreateFileWithType(char *name, long type) { char *parentDirectory, *fileName, *dirBuffer; u_int32_t parentINodeNo, inodeNo, i; u_int16_t recLength, sizeOfEntry, sizeOfNewEntry; struct ext2_inode *inode; struct ext2_dir_entry_2 *entry, *newEntry; struct FCB *dirFcb, *fcb; // Does the file already exist? if (GetFileINode(name)) return (struct FCB *) -EEXIST; // Get the INode of the parentdirectory parentDirectory = AllocUMem((size_t)(strlen(name) + 1)); strcpy(parentDirectory, name); fileName = strrchr(parentDirectory, '/'); fileName[0] = 0; fileName++; parentINodeNo = GetFileINode(parentDirectory); if (!parentINodeNo) { DeallocMem(parentDirectory); return (struct FCB *) -ENOENT; } // Create an inode for the new file inode = AllocKMem(sizeof(struct ext2_inode)); memset(inode, 0, sizeof(struct ext2_inode)); inode->i_mode = (u_int16_t)(EXT2_S_IFREG | EXT2_S_IRUSR | EXT2_S_IWUSR | EXT2_S_IRGRP | EXT2_S_IWGRP | EXT2_S_IROTH | EXT2_S_IWOTH); inode->i_atime = inode->i_ctime = inode->i_mtime = (u_int32_t)unixtime; inode->i_dtime = 0; inode->i_links_count = 1; inode->i_blocks = 0; inodeNo = GetFreeINode(0); // Write the new inode to disk PutINode(inodeNo, inode); // Create a directory entry for the new file dirFcb = OpenFileByInodeNumber(parentINodeNo); dirBuffer = AllocUMem(dirFcb->inode->i_size); (void)ReadFile(dirFcb, dirBuffer, (long)(dirFcb->inode->i_size)); sizeOfNewEntry = (u_int16_t)(8 + strlen(fileName) + 4 - strlen(fileName) % 4); entry = (struct ext2_dir_entry_2 *) dirBuffer; sizeOfEntry = (u_int16_t)(8 + entry->name_len + 4 - entry->name_len % 4); while (sizeOfEntry + sizeOfNewEntry > entry->rec_len) { entry = (struct ext2_dir_entry_2 *) ((char *) entry + entry->rec_len); sizeOfEntry = (u_int16_t)(8 + entry->name_len + 4 - entry->name_len % 4); } // There's room for the new entry at the end of this record recLength = entry->rec_len; entry->rec_len = sizeOfEntry; newEntry = AllocUMem(sizeof(struct ext2_dir_entry_2)); memset(newEntry, 0, sizeof(struct ext2_dir_entry_2)); newEntry->file_type = (u_int8_t)type; newEntry->inode = (u_int32_t)inodeNo; newEntry->name_len = (u_int8_t)strlen(fileName); newEntry->rec_len = recLength - sizeOfEntry; for (i = 0; i < newEntry->name_len; i++) newEntry->name[i] = fileName[i]; memcpy((char *) entry + sizeOfEntry, newEntry, sizeOfNewEntry); DeallocMem(parentDirectory); // Write the directory buffer back to disk (void)Seek(dirFcb, 0, SEEK_SET); (void)WriteFile(dirFcb, dirBuffer, (long)(dirFcb->inode->i_size)); DeallocMem(dirBuffer); (void)CloseFile(dirFcb); // Create a FCB for the new file fcb = AllocKMem(sizeof(struct FCB)); fcb->inode = inode; fcb->inodeNumber = inodeNo; fcb->nextFCB = 0; fcb->fileCursor = 0; fcb->bufCursor = 0; fcb->buffer = AllocKMem((size_t)block_size); fcb->currentBlock = 0; fcb->index1 = fcb->index2 = fcb->index3 = fcb->index4 = 0; return fcb; }