mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-23 10:04:00 +08:00
Enabled directory operations in plugins
Windows 10 brought a new type of reparse point for directories (0x80000018), so add opendir() and readdir() to the plugin interface to take directories into account. The interface for releasedir() is merged with release() as the plugins can discriminate them if needed.
This commit is contained in:
parent
67feb2c286
commit
1611b21908
@ -30,8 +30,9 @@
|
||||
#ifndef _NTFS_PLUGIN_H
|
||||
#define _NTFS_PLUGIN_H
|
||||
|
||||
#include "inode.h"
|
||||
#include "layout.h"
|
||||
#include "inode.h"
|
||||
#include "dir.h"
|
||||
|
||||
struct fuse_file_info;
|
||||
struct stat;
|
||||
@ -71,10 +72,10 @@ typedef struct plugin_operations {
|
||||
struct fuse_file_info *fi);
|
||||
|
||||
/*
|
||||
* Release an open file
|
||||
* Release an open file or directory
|
||||
* This is only called if fi->fh has been set to a non-null
|
||||
* value while opening. It may be used to free some context
|
||||
* specific to the open file.
|
||||
* specific to the open file or directory
|
||||
* The returned value is zero for success or a negative errno
|
||||
* value for failure.
|
||||
*/
|
||||
@ -126,6 +127,30 @@ typedef struct plugin_operations {
|
||||
*/
|
||||
int (*truncate)(ntfs_inode *ni, const REPARSE_POINT *reparse,
|
||||
off_t size);
|
||||
/*
|
||||
* Open a directory
|
||||
* The field fi->flags indicates the kind of opening.
|
||||
* The field fi->fh may be used to store some information which
|
||||
* will be available to subsequent readdir(). When used
|
||||
* this field must be non-null and freed in release().
|
||||
* The returned value is zero for success and a negative errno
|
||||
* value for failure.
|
||||
*/
|
||||
int (*opendir)(ntfs_inode *ni, const REPARSE_POINT *reparse,
|
||||
struct fuse_file_info *fi);
|
||||
|
||||
/*
|
||||
* Get entries from a directory
|
||||
*
|
||||
* Use the filldir() function with fillctx argument to return
|
||||
* the directory entries.
|
||||
* Names "." and ".." are expected to be returned.
|
||||
* The returned value is zero for success and a negative errno
|
||||
* value for failure.
|
||||
*/
|
||||
int (*readdir)(ntfs_inode *ni, const REPARSE_POINT *reparse,
|
||||
s64 *pos, void *fillctx, ntfs_filldir_t filldir,
|
||||
struct fuse_file_info *fi);
|
||||
} plugin_operations_t;
|
||||
|
||||
|
||||
|
@ -203,6 +203,9 @@ typedef struct fill_item {
|
||||
typedef struct fill_context {
|
||||
struct fill_item *first;
|
||||
struct fill_item *last;
|
||||
#ifndef DISABLE_PLUGINS
|
||||
u64 fh;
|
||||
#endif /* DISABLE_PLUGINS */
|
||||
off_t off;
|
||||
fuse_req_t req;
|
||||
fuse_ino_t ino;
|
||||
@ -1292,6 +1295,17 @@ static void ntfs_fuse_opendir(fuse_req_t req, fuse_ino_t ino,
|
||||
if (!ntfs_allowed_access(&security,ni,accesstype))
|
||||
res = -EACCES;
|
||||
}
|
||||
if (ni->flags & FILE_ATTR_REPARSE_POINT) {
|
||||
#ifndef DISABLE_PLUGINS
|
||||
const plugin_operations_t *ops;
|
||||
REPARSE_POINT *reparse;
|
||||
|
||||
fi->fh = 0;
|
||||
res = CALL_REPARSE_PLUGIN(ni, opendir, fi);
|
||||
#else /* DISABLE_PLUGINS */
|
||||
res = -EOPNOTSUPP;
|
||||
#endif /* DISABLE_PLUGINS */
|
||||
}
|
||||
if (ntfs_inode_close(ni))
|
||||
set_fuse_error(&res);
|
||||
if (!res) {
|
||||
@ -1305,6 +1319,9 @@ static void ntfs_fuse_opendir(fuse_req_t req, fuse_ino_t ino,
|
||||
fill->filled = FALSE;
|
||||
fill->ino = ino;
|
||||
fill->off = 0;
|
||||
#ifndef DISABLE_PLUGINS
|
||||
fill->fh = fi->fh;
|
||||
#endif /* DISABLE_PLUGINS */
|
||||
}
|
||||
fi->fh = (long)fill;
|
||||
}
|
||||
@ -1321,9 +1338,15 @@ static void ntfs_fuse_releasedir(fuse_req_t req,
|
||||
fuse_ino_t ino __attribute__((unused)),
|
||||
struct fuse_file_info *fi)
|
||||
{
|
||||
#ifndef DISABLE_PLUGINS
|
||||
struct fuse_file_info ufi;
|
||||
ntfs_inode *ni;
|
||||
#endif /* DISABLE_PLUGINS */
|
||||
ntfs_fuse_fill_context_t *fill;
|
||||
ntfs_fuse_fill_item_t *current;
|
||||
int res;
|
||||
|
||||
res = 0;
|
||||
fill = (ntfs_fuse_fill_context_t*)(long)fi->fh;
|
||||
if (fill && (fill->ino == ino)) {
|
||||
/* make sure to clear results */
|
||||
@ -1333,16 +1356,38 @@ static void ntfs_fuse_releasedir(fuse_req_t req,
|
||||
free(fill->first);
|
||||
fill->first = current;
|
||||
}
|
||||
#ifndef DISABLE_PLUGINS
|
||||
if (fill->fh) {
|
||||
const plugin_operations_t *ops;
|
||||
REPARSE_POINT *reparse;
|
||||
|
||||
ni = ntfs_inode_open(ctx->vol, INODE(ino));
|
||||
if (ni) {
|
||||
if (ni->flags & FILE_ATTR_REPARSE_POINT) {
|
||||
memcpy(&ufi, fi, sizeof(ufi));
|
||||
ufi.fh = fill->fh;
|
||||
res = CALL_REPARSE_PLUGIN(ni, release,
|
||||
&ufi);
|
||||
}
|
||||
if (ntfs_inode_close(ni) && !res)
|
||||
res = -errno;
|
||||
} else
|
||||
res = -errno;
|
||||
}
|
||||
#endif /* DISABLE_PLUGINS */
|
||||
fill->ino = 0;
|
||||
free(fill);
|
||||
}
|
||||
fuse_reply_err(req, 0);
|
||||
fuse_reply_err(req, -res);
|
||||
}
|
||||
|
||||
static void ntfs_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
|
||||
off_t off __attribute__((unused)),
|
||||
struct fuse_file_info *fi __attribute__((unused)))
|
||||
{
|
||||
#ifndef DISABLE_PLUGINS
|
||||
struct fuse_file_info ufi;
|
||||
#endif /* DISABLE_PLUGINS */
|
||||
ntfs_fuse_fill_item_t *first;
|
||||
ntfs_fuse_fill_item_t *current;
|
||||
ntfs_fuse_fill_context_t *fill;
|
||||
@ -1379,10 +1424,27 @@ static void ntfs_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
|
||||
if (!ni)
|
||||
err = -errno;
|
||||
else {
|
||||
if (ntfs_readdir(ni, &pos, fill,
|
||||
(ntfs_filldir_t)
|
||||
if (ni->flags
|
||||
& FILE_ATTR_REPARSE_POINT) {
|
||||
#ifndef DISABLE_PLUGINS
|
||||
const plugin_operations_t *ops;
|
||||
REPARSE_POINT *reparse;
|
||||
|
||||
memcpy(&ufi, fi, sizeof(ufi));
|
||||
ufi.fh = fill->fh;
|
||||
err = CALL_REPARSE_PLUGIN(ni,
|
||||
readdir, &pos, fill,
|
||||
(ntfs_filldir_t)
|
||||
ntfs_fuse_filler, &ufi);
|
||||
#else /* DISABLE_PLUGINS */
|
||||
err = -EOPNOTSUPP;
|
||||
#endif /* DISABLE_PLUGINS */
|
||||
} else {
|
||||
if (ntfs_readdir(ni, &pos, fill,
|
||||
(ntfs_filldir_t)
|
||||
ntfs_fuse_filler))
|
||||
err = -errno;
|
||||
err = -errno;
|
||||
}
|
||||
fill->filled = TRUE;
|
||||
ntfs_fuse_update_times(ni,
|
||||
NTFS_UPDATE_ATIME);
|
||||
|
@ -1300,6 +1300,17 @@ static int ntfs_fuse_opendir(const char *path,
|
||||
ni,accesstype))
|
||||
res = -EACCES;
|
||||
}
|
||||
if (ni->flags & FILE_ATTR_REPARSE_POINT) {
|
||||
#ifndef DISABLE_PLUGINS
|
||||
const plugin_operations_t *ops;
|
||||
REPARSE_POINT *reparse;
|
||||
|
||||
fi->fh = 0;
|
||||
res = CALL_REPARSE_PLUGIN(ni, opendir, fi);
|
||||
#else /* DISABLE_PLUGINS */
|
||||
res = -EOPNOTSUPP;
|
||||
#endif /* DISABLE_PLUGINS */
|
||||
}
|
||||
if (ntfs_inode_close(ni))
|
||||
set_fuse_error(&res);
|
||||
} else
|
||||
@ -1323,9 +1334,22 @@ static int ntfs_fuse_readdir(const char *path, void *buf,
|
||||
ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
|
||||
if (!ni)
|
||||
return -errno;
|
||||
if (ntfs_readdir(ni, &pos, &fill_ctx,
|
||||
(ntfs_filldir_t)ntfs_fuse_filler))
|
||||
err = -errno;
|
||||
|
||||
if (ni->flags & FILE_ATTR_REPARSE_POINT) {
|
||||
#ifndef DISABLE_PLUGINS
|
||||
const plugin_operations_t *ops;
|
||||
REPARSE_POINT *reparse;
|
||||
|
||||
err = CALL_REPARSE_PLUGIN(ni, readdir, &pos, &fill_ctx,
|
||||
(ntfs_filldir_t)ntfs_fuse_filler, fi);
|
||||
#else /* DISABLE_PLUGINS */
|
||||
err = -EOPNOTSUPP;
|
||||
#endif /* DISABLE_PLUGINS */
|
||||
} else {
|
||||
if (ntfs_readdir(ni, &pos, &fill_ctx,
|
||||
(ntfs_filldir_t)ntfs_fuse_filler))
|
||||
err = -errno;
|
||||
}
|
||||
ntfs_fuse_update_times(ni, NTFS_UPDATE_ATIME);
|
||||
if (ntfs_inode_close(ni))
|
||||
set_fuse_error(&err);
|
||||
@ -3732,6 +3756,7 @@ static struct fuse_operations ntfs_3g_ops = {
|
||||
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)
|
||||
.access = ntfs_fuse_access,
|
||||
.opendir = ntfs_fuse_opendir,
|
||||
.releasedir = ntfs_fuse_release,
|
||||
#endif
|
||||
#ifdef HAVE_SETXATTR
|
||||
.getxattr = ntfs_fuse_getxattr,
|
||||
|
Loading…
Reference in New Issue
Block a user