cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

stdio.h (5590B)


      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 <stdarg.h>
     11
     12#include "std.h"
     13#include "arch.h"
     14#include "errno.h"
     15#include "types.h"
     16#include "sys.h"
     17#include "stdlib.h"
     18#include "string.h"
     19
     20#ifndef EOF
     21#define EOF (-1)
     22#endif
     23
     24/* just define FILE as a non-empty type */
     25typedef struct FILE {
     26	char dummy[1];
     27} FILE;
     28
     29/* We define the 3 common stdio files as constant invalid pointers that
     30 * are easily recognized.
     31 */
     32static __attribute__((unused)) FILE* const stdin  = (FILE*)-3;
     33static __attribute__((unused)) FILE* const stdout = (FILE*)-2;
     34static __attribute__((unused)) FILE* const stderr = (FILE*)-1;
     35
     36/* getc(), fgetc(), getchar() */
     37
     38#define getc(stream) fgetc(stream)
     39
     40static __attribute__((unused))
     41int fgetc(FILE* stream)
     42{
     43	unsigned char ch;
     44	int fd;
     45
     46	if (stream < stdin || stream > stderr)
     47		return EOF;
     48
     49	fd = 3 + (long)stream;
     50
     51	if (read(fd, &ch, 1) <= 0)
     52		return EOF;
     53	return ch;
     54}
     55
     56static __attribute__((unused))
     57int getchar(void)
     58{
     59	return fgetc(stdin);
     60}
     61
     62
     63/* putc(), fputc(), putchar() */
     64
     65#define putc(c, stream) fputc(c, stream)
     66
     67static __attribute__((unused))
     68int fputc(int c, FILE* stream)
     69{
     70	unsigned char ch = c;
     71	int fd;
     72
     73	if (stream < stdin || stream > stderr)
     74		return EOF;
     75
     76	fd = 3 + (long)stream;
     77
     78	if (write(fd, &ch, 1) <= 0)
     79		return EOF;
     80	return ch;
     81}
     82
     83static __attribute__((unused))
     84int putchar(int c)
     85{
     86	return fputc(c, stdout);
     87}
     88
     89
     90/* fwrite(), puts(), fputs(). Note that puts() emits '\n' but not fputs(). */
     91
     92/* internal fwrite()-like function which only takes a size and returns 0 on
     93 * success or EOF on error. It automatically retries on short writes.
     94 */
     95static __attribute__((unused))
     96int _fwrite(const void *buf, size_t size, FILE *stream)
     97{
     98	ssize_t ret;
     99	int fd;
    100
    101	if (stream < stdin || stream > stderr)
    102		return EOF;
    103
    104	fd = 3 + (long)stream;
    105
    106	while (size) {
    107		ret = write(fd, buf, size);
    108		if (ret <= 0)
    109			return EOF;
    110		size -= ret;
    111		buf += ret;
    112	}
    113	return 0;
    114}
    115
    116static __attribute__((unused))
    117size_t fwrite(const void *s, size_t size, size_t nmemb, FILE *stream)
    118{
    119	size_t written;
    120
    121	for (written = 0; written < nmemb; written++) {
    122		if (_fwrite(s, size, stream) != 0)
    123			break;
    124		s += size;
    125	}
    126	return written;
    127}
    128
    129static __attribute__((unused))
    130int fputs(const char *s, FILE *stream)
    131{
    132	return _fwrite(s, strlen(s), stream);
    133}
    134
    135static __attribute__((unused))
    136int puts(const char *s)
    137{
    138	if (fputs(s, stdout) == EOF)
    139		return EOF;
    140	return putchar('\n');
    141}
    142
    143
    144/* fgets() */
    145static __attribute__((unused))
    146char *fgets(char *s, int size, FILE *stream)
    147{
    148	int ofs;
    149	int c;
    150
    151	for (ofs = 0; ofs + 1 < size;) {
    152		c = fgetc(stream);
    153		if (c == EOF)
    154			break;
    155		s[ofs++] = c;
    156		if (c == '\n')
    157			break;
    158	}
    159	if (ofs < size)
    160		s[ofs] = 0;
    161	return ofs ? s : NULL;
    162}
    163
    164
    165/* minimal vfprintf(). It supports the following formats:
    166 *  - %[l*]{d,u,c,x,p}
    167 *  - %s
    168 *  - unknown modifiers are ignored.
    169 */
    170static __attribute__((unused))
    171int vfprintf(FILE *stream, const char *fmt, va_list args)
    172{
    173	char escape, lpref, c;
    174	unsigned long long v;
    175	unsigned int written;
    176	size_t len, ofs;
    177	char tmpbuf[21];
    178	const char *outstr;
    179
    180	written = ofs = escape = lpref = 0;
    181	while (1) {
    182		c = fmt[ofs++];
    183
    184		if (escape) {
    185			/* we're in an escape sequence, ofs == 1 */
    186			escape = 0;
    187			if (c == 'c' || c == 'd' || c == 'u' || c == 'x' || c == 'p') {
    188				char *out = tmpbuf;
    189
    190				if (c == 'p')
    191					v = va_arg(args, unsigned long);
    192				else if (lpref) {
    193					if (lpref > 1)
    194						v = va_arg(args, unsigned long long);
    195					else
    196						v = va_arg(args, unsigned long);
    197				} else
    198					v = va_arg(args, unsigned int);
    199
    200				if (c == 'd') {
    201					/* sign-extend the value */
    202					if (lpref == 0)
    203						v = (long long)(int)v;
    204					else if (lpref == 1)
    205						v = (long long)(long)v;
    206				}
    207
    208				switch (c) {
    209				case 'c':
    210					out[0] = v;
    211					out[1] = 0;
    212					break;
    213				case 'd':
    214					i64toa_r(v, out);
    215					break;
    216				case 'u':
    217					u64toa_r(v, out);
    218					break;
    219				case 'p':
    220					*(out++) = '0';
    221					*(out++) = 'x';
    222					/* fall through */
    223				default: /* 'x' and 'p' above */
    224					u64toh_r(v, out);
    225					break;
    226				}
    227				outstr = tmpbuf;
    228			}
    229			else if (c == 's') {
    230				outstr = va_arg(args, char *);
    231				if (!outstr)
    232					outstr="(null)";
    233			}
    234			else if (c == '%') {
    235				/* queue it verbatim */
    236				continue;
    237			}
    238			else {
    239				/* modifiers or final 0 */
    240				if (c == 'l') {
    241					/* long format prefix, maintain the escape */
    242					lpref++;
    243				}
    244				escape = 1;
    245				goto do_escape;
    246			}
    247			len = strlen(outstr);
    248			goto flush_str;
    249		}
    250
    251		/* not an escape sequence */
    252		if (c == 0 || c == '%') {
    253			/* flush pending data on escape or end */
    254			escape = 1;
    255			lpref = 0;
    256			outstr = fmt;
    257			len = ofs - 1;
    258		flush_str:
    259			if (_fwrite(outstr, len, stream) != 0)
    260				break;
    261
    262			written += len;
    263		do_escape:
    264			if (c == 0)
    265				break;
    266			fmt += ofs;
    267			ofs = 0;
    268			continue;
    269		}
    270
    271		/* literal char, just queue it */
    272	}
    273	return written;
    274}
    275
    276static __attribute__((unused))
    277int fprintf(FILE *stream, const char *fmt, ...)
    278{
    279	va_list args;
    280	int ret;
    281
    282	va_start(args, fmt);
    283	ret = vfprintf(stream, fmt, args);
    284	va_end(args);
    285	return ret;
    286}
    287
    288static __attribute__((unused))
    289int printf(const char *fmt, ...)
    290{
    291	va_list args;
    292	int ret;
    293
    294	va_start(args, fmt);
    295	ret = vfprintf(stdout, fmt, args);
    296	va_end(args);
    297	return ret;
    298}
    299
    300static __attribute__((unused))
    301void perror(const char *msg)
    302{
    303	fprintf(stderr, "%s%serrno=%d\n", (msg && *msg) ? msg : "", (msg && *msg) ? ": " : "", errno);
    304}
    305
    306#endif /* _NOLIBC_STDIO_H */