1/*-
2 * Copyright (c) 2014 Pedro Souza <pedrosouza@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28#include "lstd.h"
29#include "math.h"
30
31#ifdef LOADER_VERIEXEC
32#include <verify_file.h>
33#endif
34
35FILE *
36fopen(const char *filename, const char *mode)
37{
38	struct stat	st;
39	int		fd, m, o;
40	FILE		*f;
41
42	if (mode == NULL)
43		return NULL;
44
45	switch (*mode++) {
46	case 'r':	/* open for reading */
47		m = O_RDONLY;
48		o = 0;
49		break;
50
51	case 'w':	/* open for writing */
52		m = O_WRONLY;
53		/* These are not actually implemented yet */
54		o = O_CREAT | O_TRUNC;
55		break;
56
57	default:	/* illegal mode */
58		return (NULL);
59	}
60
61	if (*mode == '+')
62		m = O_RDWR;
63
64	fd = open(filename, m | o);
65	if (fd < 0)
66		return NULL;
67
68	f = malloc(sizeof(FILE));
69	if (f == NULL) {
70		close(fd);
71		return NULL;
72	}
73
74	if (fstat(fd, &st) != 0) {
75		free(f);
76		close(fd);
77		return (NULL);
78	}
79
80#ifdef LOADER_VERIEXEC
81	/* only regular files and only reading makes sense */
82	if (S_ISREG(st.st_mode) && !(m & O_WRONLY)) {
83		if (verify_file(fd, filename, 0, VE_GUESS, __func__) < 0) {
84			free(f);
85			close(fd);
86			return (NULL);
87		}
88	}
89#endif
90
91	f->fd = fd;
92	f->offset = 0;
93	f->size = st.st_size;
94
95	return (f);
96}
97
98
99FILE *
100freopen(const char *filename, const char *mode, FILE *stream)
101{
102	fclose(stream);
103	return (fopen(filename, mode));
104}
105
106size_t
107fread(void *ptr, size_t size, size_t count, FILE *stream)
108{
109	size_t r;
110
111	if (stream == NULL)
112		return 0;
113	r = (size_t)read(stream->fd, ptr, size * count);
114	stream->offset += r;
115
116	return (r);
117}
118
119size_t
120fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
121{
122	ssize_t w;
123
124	if (stream == NULL || ptr == NULL)
125		return (0);
126	w = write(stream->fd, ptr, size * count);
127	if (w == -1)
128		return (0);
129
130	stream->offset += w;
131	return ((size_t)w);
132}
133
134int
135fclose(FILE *stream)
136{
137	if (stream == NULL)
138		return EOF;
139	close(stream->fd);
140	free(stream);
141
142	return (0);
143}
144
145int
146ferror(FILE *stream)
147{
148
149	return (stream == NULL || stream->fd < 0);
150}
151
152int
153feof(FILE *stream)
154{
155
156	if (stream == NULL)
157		return 1;
158
159	return (stream->offset >= stream->size);
160}
161
162int
163getc(FILE *stream)
164{
165	char	ch;
166	size_t	r;
167
168	if (stream == NULL)
169		return EOF;
170	r = read(stream->fd, &ch, 1);
171	if (r == 1)
172		return ch;
173	return EOF;
174}
175
176DIR *
177opendir(const char *name)
178{
179	DIR *dp;
180	int fd;
181
182	fd = open(name, O_RDONLY);
183	if (fd < 0)
184		return NULL;
185	dp = fdopendir(fd);
186	if (dp == NULL)
187		close(fd);
188	return dp;
189}
190
191DIR *
192fdopendir(int fd)
193{
194	DIR *dp;
195
196	dp = malloc(sizeof(*dp));
197	if (dp == NULL)
198		return NULL;
199	dp->fd = fd;
200	return dp;
201}
202
203int
204closedir(DIR *dp)
205{
206	close(dp->fd);
207	dp->fd = -1;
208	free(dp);
209	return 0;
210}
211
212void
213luai_writestring(const char *s, int i)
214{
215
216	while (i-- > 0)
217		putchar(*s++);
218}
219
220/*
221 * These routines from here on down are to implement the lua math
222 * library, but that's not presently included by default. They are
223 * little more than placeholders to allow compilation due to linkage
224 * issues with upstream Lua.
225 */
226
227int64_t
228lstd_pow(int64_t x, int64_t y)
229{
230	int64_t rv = 1;
231
232	if (y < 0)
233		return 0;
234	rv = x;
235	while (--y)
236		rv *= x;
237
238	return rv;
239}
240
241int64_t
242lstd_floor(int64_t x)
243{
244
245	return (x);
246}
247
248int64_t
249lstd_fmod(int64_t a, int64_t b)
250{
251
252	return (a % b);
253}
254
255/*
256 * This can't be implemented, so maybe it should just abort.
257 */
258int64_t
259lstd_frexp(int64_t a, int *y)
260{
261	*y = 0;
262
263	return 0;
264}
265