Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for decoding erofs into lcfs_node, and some tooling using it #185

Merged
merged 19 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SUBDIRS=libcomposefs tools
SUBDIRS=libcomposefs tools tests

EXTRA_DIST=\
composefs.pc.in \
Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ AC_CONFIG_FILES([
Makefile
libcomposefs/Makefile
tools/Makefile
tests/Makefile
composefs.spec
composefs.pc
])
Expand Down
1 change: 1 addition & 0 deletions libcomposefs/Makefile-lib.am
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ libcomposefs_la_SOURCES = \
$(COMPOSEFSDIR)/hash.h \
$(COMPOSEFSDIR)/lcfs-internal.h \
$(COMPOSEFSDIR)/lcfs-erofs.h \
$(COMPOSEFSDIR)/lcfs-erofs-internal.h \
$(COMPOSEFSDIR)/lcfs-fsverity.c \
$(COMPOSEFSDIR)/lcfs-fsverity.h \
$(COMPOSEFSDIR)/lcfs-writer-erofs.c \
Expand Down
9 changes: 9 additions & 0 deletions libcomposefs/erofs_fs_wrapper.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <stdbool.h>
#include <linux/types.h>

#define __packed __attribute__((__packed__))
Expand Down Expand Up @@ -33,6 +34,14 @@ static inline __u64 le64_to_cpu(__u64 val)
return le64toh(val);
}

/* Note: These only do power of 2 */
#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 ALIGN_TO(_offset, _align_size) \
(((_offset) + _align_size - 1) & ~(_align_size - 1))

#define BIT(nr) (((uint64_t) 1) << (nr))
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2 * !!(condition)]))
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
Expand Down
134 changes: 134 additions & 0 deletions libcomposefs/lcfs-erofs-internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/* lcfs
Copyright (C) 2023 Alexander Larsson <[email protected]>

This file is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.

This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */

#ifndef _LCFS_EROFS_INTERNAL_H
#define _LCFS_EROFS_INTERNAL_H

#include <string.h>

#include "lcfs-internal.h"
#include "lcfs-erofs.h"
#include "erofs_fs_wrapper.h"

typedef union {
__le16 i_format;
struct erofs_inode_compact compact;
struct erofs_inode_extended extended;
} erofs_inode;

static const char *erofs_xattr_prefixes[] = {
"",
"user.",
"system.posix_acl_access",
"system.posix_acl_default",
"trusted.",
"lustre.",
"security.",
};

static inline uint16_t erofs_inode_version(const erofs_inode *cino)
{
uint16_t i_format = lcfs_u16_from_file(cino->i_format);
return (i_format >> EROFS_I_VERSION_BIT) & EROFS_I_VERSION_MASK;
}

static inline bool erofs_inode_is_compact(const erofs_inode *cino)
{
return erofs_inode_version(cino) == 0;
}

static inline uint16_t erofs_inode_datalayout(const erofs_inode *cino)
{
uint16_t i_format = lcfs_u16_from_file(cino->i_format);
return (i_format >> EROFS_I_DATALAYOUT_BIT) & EROFS_I_DATALAYOUT_MASK;
}

static inline bool erofs_inode_is_tailpacked(const erofs_inode *cino)
{
return erofs_inode_datalayout(cino) == EROFS_INODE_FLAT_INLINE;
}

static inline bool erofs_inode_is_flat(const erofs_inode *cino)
{
return erofs_inode_datalayout(cino) == EROFS_INODE_FLAT_INLINE ||
erofs_inode_datalayout(cino) == EROFS_INODE_FLAT_PLAIN;
}

static inline size_t erofs_xattr_inode_size(uint16_t xattr_icount)
{
size_t xattr_size = 0;
if (xattr_icount > 0)
xattr_size = sizeof(struct erofs_xattr_ibody_header) +
(xattr_icount - 1) * 4;
return xattr_size;
}

#define EROFS_N_XATTR_PREFIXES (sizeof(erofs_xattr_prefixes) / sizeof(char *))

static inline bool erofs_is_acl_xattr(int prefix, const char *name, size_t name_len)
{
const char *const nfs_acl = "system.nfs4_acl";

if ((prefix == EROFS_XATTR_INDEX_POSIX_ACL_ACCESS ||
prefix == EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT) &&
name_len == 0)
return true;
if (prefix == 0 && name_len == strlen(nfs_acl) &&
memcmp(name, nfs_acl, strlen(nfs_acl)) == 0)
return true;
return false;
}

static inline int erofs_get_xattr_prefix(const char *str)
{
for (int i = 1; i < EROFS_N_XATTR_PREFIXES; i++) {
const char *prefix = erofs_xattr_prefixes[i];
if (strlen(str) >= strlen(prefix) &&
memcmp(str, prefix, strlen(prefix)) == 0) {
return i;
}
}
return 0;
}

static inline char *erofs_get_xattr_name(uint8_t index, const char *name,
size_t name_len)
{
char *res;
const char *prefix;
size_t prefix_len;

if (index >= EROFS_N_XATTR_PREFIXES) {
errno = EINVAL;
return NULL;
}

prefix = erofs_xattr_prefixes[index];
prefix_len = strlen(prefix);

res = malloc(prefix_len + name_len + 1);
if (res == NULL) {
errno = ENOMEM;
return NULL;
}
memcpy(res, prefix, prefix_len);
memcpy(res + prefix_len, name, name_len);
res[prefix_len + name_len] = 0;

return res;
Comment on lines +122 to +131
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all just return asprintf("%s%.*s", prefix, name_len, name) right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but I'm not super found of asprintf like this, because I always have to look up the length modifier in the manpage to get it right.

And also, I always worry about the integer format conversion in varargs calls like this.
Like, name_len is size_t, which could be larger than int in some compilers, and the field width must be int. So, do we need to cast? etc.

}

#endif
31 changes: 31 additions & 0 deletions libcomposefs/lcfs-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,28 @@
*/
#define LCFS_BUILD_INLINE_FILE_SIZE_LIMIT 64

#define OVERLAY_XATTR_USER_PREFIX "user."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aweseome, I think this helps a lot to have these. Then we can also followup with some links to the kernel sources.

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

#define OVERLAY_XATTR_ESCAPED_WHITEOUT OVERLAY_XATTR_ESCAPE_PREFIX "whiteout"
#define OVERLAY_XATTR_ESCAPED_WHITEOUTS OVERLAY_XATTR_ESCAPE_PREFIX "whiteouts"

#define OVERLAY_XATTR_USERXATTR_WHITEOUT \
OVERLAY_XATTR_USERXATTR_PREFIX "whiteout"
#define OVERLAY_XATTR_USERXATTR_WHITEOUTS \
OVERLAY_XATTR_USERXATTR_PREFIX "whiteouts"

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

Expand Down Expand Up @@ -147,6 +169,15 @@ struct lcfs_ctx_s {
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);
Expand Down
29 changes: 29 additions & 0 deletions libcomposefs/lcfs-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,41 @@

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

#define max(a, b) ((a > b) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))

static inline bool str_has_prefix(const char *str, const char *prefix)
{
return strncmp(str, prefix, strlen(prefix)) == 0;
}

static inline char *memdup(const char *s, size_t len)
{
char *s2 = malloc(len);
if (s2 == NULL) {
errno = ENOMEM;
return NULL;
}
memcpy(s2, s, len);
return s2;
}

static inline char *str_join(const char *a, const char *b)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optional: This is just code motion, so OK, but same question re asprintf - can be a followup.

{
size_t a_len = strlen(a);
size_t b_len = strlen(b);
char *res = malloc(a_len + b_len + 1);
if (res) {
memcpy(res, a, a_len);
memcpy(res + a_len, b, b_len + 1);
}
return res;
}

static inline void _lcfs_reset_errno_(int *saved_errno)
{
if (*saved_errno < 0)
Expand Down
Loading
Loading