Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
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;
}