@@ -24,13 +24,23 @@
#include "crypto/crc32c.h"
#include "common/utils.h"
+struct btrfs_send_attribute {
+ u16 tlv_type;
+ /*
+ * Note: in btrfs_tlv_header, this is __le16, but we need 32 bits for
+ * attributes with file data as of version 2 of the send stream format
+ */
+ u32 tlv_len;
+ char *data;
+};
+
struct btrfs_send_stream {
char read_buf[BTRFS_SEND_BUF_SIZE];
int fd;
int cmd;
struct btrfs_cmd_header *cmd_hdr;
- struct btrfs_tlv_header *cmd_attrs[BTRFS_SEND_A_MAX + 1];
+ struct btrfs_send_attribute cmd_attrs[BTRFS_SEND_A_MAX + 1];
u32 version;
/*
@@ -152,6 +162,7 @@ static int read_cmd(struct btrfs_send_stream *sctx)
struct btrfs_tlv_header *tlv_hdr;
u16 tlv_type;
u16 tlv_len;
+ struct btrfs_send_attribute *send_attr;
tlv_hdr = (struct btrfs_tlv_header *)data;
tlv_type = le16_to_cpu(tlv_hdr->tlv_type);
@@ -164,10 +175,15 @@ static int read_cmd(struct btrfs_send_stream *sctx)
goto out;
}
- sctx->cmd_attrs[tlv_type] = tlv_hdr;
+ send_attr = &sctx->cmd_attrs[tlv_type];
+ send_attr->tlv_type = tlv_type;
+ send_attr->tlv_len = tlv_len;
+ pos += sizeof(*tlv_hdr);
+ data += sizeof(*tlv_hdr);
- data += sizeof(*tlv_hdr) + tlv_len;
- pos += sizeof(*tlv_hdr) + tlv_len;
+ send_attr->data = data;
+ pos += send_attr->tlv_len;
+ data += send_attr->tlv_len;
}
sctx->cmd = cmd;
@@ -180,7 +196,7 @@ out:
static int tlv_get(struct btrfs_send_stream *sctx, int attr, void **data, int *len)
{
int ret;
- struct btrfs_tlv_header *hdr;
+ struct btrfs_send_attribute *send_attr;
if (attr <= 0 || attr > BTRFS_SEND_A_MAX) {
error("invalid attribute requested, attr = %d", attr);
@@ -188,15 +204,15 @@ static int tlv_get(struct btrfs_send_stream *sctx, int attr, void **data, int *l
goto out;
}
- hdr = sctx->cmd_attrs[attr];
- if (!hdr) {
+ send_attr = &sctx->cmd_attrs[attr];
+ if (!send_attr->data) {
error("attribute %d requested but not present", attr);
ret = -ENOENT;
goto out;
}
- *len = le16_to_cpu(hdr->tlv_len);
- *data = hdr + 1;
+ *len = send_attr->tlv_len;
+ *data = send_attr->data;
ret = 0;