]>
git.saurik.com Git - apple/libc.git/blob - libdarwin/bsd.c
30d915fad4e2fa1affcb47e68cf8c18f01dc94f4
2 * Copyright (c) 2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 #pragma mark Utilities
27 _sysctl_12809455(int mib
[4], size_t mib_cnt
, void *old
, size_t *old_len
,
28 void *new, size_t new_len
)
33 size_t *mylenp
= NULL
;
35 bool workaround_12809455
= false;
43 // sysctl(3) doesn't behave anything like its documentation leads you to
44 // believe. If the given buffer is too small to hold the requested data,
45 // what's supposed to happen is:
47 // - as much data as possible is copied into the buffer
48 // - the number of bytes copied is written to the len parameter
49 // - errno is set to ENOMEM
50 // - -1 is returned (to indicate that you should check errno)
52 // What actually happens:
54 // - no data is copied
55 // - len is set to zero
56 // - errno is undefined
59 // So... swing and a miss.
61 // Since it returns success in this case our only indication that something
62 // went wrong is if mylen is set to zero.
64 // So we do our best to sniff out the misbehavior and emulate sysctl(3)'s
65 // API contract until it's fixed.
67 // <rdar://problem/12809455>
69 if (old_len
&& *old_len
> 0) {
70 // We can only work around the bug if the passed-in length was non-zero.
71 workaround_12809455
= true;
75 ret
= sysctl(mib
, (u_int
)mib_cnt
, old
, mylenp
, new, new_len
);
77 if (workaround_12809455
&& old
&& ret
== 0 && mylen
== 0) {
81 #endif // RDAR_12809455
97 _strblk(const char *str
)
99 const char *cur
= str
;
101 while (*cur
&& !isblank(*cur
)) {
109 _get_boot_arg_value(const char *which
, char *where
, size_t max
)
111 // This is (very) loosely based on the implementation of
112 // PE_parse_boot_argn() (or at least the parts where I was able to easily
113 // decipher the policy).
121 error
= sysctlbyname_get_data_np("kern.bootargs", (void **)&buff
,
127 theone
= strstr(buff
, which
);
134 // Caller just wants to know whether the boot-arg exists.
138 equals
= strchr(theone
, '=');
139 if (!equals
|| isblank(equals
[1])) {
140 strlcpy(where
, "", max
);
142 char *nextsep
= NULL
;
143 char nextsep_old
= 0;
145 // Find the next separator and nerf it temporarily for the benefit of
146 // the underlying strcpy(3).
147 nextsep
= _strblk(theone
);
148 nextsep_old
= *nextsep
;
150 strlcpy(where
, &equals
[1], max
);
152 *nextsep
= nextsep_old
;
162 sysctl_get_data_np(int mib
[4], size_t mib_cnt
, void **buff
, size_t *buff_len
)
168 // We need to get the length of the parameter so we can allocate a buffer
169 // that's large enough.
170 error
= _sysctl_12809455(mib
, mib_cnt
, NULL
, &needed
, NULL
, 0);
175 mybuff
= malloc(needed
);
181 error
= _sysctl_12809455(mib
, mib_cnt
, mybuff
, &needed
, NULL
, 0);
183 // It's conceivable that some other process came along within this
184 // window and modified the variable to be even larger than we'd
185 // previously been told, but if that's the case, just give up.
200 sysctlbyname_get_data_np(const char *mibdesc
, void **buff
, size_t *buff_len
)
205 size_t mib_cnt
= countof(mib
);
207 ret
= sysctlnametomib(mibdesc
, mib
, &mib_cnt
);
213 error
= sysctl_get_data_np(mib
, mib_cnt
, buff
, buff_len
);
220 os_parse_boot_arg_int(const char *which
, int64_t *where
)
227 found
= _get_boot_arg_value(which
, buff
, sizeof(buff
));
228 if (!found
|| !where
) {
232 // A base of zero handles bases 8, 10, and 16.
233 val
= strtoll(buff
, &endptr
, 0);
237 // The boot-arg value was invalid, so say we didn't find it.
246 os_parse_boot_arg_string(const char *which
, char *where
, size_t maxlen
)
248 return _get_boot_arg_value(which
, where
, maxlen
);