home *** CD-ROM | disk | FTP | other *** search
/ MACD 4 / MACD4.iso / Emulatory / AROS / filesys / ramdev.c < prev   
Encoding:
C/C++ Source or Header  |  1978-03-06  |  31.1 KB  |  1,305 lines

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