~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/include/nolibc/stdio.h

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
  2 /*
  3  * minimal stdio function definitions for NOLIBC
  4  * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
  5  */
  6 
  7 #ifndef _NOLIBC_STDIO_H
  8 #define _NOLIBC_STDIO_H
  9 
 10 #include "std.h"
 11 #include "arch.h"
 12 #include "errno.h"
 13 #include "types.h"
 14 #include "sys.h"
 15 #include "stdarg.h"
 16 #include "stdlib.h"
 17 #include "string.h"
 18 
 19 #ifndef EOF
 20 #define EOF (-1)
 21 #endif
 22 
 23 /* Buffering mode used by setvbuf.  */
 24 #define _IOFBF 0        /* Fully buffered. */
 25 #define _IOLBF 1        /* Line buffered. */
 26 #define _IONBF 2        /* No buffering. */
 27 
 28 /* just define FILE as a non-empty type. The value of the pointer gives
 29  * the FD: FILE=~fd for fd>=0 or NULL for fd<0. This way positive FILE
 30  * are immediately identified as abnormal entries (i.e. possible copies
 31  * of valid pointers to something else).
 32  */
 33 typedef struct FILE {
 34         char dummy[1];
 35 } FILE;
 36 
 37 static __attribute__((unused)) FILE* const stdin  = (FILE*)(intptr_t)~STDIN_FILENO;
 38 static __attribute__((unused)) FILE* const stdout = (FILE*)(intptr_t)~STDOUT_FILENO;
 39 static __attribute__((unused)) FILE* const stderr = (FILE*)(intptr_t)~STDERR_FILENO;
 40 
 41 /* provides a FILE* equivalent of fd. The mode is ignored. */
 42 static __attribute__((unused))
 43 FILE *fdopen(int fd, const char *mode __attribute__((unused)))
 44 {
 45         if (fd < 0) {
 46                 SET_ERRNO(EBADF);
 47                 return NULL;
 48         }
 49         return (FILE*)(intptr_t)~fd;
 50 }
 51 
 52 /* provides the fd of stream. */
 53 static __attribute__((unused))
 54 int fileno(FILE *stream)
 55 {
 56         intptr_t i = (intptr_t)stream;
 57 
 58         if (i >= 0) {
 59                 SET_ERRNO(EBADF);
 60                 return -1;
 61         }
 62         return ~i;
 63 }
 64 
 65 /* flush a stream. */
 66 static __attribute__((unused))
 67 int fflush(FILE *stream)
 68 {
 69         intptr_t i = (intptr_t)stream;
 70 
 71         /* NULL is valid here. */
 72         if (i > 0) {
 73                 SET_ERRNO(EBADF);
 74                 return -1;
 75         }
 76 
 77         /* Don't do anything, nolibc does not support buffering. */
 78         return 0;
 79 }
 80 
 81 /* flush a stream. */
 82 static __attribute__((unused))
 83 int fclose(FILE *stream)
 84 {
 85         intptr_t i = (intptr_t)stream;
 86 
 87         if (i >= 0) {
 88                 SET_ERRNO(EBADF);
 89                 return -1;
 90         }
 91 
 92         if (close(~i))
 93                 return EOF;
 94 
 95         return 0;
 96 }
 97 
 98 /* getc(), fgetc(), getchar() */
 99 
100 #define getc(stream) fgetc(stream)
101 
102 static __attribute__((unused))
103 int fgetc(FILE* stream)
104 {
105         unsigned char ch;
106 
107         if (read(fileno(stream), &ch, 1) <= 0)
108                 return EOF;
109         return ch;
110 }
111 
112 static __attribute__((unused))
113 int getchar(void)
114 {
115         return fgetc(stdin);
116 }
117 
118 
119 /* putc(), fputc(), putchar() */
120 
121 #define putc(c, stream) fputc(c, stream)
122 
123 static __attribute__((unused))
124 int fputc(int c, FILE* stream)
125 {
126         unsigned char ch = c;
127 
128         if (write(fileno(stream), &ch, 1) <= 0)
129                 return EOF;
130         return ch;
131 }
132 
133 static __attribute__((unused))
134 int putchar(int c)
135 {
136         return fputc(c, stdout);
137 }
138 
139 
140 /* fwrite(), puts(), fputs(). Note that puts() emits '\n' but not fputs(). */
141 
142 /* internal fwrite()-like function which only takes a size and returns 0 on
143  * success or EOF on error. It automatically retries on short writes.
144  */
145 static __attribute__((unused))
146 int _fwrite(const void *buf, size_t size, FILE *stream)
147 {
148         ssize_t ret;
149         int fd = fileno(stream);
150 
151         while (size) {
152                 ret = write(fd, buf, size);
153                 if (ret <= 0)
154                         return EOF;
155                 size -= ret;
156                 buf += ret;
157         }
158         return 0;
159 }
160 
161 static __attribute__((unused))
162 size_t fwrite(const void *s, size_t size, size_t nmemb, FILE *stream)
163 {
164         size_t written;
165 
166         for (written = 0; written < nmemb; written++) {
167                 if (_fwrite(s, size, stream) != 0)
168                         break;
169                 s += size;
170         }
171         return written;
172 }
173 
174 static __attribute__((unused))
175 int fputs(const char *s, FILE *stream)
176 {
177         return _fwrite(s, strlen(s), stream);
178 }
179 
180 static __attribute__((unused))
181 int puts(const char *s)
182 {
183         if (fputs(s, stdout) == EOF)
184                 return EOF;
185         return putchar('\n');
186 }
187 
188 
189 /* fgets() */
190 static __attribute__((unused))
191 char *fgets(char *s, int size, FILE *stream)
192 {
193         int ofs;
194         int c;
195 
196         for (ofs = 0; ofs + 1 < size;) {
197                 c = fgetc(stream);
198                 if (c == EOF)
199                         break;
200                 s[ofs++] = c;
201                 if (c == '\n')
202                         break;
203         }
204         if (ofs < size)
205                 s[ofs] = 0;
206         return ofs ? s : NULL;
207 }
208 
209 
210 /* minimal vfprintf(). It supports the following formats:
211  *  - %[l*]{d,u,c,x,p}
212  *  - %s
213  *  - unknown modifiers are ignored.
214  */
215 static __attribute__((unused, format(printf, 2, 0)))
216 int vfprintf(FILE *stream, const char *fmt, va_list args)
217 {
218         char escape, lpref, c;
219         unsigned long long v;
220         unsigned int written;
221         size_t len, ofs;
222         char tmpbuf[21];
223         const char *outstr;
224 
225         written = ofs = escape = lpref = 0;
226         while (1) {
227                 c = fmt[ofs++];
228 
229                 if (escape) {
230                         /* we're in an escape sequence, ofs == 1 */
231                         escape = 0;
232                         if (c == 'c' || c == 'd' || c == 'u' || c == 'x' || c == 'p') {
233                                 char *out = tmpbuf;
234 
235                                 if (c == 'p')
236                                         v = va_arg(args, unsigned long);
237                                 else if (lpref) {
238                                         if (lpref > 1)
239                                                 v = va_arg(args, unsigned long long);
240                                         else
241                                                 v = va_arg(args, unsigned long);
242                                 } else
243                                         v = va_arg(args, unsigned int);
244 
245                                 if (c == 'd') {
246                                         /* sign-extend the value */
247                                         if (lpref == 0)
248                                                 v = (long long)(int)v;
249                                         else if (lpref == 1)
250                                                 v = (long long)(long)v;
251                                 }
252 
253                                 switch (c) {
254                                 case 'c':
255                                         out[0] = v;
256                                         out[1] = 0;
257                                         break;
258                                 case 'd':
259                                         i64toa_r(v, out);
260                                         break;
261                                 case 'u':
262                                         u64toa_r(v, out);
263                                         break;
264                                 case 'p':
265                                         *(out++) = '';
266                                         *(out++) = 'x';
267                                         /* fall through */
268                                 default: /* 'x' and 'p' above */
269                                         u64toh_r(v, out);
270                                         break;
271                                 }
272                                 outstr = tmpbuf;
273                         }
274                         else if (c == 's') {
275                                 outstr = va_arg(args, char *);
276                                 if (!outstr)
277                                         outstr="(null)";
278                         }
279                         else if (c == '%') {
280                                 /* queue it verbatim */
281                                 continue;
282                         }
283                         else {
284                                 /* modifiers or final 0 */
285                                 if (c == 'l') {
286                                         /* long format prefix, maintain the escape */
287                                         lpref++;
288                                 }
289                                 escape = 1;
290                                 goto do_escape;
291                         }
292                         len = strlen(outstr);
293                         goto flush_str;
294                 }
295 
296                 /* not an escape sequence */
297                 if (c == 0 || c == '%') {
298                         /* flush pending data on escape or end */
299                         escape = 1;
300                         lpref = 0;
301                         outstr = fmt;
302                         len = ofs - 1;
303                 flush_str:
304                         if (_fwrite(outstr, len, stream) != 0)
305                                 break;
306 
307                         written += len;
308                 do_escape:
309                         if (c == 0)
310                                 break;
311                         fmt += ofs;
312                         ofs = 0;
313                         continue;
314                 }
315 
316                 /* literal char, just queue it */
317         }
318         return written;
319 }
320 
321 static __attribute__((unused, format(printf, 1, 0)))
322 int vprintf(const char *fmt, va_list args)
323 {
324         return vfprintf(stdout, fmt, args);
325 }
326 
327 static __attribute__((unused, format(printf, 2, 3)))
328 int fprintf(FILE *stream, const char *fmt, ...)
329 {
330         va_list args;
331         int ret;
332 
333         va_start(args, fmt);
334         ret = vfprintf(stream, fmt, args);
335         va_end(args);
336         return ret;
337 }
338 
339 static __attribute__((unused, format(printf, 1, 2)))
340 int printf(const char *fmt, ...)
341 {
342         va_list args;
343         int ret;
344 
345         va_start(args, fmt);
346         ret = vfprintf(stdout, fmt, args);
347         va_end(args);
348         return ret;
349 }
350 
351 static __attribute__((unused))
352 void perror(const char *msg)
353 {
354         fprintf(stderr, "%s%serrno=%d\n", (msg && *msg) ? msg : "", (msg && *msg) ? ": " : "", errno);
355 }
356 
357 static __attribute__((unused))
358 int setvbuf(FILE *stream __attribute__((unused)),
359             char *buf __attribute__((unused)),
360             int mode,
361             size_t size __attribute__((unused)))
362 {
363         /*
364          * nolibc does not support buffering so this is a nop. Just check mode
365          * is valid as required by the spec.
366          */
367         switch (mode) {
368         case _IOFBF:
369         case _IOLBF:
370         case _IONBF:
371                 break;
372         default:
373                 return EOF;
374         }
375 
376         return 0;
377 }
378 
379 static __attribute__((unused))
380 const char *strerror(int errno)
381 {
382         static char buf[18] = "errno=";
383 
384         i64toa_r(errno, &buf[6]);
385 
386         return buf;
387 }
388 
389 /* make sure to include all global symbols */
390 #include "nolibc.h"
391 
392 #endif /* _NOLIBC_STDIO_H */
393 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php