File: lcfs-internal.h

package info (click to toggle)
composefs 1.0.8-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 11,040 kB
  • sloc: ansic: 9,004; sh: 416; python: 225; makefile: 5
file content (217 lines) | stat: -rw-r--r-- 6,760 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/* lcfs
   Copyright (C) 2023 Alexander Larsson <alexl@redhat.com>

   SPDX-License-Identifier: GPL-2.0-or-later OR Apache-2.0
*/
#ifndef _LCFS_INTERNAL_H
#define _LCFS_INTERNAL_H

#ifdef HAVE_MACHINE_ENDIAN_H
#include <machine/endian.h>
#endif

#ifdef HAVE_SYS_ENDIAN_H
#include <sys/endian.h>
#endif

#ifdef HAVE_ENDIAN_H
#include <endian.h>
#endif

#include "lcfs-writer.h"
#include "lcfs-fsverity.h"
#include "hash.h"

/* This is used for (internal) functions that return zero or -errno, functions that set errno return int */
typedef int errint_t;

// Should match sizeof(struct erofs_xattr_ibody_header)
#define LCFS_XATTR_HEADER_SIZE 12

/* What may be returned by the kernel for digests */
#define MAX_DIGEST_SIZE 64
/* We picked this default block size */
#define FSVERITY_BLOCK_SIZE 4096

#define OVERLAY_XATTR_USER_PREFIX "user."
#define OVERLAY_XATTR_TRUSTED_PREFIX "trusted."
#define OVERLAY_XATTR_PARTIAL_PREFIX "overlay."
// trusted.overlay.
#define OVERLAY_XATTR_PREFIX                                                   \
	OVERLAY_XATTR_TRUSTED_PREFIX OVERLAY_XATTR_PARTIAL_PREFIX
// user.overlay.
#define OVERLAY_XATTR_USERXATTR_PREFIX                                         \
	OVERLAY_XATTR_USER_PREFIX OVERLAY_XATTR_PARTIAL_PREFIX
// trusted.overlay.overlay.
#define OVERLAY_XATTR_ESCAPE_PREFIX OVERLAY_XATTR_PREFIX "overlay."
// trusted.overlay.metacopy
#define OVERLAY_XATTR_METACOPY OVERLAY_XATTR_PREFIX "metacopy"
// trusted.overlay.redirect
#define OVERLAY_XATTR_REDIRECT OVERLAY_XATTR_PREFIX "redirect"
// trusted.overlay.whiteout
#define OVERLAY_XATTR_WHITEOUT OVERLAY_XATTR_PREFIX "whiteout"
// trusted.overlay.whiteouts
#define OVERLAY_XATTR_WHITEOUTS OVERLAY_XATTR_PREFIX "whiteouts"
// trusted.overlay.opaque
#define OVERLAY_XATTR_OPAQUE OVERLAY_XATTR_PREFIX "opaque"

// trusted.overlay.overlay.whiteout
#define OVERLAY_XATTR_ESCAPED_WHITEOUT OVERLAY_XATTR_ESCAPE_PREFIX "whiteout"
// trusted.overlay.overlay.whiteouts
#define OVERLAY_XATTR_ESCAPED_WHITEOUTS OVERLAY_XATTR_ESCAPE_PREFIX "whiteouts"
// trusted.overlay.overlay.opaque
#define OVERLAY_XATTR_ESCAPED_OPAQUE OVERLAY_XATTR_ESCAPE_PREFIX "opaque"

// user.overlay.whiteout
#define OVERLAY_XATTR_USERXATTR_WHITEOUT                                       \
	OVERLAY_XATTR_USERXATTR_PREFIX "whiteout"
// user.overlay.whiteouts
#define OVERLAY_XATTR_USERXATTR_WHITEOUTS                                      \
	OVERLAY_XATTR_USERXATTR_PREFIX "whiteouts"
// user.overlay.opaque
#define OVERLAY_XATTR_USERXATTR_OPAQUE OVERLAY_XATTR_USERXATTR_PREFIX "opaque"

#define ALIGN_TO(_offset, _align_size)                                         \
	(((_offset) + _align_size - 1) & ~(_align_size - 1))

#define __round_mask(x, y) ((__typeof__(x))((y) - 1))
#define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1)
#define round_down(x, y) ((x) & ~__round_mask(x, y))

#define LCFS_MAX_NAME_LENGTH 255 /* max len of file name excluding NULL */

/* Alias macros for the generic conversions; we can drop these at some point */
#define lcfs_u16_to_file(v) (htole16(v))
#define lcfs_u32_to_file(v) (htole32(v))
#define lcfs_u64_to_file(v) (htole64(v))
#define lcfs_u16_from_file(v) (le16toh(v))
#define lcfs_u32_from_file(v) (le32toh(v))
#define lcfs_u64_from_file(v) (le64toh(v))

/* In memory representation used to build the file.  */

struct lcfs_xattr_s {
	char *key;
	char *value;
	uint16_t value_len;

	/* Used during writing */
	int64_t erofs_shared_xattr_offset; /* shared offset, or -1 if not shared */
};

struct lcfs_inode_s {
	uint32_t st_mode; /* File type and mode.  */
	uint32_t st_nlink; /* Number of hard links, only for regular files.  */
	uint32_t st_uid; /* User ID of owner.  */
	uint32_t st_gid; /* Group ID of owner.  */
	uint32_t st_rdev; /* Device ID (if special file).  */
	uint64_t st_size; /* Size of file, only used for regular files */
	int64_t st_mtim_sec;
	uint32_t st_mtim_nsec;
};

struct lcfs_node_s {
	int ref_count;

	struct lcfs_node_s *parent;

	struct lcfs_node_s **children; /* Owns refs */
	size_t children_capacity;
	size_t children_size;

	/* Used to create hard links.  */
	struct lcfs_node_s *link_to; /* Owns refs */
	bool link_to_invalid; /* We detected a cycle */

	char *name;
	char *payload; /* backing file or symlink target */

	uint8_t *content;

	struct lcfs_xattr_s *xattrs;
	size_t n_xattrs;
	/* Must not exceeded UINT16_max; the max size here is determined
	 * by sizeof(erofs_xattr_ibody_header) + n_xattrs * sizeof(erofs_xattr_entry).
	 */
	size_t xattr_size;

	bool digest_set;
	uint8_t digest[LCFS_DIGEST_SIZE]; /* sha256 fs-verity digest */

	struct lcfs_inode_s inode;

	/* Used during compute_tree */
	struct lcfs_node_s *next; /* Use for the queue in compute_tree */
	bool in_tree;
	uint32_t inode_num;

	/* These fields are set by compute_erofs_inodes */
	bool erofs_compact;
	uint32_t erofs_ipad; /* padding before inode data */
	uint32_t erofs_xattr_size;
	uint32_t erofs_isize;
	uint64_t erofs_nid;
	uint32_t erofs_n_blocks;
	uint32_t erofs_tailsize;
};

struct lcfs_ctx_s {
	struct lcfs_write_options_s *options;
	struct lcfs_node_s *root;
	bool destroy_root;

	/* Used by compute_tree.  */
	struct lcfs_node_s *queue_end;
	uint64_t num_inodes;
	int64_t min_mtim_sec;
	uint32_t min_mtim_nsec;
	bool has_acl;

	void *file;
	lcfs_write_cb write_cb;
	off_t bytes_written;
	FsVerityContext *fsverity_ctx;

	void (*finalize)(struct lcfs_ctx_s *ctx);
};

static inline void lcfs_node_unrefp(struct lcfs_node_s **nodep)
{
	if (*nodep != NULL) {
		lcfs_node_unref(*nodep);
		*nodep = NULL;
	}
}
#define cleanup_node __attribute__((cleanup(lcfs_node_unrefp)))

/* lcfs-writer.c */
size_t hash_memory(const char *string, size_t len, size_t n_buckets);
int lcfs_write(struct lcfs_ctx_s *ctx, void *_data, size_t data_len);
int lcfs_write_align(struct lcfs_ctx_s *ctx, size_t align_size);
int lcfs_write_pad(struct lcfs_ctx_s *ctx, size_t data_len);
int lcfs_compute_tree(struct lcfs_ctx_s *ctx, struct lcfs_node_s *root);
int lcfs_clone_root(struct lcfs_ctx_s *ctx);
char *maybe_join_path(const char *a, const char *b);
int follow_links(struct lcfs_node_s *node, struct lcfs_node_s **out_node);
int node_get_dtype(struct lcfs_node_s *node);

int lcfs_node_rename_xattr(struct lcfs_node_s *node, size_t index,
			   const char *new_name);
int lcfs_node_set_xattr_internal(struct lcfs_node_s *node, const char *name,
				 const char *value, size_t value_len,
				 bool from_external_input);

int lcfs_validate_mode(mode_t mode);
int lcfs_node_validate(struct lcfs_node_s *node);

/* lcfs-writer-erofs.c */

int lcfs_write_erofs_to(struct lcfs_ctx_s *ctx);
struct lcfs_ctx_s *lcfs_ctx_erofs_new(void);

/* lcfs-writer-cfs.c */

int lcfs_write_cfs_to(struct lcfs_ctx_s *ctx);
struct lcfs_ctx_s *lcfs_ctx_cfs_new(void);

#endif