Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/ficl/fileaccess.c
34677 views
1
2
#include <errno.h>
3
#include <stdlib.h>
4
#include <stdio.h>
5
#include <string.h>
6
#include <ctype.h>
7
#include <sys/stat.h>
8
#include "ficl.h"
9
10
#if FICL_WANT_FILE
11
/*
12
**
13
** fileaccess.c
14
**
15
** Implements all of the File Access word set that can be implemented in portable C.
16
**
17
*/
18
19
static void pushIor(FICL_VM *pVM, int success)
20
{
21
int ior;
22
if (success)
23
ior = 0;
24
else
25
ior = errno;
26
stackPushINT(pVM->pStack, ior);
27
}
28
29
30
31
static void ficlFopen(FICL_VM *pVM, char *writeMode) /* ( c-addr u fam -- fileid ior ) */
32
{
33
int fam = stackPopINT(pVM->pStack);
34
int length = stackPopINT(pVM->pStack);
35
void *address = (void *)stackPopPtr(pVM->pStack);
36
char mode[4];
37
FILE *f;
38
39
char *filename = (char *)alloca(length + 1);
40
memcpy(filename, address, length);
41
filename[length] = 0;
42
43
*mode = 0;
44
45
switch (FICL_FAM_OPEN_MODE(fam))
46
{
47
case 0:
48
stackPushPtr(pVM->pStack, NULL);
49
stackPushINT(pVM->pStack, EINVAL);
50
return;
51
case FICL_FAM_READ:
52
strcat(mode, "r");
53
break;
54
case FICL_FAM_WRITE:
55
strcat(mode, writeMode);
56
break;
57
case FICL_FAM_READ | FICL_FAM_WRITE:
58
strcat(mode, writeMode);
59
strcat(mode, "+");
60
break;
61
}
62
63
strcat(mode, (fam & FICL_FAM_BINARY) ? "b" : "t");
64
65
f = fopen(filename, mode);
66
if (f == NULL)
67
stackPushPtr(pVM->pStack, NULL);
68
else
69
#ifdef LOADER_VERIEXEC
70
if (*mode == 'r' &&
71
verify_file(fileno(f), filename, 0, VE_GUESS, __func__) < 0) {
72
fclose(f);
73
stackPushPtr(pVM->pStack, NULL);
74
} else
75
#endif
76
{
77
ficlFILE *ff = (ficlFILE *)malloc(sizeof(ficlFILE));
78
strcpy(ff->filename, filename);
79
ff->f = f;
80
stackPushPtr(pVM->pStack, ff);
81
82
fseek(f, 0, SEEK_SET);
83
}
84
pushIor(pVM, f != NULL);
85
}
86
87
88
89
static void ficlOpenFile(FICL_VM *pVM) /* ( c-addr u fam -- fileid ior ) */
90
{
91
ficlFopen(pVM, "a");
92
}
93
94
95
static void ficlCreateFile(FICL_VM *pVM) /* ( c-addr u fam -- fileid ior ) */
96
{
97
ficlFopen(pVM, "w");
98
}
99
100
101
static int closeFiclFILE(ficlFILE *ff) /* ( fileid -- ior ) */
102
{
103
FILE *f = ff->f;
104
free(ff);
105
return !fclose(f);
106
}
107
108
static void ficlCloseFile(FICL_VM *pVM) /* ( fileid -- ior ) */
109
{
110
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
111
pushIor(pVM, closeFiclFILE(ff));
112
}
113
114
static void ficlDeleteFile(FICL_VM *pVM) /* ( c-addr u -- ior ) */
115
{
116
int length = stackPopINT(pVM->pStack);
117
void *address = (void *)stackPopPtr(pVM->pStack);
118
119
char *filename = (char *)alloca(length + 1);
120
memcpy(filename, address, length);
121
filename[length] = 0;
122
123
pushIor(pVM, !unlink(filename));
124
}
125
126
static void ficlRenameFile(FICL_VM *pVM) /* ( c-addr1 u1 c-addr2 u2 -- ior ) */
127
{
128
int length;
129
void *address;
130
char *from;
131
char *to;
132
133
length = stackPopINT(pVM->pStack);
134
address = (void *)stackPopPtr(pVM->pStack);
135
to = (char *)alloca(length + 1);
136
memcpy(to, address, length);
137
to[length] = 0;
138
139
length = stackPopINT(pVM->pStack);
140
address = (void *)stackPopPtr(pVM->pStack);
141
142
from = (char *)alloca(length + 1);
143
memcpy(from, address, length);
144
from[length] = 0;
145
146
pushIor(pVM, !rename(from, to));
147
}
148
149
static void ficlFileStatus(FICL_VM *pVM) /* ( c-addr u -- x ior ) */
150
{
151
struct stat statbuf;
152
153
int length = stackPopINT(pVM->pStack);
154
void *address = (void *)stackPopPtr(pVM->pStack);
155
156
char *filename = (char *)alloca(length + 1);
157
memcpy(filename, address, length);
158
filename[length] = 0;
159
160
if (stat(filename, &statbuf) == 0)
161
{
162
/*
163
** the "x" left on the stack is implementation-defined.
164
** I push the file's access mode (readable, writeable, is directory, etc)
165
** as defined by ANSI C.
166
*/
167
stackPushINT(pVM->pStack, statbuf.st_mode);
168
stackPushINT(pVM->pStack, 0);
169
}
170
else
171
{
172
stackPushINT(pVM->pStack, -1);
173
stackPushINT(pVM->pStack, ENOENT);
174
}
175
}
176
177
178
static void ficlFilePosition(FICL_VM *pVM) /* ( fileid -- ud ior ) */
179
{
180
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
181
long ud = ftell(ff->f);
182
stackPushINT(pVM->pStack, ud);
183
pushIor(pVM, ud != -1);
184
}
185
186
187
188
static long fileSize(FILE *f)
189
{
190
struct stat statbuf;
191
statbuf.st_size = -1;
192
if (fstat(fileno(f), &statbuf) != 0)
193
return -1;
194
return statbuf.st_size;
195
}
196
197
198
199
static void ficlFileSize(FICL_VM *pVM) /* ( fileid -- ud ior ) */
200
{
201
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
202
long ud = fileSize(ff->f);
203
stackPushINT(pVM->pStack, ud);
204
pushIor(pVM, ud != -1);
205
}
206
207
208
209
#define nLINEBUF 256
210
static void ficlIncludeFile(FICL_VM *pVM) /* ( i*x fileid -- j*x ) */
211
{
212
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
213
CELL id = pVM->sourceID;
214
int result = VM_OUTOFTEXT;
215
long currentPosition, totalSize;
216
long size;
217
pVM->sourceID.p = (void *)ff;
218
219
currentPosition = ftell(ff->f);
220
totalSize = fileSize(ff->f);
221
size = totalSize - currentPosition;
222
223
if ((totalSize != -1) && (currentPosition != -1) && (size > 0))
224
{
225
char *buffer = (char *)malloc(size);
226
long got = fread(buffer, 1, size, ff->f);
227
if (got == size)
228
result = ficlExecC(pVM, buffer, size);
229
}
230
231
#if 0
232
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
233
CELL id = pVM->sourceID;
234
char cp[nLINEBUF];
235
int nLine = 0;
236
int keepGoing;
237
int result;
238
pVM->sourceID.p = (void *)ff;
239
240
/* feed each line to ficlExec */
241
keepGoing = TRUE;
242
while (keepGoing && fgets(cp, nLINEBUF, ff->f))
243
{
244
int len = strlen(cp) - 1;
245
246
nLine++;
247
if (len <= 0)
248
continue;
249
250
if (cp[len] == '\n')
251
cp[len] = '\0';
252
253
result = ficlExec(pVM, cp);
254
255
switch (result)
256
{
257
case VM_OUTOFTEXT:
258
case VM_USEREXIT:
259
break;
260
261
default:
262
pVM->sourceID = id;
263
keepGoing = FALSE;
264
break;
265
}
266
}
267
#endif /* 0 */
268
/*
269
** Pass an empty line with SOURCE-ID == -1 to flush
270
** any pending REFILLs (as required by FILE wordset)
271
*/
272
pVM->sourceID.i = -1;
273
ficlExec(pVM, "");
274
275
pVM->sourceID = id;
276
closeFiclFILE(ff);
277
}
278
279
280
281
static void ficlReadFile(FICL_VM *pVM) /* ( c-addr u1 fileid -- u2 ior ) */
282
{
283
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
284
int length = stackPopINT(pVM->pStack);
285
void *address = (void *)stackPopPtr(pVM->pStack);
286
int result;
287
288
clearerr(ff->f);
289
result = fread(address, 1, length, ff->f);
290
291
stackPushINT(pVM->pStack, result);
292
pushIor(pVM, ferror(ff->f) == 0);
293
}
294
295
296
297
static void ficlReadLine(FICL_VM *pVM) /* ( c-addr u1 fileid -- u2 flag ior ) */
298
{
299
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
300
int length = stackPopINT(pVM->pStack);
301
char *address = (char *)stackPopPtr(pVM->pStack);
302
int error;
303
int flag;
304
305
if (feof(ff->f))
306
{
307
stackPushINT(pVM->pStack, -1);
308
stackPushINT(pVM->pStack, 0);
309
stackPushINT(pVM->pStack, 0);
310
return;
311
}
312
313
clearerr(ff->f);
314
*address = 0;
315
fgets(address, length, ff->f);
316
317
error = ferror(ff->f);
318
if (error != 0)
319
{
320
stackPushINT(pVM->pStack, -1);
321
stackPushINT(pVM->pStack, 0);
322
stackPushINT(pVM->pStack, error);
323
return;
324
}
325
326
length = strlen(address);
327
flag = (length > 0);
328
if (length && ((address[length - 1] == '\r') || (address[length - 1] == '\n')))
329
length--;
330
331
stackPushINT(pVM->pStack, length);
332
stackPushINT(pVM->pStack, flag);
333
stackPushINT(pVM->pStack, 0); /* ior */
334
}
335
336
337
338
static void ficlWriteFile(FICL_VM *pVM) /* ( c-addr u1 fileid -- ior ) */
339
{
340
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
341
int length = stackPopINT(pVM->pStack);
342
void *address = (void *)stackPopPtr(pVM->pStack);
343
344
clearerr(ff->f);
345
fwrite(address, 1, length, ff->f);
346
pushIor(pVM, ferror(ff->f) == 0);
347
}
348
349
350
351
static void ficlWriteLine(FICL_VM *pVM) /* ( c-addr u1 fileid -- ior ) */
352
{
353
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
354
size_t length = (size_t)stackPopINT(pVM->pStack);
355
void *address = (void *)stackPopPtr(pVM->pStack);
356
357
clearerr(ff->f);
358
if (fwrite(address, 1, length, ff->f) == length)
359
fwrite("\n", 1, 1, ff->f);
360
pushIor(pVM, ferror(ff->f) == 0);
361
}
362
363
364
365
static void ficlRepositionFile(FICL_VM *pVM) /* ( ud fileid -- ior ) */
366
{
367
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
368
size_t ud = (size_t)stackPopINT(pVM->pStack);
369
370
pushIor(pVM, fseek(ff->f, ud, SEEK_SET) == 0);
371
}
372
373
374
375
static void ficlFlushFile(FICL_VM *pVM) /* ( fileid -- ior ) */
376
{
377
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
378
pushIor(pVM, fflush(ff->f) == 0);
379
}
380
381
382
383
#if FICL_HAVE_FTRUNCATE
384
385
static void ficlResizeFile(FICL_VM *pVM) /* ( ud fileid -- ior ) */
386
{
387
ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
388
size_t ud = (size_t)stackPopINT(pVM->pStack);
389
390
pushIor(pVM, ftruncate(fileno(ff->f), ud) == 0);
391
}
392
393
#endif /* FICL_HAVE_FTRUNCATE */
394
395
#endif /* FICL_WANT_FILE */
396
397
398
399
void ficlCompileFile(FICL_SYSTEM *pSys)
400
{
401
#if FICL_WANT_FILE
402
FICL_DICT *dp = pSys->dp;
403
assert(dp);
404
405
dictAppendWord(dp, "create-file", ficlCreateFile, FW_DEFAULT);
406
dictAppendWord(dp, "open-file", ficlOpenFile, FW_DEFAULT);
407
dictAppendWord(dp, "close-file", ficlCloseFile, FW_DEFAULT);
408
dictAppendWord(dp, "include-file", ficlIncludeFile, FW_DEFAULT);
409
dictAppendWord(dp, "read-file", ficlReadFile, FW_DEFAULT);
410
dictAppendWord(dp, "read-line", ficlReadLine, FW_DEFAULT);
411
dictAppendWord(dp, "write-file", ficlWriteFile, FW_DEFAULT);
412
dictAppendWord(dp, "write-line", ficlWriteLine, FW_DEFAULT);
413
dictAppendWord(dp, "file-position", ficlFilePosition, FW_DEFAULT);
414
dictAppendWord(dp, "file-size", ficlFileSize, FW_DEFAULT);
415
dictAppendWord(dp, "reposition-file", ficlRepositionFile, FW_DEFAULT);
416
dictAppendWord(dp, "file-status", ficlFileStatus, FW_DEFAULT);
417
dictAppendWord(dp, "flush-file", ficlFlushFile, FW_DEFAULT);
418
419
dictAppendWord(dp, "delete-file", ficlDeleteFile, FW_DEFAULT);
420
dictAppendWord(dp, "rename-file", ficlRenameFile, FW_DEFAULT);
421
422
#ifdef FICL_HAVE_FTRUNCATE
423
dictAppendWord(dp, "resize-file", ficlResizeFile, FW_DEFAULT);
424
425
ficlSetEnv(pSys, "file", FICL_TRUE);
426
ficlSetEnv(pSys, "file-ext", FICL_TRUE);
427
#endif /* FICL_HAVE_FTRUNCATE */
428
#else
429
(void)pSys;
430
#endif /* FICL_WANT_FILE */
431
}
432
433