Commit 539aad7f authored by Paulo Alcantara's avatar Paulo Alcantara Committed by Steve French
Browse files

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: default avatarPaulo Alcantara (SUSE) <pc@manguebit.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent ed3e0a14
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -395,8 +395,7 @@ struct smb_version_operations {
			     struct cifs_tcon *tcon,
			     struct cifs_sb_info *cifs_sb,
			     const char *full_path,
			     char **target_path,
			     struct kvec *rsp_iov);
			     char **target_path);
	/* open a file for non-posix mounts */
	int (*open)(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
		    void *buf);
@@ -551,6 +550,9 @@ struct smb_version_operations {
	bool (*is_status_io_timeout)(char *buf);
	/* Check for STATUS_NETWORK_NAME_DELETED */
	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 {
+14 −9
Original line number Diff line number Diff line
@@ -459,8 +459,7 @@ static int cifs_get_unix_fattr(const unsigned char *full_path,
			return -EOPNOTSUPP;
		rc = server->ops->query_symlink(xid, tcon,
						cifs_sb, full_path,
						&fattr->cf_symlink_target,
						NULL);
						&fattr->cf_symlink_target);
		cifs_dbg(FYI, "%s: query_symlink: %d\n", __func__, rc);
	}
	return rc;
@@ -1035,22 +1034,28 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
		if (!rc)
			iov = &rsp_iov;
	}

	rc = -EOPNOTSUPP;
	switch ((data->reparse_tag = tag)) {
	case 0: /* SMB1 symlink */
		iov = NULL;
		fallthrough;
	case IO_REPARSE_TAG_NFS:
	case IO_REPARSE_TAG_SYMLINK:
		if (!data->symlink_target && server->ops->query_symlink) {
		if (server->ops->query_symlink) {
			rc = server->ops->query_symlink(xid, tcon,
							cifs_sb, full_path,
							&data->symlink_target,
							iov);
							&data->symlink_target);
		}
		break;
	case IO_REPARSE_TAG_MOUNT_POINT:
		cifs_create_junction_fattr(fattr, sb);
		rc = 0;
		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);
+23 −18
Original line number Diff line number Diff line
@@ -976,32 +976,36 @@ static int cifs_query_symlink(const unsigned int xid,
			      struct cifs_tcon *tcon,
			      struct cifs_sb_info *cifs_sb,
			      const char *full_path,
			      char **target_path,
			      struct kvec *rsp_iov)
			      char **target_path)
{
	struct reparse_data_buffer *buf;
	TRANSACT_IOCTL_RSP *io = rsp_iov->iov_base;
	bool unicode = !!(io->hdr.Flags2 & SMBFLG2_UNICODE);
	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)) {
	if (!cap_unix(tcon->ses))
		return -EOPNOTSUPP;

	rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
					     cifs_sb->local_nls,
					     cifs_remap(cifs_sb));
				     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);
					    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;
	TRANSACT_IOCTL_RSP *io = rsp_iov->iov_base;
	bool unicode = !!(io->hdr.Flags2 & SMBFLG2_UNICODE);
	u32 plen = le16_to_cpu(io->ByteCount);

	buf = (struct reparse_data_buffer *)((__u8 *)&io->hdr.Protocol +
					     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
@@ -1200,6 +1204,7 @@ struct smb_version_operations smb1_operations = {
	.rename = CIFSSMBRename,
	.create_hardlink = CIFSCreateHardLink,
	.query_symlink = cifs_query_symlink,
	.parse_reparse_point = cifs_parse_reparse_point,
	.open = cifs_open_file,
	.set_fid = cifs_set_fid,
	.close = cifs_close_file,
+15 −13
Original line number Diff line number Diff line
@@ -2949,6 +2949,12 @@ int parse_reparse_point(struct reparse_data_buffer *buf,
		return parse_reparse_symlink(
			(struct reparse_symlink_data_buffer *)buf,
			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:
		cifs_dbg(VFS, "srv returned unknown symlink buffer tag:0x%08x\n",
			 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,
			      struct cifs_tcon *tcon,
			      struct cifs_sb_info *cifs_sb,
			      const char *full_path,
			      char **target_path,
			      struct kvec *rsp_iov)
static int smb2_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 smb2_ioctl_rsp *io = rsp_iov->iov_base;
	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 +
					     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,
@@ -5206,7 +5208,7 @@ struct smb_version_operations smb20_operations = {
	.unlink = smb2_unlink,
	.rename = smb2_rename_path,
	.create_hardlink = smb2_create_hardlink,
	.query_symlink = smb2_query_symlink,
	.parse_reparse_point = smb2_parse_reparse_point,
	.query_mf_symlink = smb3_query_mf_symlink,
	.create_mf_symlink = smb3_create_mf_symlink,
	.open = smb2_open_file,
@@ -5308,7 +5310,7 @@ struct smb_version_operations smb21_operations = {
	.unlink = smb2_unlink,
	.rename = smb2_rename_path,
	.create_hardlink = smb2_create_hardlink,
	.query_symlink = smb2_query_symlink,
	.parse_reparse_point = smb2_parse_reparse_point,
	.query_mf_symlink = smb3_query_mf_symlink,
	.create_mf_symlink = smb3_create_mf_symlink,
	.open = smb2_open_file,
@@ -5413,7 +5415,7 @@ struct smb_version_operations smb30_operations = {
	.unlink = smb2_unlink,
	.rename = smb2_rename_path,
	.create_hardlink = smb2_create_hardlink,
	.query_symlink = smb2_query_symlink,
	.parse_reparse_point = smb2_parse_reparse_point,
	.query_mf_symlink = smb3_query_mf_symlink,
	.create_mf_symlink = smb3_create_mf_symlink,
	.open = smb2_open_file,
@@ -5527,7 +5529,7 @@ struct smb_version_operations smb311_operations = {
	.unlink = smb2_unlink,
	.rename = smb2_rename_path,
	.create_hardlink = smb2_create_hardlink,
	.query_symlink = smb2_query_symlink,
	.parse_reparse_point = smb2_parse_reparse_point,
	.query_mf_symlink = smb3_query_mf_symlink,
	.create_mf_symlink = smb3_create_mf_symlink,
	.open = smb2_open_file,