xref: /xnu-12377.1.9/libsyscall/wrappers/statfs_ext.c (revision f6217f891ac0bb64f3d375211650a4c1ff8ca1ea)
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