fs/smb/common/compress/compress.c

Source file repositories/reference/linux-study-clean/fs/smb/common/compress/compress.c

File Facts

System
Linux kernel
Corpus path
fs/smb/common/compress/compress.c
Extension
.c
Size
11612 bytes
Lines
400
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct smb_compression_builder {
	u8 *pos;
	u32 remaining;
	bool first;
};

/*
 * Reserve one chained payload header and initialize its common fields.
 * OriginalPayloadSize is present only for LZNT1/LZ77/LZ77+Huffman payloads.
 */
static struct smb2_compression_payload_hdr *
smb_compression_add_payload(struct smb_compression_builder *builder,
			    __le16 alg, u32 payload_len, bool orig_size)
{
	struct smb2_compression_payload_hdr *payload;
	u32 hdr_len = SMB2_COMPRESSION_PAYLOAD_BASE_LEN;
	u32 total_len;

	if (orig_size)
		hdr_len += sizeof(payload->OriginalPayloadSize);
	if (check_add_overflow(hdr_len, payload_len, &total_len) ||
	    total_len > builder->remaining)
		return NULL;

	payload = (struct smb2_compression_payload_hdr *)builder->pos;
	payload->CompressionAlgorithm = alg;
	payload->Flags = cpu_to_le16(builder->first ?
		SMB2_COMPRESSION_FLAG_CHAINED : SMB2_COMPRESSION_FLAG_NONE);
	payload->Length = cpu_to_le32(payload_len +
		(orig_size ? sizeof(payload->OriginalPayloadSize) : 0));

	builder->pos += hdr_len;
	builder->remaining -= hdr_len;
	builder->first = false;
	return payload;
}

static int smb_compression_add_pattern(struct smb_compression_builder *builder,
				       u8 pattern, u32 repetitions)
{
	struct smb2_compression_pattern_v1 *payload;

	if (!smb_compression_add_payload(builder, SMB3_COMPRESS_PATTERN,
					 sizeof(*payload), false))
		return -ENOSPC;

	payload = (struct smb2_compression_pattern_v1 *)builder->pos;
	payload->Pattern = pattern;
	payload->Reserved1 = 0;
	payload->Reserved2 = 0;
	payload->Repetitions = cpu_to_le32(repetitions);
	builder->pos += sizeof(*payload);
	builder->remaining -= sizeof(*payload);
	return 0;
}

static int smb_compression_add_none(struct smb_compression_builder *builder,
				    const u8 *src, u32 len)
{
	if (!smb_compression_add_payload(builder, SMB3_COMPRESS_NONE, len, false))
		return -ENOSPC;

	memcpy(builder->pos, src, len);
	builder->pos += len;
	builder->remaining -= len;
	return 0;
}

static int smb_compression_add_lz77(struct smb_compression_builder *builder,
				    const u8 *src, u32 len)
{
	struct smb2_compression_payload_hdr *payload;
	u32 comp_len;
	int rc;

	if (builder->remaining <= sizeof(*payload))
		return -ENOSPC;

	comp_len = builder->remaining - sizeof(*payload);
	payload = smb_compression_add_payload(builder, SMB3_COMPRESS_LZ77,
					      comp_len, true);
	if (!payload)
		return -ENOSPC;

	rc = smb_lz77_compress(src, len, builder->pos, &comp_len);
	if (rc)
		return rc;

	payload->Length = cpu_to_le32(comp_len +
				      sizeof(payload->OriginalPayloadSize));

Annotation

Implementation Notes