diff options
author | Elliott Hughes <enh@google.com> | 2019-06-07 16:18:00 -0700 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2019-06-08 13:10:10 -0500 |
commit | 78954416db3032f93317deae1120be9cd7ec9783 (patch) | |
tree | 9c8f58f8c5d4c56ba5fd951b39e84dd15c68a0bd /lib | |
parent | 61ef1dccec4e6bf1c56384ed1cd45f93dcb6bd4c (diff) | |
download | toybox-78954416db3032f93317deae1120be9cd7ec9783.tar.gz |
macOS: numerous fixes.
This patch adds a BSD version of xgetmountlist (for the path ==
NULL case only), tested on macOS. It also papers over the differences
between macOS' and Linux's xattr APIs. For once I think the macOS
one is better. The imitation of mknodat I've had to write swings
things back in Linux's favor though.
BSD calls f_frsize by the name f_iosize instead. (FWIW, it looks
like this is meaningless on Linux and actually meaningful on macOS.)
I've added one #if to toys/ --- I'm calling pathconf in stat.c to
work around the absence of f_namelen, and have left a TODO with an
explanation. I'm not sure what the best fix is here, so punting.
No-one can agree what f_fsid is, even if they're all basically the
same, so work around the `val` versus `__val` issue between macOS
and Linux.
With this patch, it's now possible to build cp/mv/install and stat
for macOS too. (Which completes the set of "toybox commands currently
used on Linux as part of the AOSP build" if you ignore stuff that
deals with processes, which I doubt we'll ever be able to support
for lack of any API.)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/lsm.h | 1 | ||||
-rw-r--r-- | lib/portability.c | 162 | ||||
-rw-r--r-- | lib/portability.h | 22 |
3 files changed, 177 insertions, 8 deletions
@@ -24,7 +24,6 @@ #ifndef XATTR_NAME_SMACK #define XATTR_NAME_SMACK 0 #endif -//ssize_t fgetxattr (int fd, char *name, void *value, size_t size); #define smack_smackfs_path(...) (-1) #define smack_new_label_from_self(...) (-1) #define smack_new_label_from_path(...) (-1) diff --git a/lib/portability.c b/lib/portability.c index 7f81685f..088b90e1 100644 --- a/lib/portability.c +++ b/lib/portability.c @@ -46,11 +46,47 @@ int xgetrandom(void *buf, unsigned buflen, unsigned flags) return 1; } -// Get a linked list of mount points, with stat information. +// Get list of mounted filesystems, including stat and statvfs info. +// Returns a reversed list, which is good for finding overmounts and such. + #if defined(__APPLE__) || defined(__FreeBSD__) -// Not implemented for macOS. -// See <sys/mount.h>'s getmntinfo(3) for the BSD API. +#include <sys/mount.h> + +struct mtab_list *xgetmountlist(char *path) +{ + struct mtab_list *mtlist = 0, *mt; + struct statfs *entries; + int i, count; + + if (path) error_exit("xgetmountlist"); + if ((count = getmntinfo(&entries, 0)) == 0) perror_exit("getmntinfo"); + + // The "test" part of the loop is done before the first time through and + // again after each "increment", so putting the actual load there avoids + // duplicating it. If the load was NULL, the loop stops. + + for (i = 0; i < count; ++i) { + struct statfs *me = &entries[i]; + + mt = xzalloc(sizeof(struct mtab_list) + strlen(me->f_fstypename) + + strlen(me->f_mntonname) + strlen(me->f_mntfromname) + strlen("") + 4); + dlist_add_nomalloc((void *)&mtlist, (void *)mt); + + // Collect details about mounted filesystem. + // Don't report errors, just leave data zeroed. + stat(me->f_mntonname, &(mt->stat)); + statvfs(me->f_mntonname, &(mt->statvfs)); + + // Remember information from struct statfs. + mt->dir = stpcpy(mt->type, me->f_fstypename)+1; + mt->device = stpcpy(mt->dir, me->f_mntonname)+1; + mt->opts = stpcpy(mt->device, me->f_mntfromname)+1; + strcpy(mt->opts, ""); /* TODO: reverse from f_flags? */ + } + + return mtlist; +} #else @@ -110,9 +146,6 @@ int mountlist_istype(struct mtab_list *ml, char *typelist) return !skip; } -// Get list of mounted filesystems, including stat and statvfs info. -// Returns a reversed list, which is good for finding overmounts and such. - struct mtab_list *xgetmountlist(char *path) { struct mtab_list *mtlist = 0, *mt; @@ -247,3 +280,120 @@ int xnotify_wait(struct xnotify *not, char **path) } #endif + +#ifdef __APPLE__ + +ssize_t xattr_get(const char *path, const char *name, void *value, size_t size) +{ + return getxattr(path, name, value, size, 0, 0); +} + +ssize_t xattr_lget(const char *path, const char *name, void *value, size_t size) +{ + return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW); +} + +ssize_t xattr_fget(int fd, const char *name, void *value, size_t size) +{ + return fgetxattr(fd, name, value, size, 0, 0); +} + +ssize_t xattr_list(const char *path, char *list, size_t size) +{ + return listxattr(path, list, size, 0); +} + +ssize_t xattr_llist(const char *path, char *list, size_t size) +{ + return listxattr(path, list, size, XATTR_NOFOLLOW); +} + +ssize_t xattr_flist(int fd, char *list, size_t size) +{ + return flistxattr(fd, list, size, 0); +} + +ssize_t xattr_set(const char* path, const char* name, + const void* value, size_t size, int flags) +{ + return setxattr(path, name, value, size, 0, flags); +} + +ssize_t xattr_lset(const char* path, const char* name, + const void* value, size_t size, int flags) +{ + return setxattr(path, name, value, size, 0, flags | XATTR_NOFOLLOW); +} + +ssize_t xattr_fset(int fd, const char* name, + const void* value, size_t size, int flags) +{ + return fsetxattr(fd, name, value, size, 0, flags); +} + +#else + +ssize_t xattr_get(const char *path, const char *name, void *value, size_t size) +{ + return getxattr(path, name, value, size); +} + +ssize_t xattr_lget(const char *path, const char *name, void *value, size_t size) +{ + return lgetxattr(path, name, value, size); +} + +ssize_t xattr_fget(int fd, const char *name, void *value, size_t size) +{ + return fgetxattr(fd, name, value, size); +} + +ssize_t xattr_list(const char *path, char *list, size_t size) +{ + return listxattr(path, list, size); +} + +ssize_t xattr_llist(const char *path, char *list, size_t size) +{ + return llistxattr(path, list, size); +} + +ssize_t xattr_flist(int fd, char *list, size_t size) +{ + return flistxattr(fd, list, size); +} + +ssize_t xattr_set(const char* path, const char* name, + const void* value, size_t size, int flags) +{ + return setxattr(path, name, value, size, flags); +} + +ssize_t xattr_lset(const char* path, const char* name, + const void* value, size_t size, int flags) +{ + return lsetxattr(path, name, value, size, flags); +} + +ssize_t xattr_fset(int fd, const char* name, + const void* value, size_t size, int flags) +{ + return fsetxattr(fd, name, value, size, flags); +} + + +#endif + +#ifdef __APPLE__ +// In the absence of a mknodat system call, fchdir to dirfd and back +// around a regular mknod call... +int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev) +{ + int old_dirfd = open(".", O_RDONLY), result; + + if (old_dirfd == -1 || fchdir(dirfd) == -1) return -1; + result = mknod(path, mode, dev); + if (fchdir(old_dirfd) == -1) perror_exit("mknodat couldn't return"); + return result; +} +#endif diff --git a/lib/portability.h b/lib/portability.h index f57eb026..c955eddf 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -186,8 +186,24 @@ char *strcasestr(const char *haystack, const char *needle); #endif #endif -#ifndef __FreeBSD__ +#if defined(__APPLE__) || defined(__linux__) +// Linux and macOS has both have getxattr and friends in <sys/xattr.h>, but +// they aren't compatible. #include <sys/xattr.h> +ssize_t xattr_get(const char *, const char *, void *, size_t); +ssize_t xattr_lget(const char *, const char *, void *, size_t); +ssize_t xattr_fget(int fd, const char *, void *, size_t); +ssize_t xattr_list(const char *, char *, size_t); +ssize_t xattr_llist(const char *, char *, size_t); +ssize_t xattr_flist(int, char *, size_t); +ssize_t xattr_set(const char*, const char*, const void*, size_t, int); +ssize_t xattr_lset(const char*, const char*, const void*, size_t, int); +ssize_t xattr_fset(int, const char*, const void*, size_t, int); +#endif + +// macOS doesn't have mknodat, but we can fake it. +#ifdef __APPLE__ +int mknodat(int, const char*, mode_t, dev_t); #endif // Android is missing some headers and functions @@ -312,3 +328,7 @@ struct xnotify { struct xnotify *xnotify_init(int max); int xnotify_add(struct xnotify *not, int fd, char *path); int xnotify_wait(struct xnotify *not, char **path); + +#ifdef __APPLE__ +#define f_frsize f_iosize +#endif |