aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/lsm.h1
-rw-r--r--lib/portability.c162
-rw-r--r--lib/portability.h22
3 files changed, 177 insertions, 8 deletions
diff --git a/lib/lsm.h b/lib/lsm.h
index 556700ce..88bf3470 100644
--- a/lib/lsm.h
+++ b/lib/lsm.h
@@ -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