home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / workbench / devs / ram_handler.c < prev   
Encoding:
C/C++ Source or Header  |  1997-01-27  |  35.0 KB  |  1,441 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: ram_handler.c,v 1.11 1997/01/27 00:22:40 ldp Exp $
  4.  
  5.     Desc: RAM: handler
  6.     Lang: english
  7. */
  8. #include <exec/errors.h>
  9. #include <exec/types.h>
  10. #include <exec/resident.h>
  11. #include <exec/memory.h>
  12. #include <exec/semaphores.h>
  13. #include <proto/exec.h>
  14. #include <utility/tagitem.h>
  15. #include <proto/utility.h>
  16. #include <dos/dosextens.h>
  17. #include <dos/dosasl.h>
  18. #include <dos/exall.h>
  19. #include <dos/filesystem.h>
  20. #include <proto/dos.h>
  21. #include <aros/libcall.h>
  22. #ifdef __GNUC__
  23. #include "ram_handler_gcc.h"
  24. #endif
  25. #include <aros/machine.h>
  26. #include <stddef.h>
  27.  
  28. #define NEWLIST(l)                          \
  29. ((l)->lh_Head=(struct Node *)&(l)->lh_Tail, \
  30.  (l)->lh_Tail=NULL,                         \
  31.  (l)->lh_TailPred=(struct Node *)(l))
  32.  
  33. extern const char name[];
  34. extern const char version[];
  35. extern const APTR inittabl[4];
  36. extern void *const functable[];
  37. extern const UBYTE datatable;
  38. extern struct rambase *AROS_SLIB_ENTRY(init,ramdev)();
  39. extern void AROS_SLIB_ENTRY(open,ramdev)();
  40. extern BPTR AROS_SLIB_ENTRY(close,ramdev)();
  41. extern BPTR AROS_SLIB_ENTRY(expunge,ramdev)();
  42. extern int AROS_SLIB_ENTRY(null,ramdev)();
  43. extern void AROS_SLIB_ENTRY(beginio,ramdev)();
  44. extern LONG AROS_SLIB_ENTRY(abortio,ramdev)();
  45. extern void deventry();
  46. extern const char end;
  47.  
  48. /* Device node */
  49. struct cnode
  50. {
  51.     struct MinNode node;
  52.     LONG type;            /* ST_LINKDIR */
  53.     char *name;         /* Link's name */
  54.     struct cnode *self;     /* Pointer to top of structure */
  55.     struct hnode *link;     /* NULL */
  56.     LONG usecount;        /* >0 usecount locked:+(~0ul/2+1) */
  57.     ULONG protect;        /* 0 */
  58.     char *comment;        /* NULL */
  59.     struct vnode *volume;    /* Pointer to volume */
  60.     struct DosList *doslist;    /* Pointer to doslist entry */
  61. };
  62.  
  63. /* Volume node */
  64. struct vnode
  65. {
  66.     struct MinNode node;
  67.     LONG type;            /* ST_USERDIR */
  68.     char *name;         /* Directory name */
  69.     struct vnode *self;     /* Points to top of structure */
  70.     struct hnode *link;     /* This one is linked to me */
  71.     LONG usecount;        /* >0 usecount locked:+(~0ul/2+1) */
  72.     ULONG protect;        /* 0 */
  73.     char *comment;        /* NULL */
  74.     struct MinList list;    /* Contents of directory */
  75.     ULONG volcount;        /* number of handles on this volume */
  76.     struct DosList *doslist;    /* Pointer to doslist entry */
  77. };
  78.  
  79. /* Directory node */
  80. struct dnode
  81. {
  82.     struct MinNode node;
  83.     LONG type;            /* ST_USERDIR */
  84.     char *name;         /* Directory name */
  85.     struct vnode *volume;    /* Volume's root directory */
  86.     struct hnode *link;     /* This one is linked to me */
  87.     LONG usecount;        /* >0 usecount locked:+(~0ul/2+1) */
  88.     ULONG protect;        /* protection bits */
  89.     char *comment;        /* Some comment */
  90.     struct MinList list;    /* Contents of directory */
  91. };
  92.  
  93. /* File node */
  94. struct fnode
  95. {
  96.     struct MinNode node;
  97.     LONG type;            /* ST_FILE */
  98.     char *name;         /* Filename */
  99.     struct vnode *volume;    /* Volume's root directory */
  100.     struct hnode *link;     /* This one is linked to me */
  101.     LONG usecount;        /* >0 usecount locked:+(~0ul/2+1) */
  102.     ULONG protect;        /* protection bits */
  103.     char *comment;        /* Some file comment */
  104.     LONG size;            /* Filesize */
  105.     UBYTE *blocks[16];        /* Upto 0x1000 bytes */
  106.     UBYTE **iblocks[4];     /* Upto 0x41000 bytes */
  107.     UBYTE ***i2block;        /* Upto 0x1041000 bytes */
  108.     UBYTE ****i3block;        /* Upto 0x101041000 bytes */
  109. };
  110.  
  111. /* Softlink node */
  112. struct snode
  113. {
  114.     struct MinNode node;
  115.     LONG type;            /* ST_SOFTLINK */
  116.     char *name;         /* Link's name */
  117.     struct vnode *volume;    /* Volume's root directory */
  118.     struct hnode *link;     /* This one is hardlinked to me */
  119.     LONG usecount;        /* >0 usecount locked:+(~0ul/2+1) */
  120.     ULONG protect;        /* protection bits */
  121.     char *comment;        /* Some file comment */
  122.     char *contents;        /* Contents of soft link */
  123. };
  124.  
  125. /* Hardlink node */
  126. struct hnode
  127. {
  128.     struct MinNode node;
  129.     LONG type;            /* ST_LINKDIR */
  130.     char *name;         /* Link's name */
  131.     struct vnode *volume;    /* Volume's root directory */
  132.     struct hnode *link;     /* This one is hardlinked to me */
  133.     LONG usecount;        /* >0 usecount locked:+(~0ul/2+1) */
  134.     ULONG protect;        /* protection bits */
  135.     char *comment;        /* Some file comment */
  136.     struct hnode *orig;     /* original object */
  137. };
  138.  
  139. #define BLOCKSIZE    256
  140. #define PBLOCKSIZE    (256*sizeof(UBYTE *))
  141.  
  142. struct filehandle
  143. {
  144.     struct dnode *node;
  145.     IPTR position;
  146. };
  147.  
  148. int entry(void)
  149. {
  150.     /* If the device was executed by accident return error code. */
  151.     return -1;
  152. }
  153.  
  154. const struct Resident resident=
  155. {
  156.     RTC_MATCHWORD,
  157.     (struct Resident *)&resident,
  158.     (APTR)&end,
  159.     RTF_AUTOINIT,
  160.     1,
  161.     NT_LIBRARY,
  162.     0,
  163.     (char *)name,
  164.     (char *)&version[6],
  165.     (ULONG *)inittabl
  166. };
  167.  
  168. const char name[]="ram.handler";
  169.  
  170. const char version[]="$VER: ram handler 1.0 (28.3.96)\n\015";
  171.  
  172. const APTR inittabl[4]=
  173. {
  174.     (APTR)sizeof(struct rambase),
  175.     (APTR)functable,
  176.     (APTR)&datatable,
  177.     &AROS_SLIB_ENTRY(init,ramdev)
  178. };
  179.  
  180. void *const functable[]=
  181. {
  182.     &AROS_SLIB_ENTRY(open,ramdev),
  183.     &AROS_SLIB_ENTRY(close,ramdev),
  184.     &AROS_SLIB_ENTRY(expunge,ramdev),
  185.     &AROS_SLIB_ENTRY(null,ramdev),
  186.     &AROS_SLIB_ENTRY(beginio,ramdev),
  187.     &AROS_SLIB_ENTRY(abortio,ramdev),
  188.     (void *)-1
  189. };
  190.  
  191. const UBYTE datatable=0;
  192.  
  193. AROS_LH2(struct rambase *, init,
  194.  AROS_LHA(struct rambase *, rambase, D0),
  195.  AROS_LHA(BPTR,             segList,   A0),
  196.        struct ExecBase *, SysBase, 0, ramdev)
  197. {
  198.     AROS_LIBFUNC_INIT
  199.  
  200.     /* This function is single-threaded by exec by calling Forbid. */
  201.  
  202.     struct MsgPort *port;
  203.     struct Task *task;
  204.     struct SignalSemaphore *semaphore;
  205.     APTR stack;
  206.  
  207.     /* Store arguments */
  208.     rambase->sysbase=SysBase;
  209.     rambase->seglist=segList;
  210.     rambase->dosbase=(struct DosLibrary *)OpenLibrary("dos.library",39);
  211.     if(rambase->dosbase!=NULL)
  212.     {
  213.     rambase->utilitybase=(struct UtilityBase *)OpenLibrary("utility.library",39);
  214.     if(rambase->utilitybase!=NULL)
  215.     {
  216.         port=(struct MsgPort *)AllocMem(sizeof(struct MsgPort),MEMF_PUBLIC|MEMF_CLEAR);
  217.         if(port!=NULL)
  218.         {
  219.         rambase->port=port;
  220.         NEWLIST(&port->mp_MsgList);
  221.         port->mp_Node.ln_Type=NT_MSGPORT;
  222.         port->mp_SigBit=SIGB_SINGLE;
  223.  
  224.         task=(struct Task *)AllocMem(sizeof(struct Task),MEMF_PUBLIC|MEMF_CLEAR);
  225.         if(task!=NULL)
  226.         {
  227.             port->mp_SigTask=task;
  228.             port->mp_Flags=PA_IGNORE;
  229.             NEWLIST(&task->tc_MemEntry);
  230.             task->tc_Node.ln_Type=NT_TASK;
  231.             task->tc_Node.ln_Name="ram.handler task";
  232.  
  233.             stack=AllocMem(2048,MEMF_PUBLIC);
  234.             if(stack!=NULL)
  235.             {
  236.             task->tc_SPLower=stack;
  237.             task->tc_SPUpper=(BYTE *)stack+2048;
  238. #if AROS_STACK_GROWS_DOWNWARDS
  239.             task->tc_SPReg=(BYTE *)task->tc_SPUpper-SP_OFFSET-sizeof(APTR);
  240.             ((APTR *)task->tc_SPUpper)[-1]=rambase;
  241. #else
  242.             task->tc_SPReg=(BYTE *)task->tc_SPLower-SP_OFFSET+sizeof(APTR);
  243.             *(APTR *)task->tc_SPLower=rambase;
  244. #endif
  245.  
  246.             semaphore=(struct SignalSemaphore *)AllocMem(sizeof(struct SignalSemaphore),MEMF_PUBLIC|MEMF_CLEAR);
  247.             if(semaphore!=NULL)
  248.             {
  249.                 rambase->sigsem=semaphore;
  250.                 InitSemaphore(semaphore);
  251.  
  252.                 if(AddTask(task,deventry,NULL)!=NULL)
  253.                 return rambase;
  254.  
  255.                 FreeMem(semaphore,sizeof(struct SignalSemaphore));
  256.             }
  257.             FreeMem(stack,2048);
  258.             }
  259.             FreeMem(task,sizeof(struct Task));
  260.         }
  261.         FreeMem(port,sizeof(struct MsgPort));
  262.         }
  263.         CloseLibrary((struct Library *)rambase->utilitybase);
  264.     }
  265.     CloseLibrary((struct Library *)rambase->dosbase);
  266.     }
  267.  
  268.     return NULL;
  269.     AROS_LIBFUNC_EXIT
  270. }
  271.  
  272. /* Use This from now on */
  273. #ifdef SysBase
  274.     #undef SysBase
  275. #endif
  276. #ifdef DOSBase
  277.     #undef DOSBase
  278. #endif
  279. #ifdef UtilityBase
  280.     #undef UtilityBase
  281. #endif
  282. #define SysBase rambase->sysbase
  283. #define DOSBase rambase->dosbase
  284. #define UtilityBase rambase->utilitybase
  285.  
  286. static STRPTR Strdup(struct rambase *rambase, STRPTR string)
  287. {
  288.     STRPTR s2=string,s3;
  289.     while(*s2++)
  290.     ;
  291.     s3=(STRPTR)AllocMem(s2-string,MEMF_ANY);
  292.     if(s3!=NULL)
  293.     CopyMem(string,s3,s2-string);
  294.     return s3;
  295. }
  296.  
  297. static void Strfree(struct rambase *rambase, STRPTR string)
  298. {
  299.     STRPTR s2=string;
  300.     if(string==NULL)
  301.     return;
  302.     while(*s2++)
  303.     ;
  304.     FreeMem(string,s2-string);
  305. }
  306.  
  307. AROS_LH3(void, open,
  308.  AROS_LHA(struct IOFileSys *, iofs, A1),
  309.  AROS_LHA(ULONG,              unitnum, D0),
  310.  AROS_LHA(ULONG,              flags, D1),
  311.        struct rambase *, rambase, 1, ramdev)
  312. {
  313.     AROS_LIBFUNC_INIT
  314.     struct filehandle *fhv, *fhc;
  315.     struct vnode *vol;
  316.     struct cnode *dev;
  317.     struct DosList *dlv;
  318.  
  319.     /* Keep compiler happy */
  320.     unitnum=flags=0;
  321.  
  322.     /* I have one more opener. */
  323.     rambase->device.dd_Library.lib_OpenCnt++;
  324.  
  325.     /* Mark Message as recently used. */
  326.     iofs->IOFS.io_Message.mn_Node.ln_Type=NT_REPLYMSG;
  327.  
  328.     iofs->IOFS.io_Error=ERROR_NO_FREE_STORE;
  329.     fhv=(struct filehandle*)AllocMem(sizeof(struct filehandle),MEMF_CLEAR);
  330.     if(fhv!=NULL)
  331. {
  332.     fhc=(struct filehandle*)AllocMem(sizeof(struct filehandle),MEMF_CLEAR);
  333.     if(fhc!=NULL)
  334.     {
  335.         vol=(struct vnode *)AllocMem(sizeof(struct vnode),MEMF_CLEAR);
  336.         if(vol!=NULL)
  337.         {
  338.         dev=(struct cnode *)AllocMem(sizeof(struct cnode),MEMF_CLEAR);
  339.         if(dev!=NULL)
  340.         {
  341.             vol->name=Strdup(rambase,"Ram Disk");
  342.             if(vol->name!=NULL)
  343.             {
  344.             dlv=MakeDosEntry("Ram Disk",DLT_VOLUME);
  345.             if(dlv!=NULL)
  346.             {
  347.                 vol->type=ST_USERDIR;
  348.                 vol->self=vol;
  349.                 vol->doslist=dlv;
  350.                 vol->protect=FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE;
  351.                 NEWLIST((struct List *)&vol->list);
  352.                 fhv->node=(struct dnode *)vol;
  353.                 dlv->dol_Unit  =(struct Unit *)fhv;
  354.                 dlv->dol_Device=&rambase->device;
  355.                 dev->type=ST_LINKDIR;
  356.                 dev->self=dev;
  357.                 dev->volume=vol;
  358.                 fhc->node=(struct dnode *)dev;
  359.                 iofs->IOFS.io_Unit=(struct Unit *)fhc;
  360.                 iofs->IOFS.io_Device=&rambase->device;
  361.                 AddDosEntry(dlv);
  362.                 rambase->device.dd_Library.lib_Flags&=~LIBF_DELEXP;
  363.                 iofs->IOFS.io_Error=0;
  364.                 return;
  365.     }
  366.             Strfree(rambase,vol->name);
  367.             }
  368.             FreeMem(dev,sizeof(struct cnode));
  369.         }
  370.         FreeMem(vol,sizeof(struct vnode));
  371.         }
  372.         FreeMem(fhc,sizeof(struct filehandle));
  373.     }
  374.     FreeMem(fhv,sizeof(struct filehandle));
  375.     }
  376.  
  377.     /* Set returncode */
  378.     iofs->IOFS.io_Error=IOERR_OPENFAIL;
  379.  
  380.     rambase->device.dd_Library.lib_OpenCnt--;
  381.     AROS_LIBFUNC_EXIT
  382. }
  383.  
  384. AROS_LH0(BPTR, expunge, struct rambase *, rambase, 3, ramdev)
  385. {
  386.     AROS_LIBFUNC_INIT
  387.  
  388.     BPTR ret;
  389.     /*
  390.     This function is single-threaded by exec by calling Forbid.
  391.     Never break the Forbid() or strange things might happen.
  392.     */
  393.  
  394.     /* Test for openers. */
  395.     if(rambase->device.dd_Library.lib_OpenCnt)
  396.     {
  397.     /* Set the delayed expunge flag and return. */
  398.     rambase->device.dd_Library.lib_Flags|=LIBF_DELEXP;
  399.     return 0;
  400.     }
  401.  
  402.     /* Kill device task and free all resources */
  403.     RemTask(rambase->port->mp_SigTask);
  404.     FreeMem(rambase->sigsem,sizeof(struct SignalSemaphore));
  405.     FreeMem(((struct Task *)rambase->port->mp_SigTask)->tc_SPLower,2048);
  406.     FreeMem(rambase->port->mp_SigTask,sizeof(struct Task));
  407.     FreeMem(rambase->port,sizeof(struct MsgPort));
  408.     CloseLibrary((struct Library *)rambase->utilitybase);
  409.     CloseLibrary((struct Library *)rambase->dosbase);
  410.  
  411.     /* Get rid of the device. Remove it from the list. */
  412.     Remove(&rambase->device.dd_Library.lib_Node);
  413.  
  414.     /* Get returncode here - FreeMem() will destroy the field. */
  415.     ret=rambase->seglist;
  416.  
  417.     /* Free the memory. */
  418.     FreeMem((char *)rambase-rambase->device.dd_Library.lib_NegSize,
  419.         rambase->device.dd_Library.lib_NegSize+rambase->device.dd_Library.lib_PosSize);
  420.  
  421.     return ret;
  422.     AROS_LIBFUNC_EXIT
  423. }
  424.  
  425. AROS_LH0I(int, null, struct rambase *, rambase, 4, ramdev)
  426. {
  427.     AROS_LIBFUNC_INIT
  428.     return 0;
  429.     AROS_LIBFUNC_EXIT
  430. }
  431.  
  432. AROS_LH1(void, beginio,
  433.  AROS_LHA(struct IOFileSys *, iofs, A1),
  434.        struct rambase *, rambase, 5, ramdev)
  435. {
  436.     AROS_LIBFUNC_INIT
  437.  
  438.     /* WaitIO will look into this */
  439.     iofs->IOFS.io_Message.mn_Node.ln_Type=NT_MESSAGE;
  440.  
  441.     /* Nothing is done quick */
  442.     iofs->IOFS.io_Flags&=~IOF_QUICK;
  443.  
  444.     /* So let the device task do it */
  445.     PutMsg(rambase->port,&iofs->IOFS.io_Message);
  446.  
  447.     AROS_LIBFUNC_EXIT
  448. }
  449.  
  450. AROS_LH1(LONG, abortio,
  451.  AROS_LHA(struct IOFileSys *, iofs, A1),
  452.        struct rambase *, rambase, 6, ramdev)
  453. {
  454.     AROS_LIBFUNC_INIT
  455.     return 0;
  456.     AROS_LIBFUNC_EXIT
  457. }
  458.  
  459. static LONG getblock(struct rambase *rambase, struct fnode *file, LONG block, int mode, UBYTE **result)
  460. {
  461.     ULONG a, i;
  462.     UBYTE **p, **p2;
  463.  
  464.     if(block<0x10)
  465.     {
  466.     p=&file->blocks[block];
  467.     block=0;
  468.     i=0;
  469.     }else if(block<0x410)
  470.     {
  471.     block-=0x10;
  472.     p=(UBYTE **)&file->iblocks[block/0x100];
  473.     block&=0xff;
  474.     i=1;
  475.     }else if(block<0x10410)
  476.     {
  477.     block-=0x410;
  478.     p=(UBYTE **)&file->i2block;
  479.     i=2;
  480.     }else
  481.     {
  482.     block-=0x10410;
  483.     p=(UBYTE **)&file->i3block;
  484.     i=3;
  485.     }
  486.     switch(mode)
  487.     {
  488.     case -1:
  489.         p2=(UBYTE **)*p;
  490.         if(!block)
  491.         *p=NULL;
  492.         p=p2;
  493.         while(i--&&p!=NULL)
  494.         {
  495.         a=(block>>i*8)&0xff;
  496.         p2=(UBYTE **)p[a];
  497.         if(!(block&((1<<i*8)-1)))
  498.         {
  499.             p[a]=NULL;
  500.             if(!a)
  501.             FreeMem(p,PBLOCKSIZE);
  502.         }
  503.         p=p2;
  504.         }
  505.         if(p!=NULL)
  506.         FreeMem(p,BLOCKSIZE);
  507.         break;
  508.     case 0:
  509.         p=(UBYTE **)*p;
  510.         while(i--&&p!=NULL)
  511.         p=((UBYTE ***)p)[(block>>i*8)&0xff];
  512.         *result=(UBYTE *)p;
  513.         break;
  514.     case 1:
  515.         while(i--)
  516.         {
  517.         if(*p==NULL)
  518.         {
  519.             *p=AllocMem(PBLOCKSIZE,MEMF_CLEAR);
  520.             if(*p==NULL)
  521.             return ERROR_NO_FREE_STORE;
  522.         }
  523.         p=(UBYTE **)*p+((block>>i*8)&0xff);
  524.         }
  525.         if(*p==NULL)
  526.         {
  527.         *p=AllocMem(BLOCKSIZE,MEMF_CLEAR);
  528.         if(*p==NULL)
  529.             return ERROR_NO_FREE_STORE;
  530.         }
  531.         *result=*p;
  532.         break;
  533.     }
  534.     return 0;
  535. }
  536.  
  537. static void zerofill(UBYTE *address, ULONG size)
  538. {
  539.     while(size--)
  540.     *address++=0;
  541. }
  542.  
  543. static void shrinkfile(struct rambase *rambase, struct fnode *file, LONG size)
  544. {
  545.     ULONG blocks, block;
  546.     UBYTE *p;
  547.  
  548.     blocks=(size+BLOCKSIZE-1)/BLOCKSIZE;
  549.     block =(file->size+BLOCKSIZE-1)/BLOCKSIZE;
  550.     for(;block-->blocks;)
  551.     (void)getblock(rambase,file,block,-1,&p);
  552.     if(size&0xff)
  553.     {
  554.     (void)getblock(rambase,file,size,0,&p);
  555.     if(p!=NULL)
  556.         zerofill(p+(size&0xff),-size&0xff);
  557.     }
  558.     file->size=size;
  559. }
  560.  
  561. static void delete(struct rambase *rambase, struct fnode *file)
  562. {
  563.     struct hnode *link, *new, *more;
  564.     struct Node *node;
  565.  
  566.     Strfree(rambase,file->name);
  567.     Strfree(rambase,file->comment);
  568.     Remove((struct Node *)file);
  569.  
  570.     if(file->type==ST_LINKDIR)
  571.     {
  572.     /* It is a link. Remove it from the chain. */
  573.     link=((struct hnode *)file)->orig;
  574.     ((struct hnode *)file)->orig=NULL;
  575.     file->type=link->type;
  576.     while((struct fnode *)link->link!=file)
  577.         link=link->link;
  578.     link->link=file->link;
  579.     }else if(file->link!=NULL)
  580.     {
  581.     /* If there is a hard link to the object make the link the original */
  582.     link=file->link;
  583.     link->type=file->type;
  584.     more=new->link;
  585.     while(more!=NULL)
  586.     {
  587.         more->orig=new;
  588.         more=more->link;
  589.     }
  590.     switch(file->type)
  591.     {
  592.         case ST_USERDIR:
  593.         while((node=RemHead((struct List *)&((struct dnode *)file)->list))!=NULL)
  594.             AddTail((struct List *)&((struct dnode *)file)->list,node);
  595.         break;
  596.         case ST_FILE:
  597.         CopyMemQuick(&file->size,&((struct fnode *)new)->size,sizeof(struct fnode)-offsetof(struct fnode,size));
  598.         zerofill((UBYTE *)&file->size,sizeof(struct fnode)-offsetof(struct fnode,size));
  599.         break;
  600.         case ST_SOFTLINK:
  601.         ((struct snode *)new)->contents=((struct snode *)file)->contents;
  602.         ((struct snode *)file)->contents=NULL;
  603.         break;
  604.     }
  605.     }
  606.     switch(file->type)
  607.     {
  608.     case ST_USERDIR:
  609.         FreeMem(file,sizeof(struct dnode));
  610.         return;
  611.     case ST_FILE:
  612.         shrinkfile(rambase,file,0);
  613.         FreeMem(file,sizeof(struct fnode));
  614.         return;
  615.     case ST_SOFTLINK:
  616.         Strfree(rambase,((struct snode *)file)->contents);
  617.         FreeMem(file,sizeof(struct snode));
  618.         return;
  619.     }
  620. }
  621.  
  622. static int fstrcmp(struct rambase *rambase, char *s1, char *s2)
  623. {
  624.     for(;;)
  625.     {
  626.     if(ToLower(*s1)!=ToLower(*s2))
  627.         return *s1||*s2!='/';
  628.     if(!*s1)
  629.         return 0;
  630.     s1++; s2++;
  631.     }
  632. }
  633.  
  634. static LONG findname(struct rambase *rambase, STRPTR *name, struct dnode **dnode)
  635. {
  636.     struct dnode *cur=*dnode;
  637.     char *rest=*name;
  638.  
  639.     for(;;)
  640.     {
  641.     if(cur->type==ST_LINKDIR)
  642.         cur=(struct dnode *)((struct hnode *)cur)->orig;
  643.     if(!*rest)
  644.         break;
  645.     if(*rest=='/')
  646.     {
  647.         if((struct dnode *)cur->volume==cur)
  648.         return ERROR_OBJECT_NOT_FOUND;
  649.         while(cur->node.mln_Pred!=NULL)
  650.         cur=(struct dnode *)cur->node.mln_Pred;
  651.         cur=(struct dnode *)((BYTE *)cur-offsetof(struct dnode,list));
  652.     }else
  653.     {
  654.         if(cur->type==ST_SOFTLINK)
  655.         {
  656.         *dnode=cur;
  657.         *name=rest;
  658.         return ERROR_IS_SOFT_LINK;
  659.         }
  660.         if(cur->type!=ST_USERDIR)
  661.         return ERROR_DIR_NOT_FOUND;
  662.         *dnode=cur;
  663.         cur=(struct dnode *)cur->list.mlh_Head;
  664.         for(;;)
  665.         {
  666.         if(cur->node.mln_Succ==NULL)
  667.         {
  668.             *name=rest;
  669.             return ERROR_OBJECT_NOT_FOUND;
  670.         }
  671.         if(!fstrcmp(rambase,cur->name,rest))
  672.             break;
  673.         cur=(struct dnode *)cur->node.mln_Succ;
  674.         }
  675.     }
  676.     while(*rest)
  677.         if(*rest++=='/')
  678.             break;
  679.     }
  680.     *dnode=cur;
  681.     return 0;
  682. }
  683.  
  684. static LONG set_file_size(struct rambase *rambase, struct filehandle *handle, LONG *offl, LONG *offh, LONG mode)
  685. {
  686.     struct fnode *file=(struct fnode *)handle->node;
  687.     LONG size=*offl;
  688.  
  689.     if((size<0?-1:0)!=*offh)
  690.     return ERROR_SEEK_ERROR;
  691.  
  692.     if((size<0?-1:0)!=*offh)
  693.     return ERROR_SEEK_ERROR;
  694.  
  695.     if(file->type!=ST_FILE)
  696.     return ERROR_OBJECT_WRONG_TYPE;
  697.     switch(mode)
  698.     {
  699.     case OFFSET_BEGINNING:    break;
  700.     case OFFSET_CURRENT:    size+=handle->position; break;
  701.     case OFFSET_END:    size+=file->size; break;
  702.     default:        return ERROR_NOT_IMPLEMENTED;
  703.     }
  704.     if(size<0)
  705.     return ERROR_SEEK_ERROR;
  706.     if(size<file->size)
  707.     shrinkfile(rambase,file,size);
  708.     file->size=*offl=size;
  709.     *offh=0;
  710.     return 0;
  711. }
  712.  
  713. static LONG read(struct rambase *rambase, struct filehandle *handle, APTR buffer, LONG *numbytes)
  714. {
  715.     struct fnode *file=(struct fnode *)handle->node;
  716.     ULONG num =*numbytes;
  717.     ULONG size=file->size;
  718.     ULONG block, offset;
  719.     UBYTE *buf=buffer, *p;
  720.  
  721.     if(handle->position>=size)
  722.     num=0;
  723.     else if(handle->position+num>size)
  724.     num=size-handle->position;
  725.     block =handle->position/BLOCKSIZE;
  726.     offset=handle->position&(BLOCKSIZE-1);
  727.     size  =BLOCKSIZE-offset;
  728.     while(num)
  729.     {
  730.     if(size>num)
  731.         size=num;
  732.     (void)getblock(rambase,file,block,0,&p);
  733.     if(p!=NULL)
  734.         CopyMem(p+offset,buffer,size);
  735.     else
  736.         zerofill(buffer,size);
  737.     buffer+=size;
  738.     num   -=size;
  739.     block++;
  740.     offset=0;
  741.     size=BLOCKSIZE;
  742.     }
  743.     *numbytes=(UBYTE *)buffer-buf;
  744.     handle->position+=*numbytes;
  745.     return 0;
  746. }
  747.  
  748. static LONG write(struct rambase *rambase, struct filehandle *handle, UBYTE *buffer, LONG *numbytes)
  749. {
  750.     struct fnode *file=(struct fnode *)handle->node;
  751.     ULONG num =*numbytes;
  752.     ULONG size=file->size;
  753.     ULONG block, offset;
  754.     UBYTE *buf=buffer, *p;
  755.     LONG error=0;
  756.  
  757.     if((LONG)(handle->position+num)<0)
  758.     return ERROR_OBJECT_TOO_LARGE;
  759.     block =handle->position/BLOCKSIZE;
  760.     offset=handle->position&(BLOCKSIZE-1);
  761.     size  =BLOCKSIZE-offset;
  762.     while(num)
  763.     {
  764.     if(size>num)
  765.         size=num;
  766.     error=getblock(rambase,file,block,1,&p);
  767.     if(error)
  768.         break;
  769.     CopyMem(buffer,p+offset,size);
  770.     buffer+=size;
  771.     num   -=size;
  772.     block++;
  773.     offset=0;
  774.     size=BLOCKSIZE;
  775.     }
  776.     *numbytes=(UBYTE *)buffer-buf;
  777.     handle->position+=*numbytes;
  778.     if(handle->position>file->size)
  779.     file->size=handle->position;
  780.     return error;
  781. }
  782.  
  783. static LONG lock(struct dnode *dir, ULONG mode)
  784. {
  785.     if((mode&FMF_EXECUTE)&&!(dir->protect&FMF_EXECUTE))
  786.     return ERROR_NOT_EXECUTABLE;
  787.     if((mode&FMF_WRITE)&&!(dir->protect&FMF_WRITE))
  788.     return ERROR_WRITE_PROTECTED;
  789.     if((mode&FMF_READ)&&!(dir->protect&FMF_READ))
  790.     return ERROR_READ_PROTECTED;
  791.     if(mode&FMF_LOCK)
  792.     {
  793.     if(dir->usecount)
  794.         return ERROR_OBJECT_IN_USE;
  795.     dir->usecount=~0ul/2+1;
  796.     }else
  797.     if(dir->usecount<0)
  798.         return ERROR_OBJECT_IN_USE;
  799.     dir->usecount++;
  800.     dir->volume->volcount++;
  801.     return 0;
  802. }
  803.  
  804. static LONG open_(struct rambase *rambase, struct filehandle **handle, STRPTR name, ULONG mode)
  805. {
  806.     struct dnode *dir=(*handle)->node;
  807.     struct filehandle *fh;
  808.     LONG error;
  809.  
  810.     fh=(struct filehandle *)AllocMem(sizeof(struct filehandle),MEMF_CLEAR);
  811.     if(fh!=NULL)
  812.     {
  813.     error=findname(rambase,&name,&dir);
  814.     if(!error)
  815.     {
  816.         error=lock(dir,mode);
  817.         if(!error)
  818.         {
  819.         fh->node=dir;
  820.         *handle=fh;
  821.         return 0;
  822.         }
  823.     }
  824.     FreeMem(fh,sizeof(struct filehandle));
  825.     }else
  826.     error=ERROR_NO_FREE_STORE;
  827.     return error;
  828. }
  829.  
  830. static LONG open_file(struct rambase *rambase, struct filehandle **handle, STRPTR name, ULONG mode, ULONG protect)
  831. {
  832.     struct dnode *dir=(*handle)->node;
  833.     struct filehandle *fh;
  834.     LONG error;
  835.  
  836.     fh=AllocMem(sizeof(struct filehandle),MEMF_CLEAR);
  837.     if(fh!=NULL)
  838.     {
  839.     error=findname(rambase,&name,&dir);
  840.     if((mode&FMF_CREATE)&&error==ERROR_OBJECT_NOT_FOUND)
  841.     {
  842.         char *s=name;
  843.         struct fnode *file;
  844.         while(*s)
  845.         if(*s++=='/')
  846.             return error;
  847.         file=(struct fnode *)AllocMem(sizeof(struct fnode),MEMF_CLEAR);
  848.         if(file!=NULL)
  849.         {
  850.         file->name=Strdup(rambase,name);
  851.         if(file->name!=NULL)
  852.         {
  853.             file->type=ST_FILE;
  854.             file->protect=protect;
  855.             file->volume=dir->volume;
  856.             AddTail((struct List *)&dir->list,(struct Node *)file);
  857.             error=lock((struct dnode *)file,mode);
  858.             if(!error)
  859.             {
  860.             fh->node=(struct dnode *)file;
  861.             *handle=fh;
  862.             return 0;
  863.             }
  864.             Strfree(rambase,file->name);
  865.         }
  866.         FreeMem(file,sizeof(struct fnode));
  867.         }
  868.         error=ERROR_NO_FREE_STORE;
  869.     }else if(!error)
  870.     {
  871.         if(dir->type!=ST_FILE)
  872.         error=ERROR_OBJECT_WRONG_TYPE;
  873.         else
  874.         {
  875.         error=lock(dir,mode);
  876.         if(!error)
  877.         {
  878.             fh->node=dir;
  879.             *handle=fh;
  880.             return 0;
  881.         }
  882.         }
  883.     }
  884.     FreeMem(fh,sizeof(struct filehandle));
  885.     }
  886.     return error;
  887. }
  888.  
  889. static LONG create_dir(struct rambase *rambase, struct filehandle **handle, STRPTR name, ULONG protect)
  890. {
  891.     struct dnode *dir=(*handle)->node, *new;
  892.     struct filehandle *fh;
  893.     STRPTR s;
  894.     LONG error;
  895.  
  896.     error=findname(rambase,&name,&dir);
  897.     if(!error)
  898.     return ERROR_OBJECT_EXISTS;
  899.     if(error!=ERROR_OBJECT_NOT_FOUND)
  900.     return error;
  901.     s=name;
  902.     while(*s)
  903.     if(*s++=='/')
  904.         return error;
  905.     fh=AllocMem(sizeof(struct filehandle),MEMF_CLEAR);
  906.     if(fh!=NULL)
  907.     {
  908.     new=(struct dnode *)AllocMem(sizeof(struct dnode),MEMF_CLEAR);
  909.     if(new!=NULL)
  910.     {
  911.         new->name=Strdup(rambase,name);
  912.         if(new->name!=NULL)
  913.         {
  914.         new->type=ST_USERDIR;
  915.         new->protect=protect;
  916.         new->volume=dir->volume;
  917.         new->volume->volcount++;
  918.         new->usecount=~0ul/2+2;
  919.         NEWLIST((struct List *)&new->list);
  920.         AddTail((struct List *)&dir->list,(struct Node *)new);
  921.         fh->node=new;
  922.         *handle=fh;
  923.         return 0;
  924.         }
  925.         FreeMem(new,sizeof(struct dnode));
  926.     }
  927.     FreeMem(fh,sizeof(struct filehandle));
  928.     }
  929.     return ERROR_NO_FREE_STORE;
  930. }
  931.  
  932. static LONG free_lock(struct rambase *rambase, struct filehandle *filehandle)
  933. {
  934.     struct dnode *dnode=filehandle->node;
  935.     dnode->usecount=(dnode->usecount-1)&~0ul/2;
  936.     FreeMem(filehandle,sizeof(struct filehandle));
  937.     dnode->volume->volcount--;
  938.     return 0;
  939. }
  940.  
  941. static LONG seek(struct rambase *rambase, struct filehandle *filehandle, LONG *posh, LONG *posl, LONG mode)
  942. {
  943.     struct fnode *file=(struct fnode *)filehandle->node;
  944.     LONG pos=*posl;
  945.  
  946.     if((pos<0?-1:0)!=*posh)
  947.     return ERROR_SEEK_ERROR;
  948.     if(file->type!=ST_FILE)
  949.     return ERROR_OBJECT_WRONG_TYPE;
  950.     switch(mode)
  951.     {
  952.     case OFFSET_BEGINNING:    break;
  953.     case OFFSET_CURRENT:    pos+=filehandle->position; break;
  954.     case OFFSET_END:    pos+=file->size; break;
  955.     default:        return ERROR_NOT_IMPLEMENTED;
  956.     }
  957.     if(pos<0)
  958.     return ERROR_SEEK_ERROR;
  959.     *posh=0;
  960.     *posl=filehandle->position;
  961.     filehandle->position=pos;
  962.     return 0;
  963. }
  964.  
  965. static const ULONG sizes[]=
  966. { 0, offsetof(struct ExAllData,ed_Type), offsetof(struct ExAllData,ed_Size),
  967.   offsetof(struct ExAllData,ed_Prot), offsetof(struct ExAllData,ed_Days),
  968.   offsetof(struct ExAllData,ed_Comment), offsetof(struct ExAllData,ed_OwnerUID),
  969.   sizeof(struct ExAllData)
  970. };
  971.  
  972. static LONG examine(struct fnode *file, struct ExAllData *ead, ULONG size, ULONG type)
  973. {
  974.     STRPTR next, end, name;
  975.     if(type>ED_OWNER)
  976.     return ERROR_BAD_NUMBER;
  977.     next=(STRPTR)ead+sizes[type];
  978.     end=(STRPTR)ead+size;
  979.     switch(type)
  980.     {
  981.     case ED_OWNER:
  982.         ead->ed_OwnerUID=0;
  983.         ead->ed_OwnerGID=0;
  984.     case ED_COMMENT:
  985.         if(file->comment!=NULL)
  986.         {
  987.         ead->ed_Comment=next;
  988.         name=file->comment;
  989.         for(;;)
  990.         {
  991.             if(next>=end)
  992.             return ERROR_BUFFER_OVERFLOW;
  993.             if(!(*next++=*name++))
  994.             break;
  995.         }
  996.         }else
  997.         ead->ed_Comment=NULL;
  998.     case ED_DATE:
  999.         ead->ed_Days=0;
  1000.         ead->ed_Mins=0;
  1001.         ead->ed_Ticks=0;
  1002.     case ED_PROTECTION:
  1003.         ead->ed_Prot=file->protect;
  1004.     case ED_SIZE:
  1005.         ead->ed_Size=file->size;
  1006.     case ED_TYPE:
  1007.         ead->ed_Type=file->type;
  1008.         if(((struct vnode *)file)->self==(struct vnode *)file)
  1009.         ead->ed_Type=ST_ROOT;
  1010.     case ED_NAME:
  1011.         ead->ed_Name=next;
  1012.         name=file->name;
  1013.         for(;;)
  1014.         {
  1015.         if(next>=end)
  1016.             return ERROR_BUFFER_OVERFLOW;
  1017.         if(!(*next++=*name++))
  1018.             break;
  1019.         }
  1020.     case 0:
  1021.         ead->ed_Next=(struct ExAllData *)(((IPTR)next+AROS_PTRALIGN-1)&~(AROS_PTRALIGN-1));
  1022.     }
  1023.     return 0;
  1024. }
  1025.  
  1026. static LONG examine_all(struct filehandle *dir, struct ExAllData *ead, ULONG size, ULONG type)
  1027. {
  1028.     STRPTR end;
  1029.     struct ExAllData *last=NULL;
  1030.     struct fnode *ent;
  1031.     LONG error;
  1032.     end=(STRPTR)ead+size;
  1033.     if(dir->node->type!=ST_USERDIR)
  1034.     return ERROR_OBJECT_WRONG_TYPE;
  1035.     ent=(struct fnode *)dir->position;
  1036.     if(ent==NULL)
  1037.     {
  1038.     ent=(struct fnode *)dir->node->list.mlh_Head;
  1039.     ent->usecount++;
  1040.     }
  1041.     if(ent->node.mln_Succ==NULL)
  1042.     return ERROR_NO_MORE_ENTRIES;
  1043.     ent->usecount--;
  1044.     do
  1045.     {
  1046.     error=examine(ent,ead,end-(STRPTR)ead,type);
  1047.     if(error==ERROR_BUFFER_OVERFLOW)
  1048.     {
  1049.         if(last==NULL)
  1050.         return error;
  1051.         ent->usecount++;
  1052.         last->ed_Next=NULL;
  1053.         dir->position=(IPTR)ent;
  1054.         return 0;
  1055.     }
  1056.     last=ead;
  1057.     ead=ead->ed_Next;
  1058.     ent=(struct fnode *)ent->node.mln_Succ;
  1059.     }while(ent->node.mln_Succ!=NULL);
  1060.     last->ed_Next=NULL;
  1061.     dir->position=(IPTR)ent;
  1062.     return 0;
  1063. }
  1064.  
  1065. static LONG delete_object(struct rambase *rambase, struct filehandle *filehandle, STRPTR name)
  1066. {
  1067.     struct dnode *file=filehandle->node;
  1068.     LONG error;
  1069.     error=findname(rambase,&name,&file);
  1070.     if(error)
  1071.     return error;
  1072.     if((struct dnode *)file->volume==file)
  1073.     return ERROR_OBJECT_WRONG_TYPE;
  1074.     if(file->usecount)
  1075.     return ERROR_OBJECT_IN_USE;
  1076.     if(!(file->protect&FIBF_DELETE))
  1077.     return ERROR_DELETE_PROTECTED;
  1078.     if(file->type==ST_USERDIR&&file->list.mlh_Head->mln_Succ!=NULL)
  1079.     return ERROR_DIRECTORY_NOT_EMPTY;
  1080.     delete(rambase,(struct fnode *)file);
  1081.     return 0;
  1082. }
  1083.  
  1084. AROS_LH1(BPTR, close,
  1085.  AROS_LHA(struct IOFileSys *, iofs, A1),
  1086.        struct rambase *, rambase, 2, ramdev)
  1087. {
  1088.     AROS_LIBFUNC_INIT
  1089.     struct cnode *dev;
  1090.     struct vnode *vol;
  1091.     struct dnode *dir;
  1092.     struct fnode *file;
  1093.     struct filehandle *handle;
  1094.  
  1095.     handle=(struct filehandle *)iofs->IOFS.io_Unit;
  1096.     dev=(struct cnode *)handle->node;
  1097.     vol=dev->volume;
  1098.     if(dev->type!=ST_LINKDIR||dev->self!=dev)
  1099.     {
  1100.     iofs->io_DosError=ERROR_OBJECT_WRONG_TYPE;
  1101.     return 0;
  1102.     }
  1103.     if(vol->volcount)
  1104.     {
  1105.     iofs->io_DosError=ERROR_OBJECT_IN_USE;
  1106.     return 0;
  1107.     }
  1108.  
  1109.     /* Let any following attemps to use the device crash hard. */
  1110.     iofs->IOFS.io_Device=(struct Device *)-1;
  1111.  
  1112.     free_lock(rambase,handle);
  1113.     RemDosEntry(vol->doslist);
  1114.     FreeDosEntry(vol->doslist);
  1115.  
  1116.     while(vol->list.mlh_Head->mln_Succ!=NULL)
  1117.     {
  1118.     dir=(struct dnode *)vol->list.mlh_Head;
  1119.     if(dir->type==ST_USERDIR)
  1120.         while((file=(struct fnode *)RemHead((struct List *)&dir->list))!=NULL)
  1121.         AddTail((struct List *)&vol->list,(struct Node *)dir);
  1122.     delete(rambase,(struct fnode *)dir);
  1123.     }
  1124.     Strfree(rambase,vol->name);
  1125.     FreeMem(vol,sizeof(struct vnode));
  1126.  
  1127.     Strfree(rambase,dev->name);
  1128.     FreeMem(dev,sizeof(struct cnode));
  1129.  
  1130.     iofs->io_DosError=0;
  1131.  
  1132.     /* I have one fewer opener. */
  1133.     if(!--rambase->device.dd_Library.lib_OpenCnt)
  1134.     {
  1135.     /* Delayed expunge pending? */
  1136.     if(rambase->device.dd_Library.lib_Flags&LIBF_DELEXP)
  1137.         /* Then expunge the device */
  1138.         return expunge();
  1139.     }
  1140.     return 0;
  1141.     AROS_LIBFUNC_EXIT
  1142. }
  1143.  
  1144. void deventry(struct rambase *rambase)
  1145. {
  1146.     struct IOFileSys *iofs;
  1147.     struct dnode *dir;
  1148.     LONG error=0;
  1149.     /*
  1150.     Init device port. AllocSignal() cannot fail because this is a
  1151.     freshly created task with all signal bits still free.
  1152.     */
  1153.     rambase->port->mp_SigBit=AllocSignal(-1);
  1154.     rambase->port->mp_Flags=PA_SIGNAL;
  1155.  
  1156.     /* Get and process the messages. */
  1157.     for(;;)
  1158.     {
  1159.     while((iofs=(struct IOFileSys *)GetMsg(rambase->port))!=NULL)
  1160.     {
  1161.         switch(iofs->IOFS.io_Command)
  1162.         {
  1163.         case FSA_OPEN:
  1164.             /*
  1165.             get handle on a file or directory
  1166.             Unit *current; current directory / new handle on return
  1167.             STRPTR name;   file- or directoryname
  1168.             LONG mode;     open mode
  1169.             */
  1170.             error=open_(rambase,(struct filehandle **)&iofs->IOFS.io_Unit,
  1171.                       (STRPTR)iofs->io_Args[0], iofs->io_Args[1]);
  1172.             break;
  1173.  
  1174.         case FSA_OPEN_FILE:
  1175.             /*
  1176.             open a file or create a new one
  1177.             Unit *current; current directory / new handle on return
  1178.             STRPTR name;   file- or directoryname
  1179.             LONG mode;     open mode
  1180.             LONG protect;  protection flags if a new file is created
  1181.             */
  1182.             error=open_file(rambase,(struct filehandle **)&iofs->IOFS.io_Unit,
  1183.                       (STRPTR)iofs->io_Args[0], iofs->io_Args[1],
  1184.                       iofs->io_Args[2]);
  1185.             break;
  1186.  
  1187.         case FSA_READ:
  1188.             /*
  1189.             read a number of bytes from a file
  1190.             Unit *current; filehandle
  1191.             APTR buffer;   data
  1192.             LONG numbytes; number of bytes to read /
  1193.                        number of bytes read on return,
  1194.                        0 if there are no more bytes in the file
  1195.             */
  1196.             error=read(rambase,(struct filehandle *)iofs->IOFS.io_Unit,
  1197.                  (APTR)iofs->io_Args[0], &iofs->io_Args[1]);
  1198.             break;
  1199.  
  1200.         case FSA_WRITE:
  1201.             /*
  1202.             write a number of bytes to a file
  1203.             Unit *current; filehandle
  1204.             APTR buffer;   data
  1205.             LONG numbytes; number of bytes to write /
  1206.                        number of bytes written on return
  1207.             */
  1208.             error=write(rambase,(struct filehandle *)iofs->IOFS.io_Unit,
  1209.                   (APTR)iofs->io_Args[0], &iofs->io_Args[1]);
  1210.             break;
  1211.  
  1212.         case FSA_SEEK:
  1213.             /*
  1214.             set / read position in file
  1215.             Unit *current; filehandle
  1216.             LONG posh;
  1217.             LONG posl;     relative position /
  1218.                        old position on return
  1219.             LONG mode;     one of OFFSET_BEGINNING, OFFSET_CURRENT,
  1220.                        OFFSET_END
  1221.             */
  1222.             error=seek(rambase,(struct filehandle *)iofs->IOFS.io_Unit,
  1223.                  &iofs->io_Args[0], &iofs->io_Args[1], iofs->io_Args[2]);
  1224.             break;
  1225.  
  1226.         case FSA_CLOSE:
  1227.             /*
  1228.             get rid of a handle
  1229.             Unit *current; filehandle
  1230.             */
  1231.             error=free_lock(rambase,(struct filehandle *)iofs->IOFS.io_Unit);
  1232.             break;
  1233.  
  1234.         case FSA_EXAMINE:
  1235.             /*
  1236.             Get information about the current object
  1237.             Unit *current; current object
  1238.             struct ExAllData *ead; buffer to be filled
  1239.             ULONG size;    size of the buffer
  1240.             ULONG type;    type of information to get
  1241.             */
  1242.             error=examine((struct fnode *)((struct filehandle *)iofs->IOFS.io_Unit)->node,
  1243.                   (struct ExAllData*)iofs->io_Args[0],
  1244.                   iofs->io_Args[1], iofs->io_Args[2]);
  1245.             break;
  1246.  
  1247.         case FSA_EXAMINE_ALL:
  1248.             /*
  1249.             Read the current directory
  1250.             Unit *current; current directory
  1251.             struct ExAllData *ead; buffer to be filled
  1252.             ULONG size;    size of the buffer
  1253.             ULONG type;    type of information to get
  1254.             */
  1255.             error=examine_all((struct filehandle *)iofs->IOFS.io_Unit,
  1256.                       (struct ExAllData*)iofs->io_Args[0],
  1257.                       iofs->io_Args[1], iofs->io_Args[2]);
  1258.             break;
  1259.  
  1260.         case FSA_CREATE_DIR:
  1261.             /*
  1262.             Build lock and open a new directory
  1263.             Unit *current; current directory
  1264.             STRPTR name;   name of the dir to create
  1265.             LONG protect;  Protection flags for the new dir
  1266.             */
  1267.             error=create_dir(rambase,(struct filehandle **)&iofs->IOFS.io_Unit,
  1268.                      (STRPTR)iofs->io_Args[0], iofs->io_Args[1]);
  1269.             break;
  1270.  
  1271.         case FSA_DELETE_OBJECT:
  1272.             /*
  1273.             Delete file or directory
  1274.             Unit *current; current directory
  1275.             STRPTR name;   filename
  1276.             */
  1277.             error=delete_object(rambase,(struct filehandle *)iofs->IOFS.io_Unit,
  1278.                     (STRPTR)iofs->io_Args[0]);
  1279.             break;
  1280.  
  1281.         case FSA_SET_PROTECT:
  1282.             /*
  1283.             Set protection bits for a certain file or directory.
  1284.             Unit *current; current directory
  1285.             STRPTR name;   filename
  1286.             ULONG protect; new protection bits
  1287.             */
  1288.             dir=((struct filehandle *)iofs->IOFS.io_Unit)->node;
  1289.             error=findname(rambase,(STRPTR *)&iofs->io_Args[0],&dir);
  1290.             if(!error)
  1291.             dir->protect=iofs->io_Args[1];
  1292.             break;
  1293.  
  1294.         case FSA_SET_OWNER:
  1295.             /*
  1296.             Set owner and group of the file or directory
  1297.             Unit *current; current directory
  1298.             STRPTR name;   filename
  1299.             ULONG UID;
  1300.             ULONG GID;
  1301.             */
  1302.             dir=((struct filehandle *)iofs->IOFS.io_Unit)->node;
  1303.             error=findname(rambase,(STRPTR *)&iofs->io_Args[0],&dir);
  1304.             if(!error)
  1305.             {
  1306.             }
  1307.             break;
  1308.  
  1309.         case FSA_SET_DATE:
  1310.             /*
  1311.             Set creation date of the file
  1312.             Unit *current; current directory
  1313.             STRPTR name;   filename
  1314.             ULONG days;
  1315.             ULONG mins;
  1316.             ULONG ticks;   timestamp
  1317.             */
  1318.             dir=((struct filehandle *)iofs->IOFS.io_Unit)->node;
  1319.             error=findname(rambase,(STRPTR *)&iofs->io_Args[0],&dir);
  1320.             if(!error)
  1321.             {
  1322.             }
  1323.             break;
  1324.  
  1325.         case FSA_SET_COMMENT:
  1326.             /*
  1327.             Set a comment for the file or directory;
  1328.             Unit *current; current directory
  1329.             STRPTR name;   filename
  1330.             STRPTR comment; NUL terminated C string or NULL.
  1331.             */
  1332.             dir=((struct filehandle *)iofs->IOFS.io_Unit)->node;
  1333.             error=findname(rambase,(STRPTR *)&iofs->io_Args[0],&dir);
  1334.             if(!error)
  1335.             {
  1336.             if(iofs->io_Args[1])
  1337.             {
  1338.                 STRPTR s=Strdup(rambase,(STRPTR)iofs->io_Args[0]);
  1339.                 if(s!=NULL)
  1340.                 {
  1341.                 Strfree(rambase,dir->comment);
  1342.                 dir->comment=s;
  1343.                 }else
  1344.                 error=ERROR_NO_FREE_STORE;
  1345.             }else
  1346.             {
  1347.                 Strfree(rambase,dir->comment);
  1348.                 dir->comment=NULL;
  1349.             }
  1350.             }
  1351.             break;
  1352.  
  1353.         case FSA_SET_FILE_SIZE:
  1354.             /*
  1355.             Set a new size for the file.
  1356.             Unit *file;    filehandle
  1357.             LONG offh;
  1358.             LONG offl;     offset to current position/
  1359.                        new size on return
  1360.             LONG mode;     relative to what (see Seek)
  1361.             */
  1362.             error=set_file_size(rambase,(struct filehandle *)iofs->IOFS.io_Unit,
  1363.                     &iofs->io_Args[0],&iofs->io_Args[1],iofs->io_Args[2]);
  1364.             break;
  1365.  
  1366.         default:
  1367.             error=ERROR_NOT_IMPLEMENTED;
  1368.             break;
  1369. /*
  1370.   FSA_FILE_MODE
  1371.     Change or read the mode of a single filehandle
  1372.     Unit *current; filehandle to change
  1373.     ULONG newmode; new mode/old mode on return
  1374.     ULONG mask;    bits affected
  1375.  
  1376.   FSA_MOUNT_MODE
  1377.     Change or read the mode of the filesystem
  1378.     Unit *current; filesystem to change
  1379.     ULONG newmode; new mode/old mode on return
  1380.     ULONG mask;    bits affected
  1381.     STRPTR passwd; password for MMF_LOCKED
  1382.  
  1383.   FSA_MAKE_HARDLINK
  1384.     Create a hard link on a file, directory or soft link
  1385.     Unit *current; current directory
  1386.     STRPTR name;   softlink name
  1387.     Unit *target;  target handle
  1388.  
  1389.   FSA_MAKE_SOFTLINK
  1390.     Create a soft link to another object
  1391.     Unit *current; current directory
  1392.     STRPTR name;   softlink name
  1393.     STRPTR target; target name
  1394.  
  1395.   FSA_RENAME
  1396.   FSA_READ_LINK
  1397.   FSA_DISK_INFO
  1398.   FSA_SERIALIZE_DISK
  1399.   FSA_WAIT_CHAR
  1400.   FSA_INFO
  1401.   FSA_TIMER
  1402.   FSA_DISK_TYPE
  1403.   FSA_DISK_CHANGE
  1404.   FSA_SAME_LOCK
  1405.   FSA_CHANGE_SIGNAL
  1406.   FSA_FORMAT
  1407.   FSA_IS_FILESYSTEM
  1408.   FSA_EXAMINE_ALL
  1409.   FSA_EXAMINE_FH
  1410.   FSA_ADD_NOTIFY
  1411.   FSA_REMOVE_NOTIFY
  1412.   FSA_EXAMINE_ALL_END
  1413.  
  1414. */
  1415.         }
  1416.         iofs->io_DosError=error;
  1417.         ReplyMsg(&iofs->IOFS.io_Message);
  1418.     }
  1419. #if 0
  1420.     if(rambase->iofs!=NULL)
  1421.     {
  1422.         iofs=rambase->iofs;
  1423.         if(iofs->IOFS.io_Message.mn_Node.ln_Type==NT_MESSAGE)
  1424.         {
  1425.         abort_notify(rambase,iofs);
  1426.         iofs->io_DosError=ERROR_BREAK;
  1427.         rambase->iofs=NULL;
  1428.         ReplyMsg(&iofs->IOFS.io_Message);
  1429.         }else
  1430.         {
  1431.         rambase->iofs=NULL;
  1432.         Signal(1,0);
  1433.         }
  1434.     }
  1435. #endif
  1436.     Wait(1<<rambase->port->mp_SigBit);
  1437.     }
  1438. }
  1439.  
  1440. const char end=0;
  1441.