Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 568798cc authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Steve French
Browse files

CIFS: Add SMB2 support for hardlink operation

parent d6e906f1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#define SMB2_OP_MKDIR 5
#define SMB2_OP_RENAME 6
#define SMB2_OP_DELETE 7
#define SMB2_OP_HARDLINK 8

/* Used when constructing chained read requests. */
#define CHAINED_REQUEST 1
+28 −6
Original line number Diff line number Diff line
@@ -78,6 +78,10 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
		tmprc = SMB2_rename(xid, tcon, persistent_fid, volatile_fid,
				    (__le16 *)data);
		break;
	case SMB2_OP_HARDLINK:
		tmprc = SMB2_set_hardlink(xid, tcon, persistent_fid,
					  volatile_fid, (__le16 *)data);
		break;
	default:
		cERROR(1, "Invalid command");
		break;
@@ -175,10 +179,10 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
				  SMB2_OP_DELETE);
}

int
smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
static int
smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
		   const char *from_name, const char *to_name,
		 struct cifs_sb_info *cifs_sb)
		   struct cifs_sb_info *cifs_sb, __u32 access, int command)
{
	__le16 *smb2_to_name = NULL;
	int rc;
@@ -189,9 +193,27 @@ smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
		goto smb2_rename_path;
	}

	rc = smb2_open_op_close(xid, tcon, cifs_sb, from_name, DELETE,
				FILE_OPEN, 0, 0, smb2_to_name, SMB2_OP_RENAME);
	rc = smb2_open_op_close(xid, tcon, cifs_sb, from_name, access,
				FILE_OPEN, 0, 0, smb2_to_name, command);
smb2_rename_path:
	kfree(smb2_to_name);
	return rc;
}

int
smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
		 const char *from_name, const char *to_name,
		 struct cifs_sb_info *cifs_sb)
{
	return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
				  DELETE, SMB2_OP_RENAME);
}

int
smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
		     const char *from_name, const char *to_name,
		     struct cifs_sb_info *cifs_sb)
{
	return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
				  FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK);
}
+1 −0
Original line number Diff line number Diff line
@@ -452,6 +452,7 @@ struct smb_version_operations smb21_operations = {
	.rmdir = smb2_rmdir,
	.unlink = smb2_unlink,
	.rename = smb2_rename_path,
	.create_hardlink = smb2_create_hardlink,
	.open = smb2_open_file,
	.set_fid = smb2_set_fid,
	.close = smb2_close_file,
+31 −0
Original line number Diff line number Diff line
@@ -1709,3 +1709,34 @@ SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
	kfree(data);
	return rc;
}

int
SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
		  u64 persistent_fid, u64 volatile_fid, __le16 *target_file)
{
	struct smb2_file_link_info info;
	void **data;
	unsigned int size[2];
	int rc;
	int len = (2 * UniStrnlen((wchar_t *)target_file, PATH_MAX));

	data = kmalloc(sizeof(void *) * 2, GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	info.ReplaceIfExists = 0; /* 1 = replace existing link with new */
			      /* 0 = fail if link already exists */
	info.RootDirectory = 0;  /* MBZ for network ops (why does spec say?) */
	info.FileNameLength = cpu_to_le32(len);

	data[0] = &info;
	size[0] = sizeof(struct smb2_file_link_info);

	data[1] = target_file;
	size[1] = len + 2 /* null */;

	rc = send_set_info(xid, tcon, persistent_fid, volatile_fid,
			   FILE_LINK_INFORMATION, 2, data, size);
	kfree(data);
	return rc;
}
+9 −0
Original line number Diff line number Diff line
@@ -653,6 +653,15 @@ struct smb2_file_rename_info { /* encoding of request for level 10 */
	char   FileName[0];     /* New name to be assigned */
} __packed; /* level 10 Set */

struct smb2_file_link_info { /* encoding of request for level 11 */
	__u8   ReplaceIfExists; /* 1 = replace existing link with new */
				/* 0 = fail if link already exists */
	__u8   Reserved[7];
	__u64  RootDirectory;  /* MBZ for network operations (why says spec?) */
	__le32 FileNameLength;
	char   FileName[0];     /* Name to be assigned to new link */
} __packed; /* level 11 Set */

/*
 * This level 18, although with struct with same name is different from cifs
 * level 0x107. Level 0x107 has an extra u64 between AccessFlags and
Loading