The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/boot/ficl/fileaccess.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: e7594f216f26c4fd81a683bb4dda5c47


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.