uint64_t fs_get_block(struct superblock *sb) { if (sb->freeblks == 0) { //report Error return 0; } uint64_t freeList = sb->freelist; struct freepage *fp = (struct freepage *) malloc(sb->blksz); struct freepage *fp_prev = (struct freepage *) malloc(sb->blksz); struct freepage *fp_next = (struct freepage *) malloc(sb->blksz); seek_read(sb, freeList, fp); if (fp->count != 0) { //update previous pointers seek_read(sb, fp->links[0], fp_prev); fp_prev->next = fp->next; seek_write(sb, fp->links[0], fp_prev); } if (fp->next != 0) { //update next pointers seek_read(sb, fp->next, fp_next); fp_next->links[0] = fp->links[0]; seek_write(sb, fp->next, fp_next); } sb->freelist = fp->next; sb->freeblks--; seek_write(sb, 0, sb); free(fp_prev); free(fp); free(fp_next); return freeList; }
int fs_put_block(struct superblock *sb, uint64_t block) { if (sb->freeblks != 0) { uint64_t freeList = sb->freelist; struct freepage *fp = NULL, *fp_next = NULL; fp = (struct freepage *) malloc(sb->blksz); fp_next = (struct freepage *) malloc(sb->blksz); seek_read(sb, freeList, fp_next); fp->next = freeList; fp->count = 0; seek_write(sb, block, fp); fp_next->count = 1; fp_next->links[0] = block; seek_write(sb, freeList, fp_next); free(fp); free(fp_next); } else { struct freepage *fp = NULL; fp = (struct freepage *) malloc(sb->blksz); fp->next = 0; fp->count = 0; seek_write(sb, block, fp); free(fp); } sb->freelist = block; sb->freeblks++; seek_write(sb, 0, sb); return 0; }
int InsertInNode(struct superblock* sb, const char* dirName, const uint64_t fileBlock) { int exists; struct inode*dirNode = NULL; struct nodeinfo* meta = NULL; dirNode = malloc(sb->blksz); meta = malloc(sb->blksz); uint64_t dirBlock = findFile(sb, dirName, &exists); seek_read(sb, dirBlock, dirNode); seek_read(sb, dirNode->meta, meta); int len = 0; char** fileparts = getFileParts(dirName, &len); if (strcmp(meta->name, fileparts[len - 1]) != 0)return 0; //dir does not exists if ((++meta->size) % getLinksMaxLen(sb) == 0) { //needs to create another link block struct inode* linknode = NULL; linknode = malloc(sb->blksz); linknode->links[0] = fileBlock; linknode->links[1] = 0; uint64_t lastLinkBlock = getNodeLastLinkBlock(sb, dirBlock); struct inode* lastLinkNode = NULL; lastLinkNode = malloc(sb->blksz); seek_read(sb, lastLinkBlock, lastLinkNode); if (lastLinkNode->next != 0) { exit(EXIT_FAILURE); } lastLinkNode->next = fs_get_block(sb); seek_write(sb, lastLinkNode->next, linknode); seek_write(sb, lastLinkBlock, lastLinkNode); free(linknode); free(lastLinkNode); } else { int linkLen = getLinksLen(dirNode); dirNode->links[linkLen] = fileBlock; dirNode->links[linkLen + 1] = 0; } seek_write(sb, dirBlock, dirNode); seek_write(sb, dirNode->meta, meta); freeFileParts(&fileparts, len); free(dirNode); free(meta); return FALSE; }
int fs_close(struct superblock *sb) { if (sb == NULL) { return -1; } seek_write(sb, 0, sb); if (flock(sb->fd, LOCK_UN | LOCK_NB) != 0) { errno = EBADF; return -1; } close(sb->fd); free(sb); return 0; }
/** * Inserts block2Add in the links relative to destBlock. * Does not check if destBlock is valid! * @param sb the superblock * @param destBlock block to receive block2Add as a child * @param block2Add block to be added in the children of destBlock * @return as of now you can ignore this */ int insertInBlock(struct superblock* sb, const uint64_t destBlock, const uint64_t block2Add) { struct inode *dirNode = NULL; struct nodeinfo* meta = NULL; dirNode = malloc(sb->blksz); meta = malloc(sb->blksz); seek_read(sb, destBlock, dirNode); seek_read(sb, dirNode->meta, meta); if ((++meta->size) % getLinksMaxLen(sb) == 0) { //needs to create another link block struct inode* linknode = NULL; linknode = malloc(sb->blksz); linknode->links[0] = block2Add; linknode->links[1] = 0; uint64_t lastLinkBlock = getNodeLastLinkBlock(sb, destBlock); struct inode* lastLinkNode = NULL; lastLinkNode = malloc(sb->blksz); seek_read(sb, lastLinkBlock, lastLinkNode); if (lastLinkNode->next != 0) { exit(EXIT_FAILURE); } lastLinkNode->next = fs_get_block(sb); seek_write(sb, lastLinkNode->next, linknode); seek_write(sb, lastLinkBlock, lastLinkNode); free(linknode); free(lastLinkNode); } else { int linkLen = getLinksLen(dirNode); dirNode->links[linkLen] = block2Add; dirNode->links[linkLen + 1] = 0; } seek_write(sb, destBlock, dirNode); seek_write(sb, dirNode->meta, meta); free(dirNode); free(meta); return TRUE; }
////////////////////////////////////////////////// // // SND_IO_File // ////////////////////////////////////////////////// bool SND_IO_File::open(const char *fname) { if (file.is_open()) close(); file.clear(); is_valid = false; file.open(fname, ios::in | ios::out | ios::binary); if (!file) return false; if (!read_header(file)) { file.close(); return false; } if (!seek_read(0) || !seek_write(0)) { file.close(); return false; } is_valid = true; return true; }
int main(int argc, char** argv) { int i = 0; if (argc == 1) { printf("Usage: %s <filename>\n", argv[0]); return EXIT_FAILURE; } signal(SIGBUS, catch_sigbus); /* the next test should not trigger SIGBUS */ expect_sigbus = 0; for (i = 0; i < RUN_LOOP; i++) { seek_write(argv[1]); } /* the next test should trigger SIGBUS */ expect_sigbus = 1; if (read_after_eof(argv[1])) return EXIT_FAILURE; return EXIT_SUCCESS; }
int fs_mkdir(struct superblock *sb, const char *dname) { if (!sb->freeblks) { // disk is full errno = ENOSPC; return invalid; } int exists = 0; uint64_t fileBlock = findFile(sb, dname, &exists); if (exists) { // dir already exist; errno = EEXIST; return invalid; } struct inode *father = (struct inode*) malloc(sb->blksz); struct inode *folder = (struct inode*) malloc(sb->blksz); struct nodeinfo *n_info = (struct nodeinfo*) malloc(sb->blksz); uint64_t folder_block = fs_get_block(sb); uint64_t nodeinfo_block = fs_get_block(sb); init_folder_struct(folder, folder_block, nodeinfo_block); int status = init_nodeinfo_struct(sb, dname, n_info, nodeinfo_block); if (status == invalid) { free(father); father = NULL; free(folder); folder = NULL; free(n_info); n_info = NULL; errno = ENAMETOOLONG; return invalid; } /* Read father inode stored in file */ seek_read(sb, fileBlock, father); status = checkfather_path(sb, dname, father); if (status == invalid) { free(father); father = NULL; free(folder); folder = NULL; free(n_info); n_info = NULL; errno = ENOENT; return invalid; } /* Ok, proceed */ if (!exists) { insertInBlock(sb, fileBlock, folder_block); /* store both inodes related to the folder that has been just created */ seek_write(sb, folder_block, folder); seek_write(sb, nodeinfo_block, n_info); } free(father); father = NULL; free(folder); folder = NULL; free(n_info); n_info = NULL; return success; }
int fs_delete_file(struct superblock *sb, const char *fname) { //o proprio nome ja diz. int i = 0, found, maxLink, ultimo; uint64_t fileBlock, fileLinkBlk, lastBlock, folderBlock; //numero do bloco e do bloco do link no diretorio que tem ele struct inode *file; struct inode *folder; struct inode *aux; struct nodeinfo *folderInfo; maxLink = getLinksMaxLen(sb); file = (struct inode *) malloc(sb->blksz); folder = (struct inode *) malloc(sb->blksz); aux = (struct inode *) malloc(sb->blksz); folderInfo = (struct nodeinfo *) malloc(sb->blksz); fileBlock = findFile(sb, fname, &found); if (found == 0) { //arquivo nao existe errno = ENOENT; return -1; } seek_read(sb, fileBlock, file); //pegando inode do arquivo if (file->mode == IMDIR) { //se for diretorio errno = EISDIR; return -1; } folderBlock = file->parent; fileLinkBlk = folderBlock; seek_read(sb, folderBlock, folder); //diretorio onde esta o arquivo seek_read(sb, folder->meta, folderInfo); //removendo o arquivo e blocos associados fs_put_block(sb, file->meta); //liberando bloco nodeinfo while ((i < maxLink) && (file->links[i] != 0)) { //if (i == maxLink) fs_put_block(sb, file->links[i]); file->links[i] = 0; //marcando que nao tem mais bloco neste link. i++; if (i == maxLink && file->next != 0) { seek_read(sb, file->next, file); fs_put_block(sb, file->meta); //apagando bloco anterior depois de ir pro próximo. i = 0; } } //removendo na pasta tambem; ultimo = (folder->links[getLinksLen(folder) - 1] == fileBlock); if (ultimo) { folder->links[getLinksLen(folder) - 1] = 0; //folderInfo->size--; } else { i = 0; while ((folder->links[i % maxLink] != fileBlock) && i < folderInfo->size) { i++; if ((i % maxLink == 0) && (folder->next != 0)) { fileLinkBlk = folder->next; //guardando bloco que pode conter link pro arquivo. Saindo do while sera ele. seek_read(sb, folder->next, folder); } } lastBlock = getNodeLastLinkBlock(sb, folderBlock); if (lastBlock == fileLinkBlk) { folder->links[i % maxLink] = folder->links[getLinksLen(folder) - 1]; folder->links[getLinksLen(folder) - 1] = 0; } else { seek_read(sb, lastBlock, aux); folder->links[i % maxLink] = aux->links[getLinksLen(aux) - 1]; //copiando ultimo link pra posicao q indicava bloco do arquivo removido aux->links[getLinksLen(aux) - 1] = 0; seek_write(sb, lastBlock, aux); //Devo escrever o bloco alterado de volta no disco, certo? } } folderInfo->size--; seek_write(sb, fileLinkBlk, folder); //escrevendo o que contem o link pro arquivo (foi alterado ali em cima) seek_read(sb, folderBlock, folder); //voltando pro inode principal da pasta seek_write(sb, folder->meta, folderInfo); //pra escrever o folderinfo no bloco onde ele estava. free(file); free(folder); free(folderInfo); free(aux); return 0; }
int fs_write_file(struct superblock *sb, const char *fname, char *buf, size_t cnt) { const uint64_t blocksNeeded = MAX(1, cnt / sb->blksz); if (blocksNeeded > sb->freeblks) { errno = ENOSPC; return -1; } int blocksUsed = 0; if (strlen(fname) + 1 > getFileNameMaxLen(sb)) { errno = ENAMETOOLONG; return -1; } if (existsFile(sb, fname)) { errno = EEXIST; return -1; } int len = 0, exists = 0; char** fileParts = getFileParts(fname, &len); uint64_t dirBlock = findFile(sb, fname, &exists); char* dirName = NULL; struct inode* dirNode, *node; struct nodeinfo* meta = (struct nodeinfo*) calloc(1, sb->blksz); initNode(&dirNode, sb->blksz); initNode(&node, sb->blksz); seek_read(sb, dirBlock, dirNode); seek_read(sb, dirNode->meta, meta); dirName = calloc(1, sizeof (char)* (strlen(meta->name) + 1)); strcpy(dirName, meta->name); if (strcmp(fileParts[MAX(0, len - 2)], dirName) != 0) { errno = EBADF; free(dirName); free(node); free(meta); free(dirNode); return -1; } uint64_t fileBlock = fs_get_block(sb); insertInBlock(sb, dirBlock, fileBlock); uint64_t blocksList[blocksNeeded]; ///properly write the file while (blocksUsed < blocksNeeded) { uint64_t block = fs_get_block(sb); blocksList[blocksUsed] = block; char* temp = calloc(1, sb->blksz); char* blockContent = buf + sb->blksz * (blocksUsed); strcpy(temp, blockContent); blocksUsed++; seek_write(sb, block, temp); free(temp); } strcpy(meta->name, fileParts[len - 1]); meta->size = cnt; meta->reserved[0] = 0; node->meta = fs_get_block(sb); node->mode = IMREG; node->parent = dirBlock; seek_write(sb, node->meta, meta); uint64_t nodeBlock = fileBlock; blocksUsed = 0; while (blocksUsed < blocksNeeded) { int i = 0; int linksLen = getLinksMaxLen(sb); int N = MIN(linksLen, blocksNeeded); while (i < N) { node->links[i] = blocksList[i]; i++; blocksUsed++; } if (blocksUsed < blocksNeeded) { node->next = fs_get_block(sb); seek_write(sb, nodeBlock, node); nodeBlock = node->next; node->next = 0; node->parent = fileBlock; node->mode = IMCHILD | IMREG; node->meta = fs_get_block(sb); strcpy(meta->name, fileParts[len - 1]); meta->size = cnt; seek_write(sb, node->meta, meta); } } seek_write(sb, nodeBlock, node); free(meta); free(node); freeFileParts(&fileParts, len); free(dirNode); free(dirName); return 0; }