delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1998/02/02/11:53:59

Message-Id: <3.0.1.32.19980202103309.007f6ce0@yacker.xiotech.com>
Date: Mon, 02 Feb 1998 10:33:09 -0600
To: djgpp-workers AT delorie DOT com
From: Randy Maas <randym AT acm DOT org>
Subject: A patch for fsext.txh
Cc: bcurrie AT tssc DOT co DOT nz
Mime-Version: 1.0

--=====================_886458789==_
Content-Type: text/plain; charset="us-ascii"

Here is a *much* larger example that has some functionality.  My only
concern is that it may too much to take in if you want to know what
__FSEXT_{get,set}_data does.   I've tried to vary the comments -- if
describing it one way doesn't help, maybe the other way will.  The code is
a very stripped down version of a different one I have used; it can be
stripped further by doing even less error checking (currently it  doesn't
set errno).  This version does compile without warnings.

One possibility, is that the other io functions *could* be emulated, but
not provided in the example. ie:
	...inside of the switch...
	case __FSEXT_stat:
	 *RV = my_stat(Args); /* see XYZ for an example of a stat handler */
	 return 1;

Randy
randym AT acm DOT org
--=====================_886458789==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="fsext.dif"

*** src/libc/fsext/fsext.txh~1	Fri Jan  2 00:28:02 1998
--- src/libc/fsext/fsext.txh	Mon Feb  2 10:17:26 1998
***************
*** 291,300 ****
--- 291,542 ----
  to store a descriptor-specific pointer that can later be retrieved by
  @ref{__FSEXT_get_data}.  The pointer is not otherwise used.
  
+ This is useful when writing an extension that may be handling several
+ open psuedo-files.  @code{__FSEXT_set_data} can be used when creating or
+ opening the file to store a pointer to data about the specific file.  Later,
+ when specific operation needs to be done (e.g. read, write, etc.) a
+ pointer to psuedo-file associated with the file descriptor can  be fetched
+ with @code{__FSEXT_get_data}.
+ 
  @subheading Return Value
  
  Returns the pointer you passed it, or NULL if there was an error.
  
+ @subheading Example
+ /*
+    This is a example fsext that will simulate a ramdisk.  You can create,
+    open and close files in the /ramdisk directory.  These files will exist
+    only in memory and will not be written to disk.  You can read and write
+    to these files; the other FSEXT functions are implemented.
+ 
+    Files are not deletable or seekable or such.
+    Read/write permissions are ignored.
+  */
+ 
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/fsext.h>
+ #include <search.h>
+ #include <malloc.h>
+ #include <string.h>
+ 
+ typedef struct
+ @{
+    void*  Ptr;
+    off_t  Current_Ofs;
+    size_t Size;
+    int    Opend;
+ @} _mem_file_t;
+ 
+ /* A list of our file names, use insque and remque */
+ typedef struct _mem_name_t
+ @{
+    struct _mem_name_t* q_forw;
+    struct _mem_name_t* q_back;
+    char* Name;
+    _mem_file_t* FPtr;
+ @} _mem_name_t;
+ 
+ static _mem_name_t Head = @{NULL, NULL, NULL@};
+ 
+ int my_fsext(__FSEXT_Fnumber Op, int* RV, va_list Args)
+ @{
+    const char* Path;
+    void* Buffer;
+    size_t Size;
+    mode_t Mode;
+    int fd;
+    _mem_file_t* MPtr;
+    _mem_name_t* NPtr;
+ 
+    if (Op == __FSEXT_open || Op == __FSEXT_creat)
+    @{
+       /* Get the path name */
+       Path = va_arg(Args, const char*);
+       Mode = va_arg(Args, mode_t);
+ 
+       /* Check that we are dealing the proper folder */
+       if (strnicmp("/ramdisk/", Path, 5) != 0) return 0;
+    @}
+ 
+    switch (Op)
+    @{
+       case __FSEXT_open:
+        /* Open an existing memory file or create a new one */
+ 
+        /* Check to see if we should create a new file */
+        if (! (Mode & (O_CREAT | O_TRUNC)))
+        @{
+           int Found = 0;
+ 
+           /* Look up the file */
+           for (NPtr = Head.q_forw; NPtr; NPtr = NPtr->q_forw)
+            if (stricmp(Path+9, NPtr->Name)) @{Found = 1; break;@}
+ 
+           if (!Found) return 0;
+ 
+           /* Now check to see if it is already opened */
+           if (NPtr->FPtr->Opend)
+           @{
+              /* It is already opened */
+              *RV = -1;
+              return 1;
+           @}
+ 
+           /* Mark the file as open now */
+           NPtr->FPtr->Opend = 1;
+ 
+           /* Start at the beginning of the file */
+           NPtr->FPtr->Current_Ofs = 0;
+ 
+           /* Set ourselves up with a file descriptor */
+           fd = __FSEXT_alloc_fd(my_fsext);
+           *RV = fd;
+ 
+           if (fd >= 0)
+           @{
+              /* Associate the file data point with the file descriptor for
+                 fast look up later */
+              __FSEXT_set_data(fd, NPtr->FPtr);
+           @}
+ 
+           return 1;
+        @}
+        /* Otherwise fall-thru and create the file */
+        
+       case __FSEXT_creat:
+        /* Create a new memory file */
+ 
+        /* Nuke any files with the same name */
+        for (NPtr = Head.q_forw; NPtr; NPtr = NPtr->q_forw)
+         if (stricmp(NPtr->Name, Path+9) == 0)
+          @{
+             free(NPtr->Name);
+             if (NPtr->FPtr)
+             @{
+                free(NPtr->FPtr->Ptr);
+                free(NPtr->FPtr);
+             @}
+             remque((struct qelem*) NPtr);
+             break;
+          @}
+ 
+        /* Prevent any one else from opening it */
+        MPtr->Opend = 1;
+ 
+        /* Allocate some memory to keep info on our fake file */
+        MPtr = malloc(sizeof(_mem_file_t));
+        if (!MPtr) return 0;
+ 
+        memset(MPtr, 0, sizeof(_mem_file_t));
+ 
+        /* Get a file descriptor we can use */
+        fd = __FSEXT_alloc_fd(my_fsext);
+        if (fd < 0)
+        @{
+           free(MPtr);
+           return 0;
+        @}
+ 
+        /* Now store our note about this file descriptor so we can lookup it
+           up quickly later. */
+        __FSEXT_set_data(fd, MPtr);
+ 
+        /* Store our name for later look up */
+        NPtr = malloc(sizeof(_mem_name_t));
+        NPtr->Name = strdup(Path+9);
+        NPtr->FPtr = MPtr;
+        insque((struct qelem*) NPtr, (struct qelem*) &Head);
+ 
+        /* Return the file descriptor */
+        *RV = fd;
+        return 1;
+ 
+       case __FSEXT_close:
+        fd = va_arg(Args, int);
+ 
+        /* Allow others to open this file */
+        MPtr = __FSEXT_get_data(fd);
+        if (MPtr) MPtr->Opend = 0;
+ 
+        /* Disassociate ourselves from the file descriptor */
+        __FSEXT_set_data(fd, NULL);
+        __FSEXT_set_function(fd, NULL);
+ 
+        /* Now close the DOS descriptor itself */
+        *RV = close(fd);
+        return 1;
+ 
+       case __FSEXT_read:
+        /* Read from our memory file. */
+        fd = va_arg(Args, int);
+        Buffer = va_arg(Args, void*);
+        Size = va_arg(Args, size_t);
+ 
+        /* Look up the information about this file */
+        MPtr = __FSEXT_get_data(fd);
+        if (!MPtr)
+        @{
+            *RV = -1;
+            return 1;
+        @}
+ 
+        if (MPtr->Current_Ofs >= MPtr->Size)
+        @{
+            *RV = 0;
+            return 1;
+        @}
+ 
+        if (Size > (MPtr->Size - MPtr->Current_Ofs))
+         Size = MPtr->Size - MPtr->Current_Ofs;
+ 
+        memcpy(Buffer, (char*) MPtr->Ptr+MPtr->Current_Ofs, Size);
+        MPtr->Current_Ofs += Size;
+ 
+        *RV = Size;
+        return 1;
+        
+       case __FSEXT_write:
+        /* Write data to our memory file */
+        fd = va_arg(Args, int);
+        Buffer = va_arg(Args, void*);
+        Size = va_arg(Args, size_t);
+ 
+        /* Get the file associated with this descriptor */
+        MPtr = __FSEXT_get_data(fd);
+        if (!MPtr)
+        @{
+           *RV = -1;
+           return 1;
+        @}
+ 
+        /* Do we need to resize our file? */
+        if (Size + MPtr->Current_Ofs >= MPtr->Size)
+        @{
+           MPtr->Ptr = realloc(MPtr->Ptr, MPtr->Current_Ofs+Size);
+           if (!MPtr->Ptr)
+           @{
+              *RV = -1;
+              return 1;
+           @}
+ 
+           MPtr->Size = MPtr->Current_Ofs + Size;
+        @}
+ 
+        /* Store the data */
+        memcpy((char*)MPtr->Ptr + MPtr->Current_Ofs, Buffer, Size);
+        MPtr->Current_Ofs += Size;
+ 
+        /* And return */
+        *RV = Size;
+        return 1;
+ 
+       default: return 0; /* Not done. */
+     @}
+ @}
+     
+     
+ 
  @c ----------------------------------------------------------------------
  @node __FSEXT_get_data, file system
  @subheading Syntax
***************
*** 311,317 ****
--- 553,562 ----
  to retrieve a descriptor-specific pointer that was previously stored
  by @ref{__FSEXT_set_data}.  The pointer is not otherwise used.
  
+ @pxref{__FSEXT_set_data} for an example of how this may be used.
+ 
  @subheading Return Value
  
  Returns the stored pointer, or NULL if there was an error (or no
  pointer had been stored).


--=====================_886458789==_
Content-Type: text/plain; charset="us-ascii"



--=====================_886458789==_--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019