1*f6217f89SApple OSS Distributions /*
2*f6217f89SApple OSS Distributions * Copyright (c) 2024 Apple Inc. All rights reserved.
3*f6217f89SApple OSS Distributions *
4*f6217f89SApple OSS Distributions * @APPLE_LICENSE_HEADER_START@
5*f6217f89SApple OSS Distributions *
6*f6217f89SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*f6217f89SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*f6217f89SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*f6217f89SApple OSS Distributions * compliance with the License. Please obtain a copy of the License at
10*f6217f89SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this
11*f6217f89SApple OSS Distributions * file.
12*f6217f89SApple OSS Distributions *
13*f6217f89SApple OSS Distributions * The Original Code and all software distributed under the License are
14*f6217f89SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15*f6217f89SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16*f6217f89SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17*f6217f89SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18*f6217f89SApple OSS Distributions * Please see the License for the specific language governing rights and
19*f6217f89SApple OSS Distributions * limitations under the License.
20*f6217f89SApple OSS Distributions *
21*f6217f89SApple OSS Distributions * @APPLE_LICENSE_HEADER_END@
22*f6217f89SApple OSS Distributions */
23*f6217f89SApple OSS Distributions
24*f6217f89SApple OSS Distributions #include <errno.h>
25*f6217f89SApple OSS Distributions #include <stdlib.h>
26*f6217f89SApple OSS Distributions #include <unistd.h>
27*f6217f89SApple OSS Distributions #include <strings.h>
28*f6217f89SApple OSS Distributions #include <sys/attr.h>
29*f6217f89SApple OSS Distributions #include <sys/param.h>
30*f6217f89SApple OSS Distributions #include <sys/mount.h>
31*f6217f89SApple OSS Distributions
32*f6217f89SApple OSS Distributions static int
__statfs_ext_default(const char * path,int fd,struct statfs * buf)33*f6217f89SApple OSS Distributions __statfs_ext_default(const char *path, int fd, struct statfs *buf)
34*f6217f89SApple OSS Distributions {
35*f6217f89SApple OSS Distributions int ret = 0;
36*f6217f89SApple OSS Distributions
37*f6217f89SApple OSS Distributions if (path) {
38*f6217f89SApple OSS Distributions ret = statfs(path, buf);
39*f6217f89SApple OSS Distributions } else {
40*f6217f89SApple OSS Distributions ret = fstatfs(fd, buf);
41*f6217f89SApple OSS Distributions }
42*f6217f89SApple OSS Distributions
43*f6217f89SApple OSS Distributions return ret;
44*f6217f89SApple OSS Distributions }
45*f6217f89SApple OSS Distributions
46*f6217f89SApple OSS Distributions static int
__statfs_ext_noblock(const char * path,int fd,struct statfs * buf)47*f6217f89SApple OSS Distributions __statfs_ext_noblock(const char *path, int fd, struct statfs *buf)
48*f6217f89SApple OSS Distributions {
49*f6217f89SApple OSS Distributions int ret = 0;
50*f6217f89SApple OSS Distributions char *ptr;
51*f6217f89SApple OSS Distributions
52*f6217f89SApple OSS Distributions struct {
53*f6217f89SApple OSS Distributions uint32_t size;
54*f6217f89SApple OSS Distributions attribute_set_t f_attrs;
55*f6217f89SApple OSS Distributions fsid_t f_fsid;
56*f6217f89SApple OSS Distributions uint32_t f_type;
57*f6217f89SApple OSS Distributions attrreference_t f_mntonname;
58*f6217f89SApple OSS Distributions uint32_t f_flags;
59*f6217f89SApple OSS Distributions attrreference_t f_mntfromname;
60*f6217f89SApple OSS Distributions uint32_t f_flags_ext;
61*f6217f89SApple OSS Distributions attrreference_t f_fstypename;
62*f6217f89SApple OSS Distributions uint32_t f_fssubtype;
63*f6217f89SApple OSS Distributions uid_t f_owner;
64*f6217f89SApple OSS Distributions char f_mntonname_buf[MAXPATHLEN];
65*f6217f89SApple OSS Distributions char f_mntfromname_buf[MAXPATHLEN];
66*f6217f89SApple OSS Distributions char f_fstypename_buf[MFSTYPENAMELEN];
67*f6217f89SApple OSS Distributions } __attribute__((aligned(4), packed)) *attrbuf;
68*f6217f89SApple OSS Distributions
69*f6217f89SApple OSS Distributions struct attrlist al = {
70*f6217f89SApple OSS Distributions .bitmapcount = ATTR_BIT_MAP_COUNT,
71*f6217f89SApple OSS Distributions .commonattr = ATTR_CMN_FSID | ATTR_CMN_RETURNED_ATTRS,
72*f6217f89SApple OSS Distributions .volattr = ATTR_VOL_INFO | ATTR_VOL_FSTYPE | ATTR_VOL_MOUNTPOINT |
73*f6217f89SApple OSS Distributions ATTR_VOL_MOUNTFLAGS | ATTR_VOL_MOUNTEDDEVICE | ATTR_VOL_FSTYPENAME |
74*f6217f89SApple OSS Distributions ATTR_VOL_FSSUBTYPE | ATTR_VOL_MOUNTEXTFLAGS | ATTR_VOL_OWNER,
75*f6217f89SApple OSS Distributions };
76*f6217f89SApple OSS Distributions
77*f6217f89SApple OSS Distributions attrbuf = malloc(sizeof(*attrbuf));
78*f6217f89SApple OSS Distributions if (attrbuf == NULL) {
79*f6217f89SApple OSS Distributions errno = ENOMEM;
80*f6217f89SApple OSS Distributions return -1;
81*f6217f89SApple OSS Distributions }
82*f6217f89SApple OSS Distributions bzero(attrbuf, sizeof(*attrbuf));
83*f6217f89SApple OSS Distributions
84*f6217f89SApple OSS Distributions if (path) {
85*f6217f89SApple OSS Distributions ret = getattrlist(path, &al, attrbuf, sizeof(*attrbuf), FSOPT_NOFOLLOW | FSOPT_RETURN_REALDEV);
86*f6217f89SApple OSS Distributions } else {
87*f6217f89SApple OSS Distributions ret = fgetattrlist(fd, &al, attrbuf, sizeof(*attrbuf), FSOPT_RETURN_REALDEV);
88*f6217f89SApple OSS Distributions }
89*f6217f89SApple OSS Distributions
90*f6217f89SApple OSS Distributions if (ret < 0) {
91*f6217f89SApple OSS Distributions goto out;
92*f6217f89SApple OSS Distributions }
93*f6217f89SApple OSS Distributions
94*f6217f89SApple OSS Distributions /* Update user structure */
95*f6217f89SApple OSS Distributions if (attrbuf->f_attrs.commonattr & ATTR_CMN_FSID) {
96*f6217f89SApple OSS Distributions buf->f_fsid = attrbuf->f_fsid;
97*f6217f89SApple OSS Distributions }
98*f6217f89SApple OSS Distributions if (attrbuf->f_attrs.volattr & ATTR_VOL_OWNER) {
99*f6217f89SApple OSS Distributions buf->f_owner = attrbuf->f_owner;
100*f6217f89SApple OSS Distributions }
101*f6217f89SApple OSS Distributions if (attrbuf->f_attrs.volattr & ATTR_VOL_FSTYPE) {
102*f6217f89SApple OSS Distributions buf->f_type = attrbuf->f_type;
103*f6217f89SApple OSS Distributions }
104*f6217f89SApple OSS Distributions if (attrbuf->f_attrs.volattr & ATTR_VOL_MOUNTFLAGS) {
105*f6217f89SApple OSS Distributions buf->f_flags = attrbuf->f_flags;
106*f6217f89SApple OSS Distributions }
107*f6217f89SApple OSS Distributions if (attrbuf->f_attrs.volattr & ATTR_VOL_FSSUBTYPE) {
108*f6217f89SApple OSS Distributions buf->f_fssubtype = attrbuf->f_fssubtype;
109*f6217f89SApple OSS Distributions }
110*f6217f89SApple OSS Distributions if (attrbuf->f_attrs.volattr & ATTR_VOL_FSTYPENAME) {
111*f6217f89SApple OSS Distributions ptr = (char *)&attrbuf->f_fstypename + attrbuf->f_fstypename.attr_dataoffset;
112*f6217f89SApple OSS Distributions strlcpy(buf->f_fstypename, ptr, sizeof(buf->f_fstypename));
113*f6217f89SApple OSS Distributions }
114*f6217f89SApple OSS Distributions if (attrbuf->f_attrs.volattr & ATTR_VOL_MOUNTPOINT) {
115*f6217f89SApple OSS Distributions ptr = (char *)&attrbuf->f_mntonname + attrbuf->f_mntonname.attr_dataoffset;
116*f6217f89SApple OSS Distributions strlcpy(buf->f_mntonname, ptr, sizeof(buf->f_mntonname));
117*f6217f89SApple OSS Distributions }
118*f6217f89SApple OSS Distributions if (attrbuf->f_attrs.volattr & ATTR_VOL_MOUNTEDDEVICE) {
119*f6217f89SApple OSS Distributions ptr = (char *)&attrbuf->f_mntfromname + attrbuf->f_mntfromname.attr_dataoffset;
120*f6217f89SApple OSS Distributions strlcpy(buf->f_mntfromname, ptr, sizeof(buf->f_mntfromname));
121*f6217f89SApple OSS Distributions }
122*f6217f89SApple OSS Distributions if (attrbuf->f_attrs.volattr & ATTR_VOL_MOUNTEXTFLAGS) {
123*f6217f89SApple OSS Distributions buf->f_flags_ext = attrbuf->f_flags_ext;
124*f6217f89SApple OSS Distributions }
125*f6217f89SApple OSS Distributions
126*f6217f89SApple OSS Distributions out:
127*f6217f89SApple OSS Distributions free(attrbuf);
128*f6217f89SApple OSS Distributions return ret;
129*f6217f89SApple OSS Distributions }
130*f6217f89SApple OSS Distributions
131*f6217f89SApple OSS Distributions static int
__statfs_ext_impl(const char * path,int fd,struct statfs * buf,int flags)132*f6217f89SApple OSS Distributions __statfs_ext_impl(const char *path, int fd, struct statfs *buf, int flags)
133*f6217f89SApple OSS Distributions {
134*f6217f89SApple OSS Distributions int ret = 0;
135*f6217f89SApple OSS Distributions
136*f6217f89SApple OSS Distributions bzero(buf, sizeof(struct statfs));
137*f6217f89SApple OSS Distributions
138*f6217f89SApple OSS Distributions /* Check for invalid flags */
139*f6217f89SApple OSS Distributions if (flags & ~(STATFS_EXT_NOBLOCK)) {
140*f6217f89SApple OSS Distributions errno = EINVAL;
141*f6217f89SApple OSS Distributions return -1;
142*f6217f89SApple OSS Distributions }
143*f6217f89SApple OSS Distributions
144*f6217f89SApple OSS Distributions /* Retrieve filesystem statistics with extended options */
145*f6217f89SApple OSS Distributions if (flags & STATFS_EXT_NOBLOCK) {
146*f6217f89SApple OSS Distributions ret = __statfs_ext_noblock(path, fd, buf);
147*f6217f89SApple OSS Distributions }
148*f6217f89SApple OSS Distributions
149*f6217f89SApple OSS Distributions /*
150*f6217f89SApple OSS Distributions * Fall back to statfs()/fstatfs() if:
151*f6217f89SApple OSS Distributions * 1. No options are provided.
152*f6217f89SApple OSS Distributions * 2. __statfs_ext_noblock() returns EINVAL.
153*f6217f89SApple OSS Distributions */
154*f6217f89SApple OSS Distributions if ((flags == 0) || (ret == -1 && errno == EINVAL)) {
155*f6217f89SApple OSS Distributions ret = __statfs_ext_default(path, fd, buf);
156*f6217f89SApple OSS Distributions }
157*f6217f89SApple OSS Distributions
158*f6217f89SApple OSS Distributions return ret;
159*f6217f89SApple OSS Distributions }
160*f6217f89SApple OSS Distributions
161*f6217f89SApple OSS Distributions int
fstatfs_ext(int fd,struct statfs * buf,int flags)162*f6217f89SApple OSS Distributions fstatfs_ext(int fd, struct statfs *buf, int flags)
163*f6217f89SApple OSS Distributions {
164*f6217f89SApple OSS Distributions /* fstatfs() sanity checks */
165*f6217f89SApple OSS Distributions if (fd < 0) {
166*f6217f89SApple OSS Distributions errno = EBADF;
167*f6217f89SApple OSS Distributions return -1;
168*f6217f89SApple OSS Distributions }
169*f6217f89SApple OSS Distributions if (buf == NULL) {
170*f6217f89SApple OSS Distributions errno = EFAULT;
171*f6217f89SApple OSS Distributions return -1;
172*f6217f89SApple OSS Distributions }
173*f6217f89SApple OSS Distributions
174*f6217f89SApple OSS Distributions return __statfs_ext_impl(NULL, fd, buf, flags);
175*f6217f89SApple OSS Distributions }
176*f6217f89SApple OSS Distributions
177*f6217f89SApple OSS Distributions int
statfs_ext(const char * path,struct statfs * buf,int flags)178*f6217f89SApple OSS Distributions statfs_ext(const char *path, struct statfs *buf, int flags)
179*f6217f89SApple OSS Distributions {
180*f6217f89SApple OSS Distributions /* statfs() sanity checks */
181*f6217f89SApple OSS Distributions if (path == NULL) {
182*f6217f89SApple OSS Distributions errno = EFAULT;
183*f6217f89SApple OSS Distributions return -1;
184*f6217f89SApple OSS Distributions }
185*f6217f89SApple OSS Distributions if (buf == NULL) {
186*f6217f89SApple OSS Distributions errno = EFAULT;
187*f6217f89SApple OSS Distributions return -1;
188*f6217f89SApple OSS Distributions }
189*f6217f89SApple OSS Distributions
190*f6217f89SApple OSS Distributions return __statfs_ext_impl(path, -1, buf, flags);
191*f6217f89SApple OSS Distributions }
192