[PATCH] erofs-utils: fix macOS build & functionality
Gao Xiang
hsiangkao at linux.alibaba.com
Sat Jul 24 23:32:03 AEST 2021
Tested on MacOS Big Sur 11.4.
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
autogen.sh | 3 ++-
configure.ac | 17 ++++++++++++++++-
fuse/dir.c | 2 +-
fuse/macosx.h | 3 +++
fuse/main.c | 6 +++---
include/erofs/defs.h | 25 +++++++++++++++++++++++++
include/erofs/internal.h | 6 ++++--
lib/data.c | 26 +++++++++++++++++++-------
lib/inode.c | 5 ++++-
lib/io.c | 9 ++++++++-
lib/namei.c | 5 +++--
lib/super.c | 2 --
lib/xattr.c | 28 +++++++++++++++++++++++++++-
13 files changed, 115 insertions(+), 22 deletions(-)
create mode 100644 fuse/macosx.h
diff --git a/autogen.sh b/autogen.sh
index fdda7e1995a1..6816b1153f97 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -4,6 +4,7 @@
aclocal && \
autoheader && \
autoconf && \
-libtoolize && \
+case `uname` in Darwin*) glibtoolize --copy ;; \
+ *) libtoolize --copy ;; esac && \
automake -a -c
diff --git a/configure.ac b/configure.ac
index 173642ba7487..6f93bcca22e5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -128,6 +128,8 @@ AC_TYPE_INT64_T
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
AC_CHECK_MEMBERS([struct stat.st_rdev])
+AC_CHECK_MEMBERS([struct stat.st_atim])
+AC_CHECK_MEMBERS([struct stat.st_atimensec])
AC_TYPE_UINT64_T
#
@@ -154,7 +156,20 @@ AC_CHECK_DECL(lseek64,[AC_DEFINE(HAVE_LSEEK64_PROTOTYPE, 1,
#include <unistd.h>])
# Checks for library functions.
-AC_CHECK_FUNCS([backtrace fallocate gettimeofday memset realpath strdup strerror strrchr strtoull])
+AC_CHECK_FUNCS(m4_flatten([
+ backtrace
+ fallocate
+ gettimeofday
+ lgetxattr
+ llistxattr
+ memset
+ realpath
+ pread64
+ pwrite64
+ strdup
+ strerror
+ strrchr
+ strtoull]))
# Configure debug mode
AS_IF([test "x$enable_debug" != "xno"], [], [
diff --git a/fuse/dir.c b/fuse/dir.c
index f8fa0f6616a6..e16fda125270 100644
--- a/fuse/dir.c
+++ b/fuse/dir.c
@@ -6,7 +6,7 @@
*/
#include <fuse.h>
#include <fuse_opt.h>
-
+#include "macosx.h"
#include "erofs/internal.h"
#include "erofs/print.h"
diff --git a/fuse/macosx.h b/fuse/macosx.h
new file mode 100644
index 000000000000..372eba6058d6
--- /dev/null
+++ b/fuse/macosx.h
@@ -0,0 +1,3 @@
+#ifdef __APPLE__
+#undef LIST_HEAD
+#endif
diff --git a/fuse/main.c b/fuse/main.c
index 37119ea8728d..5552480aa4a3 100644
--- a/fuse/main.c
+++ b/fuse/main.c
@@ -10,7 +10,7 @@
#include <libgen.h>
#include <fuse.h>
#include <fuse_opt.h>
-
+#include "macosx.h"
#include "erofs/config.h"
#include "erofs/print.h"
#include "erofs/io.h"
@@ -74,10 +74,10 @@ static int erofsfuse_read(const char *path, char *buffer,
ret = erofs_pread(&vi, buffer, size, offset);
if (ret)
return ret;
- if (offset + size > vi.i_size)
- return vi.i_size - offset;
if (offset >= vi.i_size)
return 0;
+ if (offset + size > vi.i_size)
+ return vi.i_size - offset;
return size;
}
diff --git a/include/erofs/defs.h b/include/erofs/defs.h
index 2e40944c1045..54106853602b 100644
--- a/include/erofs/defs.h
+++ b/include/erofs/defs.h
@@ -96,6 +96,7 @@ typedef int64_t s64;
#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
#define round_down(x, y) ((x) & ~__round_mask(x, y))
+#ifndef roundup
/* The `const' in roundup() prevents gcc-3.3 from calling __divdi3 */
#define roundup(x, y) ( \
{ \
@@ -103,6 +104,7 @@ typedef int64_t s64;
(((x) + (__y - 1)) / __y) * __y; \
} \
)
+#endif
#define rounddown(x, y) ( \
{ \
typeof(x) __x = (x); \
@@ -175,5 +177,28 @@ static inline u32 get_unaligned_le32(const u8 *p)
return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
}
+#ifndef __always_inline
+#define __always_inline inline
+#endif
+
+#ifdef HAVE_STRUCT_STAT_ST_ATIM
+/* Linux */
+#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atim.tv_nsec)
+#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctim.tv_nsec)
+#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtim.tv_nsec)
+#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
+/* macOS */
+#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atimensec)
+#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctimensec)
+#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtimensec)
+#else
+#define ST_ATIM_NSEC(stbuf) 0
+#define ST_CTIM_NSEC(stbuf) 0
+#define ST_MTIM_NSEC(stbuf) 0
#endif
+#ifdef __APPLE__
+#define stat64 stat
+#define lstat64 lstat
+#endif
+#endif
diff --git a/include/erofs/internal.h b/include/erofs/internal.h
index da7be569d8ee..5583861b766d 100644
--- a/include/erofs/internal.h
+++ b/include/erofs/internal.h
@@ -266,7 +266,9 @@ int z_erofs_fill_inode(struct erofs_inode *vi);
int z_erofs_map_blocks_iter(struct erofs_inode *vi,
struct erofs_map_blocks *map);
+#ifdef EUCLEAN
#define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */
-
+#else
+#define EFSCORRUPTED EIO
+#endif
#endif
-
diff --git a/lib/data.c b/lib/data.c
index 31d81f3c8a2a..42b4904abee6 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -5,6 +5,7 @@
* Copyright (C) 2020 Gao Xiang <hsiangkao at aol.com>
* Compression support by Huang Jianan <huangjianan at oppo.com>
*/
+#include <stdlib.h>
#include "erofs/print.h"
#include "erofs/internal.h"
#include "erofs/io.h"
@@ -123,22 +124,23 @@ static int erofs_read_raw_data(struct erofs_inode *inode, char *buffer,
static int z_erofs_read_data(struct erofs_inode *inode, char *buffer,
erofs_off_t size, erofs_off_t offset)
{
- int ret;
erofs_off_t end, length, skip;
struct erofs_map_blocks map = {
.index = UINT_MAX,
};
bool partial;
- unsigned int algorithmformat;
- char raw[Z_EROFS_PCLUSTER_MAX_SIZE];
+ unsigned int algorithmformat, bufsize;
+ char *raw = NULL;
+ int ret = 0;
end = offset + size;
+ bufsize = 0;
while (end > offset) {
map.m_la = end - 1;
ret = z_erofs_map_blocks_iter(inode, &map);
if (ret)
- return ret;
+ break;
/*
* trim to the needed size if the returned extent is quite
@@ -167,9 +169,17 @@ static int z_erofs_read_data(struct erofs_inode *inode, char *buffer,
continue;
}
+ if (map.m_plen > bufsize) {
+ bufsize = map.m_plen;
+ raw = realloc(raw, bufsize);
+ if (!raw) {
+ ret = -ENOMEM;
+ break;
+ }
+ }
ret = dev_read(raw, map.m_pa, map.m_plen);
if (ret < 0)
- return -EIO;
+ break;
algorithmformat = map.m_flags & EROFS_MAP_ZIPPED ?
Z_EROFS_COMPRESSION_LZ4 :
@@ -185,9 +195,11 @@ static int z_erofs_read_data(struct erofs_inode *inode, char *buffer,
.partial_decoding = partial
});
if (ret < 0)
- return ret;
+ break;
}
- return 0;
+ if (raw)
+ free(raw);
+ return ret < 0 ? ret : 0;
}
int erofs_pread(struct erofs_inode *inode, char *buf,
diff --git a/lib/inode.c b/lib/inode.c
index 787e5b4485a2..ec6bbf358cdc 100644
--- a/lib/inode.c
+++ b/lib/inode.c
@@ -12,7 +12,10 @@
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
+#include <config.h>
+#if defined(HAVE_SYS_SYSMACROS_H)
#include <sys/sysmacros.h>
+#endif
#include <dirent.h>
#include "erofs/print.h"
#include "erofs/inode.h"
@@ -765,7 +768,7 @@ int erofs_fill_inode(struct erofs_inode *inode,
inode->i_uid = cfg.c_uid == -1 ? st->st_uid : cfg.c_uid;
inode->i_gid = cfg.c_gid == -1 ? st->st_gid : cfg.c_gid;
inode->i_ctime = st->st_ctime;
- inode->i_ctime_nsec = st->st_ctim.tv_nsec;
+ inode->i_ctime_nsec = ST_CTIM_NSEC(st);
switch (cfg.c_timeinherit) {
case TIMESTAMP_CLAMPING:
diff --git a/lib/io.c b/lib/io.c
index d835f34da50f..6067041fd829 100644
--- a/lib/io.c
+++ b/lib/io.c
@@ -148,7 +148,11 @@ int dev_write(const void *buf, u64 offset, size_t len)
return -EINVAL;
}
+#ifdef HAVE_PWRITE64
ret = pwrite64(erofs_devfd, buf, len, (off64_t)offset);
+#else
+ ret = pwrite(erofs_devfd, buf, len, (off_t)offset);
+#endif
if (ret != (int)len) {
if (ret < 0) {
erofs_err("Failed to write data into device - %s:[%" PRIu64 ", %zd].",
@@ -245,8 +249,11 @@ int dev_read(void *buf, u64 offset, size_t len)
offset, len, erofs_devsz);
return -EINVAL;
}
-
+#ifdef HAVE_PREAD64
ret = pread64(erofs_devfd, buf, len, (off64_t)offset);
+#else
+ ret = pread(erofs_devfd, buf, len, (off_t)offset);
+#endif
if (ret != (int)len) {
erofs_err("Failed to read data from device - %s:[%" PRIu64 ", %zd].",
erofs_devname, offset, len);
diff --git a/lib/namei.c b/lib/namei.c
index 4e06ba468dc4..b572d17daeab 100644
--- a/lib/namei.c
+++ b/lib/namei.c
@@ -4,14 +4,15 @@
*
* Created by Li Guifu <blucerlee at gmail.com>
*/
-#include <linux/kdev_t.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
+#include <config.h>
+#if defined(HAVE_SYS_SYSMACROS_H)
#include <sys/sysmacros.h>
-
+#endif
#include "erofs/print.h"
#include "erofs/io.h"
diff --git a/lib/super.c b/lib/super.c
index 025cefee3aac..11405ec014d2 100644
--- a/lib/super.c
+++ b/lib/super.c
@@ -6,8 +6,6 @@
*/
#include <string.h>
#include <stdlib.h>
-#include <asm-generic/errno-base.h>
-
#include "erofs/io.h"
#include "erofs/print.h"
diff --git a/lib/xattr.c b/lib/xattr.c
index a7677b94d148..aff3d67f6344 100644
--- a/lib/xattr.c
+++ b/lib/xattr.c
@@ -159,7 +159,13 @@ static struct xattr_item *parse_one_xattr(const char *path, const char *key,
DBG_BUGON(keylen < prefixlen);
/* determine length of the value */
+#ifdef HAVE_LGETXATTR
ret = lgetxattr(path, key, NULL, 0);
+#elif defined(__APPLE__)
+ ret = getxattr(path, key, NULL, 0, 0, XATTR_NOFOLLOW);
+#else
+ return ERR_PTR(-EOPNOTSUPP);
+#endif
if (ret < 0)
return ERR_PTR(-errno);
len[1] = ret;
@@ -173,7 +179,15 @@ static struct xattr_item *parse_one_xattr(const char *path, const char *key,
memcpy(kvbuf, key + prefixlen, len[0]);
if (len[1]) {
/* copy value to buffer */
+#ifdef HAVE_LGETXATTR
ret = lgetxattr(path, key, kvbuf + len[0], len[1]);
+#elif defined(__APPLE__)
+ ret = getxattr(path, key, kvbuf + len[0], len[1], 0,
+ XATTR_NOFOLLOW);
+#else
+ free(kvbuf);
+ return ERR_PTR(-EOPNOTSUPP);
+#endif
if (ret < 0) {
free(kvbuf);
return ERR_PTR(-errno);
@@ -292,7 +306,13 @@ static bool erofs_is_skipped_xattr(const char *key)
static int read_xattrs_from_file(const char *path, mode_t mode,
struct list_head *ixattrs)
{
+#ifdef HAVE_LLISTXATTR
ssize_t kllen = llistxattr(path, NULL, 0);
+#elif defined(__APPLE__)
+ ssize_t kllen = listxattr(path, NULL, 0, XATTR_NOFOLLOW);
+#else
+ ssize_t kllen = 0;
+#endif
int ret;
char *keylst, *key, *klend;
unsigned int keylen;
@@ -313,13 +333,19 @@ static int read_xattrs_from_file(const char *path, mode_t mode,
return -ENOMEM;
/* copy the list of attribute keys to the buffer.*/
+#ifdef HAVE_LLISTXATTR
kllen = llistxattr(path, keylst, kllen);
+#elif defined(__APPLE__)
+ kllen = listxattr(path, keylst, kllen, XATTR_NOFOLLOW);
if (kllen < 0) {
erofs_err("llistxattr to get names for %s failed", path);
ret = -errno;
goto err;
}
-
+#else
+ ret = -EOPNOTSUPP;
+ goto err;
+#endif
/*
* loop over the list of zero terminated strings with the
* attribute keys. Use the remaining buffer length to determine
--
2.24.4
More information about the Linux-erofs
mailing list