Inserted the reparse tag in the bad reparse symlink

The reparse tag is not quoted in the "unsupported reparse point"
fake symlink shown when a reparse point cannot be processed. The tag
is useful to determine which plugin, if any, is missing.
This commit is contained in:
Jean-Pierre André 2021-01-26 10:06:17 +01:00
parent 02673bd04a
commit b086c9ef73
2 changed files with 97 additions and 39 deletions

View File

@ -277,7 +277,9 @@ static const char *usage_msg =
#endif /* PLUGIN_DIR */ #endif /* PLUGIN_DIR */
"%s"; "%s";
static const char ntfs_bad_reparse[] = "unsupported reparse point"; static const char ntfs_bad_reparse[] = "unsupported reparse tag 0x%08lx";
/* exact length of target text, without the terminator */
#define ntfs_bad_reparse_lth (sizeof(ntfs_bad_reparse) + 2)
#ifdef FUSE_INTERNAL #ifdef FUSE_INTERNAL
int drop_privs(void); int drop_privs(void);
@ -664,7 +666,7 @@ static int junction_getstat(ntfs_inode *ni,
if (target) if (target)
stbuf->st_size = strlen(target); stbuf->st_size = strlen(target);
else else
stbuf->st_size = sizeof(ntfs_bad_reparse) - 1; stbuf->st_size = ntfs_bad_reparse_lth;
stbuf->st_blocks = (ni->allocated_size + 511) >> 9; stbuf->st_blocks = (ni->allocated_size + 511) >> 9;
stbuf->st_mode = S_IFLNK; stbuf->st_mode = S_IFLNK;
free(target); free(target);
@ -722,8 +724,7 @@ static int ntfs_fuse_getstat(struct SECURITY_CONTEXT *scx,
if (!res) { if (!res) {
apply_umask(stbuf); apply_umask(stbuf);
} else { } else {
stbuf->st_size = stbuf->st_size = ntfs_bad_reparse_lth;
sizeof(ntfs_bad_reparse) - 1;
stbuf->st_blocks = stbuf->st_blocks =
(ni->allocated_size + 511) >> 9; (ni->allocated_size + 511) >> 9;
stbuf->st_mode = S_IFLNK; stbuf->st_mode = S_IFLNK;
@ -744,8 +745,7 @@ static int ntfs_fuse_getstat(struct SECURITY_CONTEXT *scx,
if (target) if (target)
stbuf->st_size = strlen(target); stbuf->st_size = strlen(target);
else else
stbuf->st_size = stbuf->st_size = ntfs_bad_reparse_lth;
sizeof(ntfs_bad_reparse) - 1;
stbuf->st_blocks = stbuf->st_blocks =
(ni->allocated_size + 511) >> 9; (ni->allocated_size + 511) >> 9;
stbuf->st_nlink = stbuf->st_nlink =
@ -1035,19 +1035,33 @@ static void ntfs_fuse_lookup(fuse_req_t req, fuse_ino_t parent,
*/ */
static int junction_readlink(ntfs_inode *ni, static int junction_readlink(ntfs_inode *ni,
const REPARSE_POINT *reparse __attribute__((unused)), const REPARSE_POINT *reparse, char **pbuf)
char **pbuf)
{ {
int res; int res;
le32 tag;
int lth;
errno = 0; errno = 0;
res = 0; res = 0;
*pbuf = ntfs_make_symlink(ni, ctx->abs_mnt_point); *pbuf = ntfs_make_symlink(ni, ctx->abs_mnt_point);
if (!*pbuf) { if (!*pbuf) {
if (errno == EOPNOTSUPP) { if (errno == EOPNOTSUPP) {
*pbuf = strdup(ntfs_bad_reparse); *pbuf = (char*)ntfs_malloc(ntfs_bad_reparse_lth + 1);
if (!*pbuf) if (*pbuf) {
if (reparse)
tag = reparse->reparse_tag;
else
tag = const_cpu_to_le32(0);
lth = snprintf(*pbuf, ntfs_bad_reparse_lth + 1,
ntfs_bad_reparse,
(long)le32_to_cpu(tag));
if (lth != ntfs_bad_reparse_lth) {
free(*pbuf);
*pbuf = (char*)NULL;
res = -errno; res = -errno;
}
} else
res = -ENOMEM;
} else } else
res = -errno; res = -errno;
} }
@ -1074,26 +1088,41 @@ static void ntfs_fuse_readlink(fuse_req_t req, fuse_ino_t ino)
* Reparse point : analyze as a junction point * Reparse point : analyze as a junction point
*/ */
if (ni->flags & FILE_ATTR_REPARSE_POINT) { if (ni->flags & FILE_ATTR_REPARSE_POINT) {
REPARSE_POINT *reparse;
le32 tag;
int lth;
#ifndef DISABLE_PLUGINS #ifndef DISABLE_PLUGINS
const plugin_operations_t *ops; const plugin_operations_t *ops;
REPARSE_POINT *reparse;
res = CALL_REPARSE_PLUGIN(ni, readlink, &buf); res = CALL_REPARSE_PLUGIN(ni, readlink, &buf);
if (res || !buf) { if (res && (errno == ELIBACC))
buf = strdup(ntfs_bad_reparse); errno = EOPNOTSUPP;
res = (buf ? 0 : -errno);
}
#else /* DISABLE_PLUGINS */ #else /* DISABLE_PLUGINS */
errno = 0; errno = 0;
res = 0; res = 0;
buf = ntfs_make_symlink(ni, ctx->abs_mnt_point); buf = ntfs_make_symlink(ni, ctx->abs_mnt_point);
if (!buf) { #endif /* DISABLE_PLUGINS */
if (errno == EOPNOTSUPP) if (!buf && (errno == EOPNOTSUPP)) {
buf = strdup(ntfs_bad_reparse); buf = (char*)malloc(ntfs_bad_reparse_lth + 1);
if (buf) {
reparse = ntfs_get_reparse_point(ni);
if (reparse) {
tag = reparse->reparse_tag;
free(reparse);
} else
tag = const_cpu_to_le32(0);
lth = snprintf(buf, ntfs_bad_reparse_lth + 1,
ntfs_bad_reparse,
(long)le32_to_cpu(tag));
res = 0;
if (lth != ntfs_bad_reparse_lth) {
free(buf);
buf = (char*)NULL;
}
}
}
if (!buf) if (!buf)
res = -errno; res = -errno;
}
#endif /* DISABLE_PLUGINS */
goto exit; goto exit;
} }
/* Sanity checks. */ /* Sanity checks. */
@ -1149,7 +1178,6 @@ exit:
fuse_reply_err(req, -res); fuse_reply_err(req, -res);
else else
fuse_reply_readlink(req, buf); fuse_reply_readlink(req, buf);
if (buf != ntfs_bad_reparse)
free(buf); free(buf);
} }

View File

@ -212,7 +212,9 @@ static const char *usage_msg =
#endif /* PLUGIN_DIR */ #endif /* PLUGIN_DIR */
"%s"; "%s";
static const char ntfs_bad_reparse[] = "unsupported reparse point"; static const char ntfs_bad_reparse[] = "unsupported reparse tag 0x%08lx";
/* exact length of target text, without the terminator */
#define ntfs_bad_reparse_lth (sizeof(ntfs_bad_reparse) + 2)
#ifdef FUSE_INTERNAL #ifdef FUSE_INTERNAL
int drop_privs(void); int drop_privs(void);
@ -722,7 +724,7 @@ static int junction_getattr(ntfs_inode *ni,
if (target) if (target)
stbuf->st_size = strlen(target); stbuf->st_size = strlen(target);
else else
stbuf->st_size = sizeof(ntfs_bad_reparse) - 1; stbuf->st_size = ntfs_bad_reparse_lth;
stbuf->st_blocks = (ni->allocated_size + 511) >> 9; stbuf->st_blocks = (ni->allocated_size + 511) >> 9;
stbuf->st_mode = S_IFLNK; stbuf->st_mode = S_IFLNK;
free(target); free(target);
@ -807,8 +809,7 @@ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf)
apply_umask(stbuf); apply_umask(stbuf);
goto ok; goto ok;
} else { } else {
stbuf->st_size = stbuf->st_size = ntfs_bad_reparse_lth;
sizeof(ntfs_bad_reparse) - 1;
stbuf->st_blocks = stbuf->st_blocks =
(ni->allocated_size + 511) >> 9; (ni->allocated_size + 511) >> 9;
stbuf->st_mode = S_IFLNK; stbuf->st_mode = S_IFLNK;
@ -830,7 +831,7 @@ static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf)
if (target) if (target)
stbuf->st_size = strlen(target); stbuf->st_size = strlen(target);
else else
stbuf->st_size = sizeof(ntfs_bad_reparse) - 1; stbuf->st_size = ntfs_bad_reparse_lth;
stbuf->st_blocks = (ni->allocated_size + 511) >> 9; stbuf->st_blocks = (ni->allocated_size + 511) >> 9;
stbuf->st_nlink = le16_to_cpu(ni->mrec->link_count); stbuf->st_nlink = le16_to_cpu(ni->mrec->link_count);
stbuf->st_mode = S_IFLNK; stbuf->st_mode = S_IFLNK;
@ -1052,15 +1053,30 @@ static int junction_readlink(ntfs_inode *ni,
char **pbuf) char **pbuf)
{ {
int res; int res;
le32 tag;
int lth;
errno = 0; errno = 0;
res = 0; res = 0;
*pbuf = ntfs_make_symlink(ni, ctx->abs_mnt_point); *pbuf = ntfs_make_symlink(ni, ctx->abs_mnt_point);
if (!*pbuf) { if (!*pbuf) {
if (errno == EOPNOTSUPP) { if (errno == EOPNOTSUPP) {
*pbuf = strdup(ntfs_bad_reparse); *pbuf = (char*)ntfs_malloc(ntfs_bad_reparse_lth + 1);
if (!*pbuf) if (*pbuf) {
if (reparse)
tag = reparse->reparse_tag;
else
tag = const_cpu_to_le32(0);
lth = snprintf(*pbuf, ntfs_bad_reparse_lth + 1,
ntfs_bad_reparse,
(long)le32_to_cpu(tag));
if (lth != ntfs_bad_reparse_lth) {
free(*pbuf);
*pbuf = (char*)NULL;
res = -errno; res = -errno;
}
} else
res = -ENOMEM;
} else } else
res = -errno; res = -errno;
} }
@ -1077,6 +1093,9 @@ static int ntfs_fuse_readlink(const char *org_path, char *buf, size_t buf_size)
ntfs_attr *na = NULL; ntfs_attr *na = NULL;
INTX_FILE *intx_file = NULL; INTX_FILE *intx_file = NULL;
int stream_name_len, res = 0; int stream_name_len, res = 0;
REPARSE_POINT *reparse;
le32 tag;
int lth;
/* Get inode. */ /* Get inode. */
stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name); stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
@ -1098,16 +1117,16 @@ static int ntfs_fuse_readlink(const char *org_path, char *buf, size_t buf_size)
#ifndef DISABLE_PLUGINS #ifndef DISABLE_PLUGINS
char *gotlink; char *gotlink;
const plugin_operations_t *ops; const plugin_operations_t *ops;
REPARSE_POINT *reparse;
gotlink = (char*)NULL; gotlink = (char*)NULL;
res = CALL_REPARSE_PLUGIN(ni, readlink, &gotlink); res = CALL_REPARSE_PLUGIN(ni, readlink, &gotlink);
if (gotlink) { if (gotlink) {
strncpy(buf, gotlink, buf_size); strncpy(buf, gotlink, buf_size);
free(gotlink); free(gotlink);
} else {
strncpy(buf, ntfs_bad_reparse, buf_size);
res = 0; res = 0;
} else {
errno = EOPNOTSUPP;
res = -EOPNOTSUPP;
} }
#else /* DISABLE_PLUGINS */ #else /* DISABLE_PLUGINS */
char *target; char *target;
@ -1119,11 +1138,22 @@ static int ntfs_fuse_readlink(const char *org_path, char *buf, size_t buf_size)
strncpy(buf,target,buf_size); strncpy(buf,target,buf_size);
free(target); free(target);
} else } else
if (errno == EOPNOTSUPP)
strcpy(buf,ntfs_bad_reparse);
else
res = -errno; res = -errno;
#endif /* DISABLE_PLUGINS */ #endif /* DISABLE_PLUGINS */
if (res == -EOPNOTSUPP) {
reparse = ntfs_get_reparse_point(ni);
if (reparse) {
tag = reparse->reparse_tag;
free(reparse);
} else
tag = const_cpu_to_le32(0);
lth = snprintf(buf, ntfs_bad_reparse_lth + 1,
ntfs_bad_reparse,
(long)le32_to_cpu(tag));
res = 0;
if (lth != ntfs_bad_reparse_lth)
res = -errno;
}
goto exit; goto exit;
} }
/* Sanity checks. */ /* Sanity checks. */