Mail Archives: djgpp-workers/1998/02/02/11:53:59
--=====================_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 -