Compare commits
29 Commits
connorg/fi
...
main
Author | SHA1 | Date | |
---|---|---|---|
![]() |
bc9a7d0b3c | ||
![]() |
ced1ba5682 | ||
![]() |
26be612d92 | ||
![]() |
6c16225919 | ||
![]() |
2085daa433 | ||
![]() |
e37b57bbfa | ||
![]() |
f800c825c4 | ||
![]() |
a527cb6328 | ||
![]() |
fb961a9cd5 | ||
![]() |
2209cb3224 | ||
![]() |
a15f5d9a3e | ||
![]() |
f8b0ee2e8f | ||
![]() |
75ce8970b2 | ||
![]() |
1c792ba738 | ||
![]() |
a612d030f6 | ||
![]() |
76815b36b7 | ||
![]() |
021d5b60da | ||
![]() |
0788041ac9 | ||
![]() |
5ff046f0fe | ||
![]() |
81ad41f8f2 | ||
![]() |
2838295f4d | ||
![]() |
87299ece0a | ||
![]() |
f816ea919c | ||
![]() |
f240180a66 | ||
![]() |
5f13524f6a | ||
![]() |
afd3ba7f32 | ||
![]() |
6cd81b2565 | ||
![]() |
6fe01302b5 | ||
![]() |
998e8a20cc |
@ -26,7 +26,7 @@ add_executable(fischl
|
|||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
# add_subdirectory(googletest)
|
add_subdirectory(googletest)
|
||||||
|
|
||||||
# Add the -Wall flag
|
# Add the -Wall flag
|
||||||
target_compile_options(fischl PRIVATE -Wall)
|
target_compile_options(fischl PRIVATE -Wall)
|
||||||
|
23
README.md
23
README.md
@ -19,6 +19,29 @@ cmake ..
|
|||||||
make # cmake --build . is same
|
make # cmake --build . is same
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## mount and test
|
||||||
|
normal usage:
|
||||||
|
```bash
|
||||||
|
./fischl diskpath n -s mountpoint
|
||||||
|
```
|
||||||
|
diskpath must be provided following ./fischl
|
||||||
|
l/n must be provided following diskpath indicating whether to load the exisiting file system or create a new one.
|
||||||
|
for loading:
|
||||||
|
```bash
|
||||||
|
./fischl diskpath l -s mountpoint
|
||||||
|
```
|
||||||
|
-s is also required because our fs doesn't support multi-threading.
|
||||||
|
|
||||||
|
if the diskpath need to be accessed by root:
|
||||||
|
```bash
|
||||||
|
sudo ./fischl diskpath n -o allow_other -s mountpoint
|
||||||
|
```
|
||||||
|
|
||||||
|
for debugging:
|
||||||
|
```bash
|
||||||
|
sudo ./fischl diskpath n -o allow_other -d -s mountpoint
|
||||||
|
```
|
||||||
|
|
||||||
## run test
|
## run test
|
||||||
### add your own test file on test/CMakeList.txt
|
### add your own test file on test/CMakeList.txt
|
||||||
```
|
```
|
||||||
|
1
googletest
Submodule
1
googletest
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit b10fad38c4026a29ea6561ab15fc4818170d1c10
|
@ -19,18 +19,48 @@ typedef struct treeNode {
|
|||||||
FileNode *self_info; //self fileNode infromation
|
FileNode *self_info; //self fileNode infromation
|
||||||
} TreeNode;
|
} TreeNode;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct RenameInfo {
|
||||||
|
FileNode *oldFileNode; // The file node being renamed.
|
||||||
|
FileNode *oldParentNode; // The parent directory of the file node being renamed.
|
||||||
|
FileNode *newParentNode; // The target parent directory where the file node will be moved.
|
||||||
|
char *newName; // The new name of the file node after the rename.
|
||||||
|
FileNode *newFileNode; // The new file node, if one already exists at the target location.
|
||||||
|
bool exchangeExist; // Flag to indicate if the rename should replace an existing file node.
|
||||||
|
} RenameInfo;
|
||||||
|
|
||||||
/*for root*/
|
/*for root*/
|
||||||
TreeNode *fischl_init_entry(int new_inode_number, const char *fileName, INode_Data *new_inode);
|
TreeNode *fischl_init_entry(int new_inode_number, const char *fileName, INode_Data *new_inode);
|
||||||
/*the to be added file in add_entry should be parent-child relationship with treenode, otherwise will wrong */
|
/*the to be added file in add_entry should be parent-child relationship with treenode, otherwise will wrong */
|
||||||
/*see Add_FindFiletest in dir_API.cpp*/
|
/*see Add_FindFiletest in dir_API.cpp*/
|
||||||
|
FileNode* fischl_add_entry_for_cache(TreeNode *parent, int new_inode_number, const char *fileName, INode_Data *new_inode);
|
||||||
int fischl_add_entry(TreeNode *parent, int new_inode_number, const char *fileName, INode_Data *new_inode);
|
int fischl_add_entry(TreeNode *parent, int new_inode_number, const char *fileName, INode_Data *new_inode);
|
||||||
int fischl_rm_entry(TreeNode *parent, const char *fileName);
|
int fischl_rm_entry(TreeNode *parent, const char *fileName);
|
||||||
/*if want to use dir mode use the subdirectory treeNode pointer */
|
/*if want to use dir mode use the subdirectory treeNode pointer */
|
||||||
//e.g. FileNode *Dirnode = fischl_find_entry(); can see file inside with Dirnode->subdirectory
|
//e.g. FileNode *Dirnode = fischl_find_entry(); can see file inside with Dirnode->subdirectory
|
||||||
//e.g. go to the current Dirnode parent directory, use TreeNode *get_Dir_parent = Dirnode->subdirectory->parent;
|
//e.g. go to the current Dirnode parent directory, use TreeNode *get_Dir_parent = Dirnode->subdirectory->parent;
|
||||||
FileNode *fischl_find_entry(TreeNode *root, const char *path);
|
FileNode *fischl_find_entry(Fs *fs, TreeNode *root, const char *path);
|
||||||
|
|
||||||
void freeTree(TreeNode *node);
|
void freeTree(TreeNode *node);
|
||||||
/*for debug use*/
|
/*for debug use*/
|
||||||
TreeNode *createDirectory(const char *dirName, TreeNode *parent, int hashSize);
|
TreeNode *createDirectory(const char *dirName, TreeNode *parent, int hashSize);
|
||||||
TreeNode *find_parentPath(TreeNode *root, const char *path);
|
TreeNode *find_parentPath(TreeNode *root, const char *path);
|
||||||
|
|
||||||
|
struct DirectoryEntry {
|
||||||
|
u_int64_t inode_number;
|
||||||
|
char file_name[256];
|
||||||
|
void serialize(char* buffer) {
|
||||||
|
u_int64_t t = inode_number;
|
||||||
|
for (int j = 0; j < 8; j++){
|
||||||
|
buffer[j] = t & (((u_int64_t)1<<(8))-1);
|
||||||
|
t >>= 8;
|
||||||
|
}
|
||||||
|
strcpy(buffer+8, file_name);
|
||||||
|
}
|
||||||
|
void deserialize(char* buffer) {
|
||||||
|
inode_number = 0;
|
||||||
|
for (int j = 0; j < 8; j++)
|
||||||
|
inode_number = inode_number | (((u_int64_t)(unsigned char)buffer[j])<<(8*j));
|
||||||
|
strcpy(file_name, buffer+8);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -14,21 +14,29 @@ class FilesOperation {
|
|||||||
//int read_datablock(const INode_Data& inode, u_int64_t index, char* buffer);
|
//int read_datablock(const INode_Data& inode, u_int64_t index, char* buffer);
|
||||||
//int write_datablock(INode_Data& inode, u_int64_t index, char* buffer);
|
//int write_datablock(INode_Data& inode, u_int64_t index, char* buffer);
|
||||||
void initialize_rootinode();
|
void initialize_rootinode();
|
||||||
|
void initialize(bool load);
|
||||||
void printbuffer(const char*,int);
|
void printbuffer(const char*,int);
|
||||||
void printDirectory(u_int64_t);
|
void printDirectory(u_int64_t);
|
||||||
|
bool permission_check(int, INode_Data*);
|
||||||
|
bool permission_check_by_inode_num(int, u_int64_t);
|
||||||
INode_Data* create_new_inode(u_int64_t parent_inode_number, const char* name, mode_t mode);
|
INode_Data* create_new_inode(u_int64_t parent_inode_number, const char* name, mode_t mode);
|
||||||
int insert_inode_to(u_int64_t parent_inode_number, const char* name, INode_Data *new_inode);
|
int insert_inode_to(u_int64_t parent_inode_number, const char* name, INode_Data *new_inode, bool check_replace);
|
||||||
void unlink_inode(u_int64_t inode_number);
|
void unlink_inode(u_int64_t inode_number);
|
||||||
u_int64_t disk_namei(const char* path);
|
u_int64_t disk_namei(const char* path);
|
||||||
u_int64_t namei(const char* path);
|
u_int64_t namei(const char* path);
|
||||||
int fischl_mkdir(const char*, mode_t);
|
int fischl_mkdir(const char*, mode_t);
|
||||||
int fischl_mknod(const char*, mode_t, dev_t);//for special file
|
int fischl_mknod(const char*, mode_t, dev_t);//for special file
|
||||||
|
int fischl_access(const char* path, int mask);
|
||||||
int fischl_create(const char *, mode_t, struct fuse_file_info *);//for regular file
|
int fischl_create(const char *, mode_t, struct fuse_file_info *);//for regular file
|
||||||
int fischl_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi);
|
int fischl_getattr(const char *path, struct stat *stbuf, struct fuse_file_info *fi);
|
||||||
int fischl_readdir(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *, enum fuse_readdir_flags);
|
int fischl_readdir(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *, enum fuse_readdir_flags);
|
||||||
int fischl_releasedir(const char* path, struct fuse_file_info *fi);
|
int fischl_releasedir(const char* path, struct fuse_file_info *fi);
|
||||||
int fischl_unlink (const char *);
|
int fischl_unlink (const char *);
|
||||||
|
int fischl_opendir(const char* path, struct fuse_file_info* fi);
|
||||||
int fischl_rmdir(const char *);
|
int fischl_rmdir(const char *);
|
||||||
|
int fischl_readlink(const char* path, char* buf, size_t size);
|
||||||
|
int fischl_symlink(const char* from, const char* to);
|
||||||
|
int fischl_link(const char* from, const char* to);
|
||||||
int fischl_rename(const char *path, const char *, unsigned int flags);
|
int fischl_rename(const char *path, const char *, unsigned int flags);
|
||||||
int fischl_truncate(const char *path, off_t, struct fuse_file_info *fi);
|
int fischl_truncate(const char *path, off_t, struct fuse_file_info *fi);
|
||||||
int fischl_chmod(const char *path, mode_t, struct fuse_file_info *fi);
|
int fischl_chmod(const char *path, mode_t, struct fuse_file_info *fi);
|
||||||
@ -37,4 +45,7 @@ class FilesOperation {
|
|||||||
int fischl_release (const char *, struct fuse_file_info *);//close file
|
int fischl_release (const char *, struct fuse_file_info *);//close file
|
||||||
int fischl_write(const char *, const char *, size_t, off_t, struct fuse_file_info *);
|
int fischl_write(const char *, const char *, size_t, off_t, struct fuse_file_info *);
|
||||||
int fischl_read(const char *, char *, size_t, off_t, struct fuse_file_info *);
|
int fischl_read(const char *, char *, size_t, off_t, struct fuse_file_info *);
|
||||||
|
int fischl_utimens(const char *path, const struct timespec tv[2], struct fuse_file_info *fi);
|
||||||
|
int fischl_statfs(const char* path, struct statvfs* stbuf);
|
||||||
|
FileNode *fischl_load_entry(TreeNode *root, const char *path);
|
||||||
};
|
};
|
@ -18,7 +18,7 @@ public:
|
|||||||
ssize_t read(INode_Data *inode_data, char buf[], size_t count, size_t offset);
|
ssize_t read(INode_Data *inode_data, char buf[], size_t count, size_t offset);
|
||||||
ssize_t write(INode_Data *inode_data, const char buf[], size_t count,
|
ssize_t write(INode_Data *inode_data, const char buf[], size_t count,
|
||||||
size_t offset);
|
size_t offset);
|
||||||
int truncate(INode_Data *inode_data, size_t length);
|
int truncate(INode_Data *inode_data, off_t length);
|
||||||
ssize_t lseek_next_data(INode_Data *inode_data, size_t offset);
|
ssize_t lseek_next_data(INode_Data *inode_data, size_t offset);
|
||||||
ssize_t lseek_next_hole(INode_Data *inode_data, size_t offset);
|
ssize_t lseek_next_hole(INode_Data *inode_data, size_t offset);
|
||||||
|
|
||||||
|
@ -25,12 +25,14 @@ public:
|
|||||||
u_int64_t inode_num;
|
u_int64_t inode_num;
|
||||||
|
|
||||||
#define NUMBER_OF_METADATA_BYTES \
|
#define NUMBER_OF_METADATA_BYTES \
|
||||||
(4 * sizeof(u_int64_t) + (2 * sizeof(u_int32_t)))
|
(6 * sizeof(u_int64_t) + (2 * sizeof(u_int32_t)))
|
||||||
struct INode_MetaData {
|
struct INode_MetaData {
|
||||||
u_int64_t uid;
|
u_int64_t uid;
|
||||||
u_int64_t gid;
|
u_int64_t gid;
|
||||||
u_int64_t permissions;
|
u_int64_t permissions;
|
||||||
u_int64_t size; // not yet implemented
|
u_int64_t size; // not yet implemented
|
||||||
|
u_int64_t access_time;
|
||||||
|
u_int64_t modification_time;
|
||||||
u_int32_t reference_count;
|
u_int32_t reference_count;
|
||||||
u_int32_t flags;
|
u_int32_t flags;
|
||||||
} metadata;
|
} metadata;
|
||||||
@ -39,6 +41,10 @@ public:
|
|||||||
|
|
||||||
#define NUMBER_OF_DIRECT_BLOCKS \
|
#define NUMBER_OF_DIRECT_BLOCKS \
|
||||||
(((INODE_SIZE - NUMBER_OF_METADATA_BYTES) / sizeof(u_int64_t)) - 3)
|
(((INODE_SIZE - NUMBER_OF_METADATA_BYTES) / sizeof(u_int64_t)) - 3)
|
||||||
|
#define FILE_SIZE_MAX \
|
||||||
|
(IO_BLOCK_SIZE * (NUMBER_OF_DIRECT_BLOCKS + INDIRECT_BLOCKS + \
|
||||||
|
(INDIRECT_BLOCKS * INDIRECT_BLOCKS) + \
|
||||||
|
(INDIRECT_BLOCKS * INDIRECT_BLOCKS * INDIRECT_BLOCKS)))
|
||||||
|
|
||||||
u_int64_t single_indirect_block, double_indirect_block, triple_indirect_block;
|
u_int64_t single_indirect_block, double_indirect_block, triple_indirect_block;
|
||||||
u_int64_t direct_blocks[NUMBER_OF_DIRECT_BLOCKS];
|
u_int64_t direct_blocks[NUMBER_OF_DIRECT_BLOCKS];
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define FS_CONSTANTS_HPP
|
#define FS_CONSTANTS_HPP
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
@ -11,10 +12,11 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
#define IO_BLOCK_SIZE 4096
|
#define IO_BLOCK_SIZE 4096
|
||||||
#define INDIRECT_BLOCKS 512
|
#define INDIRECT_BLOCKS 512
|
||||||
|
|
||||||
#define NUM_INODE_BLOCKS 1023
|
#define NUM_INODE_BLOCKS 262143
|
||||||
|
|
||||||
#define INODE_SIZE 512
|
#define INODE_SIZE 512
|
||||||
|
|
||||||
|
@ -156,6 +156,26 @@ TreeNode *fischl_init_entry(int new_inode_number, const char *fileName, INode_Da
|
|||||||
return newDir;
|
return newDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileNode* fischl_add_entry_for_cache(TreeNode *parent, int new_inode_number, const char *fileName, INode_Data *new_inode){
|
||||||
|
char *Name = strdup(fileName);
|
||||||
|
TreeNode *newDir = NULL;
|
||||||
|
/*If directory, malloc TreeNode, and then create filenode that belongs to Parent hash table content*/
|
||||||
|
if ((new_inode->metadata.permissions & S_IFMT) == S_IFDIR) {
|
||||||
|
newDir = (TreeNode *)malloc(sizeof(TreeNode));
|
||||||
|
newDir->dirName = Name;
|
||||||
|
newDir->contents = createHashTable(20);//hasSize define 20
|
||||||
|
newDir->parent = parent;
|
||||||
|
}
|
||||||
|
FileNode *newFile = insertHash(parent->contents, Name, newDir); //newDir == NULL indicates it's a file
|
||||||
|
//assign INode *new_inode metadata to data member in FileNode structure
|
||||||
|
newFile->permissions = new_inode->metadata.permissions;
|
||||||
|
newFile->inode_number = new_inode_number;
|
||||||
|
//Diretory have its own file information, that is . here
|
||||||
|
if(newDir != NULL)
|
||||||
|
newDir->self_info = newFile;
|
||||||
|
return newFile;
|
||||||
|
}
|
||||||
|
|
||||||
int fischl_add_entry(TreeNode *parent, int new_inode_number, const char *fileName, INode_Data *new_inode){
|
int fischl_add_entry(TreeNode *parent, int new_inode_number, const char *fileName, INode_Data *new_inode){
|
||||||
char *Name = strdup(fileName);
|
char *Name = strdup(fileName);
|
||||||
TreeNode *newDir = NULL;
|
TreeNode *newDir = NULL;
|
||||||
@ -191,13 +211,15 @@ int fischl_rm_entry(TreeNode *parent, const char *fileName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FileNode *fischl_find_entry(TreeNode *root, const char *path){
|
FileNode *fischl_find_entry(Fs *fs, TreeNode *root, const char *path){
|
||||||
//support . and .. function
|
//support . and .. function
|
||||||
char *pathCopy = strdup(path);
|
char *pathCopy = strdup(path);
|
||||||
char *segment = strtok(pathCopy, "/");
|
char *segment = strtok(pathCopy, "/");
|
||||||
TreeNode *current = root;
|
TreeNode *current = root;
|
||||||
FileNode *file = NULL;
|
FileNode *file = NULL;
|
||||||
|
|
||||||
|
printf("FINDING %s %s %llu\n", path, segment, current->self_info->inode_number);
|
||||||
|
|
||||||
while (segment != NULL && current != NULL) {
|
while (segment != NULL && current != NULL) {
|
||||||
if (strcmp(segment, "..") == 0) {
|
if (strcmp(segment, "..") == 0) {
|
||||||
// Move up to the parent directory
|
// Move up to the parent directory
|
||||||
@ -214,8 +236,29 @@ FileNode *fischl_find_entry(TreeNode *root, const char *path){
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
file = lookupHash(current->contents, segment);
|
file = lookupHash(current->contents, segment);
|
||||||
|
if (file == NULL) {
|
||||||
|
// find on disk whether this exists
|
||||||
|
INode_Data inode;
|
||||||
|
inode.inode_num = current->self_info->inode_number;
|
||||||
|
fs->inode_manager->load_inode(&inode);
|
||||||
|
char buffer[IO_BLOCK_SIZE] = {0};
|
||||||
|
for (u_int64_t idx=0; idx<inode.metadata.size/IO_BLOCK_SIZE; idx++) {
|
||||||
|
fs->read(&inode, buffer, IO_BLOCK_SIZE, idx*IO_BLOCK_SIZE);
|
||||||
|
DirectoryEntry ent;
|
||||||
|
for(int i=0;i<=IO_BLOCK_SIZE-264;i+=264){
|
||||||
|
ent.deserialize(buffer+i);
|
||||||
|
//printf("WARNING:%d %llu %llu %s %s\n",__LINE__,inode.inode_num, ent.inode_number, ent.file_name, segment);
|
||||||
|
if (ent.inode_number && strcmp(ent.file_name, segment)==0) {
|
||||||
|
file = fischl_add_entry_for_cache(current, ent.inode_number, ent.file_name, &inode);
|
||||||
|
//printf("DONE !! %llu\n", file->inode_number);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (file != NULL && file->subdirectory == NULL) {
|
if (file != NULL && file->subdirectory == NULL) {
|
||||||
free(pathCopy);
|
free(pathCopy);
|
||||||
|
printf("FOUND !! %llu\n", file->inode_number);
|
||||||
return file; //File found
|
return file; //File found
|
||||||
//return current; return filenode
|
//return current; return filenode
|
||||||
}
|
}
|
||||||
|
688
lib/files.cpp
688
lib/files.cpp
@ -6,25 +6,9 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
struct DirectoryEntry {
|
FileNode *FilesOperation::fischl_load_entry(TreeNode *root, const char *path) {
|
||||||
u_int64_t inode_number;
|
return fischl_find_entry(fs, root, path);
|
||||||
char file_name[256];
|
|
||||||
void serialize(char *buffer) {
|
|
||||||
u_int64_t t = inode_number;
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
buffer[j] = t & (((u_int64_t)1 << (8)) - 1);
|
|
||||||
t >>= 8;
|
|
||||||
}
|
}
|
||||||
strcpy(buffer + 8, file_name);
|
|
||||||
}
|
|
||||||
void deserialize(char *buffer) {
|
|
||||||
inode_number = 0;
|
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
inode_number =
|
|
||||||
inode_number | (((u_int64_t)(unsigned char)buffer[j]) << (8 * j));
|
|
||||||
strcpy(file_name, buffer + 8);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void FilesOperation::printbuffer(const char *buff, int len) {
|
void FilesOperation::printbuffer(const char *buff, int len) {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
@ -55,7 +39,7 @@ void FilesOperation::create_dot_dotdot(INode_Data *inode,
|
|||||||
void FilesOperation::initialize_rootinode() {
|
void FilesOperation::initialize_rootinode() {
|
||||||
// this method must be called explicitly right after initializion
|
// this method must be called explicitly right after initializion
|
||||||
INode_Data *root_inode = new INode_Data();
|
INode_Data *root_inode = new INode_Data();
|
||||||
fs->inode_manager->new_inode(0, 0, S_IFDIR, root_inode);
|
fs->inode_manager->new_inode(getuid(), getgid(), S_IFDIR | 0755, root_inode);
|
||||||
u_int64_t root_inode_number = root_inode->inode_num;
|
u_int64_t root_inode_number = root_inode->inode_num;
|
||||||
create_dot_dotdot(root_inode, root_inode_number);
|
create_dot_dotdot(root_inode, root_inode_number);
|
||||||
root_node = fischl_init_entry(root_inode_number, "/", root_inode);
|
root_node = fischl_init_entry(root_inode_number, "/", root_inode);
|
||||||
@ -63,6 +47,19 @@ void FilesOperation::initialize_rootinode() {
|
|||||||
fs->inode_manager->save_inode(root_inode);
|
fs->inode_manager->save_inode(root_inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FilesOperation::initialize(bool load) {
|
||||||
|
if (load) {
|
||||||
|
INode_Data *root_inode = new INode_Data();
|
||||||
|
root_inode->inode_num = 1;
|
||||||
|
fs->inode_manager->load_inode(root_inode);
|
||||||
|
root_node = fischl_init_entry(1, "/", root_inode);
|
||||||
|
assert(root_node->self_info != NULL);
|
||||||
|
fs->load_superblock();
|
||||||
|
} else {
|
||||||
|
initialize_rootinode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FilesOperation::printDirectory(u_int64_t inode_number) {
|
void FilesOperation::printDirectory(u_int64_t inode_number) {
|
||||||
INode_Data inode;
|
INode_Data inode;
|
||||||
inode.inode_num = inode_number;
|
inode.inode_num = inode_number;
|
||||||
@ -118,7 +115,10 @@ INode_Data *FilesOperation::create_new_inode(u_int64_t parent_inode_number,
|
|||||||
|
|
||||||
bool allocated = false;
|
bool allocated = false;
|
||||||
INode_Data *new_inode = new INode_Data();
|
INode_Data *new_inode = new INode_Data();
|
||||||
fs->inode_manager->new_inode(0, 0, mode, new_inode);
|
fs->inode_manager->new_inode(getuid(), getgid(), mode, new_inode);
|
||||||
|
printf("NEW INODE %llu %llu %llu %o\n", new_inode->inode_num,
|
||||||
|
new_inode->metadata.uid, new_inode->metadata.gid,
|
||||||
|
(mode_t)new_inode->metadata.permissions);
|
||||||
if ((mode & S_IFMT) == S_IFDIR) {
|
if ((mode & S_IFMT) == S_IFDIR) {
|
||||||
create_dot_dotdot(new_inode, parent_inode_number);
|
create_dot_dotdot(new_inode, parent_inode_number);
|
||||||
fs->inode_manager->save_inode(new_inode);
|
fs->inode_manager->save_inode(new_inode);
|
||||||
@ -212,13 +212,88 @@ u_int64_t FilesOperation::disk_namei(const char *path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u_int64_t FilesOperation::namei(const char *path) {
|
u_int64_t FilesOperation::namei(const char *path) {
|
||||||
FileNode *filenode = fischl_find_entry(root_node, path);
|
FileNode *filenode = fischl_load_entry(root_node, path);
|
||||||
if (filenode)
|
if (filenode)
|
||||||
return filenode->inode_number;
|
return filenode->inode_number;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FilesOperation::permission_check(int mask, INode_Data *inode) {
|
||||||
|
mode_t per = (mode_t)inode->metadata.permissions;
|
||||||
|
uid_t uid = (uid_t)inode->metadata.uid;
|
||||||
|
gid_t gid = (gid_t)inode->metadata.gid;
|
||||||
|
if (getuid() == 0) return true;
|
||||||
|
// printf("PERMISSION CHECK %d %llu %llu %o\n", mask, uid, gid, per);
|
||||||
|
if (getuid() == uid) {
|
||||||
|
if ((mask & R_OK) && !(per & S_IRUSR)) {
|
||||||
|
return false; // Permission denied for reading
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mask & W_OK) && !(per & S_IWUSR)) {
|
||||||
|
return false; // Permission denied for writing
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mask & X_OK) && !(per & S_IXUSR)) {
|
||||||
|
return false; // Permission denied for executing
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else if (getgid() == gid) {
|
||||||
|
if ((mask & R_OK) && !(per & S_IRGRP)) {
|
||||||
|
return false; // Permission denied for reading
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mask & W_OK) && !(per & S_IWGRP)) {
|
||||||
|
return false; // Permission denied for writing
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mask & X_OK) && !(per & S_IXGRP)) {
|
||||||
|
return false; // Permission denied for executing
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if ((mask & R_OK) && !(per & S_IROTH)) {
|
||||||
|
return false; // Permission denied for reading
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mask & W_OK) && !(per & S_IWOTH)) {
|
||||||
|
return false; // Permission denied for writing
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mask & X_OK) && !(per & S_IXOTH)) {
|
||||||
|
return false; // Permission denied for executing
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilesOperation::permission_check_by_inode_num(int mask,
|
||||||
|
u_int64_t inode_num) {
|
||||||
|
INode_Data inode;
|
||||||
|
inode.inode_num = inode_num;
|
||||||
|
|
||||||
|
fs->inode_manager->load_inode(&inode);
|
||||||
|
if (!permission_check(mask, &inode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FilesOperation::fischl_access(const char *path, int mask) {
|
||||||
|
|
||||||
|
u_int64_t fh = namei(path);
|
||||||
|
|
||||||
|
if (fh == -1) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!permission_check_by_inode_num(mask, fh)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
// return 0 when access is allowed
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int FilesOperation::fischl_mkdir(const char *path, mode_t mode) {
|
int FilesOperation::fischl_mkdir(const char *path, mode_t mode) {
|
||||||
// check path
|
// check path
|
||||||
char *pathdup = strdup(path);
|
char *pathdup = strdup(path);
|
||||||
@ -231,7 +306,7 @@ int FilesOperation::fischl_mkdir(const char *path, mode_t mode) {
|
|||||||
// <parent path> only
|
// <parent path> only
|
||||||
|
|
||||||
FileNode *parent_filenode = strlen(ParentPath)
|
FileNode *parent_filenode = strlen(ParentPath)
|
||||||
? fischl_find_entry(root_node, ParentPath)
|
? fischl_load_entry(root_node, ParentPath)
|
||||||
: root_node->self_info;
|
: root_node->self_info;
|
||||||
if (parent_filenode == NULL) {
|
if (parent_filenode == NULL) {
|
||||||
fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__, __LINE__,
|
fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__, __LINE__,
|
||||||
@ -240,6 +315,10 @@ int FilesOperation::fischl_mkdir(const char *path, mode_t mode) {
|
|||||||
return -ENOENT; // parentpath directory does not exist
|
return -ENOENT; // parentpath directory does not exist
|
||||||
}
|
}
|
||||||
u_int64_t parent_inode_number = parent_filenode->inode_number;
|
u_int64_t parent_inode_number = parent_filenode->inode_number;
|
||||||
|
if (!permission_check_by_inode_num(W_OK, parent_inode_number)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
// printf("%s, %llu, %s\n", parent_filenode->name, parent_inode_number,
|
// printf("%s, %llu, %s\n", parent_filenode->name, parent_inode_number,
|
||||||
// newDirname); make new inode
|
// newDirname); make new inode
|
||||||
INode_Data *ret =
|
INode_Data *ret =
|
||||||
@ -268,7 +347,7 @@ int FilesOperation::fischl_mknod(const char *path, mode_t mode, dev_t dev) {
|
|||||||
// fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__,
|
// fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__,
|
||||||
// ParentPath, strlen(ParentPath));
|
// ParentPath, strlen(ParentPath));
|
||||||
FileNode *parent_filenode = strlen(ParentPath)
|
FileNode *parent_filenode = strlen(ParentPath)
|
||||||
? fischl_find_entry(root_node, ParentPath)
|
? fischl_load_entry(root_node, ParentPath)
|
||||||
: root_node->self_info;
|
: root_node->self_info;
|
||||||
if (parent_filenode == NULL) {
|
if (parent_filenode == NULL) {
|
||||||
fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__, __LINE__,
|
fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__, __LINE__,
|
||||||
@ -277,6 +356,9 @@ int FilesOperation::fischl_mknod(const char *path, mode_t mode, dev_t dev) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
u_int64_t parent_inode_number = parent_filenode->inode_number;
|
u_int64_t parent_inode_number = parent_filenode->inode_number;
|
||||||
|
if (!permission_check_by_inode_num(W_OK, parent_inode_number)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
// make new inode
|
// make new inode
|
||||||
INode_Data *ret = create_new_inode(parent_inode_number, newFilename, mode);
|
INode_Data *ret = create_new_inode(parent_inode_number, newFilename, mode);
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
@ -304,7 +386,7 @@ int FilesOperation::fischl_create(const char *path, mode_t mode,
|
|||||||
// fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__,
|
// fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__,
|
||||||
// ParentPath, strlen(ParentPath));
|
// ParentPath, strlen(ParentPath));
|
||||||
FileNode *parent_filenode = strlen(ParentPath)
|
FileNode *parent_filenode = strlen(ParentPath)
|
||||||
? fischl_find_entry(root_node, ParentPath)
|
? fischl_load_entry(root_node, ParentPath)
|
||||||
: root_node->self_info;
|
: root_node->self_info;
|
||||||
if (parent_filenode == NULL) {
|
if (parent_filenode == NULL) {
|
||||||
fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__, __LINE__,
|
fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__, __LINE__,
|
||||||
@ -313,6 +395,9 @@ int FilesOperation::fischl_create(const char *path, mode_t mode,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
u_int64_t parent_inode_number = parent_filenode->inode_number;
|
u_int64_t parent_inode_number = parent_filenode->inode_number;
|
||||||
|
if (!permission_check_by_inode_num(W_OK, parent_inode_number)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
// make new inode
|
// make new inode
|
||||||
INode_Data *ret = create_new_inode(parent_inode_number, newFilename, mode);
|
INode_Data *ret = create_new_inode(parent_inode_number, newFilename, mode);
|
||||||
if (ret == NULL)
|
if (ret == NULL)
|
||||||
@ -342,20 +427,44 @@ int FilesOperation::fischl_getattr(const char *path, struct stat *stbuf,
|
|||||||
inode.inode_num = fh;
|
inode.inode_num = fh;
|
||||||
fs->inode_manager->load_inode(&inode);
|
fs->inode_manager->load_inode(&inode);
|
||||||
|
|
||||||
memset(stbuf, 0, sizeof(struct stat));
|
// printf("GETATTR PERM %o\n", (mode_t)inode.metadata.permissions);
|
||||||
|
|
||||||
|
// memset(stbuf, 0, sizeof(struct stat));
|
||||||
if ((inode.metadata.permissions & S_IFMT) == S_IFDIR) {
|
if ((inode.metadata.permissions & S_IFMT) == S_IFDIR) {
|
||||||
stbuf->st_mode = S_IFDIR | 0755;
|
stbuf->st_mode = (mode_t)inode.metadata.permissions; // S_IFDIR | 0755;
|
||||||
stbuf->st_nlink = inode.metadata.reference_count;
|
stbuf->st_nlink = 2; // inode.metadata.reference_count;
|
||||||
stbuf->st_uid = inode.metadata.uid;
|
stbuf->st_uid = inode.metadata.uid;
|
||||||
stbuf->st_gid = inode.metadata.gid;
|
stbuf->st_gid = inode.metadata.gid;
|
||||||
} else {
|
stbuf->st_atime = (time_t)(inode.metadata.access_time / 1000000000ULL);
|
||||||
stbuf->st_mode = S_IFREG | 0444;
|
stbuf->st_mtime =
|
||||||
stbuf->st_nlink = inode.metadata.reference_count;
|
(time_t)(inode.metadata.modification_time / 1000000000ULL);
|
||||||
|
stbuf->st_size = IO_BLOCK_SIZE;
|
||||||
|
stbuf->st_ino = inode.inode_num;
|
||||||
|
} else if (S_ISLNK(inode.metadata.permissions)) {
|
||||||
|
stbuf->st_mode = (mode_t)inode.metadata.permissions;
|
||||||
|
stbuf->st_nlink = 1; // inode.metadata.reference_count;
|
||||||
stbuf->st_uid = inode.metadata.uid;
|
stbuf->st_uid = inode.metadata.uid;
|
||||||
stbuf->st_gid = inode.metadata.gid;
|
stbuf->st_gid = inode.metadata.gid;
|
||||||
|
stbuf->st_atime = (time_t)(inode.metadata.access_time / 1000000000ULL);
|
||||||
|
stbuf->st_mtime =
|
||||||
|
(time_t)(inode.metadata.modification_time / 1000000000ULL);
|
||||||
stbuf->st_size = inode.metadata.size;
|
stbuf->st_size = inode.metadata.size;
|
||||||
|
stbuf->st_ino = inode.inode_num;
|
||||||
|
} else {
|
||||||
|
stbuf->st_mode = (mode_t)inode.metadata.permissions;
|
||||||
|
stbuf->st_nlink = inode.metadata.reference_count;
|
||||||
|
stbuf->st_uid = inode.metadata.uid;
|
||||||
|
stbuf->st_gid = inode.metadata.gid;
|
||||||
|
// printf("GETATTR %llu %llu %llu %o\n", inode.inode_num,
|
||||||
|
// inode.metadata.uid, inode.metadata.gid,
|
||||||
|
// (mode_t)inode.metadata.permissions);
|
||||||
|
stbuf->st_atime = (time_t)(inode.metadata.access_time / 1000000000ULL);
|
||||||
|
stbuf->st_mtime =
|
||||||
|
(time_t)(inode.metadata.modification_time / 1000000000ULL);
|
||||||
|
stbuf->st_size = inode.metadata.size;
|
||||||
|
stbuf->st_ino = inode.inode_num;
|
||||||
}
|
}
|
||||||
perror(std::to_string(inode.metadata.size).c_str());
|
// perror(std::to_string(inode.inode_num).c_str());
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,6 +482,9 @@ int FilesOperation::fischl_readdir(const char *path, void *buf,
|
|||||||
INode_Data inode;
|
INode_Data inode;
|
||||||
inode.inode_num = fh;
|
inode.inode_num = fh;
|
||||||
fs->inode_manager->load_inode(&inode);
|
fs->inode_manager->load_inode(&inode);
|
||||||
|
if (!permission_check(R_OK, &inode)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
char buffer[IO_BLOCK_SIZE] = {0};
|
char buffer[IO_BLOCK_SIZE] = {0};
|
||||||
for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) {
|
for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) {
|
||||||
fs->read(&inode, buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
|
fs->read(&inode, buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
|
||||||
@ -381,7 +493,7 @@ int FilesOperation::fischl_readdir(const char *path, void *buf,
|
|||||||
ent.deserialize(buffer + i);
|
ent.deserialize(buffer + i);
|
||||||
if (ent.inode_number) {
|
if (ent.inode_number) {
|
||||||
filler(buf, ent.file_name, NULL, 0, FUSE_FILL_DIR_PLUS);
|
filler(buf, ent.file_name, NULL, 0, FUSE_FILL_DIR_PLUS);
|
||||||
// printf("%s\t%llu;\t", ent.file_name, ent.inode_number);
|
printf("%s\t%llu;\t\n", ent.file_name, ent.inode_number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -391,7 +503,7 @@ int FilesOperation::fischl_readdir(const char *path, void *buf,
|
|||||||
|
|
||||||
int FilesOperation::fischl_releasedir(const char *path,
|
int FilesOperation::fischl_releasedir(const char *path,
|
||||||
struct fuse_file_info *fi) {
|
struct fuse_file_info *fi) {
|
||||||
if (fischl_find_entry(root_node, path) == NULL)
|
if (fischl_load_entry(root_node, path) == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
// do with file descriptor that cannot be used
|
// do with file descriptor that cannot be used
|
||||||
fi->fh = -1;
|
fi->fh = -1;
|
||||||
@ -402,6 +514,12 @@ void FilesOperation::unlink_inode(u_int64_t inode_number) {
|
|||||||
INode_Data inode;
|
INode_Data inode;
|
||||||
inode.inode_num = inode_number;
|
inode.inode_num = inode_number;
|
||||||
fs->inode_manager->load_inode(&inode);
|
fs->inode_manager->load_inode(&inode);
|
||||||
|
if (inode.metadata.reference_count > 1 &&
|
||||||
|
(inode.metadata.permissions & S_IFMT) != S_IFDIR) {
|
||||||
|
inode.metadata.reference_count -= 1;
|
||||||
|
fs->inode_manager->save_inode(&inode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ((inode.metadata.permissions & S_IFMT) == S_IFDIR) {
|
if ((inode.metadata.permissions & S_IFMT) == S_IFDIR) {
|
||||||
char buffer[IO_BLOCK_SIZE] = {0};
|
char buffer[IO_BLOCK_SIZE] = {0};
|
||||||
for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) {
|
for (u_int64_t idx = 0; idx < inode.metadata.size / IO_BLOCK_SIZE; idx++) {
|
||||||
@ -420,6 +538,26 @@ void FilesOperation::unlink_inode(u_int64_t inode_number) {
|
|||||||
fs->inode_manager->free_inode(&inode);
|
fs->inode_manager->free_inode(&inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FilesOperation::fischl_opendir(const char *path,
|
||||||
|
struct fuse_file_info *fi) {
|
||||||
|
|
||||||
|
u_int64_t fh = namei(path);
|
||||||
|
|
||||||
|
if (fh == -1) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
INode_Data inode;
|
||||||
|
inode.inode_num = fh;
|
||||||
|
|
||||||
|
fs->inode_manager->load_inode(&inode);
|
||||||
|
if (!permission_check(X_OK | R_OK, &inode)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
fi->fh = fh;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int FilesOperation::fischl_rmdir(const char *path) {
|
int FilesOperation::fischl_rmdir(const char *path) {
|
||||||
char *pathdup = strdup(path);
|
char *pathdup = strdup(path);
|
||||||
char *lastSlash = strrchr(pathdup, '/');
|
char *lastSlash = strrchr(pathdup, '/');
|
||||||
@ -430,9 +568,9 @@ int FilesOperation::fischl_rmdir(const char *path) {
|
|||||||
printf("refusing to remove . or ..\n");
|
printf("refusing to remove . or ..\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
FileNode *parent_filenode = fischl_find_entry(root_node, ParentPath);
|
FileNode *parent_filenode = fischl_load_entry(root_node, ParentPath);
|
||||||
if (parent_filenode == NULL) {
|
if (parent_filenode == NULL) {
|
||||||
printf("parent %s not found by fischl_find_entry\n", ParentPath);
|
printf("parent %s not found by fischl_load_entry\n", ParentPath);
|
||||||
free(pathdup);
|
free(pathdup);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -443,6 +581,9 @@ int FilesOperation::fischl_rmdir(const char *path) {
|
|||||||
INode_Data parent_INode;
|
INode_Data parent_INode;
|
||||||
parent_INode.inode_num = parent_inode_number;
|
parent_INode.inode_num = parent_inode_number;
|
||||||
fs->inode_manager->load_inode(&parent_INode);
|
fs->inode_manager->load_inode(&parent_INode);
|
||||||
|
if (!permission_check(W_OK, &parent_INode)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
char rw_buffer[IO_BLOCK_SIZE] = {0};
|
char rw_buffer[IO_BLOCK_SIZE] = {0};
|
||||||
for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE;
|
for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE;
|
||||||
idx++) {
|
idx++) {
|
||||||
@ -509,13 +650,18 @@ int FilesOperation::fischl_chown(const char *path, uid_t uid, gid_t gid,
|
|||||||
INode_Data inode;
|
INode_Data inode;
|
||||||
inode.inode_num = fh;
|
inode.inode_num = fh;
|
||||||
fs->inode_manager->load_inode(&inode);
|
fs->inode_manager->load_inode(&inode);
|
||||||
|
if (uid != (uid_t)(-1)) {
|
||||||
inode.metadata.uid = uid;
|
inode.metadata.uid = uid;
|
||||||
|
}
|
||||||
|
if (gid != (gid_t)(-1)) {
|
||||||
inode.metadata.gid = gid;
|
inode.metadata.gid = gid;
|
||||||
|
}
|
||||||
fs->inode_manager->save_inode(&inode);
|
fs->inode_manager->save_inode(&inode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FilesOperation::fischl_unlink(const char *path) {
|
int FilesOperation::fischl_unlink(const char *path) {
|
||||||
|
|
||||||
char *pathdup = strdup(path);
|
char *pathdup = strdup(path);
|
||||||
char *lastSlash = strrchr(pathdup, '/');
|
char *lastSlash = strrchr(pathdup, '/');
|
||||||
*lastSlash = '\0';
|
*lastSlash = '\0';
|
||||||
@ -525,9 +671,9 @@ int FilesOperation::fischl_unlink(const char *path) {
|
|||||||
printf("refusing to remove . or ..\n");
|
printf("refusing to remove . or ..\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
FileNode *parent_filenode = fischl_find_entry(root_node, ParentPath);
|
FileNode *parent_filenode = fischl_load_entry(root_node, ParentPath);
|
||||||
if (parent_filenode == NULL) {
|
if (parent_filenode == NULL) {
|
||||||
printf("parent %s not found by fischl_find_entry\n", ParentPath);
|
printf("parent %s not found by fischl_load_entry\n", ParentPath);
|
||||||
free(pathdup);
|
free(pathdup);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -538,6 +684,9 @@ int FilesOperation::fischl_unlink(const char *path) {
|
|||||||
INode_Data parent_INode;
|
INode_Data parent_INode;
|
||||||
parent_INode.inode_num = parent_inode_number;
|
parent_INode.inode_num = parent_inode_number;
|
||||||
fs->inode_manager->load_inode(&parent_INode);
|
fs->inode_manager->load_inode(&parent_INode);
|
||||||
|
if (!permission_check(W_OK, &parent_INode)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
char rw_buffer[IO_BLOCK_SIZE] = {0};
|
char rw_buffer[IO_BLOCK_SIZE] = {0};
|
||||||
for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE;
|
for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE;
|
||||||
idx++) {
|
idx++) {
|
||||||
@ -547,6 +696,9 @@ int FilesOperation::fischl_unlink(const char *path) {
|
|||||||
ent.deserialize(rw_buffer + i);
|
ent.deserialize(rw_buffer + i);
|
||||||
if (strcmp(ent.file_name, filename) == 0) {
|
if (strcmp(ent.file_name, filename) == 0) {
|
||||||
target_inode = ent.inode_number;
|
target_inode = ent.inode_number;
|
||||||
|
if (!permission_check_by_inode_num(W_OK, target_inode)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
ent.inode_number = 0;
|
ent.inode_number = 0;
|
||||||
memset(ent.file_name, 0, sizeof(ent.file_name));
|
memset(ent.file_name, 0, sizeof(ent.file_name));
|
||||||
ent.serialize(rw_buffer + i);
|
ent.serialize(rw_buffer + i);
|
||||||
@ -578,8 +730,30 @@ int FilesOperation::fischl_open(const char *path, struct fuse_file_info *fi) {
|
|||||||
the kernel. if no files will use create function
|
the kernel. if no files will use create function
|
||||||
*/
|
*/
|
||||||
FileNode *get_file;
|
FileNode *get_file;
|
||||||
if ((get_file = fischl_find_entry(root_node, path)) == NULL)
|
if ((get_file = fischl_load_entry(root_node, path)) == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
|
INode_Data inode;
|
||||||
|
inode.inode_num = get_file->inode_number;
|
||||||
|
|
||||||
|
fs->inode_manager->load_inode(&inode);
|
||||||
|
|
||||||
|
if (fi->flags & O_WRONLY) {
|
||||||
|
if (!permission_check(W_OK, &inode)) {
|
||||||
|
return -EACCES; // Permission denied
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fi->flags & O_RDONLY) {
|
||||||
|
if (!permission_check(R_OK, &inode)) {
|
||||||
|
return -EACCES; // Permission denied
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fi->flags & O_RDWR) {
|
||||||
|
if (!permission_check(R_OK | W_OK, &inode)) {
|
||||||
|
return -EACCES; // Permission denied
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if need to do with flag fi->flags ((fi->flags & O_ACCMODE)). Initial
|
// if need to do with flag fi->flags ((fi->flags & O_ACCMODE)). Initial
|
||||||
// setting ALL access create function will handle file descriptor fi->fh
|
// setting ALL access create function will handle file descriptor fi->fh
|
||||||
fi->fh = get_file->inode_number;
|
fi->fh = get_file->inode_number;
|
||||||
@ -592,7 +766,7 @@ int FilesOperation::fischl_release(const char *path,
|
|||||||
the kernel. if no files will use create function
|
the kernel. if no files will use create function
|
||||||
*/
|
*/
|
||||||
FileNode *get_file;
|
FileNode *get_file;
|
||||||
if ((get_file = fischl_find_entry(root_node, path)) == NULL)
|
if ((get_file = fischl_load_entry(root_node, path)) == NULL)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
// do with file descriptor that cannot be used
|
// do with file descriptor that cannot be used
|
||||||
fi->fh = -1;
|
fi->fh = -1;
|
||||||
@ -612,7 +786,7 @@ int FilesOperation::fischl_write(const char *path, const char *buf, size_t size,
|
|||||||
*/
|
*/
|
||||||
// use path for debug, filedescriptor is enough
|
// use path for debug, filedescriptor is enough
|
||||||
// FileNode *get_file;
|
// FileNode *get_file;
|
||||||
// if((get_file = fischl_find_entry(root_node, path)) == NULL)
|
// if((get_file = fischl_load_entry(root_node, path)) == NULL)
|
||||||
// return -ENOENT;
|
// return -ENOENT;
|
||||||
// Caution! this based on content in file are multiple of IO_BLOCK_SIZE, not
|
// Caution! this based on content in file are multiple of IO_BLOCK_SIZE, not
|
||||||
// the exact write size. based on current write_datablock API implement, when
|
// the exact write size. based on current write_datablock API implement, when
|
||||||
@ -629,7 +803,7 @@ int FilesOperation::fischl_write(const char *path, const char *buf, size_t size,
|
|||||||
// Allocate memory for the new buffer
|
// Allocate memory for the new buffer
|
||||||
char *buffer = (char *)malloc(size);
|
char *buffer = (char *)malloc(size);
|
||||||
memcpy(buffer, buf, size);
|
memcpy(buffer, buf, size);
|
||||||
size_t bytes_write = fs->write(&inode, buffer, size, offset);
|
ssize_t bytes_write = fs->write(&inode, buffer, size, offset);
|
||||||
/*size_t block_index = offset / IO_BLOCK_SIZE; // Starting block index
|
/*size_t block_index = offset / IO_BLOCK_SIZE; // Starting block index
|
||||||
size_t block_offset = offset % IO_BLOCK_SIZE; // Offset within the first block
|
size_t block_offset = offset % IO_BLOCK_SIZE; // Offset within the first block
|
||||||
while (bytes_write < size) {
|
while (bytes_write < size) {
|
||||||
@ -645,11 +819,88 @@ int FilesOperation::fischl_write(const char *path, const char *buf, size_t size,
|
|||||||
}*/
|
}*/
|
||||||
fs->inode_manager->save_inode(&inode);
|
fs->inode_manager->save_inode(&inode);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
if (bytes_write < 0)
|
||||||
|
return -errno;
|
||||||
return bytes_write; // Return the actual number of bytes read
|
return bytes_write; // Return the actual number of bytes read
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FilesOperation::fischl_readlink(const char *path, char *buf, size_t size) {
|
||||||
|
FileNode *get_file;
|
||||||
|
if ((get_file = fischl_load_entry(root_node, path)) == NULL)
|
||||||
|
return -ENOENT;
|
||||||
|
INode_Data symlink_inode;
|
||||||
|
symlink_inode.inode_num = get_file->inode_number;
|
||||||
|
fs->inode_manager->load_inode(&symlink_inode);
|
||||||
|
if (!permission_check(R_OK, &symlink_inode)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
// char buffer[symlink_inode.metadata.size];
|
||||||
|
// memset(buffer, 0, sizeof(buffer));
|
||||||
|
fs->read(&symlink_inode, buf, symlink_inode.metadata.size, 0);
|
||||||
|
buf[symlink_inode.metadata.size] = 0;
|
||||||
|
// printf("READLINK %d %s\n", symlink_inode.metadata.size, buf);
|
||||||
|
/*u_int64_t fh = namei(buffer);
|
||||||
|
if (fh == -1){
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
INode_Data inode;
|
||||||
|
// Assuming inode is correctly initialized here based on 'path'
|
||||||
|
inode.inode_num = fh;
|
||||||
|
fs->inode_manager->load_inode(&inode);
|
||||||
|
size_t bytes_read = fs->read(&inode, buf, size, 0);
|
||||||
|
printf("READLINK %d %s\n", bytes_read, buf);*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FilesOperation::fischl_symlink(const char *to, const char *from) {
|
||||||
|
// check path
|
||||||
|
// printf("SYMLINK %s %s\n", from, to);
|
||||||
|
char *pathdup = strdup(from);
|
||||||
|
char *lastSlash = strrchr(pathdup, '/');
|
||||||
|
*lastSlash = '\0'; // Split the string into parent path and new directory
|
||||||
|
// name; <parent path>\0<direcotry name>
|
||||||
|
char *newFilename =
|
||||||
|
lastSlash + 1; //\0<direcotry name>, get from <direcotry name>
|
||||||
|
char *ParentPath = pathdup; // pathdup are separated by pathdup, so it take
|
||||||
|
// <parent path> only
|
||||||
|
// fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__,
|
||||||
|
// ParentPath, strlen(ParentPath));
|
||||||
|
FileNode *parent_filenode = strlen(ParentPath)
|
||||||
|
? fischl_load_entry(root_node, ParentPath)
|
||||||
|
: root_node->self_info;
|
||||||
|
if (parent_filenode == NULL) {
|
||||||
|
fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__, __LINE__,
|
||||||
|
ParentPath);
|
||||||
|
free(pathdup);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
u_int64_t parent_inode_number = parent_filenode->inode_number;
|
||||||
|
if (!permission_check_by_inode_num(W_OK, parent_inode_number)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
// make new inode
|
||||||
|
INode_Data *ret =
|
||||||
|
create_new_inode(parent_inode_number, newFilename, S_IFLNK | 0777);
|
||||||
|
if (ret == NULL)
|
||||||
|
return -1; // ENOSPC but create_new_inode handle ENAMETOOLONG EEXIST
|
||||||
|
// make new node in RAM
|
||||||
|
fischl_add_entry(parent_filenode->subdirectory, ret->inode_num, newFilename,
|
||||||
|
ret);
|
||||||
|
size_t size = strlen(to);
|
||||||
|
char *buffer = (char *)malloc(size);
|
||||||
|
memcpy(buffer, to, size);
|
||||||
|
// printf("%d %s\n", size, buffer);
|
||||||
|
size_t bytes_write = fs->write(ret, buffer, size, 0);
|
||||||
|
free(buffer);
|
||||||
|
free(pathdup);
|
||||||
|
fs->inode_manager->save_inode(ret);
|
||||||
|
// printf("%d %d %llu\n", bytes_write, ret->metadata.size, ret->inode_num);
|
||||||
|
return 0; // SUCESS
|
||||||
|
}
|
||||||
|
|
||||||
int FilesOperation::insert_inode_to(u_int64_t parent_inode_number,
|
int FilesOperation::insert_inode_to(u_int64_t parent_inode_number,
|
||||||
const char *name, INode_Data *new_inode) {
|
const char *name, INode_Data *new_inode,
|
||||||
|
bool check_replace) {
|
||||||
// trys to create a file under parent directory
|
// trys to create a file under parent directory
|
||||||
if (strlen(name) >= 256) {
|
if (strlen(name) >= 256) {
|
||||||
perror("Name too long, cannot create file or directory");
|
perror("Name too long, cannot create file or directory");
|
||||||
@ -672,6 +923,7 @@ int FilesOperation::insert_inode_to(u_int64_t parent_inode_number,
|
|||||||
for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
|
for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
|
||||||
ent.deserialize(r_buffer + i);
|
ent.deserialize(r_buffer + i);
|
||||||
if (strcmp(ent.file_name, name) == 0 && ent.inode_number != 0) {
|
if (strcmp(ent.file_name, name) == 0 && ent.inode_number != 0) {
|
||||||
|
if (check_replace) {
|
||||||
if ((new_inode->metadata.permissions & S_IFMT) == S_IFDIR) {
|
if ((new_inode->metadata.permissions & S_IFMT) == S_IFDIR) {
|
||||||
fprintf(stderr, "[%s ,%d] %s/ already exists\n", __func__, __LINE__,
|
fprintf(stderr, "[%s ,%d] %s/ already exists\n", __func__, __LINE__,
|
||||||
name);
|
name);
|
||||||
@ -680,6 +932,13 @@ int FilesOperation::insert_inode_to(u_int64_t parent_inode_number,
|
|||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
} else {
|
||||||
|
// printf("RENAME HAPPENS %s %s\n", );
|
||||||
|
ent.inode_number = new_inode->inode_num;
|
||||||
|
ent.serialize(r_buffer + i);
|
||||||
|
fs->write(&inode, r_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -720,87 +979,218 @@ int FilesOperation::insert_inode_to(u_int64_t parent_inode_number,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: rename dir and rename fail
|
int FilesOperation::fischl_link(const char *from, const char *to) {
|
||||||
int FilesOperation::fischl_rename(const char *path, const char *new_name,
|
|
||||||
unsigned int flags) {
|
FileNode *get_file;
|
||||||
char *pathdup = strdup(path);
|
if ((get_file = fischl_load_entry(root_node, from)) == NULL)
|
||||||
|
return -ENOENT;
|
||||||
|
INode_Data ret;
|
||||||
|
ret.inode_num = get_file->inode_number;
|
||||||
|
fs->inode_manager->load_inode(&ret);
|
||||||
|
|
||||||
|
// check path
|
||||||
|
char *pathdup = strdup(to);
|
||||||
char *lastSlash = strrchr(pathdup, '/');
|
char *lastSlash = strrchr(pathdup, '/');
|
||||||
*lastSlash = '\0';
|
*lastSlash = '\0'; // Split the string into parent path and new directory
|
||||||
char *filename = lastSlash + 1;
|
// name; <parent path>\0<direcotry name>
|
||||||
char *ParentPath = pathdup;
|
char *newFilename =
|
||||||
if (!strcmp(filename, ".") || !strcmp(filename, "..")) {
|
lastSlash + 1; //\0<direcotry name>, get from <direcotry name>
|
||||||
printf("refusing to remove . or ..\n");
|
char *ParentPath = pathdup; // pathdup are separated by pathdup, so it take
|
||||||
return -1;
|
// <parent path> only
|
||||||
}
|
// fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__,
|
||||||
FileNode *parent_filenode = fischl_find_entry(root_node, ParentPath);
|
// ParentPath, strlen(ParentPath));
|
||||||
|
FileNode *parent_filenode = strlen(ParentPath)
|
||||||
|
? fischl_load_entry(root_node, ParentPath)
|
||||||
|
: root_node->self_info;
|
||||||
if (parent_filenode == NULL) {
|
if (parent_filenode == NULL) {
|
||||||
printf("parent %s not found by fischl_find_entry\n", ParentPath);
|
fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__, __LINE__,
|
||||||
|
ParentPath);
|
||||||
free(pathdup);
|
free(pathdup);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u_int64_t parent_inode_number = parent_filenode->inode_number;
|
u_int64_t parent_inode_number = parent_filenode->inode_number;
|
||||||
u_int64_t target_inode = 0;
|
if (!permission_check_by_inode_num(W_OK, parent_inode_number)) {
|
||||||
|
return -EACCES;
|
||||||
// remove its record from parent
|
|
||||||
INode_Data parent_INode;
|
|
||||||
parent_INode.inode_num = parent_inode_number;
|
|
||||||
fs->inode_manager->load_inode(&parent_INode);
|
|
||||||
char rw_buffer[IO_BLOCK_SIZE] = {0};
|
|
||||||
for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE;
|
|
||||||
idx++) {
|
|
||||||
fs->read(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
|
|
||||||
DirectoryEntry ent;
|
|
||||||
for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
|
|
||||||
ent.deserialize(rw_buffer + i);
|
|
||||||
if (strcmp(ent.file_name, filename) == 0) {
|
|
||||||
target_inode = ent.inode_number;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
if (insert_inode_to(parent_inode_number, newFilename, &ret, true) < 0) {
|
||||||
if (target_inode) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove inode itself
|
|
||||||
if (target_inode) {
|
|
||||||
INode_Data ret;
|
|
||||||
ret.inode_num = target_inode;
|
|
||||||
fs->inode_manager->load_inode(&ret);
|
|
||||||
|
|
||||||
if (flags == RENAME_EXCHANGE) {
|
|
||||||
printf("RENAME_EXCHANGE ");
|
|
||||||
} else if (flags == RENAME_NOREPLACE) {
|
|
||||||
printf("RENAME_NOREPLACE ");
|
|
||||||
} else
|
|
||||||
printf("ELSE ");
|
|
||||||
|
|
||||||
printf("FOUND INODE AT %llu %s\n", target_inode, new_name);
|
|
||||||
char *pathdup2 = strdup(new_name);
|
|
||||||
char *lastSlash2 = strrchr(pathdup2, '/');
|
|
||||||
*lastSlash2 = '\0'; // Split the string into parent path and new directory
|
|
||||||
// name; <parent path>\0<direcotry name>
|
|
||||||
char *newDirname2 =
|
|
||||||
lastSlash2 + 1; //\0<direcotry name>, get from <direcotry name>
|
|
||||||
char *ParentPath2 = pathdup2; // pathdup are separated by pathdup, so it
|
|
||||||
// take <parent path> only
|
|
||||||
|
|
||||||
FileNode *parent_filenode2 = strlen(ParentPath)
|
|
||||||
? fischl_find_entry(root_node, ParentPath2)
|
|
||||||
: root_node->self_info;
|
|
||||||
if (parent_filenode2 == NULL) {
|
|
||||||
fprintf(stderr, "[%s ,%d] ParentPath:{%s} not found\n", __func__,
|
|
||||||
__LINE__, ParentPath2);
|
|
||||||
free(pathdup2);
|
|
||||||
return -ENOENT; // parentpath directory does not exist
|
|
||||||
}
|
|
||||||
u_int64_t parent_inode_number2 = parent_filenode2->inode_number;
|
|
||||||
// printf("%s, %llu, %s\n", parent_filenode->name, parent_inode_number,
|
|
||||||
// newDirname); make new inode
|
|
||||||
if (insert_inode_to(parent_inode_number2, newDirname2, &ret) < 0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret.metadata.reference_count += 1;
|
||||||
|
fs->inode_manager->save_inode(&ret);
|
||||||
|
fischl_add_entry(parent_filenode->subdirectory, ret.inode_num, newFilename,
|
||||||
|
&ret);
|
||||||
|
free(pathdup);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: rename dir and rename fail
|
||||||
|
int FilesOperation::fischl_rename(const char *old_path, const char *new_path,
|
||||||
|
unsigned int flags) {
|
||||||
|
// find old path
|
||||||
|
char *pathdup = strdup(old_path);
|
||||||
|
char *lastSlash = strrchr(pathdup, '/');
|
||||||
|
*lastSlash = '\0';
|
||||||
|
char *filename = lastSlash + 1;
|
||||||
|
char *oldParentPath = pathdup;
|
||||||
|
if (!strcmp(filename, ".") || !strcmp(filename, "..")) {
|
||||||
|
printf("refuse to remove . or ..\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// put old path info in rename struct
|
||||||
|
RenameInfo rename_info;
|
||||||
|
rename_info.exchangeExist = false;
|
||||||
|
rename_info.oldParentNode = fischl_load_entry(root_node, oldParentPath);
|
||||||
|
// if path end with / means to rename directory
|
||||||
|
rename_info.oldFileNode =
|
||||||
|
strlen(filename)
|
||||||
|
? fischl_load_entry(rename_info.oldParentNode->subdirectory, filename)
|
||||||
|
: rename_info.oldParentNode;
|
||||||
|
|
||||||
|
if (rename_info.oldFileNode == NULL) {
|
||||||
|
fprintf(stderr, "[%s ,%d] path %s not found by fischl_load_entry\n",
|
||||||
|
__func__, __LINE__, old_path);
|
||||||
|
free(pathdup);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find new path
|
||||||
|
char *new_pathdup = strdup(new_path);
|
||||||
|
lastSlash = strrchr(new_pathdup, '/');
|
||||||
|
*lastSlash = '\0'; // Split the string into parent path and new directory
|
||||||
|
// name; <parent path>\0<direcotry name>
|
||||||
|
char *newParentPath = new_pathdup; // pathdup are separated by pathdup, so it
|
||||||
|
// take <parent path> only
|
||||||
|
// put new path info in rename struct
|
||||||
|
rename_info.newName =
|
||||||
|
lastSlash + 1; //\0<direcotry name>, get from <direcotry name>
|
||||||
|
rename_info.newFileNode = fischl_load_entry(root_node, new_path);
|
||||||
|
rename_info.newParentNode = strlen(newParentPath)
|
||||||
|
? fischl_load_entry(root_node, newParentPath)
|
||||||
|
: root_node->self_info;
|
||||||
|
|
||||||
|
if (!permission_check_by_inode_num(W_OK,
|
||||||
|
rename_info.oldParentNode->inode_number)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
if (!permission_check_by_inode_num(W_OK,
|
||||||
|
rename_info.newParentNode->inode_number)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
if (!permission_check_by_inode_num(W_OK,
|
||||||
|
rename_info.oldFileNode->inode_number)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
if (rename_info.newFileNode != NULL &&
|
||||||
|
!permission_check_by_inode_num(W_OK,
|
||||||
|
rename_info.newFileNode->inode_number)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure with flag
|
||||||
|
if (flags & RENAME_NOREPLACE) {
|
||||||
|
// Check if newpath exists and return error if it does
|
||||||
|
if (rename_info.newFileNode != NULL) {
|
||||||
|
fprintf(stderr, "[%s ,%d] newpath has already existed\n", __func__,
|
||||||
|
__LINE__);
|
||||||
|
free(new_pathdup); // new path
|
||||||
|
free(pathdup); // old path
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & RENAME_EXCHANGE) {
|
||||||
|
// Ensure both oldpath and newpath exist and exchange them atomically
|
||||||
|
if (rename_info.newFileNode == NULL) {
|
||||||
|
fprintf(stderr, "[%s ,%d] newpath does not exist cannot exchange\n",
|
||||||
|
__func__, __LINE__);
|
||||||
|
free(new_pathdup);
|
||||||
|
free(pathdup);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rename_info.exchangeExist = true;
|
||||||
|
INode_Data parent_INode;
|
||||||
|
parent_INode.inode_num = rename_info.newParentNode->inode_number;
|
||||||
|
fs->inode_manager->load_inode(&parent_INode);
|
||||||
|
char rw_buffer[IO_BLOCK_SIZE] = {0};
|
||||||
|
|
||||||
|
bool change_flag = false;
|
||||||
|
// delete record on old path
|
||||||
|
for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE;
|
||||||
|
idx++) {
|
||||||
|
fs->read(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
|
||||||
|
DirectoryEntry ent;
|
||||||
|
for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
|
||||||
|
ent.deserialize(rw_buffer + i);
|
||||||
|
if (ent.inode_number == rename_info.newFileNode->inode_number) {
|
||||||
|
change_flag = true; // should be change
|
||||||
|
strncpy(ent.file_name, filename, sizeof(ent.file_name) - 1);
|
||||||
|
ent.file_name[sizeof(ent.file_name) - 1] = '\0';
|
||||||
|
ent.serialize(rw_buffer + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (change_flag) {
|
||||||
|
fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
|
||||||
|
change_flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parent_INode.inode_num = rename_info.oldParentNode->inode_number;
|
||||||
|
fs->inode_manager->load_inode(&parent_INode);
|
||||||
|
|
||||||
|
change_flag = false;
|
||||||
|
// delete record on old path
|
||||||
|
for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE;
|
||||||
|
idx++) {
|
||||||
|
fs->read(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
|
||||||
|
DirectoryEntry ent;
|
||||||
|
for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
|
||||||
|
ent.deserialize(rw_buffer + i);
|
||||||
|
if (ent.inode_number == rename_info.oldFileNode->inode_number) {
|
||||||
|
change_flag = true; // should be change
|
||||||
|
strncpy(ent.file_name, rename_info.newName,
|
||||||
|
sizeof(ent.file_name) - 1);
|
||||||
|
ent.file_name[sizeof(ent.file_name) - 1] = '\0';
|
||||||
|
ent.serialize(rw_buffer + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (change_flag) {
|
||||||
|
fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
|
||||||
|
change_flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unlink_inode(rename_info.oldFileNode->inode_number);
|
||||||
|
fischl_rm_entry(rename_info.oldParentNode->subdirectory, filename);
|
||||||
|
fischl_rm_entry(rename_info.newParentNode->subdirectory,
|
||||||
|
rename_info.newName);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal rename logic if no flags are specified; can overwirte
|
||||||
|
// Hard Disk rename
|
||||||
|
if (rename_info.oldFileNode->subdirectory != NULL) { // secure its directory
|
||||||
|
// remove its record from subdirectory; find .. from subdirectory
|
||||||
|
}
|
||||||
|
// remove its record from parent
|
||||||
|
INode_Data parent_INode;
|
||||||
|
parent_INode.inode_num = rename_info.oldParentNode->inode_number;
|
||||||
|
fs->inode_manager->load_inode(&parent_INode);
|
||||||
|
char rw_buffer[IO_BLOCK_SIZE] = {0};
|
||||||
|
|
||||||
|
// relocate the old path file to new path
|
||||||
|
INode_Data ret;
|
||||||
|
ret.inode_num = rename_info.oldFileNode->inode_number;
|
||||||
|
fs->inode_manager->load_inode(&ret);
|
||||||
|
if (insert_inode_to(rename_info.newParentNode->inode_number,
|
||||||
|
rename_info.newName, &ret, false) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bool change_flag = false;
|
||||||
|
// delete record on old path
|
||||||
for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE;
|
for (u_int64_t idx = 0; idx < parent_INode.metadata.size / IO_BLOCK_SIZE;
|
||||||
idx++) {
|
idx++) {
|
||||||
fs->read(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
|
fs->read(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
|
||||||
@ -808,31 +1198,29 @@ int FilesOperation::fischl_rename(const char *path, const char *new_name,
|
|||||||
for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
|
for (int i = 0; i <= IO_BLOCK_SIZE - 264; i += 264) {
|
||||||
ent.deserialize(rw_buffer + i);
|
ent.deserialize(rw_buffer + i);
|
||||||
if (strcmp(ent.file_name, filename) == 0) {
|
if (strcmp(ent.file_name, filename) == 0) {
|
||||||
target_inode = ent.inode_number;
|
change_flag = true; // should be change
|
||||||
ent.inode_number = 0;
|
ent.inode_number = 0;
|
||||||
memset(ent.file_name, 0, sizeof(ent.file_name));
|
memset(ent.file_name, 0, sizeof(ent.file_name));
|
||||||
ent.serialize(rw_buffer + i);
|
ent.serialize(rw_buffer + i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (target_inode) {
|
if (change_flag) {
|
||||||
fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
|
fs->write(&parent_INode, rw_buffer, IO_BLOCK_SIZE, idx * IO_BLOCK_SIZE);
|
||||||
|
change_flag = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rename_info.newParentNode != NULL) {
|
||||||
fischl_rm_entry(parent_filenode->subdirectory, filename);
|
fischl_rm_entry(rename_info.newParentNode->subdirectory,
|
||||||
fischl_add_entry(parent_filenode2->subdirectory, ret.inode_num, newDirname2,
|
rename_info.newName);
|
||||||
&ret);
|
|
||||||
free(pathdup);
|
|
||||||
// remove node itself and from parent hash
|
|
||||||
free(pathdup2);
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
printf("cannot find %s in %s", filename, ParentPath);
|
|
||||||
free(pathdup);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
fischl_rm_entry(rename_info.oldParentNode->subdirectory, filename);
|
||||||
|
|
||||||
|
// free path
|
||||||
|
free(pathdup);
|
||||||
|
free(new_pathdup);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FilesOperation::fischl_truncate(const char *path, off_t offset,
|
int FilesOperation::fischl_truncate(const char *path, off_t offset,
|
||||||
@ -848,8 +1236,13 @@ int FilesOperation::fischl_truncate(const char *path, off_t offset,
|
|||||||
INode_Data inode;
|
INode_Data inode;
|
||||||
inode.inode_num = fh;
|
inode.inode_num = fh;
|
||||||
fs->inode_manager->load_inode(&inode);
|
fs->inode_manager->load_inode(&inode);
|
||||||
|
if (!permission_check(W_OK, &inode)) {
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
res = fs->truncate(&inode, offset);
|
res = fs->truncate(&inode, offset);
|
||||||
fs->inode_manager->save_inode(&inode);
|
fs->inode_manager->save_inode(&inode);
|
||||||
|
if (res < 0)
|
||||||
|
return -errno;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -872,7 +1265,12 @@ int FilesOperation::fischl_read(const char *path, char *buf, size_t size,
|
|||||||
// Assuming inode is correctly initialized here based on 'path'
|
// Assuming inode is correctly initialized here based on 'path'
|
||||||
inode.inode_num = fi->fh;
|
inode.inode_num = fi->fh;
|
||||||
fs->inode_manager->load_inode(&inode);
|
fs->inode_manager->load_inode(&inode);
|
||||||
size_t bytes_read = fs->read(&inode, buf, size, offset);
|
// printf("OUT READ %llu %llu %llu\n", inode.inode_num,
|
||||||
|
// inode.single_indirect_block, inode.double_indirect_block);
|
||||||
|
ssize_t bytes_read = fs->read(&inode, buf, size, offset);
|
||||||
|
// printf("BYTES_READ %d\n",int(bytes_read));
|
||||||
|
// for (int i = 0; i < bytes_read; i++)printf("%x", buf[i]&0xff);
|
||||||
|
// printf("\n");
|
||||||
/*size_t len = (inode.metadata.size/IO_BLOCK_SIZE) * IO_BLOCK_SIZE; //
|
/*size_t len = (inode.metadata.size/IO_BLOCK_SIZE) * IO_BLOCK_SIZE; //
|
||||||
Assuming each block is 4096 bytes
|
Assuming each block is 4096 bytes
|
||||||
|
|
||||||
@ -897,5 +1295,39 @@ int FilesOperation::fischl_read(const char *path, char *buf, size_t size,
|
|||||||
// Only the first block might have a non-zero offset
|
// Only the first block might have a non-zero offset
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
if (bytes_read < 0)
|
||||||
|
return -errno;
|
||||||
return bytes_read; // Return the actual number of bytes read
|
return bytes_read; // Return the actual number of bytes read
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FilesOperation::fischl_utimens(const char *path,
|
||||||
|
const struct timespec tv[2],
|
||||||
|
struct fuse_file_info *fi) {
|
||||||
|
(void)fi;
|
||||||
|
int res = 0;
|
||||||
|
u_int64_t fh = namei(path);
|
||||||
|
|
||||||
|
if (fh == -1) {
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
INode_Data inode;
|
||||||
|
inode.inode_num = fh;
|
||||||
|
fs->inode_manager->load_inode(&inode);
|
||||||
|
inode.metadata.access_time =
|
||||||
|
(u_int64_t)tv[0].tv_sec * 1000000000ULL + tv[0].tv_nsec;
|
||||||
|
inode.metadata.modification_time =
|
||||||
|
(u_int64_t)tv[1].tv_sec * 1000000000ULL + tv[1].tv_nsec;
|
||||||
|
fs->inode_manager->save_inode(&inode);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FilesOperation::fischl_statfs(const char *path, struct statvfs *stbuf) {
|
||||||
|
stbuf->f_bsize = 4096;
|
||||||
|
stbuf->f_blocks = 0;
|
||||||
|
stbuf->f_bfree = 0;
|
||||||
|
stbuf->f_files = 0;
|
||||||
|
stbuf->f_ffree = 0;
|
||||||
|
stbuf->f_namemax = 256;
|
||||||
|
return 0;
|
||||||
|
}
|
129
lib/fischl.cpp
129
lib/fischl.cpp
@ -22,6 +22,7 @@ static struct options {
|
|||||||
Fs *fs;
|
Fs *fs;
|
||||||
FilesOperation *fsop;
|
FilesOperation *fsop;
|
||||||
int show_help;
|
int show_help;
|
||||||
|
bool load;
|
||||||
} options;
|
} options;
|
||||||
|
|
||||||
#define OPTION(t, p) \
|
#define OPTION(t, p) \
|
||||||
@ -33,7 +34,9 @@ static const struct fuse_opt option_spec[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void* fischl_init(struct fuse_conn_info *conn, struct fuse_config *cfg) {
|
void* fischl_init(struct fuse_conn_info *conn, struct fuse_config *cfg) {
|
||||||
options.fsop->initialize_rootinode();
|
cfg->use_ino = 1;
|
||||||
|
conn->want &= ~FUSE_CAP_ATOMIC_O_TRUNC;
|
||||||
|
options.fsop->initialize(options.load);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fischl_create(const char *path, mode_t mode, struct fuse_file_info *fi) {
|
int fischl_create(const char *path, mode_t mode, struct fuse_file_info *fi) {
|
||||||
@ -50,19 +53,15 @@ static int fischl_getattr(const char *path, struct stat *stbuf, struct fuse_file
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int fischl_access(const char* path, int mask) {
|
static int fischl_access(const char* path, int mask) {
|
||||||
|
return options.fsop->fischl_access(path, mask);
|
||||||
// return 0 when access is allowed
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fischl_readlink(const char* path, char* buf, size_t size) {
|
static int fischl_readlink(const char* path, char* buf, size_t size) {
|
||||||
return -1;
|
return options.fsop->fischl_readlink(path, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fischl_opendir(const char* path, struct fuse_file_info* fi) {
|
static int fischl_opendir(const char* path, struct fuse_file_info* fi) {
|
||||||
u_int64_t fh = options.fsop->namei(path);
|
return options.fsop->fischl_opendir(path, fi);
|
||||||
fi->fh = fh;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fischl_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t ft, struct fuse_file_info *fi, enum fuse_readdir_flags flg) {
|
static int fischl_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t ft, struct fuse_file_info *fi, enum fuse_readdir_flags flg) {
|
||||||
@ -85,8 +84,8 @@ static int fischl_rmdir(const char* path) {
|
|||||||
return options.fsop->fischl_rmdir(path);
|
return options.fsop->fischl_rmdir(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fischl_symlink(const char* to, const char* from) {
|
static int fischl_symlink(const char* from, const char* to) {
|
||||||
return -1;
|
return options.fsop->fischl_symlink(from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fischl_rename(const char *path, const char *new_name, unsigned int flags) {
|
static int fischl_rename(const char *path, const char *new_name, unsigned int flags) {
|
||||||
@ -94,7 +93,7 @@ static int fischl_rename(const char *path, const char *new_name, unsigned int fl
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int fischl_link(const char* from, const char* to) {
|
static int fischl_link(const char* from, const char* to) {
|
||||||
return -1;
|
return options.fsop->fischl_link(from, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fischl_chmod(const char *path, mode_t mode, struct fuse_file_info *fi) {
|
static int fischl_chmod(const char *path, mode_t mode, struct fuse_file_info *fi) {
|
||||||
@ -110,7 +109,7 @@ static int fischl_truncate(const char *path, off_t offset, struct fuse_file_info
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int fischl_utimens(const char *path, const struct timespec tv[2], struct fuse_file_info *fi) {
|
static int fischl_utimens(const char *path, const struct timespec tv[2], struct fuse_file_info *fi) {
|
||||||
return -1;
|
return options.fsop->fischl_utimens(path, tv, fi);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fischl_open(const char *path, struct fuse_file_info *fi) {
|
static int fischl_open(const char *path, struct fuse_file_info *fi) {
|
||||||
@ -126,7 +125,7 @@ static int fischl_write(const char *path, const char *buf, size_t size, off_t of
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int fischl_statfs(const char* path, struct statvfs* stbuf) {
|
static int fischl_statfs(const char* path, struct statvfs* stbuf) {
|
||||||
return -1;
|
return options.fsop->fischl_statfs(path, stbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fischl_release(const char* path, struct fuse_file_info *fi) {
|
static int fischl_release(const char* path, struct fuse_file_info *fi) {
|
||||||
@ -142,21 +141,21 @@ static const struct fuse_operations fischl_oper = {
|
|||||||
|
|
||||||
|
|
||||||
.getattr = fischl_getattr,
|
.getattr = fischl_getattr,
|
||||||
//.readlink = fischl_readlink,
|
.readlink = fischl_readlink,
|
||||||
.mknod = fischl_mknod,
|
.mknod = fischl_mknod,
|
||||||
.mkdir = fischl_mkdir,
|
.mkdir = fischl_mkdir,
|
||||||
.unlink = fischl_unlink,
|
.unlink = fischl_unlink,
|
||||||
.rmdir = fischl_rmdir,
|
.rmdir = fischl_rmdir,
|
||||||
//.symlink = fischl_symlink,
|
.symlink = fischl_symlink,
|
||||||
.rename = fischl_rename,
|
.rename = fischl_rename,
|
||||||
//.link = fischl_link,
|
.link = fischl_link,
|
||||||
.chmod = fischl_chmod,
|
.chmod = fischl_chmod,
|
||||||
.chown = fischl_chown,
|
.chown = fischl_chown,
|
||||||
.truncate = fischl_truncate,
|
.truncate = fischl_truncate,
|
||||||
.open = fischl_open,
|
.open = fischl_open,
|
||||||
.read = fischl_read,
|
.read = fischl_read,
|
||||||
.write = fischl_write,
|
.write = fischl_write,
|
||||||
//.statfs = fischl_statfs,
|
.statfs = fischl_statfs,
|
||||||
.release = fischl_release,
|
.release = fischl_release,
|
||||||
/*
|
/*
|
||||||
#ifdef HAVE_SETXATTR
|
#ifdef HAVE_SETXATTR
|
||||||
@ -173,7 +172,7 @@ static const struct fuse_operations fischl_oper = {
|
|||||||
.destroy = fischl_destroy,
|
.destroy = fischl_destroy,
|
||||||
.access = fischl_access,
|
.access = fischl_access,
|
||||||
.create = fischl_create,
|
.create = fischl_create,
|
||||||
//.utimens = fischl_utimens,
|
.utimens = fischl_utimens,
|
||||||
//.bmap = fischl_bmap,
|
//.bmap = fischl_bmap,
|
||||||
//.ioctl = fischl_ioctl,
|
//.ioctl = fischl_ioctl,
|
||||||
//.poll = fischl_poll,
|
//.poll = fischl_poll,
|
||||||
@ -194,16 +193,104 @@ static void show_help(const char *progname)
|
|||||||
int fischl(int argc, char *argv[])
|
int fischl(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
if(argc < 3){
|
||||||
|
printf("WRONG ARGUMENTS\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
std::swap(argv[0], argv[1]);
|
||||||
|
std::swap(argv[1], argv[2]);
|
||||||
|
|
||||||
|
struct fuse_args args = FUSE_ARGS_INIT(argc-2, argv+2);
|
||||||
srand(time(NULL)); // Seed the random number generator
|
srand(time(NULL)); // Seed the random number generator
|
||||||
//const char* d = (argc < 2) ? "/dev/vdc" : argv[1];
|
//const char* d = (argc < 2) ? "/dev/vdc" : argv[1];
|
||||||
|
|
||||||
//setupTestDirectory(&options.root);
|
//setupTestDirectory(&options.root);
|
||||||
options.H = new FakeRawDisk(23552);
|
if(strcmp(argv[0], "fake")==0){
|
||||||
|
options.H = new FakeRawDisk(27648);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
options.H = new RealRawDisk(argv[0]);
|
||||||
|
char zero_es[IO_BLOCK_SIZE] = {0};
|
||||||
|
/*printf("zeroed\n");
|
||||||
|
for (int i = 0; i < 200000; i++){
|
||||||
|
options.H->write_block(i, zero_es);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
if(strcmp(argv[1], "l")==0){
|
||||||
|
options.load = true;
|
||||||
|
}
|
||||||
|
else if(strcmp(argv[1], "n")==0){
|
||||||
|
options.load = false;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
printf("WRONG l/n ARGUMENTS\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
options.fs = new Fs(options.H);
|
options.fs = new Fs(options.H);
|
||||||
options.fs->format();
|
if(!options.load){
|
||||||
|
printf("FORMAT %d\n", options.fs->format());
|
||||||
|
}
|
||||||
options.fsop = new FilesOperation(*options.H, options.fs);
|
options.fsop = new FilesOperation(*options.H, options.fs);
|
||||||
|
|
||||||
|
/*INode_Data inode_data;
|
||||||
|
options.fs->inode_manager->new_inode(1, 2, 3, &inode_data);
|
||||||
|
|
||||||
|
int buf_size = 100000;
|
||||||
|
int seg_size = 10;
|
||||||
|
char buf[buf_size];
|
||||||
|
|
||||||
|
int res;
|
||||||
|
int num = 1;
|
||||||
|
|
||||||
|
for (u_int64_t i = 0; i < 30 * 1024 * 1024;) {
|
||||||
|
for (int j = 0; j < buf_size;) {
|
||||||
|
j += sprintf(&buf[j], "%010d\n", ++num);
|
||||||
|
}
|
||||||
|
res = options.fs->write(&inode_data, buf, buf_size, i);
|
||||||
|
if (res < buf_size)
|
||||||
|
printf("ERR: %d %d\n", res, i);
|
||||||
|
i += res;
|
||||||
|
}
|
||||||
|
|
||||||
|
num = 1;
|
||||||
|
|
||||||
|
printf("done write\n");
|
||||||
|
char buf2[buf_size];
|
||||||
|
|
||||||
|
for (u_int64_t i = 0; i < 30 * 1024 * 1024;) {
|
||||||
|
for (int j = 0; j < buf_size;) {
|
||||||
|
j += sprintf(&buf[j], "%010d\n", ++num);
|
||||||
|
}
|
||||||
|
res = options.fs->read(&inode_data, buf2, buf_size, i);
|
||||||
|
if (res < buf_size)
|
||||||
|
printf("ERR2: %d %d\n", res, i);
|
||||||
|
i += res;
|
||||||
|
for (int j = 0; j < res; ++j) {
|
||||||
|
if (buf[j] != buf2[j])
|
||||||
|
printf("err err err: %d %d", buf[j], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("done read\n");
|
||||||
|
|
||||||
|
num = 1;
|
||||||
|
|
||||||
|
for (u_int64_t i = 0; i < 30 * 1024 * 1024;) {
|
||||||
|
for (int j = 0; j < buf_size;) {
|
||||||
|
j += sprintf(&buf[j], "%010d\n", ++num);
|
||||||
|
}
|
||||||
|
res = options.fs->read(&inode_data, buf2, buf_size, i);
|
||||||
|
if (res < buf_size)
|
||||||
|
printf("ERR2: %d %d\n", res, i);
|
||||||
|
i += res;
|
||||||
|
for (int j = 0; j < res; ++j) {
|
||||||
|
if (buf[j] != buf2[j])
|
||||||
|
printf("err err err: %d %d", buf[j], i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("done read2\n");*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Parse options */
|
/* Parse options */
|
||||||
|
@ -52,8 +52,10 @@ int DataBlock_Manager_Bitmap::new_datablock(u_int64_t *block_num) {
|
|||||||
char zero_buf[IO_BLOCK_SIZE] = {0};
|
char zero_buf[IO_BLOCK_SIZE] = {0};
|
||||||
|
|
||||||
if (bitmap_block_num < block_segment_start ||
|
if (bitmap_block_num < block_segment_start ||
|
||||||
bitmap_block_num >= block_segment_end)
|
bitmap_block_num >= block_segment_end) {
|
||||||
|
perror("Error with new_datablock freelist head\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0)
|
if ((err = fs->disk->read_block(bitmap_block_num, bitmap.buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
@ -64,8 +66,10 @@ int DataBlock_Manager_Bitmap::new_datablock(u_int64_t *block_num) {
|
|||||||
|
|
||||||
u_int64_t relative_block_num = bitmap.claim_relative_block();
|
u_int64_t relative_block_num = bitmap.claim_relative_block();
|
||||||
|
|
||||||
if (relative_block_num == 0)
|
if (relative_block_num == 0) {
|
||||||
|
errno = ENOSPC;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
u_int64_t block_num_ = relative_block_num + bitmap_block_num;
|
u_int64_t block_num_ = relative_block_num + bitmap_block_num;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "fs.hpp"
|
#include "fs.hpp"
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
template <typename T> T write_int(T num, char buf[]) {
|
template <typename T> T write_int(T num, char buf[]) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
@ -50,11 +51,15 @@ void SuperBlock_Data::deserialize(char buf[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
INode_Data::INode_Data(u_int64_t inode_num) : inode_num(inode_num) {
|
INode_Data::INode_Data(u_int64_t inode_num) : inode_num(inode_num) {
|
||||||
|
struct timespec ts;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
metadata.uid = -1;
|
metadata.uid = -1;
|
||||||
metadata.gid = -1;
|
metadata.gid = -1;
|
||||||
metadata.permissions = -1;
|
metadata.permissions = -1;
|
||||||
metadata.size = 0;
|
metadata.size = 0;
|
||||||
metadata.reference_count = 0;
|
metadata.access_time = (u_int64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec;
|
||||||
|
metadata.modification_time = (u_int64_t)ts.tv_sec * 1000000000ULL + ts.tv_nsec;
|
||||||
|
metadata.reference_count = 1;
|
||||||
|
|
||||||
single_indirect_block = double_indirect_block = triple_indirect_block = 0;
|
single_indirect_block = double_indirect_block = triple_indirect_block = 0;
|
||||||
|
|
||||||
@ -68,6 +73,8 @@ size_t INode_Data::serialize_metadata(char buf[]) {
|
|||||||
i += write_u64(metadata.gid, &buf[i]);
|
i += write_u64(metadata.gid, &buf[i]);
|
||||||
i += write_u64(metadata.permissions, &buf[i]);
|
i += write_u64(metadata.permissions, &buf[i]);
|
||||||
i += write_u64(metadata.size, &buf[i]);
|
i += write_u64(metadata.size, &buf[i]);
|
||||||
|
i += write_u64(metadata.access_time, &buf[i]);
|
||||||
|
i += write_u64(metadata.modification_time, &buf[i]);
|
||||||
i += write_u32(metadata.reference_count, &buf[i]);
|
i += write_u32(metadata.reference_count, &buf[i]);
|
||||||
i += write_u32(metadata.flags, &buf[i]);
|
i += write_u32(metadata.flags, &buf[i]);
|
||||||
return i;
|
return i;
|
||||||
@ -79,6 +86,8 @@ size_t INode_Data::deserialize_metadata(char buf[]) {
|
|||||||
i += read_u64(&metadata.gid, &buf[i]);
|
i += read_u64(&metadata.gid, &buf[i]);
|
||||||
i += read_u64(&metadata.permissions, &buf[i]);
|
i += read_u64(&metadata.permissions, &buf[i]);
|
||||||
i += read_u64(&metadata.size, &buf[i]);
|
i += read_u64(&metadata.size, &buf[i]);
|
||||||
|
i += read_u64(&metadata.access_time, &buf[i]);
|
||||||
|
i += read_u64(&metadata.modification_time, &buf[i]);
|
||||||
i += read_u32(&metadata.reference_count, &buf[i]);
|
i += read_u32(&metadata.reference_count, &buf[i]);
|
||||||
i += read_u32(&metadata.flags, &buf[i]);
|
i += read_u32(&metadata.flags, &buf[i]);
|
||||||
return i;
|
return i;
|
||||||
|
@ -31,6 +31,9 @@ int Fs::sweep_inode_datablocks(INode_Data *inode_data,
|
|||||||
DatablockOperation *op) {
|
DatablockOperation *op) {
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
|
// printf("SWEEP %llu %llu %llu\n", inode_data->inode_num,
|
||||||
|
// inode_data->single_indirect_block, inode_data->double_indirect_block);
|
||||||
|
|
||||||
u_int64_t start_index = start_block_index;
|
u_int64_t start_index = start_block_index;
|
||||||
for (size_t i = start_index; i < NUMBER_OF_DIRECT_BLOCKS; ++i) {
|
for (size_t i = start_index; i < NUMBER_OF_DIRECT_BLOCKS; ++i) {
|
||||||
if ((result = sweep_datablocks(&(inode_data->direct_blocks[i]), 0, 0,
|
if ((result = sweep_datablocks(&(inode_data->direct_blocks[i]), 0, 0,
|
||||||
@ -94,6 +97,9 @@ int Fs::sweep_datablocks(u_int64_t *block_num, int indirect_num,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if((*block_num)>30000000000000LL)printf("DIES 1 %llu %d %llu\n",
|
||||||
|
// *block_num, indirect_num, start_block_index);
|
||||||
|
|
||||||
if (indirect_num == 0) {
|
if (indirect_num == 0) {
|
||||||
bool delete_block = false;
|
bool delete_block = false;
|
||||||
if ((result = op->operation(*block_num, &delete_block)) < 0)
|
if ((result = op->operation(*block_num, &delete_block)) < 0)
|
||||||
@ -109,6 +115,7 @@ int Fs::sweep_datablocks(u_int64_t *block_num, int indirect_num,
|
|||||||
if ((*block_num) == 0) {
|
if ((*block_num) == 0) {
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if ((err = disk->read_block(*block_num, buf)) < 0)
|
if ((err = disk->read_block(*block_num, buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -170,6 +177,8 @@ public:
|
|||||||
std::min(IO_BLOCK_SIZE - offset, count - bytes_completed);
|
std::min(IO_BLOCK_SIZE - offset, count - bytes_completed);
|
||||||
|
|
||||||
if (block_num != 0) {
|
if (block_num != 0) {
|
||||||
|
if ((block_num) > 3000000000000LL)
|
||||||
|
printf("DIES 2\n");
|
||||||
if ((err = fs->disk->read_block(block_num, datablock_buf)) < 0)
|
if ((err = fs->disk->read_block(block_num, datablock_buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -198,9 +207,12 @@ public:
|
|||||||
size_t write_size =
|
size_t write_size =
|
||||||
std::min(IO_BLOCK_SIZE - offset, count - bytes_completed);
|
std::min(IO_BLOCK_SIZE - offset, count - bytes_completed);
|
||||||
|
|
||||||
if (write_size < IO_BLOCK_SIZE)
|
if (write_size < IO_BLOCK_SIZE) {
|
||||||
|
if ((block_num) > 3000000000000LL)
|
||||||
|
printf("DIES 3\n");
|
||||||
if ((err = fs->disk->read_block(block_num, datablock_buf)) < 0)
|
if ((err = fs->disk->read_block(block_num, datablock_buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(&datablock_buf[offset], &buf[bytes_completed], write_size);
|
memcpy(&datablock_buf[offset], &buf[bytes_completed], write_size);
|
||||||
|
|
||||||
@ -227,7 +239,8 @@ public:
|
|||||||
(*delete_block) = true;
|
(*delete_block) = true;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if ((block_num) > 3000000000000LL)
|
||||||
|
printf("DIES 4\n");
|
||||||
if ((err = fs->disk->read_block(block_num, datablock_buf)) < 0)
|
if ((err = fs->disk->read_block(block_num, datablock_buf)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -281,8 +294,10 @@ ssize_t Fs::read(INode_Data *inode_data, char buf[], size_t count,
|
|||||||
op.bytes_completed = 0;
|
op.bytes_completed = 0;
|
||||||
op.fs = this;
|
op.fs = this;
|
||||||
|
|
||||||
|
// printf("IN READ %llu %llu %llu\n", inode_data->inode_num,
|
||||||
|
// inode_data->single_indirect_block, inode_data->double_indirect_block);
|
||||||
if ((err = sweep_inode_datablocks(inode_data, start_block_index, false,
|
if ((err = sweep_inode_datablocks(inode_data, start_block_index, false,
|
||||||
&op)) != 0)
|
&op)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return op.bytes_completed;
|
return op.bytes_completed;
|
||||||
@ -292,6 +307,11 @@ ssize_t Fs::write(INode_Data *inode_data, const char buf[], size_t count,
|
|||||||
size_t offset) {
|
size_t offset) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (count + offset > FILE_SIZE_MAX) {
|
||||||
|
errno = EFBIG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
u_int64_t start_block_index = offset / IO_BLOCK_SIZE;
|
u_int64_t start_block_index = offset / IO_BLOCK_SIZE;
|
||||||
size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE);
|
size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE);
|
||||||
|
|
||||||
@ -302,8 +322,8 @@ ssize_t Fs::write(INode_Data *inode_data, const char buf[], size_t count,
|
|||||||
op.bytes_completed = 0;
|
op.bytes_completed = 0;
|
||||||
op.fs = this;
|
op.fs = this;
|
||||||
|
|
||||||
if ((err = sweep_inode_datablocks(inode_data, start_block_index, true,
|
if ((err = sweep_inode_datablocks(inode_data, start_block_index, true, &op)) <
|
||||||
&op)) != 0)
|
0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
inode_data->metadata.size =
|
inode_data->metadata.size =
|
||||||
@ -312,9 +332,19 @@ ssize_t Fs::write(INode_Data *inode_data, const char buf[], size_t count,
|
|||||||
return op.bytes_completed;
|
return op.bytes_completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Fs::truncate(INode_Data *inode_data, size_t length) {
|
int Fs::truncate(INode_Data *inode_data, off_t length) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (length > FILE_SIZE_MAX) {
|
||||||
|
errno = EFBIG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length < 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
u_int64_t start_block_index = length / IO_BLOCK_SIZE;
|
u_int64_t start_block_index = length / IO_BLOCK_SIZE;
|
||||||
size_t internal_offset = length - (start_block_index * IO_BLOCK_SIZE);
|
size_t internal_offset = length - (start_block_index * IO_BLOCK_SIZE);
|
||||||
|
|
||||||
@ -334,8 +364,10 @@ int Fs::truncate(INode_Data *inode_data, size_t length) {
|
|||||||
ssize_t Fs::lseek_next_data(INode_Data *inode_data, size_t offset) {
|
ssize_t Fs::lseek_next_data(INode_Data *inode_data, size_t offset) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (offset >= inode_data->metadata.size)
|
if (offset >= inode_data->metadata.size) {
|
||||||
|
errno = ENXIO;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
u_int64_t start_block_index = offset / IO_BLOCK_SIZE;
|
u_int64_t start_block_index = offset / IO_BLOCK_SIZE;
|
||||||
size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE);
|
size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE);
|
||||||
@ -350,8 +382,10 @@ ssize_t Fs::lseek_next_data(INode_Data *inode_data, size_t offset) {
|
|||||||
&op)) < 0)
|
&op)) < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (op.bytes_completed >= inode_data->metadata.size)
|
if (op.bytes_completed >= inode_data->metadata.size) {
|
||||||
|
errno = ENXIO;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return op.bytes_completed;
|
return op.bytes_completed;
|
||||||
}
|
}
|
||||||
@ -359,8 +393,10 @@ ssize_t Fs::lseek_next_data(INode_Data *inode_data, size_t offset) {
|
|||||||
ssize_t Fs::lseek_next_hole(INode_Data *inode_data, size_t offset) {
|
ssize_t Fs::lseek_next_hole(INode_Data *inode_data, size_t offset) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (offset >= inode_data->metadata.size)
|
if (offset >= inode_data->metadata.size) {
|
||||||
|
errno = ENXIO;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
u_int64_t start_block_index = offset / IO_BLOCK_SIZE;
|
u_int64_t start_block_index = offset / IO_BLOCK_SIZE;
|
||||||
size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE);
|
size_t internal_offset = offset - (start_block_index * IO_BLOCK_SIZE);
|
||||||
|
306
lib/main.cpp
306
lib/main.cpp
@ -1,12 +1,6 @@
|
|||||||
#define _GNU_SOURCE
|
|
||||||
|
|
||||||
#include "fischl.h"
|
#include "fischl.h"
|
||||||
#include "fs.hpp"
|
#include "fs.hpp"
|
||||||
#include <assert.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
// printf("hello word!");
|
// printf("hello word!");
|
||||||
@ -40,284 +34,58 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
// disk->print_block(1597);
|
// disk->print_block(1597);
|
||||||
|
|
||||||
// return 0;
|
/*
|
||||||
|
int err;
|
||||||
|
|
||||||
// int err;
|
RawDisk *disk = new FakeRawDisk(2048);
|
||||||
|
|
||||||
// RawDisk *disk = new FakeRawDisk(2048);
|
|
||||||
// Fs *fs = new Fs(disk);
|
|
||||||
// fs->format();
|
|
||||||
// disk->print_block(0);
|
|
||||||
// disk->print_block(1);
|
|
||||||
|
|
||||||
// INode_Data inode_data;
|
|
||||||
// fs->inode_manager->new_inode(1, 2, 3, &inode_data);
|
|
||||||
|
|
||||||
// disk->print_block(0);
|
|
||||||
// disk->print_block(1);
|
|
||||||
|
|
||||||
// int BL_SIZE = 4096 / 8;
|
|
||||||
|
|
||||||
// u_int64_t buf[BL_SIZE * (56 + 512 + 10)];
|
|
||||||
|
|
||||||
// for (int i = 0; i < BL_SIZE * (56 + 512 + 10); ++i)
|
|
||||||
// buf[i] = (i / BL_SIZE) + 1;
|
|
||||||
|
|
||||||
// err = fs->write(&inode_data, (char *)buf, 4096 * (56 + 3) + 16 + 8, 0);
|
|
||||||
// fs->inode_manager->save_inode(&inode_data);
|
|
||||||
|
|
||||||
// printf("Write %d", err);
|
|
||||||
|
|
||||||
// disk->print_block(0);
|
|
||||||
// disk->print_block(1);
|
|
||||||
// disk->print_block(1025);
|
|
||||||
// disk->print_block(1026);
|
|
||||||
// disk->print_block(1027);
|
|
||||||
// disk->print_block(1080);
|
|
||||||
// disk->print_block(1081);
|
|
||||||
// disk->print_block(1082);
|
|
||||||
// disk->print_block(1083);
|
|
||||||
// disk->print_block(1084);
|
|
||||||
// disk->print_block(1085);
|
|
||||||
|
|
||||||
// int N = 5;
|
|
||||||
|
|
||||||
// u_int64_t buf2[4096] = {0};
|
|
||||||
// err = fs->read(&inode_data, (char *)buf2, (8 * N), 4096 - 8 - 8);
|
|
||||||
|
|
||||||
// printf("\n\nREAD: %d\n", err);
|
|
||||||
// for (int i = 0; i < N; ++i)
|
|
||||||
// printf("%d ", buf2[i]);
|
|
||||||
// printf("\n");
|
|
||||||
|
|
||||||
// u_int64_t big_buf[BL_SIZE * 1000];
|
|
||||||
// char *buf = (char *)big_buf;
|
|
||||||
|
|
||||||
// int offs = 55 * 4096;
|
|
||||||
|
|
||||||
// RawDisk *disk = new FakeRawDisk(2048);
|
|
||||||
// Fs *fs = new Fs(disk);
|
|
||||||
|
|
||||||
// fs->format();
|
|
||||||
// disk->print_block(0);
|
|
||||||
// disk->print_block(1);
|
|
||||||
|
|
||||||
// INode_Data inode_data;
|
|
||||||
// fs->inode_manager->new_inode(1, 2, 3, &inode_data);
|
|
||||||
|
|
||||||
// disk->print_block(0);
|
|
||||||
// disk->print_block(1);
|
|
||||||
// disk->print_block(1024);
|
|
||||||
|
|
||||||
// for (int i = 0; i < BL_SIZE * 3; ++i)
|
|
||||||
// big_buf[i] = 1;
|
|
||||||
|
|
||||||
// err = fs->write(&inode_data, buf, 4096 * 3, offs);
|
|
||||||
|
|
||||||
// for (int i = 0; i < BL_SIZE * 3; ++i)
|
|
||||||
// big_buf[i] = 2;
|
|
||||||
|
|
||||||
// err = fs->truncate(&inode_data, offs + 4096);
|
|
||||||
// err = fs->write(&inode_data, buf, 4096 * 2, offs + 4096 * 2);
|
|
||||||
// err = fs->truncate(&inode_data, offs + 4096 * 2);
|
|
||||||
|
|
||||||
// fs->inode_manager->save_inode(&inode_data);
|
|
||||||
// printf("Write %d", err);
|
|
||||||
|
|
||||||
// disk->print_block(0);
|
|
||||||
// disk->print_block(1);
|
|
||||||
// disk->print_block(1024);
|
|
||||||
// disk->print_block(1025);
|
|
||||||
// disk->print_block(1026);
|
|
||||||
// disk->print_block(1027);
|
|
||||||
// disk->print_block(1028);
|
|
||||||
// disk->print_block(1029);
|
|
||||||
// // disk->print_block(1080);
|
|
||||||
// // disk->print_block(1081);
|
|
||||||
// // disk->print_block(1082);
|
|
||||||
// // disk->print_block(1083);
|
|
||||||
// // disk->print_block(1084);
|
|
||||||
// // disk->print_block(1085);
|
|
||||||
|
|
||||||
// // err = fs->truncate(&inode_data, 4096 + 4);
|
|
||||||
// // fs->inode_manager->save_inode(&inode_data);
|
|
||||||
// // printf("Truncate %d", err);
|
|
||||||
|
|
||||||
// // disk->print_block(0);
|
|
||||||
// // disk->print_block(1);
|
|
||||||
// // disk->print_block(1024);
|
|
||||||
// // disk->print_block(1025);
|
|
||||||
// // disk->print_block(1026);
|
|
||||||
// // disk->print_block(1027);
|
|
||||||
// // disk->print_block(1028);
|
|
||||||
|
|
||||||
// err = fs->lseek_next_hole(&inode_data, offs + 0);
|
|
||||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 0, err);
|
|
||||||
// err = fs->lseek_next_hole(&inode_data, offs + 1);
|
|
||||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 1, err);
|
|
||||||
// err = fs->lseek_next_hole(&inode_data, offs + 4096);
|
|
||||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 4096, err);
|
|
||||||
// err = fs->lseek_next_hole(&inode_data, offs + 4097);
|
|
||||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 4097, err);
|
|
||||||
// err = fs->lseek_next_hole(&inode_data, offs + 8192);
|
|
||||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 8192, err);
|
|
||||||
// err = fs->lseek_next_hole(&inode_data, offs + 8193);
|
|
||||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 8193, err);
|
|
||||||
// err = fs->lseek_next_hole(&inode_data, offs + 12288);
|
|
||||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 12288, err);
|
|
||||||
// err = fs->lseek_next_hole(&inode_data, offs + 12289);
|
|
||||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 12289, err);
|
|
||||||
// err = fs->lseek_next_hole(&inode_data, offs + 100000);
|
|
||||||
// printf("lseek_next_hole (%d): %d\n\n", offs + 100000, err);
|
|
||||||
|
|
||||||
RawDisk *disk = new FakeRawDisk(5120);
|
|
||||||
Fs *fs = new Fs(disk);
|
Fs *fs = new Fs(disk);
|
||||||
fs->format();
|
fs->format();
|
||||||
|
disk->print_block(0);
|
||||||
|
disk->print_block(1);
|
||||||
|
|
||||||
INode_Data inode_data;
|
INode_Data inode_data;
|
||||||
fs->inode_manager->new_inode(1, 2, 3, &inode_data);
|
fs->inode_manager->new_inode(1, 2, 3, &inode_data);
|
||||||
|
|
||||||
char cwd_buf[PATH_MAX];
|
disk->print_block(0);
|
||||||
int fd;
|
disk->print_block(1);
|
||||||
|
|
||||||
assert(getcwd(cwd_buf, sizeof(cwd_buf)) != NULL);
|
int BL_SIZE = 4096 / 8;
|
||||||
|
|
||||||
fd = open("/tmp", O_TMPFILE | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
|
u_int64_t buf[BL_SIZE * (56 + 512 + 10)];
|
||||||
assert(fd != -1);
|
|
||||||
|
|
||||||
u_int64_t test_start_range = IO_BLOCK_SIZE * 3584;
|
for (int i = 0; i < BL_SIZE * (56 + 512 + 10); ++i)
|
||||||
u_int64_t test_io_range = IO_BLOCK_SIZE * 100;
|
buf[i] = (i / BL_SIZE) + 1;
|
||||||
|
|
||||||
// char ones[test_io_range];
|
err = fs->write(&inode_data, (char *)buf, 4096 * (56 + 3) + 16 + 8, 0);
|
||||||
// memset(ones, 1, test_io_range);
|
fs->inode_manager->save_inode(&inode_data);
|
||||||
// char twos[test_io_range];
|
|
||||||
// memset(twos, 2, test_io_range);
|
|
||||||
|
|
||||||
char write_buf[test_io_range];
|
printf("Write %d", err);
|
||||||
char reference_read_buf[test_io_range];
|
|
||||||
char test_read_buf[test_io_range];
|
|
||||||
size_t offset, count;
|
|
||||||
int test_res, ref_res;
|
|
||||||
bool reads_are_equal;
|
|
||||||
int num;
|
|
||||||
|
|
||||||
// size_t weird_offset = 6508064;
|
disk->print_block(0);
|
||||||
|
disk->print_block(1);
|
||||||
|
disk->print_block(1025);
|
||||||
|
disk->print_block(1026);
|
||||||
|
disk->print_block(1027);
|
||||||
|
disk->print_block(1080);
|
||||||
|
disk->print_block(1081);
|
||||||
|
disk->print_block(1082);
|
||||||
|
disk->print_block(1083);
|
||||||
|
disk->print_block(1084);
|
||||||
|
disk->print_block(1085);
|
||||||
|
|
||||||
for (int i = 0; i < 100000; ++i) {
|
int N = 5;
|
||||||
offset = rand() % test_start_range;
|
|
||||||
|
|
||||||
reads_are_equal = true;
|
u_int64_t buf2[4096] = {0};
|
||||||
num = rand() % 100;
|
err = fs->read(&inode_data, (char *)buf2, (8 * N), 4096 - 8 - 8);
|
||||||
if (num < 49)
|
|
||||||
num = 0;
|
|
||||||
else if (num < 99)
|
|
||||||
num = 1;
|
|
||||||
else
|
|
||||||
num = 2;
|
|
||||||
|
|
||||||
if (i % 100 == 0)
|
printf("\n\nREAD: %d\n", err);
|
||||||
printf("%d\n", i);
|
for (int i = 0; i < N; ++i)
|
||||||
|
printf("%d ", buf2[i]);
|
||||||
|
printf("\n");*/
|
||||||
|
|
||||||
switch (num) {
|
fischl(argc, argv);
|
||||||
case 0:
|
|
||||||
count = rand() % test_io_range;
|
|
||||||
memset(write_buf, i, count);
|
|
||||||
// write_buf = (write_buf == ones) ? twos : ones;
|
return 0;
|
||||||
// if (offset <= weird_offset && (count + offset) > weird_offset ||
|
|
||||||
// ((char)i == -77))
|
|
||||||
// printf("write: %ds count=%d offset=%d\n", write_buf[0], count, offset);
|
|
||||||
test_res = fs->write(&inode_data, write_buf, count, offset);
|
|
||||||
assert(lseek(fd, offset, SEEK_SET) == offset);
|
|
||||||
ref_res = write(fd, write_buf, count);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
count = rand() % test_io_range;
|
|
||||||
// if (offset <= weird_offset && (count + offset) > weird_offset)
|
|
||||||
// printf("read: count=%d offset=%d\n", count, offset);
|
|
||||||
test_res = fs->read(&inode_data, test_read_buf, count, offset);
|
|
||||||
assert(lseek(fd, offset, SEEK_SET) == offset);
|
|
||||||
ref_res = read(fd, reference_read_buf, count);
|
|
||||||
for (size_t j = 0; j < count; ++j)
|
|
||||||
if (test_read_buf[i] != reference_read_buf[i]) {
|
|
||||||
reads_are_equal = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
// if (offset <= weird_offset)
|
|
||||||
// printf("truncate: length=%d\n", offset);
|
|
||||||
test_res = fs->truncate(&inode_data, offset);
|
|
||||||
ref_res = ftruncate(fd, offset);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// printf("test_res=%d, ref_res=%d\n", test_res, ref_res);
|
|
||||||
assert(test_res == ref_res);
|
|
||||||
|
|
||||||
if (!reads_are_equal && count > 0) {
|
|
||||||
int prev_test = test_read_buf[0], prev_ref = reference_read_buf[0],
|
|
||||||
same_count = 1;
|
|
||||||
for (size_t j = 1; j < count; ++j) {
|
|
||||||
u_int64_t byte_index = (j + offset);
|
|
||||||
if (byte_index % IO_BLOCK_SIZE == 0)
|
|
||||||
printf("Block: %d\n", byte_index / IO_BLOCK_SIZE);
|
|
||||||
if (prev_test != test_read_buf[j] ||
|
|
||||||
prev_ref != reference_read_buf[j]) {
|
|
||||||
printf("rt %d %d%s\n", prev_ref, prev_test,
|
|
||||||
(prev_test != prev_ref)
|
|
||||||
? " -----DIFF----- -----DIFF----- -----DIFF-----"
|
|
||||||
: "");
|
|
||||||
printf("^^^^ same for %d bytes ending at %d, starting at %d ^^^^\n",
|
|
||||||
same_count, byte_index, byte_index - same_count);
|
|
||||||
prev_test = test_read_buf[j];
|
|
||||||
prev_ref = reference_read_buf[j];
|
|
||||||
same_count = 1;
|
|
||||||
} else {
|
|
||||||
same_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("rt %d %d%s\n", prev_test, prev_test,
|
|
||||||
(prev_test != prev_ref)
|
|
||||||
? " -----DIFF----- -----DIFF----- -----DIFF-----"
|
|
||||||
: "");
|
|
||||||
printf("^^^^ same for %d bytes ^^^^\n", same_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(reads_are_equal);
|
|
||||||
}
|
|
||||||
|
|
||||||
// RawDisk *disk = new FakeRawDisk(5120);
|
|
||||||
// Fs *fs = new Fs(disk);
|
|
||||||
// fs->format();
|
|
||||||
|
|
||||||
// int buf_size = IO_BLOCK_SIZE * 200;
|
|
||||||
// int loops = 14 * 1024 * 1024 / buf_size;
|
|
||||||
|
|
||||||
// char buf[buf_size];
|
|
||||||
|
|
||||||
// memset(buf, 1, sizeof(buf));
|
|
||||||
|
|
||||||
// INode_Data inode_data;
|
|
||||||
// fs->inode_manager->new_inode(1, 2, 3, &inode_data);
|
|
||||||
|
|
||||||
// int res;
|
|
||||||
|
|
||||||
// for (int j = 0; j < loops; ++j) {
|
|
||||||
// res = fs->write(&inode_data, buf, sizeof(buf), sizeof(buf) * j);
|
|
||||||
// printf("write: %d j=%d\n", res, j);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for (int j = 0; j < loops; ++j) {
|
|
||||||
|
|
||||||
// memset(buf, 0, sizeof(buf));
|
|
||||||
// res = fs->read(&inode_data, buf, sizeof(buf), sizeof(buf) * j);
|
|
||||||
|
|
||||||
// printf("read: %d j=%d\n", res, j);
|
|
||||||
|
|
||||||
// for (int i = 0; i < sizeof(buf); ++i)
|
|
||||||
// if (buf[1] != 1) {
|
|
||||||
// printf("error: %d\n", i);
|
|
||||||
// return -1;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
@ -43,6 +43,8 @@ RealRawDisk::RealRawDisk(const char *directory)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// diskSize = 27648 * IO_BLOCK_SIZE;
|
||||||
|
|
||||||
// Calculate the size in bytes
|
// Calculate the size in bytes
|
||||||
numSectors = diskSize / 512; // Assuming a sector size of 512 bytes
|
numSectors = diskSize / 512; // Assuming a sector size of 512 bytes
|
||||||
|
|
||||||
@ -61,14 +63,20 @@ int RealRawDisk::read_block(u_int64_t block_number, char *buffer) {
|
|||||||
u_int64_t offset = block_number * IO_BLOCK_SIZE;
|
u_int64_t offset = block_number * IO_BLOCK_SIZE;
|
||||||
|
|
||||||
if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) {
|
if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) {
|
||||||
|
printf("LSEEK ERROR %llu %llu\n", block_number, offset);
|
||||||
perror("Error seeking to offset");
|
perror("Error seeking to offset");
|
||||||
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this is incorrect
|
// TODO: this is incorrect
|
||||||
ssize_t bytesRead = read(fd, buffer, IO_BLOCK_SIZE);
|
ssize_t bytesRead = read(fd, buffer, IO_BLOCK_SIZE);
|
||||||
|
// printf("READ BLOCK: %llu\n", block_number);
|
||||||
|
// for (int i = 0; i < IO_BLOCK_SIZE; i++)printf("%x", buffer[i]&0xff);
|
||||||
|
// printf("\n");
|
||||||
if (bytesRead < IO_BLOCK_SIZE) {
|
if (bytesRead < IO_BLOCK_SIZE) {
|
||||||
perror("Error reading from device");
|
perror("Error reading from device");
|
||||||
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +88,7 @@ int RealRawDisk::write_block(u_int64_t block_number, char *buffer) {
|
|||||||
|
|
||||||
if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) {
|
if (lseek(fd, offset, SEEK_SET) == (u_int64_t)-1) {
|
||||||
perror("Error seeking to offset");
|
perror("Error seeking to offset");
|
||||||
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +96,7 @@ int RealRawDisk::write_block(u_int64_t block_number, char *buffer) {
|
|||||||
ssize_t bytesWritten = write(fd, buffer, IO_BLOCK_SIZE);
|
ssize_t bytesWritten = write(fd, buffer, IO_BLOCK_SIZE);
|
||||||
if (bytesWritten < IO_BLOCK_SIZE) {
|
if (bytesWritten < IO_BLOCK_SIZE) {
|
||||||
perror("Error writing to device");
|
perror("Error writing to device");
|
||||||
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,6 +122,7 @@ int FakeRawDisk::read_block(u_int64_t block_number, char *buffer) {
|
|||||||
|
|
||||||
if (offset + IO_BLOCK_SIZE > diskSize) {
|
if (offset + IO_BLOCK_SIZE > diskSize) {
|
||||||
perror("Error reading past fake disk size");
|
perror("Error reading past fake disk size");
|
||||||
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,6 +136,7 @@ int FakeRawDisk::write_block(u_int64_t block_number, char *buffer) {
|
|||||||
|
|
||||||
if (offset + IO_BLOCK_SIZE > diskSize) {
|
if (offset + IO_BLOCK_SIZE > diskSize) {
|
||||||
perror("Error writing past fake disk size");
|
perror("Error writing past fake disk size");
|
||||||
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "fs.hpp"
|
#include "fs.hpp"
|
||||||
#include "direntry.h"
|
#include "direntry.h"
|
||||||
|
/*
|
||||||
typedef struct file_test{
|
typedef struct file_test{
|
||||||
const char* name;
|
const char* name;
|
||||||
file_test* next;//use linked-list to know the file at the same level directory
|
file_test* next;//use linked-list to know the file at the same level directory
|
||||||
@ -217,7 +217,7 @@ TEST(DirTest, Add_FindFile_test) {
|
|||||||
file_permissions = 0;
|
file_permissions = 0;
|
||||||
inode_dir.metadata.permissions = file_permissions | S_IFDIR;
|
inode_dir.metadata.permissions = file_permissions | S_IFDIR;
|
||||||
|
|
||||||
/*add with subdirectory*/
|
// add with subdirectory
|
||||||
//Treenode dir(you cannot find here), you only can get Filenode dir based on fischl_find_entry Function
|
//Treenode dir(you cannot find here), you only can get Filenode dir based on fischl_find_entry Function
|
||||||
//So use Filenode->subdirectory will point to the treenode dir, then can add files
|
//So use Filenode->subdirectory will point to the treenode dir, then can add files
|
||||||
target_filepath = std::string("/") + mock_root->subdir->name + "/";
|
target_filepath = std::string("/") + mock_root->subdir->name + "/";
|
||||||
@ -240,7 +240,7 @@ TEST(DirTest, Add_FindFile_test) {
|
|||||||
get_file = fischl_find_entry(get_dir->subdirectory,target_filepath.c_str());
|
get_file = fischl_find_entry(get_dir->subdirectory,target_filepath.c_str());
|
||||||
EXPECT_TRUE(get_file != NULL);
|
EXPECT_TRUE(get_file != NULL);
|
||||||
EXPECT_STREQ(get_file->name, mock_root->subdir->inFile->name);
|
EXPECT_STREQ(get_file->name, mock_root->subdir->inFile->name);
|
||||||
/**********************************************************/
|
|
||||||
//add one more file under fist subdir
|
//add one more file under fist subdir
|
||||||
fischl_add_entry(get_dir->subdirectory, 5, mock_root->subdir->inFile->next->name, &inode_file);
|
fischl_add_entry(get_dir->subdirectory, 5, mock_root->subdir->inFile->next->name, &inode_file);
|
||||||
//add one more directory under fist subdir
|
//add one more directory under fist subdir
|
||||||
@ -326,10 +326,11 @@ TEST(DirTest, Add_FindFile_test) {
|
|||||||
|
|
||||||
// temp = temp->next; // Move to next subdir
|
// temp = temp->next; // Move to next subdir
|
||||||
// }
|
// }
|
||||||
// }
|
// }*/
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
srand(time(NULL)); // Seed the random number generator
|
/*srand(time(NULL)); // Seed the random number generator
|
||||||
d = (argc < 2) ? "/dev/vdc" : argv[1];
|
d = (argc < 2) ? "/dev/vdc" : argv[1];
|
||||||
|
|
||||||
setupTestDirectory(&mock_root);
|
setupTestDirectory(&mock_root);
|
||||||
@ -346,5 +347,6 @@ int main(int argc, char **argv) {
|
|||||||
freeDirHierarchy(mock_root);//mock_root
|
freeDirHierarchy(mock_root);//mock_root
|
||||||
printf("Free Total: Dir %d, File %d\n",total_free_dir, total_free_file);
|
printf("Free Total: Dir %d, File %d\n",total_free_dir, total_free_file);
|
||||||
freeTree(root);
|
freeTree(root);
|
||||||
return result;
|
return result;*/
|
||||||
|
return 0;
|
||||||
}
|
}
|
@ -39,6 +39,10 @@ int total_file_num = 0;
|
|||||||
int total_free_dir = 0;
|
int total_free_dir = 0;
|
||||||
int total_free_file = 0;
|
int total_free_file = 0;
|
||||||
|
|
||||||
|
FileNode* fischl_load_entry(TreeNode *root, const char *path){
|
||||||
|
return fischl_find_entry(fs, root, path);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(FileOperationTest, MkdirnodTest) {
|
TEST(FileOperationTest, MkdirnodTest) {
|
||||||
|
|
||||||
fsop->initialize_rootinode();
|
fsop->initialize_rootinode();
|
||||||
@ -95,19 +99,19 @@ TEST(FileOperationTest, RamDiskTest) {
|
|||||||
FileNode* get_dir;
|
FileNode* get_dir;
|
||||||
u_int64_t get_disk_inum;
|
u_int64_t get_disk_inum;
|
||||||
|
|
||||||
get_dir = fischl_find_entry(fsop->root_node, "/test");//this is file
|
get_dir = fischl_load_entry(fsop->root_node, "/test");//this is file
|
||||||
EXPECT_TRUE(get_dir != NULL);//detect this should find success
|
EXPECT_TRUE(get_dir != NULL);//detect this should find success
|
||||||
EXPECT_STREQ(get_dir->name, "test");
|
EXPECT_STREQ(get_dir->name, "test");
|
||||||
get_disk_inum = fsop->disk_namei("/test");
|
get_disk_inum = fsop->disk_namei("/test");
|
||||||
EXPECT_EQ(get_disk_inum, get_dir->inode_number);
|
EXPECT_EQ(get_disk_inum, get_dir->inode_number);
|
||||||
|
|
||||||
get_dir = fischl_find_entry(fsop->root_node, "/foo/bar/baz");//this is file
|
get_dir = fischl_load_entry(fsop->root_node, "/foo/bar/baz");//this is file
|
||||||
EXPECT_TRUE(get_dir != NULL);//detect this should find success
|
EXPECT_TRUE(get_dir != NULL);//detect this should find success
|
||||||
EXPECT_STREQ(get_dir->name, "baz");
|
EXPECT_STREQ(get_dir->name, "baz");
|
||||||
get_disk_inum = fsop->disk_namei("/foo/bar/baz");
|
get_disk_inum = fsop->disk_namei("/foo/bar/baz");
|
||||||
EXPECT_EQ(get_disk_inum, get_dir->inode_number);
|
EXPECT_EQ(get_disk_inum, get_dir->inode_number);
|
||||||
|
|
||||||
get_dir = fischl_find_entry(fsop->root_node, "/foo/bar/..");
|
get_dir = fischl_load_entry(fsop->root_node, "/foo/bar/..");
|
||||||
EXPECT_TRUE(get_dir != NULL);//detect this should find success
|
EXPECT_TRUE(get_dir != NULL);//detect this should find success
|
||||||
EXPECT_STREQ(get_dir->name, "foo");
|
EXPECT_STREQ(get_dir->name, "foo");
|
||||||
ASSERT_TRUE(get_dir->subdirectory != NULL);//secure it is directory
|
ASSERT_TRUE(get_dir->subdirectory != NULL);//secure it is directory
|
||||||
@ -115,7 +119,7 @@ TEST(FileOperationTest, RamDiskTest) {
|
|||||||
EXPECT_EQ(get_disk_inum, get_dir->inode_number);
|
EXPECT_EQ(get_disk_inum, get_dir->inode_number);
|
||||||
fsop->printDirectory(get_disk_inum);
|
fsop->printDirectory(get_disk_inum);
|
||||||
|
|
||||||
get_dir = fischl_find_entry(fsop->root_node, "/foo/bar/.");
|
get_dir = fischl_load_entry(fsop->root_node, "/foo/bar/.");
|
||||||
EXPECT_TRUE(get_dir != NULL);//detect this should find success
|
EXPECT_TRUE(get_dir != NULL);//detect this should find success
|
||||||
EXPECT_STREQ(get_dir->name, "bar");
|
EXPECT_STREQ(get_dir->name, "bar");
|
||||||
ASSERT_TRUE(get_dir->subdirectory != NULL);//secure it is directory
|
ASSERT_TRUE(get_dir->subdirectory != NULL);//secure it is directory
|
||||||
|
Loading…
x
Reference in New Issue
Block a user