int allocate_directory(ino iNode, DirEntry **ppListeFichiers) { char iNodeDataBlock[BLOCK_SIZE]; char directoryDataBlock[BLOCK_SIZE]; ReadBlock(6 + iNode - 1, directoryDataBlock); DirEntry *directory = (DirEntry *)directoryDataBlock; if (iNode < 16) { ReadBlock(4, iNodeDataBlock); iNodeEntry *iNodes = (iNodeEntry *)iNodeDataBlock; // If it isn't a directory if (!(iNodes[iNode].iNodeStat.st_mode & G_IFDIR)) { return -1; } int directorySizeNumber = iNodes[iNode].iNodeStat.st_size; (*ppListeFichiers) = (DirEntry *)malloc(directorySizeNumber); memcpy((*ppListeFichiers), directory, directorySizeNumber); return NumberofDirEntry(directorySizeNumber); } else { ReadBlock(5, iNodeDataBlock); iNodeEntry *iNodes = (iNodeEntry *)iNodeDataBlock; // If it isn't a directory if (!(iNodes[iNode].iNodeStat.st_mode & G_IFDIR)) { return -1; } int directorySizeNumber = iNodes[iNode - 16].iNodeStat.st_size; (*ppListeFichiers) = (DirEntry *)malloc(directorySizeNumber); memcpy((*ppListeFichiers), directory, directorySizeNumber); return NumberofDirEntry(directorySizeNumber); } return -1; }
int bd_rmdir(const char *pFilename) { iNodeEntry *pInodeDir = alloca(sizeof(*pInodeDir)); if (GetINodeFromPath(pFilename, &pInodeDir) == -1) return -1; if (pInodeDir->iNodeStat.st_mode & G_IFREG) return -2; const size_t nDir = NumberofDirEntry(pInodeDir->iNodeStat.st_size); if (nDir == 2) { iNodeEntry *pInodeParent = alloca(sizeof(*pInodeParent)); char directory[PATH_SIZE]; if (GetDirFromPath(pFilename, directory) == 0) return -1; if (GetINodeFromPath(directory, &pInodeParent) == -1) return -1; pInodeParent->iNodeStat.st_nlink--; char filename[FILENAME_SIZE]; if (GetFilenameFromPath(pFilename, filename) == 0) return -1; if (RemoveINodeFromINode(filename, pInodeDir, pInodeParent) == -1) return -1; ReleaseBlockFromDisk(pInodeDir->Block[0]); ReleaseINodeFromDisk(pInodeDir->iNodeStat.st_ino); return 0; } return -3; }
static int RemoveINodeFromINode(const char* filename, const iNodeEntry *pSrcInode, iNodeEntry *pDstInode) { if (!(pDstInode->iNodeStat.st_mode & G_IFDIR)) return -1; char dataBlock[BLOCK_SIZE]; if (ReadBlock(pDstInode->Block[0], dataBlock) == -1) return -1; DirEntry *pDirEntry = (DirEntry*)dataBlock; if (pDirEntry == NULL) return -1; const ino inode = pSrcInode->iNodeStat.st_ino; const size_t nDir = NumberofDirEntry(pDstInode->iNodeStat.st_size); size_t i; for (i = 0; i < nDir; ++i) { if ((pDirEntry[i].iNode == inode) && (strcmp(pDirEntry[i].Filename, filename) == 0)) break; } for (; i< nDir; ++i) { pDirEntry[i] = pDirEntry[i + 1]; } pDstInode->iNodeStat.st_size -= sizeof(DirEntry); if (WriteBlock(pDstInode->Block[0], dataBlock) == -1) return -1; return WriteINodeToDisk(pDstInode); }
int numberOfFilesInDirectory(DirEntry *directory) { int directoryiNode = directory[0].iNode; char currentINodeBlock[BLOCK_SIZE]; // TODO: Adds condition to check for the good iNode block ReadBlock(4, currentINodeBlock); iNodeEntry *iNodes = (iNodeEntry *)currentINodeBlock; int sizeDir; if (directoryiNode >= 0 && directoryiNode < BLOCK_SIZE) { sizeDir = NumberofDirEntry(iNodes[directoryiNode].iNodeStat.st_size); } else { sizeDir = 0; } return sizeDir; }
int bd_readdir(const char *pDirLocation, DirEntry **ppListeFichiers) { iNodeEntry *pInodeDir = alloca(sizeof(*pInodeDir)); if (GetINodeFromPath(pDirLocation, &pInodeDir) == -1 || pInodeDir->iNodeStat.st_mode & G_IFREG) return -1; char *dataBlock = NULL; if ((dataBlock = malloc(BLOCK_SIZE)) == NULL) return -1; if (ReadBlock(pInodeDir->Block[0], dataBlock) == -1) return -1; *ppListeFichiers = (DirEntry *)dataBlock; return NumberofDirEntry(pInodeDir->iNodeStat.st_size); }
static int AddINodeToINode(const char* filename, const iNodeEntry *pSrcInode, iNodeEntry *pDstInode) { if (!(pDstInode->iNodeStat.st_mode & G_IFDIR)) return -1; char dataBlock[BLOCK_SIZE]; if (ReadBlock(pDstInode->Block[0], dataBlock) == -1) return -1; DirEntry *pDirEntry = (DirEntry*)dataBlock; if (pDirEntry == NULL) return -1; const size_t nDir = NumberofDirEntry(pDstInode->iNodeStat.st_size); pDirEntry[nDir].iNode = pSrcInode->iNodeStat.st_ino; strcpy(pDirEntry[nDir].Filename, filename); if (WriteBlock(pDstInode->Block[0], dataBlock) == -1) return -1; pDstInode->iNodeStat.st_size += sizeof(DirEntry); return WriteINodeToDisk(pDstInode); }
static int GetINodeFromPathAux(const char *pFilename, const ino inode, iNodeEntry **pOutInode) { iNodeEntry *pInode = alloca(sizeof(*pInode)); if (GetINode(inode, &pInode) != 0) return -1; char dirEntryBlock[BLOCK_SIZE]; if (ReadBlock(pInode->Block[0], dirEntryBlock) == -1) return -1; DirEntry *pDirEntry = (DirEntry*)dirEntryBlock; if (pDirEntry == NULL) return -1; char *pos = strchr(pFilename, '/'); char path[FILENAME_SIZE]; if (pos != NULL) { strncpy(path, pFilename, (pos - pFilename)); path[(pos - pFilename)] = 0; } else { strcpy(path, pFilename); } const size_t nDir = NumberofDirEntry(pInode->iNodeStat.st_size); size_t i = 0; for (; i < nDir; ++i) { if (strcmp(pDirEntry[i].Filename, path) == 0) { if (GetINode(pDirEntry[i].iNode, pOutInode) != 0) return -1; if (pos != NULL && strcmp(pos, "/") && ((*pOutInode)->iNodeStat.st_mode & G_IFDIR)) { return GetINodeFromPathAux(pos + 1, pDirEntry[i].iNode, pOutInode); } return pDirEntry[i].iNode; } } 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; }