コード例 #1
0
ファイル: UFS.c プロジェクト: antiqe/UnixFileSystem
int bd_rename(const char *pFilename, const char *pDestFilename) {

  if (strcmp(pFilename, pDestFilename) == 0)
    return 0;

  char filenameSrc[FILENAME_SIZE];
  if (GetFilenameFromPath(pFilename, filenameSrc) == 0)
    return -1;
  char directorySrc[PATH_SIZE];
  if (GetDirFromPath(pFilename, directorySrc) == 0)
    return -1;
  iNodeEntry *pInodeParentSrc = alloca(sizeof(*pInodeParentSrc));
  if (GetINodeFromPath(directorySrc, &pInodeParentSrc) == -1)
    return -1;
  iNodeEntry *pInodeSrc = alloca(sizeof(*pInodeSrc));
  if (GetINodeFromPath(pFilename, &pInodeSrc) == -1)
    return -1;
  char filenameDest[FILENAME_SIZE];
  if (GetFilenameFromPath(pDestFilename, filenameDest) == 0)
    return -1;
  char directoryDest[PATH_SIZE];
  if (GetDirFromPath(pDestFilename, directoryDest) == 0)
    return -1;
  iNodeEntry *pInodeParentDest = alloca(sizeof(*pInodeParentDest));
  if (GetINodeFromPath(directoryDest, &pInodeParentDest) == -1)
    return -1;

  if (pInodeSrc->iNodeStat.st_mode & G_IFDIR) {
    if (strcmp(directorySrc, directoryDest) != 0) {
      pInodeParentSrc->iNodeStat.st_nlink--;
      pInodeParentDest->iNodeStat.st_nlink++;
    }
    char dataBlock[BLOCK_SIZE];
    if (ReadBlock(pInodeSrc->Block[0], dataBlock) == -1)
      return -1;
    DirEntry *pDirEntry = (DirEntry*)dataBlock;
    pDirEntry[1].iNode = pInodeParentDest->iNodeStat.st_ino;
    if (WriteBlock(pInodeSrc->Block[0], dataBlock) == -1)
      return -1;
  }

  if (RemoveINodeFromINode(filenameSrc, pInodeSrc, pInodeParentSrc) == -1)
    return -1;

  if (strcmp(directorySrc, directoryDest) == 0) {
    pInodeParentDest = pInodeParentSrc;
  }

  if (AddINodeToINode(filenameDest, pInodeSrc, pInodeParentDest) == -1)
    return  -1;

  return 0;
}
コード例 #2
0
void ZipArchiveEntry::SetFullName(const std::string& fullName)
{
  std::string filename = fullName;
  std::string correctFilename;

  // unify slashes
  std::replace(filename.begin(), filename.end(), '\\', '/');

  bool isDirectory = IsDirectoryPath(filename);

  // if slash is first char, remove it
  if (filename[0] == '/')
  {
    filename = filename.substr(filename.find_first_not_of('/'));
  }

  // find multiply slashes
  bool prevWasSlash = false;
  for (std::string::size_type i = 0; i < filename.length(); ++i)
  {
    if (filename[i] == '/' && prevWasSlash) continue;
    prevWasSlash = (filename[i] == '/');

    correctFilename += filename[i];
  }

  _centralDirectoryFileHeader.Filename = correctFilename;
  _name = GetFilenameFromPath(correctFilename);

  this->SetAttributes(isDirectory ? Attributes::Directory : Attributes::Archive);
}
コード例 #3
0
ファイル: UFS.c プロジェクト: antiqe/UnixFileSystem
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;
}
コード例 #4
0
ファイル: UFS.c プロジェクト: AntoineGagne/TPOS
int bd_rmdir(const char *pFilename) {
    int iNode = find_iNode(pFilename);
    if (iNode == -1) {
        return iNode;
    }

    int isDirectory = is_directory(iNode);
    if (!isDirectory) {
        return -2;
    }

    int isDirectoryEmpty = is_directory_empty(iNode);
    if (isDirectoryEmpty == -3) {
        return isDirectoryEmpty;
    }

    char parentPath[strlen(pFilename)];
    GetDirFromPath(pFilename, parentPath);
    int parentiNode = find_iNode(parentPath);

    char filename[FILENAME_SIZE];
    GetFilenameFromPath(pFilename, filename);

    remove_directory(iNode, parentiNode, filename);

    return 0;
}
コード例 #5
0
ファイル: UFS.c プロジェクト: AntoineGagne/TPOS
int bd_mkdir(const char *pDirName) {
    char pathName[strlen(pDirName)];
    GetDirFromPath(pDirName, pathName);
    int parentiNode = find_iNode(pathName);
    if (parentiNode == -1) {
        return parentiNode;
    }

    int iNode = find_iNode(pDirName);
    if (iNode != -1) {
        return -2;
    }

    char directoryName[FILENAME_SIZE];
    GetFilenameFromPath(pDirName, directoryName);

    // Create a file with the directory name
    create_file(parentiNode, directoryName);
    increase_link_count(parentiNode);

    // Find the newly created directory inode
    iNode = find_iNode(pDirName);

    // Increase its link count
    increase_link_count(iNode);

    // Set the right flags
    set_directory_flags(iNode);

    // Adds '.' and '..' directories
    add_default_directories(iNode, parentiNode);

    return 0;
}
コード例 #6
0
ファイル: UFS.c プロジェクト: AntoineGagne/TPOS
int bd_hardlink(const char *pPathExistant, const char *pPathNouveauLien) {
    int existingFileiNode = find_iNode(pPathExistant);
    if (existingFileiNode == -1) {
        return -1;
    }

    // We check if the directory that will contain the new hardlink exists
    char newLinkPath[strlen(pPathNouveauLien)];
    GetDirFromPath(pPathNouveauLien, newLinkPath);
    int newLinkPathiNode = find_iNode(newLinkPath);
    if (newLinkPathiNode == -1) {
        return -1;
    }

    // We check that the new hardlink doesn't already exists
    int newLinkExists = find_iNode(pPathNouveauLien);
    if (newLinkExists != -1) {
        return -2;
    }

    char linkName[strlen(pPathNouveauLien)];
    GetFilenameFromPath(pPathNouveauLien, linkName);

    int isSuccess =
        create_hardlink(existingFileiNode, newLinkPathiNode, linkName);

    return isSuccess;
}
コード例 #7
0
ファイル: UFS.c プロジェクト: antiqe/UnixFileSystem
int bd_hardlink(const char *pPathExistant, const char *pPathNouveauLien) {

  iNodeEntry *pInodeEx = alloca(sizeof(*pInodeEx));
  if (GetINodeFromPath(pPathExistant, &pInodeEx) == -1)
    return -1;

  char directory[PATH_SIZE];
  if (GetDirFromPath(pPathNouveauLien, directory) == 0)
    return -1;

  iNodeEntry *pInodeNewDir = alloca(sizeof(*pInodeNewDir));
  if (GetINodeFromPath(directory, &pInodeNewDir) == -1)
    return -1;

  iNodeEntry *pInodeNewFile = alloca(sizeof(*pInodeNewFile));
  if (GetINodeFromPath(pPathNouveauLien, &pInodeNewFile) != -1)
    return -2;

  if ((pInodeEx->iNodeStat.st_mode & G_IFDIR) &&
      !(pInodeEx->iNodeStat.st_mode & G_IFREG))
    return -3;

  char filename[FILENAME_SIZE];
  if (GetFilenameFromPath(pPathNouveauLien, filename) == 0)
    return -1;

  pInodeEx->iNodeStat.st_nlink++;

  if (AddINodeToINode(filename, pInodeEx, pInodeNewDir) == -1)
    return -1;
  return WriteINodeToDisk(pInodeEx);
}
コード例 #8
0
ファイル: UFS.c プロジェクト: antiqe/UnixFileSystem
int bd_unlink(const char *pFilename) {

  iNodeEntry *pInode = alloca(sizeof(*pInode));
  if (GetINodeFromPath(pFilename, &pInode) == -1)
    return -1;

  if (!(pInode->iNodeStat.st_mode & G_IFREG))
    return -2;

  char directory[PATH_SIZE];
  if (GetDirFromPath(pFilename, directory) == 0)
    return -1;

  iNodeEntry *pInodeDir = alloca(sizeof(*pInodeDir));
  if (GetINodeFromPath(directory, &pInodeDir) == -1)
    return -1;

  pInode->iNodeStat.st_nlink -= 1;
  if (pInode->iNodeStat.st_nlink == 0) {
    size_t i;
    for (i = 0; i < pInode->iNodeStat.st_blocks; ++i)
        ReleaseBlockFromDisk(pInode->Block[i]);
    ReleaseINodeFromDisk(pInode->iNodeStat.st_ino);
  }
  else
    WriteINodeToDisk(pInode);

  char filename[FILENAME_SIZE];
  if (GetFilenameFromPath(pFilename, filename) == 0)
    return -1;

  if (RemoveINodeFromINode(filename, pInode, pInodeDir) == -1)
    return -1;
  return 0;
}
コード例 #9
0
ファイル: UFS.c プロジェクト: antiqe/UnixFileSystem
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;
}
コード例 #10
0
void CScriptDebugging::LogBadType ( lua_State* luaVM, const char* szFunction )
{
    assert ( szFunction );

    lua_Debug debugInfo;
    if ( lua_getstack ( luaVM, 1, &debugInfo ) )
    {
        lua_getinfo ( luaVM, "nlS", &debugInfo );
        const char* szFilename = GetFilenameFromPath ( debugInfo.source );

        // Populate a message to print/send
        LogWarning ( luaVM, "%s: Bad argument @ '%s' - Line: %d", szFilename, szFunction, debugInfo.currentline );
    }
}
コード例 #11
0
void CScriptDebugging::LogBadLevel ( lua_State* luaVM, const char* szFunction, unsigned int uiRequiredLevel )
{
    assert ( szFunction );
    
    lua_Debug debugInfo;
    if ( lua_getstack ( luaVM, 1, &debugInfo ) )
    {
        lua_getinfo ( luaVM, "nlS", &debugInfo );
        const char* szFilename = GetFilenameFromPath ( debugInfo.source );

        // Populate a message to print/send
        LogWarning ( luaVM, "%s: Requires level '%d' @ '%s' - Line: %d", szFilename, uiRequiredLevel, szFunction, debugInfo.currentline );
    }
}
コード例 #12
0
void CScriptDebugging::LogBadPointer ( lua_State* luaVM, const char* szFunction, const char* szArgumentType, unsigned int uiArgument )
{
    assert ( szFunction );
    assert ( szArgumentType );

    lua_Debug debugInfo;
    if ( lua_getstack ( luaVM, 1, &debugInfo ) )
    {
        lua_getinfo ( luaVM, "nlS", &debugInfo );
        const char* szFilename = GetFilenameFromPath ( debugInfo.source );

        // Populate a message to print/send
        LogWarning ( luaVM, "%s: Bad '%s' pointer @ '%s'(%u) - Line: %d", szFilename, szArgumentType, szFunction, uiArgument, debugInfo.currentline );
    }
}
コード例 #13
0
ファイル: Log.cpp プロジェクト: ctmartinez1992/Blood-Arena
void _log(char* path, char* function, int line, GAME_LOG type, char* vaArgs, ...) {
    va_list list;

    fopen_s(&fileHandler, "log.txt", SESSION_TRACKER ? "a+" : "w");

    char* typeOfLog = GetTypeOfLog(type);

	fprintf(fileHandler, "[%s][%s - %s - %d] : ", typeOfLog, GetFilenameFromPath(path) , function, line);

    va_start(list, vaArgs);
 
    for(char* arg = vaArgs; *arg; ++arg) {
        if(*arg != '%') {
            fputc(*arg, fileHandler);
        }
        else {
            switch(*++arg) {
            
                //char
                case 's':
                {
                    char* argValueCharPointer = va_arg(list, char*);
                    fprintf(fileHandler, "%s", argValueCharPointer);
                } continue;
 
                //integer
                case 'd':
                {
                    int argValueInteger = va_arg(list, int);
                    fprintf(fileHandler, "%d", argValueInteger);  
                } continue;
 
                default:
                {
                    fputc(*arg, fileHandler);
                } break;
            }
        }
    }

    va_end(list);

    fputc('\n', fileHandler);

    SESSION_TRACKER++;

    fclose(fileHandler);
}
コード例 #14
0
ファイル: train.cpp プロジェクト: yuzhuqingyun/face_log
int GetFaceFromFilename(const string filePath, const Vec4f point, Face& faces)
{
	string sign;
	int id;
	string filename = GetFilenameFromPath(filePath);
	ReadFilename(filename, id, sign);
	Mat image = imread(filePath, 0);
	if (image.empty()) return 0;	//图片读取失败,返回
	Point2f pLeft = Point2f(point[0],point[1]);
	Point2f pRight = Point2f(point[2],point[3]);
	Mat dst = AlignFace(image, pRight, pLeft);	//尺寸归一化
	faces.filename = filePath;
	faces.id = id;
	faces.sign = sign;
	faces.eyePoints = point;
	faces.face = dst;
	faces.value = 0.0;
	return 1;
}
コード例 #15
0
ファイル: UFS.c プロジェクト: AntoineGagne/TPOS
int bd_create(const char *pFilename) {
    int fileExists = find_iNode(pFilename);
    if (fileExists != -1) {
        return -2;
    }

    char pathName[strlen(pFilename)];
    GetDirFromPath(pFilename, pathName);
    int pathiNode = find_iNode(pathName);
    if (pathiNode == -1) {
        return -1;
    }

    char filename[FILENAME_SIZE];
    GetFilenameFromPath(pFilename, filename);

    create_file(pathiNode, filename);

    return 0;
}
コード例 #16
0
ファイル: UFS.c プロジェクト: AntoineGagne/TPOS
int remove_file(ino iNode, const char *filePath) {
    int isFile = check_if_inode_is_file(iNode);
    if (isFile == -2) {
        return isFile;
    }

    char path[strlen(filePath)];
    GetDirFromPath(filePath, path);
    int pathiNode = find_iNode(path);

    char file[FILENAME_SIZE];
    GetFilenameFromPath(filePath, file);

    // We can't use the file inode directly since hardlinks have the same name
    // as the file they are linked against
    remove_file_from_directory(pathiNode, iNode, file);

    // Decrease link count and, if link == 0, remove file
    decrease_link_count(iNode);
    return 0;
}
コード例 #17
0
ファイル: UFS.c プロジェクト: AntoineGagne/TPOS
int find_iNode(const char *pFilename) {
    int slashesCount = count_delimiter(pFilename, '/');
    char filename[FILENAME_SIZE];
    char path[strlen(pFilename)];

    GetFilenameFromPath(pFilename, filename);
    GetDirFromPath(pFilename, path);

    if (slashesCount > 1) {
        return find_iNode_in_subpath(filename, path);
    } else {
        char directoryDataBlock[BLOCK_SIZE];
        // We read the root directory
        ReadBlock(6, directoryDataBlock);
        DirEntry *directory = (DirEntry *)directoryDataBlock;

        if (strlen(pFilename) == 1) {
            int i;
            for (i = 0; i < BLOCK_SIZE; ++i) {
                if (strcmp(directory[i].Filename, ".") == 0) {
                    return directory[i].iNode;
                }
            }
        } else {

            int i;
            for (i = 0; i < BLOCK_SIZE; ++i) {
                // printf("\tFile: %s\n", directory[i].Filename);
                // printf("\tFile to find: %s\n\n", filename);
                if (strcmp(directory[i].Filename, filename) == 0) {
                    return directory[i].iNode;
                }
            }
        }
    }

    return -1;
}
コード例 #18
0
ファイル: UFS.c プロジェクト: AntoineGagne/TPOS
int bd_rename(const char *pFilename, const char *pDestFilename) {

    // Check if both directory are valid, if so keep them in memory
    char initialDirectory[BLOCK_SIZE];
    char newDirectory[BLOCK_SIZE];
    if (GetDirFromPath(pFilename, initialDirectory) != 1) {
        return -1;
    }

    if (GetDirFromPath(pDestFilename, newDirectory) != 1) {
        return -1;
    }

    // Find directory inodes and if there are valid
    int newDirectoryiNode = find_iNode(newDirectory);
    if (newDirectoryiNode == -1) {
        return -1;
    }

    int initialDirectoryiNode = find_iNode(initialDirectory);
    if (initialDirectoryiNode == -1) {
        return -1;
    }

    // Check if they have the same directory, if so, assigned the initial inode
    // to the newDirectory
    if (strcmp(initialDirectory, newDirectory) == 0) {
        newDirectoryiNode = initialDirectoryiNode;
    }

    // If pFilename is not a directory, we simply do an hardlink
    int pFilenameiNode = find_iNode(pFilename);
    if (check_if_inode_is_file(pFilenameiNode) == 0) {

        int renamingFilenameSuccess = bd_hardlink(pFilename, pDestFilename);

        if (renamingFilenameSuccess == 0) {
            int unlinkingFilenameSuccess = bd_unlink(pFilename);
            return unlinkingFilenameSuccess;
        }
    } else {

        // If pFilename is a directory
        char newFile[BLOCK_SIZE];

        // If the new directory doesn't exists
        if (find_iNode(pDestFilename) == -1) {

            // We remove directory from it's initial parentDirectory
            if (GetFilenameFromPath(pFilename, newFile) == 1) {
                remove_file_from_directory(initialDirectoryiNode,
                                           pFilenameiNode, newFile);
                decrease_link_count(initialDirectoryiNode);
            } else {
                return -1;
            }

            // We add directory to it's new parentDirectory
            if (GetFilenameFromPath(pDestFilename, newFile) == 1) {
                char directoryDataBlock[BLOCK_SIZE];
                ReadBlock(6 + newDirectoryiNode - 1, directoryDataBlock);
                DirEntry *directory = (DirEntry *)directoryDataBlock;
                int filesNumber = numberOfFilesInDirectory(directory);

                // Assign newDirectory informations
                strcpy(directory[filesNumber].Filename, newFile);
                directory[filesNumber].iNode = pFilenameiNode;

                // Adjuste the newDirectory and its parentDirectory size
                add_size_to_inode_size(sizeof(directory[filesNumber]),
                                       newDirectoryiNode);
                increase_link_count(newDirectoryiNode);
                add_parentiNode(pFilenameiNode, newDirectoryiNode);

                WriteBlock(6 + newDirectoryiNode - 1, directoryDataBlock);
            }
        }
    }

    return 0;
}
コード例 #19
0
ファイル: UFS.c プロジェクト: antiqe/UnixFileSystem
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;
}