]> git.saurik.com Git - apple/libc.git/blame - libdarwin/stdio.c
Libc-1353.60.8.tar.gz
[apple/libc.git] / libdarwin / stdio.c
CommitLineData
e9ce8d39 1/*
70ad1dc8 2 * Copyright (c) 2018 Apple Inc. All rights reserved.
e9ce8d39
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
70ad1dc8 5 *
734aad71
A
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
11 * file.
70ad1dc8 12 *
734aad71
A
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
e9ce8d39
A
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
734aad71
A
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.
70ad1dc8 20 *
e9ce8d39
A
21 * @APPLE_LICENSE_HEADER_END@
22 */
70ad1dc8 23#include "internal.h"
e9ce8d39 24
70ad1dc8 25#pragma mark API
507116e3
A
26int
27fcheck_np(FILE *f, size_t n, size_t expected)
28{
29 if (n == expected) {
30 return 0;
31 }
32 if (feof(f)) {
33 return EOF;
34 }
35 if (ferror(f)) {
36 return 1;
37 }
38 __builtin_unreachable();
39}
40
41os_fd_t
42dup_np(os_fd_t fd)
43{
44 os_fd_t dfd = -1;
45
46 while (true) {
47 dfd = dup(fd);
48
49 if (os_fd_valid(dfd)) {
50 break;
51 }
52
53 switch (errno) {
54 case EINTR:
55 break;
56 case EBADF:
57 os_crash("bad fd");
58 case EMFILE:
59 case ENFILE:
60 os_crash("failed to dup fd");
61 default:
62 os_crash("unhandled error: %s", symerror_np(errno));
63 }
64 }
65
66 return dfd;
67}
68
e1ee4b85
A
69os_fd_t
70claimfd_np(os_fd_t *fdp, const guardid_t *gdid, u_int gdflags)
71{
72 int ret = -1;
73 int fd = *fdp;
74
75 if (gdid) {
76 ret = change_fdguard_np(fd, NULL, 0, gdid, gdflags, NULL);
77 if (ret) {
78 os_crash("change_fdguard_np: %{darwin.errno}d", errno);
79 }
80 }
81
82 *fdp = -1;
83 return fd;
84}
85
86os_fd_t
87xferfd_np(os_fd_t *fdp, const guardid_t *gdid, u_int gdflags)
88{
89 int ret = -1;
90 int fd = *fdp;
91
92 ret = change_fdguard_np(fd, gdid, gdflags, NULL, 0, NULL);
93 if (ret) {
94 os_crash("change_fdguard_np: %{darwin.errno}d", errno);
95 }
96
97 *fdp = -1;
98 return fd;
99}
100
101void
102close_drop_np(os_fd_t *fdp, const guardid_t *gdid)
103{
104 int ret = -1;
105 int fd = *fdp;
106
107 if (gdid) {
108 ret = guarded_close_np(fd, gdid);
109 } else {
110 ret = close(fd);
111 }
112
113 posix_assert_zero(ret);
114 *fdp = -1;
115}
116
117void
118close_drop_optional_np(os_fd_t *fdp, const guardid_t *gdid)
119{
120 if (!os_fd_valid(*fdp)) {
121 return;
122 }
123 close_drop_np(fdp, gdid);
124}
125
ad3c9f2a 126size_t
70ad1dc8
A
127zsnprintf_np(char *buff, size_t len, const char *fmt, ...)
128{
129 int np = 0;
130 va_list ap;
131
132 va_start(ap, fmt);
133 np = vsnprintf(buff, len, fmt, ap);
134 va_end(ap);
135
136 if (np < 0) {
137 np = 0;
138 } else if ((size_t)np >= len) {
139 np = (int)len - 1;
140 }
141
142 return (size_t)np;
e9ce8d39 143}
507116e3
A
144
145void
146crfprintf_np(FILE *f, const char *fmt, ...)
147{
148 va_list ap;
149
150 va_start(ap, fmt);
151 vcrfprintf_np(f, fmt, ap);
152 va_end(ap);
153}
154
155void
156vcrfprintf_np(FILE *f, const char *fmt, va_list ap)
157{
158 vfprintf(f, fmt, ap);
159 fprintf(f, "\n");
160}
161
162void
163wfprintf_np(FILE *f, ssize_t initpad, size_t pad, size_t width,
164 const char *fmt, ...)
165{
166 va_list ap;
167
168 va_start(ap, fmt);
169 vwfprintf_np(f, initpad, pad, width, fmt, ap);
170 va_end(ap);
171}
172
173void
174vwfprintf_np(FILE *f, ssize_t initpad, size_t pad, size_t width,
175 const char *fmt, va_list ap)
176{
177 char *__os_free string = NULL;
178 char *__os_free working = NULL;
179 char *__os_free init_padding = NULL;
180 char *__os_free padding = NULL;
181 const char *curline = NULL;;
182 size_t left = 0;
183 size_t initpad_labs = (size_t)labs(initpad);
184 int ret = -1;
185
186 if (width && width <= pad) {
187 os_crash("width cannot be smaller than pad");
188 }
189 if (width && (initpad > 0) && width <= initpad_labs) {
190 os_crash("width cannot be smaller than initpad");
191 }
192 if (width && (initpad < 0) && width <= initpad_labs) {
193 os_crash("width cannot be smaller than negative initpad");
194 }
195
196 ret = vasprintf(&string, fmt, ap);
197 if (ret < 0 || !string) {
198 return;
199 }
200
201 left = (size_t)ret;
202 curline = string;
203
204 // The working buffer will always be large enough to handle any individual
205 // line. vasprintf(3) returns the number of characters printed not including
206 // the null terminator, so add space for that.
207 working = malloc(left + 1);
208 if (!working) {
209 return;
210 }
211
212 init_padding = malloc(initpad_labs + 1);
213 if (!init_padding) {
214 return;
215 }
216
217 if (initpad >= 0) {
218 memset(init_padding, ' ', initpad);
219 init_padding[initpad] = 0;
220 } else {
221 init_padding[0] = 0;
222 }
223
224 padding = malloc(pad + 1);
225 if (!padding) {
226 return;
227 }
228
229 memset(padding, ' ', pad);
230 padding[pad] = 0;
231
232 do {
233 size_t which_pad = pad;
234 char *which_padding = padding;
235 bool findspace = true;
236 size_t n2consume = 0;
237 char *breakchar = NULL;
238
239 if (curline == string) {
240 which_padding = init_padding;
241 which_pad = initpad_labs;
242 }
243
244 if (width == 0) {
245 // Width is unconstrained so just consume the entire string and
246 // indent any new lines within.
247 n2consume = left;
248 findspace = false;
249 } else {
250 n2consume = width - which_pad;
251 if (n2consume >= left) {
252 n2consume = left;
253 findspace = false;
254 }
255 }
256
257 strlcpy(working, curline, n2consume + 1);
258 breakchar = strchr(working, '\n');
259 if (!breakchar && findspace) {
260 // No new line within our maximally-constrained width of characters,
261 // so search for a space instead.
262 breakchar = strrchr(working, ' ');
263 }
264
265 if (breakchar) {
266 // Found something to break on, so nerf it and only consume the
267 // characters up until that break character.
268 *breakchar = 0;
269 n2consume = (size_t)(breakchar - working);
270 curline += n2consume + 1;
271 }
272
273 fprintf(f, "%s%s\n", which_padding, working);
274 left -= n2consume;
275 } while (left);
276}