Fsutil mount: symlink() and readlink() calls completed.
This commit is contained in:
@@ -103,10 +103,6 @@ static int getstat (fs_inode_t *inode, struct stat *statbuf)
|
||||
|
||||
/*
|
||||
* Get file attributes.
|
||||
*
|
||||
* Similar to stat(). The 'st_dev' and 'st_blksize' fields are
|
||||
* ignored. The 'st_ino' field is ignored except if the 'use_ino'
|
||||
* mount option is given.
|
||||
*/
|
||||
int op_getattr(const char *path, struct stat *statbuf)
|
||||
{
|
||||
@@ -123,14 +119,7 @@ int op_getattr(const char *path, struct stat *statbuf)
|
||||
}
|
||||
|
||||
/*
|
||||
* Get attributes from an open file
|
||||
*
|
||||
* This method is called instead of the getattr() method if the
|
||||
* file information is available.
|
||||
*
|
||||
* Currently this is only called after the create() method if that
|
||||
* is implemented (see above). Later it may be called for
|
||||
* invocations of fstat() too.
|
||||
* Get attributes from an open file.
|
||||
*/
|
||||
int op_fgetattr(const char *path, struct stat *statbuf, struct fuse_file_info *fi)
|
||||
{
|
||||
@@ -147,13 +136,7 @@ int op_fgetattr(const char *path, struct stat *statbuf, struct fuse_file_info *f
|
||||
}
|
||||
|
||||
/*
|
||||
* File open operation
|
||||
*
|
||||
* No creation, or truncation flags (O_CREAT, O_EXCL, O_TRUNC)
|
||||
* will be passed to open(). Open should check if the operation
|
||||
* is permitted for the given flags. Optionally open may also
|
||||
* return an arbitrary filehandle in the fuse_file_info structure,
|
||||
* which will be passed to all file operations.
|
||||
* File open operation.
|
||||
*/
|
||||
int op_open(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
@@ -181,14 +164,7 @@ int op_open(const char *path, struct fuse_file_info *fi)
|
||||
}
|
||||
|
||||
/*
|
||||
* Create and open a file
|
||||
*
|
||||
* If the file does not exist, first create it with the specified
|
||||
* mode, and then open it.
|
||||
*
|
||||
* If this method is not implemented or under Linux kernel
|
||||
* versions earlier than 2.6.15, the mknod() and open() methods
|
||||
* will be called instead.
|
||||
* Create and open a file.
|
||||
*/
|
||||
int op_create(const char *path, mode_t mode, struct fuse_file_info *fi)
|
||||
{
|
||||
@@ -211,14 +187,7 @@ int op_create(const char *path, mode_t mode, struct fuse_file_info *fi)
|
||||
}
|
||||
|
||||
/*
|
||||
* Read data from an open file
|
||||
*
|
||||
* Read should return exactly the number of bytes requested except
|
||||
* on EOF or error, otherwise the rest of the data will be
|
||||
* substituted with zeroes. An exception to this is when the
|
||||
* 'direct_io' mount option is specified, in which case the return
|
||||
* value of the read system call will reflect the return value of
|
||||
* this operation.
|
||||
* Read data from an open file.
|
||||
*/
|
||||
int op_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
|
||||
{
|
||||
@@ -241,11 +210,7 @@ int op_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to an open file
|
||||
*
|
||||
* Write should return exactly the number of bytes requested
|
||||
* except on error. An exception to this is when the 'direct_io'
|
||||
* mount option is specified (see read operation).
|
||||
* Write data to an open file.
|
||||
*/
|
||||
int op_write(const char *path, const char *buf, size_t size, off_t offset,
|
||||
struct fuse_file_info *fi)
|
||||
@@ -264,17 +229,7 @@ int op_write(const char *path, const char *buf, size_t size, off_t offset,
|
||||
}
|
||||
|
||||
/*
|
||||
* Release an open file
|
||||
*
|
||||
* Release is called when there are no more references to an open
|
||||
* file: all file descriptors are closed and all memory mappings
|
||||
* are unmapped.
|
||||
*
|
||||
* For every open() call there will be exactly one release() call
|
||||
* with the same flags and file descriptor. It is possible to
|
||||
* have a file opened more than once, in which case only the last
|
||||
* release will mean, that no more reads/writes will happen on the
|
||||
* file. The return value of release is ignored.
|
||||
* Release an open file.
|
||||
*/
|
||||
int op_release(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
@@ -315,10 +270,7 @@ int op_truncate(const char *path, off_t newsize)
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the size of an open file
|
||||
*
|
||||
* This method is called instead of the truncate() method if the
|
||||
* truncation was invoked from an ftruncate() system call.
|
||||
* Change the size of an open file.
|
||||
*/
|
||||
int op_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi)
|
||||
{
|
||||
@@ -340,14 +292,14 @@ int op_ftruncate(const char *path, off_t offset, struct fuse_file_info *fi)
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a file
|
||||
* Remove a file.
|
||||
*/
|
||||
int op_unlink(const char *path)
|
||||
{
|
||||
fs_t *fs = fuse_get_context()->private_data;
|
||||
fs_inode_t inode;
|
||||
|
||||
printlog("op_unlink(path=\"%s\")\n", path);
|
||||
printlog("--- op_unlink(path=\"%s\")\n", path);
|
||||
|
||||
/* Get the file type. */
|
||||
if (! fs_inode_by_name (fs, &inode, path, 0, 0)) {
|
||||
@@ -369,7 +321,7 @@ int op_unlink(const char *path)
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a directory
|
||||
* Remove a directory.
|
||||
*/
|
||||
int op_rmdir(const char *path)
|
||||
{
|
||||
@@ -377,7 +329,7 @@ int op_rmdir(const char *path)
|
||||
fs_inode_t inode, parent;
|
||||
char buf [BSDFS_BSIZE], *p;
|
||||
|
||||
printlog("op_rmdir(path=\"%s\")\n", path);
|
||||
printlog("--- op_rmdir(path=\"%s\")\n", path);
|
||||
|
||||
/* Get the file type. */
|
||||
if (! fs_inode_by_name (fs, &inode, path, 0, 0)) {
|
||||
@@ -430,7 +382,7 @@ int op_rmdir(const char *path)
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a directory
|
||||
* Create a directory.
|
||||
*/
|
||||
int op_mkdir(const char *path, mode_t mode)
|
||||
{
|
||||
@@ -481,7 +433,7 @@ int op_mkdir(const char *path, mode_t mode)
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a hard link to a file
|
||||
* Create a hard link to a file.
|
||||
*/
|
||||
int op_link(const char *path, const char *newpath)
|
||||
{
|
||||
@@ -510,9 +462,7 @@ int op_link(const char *path, const char *newpath)
|
||||
}
|
||||
|
||||
/*
|
||||
* Rename a file
|
||||
*
|
||||
* Both path and newpath are fs-relative.
|
||||
* Rename a file.
|
||||
*/
|
||||
int op_rename(const char *path, const char *newpath)
|
||||
{
|
||||
@@ -589,56 +539,76 @@ int op_mknod(const char *path, mode_t mode, dev_t dev)
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the target of a symbolic link
|
||||
*
|
||||
* The buffer should be filled with a null terminated string. The
|
||||
* buffer size argument includes the space for the terminating
|
||||
* null character. If the linkname is too long to fit in the
|
||||
* buffer, it should be truncated. The return value should be 0
|
||||
* for success.
|
||||
* Read the target of a symbolic link.
|
||||
*/
|
||||
// Note the system readlink() will truncate and lose the terminating
|
||||
// null. So, the size passed to to the system readlink() must be one
|
||||
// less than the size passed to op_readlink()
|
||||
// op_readlink() code by Bernardo F Costa (thanks!)
|
||||
int op_readlink(const char *path, char *link, size_t size)
|
||||
{
|
||||
printlog("op_readlink(path=\"%s\", link=\"%s\", size=%d)\n",
|
||||
fs_t *fs = fuse_get_context()->private_data;
|
||||
fs_inode_t inode;
|
||||
|
||||
printlog("--- op_readlink(path=\"%s\", link=\"%s\", size=%d)\n",
|
||||
path, link, size);
|
||||
|
||||
//TODO
|
||||
//retstat = readlink(path, link, size - 1);
|
||||
//if (retstat < 0)
|
||||
// retstat = print_errno("op_readlink readlink");
|
||||
//else {
|
||||
// link[retstat] = '\0';
|
||||
// retstat = 0;
|
||||
//}
|
||||
/* Open the file. */
|
||||
if (! fs_inode_by_name (fs, &inode, path, 0, 0)) {
|
||||
printlog("--- file not found\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if ((inode.mode & INODE_MODE_FMT) != INODE_MODE_FLNK)
|
||||
return -EINVAL;
|
||||
|
||||
/* Leave one byte for the terminating null. */
|
||||
if (size > inode.size + 1)
|
||||
size = inode.size + 1;
|
||||
if (! fs_inode_read (&inode, 0, (unsigned char*)link, size-1)) {
|
||||
printlog("--- read failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
link[size-1] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a symbolic link
|
||||
* The parameters here are a little bit confusing, but do correspond
|
||||
* to the symlink() system call. The 'path' is where the link points,
|
||||
* while the 'link' is the link itself. So we need to leave the path
|
||||
* unaltered, but insert the link into the mounted directory.
|
||||
* Create a symbolic link.
|
||||
*/
|
||||
int op_symlink(const char *path, const char *link)
|
||||
int op_symlink(const char *path, const char *newpath)
|
||||
{
|
||||
printlog("--- op_symlink(path=\"%s\", link=\"%s\")\n", path, link);
|
||||
fs_t *fs = fuse_get_context()->private_data;
|
||||
fs_inode_t inode;
|
||||
int len, mode;
|
||||
|
||||
//TODO
|
||||
//retstat = symlink(path, link);
|
||||
//if (retstat < 0)
|
||||
// retstat = print_errno("op_symlink symlink");
|
||||
printlog("--- op_symlink(path=\"%s\", newpath=\"%s\")\n", path, newpath);
|
||||
|
||||
/* Check if the file already exists. */
|
||||
if (fs_inode_by_name (fs, &inode, newpath, 0, 0)) {
|
||||
printlog("--- already exists\n");
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
mode = 0777 | INODE_MODE_FLNK;
|
||||
if (! fs_inode_by_name (fs, &inode, newpath, 1, mode)) {
|
||||
printlog("--- create failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
fs_inode_save (&inode, 0);
|
||||
|
||||
len = strlen (path);
|
||||
if (! fs_inode_write (&inode, 0, (unsigned char*)path, len)) {
|
||||
printlog("--- write failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
inode.mtime = time(0);
|
||||
inode.dirty = 1;
|
||||
if (! fs_inode_save (&inode, 0)) {
|
||||
printlog("--- create failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the permission bits of a file
|
||||
* Change the permission bits of a file.
|
||||
*/
|
||||
int op_chmod(const char *path, mode_t mode)
|
||||
{
|
||||
@@ -653,7 +623,7 @@ int op_chmod(const char *path, mode_t mode)
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the owner and group of a file
|
||||
* Change the owner and group of a file.
|
||||
*/
|
||||
int op_chown(const char *path, uid_t uid, gid_t gid)
|
||||
{
|
||||
@@ -668,7 +638,7 @@ int op_chown(const char *path, uid_t uid, gid_t gid)
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the access and/or modification times of a file
|
||||
* Change the access and/or modification times of a file.
|
||||
*/
|
||||
int op_utime(const char *path, struct utimbuf *ubuf)
|
||||
{
|
||||
@@ -683,7 +653,7 @@ int op_utime(const char *path, struct utimbuf *ubuf)
|
||||
}
|
||||
|
||||
/*
|
||||
* Get file system statistics
|
||||
* Get file system statistics.
|
||||
*
|
||||
* The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored
|
||||
*/
|
||||
@@ -701,26 +671,7 @@ int op_statfs(const char *path, struct statvfs *statv)
|
||||
}
|
||||
|
||||
/*
|
||||
* Possibly flush cached data
|
||||
*
|
||||
* BIG NOTE: This is not equivalent to fsync(). It's not a
|
||||
* request to sync dirty data.
|
||||
*
|
||||
* Flush is called on each close() of a file descriptor. So if a
|
||||
* filesystem wants to return write errors in close() and the file
|
||||
* has cached dirty data, this is a good place to write back data
|
||||
* and return any errors. Since many applications ignore close()
|
||||
* errors this is not always useful.
|
||||
*
|
||||
* NOTE: The flush() method may be called more than once for each
|
||||
* open(). This happens if more than one file descriptor refers
|
||||
* to an opened file due to dup(), dup2() or fork() calls. It is
|
||||
* not possible to determine if a flush is final, so each flush
|
||||
* should be treated equally. Multiple write-flush sequences are
|
||||
* relatively rare, so this shouldn't be a problem.
|
||||
*
|
||||
* Filesystems shouldn't assume that flush will always be called
|
||||
* after some writes, or that if will be called at all.
|
||||
* Possibly flush cached data.
|
||||
*/
|
||||
int op_flush(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
@@ -729,8 +680,7 @@ int op_flush(const char *path, struct fuse_file_info *fi)
|
||||
}
|
||||
|
||||
/*
|
||||
* Synchronize file contents
|
||||
*
|
||||
* Synchronize file contents.
|
||||
* If the datasync parameter is non-zero, then only the user data
|
||||
* should be flushed, not the meta data.
|
||||
*/
|
||||
@@ -747,10 +697,7 @@ int op_fsync(const char *path, int datasync, struct fuse_file_info *fi)
|
||||
}
|
||||
|
||||
/*
|
||||
* Open directory
|
||||
*
|
||||
* This method should check if the open operation is permitted for
|
||||
* this directory
|
||||
* Open directory.
|
||||
*/
|
||||
int op_opendir(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
@@ -759,24 +706,7 @@ int op_opendir(const char *path, struct fuse_file_info *fi)
|
||||
}
|
||||
|
||||
/*
|
||||
* Read directory
|
||||
*
|
||||
* This supersedes the old getdir() interface. New applications
|
||||
* should use this.
|
||||
*
|
||||
* The filesystem may choose between two modes of operation:
|
||||
*
|
||||
* 1) The readdir implementation ignores the offset parameter, and
|
||||
* passes zero to the filler function's offset. The filler
|
||||
* function will not return '1' (unless an error happens), so the
|
||||
* whole directory is read in a single readdir operation. This
|
||||
* works just like the old getdir() method.
|
||||
*
|
||||
* 2) The readdir implementation keeps track of the offsets of the
|
||||
* directory entries. It uses the offset parameter and always
|
||||
* passes non-zero offset to the filler function. When the buffer
|
||||
* is full (or an error happens) the filler function will return
|
||||
* '1'.
|
||||
* Read directory.
|
||||
*/
|
||||
int op_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
|
||||
struct fuse_file_info *fi)
|
||||
@@ -827,7 +757,7 @@ int op_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset
|
||||
}
|
||||
|
||||
/*
|
||||
* Release directory
|
||||
* Release directory.
|
||||
*/
|
||||
int op_releasedir(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
@@ -836,8 +766,7 @@ int op_releasedir(const char *path, struct fuse_file_info *fi)
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up filesystem
|
||||
*
|
||||
* Clean up filesystem.
|
||||
* Called on filesystem exit.
|
||||
*/
|
||||
void op_destroy(void *userdata)
|
||||
@@ -846,11 +775,7 @@ void op_destroy(void *userdata)
|
||||
}
|
||||
|
||||
/*
|
||||
* Check file access permissions
|
||||
*
|
||||
* This will be called for the access() system call. If the
|
||||
* 'default_permissions' mount option is given, this method is not
|
||||
* called.
|
||||
* Check file access permissions.
|
||||
*/
|
||||
int op_access(const char *path, int mask)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user