Enabled actions on directories in reparse plugins

The plugins triggered by reparse points can now act on a directory
through link(2) unlink(2) and creat(2).
This commit is contained in:
Jean-Pierre André 2021-01-26 10:06:17 +01:00
parent 4b8a660006
commit 02673bd04a
4 changed files with 181 additions and 62 deletions

View File

@ -1,7 +1,7 @@
/*
* plugin.h : define interface for plugin development
*
* Copyright (c) 2015 Jean-Pierre Andre
* Copyright (c) 2015-2021 Jean-Pierre Andre
*
*/
@ -151,6 +151,34 @@ typedef struct plugin_operations {
int (*readdir)(ntfs_inode *ni, const REPARSE_POINT *reparse,
s64 *pos, void *fillctx, ntfs_filldir_t filldir,
struct fuse_file_info *fi);
/*
* Create a new file of any type
*
* The returned value is a pointer to the inode created, or
* NULL if failed, with errno telling why.
*/
ntfs_inode *(*create)(ntfs_inode *dir_ni, const REPARSE_POINT *reparse,
le32 securid, ntfschar *name, int name_len,
mode_t type);
/*
* Link a new name to a file or directory
* Linking a directory is needed for renaming a directory
* The returned value is zero for success or a negative errno
* value for failure.
* If the returned value is zero, the modified time stamp
* will be updated after the call.
*/
int (*link)(ntfs_inode *dir_ni, const REPARSE_POINT *reparse,
ntfs_inode *ni, ntfschar *name, int name_len);
/*
* Unlink a name from a directory
* The argument pathname may be NULL
* The returned value is zero for success or a negative errno
* value for failure.
*/
int (*unlink)(ntfs_inode *dir_ni, const REPARSE_POINT *reparse,
const char *pathname,
ntfs_inode *ni, ntfschar *name, int name_len);
} plugin_operations_t;

View File

@ -1509,11 +1509,6 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
return NULL;
}
if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
errno = EOPNOTSUPP;
return NULL;
}
ni = ntfs_mft_record_alloc(dir_ni->vol, NULL);
if (!ni)
return NULL;

View File

@ -4,7 +4,7 @@
* Copyright (c) 2005-2007 Yura Pakhuchiy
* Copyright (c) 2005 Yuval Fledel
* Copyright (c) 2006-2009 Szabolcs Szakacsits
* Copyright (c) 2007-2020 Jean-Pierre Andre
* Copyright (c) 2007-2021 Jean-Pierre Andre
* Copyright (c) 2009 Erik Larsson
*
* This file is originated from the Linux-NTFS project.
@ -261,7 +261,7 @@ static const char *usage_msg =
"\n"
"Copyright (C) 2005-2007 Yura Pakhuchiy\n"
"Copyright (C) 2006-2009 Szabolcs Szakacsits\n"
"Copyright (C) 2007-2020 Jean-Pierre Andre\n"
"Copyright (C) 2007-2021 Jean-Pierre Andre\n"
"Copyright (C) 2009 Erik Larsson\n"
"\n"
"Usage: %s [-o option[,...]] <device|image_file> <mount_point>\n"
@ -2336,26 +2336,50 @@ static int ntfs_fuse_create(fuse_req_t req, fuse_ino_t parent, const char *name,
perm & ~security.umask, S_ISDIR(type));
#endif
/* Create object specified in @type. */
switch (type) {
case S_IFCHR:
case S_IFBLK:
ni = ntfs_create_device(dir_ni, securid,
uname, uname_len, type, dev);
break;
case S_IFLNK:
utarget_len = ntfs_mbstoucs(target, &utarget);
if (utarget_len < 0) {
res = -errno;
goto exit;
}
ni = ntfs_create_symlink(dir_ni, securid,
uname, uname_len,
utarget, utarget_len);
break;
default:
ni = ntfs_create(dir_ni, securid, uname,
uname_len, type);
break;
if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
#ifndef DISABLE_PLUGINS
const plugin_operations_t *ops;
REPARSE_POINT *reparse;
reparse = (REPARSE_POINT*)NULL;
ops = select_reparse_plugin(ctx, dir_ni, &reparse);
if (ops && ops->create) {
ni = (*ops->create)(dir_ni, reparse,
securid, uname, uname_len, type);
} else {
ni = (ntfs_inode*)NULL;
errno = EOPNOTSUPP;
}
free(reparse);
#else /* DISABLE_PLUGINS */
ni = (ntfs_inode*)NULL;
errno = EOPNOTSUPP;
#endif /* DISABLE_PLUGINS */
} else {
switch (type) {
case S_IFCHR:
case S_IFBLK:
ni = ntfs_create_device(dir_ni, securid,
uname, uname_len,
type, dev);
break;
case S_IFLNK:
utarget_len = ntfs_mbstoucs(target,
&utarget);
if (utarget_len < 0) {
res = -errno;
goto exit;
}
ni = ntfs_create_symlink(dir_ni,
securid,
uname, uname_len,
utarget, utarget_len);
break;
default:
ni = ntfs_create(dir_ni, securid, uname,
uname_len, type);
break;
}
}
if (ni) {
/*
@ -2525,10 +2549,25 @@ static int ntfs_fuse_newlink(fuse_req_t req __attribute__((unused)),
#else
ntfs_fuse_fill_security_context(req, &security);
#endif
{
if (ntfs_link(ni, dir_ni, uname, uname_len)) {
res = -errno;
{
if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
#ifndef DISABLE_PLUGINS
const plugin_operations_t *ops;
REPARSE_POINT *reparse;
res = CALL_REPARSE_PLUGIN(dir_ni, link,
ni, uname, uname_len);
if (res < 0)
goto exit;
#else /* DISABLE_PLUGINS */
res = -EOPNOTSUPP;
goto exit;
#endif /* DISABLE_PLUGINS */
} else {
if (ntfs_link(ni, dir_ni, uname, uname_len)) {
res = -errno;
goto exit;
}
}
ntfs_inode_update_mbsname(dir_ni, newname, ni->mft_no);
if (e) {
@ -2712,9 +2751,20 @@ static int ntfs_fuse_rm(fuse_req_t req, fuse_ino_t parent, const char *name,
goto exit;
}
}
if (ntfs_delete(ctx->vol, (char*)NULL, ni, dir_ni,
uname, uname_len))
res = -errno;
if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
#ifndef DISABLE_PLUGINS
const plugin_operations_t *ops;
REPARSE_POINT *reparse;
res = CALL_REPARSE_PLUGIN(dir_ni, unlink, (char*)NULL,
ni, uname, uname_len);
#else /* DISABLE_PLUGINS */
res = -EOPNOTSUPP;
#endif /* DISABLE_PLUGINS */
} else
if (ntfs_delete(ctx->vol, (char*)NULL, ni, dir_ni,
uname, uname_len))
res = -errno;
/* ntfs_delete() always closes ni and dir_ni */
ni = dir_ni = NULL;
exit:

View File

@ -4,7 +4,7 @@
* Copyright (c) 2005-2007 Yura Pakhuchiy
* Copyright (c) 2005 Yuval Fledel
* Copyright (c) 2006-2009 Szabolcs Szakacsits
* Copyright (c) 2007-2020 Jean-Pierre Andre
* Copyright (c) 2007-2021 Jean-Pierre Andre
* Copyright (c) 2009 Erik Larsson
*
* This file is originated from the Linux-NTFS project.
@ -196,7 +196,7 @@ static const char *usage_msg =
"\n"
"Copyright (C) 2005-2007 Yura Pakhuchiy\n"
"Copyright (C) 2006-2009 Szabolcs Szakacsits\n"
"Copyright (C) 2007-2020 Jean-Pierre Andre\n"
"Copyright (C) 2007-2021 Jean-Pierre Andre\n"
"Copyright (C) 2009 Erik Larsson\n"
"\n"
"Usage: %s [-o option[,...]] <device|image_file> <mount_point>\n"
@ -2067,26 +2067,47 @@ static int ntfs_fuse_create(const char *org_path, mode_t typemode, dev_t dev,
perm & ~security.umask, S_ISDIR(type));
#endif
/* Create object specified in @type. */
switch (type) {
case S_IFCHR:
case S_IFBLK:
ni = ntfs_create_device(dir_ni, securid,
if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
#ifndef DISABLE_PLUGINS
const plugin_operations_t *ops;
REPARSE_POINT *reparse;
reparse = (REPARSE_POINT*)NULL;
ops = select_reparse_plugin(ctx, dir_ni, &reparse);
if (ops && ops->create) {
ni = (*ops->create)(dir_ni, reparse,
securid, uname, uname_len, type);
} else {
ni = (ntfs_inode*)NULL;
errno = EOPNOTSUPP;
}
free(reparse);
#else /* DISABLE_PLUGINS */
errno = EOPNOTSUPP;
#endif /* DISABLE_PLUGINS */
} else {
switch (type) {
case S_IFCHR:
case S_IFBLK:
ni = ntfs_create_device(dir_ni, securid,
uname, uname_len, type, dev);
break;
case S_IFLNK:
utarget_len = ntfs_mbstoucs(target, &utarget);
if (utarget_len < 0) {
res = -errno;
goto exit;
}
ni = ntfs_create_symlink(dir_ni, securid,
uname, uname_len,
break;
case S_IFLNK:
utarget_len = ntfs_mbstoucs(target,
&utarget);
if (utarget_len < 0) {
res = -errno;
goto exit;
}
ni = ntfs_create_symlink(dir_ni,
securid, uname, uname_len,
utarget, utarget_len);
break;
default:
ni = ntfs_create(dir_ni, securid, uname,
uname_len, type);
break;
break;
default:
ni = ntfs_create(dir_ni, securid,
uname, uname_len, type);
break;
}
}
if (ni) {
/*
@ -2309,10 +2330,24 @@ static int ntfs_fuse_link(const char *old_path, const char *new_path)
else
#endif
{
if (ntfs_link(ni, dir_ni, uname, uname_len)) {
res = -errno;
goto exit;
}
if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
#ifndef DISABLE_PLUGINS
const plugin_operations_t *ops;
REPARSE_POINT *reparse;
res = CALL_REPARSE_PLUGIN(dir_ni, link,
ni, uname, uname_len);
#else /* DISABLE_PLUGINS */
errno = EOPNOTSUPP;
res = -errno;
#endif /* DISABLE_PLUGINS */
if (res)
goto exit;
} else
if (ntfs_link(ni, dir_ni, uname, uname_len)) {
res = -errno;
goto exit;
}
set_archive(ni);
ntfs_fuse_update_times(ni, NTFS_UPDATE_CTIME);
@ -2384,9 +2419,20 @@ static int ntfs_fuse_rm(const char *org_path)
|| ntfs_allowed_dir_access(&security, org_path, dir_ni, ni,
S_IEXEC + S_IWRITE + S_ISVTX)) {
#endif
if (ntfs_delete(ctx->vol, org_path, ni, dir_ni,
uname, uname_len))
res = -errno;
if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
#ifndef DISABLE_PLUGINS
const plugin_operations_t *ops;
REPARSE_POINT *reparse;
res = CALL_REPARSE_PLUGIN(dir_ni, unlink,
org_path, ni, uname, uname_len);
#else /* DISABLE_PLUGINS */
res = -EOPNOTSUPP;
#endif /* DISABLE_PLUGINS */
} else
if (ntfs_delete(ctx->vol, org_path, ni, dir_ni,
uname, uname_len))
res = -errno;
/* ntfs_delete() always closes ni and dir_ni */
ni = dir_ni = NULL;
#if !KERNELPERMS | (POSIXACLS & !KERNELACLS)