diff --git a/include/files.h b/include/files.h index df15c67..f3cd1f0 100644 --- a/include/files.h +++ b/include/files.h @@ -1,5 +1,6 @@ #include #include +#include "fuse_common.h" #include "direntry.h" class FilesOperation { @@ -20,7 +21,8 @@ class FilesOperation { u_int64_t disk_namei(const char* path); u_int64_t namei(const char* path); int fischl_mkdir(const char*, mode_t); - int fischl_mknod(const char*, mode_t); + int fischl_mknod(const char*, mode_t, dev_t);//for special file + int fischl_create(const char *, mode_t, struct fuse_file_info *);//for regular file //int fischl_readdir(const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *, enum fuse_readdir_flags); int fischl_unlink (const char *); //int fischl_open (const char *, struct fuse_file_info *); diff --git a/include/fuse_common.h b/include/fuse_common.h new file mode 100644 index 0000000..eef2f49 --- /dev/null +++ b/include/fuse_common.h @@ -0,0 +1,82 @@ +#ifndef FUSE_COMMON_H_ +#define FUSE_COMMON_H_ + +#include +#include + +/** + * Information about an open file. + * + * File Handles are created by the open, opendir, and create methods and closed + * by the release and releasedir methods. Multiple file handles may be + * concurrently open for the same file. Generally, a client will create one + * file handle per file descriptor, though in some cases multiple file + * descriptors can share a single file handle. + */ +struct fuse_file_info { + /** Open flags. Available in open() and release() */ + int flags; + + /** In case of a write operation indicates if this was caused + by a delayed write from the page cache. If so, then the + context's pid, uid, and gid fields will not be valid, and + the *fh* value may not match the *fh* value that would + have been sent with the corresponding individual write + requests if write caching had been disabled. */ + unsigned int writepage : 1; + + /** Can be filled in by open/create, to use direct I/O on this file. */ + unsigned int direct_io : 1; + + /** Can be filled in by open and opendir. It signals the kernel that any + currently cached data (ie., data that the filesystem provided the + last time the file/directory was open) need not be invalidated when + the file/directory is closed. */ + unsigned int keep_cache : 1; + + /** Can be filled by open/create, to allow parallel direct writes on this + * file */ + unsigned int parallel_direct_writes : 1; + + /** Indicates a flush operation. Set in flush operation, also + maybe set in highlevel lock operation and lowlevel release + operation. */ + unsigned int flush : 1; + + /** Can be filled in by open, to indicate that the file is not + seekable. */ + unsigned int nonseekable : 1; + + /* Indicates that flock locks for this file should be + released. If set, lock_owner shall contain a valid value. + May only be set in ->release(). */ + unsigned int flock_release : 1; + + /** Can be filled in by opendir. It signals the kernel to + enable caching of entries returned by readdir(). Has no + effect when set in other contexts (in particular it does + nothing when set by open()). */ + unsigned int cache_readdir : 1; + + /** Can be filled in by open, to indicate that flush is not needed + on close. */ + unsigned int noflush : 1; + + /** Padding. Reserved for future use*/ + unsigned int padding : 23; + unsigned int padding2 : 32; + + /** File handle id. May be filled in by filesystem in create, + * open, and opendir(). Available in most other file operations on the + * same file handle. */ + uint64_t fh; + + /** Lock owner id. Available in locking operations and flush */ + uint64_t lock_owner; + + /** Requested poll events. Available in ->poll. Only set on kernels + which support it. If unsupported, this field is set to zero. */ + uint32_t poll_events; +}; + +#endif /* FUSE_COMMON_H_ */ diff --git a/lib/files.cpp b/lib/files.cpp index 93ca218..35efd3f 100644 --- a/lib/files.cpp +++ b/lib/files.cpp @@ -281,8 +281,10 @@ int FilesOperation::fischl_mkdir(const char* path, mode_t mode) { delete pathdup; return 0;//SUCCESS } - -int FilesOperation::fischl_mknod(const char* path, mode_t mode) { +/* + special file +*/ +int FilesOperation::fischl_mknod(const char* path, mode_t mode, dev_t dev) { //check path char *pathdup = strdup(path); char *lastSlash = strrchr(pathdup, '/'); @@ -305,6 +307,34 @@ int FilesOperation::fischl_mknod(const char* path, mode_t mode) { delete pathdup; return 0;//SUCESS } +/* + regular file +*/ +int FilesOperation::fischl_create(const char* path, mode_t mode, struct fuse_file_info* fi) { + //check path + char *pathdup = strdup(path); + char *lastSlash = strrchr(pathdup, '/'); + *lastSlash = '\0'; // Split the string into parent path and new directory name; \0 + char *newFilename = lastSlash+1; //\0, get from + char *ParentPath = pathdup;//pathdup are separated by pathdup, so it take only + // fprintf(stderr,"[%s ,%d] ParentPath:%s, strlen=%d\n",__func__,__LINE__, ParentPath, strlen(ParentPath)); + FileNode *parent_filenode = strlen(ParentPath)? fischl_find_entry(root_node, ParentPath): root_node->self_info; + if (parent_filenode == NULL) { + fprintf(stderr,"[%s ,%d] ParentPath:{%s} not found\n",__func__,__LINE__, ParentPath); + delete pathdup; + return -1; + } + u_int64_t parent_inode_number = parent_filenode->inode_number; + //make new inode + INode* ret = create_new_inode(parent_inode_number, newFilename, mode); + 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->block_number, newFilename, ret); + //directly give inode number rather than create file descriptor table + fi->fh = ret->block_number;//assign file descriptor as inode number to fuse system + delete pathdup; + return 0;//SUCESS +} void FilesOperation::unlink_inode(u_int64_t inode_number) { INode inode; diff --git a/test/layer2_API_dir.cpp b/test/layer2_API_dir.cpp index fb33bb5..8de0cad 100644 --- a/test/layer2_API_dir.cpp +++ b/test/layer2_API_dir.cpp @@ -37,14 +37,15 @@ int total_free_file = 0; TEST(FileOperationTest, MkdirnodTest) { fsop->initialize_rootinode(); - + struct fuse_file_info fi; + mode_t mode;//set mode mode = S_IRWXU | S_IRWXG | S_IRWXO;//future should test permission //S_IRWXU(S_IRUSR | S_IWUSR | S_IXUSR) (owner), S_IRWXG(S_IRGRP | S_IWGRP | S_IXGRP) (group), S_IRWXO(S_IROTH | S_IWOTH | S_IXOTH) - EXPECT_EQ(fsop->fischl_mknod("/test", mode), 0); // mode here is not used yet + EXPECT_EQ(fsop->fischl_create("/test", mode, &fi), 0); // mode here is not used yet EXPECT_EQ(fsop->fischl_mkdir("/foo", mode), 0); EXPECT_EQ(fsop->fischl_mkdir("/foo/bar", mode),0); - EXPECT_EQ(fsop->fischl_mknod("/foo/bar/baz", mode), 0); + EXPECT_EQ(fsop->fischl_create("/foo/bar/baz", mode, &fi), 0); // the following three testcases will fail EXPECT_TRUE(fsop->fischl_mkdir("foo/bar", mode) < 0); EXPECT_TRUE(fsop->fischl_mkdir("/doesnt_exist/bar", mode) < 0);