smb: client: introduce ->parse_reparse_point()
Parse reparse point into cifs_open_info_data structure and feed it through cifs_open_info_to_fattr(). Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
ed3e0a149b
commit
539aad7f14
4 changed files with 56 additions and 42 deletions
|
@ -395,8 +395,7 @@ struct smb_version_operations {
|
||||||
struct cifs_tcon *tcon,
|
struct cifs_tcon *tcon,
|
||||||
struct cifs_sb_info *cifs_sb,
|
struct cifs_sb_info *cifs_sb,
|
||||||
const char *full_path,
|
const char *full_path,
|
||||||
char **target_path,
|
char **target_path);
|
||||||
struct kvec *rsp_iov);
|
|
||||||
/* open a file for non-posix mounts */
|
/* open a file for non-posix mounts */
|
||||||
int (*open)(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
|
int (*open)(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
|
||||||
void *buf);
|
void *buf);
|
||||||
|
@ -551,6 +550,9 @@ struct smb_version_operations {
|
||||||
bool (*is_status_io_timeout)(char *buf);
|
bool (*is_status_io_timeout)(char *buf);
|
||||||
/* Check for STATUS_NETWORK_NAME_DELETED */
|
/* Check for STATUS_NETWORK_NAME_DELETED */
|
||||||
bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
|
bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
|
||||||
|
int (*parse_reparse_point)(struct cifs_sb_info *cifs_sb,
|
||||||
|
struct kvec *rsp_iov,
|
||||||
|
struct cifs_open_info_data *data);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct smb_version_values {
|
struct smb_version_values {
|
||||||
|
|
|
@ -459,8 +459,7 @@ static int cifs_get_unix_fattr(const unsigned char *full_path,
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
rc = server->ops->query_symlink(xid, tcon,
|
rc = server->ops->query_symlink(xid, tcon,
|
||||||
cifs_sb, full_path,
|
cifs_sb, full_path,
|
||||||
&fattr->cf_symlink_target,
|
&fattr->cf_symlink_target);
|
||||||
NULL);
|
|
||||||
cifs_dbg(FYI, "%s: query_symlink: %d\n", __func__, rc);
|
cifs_dbg(FYI, "%s: query_symlink: %d\n", __func__, rc);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -1035,22 +1034,28 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
|
||||||
if (!rc)
|
if (!rc)
|
||||||
iov = &rsp_iov;
|
iov = &rsp_iov;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = -EOPNOTSUPP;
|
||||||
switch ((data->reparse_tag = tag)) {
|
switch ((data->reparse_tag = tag)) {
|
||||||
case 0: /* SMB1 symlink */
|
case 0: /* SMB1 symlink */
|
||||||
iov = NULL;
|
if (server->ops->query_symlink) {
|
||||||
fallthrough;
|
|
||||||
case IO_REPARSE_TAG_NFS:
|
|
||||||
case IO_REPARSE_TAG_SYMLINK:
|
|
||||||
if (!data->symlink_target && server->ops->query_symlink) {
|
|
||||||
rc = server->ops->query_symlink(xid, tcon,
|
rc = server->ops->query_symlink(xid, tcon,
|
||||||
cifs_sb, full_path,
|
cifs_sb, full_path,
|
||||||
&data->symlink_target,
|
&data->symlink_target);
|
||||||
iov);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IO_REPARSE_TAG_MOUNT_POINT:
|
case IO_REPARSE_TAG_MOUNT_POINT:
|
||||||
cifs_create_junction_fattr(fattr, sb);
|
cifs_create_junction_fattr(fattr, sb);
|
||||||
|
rc = 0;
|
||||||
goto out;
|
goto out;
|
||||||
|
default:
|
||||||
|
if (data->symlink_target) {
|
||||||
|
rc = 0;
|
||||||
|
} else if (server->ops->parse_reparse_point) {
|
||||||
|
rc = server->ops->parse_reparse_point(cifs_sb,
|
||||||
|
iov, data);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
cifs_open_info_to_fattr(fattr, data, sb);
|
cifs_open_info_to_fattr(fattr, data, sb);
|
||||||
|
|
|
@ -976,32 +976,36 @@ static int cifs_query_symlink(const unsigned int xid,
|
||||||
struct cifs_tcon *tcon,
|
struct cifs_tcon *tcon,
|
||||||
struct cifs_sb_info *cifs_sb,
|
struct cifs_sb_info *cifs_sb,
|
||||||
const char *full_path,
|
const char *full_path,
|
||||||
char **target_path,
|
char **target_path)
|
||||||
struct kvec *rsp_iov)
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
|
||||||
|
|
||||||
|
if (!cap_unix(tcon->ses))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
|
||||||
|
cifs_sb->local_nls, cifs_remap(cifs_sb));
|
||||||
|
if (rc == -EREMOTE)
|
||||||
|
rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
|
||||||
|
target_path, cifs_sb->local_nls);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cifs_parse_reparse_point(struct cifs_sb_info *cifs_sb,
|
||||||
|
struct kvec *rsp_iov,
|
||||||
|
struct cifs_open_info_data *data)
|
||||||
{
|
{
|
||||||
struct reparse_data_buffer *buf;
|
struct reparse_data_buffer *buf;
|
||||||
TRANSACT_IOCTL_RSP *io = rsp_iov->iov_base;
|
TRANSACT_IOCTL_RSP *io = rsp_iov->iov_base;
|
||||||
bool unicode = !!(io->hdr.Flags2 & SMBFLG2_UNICODE);
|
bool unicode = !!(io->hdr.Flags2 & SMBFLG2_UNICODE);
|
||||||
u32 plen = le16_to_cpu(io->ByteCount);
|
u32 plen = le16_to_cpu(io->ByteCount);
|
||||||
int rc;
|
|
||||||
|
|
||||||
cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
|
|
||||||
|
|
||||||
/* Check for unix extensions */
|
|
||||||
if (cap_unix(tcon->ses)) {
|
|
||||||
rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
|
|
||||||
cifs_sb->local_nls,
|
|
||||||
cifs_remap(cifs_sb));
|
|
||||||
if (rc == -EREMOTE)
|
|
||||||
rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
|
|
||||||
target_path,
|
|
||||||
cifs_sb->local_nls);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = (struct reparse_data_buffer *)((__u8 *)&io->hdr.Protocol +
|
buf = (struct reparse_data_buffer *)((__u8 *)&io->hdr.Protocol +
|
||||||
le32_to_cpu(io->DataOffset));
|
le32_to_cpu(io->DataOffset));
|
||||||
return parse_reparse_point(buf, plen, cifs_sb, unicode, target_path);
|
return parse_reparse_point(buf, plen, cifs_sb, unicode,
|
||||||
|
&data->symlink_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -1200,6 +1204,7 @@ struct smb_version_operations smb1_operations = {
|
||||||
.rename = CIFSSMBRename,
|
.rename = CIFSSMBRename,
|
||||||
.create_hardlink = CIFSCreateHardLink,
|
.create_hardlink = CIFSCreateHardLink,
|
||||||
.query_symlink = cifs_query_symlink,
|
.query_symlink = cifs_query_symlink,
|
||||||
|
.parse_reparse_point = cifs_parse_reparse_point,
|
||||||
.open = cifs_open_file,
|
.open = cifs_open_file,
|
||||||
.set_fid = cifs_set_fid,
|
.set_fid = cifs_set_fid,
|
||||||
.close = cifs_close_file,
|
.close = cifs_close_file,
|
||||||
|
|
|
@ -2949,6 +2949,12 @@ int parse_reparse_point(struct reparse_data_buffer *buf,
|
||||||
return parse_reparse_symlink(
|
return parse_reparse_symlink(
|
||||||
(struct reparse_symlink_data_buffer *)buf,
|
(struct reparse_symlink_data_buffer *)buf,
|
||||||
plen, unicode, target_path, cifs_sb);
|
plen, unicode, target_path, cifs_sb);
|
||||||
|
case IO_REPARSE_TAG_LX_SYMLINK:
|
||||||
|
case IO_REPARSE_TAG_AF_UNIX:
|
||||||
|
case IO_REPARSE_TAG_LX_FIFO:
|
||||||
|
case IO_REPARSE_TAG_LX_CHR:
|
||||||
|
case IO_REPARSE_TAG_LX_BLK:
|
||||||
|
return 0;
|
||||||
default:
|
default:
|
||||||
cifs_dbg(VFS, "srv returned unknown symlink buffer tag:0x%08x\n",
|
cifs_dbg(VFS, "srv returned unknown symlink buffer tag:0x%08x\n",
|
||||||
le32_to_cpu(buf->ReparseTag));
|
le32_to_cpu(buf->ReparseTag));
|
||||||
|
@ -2956,22 +2962,18 @@ int parse_reparse_point(struct reparse_data_buffer *buf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smb2_query_symlink(const unsigned int xid,
|
static int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
|
||||||
struct cifs_tcon *tcon,
|
struct kvec *rsp_iov,
|
||||||
struct cifs_sb_info *cifs_sb,
|
struct cifs_open_info_data *data)
|
||||||
const char *full_path,
|
|
||||||
char **target_path,
|
|
||||||
struct kvec *rsp_iov)
|
|
||||||
{
|
{
|
||||||
struct reparse_data_buffer *buf;
|
struct reparse_data_buffer *buf;
|
||||||
struct smb2_ioctl_rsp *io = rsp_iov->iov_base;
|
struct smb2_ioctl_rsp *io = rsp_iov->iov_base;
|
||||||
u32 plen = le32_to_cpu(io->OutputCount);
|
u32 plen = le32_to_cpu(io->OutputCount);
|
||||||
|
|
||||||
cifs_tcon_dbg(FYI, "%s: path: %s\n", __func__, full_path);
|
|
||||||
|
|
||||||
buf = (struct reparse_data_buffer *)((u8 *)io +
|
buf = (struct reparse_data_buffer *)((u8 *)io +
|
||||||
le32_to_cpu(io->OutputOffset));
|
le32_to_cpu(io->OutputOffset));
|
||||||
return parse_reparse_point(buf, plen, cifs_sb, true, target_path);
|
return parse_reparse_point(buf, plen, cifs_sb,
|
||||||
|
true, &data->symlink_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smb2_query_reparse_point(const unsigned int xid,
|
static int smb2_query_reparse_point(const unsigned int xid,
|
||||||
|
@ -5206,7 +5208,7 @@ struct smb_version_operations smb20_operations = {
|
||||||
.unlink = smb2_unlink,
|
.unlink = smb2_unlink,
|
||||||
.rename = smb2_rename_path,
|
.rename = smb2_rename_path,
|
||||||
.create_hardlink = smb2_create_hardlink,
|
.create_hardlink = smb2_create_hardlink,
|
||||||
.query_symlink = smb2_query_symlink,
|
.parse_reparse_point = smb2_parse_reparse_point,
|
||||||
.query_mf_symlink = smb3_query_mf_symlink,
|
.query_mf_symlink = smb3_query_mf_symlink,
|
||||||
.create_mf_symlink = smb3_create_mf_symlink,
|
.create_mf_symlink = smb3_create_mf_symlink,
|
||||||
.open = smb2_open_file,
|
.open = smb2_open_file,
|
||||||
|
@ -5308,7 +5310,7 @@ struct smb_version_operations smb21_operations = {
|
||||||
.unlink = smb2_unlink,
|
.unlink = smb2_unlink,
|
||||||
.rename = smb2_rename_path,
|
.rename = smb2_rename_path,
|
||||||
.create_hardlink = smb2_create_hardlink,
|
.create_hardlink = smb2_create_hardlink,
|
||||||
.query_symlink = smb2_query_symlink,
|
.parse_reparse_point = smb2_parse_reparse_point,
|
||||||
.query_mf_symlink = smb3_query_mf_symlink,
|
.query_mf_symlink = smb3_query_mf_symlink,
|
||||||
.create_mf_symlink = smb3_create_mf_symlink,
|
.create_mf_symlink = smb3_create_mf_symlink,
|
||||||
.open = smb2_open_file,
|
.open = smb2_open_file,
|
||||||
|
@ -5413,7 +5415,7 @@ struct smb_version_operations smb30_operations = {
|
||||||
.unlink = smb2_unlink,
|
.unlink = smb2_unlink,
|
||||||
.rename = smb2_rename_path,
|
.rename = smb2_rename_path,
|
||||||
.create_hardlink = smb2_create_hardlink,
|
.create_hardlink = smb2_create_hardlink,
|
||||||
.query_symlink = smb2_query_symlink,
|
.parse_reparse_point = smb2_parse_reparse_point,
|
||||||
.query_mf_symlink = smb3_query_mf_symlink,
|
.query_mf_symlink = smb3_query_mf_symlink,
|
||||||
.create_mf_symlink = smb3_create_mf_symlink,
|
.create_mf_symlink = smb3_create_mf_symlink,
|
||||||
.open = smb2_open_file,
|
.open = smb2_open_file,
|
||||||
|
@ -5527,7 +5529,7 @@ struct smb_version_operations smb311_operations = {
|
||||||
.unlink = smb2_unlink,
|
.unlink = smb2_unlink,
|
||||||
.rename = smb2_rename_path,
|
.rename = smb2_rename_path,
|
||||||
.create_hardlink = smb2_create_hardlink,
|
.create_hardlink = smb2_create_hardlink,
|
||||||
.query_symlink = smb2_query_symlink,
|
.parse_reparse_point = smb2_parse_reparse_point,
|
||||||
.query_mf_symlink = smb3_query_mf_symlink,
|
.query_mf_symlink = smb3_query_mf_symlink,
|
||||||
.create_mf_symlink = smb3_create_mf_symlink,
|
.create_mf_symlink = smb3_create_mf_symlink,
|
||||||
.open = smb2_open_file,
|
.open = smb2_open_file,
|
||||||
|
|
Loading…
Add table
Reference in a new issue