1 /* SPDX-License-Identifier: GPL-2.0 */ 2 3 #ifndef __STATMOUNT_H 4 #define __STATMOUNT_H 5 6 #include <errno.h> 7 #include <stdint.h> 8 #include <stdlib.h> 9 #include <linux/mount.h> 10 #include <asm/unistd.h> 11 12 #define STATMOUNT_BUFSIZE (1 << 15) 13 14 #ifndef __NR_statmount 15 #if defined __alpha__ 16 #define __NR_statmount 567 17 #elif defined _MIPS_SIM 18 #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ 19 #define __NR_statmount 4457 20 #endif 21 #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ 22 #define __NR_statmount 6457 23 #endif 24 #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ 25 #define __NR_statmount 5457 26 #endif 27 #else 28 #define __NR_statmount 457 29 #endif 30 #endif 31 32 #ifndef __NR_listmount 33 #if defined __alpha__ 34 #define __NR_listmount 568 35 #elif defined _MIPS_SIM 36 #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ 37 #define __NR_listmount 4458 38 #endif 39 #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ 40 #define __NR_listmount 6458 41 #endif 42 #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ 43 #define __NR_listmount 5458 44 #endif 45 #else 46 #define __NR_listmount 458 47 #endif 48 #endif 49 50 static inline int statmount(uint64_t mnt_id, uint64_t mnt_ns_id, uint32_t fd, 51 uint64_t mask, struct statmount *buf, size_t bufsize, 52 unsigned int flags) 53 { 54 struct mnt_id_req req = { 55 .size = MNT_ID_REQ_SIZE_VER0, 56 .param = mask, 57 }; 58 59 if (flags & STATMOUNT_BY_FD) { 60 req.size = MNT_ID_REQ_SIZE_VER1; 61 req.mnt_fd = fd; 62 } else { 63 req.mnt_id = mnt_id; 64 if (mnt_ns_id) { 65 req.size = MNT_ID_REQ_SIZE_VER1; 66 req.mnt_ns_id = mnt_ns_id; 67 } 68 } 69 70 return syscall(__NR_statmount, &req, buf, bufsize, flags); 71 } 72 73 static inline ssize_t listmount(uint64_t mnt_id, uint64_t mnt_ns_id, 74 uint64_t last_mnt_id, uint64_t list[], size_t num, 75 unsigned int flags) 76 { 77 struct mnt_id_req req = { 78 .size = MNT_ID_REQ_SIZE_VER0, 79 .mnt_id = mnt_id, 80 .param = last_mnt_id, 81 }; 82 83 if (mnt_ns_id) { 84 req.size = MNT_ID_REQ_SIZE_VER1; 85 req.mnt_ns_id = mnt_ns_id; 86 } 87 88 return syscall(__NR_listmount, &req, list, num, flags); 89 } 90 91 static inline struct statmount *statmount_alloc(uint64_t mnt_id, uint64_t mnt_ns_id, 92 uint64_t mask, unsigned int flags) 93 { 94 struct statmount *buf; 95 size_t bufsize = STATMOUNT_BUFSIZE; 96 int ret; 97 98 for (;;) { 99 buf = malloc(bufsize); 100 if (!buf) 101 return NULL; 102 103 ret = statmount(mnt_id, mnt_ns_id, 0, mask, buf, bufsize, flags); 104 if (ret == 0) 105 return buf; 106 107 free(buf); 108 if (errno != EOVERFLOW) 109 return NULL; 110 111 bufsize <<= 1; 112 } 113 } 114 115 static inline struct statmount *statmount_alloc_by_fd(int fd, uint64_t mask) 116 { 117 struct statmount *buf; 118 size_t bufsize = STATMOUNT_BUFSIZE; 119 int ret; 120 121 for (;;) { 122 buf = malloc(bufsize); 123 if (!buf) 124 return NULL; 125 126 ret = statmount(0, 0, fd, mask, buf, bufsize, STATMOUNT_BY_FD); 127 if (ret == 0) 128 return buf; 129 130 free(buf); 131 if (errno != EOVERFLOW) 132 return NULL; 133 134 bufsize <<= 1; 135 } 136 } 137 138 #endif /* __STATMOUNT_H */ 139