Resync patch with contrib.
[dragonfly.git] / sys / boot / ficl / fileaccess.c
blob3135d059d2405afb926578374a76c8796317617e
1 /*
2 * $FreeBSD: src/sys/boot/ficl/fileaccess.c,v 1.1 2002/04/09 17:45:11 dcs Exp $
3 * $DragonFly: src/sys/boot/ficl/fileaccess.c,v 1.1 2003/11/10 06:08:33 dillon Exp $
4 */
6 #include <errno.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include <sys/stat.h>
12 #include "ficl.h"
14 #if FICL_WANT_FILE
17 ** fileaccess.c
19 ** Implements all of the File Access word set that can be implemented in portable C.
23 static void pushIor(FICL_VM *pVM, int success)
25 int ior;
26 if (success)
27 ior = 0;
28 else
29 ior = errno;
30 stackPushINT(pVM->pStack, ior);
35 static void ficlFopen(FICL_VM *pVM, char *writeMode) /* ( c-addr u fam -- fileid ior ) */
37 int fam = stackPopINT(pVM->pStack);
38 int length = stackPopINT(pVM->pStack);
39 void *address = (void *)stackPopPtr(pVM->pStack);
40 char mode[4];
41 FILE *f;
43 char *filename = (char *)alloca(length + 1);
44 memcpy(filename, address, length);
45 filename[length] = 0;
47 *mode = 0;
49 switch (FICL_FAM_OPEN_MODE(fam))
51 case 0:
52 stackPushPtr(pVM->pStack, NULL);
53 stackPushINT(pVM->pStack, EINVAL);
54 return;
55 case FICL_FAM_READ:
56 strcat(mode, "r");
57 break;
58 case FICL_FAM_WRITE:
59 strcat(mode, writeMode);
60 break;
61 case FICL_FAM_READ | FICL_FAM_WRITE:
62 strcat(mode, writeMode);
63 strcat(mode, "+");
64 break;
67 strcat(mode, (fam & FICL_FAM_BINARY) ? "b" : "t");
69 f = fopen(filename, mode);
70 if (f == NULL)
71 stackPushPtr(pVM->pStack, NULL);
72 else
74 ficlFILE *ff = (ficlFILE *)malloc(sizeof(ficlFILE));
75 strcpy(ff->filename, filename);
76 ff->f = f;
77 stackPushPtr(pVM->pStack, ff);
79 fseek(f, 0, SEEK_SET);
81 pushIor(pVM, f != NULL);
86 static void ficlOpenFile(FICL_VM *pVM) /* ( c-addr u fam -- fileid ior ) */
88 ficlFopen(pVM, "a");
92 static void ficlCreateFile(FICL_VM *pVM) /* ( c-addr u fam -- fileid ior ) */
94 ficlFopen(pVM, "w");
98 static int closeFiclFILE(ficlFILE *ff) /* ( fileid -- ior ) */
100 FILE *f = ff->f;
101 free(ff);
102 return !fclose(f);
105 static void ficlCloseFile(FICL_VM *pVM) /* ( fileid -- ior ) */
107 ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
108 pushIor(pVM, closeFiclFILE(ff));
111 static void ficlDeleteFile(FICL_VM *pVM) /* ( c-addr u -- ior ) */
113 int length = stackPopINT(pVM->pStack);
114 void *address = (void *)stackPopPtr(pVM->pStack);
116 char *filename = (char *)alloca(length + 1);
117 memcpy(filename, address, length);
118 filename[length] = 0;
120 pushIor(pVM, !unlink(filename));
123 static void ficlRenameFile(FICL_VM *pVM) /* ( c-addr1 u1 c-addr2 u2 -- ior ) */
125 int length;
126 void *address;
127 char *from;
128 char *to;
130 length = stackPopINT(pVM->pStack);
131 address = (void *)stackPopPtr(pVM->pStack);
132 to = (char *)alloca(length + 1);
133 memcpy(to, address, length);
134 to[length] = 0;
136 length = stackPopINT(pVM->pStack);
137 address = (void *)stackPopPtr(pVM->pStack);
139 from = (char *)alloca(length + 1);
140 memcpy(from, address, length);
141 from[length] = 0;
143 pushIor(pVM, !rename(from, to));
146 static void ficlFileStatus(FICL_VM *pVM) /* ( c-addr u -- x ior ) */
148 struct stat statbuf;
150 int length = stackPopINT(pVM->pStack);
151 void *address = (void *)stackPopPtr(pVM->pStack);
153 char *filename = (char *)alloca(length + 1);
154 memcpy(filename, address, length);
155 filename[length] = 0;
157 if (stat(filename, &statbuf) == 0)
160 ** the "x" left on the stack is implementation-defined.
161 ** I push the file's access mode (readable, writeable, is directory, etc)
162 ** as defined by ANSI C.
164 stackPushINT(pVM->pStack, statbuf.st_mode);
165 stackPushINT(pVM->pStack, 0);
167 else
169 stackPushINT(pVM->pStack, -1);
170 stackPushINT(pVM->pStack, ENOENT);
175 static void ficlFilePosition(FICL_VM *pVM) /* ( fileid -- ud ior ) */
177 ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
178 long ud = ftell(ff->f);
179 stackPushINT(pVM->pStack, ud);
180 pushIor(pVM, ud != -1);
185 static long fileSize(FILE *f)
187 struct stat statbuf;
188 statbuf.st_size = -1;
189 if (fstat(fileno(f), &statbuf) != 0)
190 return -1;
191 return statbuf.st_size;
196 static void ficlFileSize(FICL_VM *pVM) /* ( fileid -- ud ior ) */
198 ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
199 long ud = fileSize(ff->f);
200 stackPushINT(pVM->pStack, ud);
201 pushIor(pVM, ud != -1);
206 #define nLINEBUF 256
207 static void ficlIncludeFile(FICL_VM *pVM) /* ( i*x fileid -- j*x ) */
209 ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
210 CELL id = pVM->sourceID;
211 int result = VM_OUTOFTEXT;
212 long currentPosition, totalSize;
213 long size;
214 pVM->sourceID.p = (void *)ff;
216 currentPosition = ftell(ff->f);
217 totalSize = fileSize(ff->f);
218 size = totalSize - currentPosition;
220 if ((totalSize != -1) && (currentPosition != -1) && (size > 0))
222 char *buffer = (char *)malloc(size);
223 long got = fread(buffer, 1, size, ff->f);
224 if (got == size)
225 result = ficlExecC(pVM, buffer, size);
228 #if 0
229 ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
230 CELL id = pVM->sourceID;
231 char cp[nLINEBUF];
232 int nLine = 0;
233 int keepGoing;
234 int result;
235 pVM->sourceID.p = (void *)ff;
237 /* feed each line to ficlExec */
238 keepGoing = TRUE;
239 while (keepGoing && fgets(cp, nLINEBUF, ff->f))
241 int len = strlen(cp) - 1;
243 nLine++;
244 if (len <= 0)
245 continue;
247 if (cp[len] == '\n')
248 cp[len] = '\0';
250 result = ficlExec(pVM, cp);
252 switch (result)
254 case VM_OUTOFTEXT:
255 case VM_USEREXIT:
256 break;
258 default:
259 pVM->sourceID = id;
260 keepGoing = FALSE;
261 break;
264 #endif /* 0 */
266 ** Pass an empty line with SOURCE-ID == -1 to flush
267 ** any pending REFILLs (as required by FILE wordset)
269 pVM->sourceID.i = -1;
270 ficlExec(pVM, "");
272 pVM->sourceID = id;
273 closeFiclFILE(ff);
278 static void ficlReadFile(FICL_VM *pVM) /* ( c-addr u1 fileid -- u2 ior ) */
280 ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
281 int length = stackPopINT(pVM->pStack);
282 void *address = (void *)stackPopPtr(pVM->pStack);
283 int result;
285 clearerr(ff->f);
286 result = fread(address, 1, length, ff->f);
288 stackPushINT(pVM->pStack, result);
289 pushIor(pVM, ferror(ff->f) == 0);
294 static void ficlReadLine(FICL_VM *pVM) /* ( c-addr u1 fileid -- u2 flag ior ) */
296 ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
297 int length = stackPopINT(pVM->pStack);
298 char *address = (char *)stackPopPtr(pVM->pStack);
299 int error;
300 int flag;
302 if (feof(ff->f))
304 stackPushINT(pVM->pStack, -1);
305 stackPushINT(pVM->pStack, 0);
306 stackPushINT(pVM->pStack, 0);
307 return;
310 clearerr(ff->f);
311 *address = 0;
312 fgets(address, length, ff->f);
314 error = ferror(ff->f);
315 if (error != 0)
317 stackPushINT(pVM->pStack, -1);
318 stackPushINT(pVM->pStack, 0);
319 stackPushINT(pVM->pStack, error);
320 return;
323 length = strlen(address);
324 flag = (length > 0);
325 if (length && ((address[length - 1] == '\r') || (address[length - 1] == '\n')))
326 length--;
328 stackPushINT(pVM->pStack, length);
329 stackPushINT(pVM->pStack, flag);
330 stackPushINT(pVM->pStack, 0); /* ior */
335 static void ficlWriteFile(FICL_VM *pVM) /* ( c-addr u1 fileid -- ior ) */
337 ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
338 int length = stackPopINT(pVM->pStack);
339 void *address = (void *)stackPopPtr(pVM->pStack);
341 clearerr(ff->f);
342 fwrite(address, 1, length, ff->f);
343 pushIor(pVM, ferror(ff->f) == 0);
348 static void ficlWriteLine(FICL_VM *pVM) /* ( c-addr u1 fileid -- ior ) */
350 ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
351 size_t length = (size_t)stackPopINT(pVM->pStack);
352 void *address = (void *)stackPopPtr(pVM->pStack);
354 clearerr(ff->f);
355 if (fwrite(address, 1, length, ff->f) == length)
356 fwrite("\n", 1, 1, ff->f);
357 pushIor(pVM, ferror(ff->f) == 0);
362 static void ficlRepositionFile(FICL_VM *pVM) /* ( ud fileid -- ior ) */
364 ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
365 size_t ud = (size_t)stackPopINT(pVM->pStack);
367 pushIor(pVM, fseek(ff->f, ud, SEEK_SET) == 0);
372 static void ficlFlushFile(FICL_VM *pVM) /* ( fileid -- ior ) */
374 ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
375 pushIor(pVM, fflush(ff->f) == 0);
380 #if FICL_HAVE_FTRUNCATE
382 static void ficlResizeFile(FICL_VM *pVM) /* ( ud fileid -- ior ) */
384 ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
385 size_t ud = (size_t)stackPopINT(pVM->pStack);
387 pushIor(pVM, ftruncate(fileno(ff->f), ud) == 0);
390 #endif /* FICL_HAVE_FTRUNCATE */
392 #endif /* FICL_WANT_FILE */
396 void ficlCompileFile(FICL_SYSTEM *pSys)
398 #if FICL_WANT_FILE
399 FICL_DICT *dp = pSys->dp;
400 assert(dp);
402 dictAppendWord(dp, "create-file", ficlCreateFile, FW_DEFAULT);
403 dictAppendWord(dp, "open-file", ficlOpenFile, FW_DEFAULT);
404 dictAppendWord(dp, "close-file", ficlCloseFile, FW_DEFAULT);
405 dictAppendWord(dp, "include-file", ficlIncludeFile, FW_DEFAULT);
406 dictAppendWord(dp, "read-file", ficlReadFile, FW_DEFAULT);
407 dictAppendWord(dp, "read-line", ficlReadLine, FW_DEFAULT);
408 dictAppendWord(dp, "write-file", ficlWriteFile, FW_DEFAULT);
409 dictAppendWord(dp, "write-line", ficlWriteLine, FW_DEFAULT);
410 dictAppendWord(dp, "file-position", ficlFilePosition, FW_DEFAULT);
411 dictAppendWord(dp, "file-size", ficlFileSize, FW_DEFAULT);
412 dictAppendWord(dp, "reposition-file", ficlRepositionFile, FW_DEFAULT);
413 dictAppendWord(dp, "file-status", ficlFileStatus, FW_DEFAULT);
414 dictAppendWord(dp, "flush-file", ficlFlushFile, FW_DEFAULT);
416 dictAppendWord(dp, "delete-file", ficlDeleteFile, FW_DEFAULT);
417 dictAppendWord(dp, "rename-file", ficlRenameFile, FW_DEFAULT);
419 #ifdef FICL_HAVE_FTRUNCATE
420 dictAppendWord(dp, "resize-file", ficlResizeFile, FW_DEFAULT);
422 ficlSetEnv(pSys, "file", FICL_TRUE);
423 ficlSetEnv(pSys, "file-ext", FICL_TRUE);
424 #endif /* FICL_HAVE_FTRUNCATE */
425 #else
426 &pSys;
427 #endif /* FICL_WANT_FILE */