home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / rom / devs / filesys / emul_handler.c < prev    next >
C/C++ Source or Header  |  1997-02-03  |  16KB  |  697 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: emul_handler.c,v 1.20 1997/02/02 10:17:02 iaint Exp $
  4.  
  5.     Desc: Emulation filesystem.
  6.     Lang: english
  7. */
  8. #include <aros/system.h>
  9. #include <exec/resident.h>
  10. #include <exec/memory.h>
  11. #include <proto/exec.h>
  12. #include <utility/tagitem.h>
  13. #include <dos/dosextens.h>
  14. #include <dos/filesystem.h>
  15. #include <dos/exall.h>
  16. #include <dos/dosasl.h>
  17. #include <proto/dos.h>
  18. #include <aros/libcall.h>
  19. #include <unistd.h>
  20. #include <fcntl.h>
  21. #include <dirent.h>
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <stddef.h>
  25. #include <errno.h>
  26. #define timeval sys_timeval
  27. #include <sys/stat.h>
  28. #include <sys/time.h>
  29. #undef timeval
  30. #ifdef __GNUC__
  31. #   include "emul_handler_gcc.h"
  32. #endif
  33.  
  34. static const char name[];
  35. static const char version[];
  36. static const APTR inittabl[4];
  37. static void *const functable[];
  38. static const UBYTE datatable;
  39.  
  40. struct emulbase * AROS_SLIB_ENTRY(init,emul_handler) ();
  41. void AROS_SLIB_ENTRY(open,emul_handler) ();
  42. BPTR AROS_SLIB_ENTRY(close,emul_handler) ();
  43. BPTR AROS_SLIB_ENTRY(expunge,emul_handler) ();
  44. int AROS_SLIB_ENTRY(null,emul_handler) ();
  45. void AROS_SLIB_ENTRY(beginio,emul_handler) ();
  46. LONG AROS_SLIB_ENTRY(abortio,emul_handler) ();
  47.  
  48. static const char end;
  49.  
  50. struct filehandle
  51. {
  52.     char *name;
  53.     int type;
  54.     long fd;
  55. };
  56. #define FHD_FILE    0
  57. #define FHD_DIRECTORY    1
  58.  
  59. int emul_handler_entry(void)
  60. {
  61.     /* If the device was executed by accident return error code. */
  62.     return -1;
  63. }
  64.  
  65. const struct Resident emul_handler_resident=
  66. {
  67.     RTC_MATCHWORD,
  68.     (struct Resident *)&emul_handler_resident,
  69.     (APTR)&end,
  70.     RTF_AUTOINIT,
  71.     1,
  72.     NT_LIBRARY,
  73.     0,
  74.     (char *)name,
  75.     (char *)&version[6],
  76.     (ULONG *)inittabl
  77. };
  78.  
  79. static const char name[]="emul.handler";
  80.  
  81. static const char version[]="$VER: emul_handler 1.0 (28.3.96)\n\015";
  82.  
  83. static const APTR inittabl[4]=
  84. {
  85.     (APTR)sizeof(struct emulbase),
  86.     (APTR)functable,
  87.     (APTR)&datatable,
  88.     &AROS_SLIB_ENTRY(init,emul_handler)
  89. };
  90.  
  91. static void *const functable[]=
  92. {
  93.     &AROS_SLIB_ENTRY(open,emul_handler),
  94.     &AROS_SLIB_ENTRY(close,emul_handler),
  95.     &AROS_SLIB_ENTRY(expunge,emul_handler),
  96.     &AROS_SLIB_ENTRY(null,emul_handler),
  97.     &AROS_SLIB_ENTRY(beginio,emul_handler),
  98.     &AROS_SLIB_ENTRY(abortio,emul_handler),
  99.     (void *)-1
  100. };
  101.  
  102. static const UBYTE datatable=0;
  103.  
  104. LONG u2a[][2]=
  105. {
  106.   { ENOMEM, ERROR_NO_FREE_STORE },
  107.   { ENOENT, ERROR_OBJECT_NOT_FOUND },
  108.   { 0, 0 }
  109. };
  110.  
  111. LONG err_u2a(void)
  112. {
  113.     ULONG i;
  114.     for(i=0;i<sizeof(u2a)/sizeof(u2a[0]);i++)
  115.     if(u2a[i][0]==errno)
  116.         break;
  117.     return u2a[i][1];
  118. }
  119.  
  120. static void shrink(char *filename)
  121. {
  122.     char *s1,*s2;
  123.     unsigned long len;
  124.     for(;;)
  125.     {
  126.     while(*filename=='/')
  127.         memmove(filename,filename+1,strlen(filename));
  128.     s1=strstr(filename,"//");
  129.     if(s1==NULL)
  130.         break;
  131.     s2=s1;
  132.     while(s2>filename&&*--s2!='/')
  133.         ;
  134.     memmove(s2,s1+2,strlen(s1+1));
  135.     }
  136.     len=strlen(filename);
  137.     if(len&&filename[len-1]=='/')
  138.     filename[len-1]=0;
  139. }
  140.  
  141. static LONG open_(struct filehandle **handle,STRPTR name,LONG mode)
  142. {
  143.     LONG ret=ERROR_NO_FREE_STORE;
  144.     struct filehandle *fh;
  145.     struct stat st;
  146.     long flags;
  147.     fh=(struct filehandle *)malloc(sizeof(struct filehandle));
  148.     if(fh!=NULL)
  149.     {
  150.     if(!*name&&(*handle)->type==FHD_FILE&&((*handle)->fd==STDIN_FILENO||
  151.        (*handle)->fd==STDOUT_FILENO||(*handle)->fd==STDERR_FILENO))
  152.     {
  153.         fh->type=FHD_FILE;
  154.         fh->fd=(*handle)->fd;
  155.         fh->name="";
  156.         *handle=fh;
  157.         return 0;
  158.     }
  159.     fh->name=(char *)malloc(strlen((*handle)->name)+strlen(name)+2);
  160.     if(fh->name!=NULL)
  161.     {
  162.         strcpy(fh->name,(*handle)->name);
  163.         strcat(fh->name,"/");
  164.         strcat(fh->name,name);
  165.         shrink(fh->name);
  166.         if(!stat(*fh->name?fh->name:".",&st))
  167.         {
  168.         if(S_ISREG(st.st_mode))
  169.         {
  170.             fh->type=FHD_FILE;
  171.             flags=(mode&FMF_CREATE?O_CREAT:0)|
  172.               (mode&FMF_CLEAR?O_TRUNC:0);
  173.             if(mode&FMF_WRITE)
  174.             flags|=mode&FMF_READ?O_RDWR:O_WRONLY;
  175.             else
  176.             flags|=O_RDONLY;
  177.             fh->fd=open(*fh->name?fh->name:".",flags,0770);
  178.             if(fh->fd>=0)
  179.             {
  180.             *handle=fh;
  181.             return 0;
  182.             }
  183.         }else if(S_ISDIR(st.st_mode))
  184.         {
  185.             fh->type=FHD_DIRECTORY;
  186.             fh->fd=(long)opendir(*fh->name?fh->name:".");
  187.             if(fh->fd)
  188.             {
  189.             *handle=fh;
  190.             return 0;
  191.             }
  192.         }else
  193.             errno=ENOENT;
  194.         }
  195.         ret=err_u2a();
  196.         free(fh->name);
  197.     }
  198.     free(fh);
  199.     }
  200.     return ret;
  201. }
  202.  
  203. static LONG open_file(struct filehandle **handle,STRPTR name,LONG mode,LONG protect)
  204. {
  205.     LONG ret=ERROR_NO_FREE_STORE;
  206.     struct filehandle *fh;
  207.     long flags;
  208.     fh=(struct filehandle *)malloc(sizeof(struct filehandle));
  209.     if(fh!=NULL)
  210.     {
  211.     if(!*name&&(*handle)->type==FHD_FILE&&((*handle)->fd==STDIN_FILENO||
  212.        (*handle)->fd==STDOUT_FILENO||(*handle)->fd==STDERR_FILENO))
  213.     {
  214.         fh->type=FHD_FILE;
  215.         fh->fd=(*handle)->fd;
  216.         fh->name="";
  217.         *handle=fh;
  218.         return 0;
  219.     }
  220.     fh->name=(char *)malloc(strlen((*handle)->name)+strlen(name)+2);
  221.     if(fh->name!=NULL)
  222.     {
  223.         strcpy(fh->name,(*handle)->name);
  224.         strcat(fh->name,"/");
  225.         strcat(fh->name,name);
  226.         shrink(fh->name);
  227.         fh->type=FHD_FILE;
  228.         flags=(mode&FMF_CREATE?O_CREAT:0)|
  229.           (mode&FMF_CLEAR?O_TRUNC:0);
  230.         if(mode&FMF_WRITE)
  231.         flags|=mode&FMF_READ?O_RDWR:O_WRONLY;
  232.         else
  233.         flags|=O_RDONLY;
  234.         fh->fd=open(fh->name,flags,0770);
  235.         if(fh->fd>=0)
  236.         {
  237.         *handle=fh;
  238.         return 0;
  239.         }
  240.         ret=err_u2a();
  241.         free(fh->name);
  242.     }
  243.     free(fh);
  244.     }
  245.     return ret;
  246. }
  247.  
  248. static LONG free_lock(struct filehandle *current)
  249. {
  250.     switch(current->type)
  251.     {
  252.     case FHD_FILE:
  253.         if(current->fd!=STDIN_FILENO&¤t->fd!=STDOUT_FILENO&&
  254.            current->fd!=STDERR_FILENO)
  255.         {
  256.         close(current->fd);
  257.         free(current->name);
  258.         }
  259.         break;
  260.     case FHD_DIRECTORY:
  261.         closedir((DIR *)current->fd);
  262.         free(current->name);
  263.         break;
  264.     }
  265.     free(current);
  266.     return 0;
  267. }
  268.  
  269. static LONG startup(struct emulbase *emulbase)
  270. {
  271.     struct filehandle *fhi, *fho, *fhe, *fhv, *fhc, *fhs;
  272.     struct DosList *dlv, *dlc;
  273.     static struct filehandle sys={ "", FHD_DIRECTORY, 0 };
  274.     LONG ret=ERROR_NO_FREE_STORE;
  275.  
  276.     fhi=(struct filehandle *)malloc(sizeof(struct filehandle));
  277.     if(fhi!=NULL)
  278.     {
  279.     fho=(struct filehandle *)malloc(sizeof(struct filehandle));
  280.     if(fho!=NULL)
  281.     {
  282.         fhe=(struct filehandle *)malloc(sizeof(struct filehandle));
  283.         if(fhe!=NULL)
  284.         {
  285.         fhv=&sys;
  286.         ret=open_(&fhv,"",0);
  287.         if(!ret)
  288.         {
  289.             fhc=&sys;
  290.             ret=open_(&fhc,"",0);
  291.             if(!ret)
  292.             {
  293.             fhs=&sys;
  294.             ret=open_(&fhs,"",0);
  295.             if(!ret)
  296.             {
  297.                 ret=ERROR_NO_FREE_STORE;
  298.                 dlv=MakeDosEntry("Workbench",DLT_VOLUME);
  299.                 if(dlv!=NULL)
  300.                 {
  301.                 dlc=MakeDosEntry("SYS",DLT_DEVICE);
  302.                 if(dlc!=NULL)
  303.                 {
  304.                     ret=ERROR_OBJECT_EXISTS;
  305.                     dlv->dol_Unit  =(struct Unit *)fhv;
  306.                     dlv->dol_Device=&emulbase->device;
  307.                     dlc->dol_Unit  =(struct Unit *)fhc;
  308.                     dlc->dol_Device=&emulbase->device;
  309.                     fhi->type=FHD_FILE;
  310.                     fhi->fd=STDIN_FILENO;
  311.                     fhi->name="";
  312.                     emulbase->stdin=(struct Unit *)fhi;
  313.                     fho->type=FHD_FILE;
  314.                     fho->fd=STDOUT_FILENO;
  315.                     fho->name="";
  316.                     emulbase->stdout=(struct Unit *)fho;
  317.                     fhe->type=FHD_FILE;
  318.                     fhe->fd=STDERR_FILENO;
  319.                     fhe->name="";
  320.                     emulbase->stderr=(struct Unit *)fhe;
  321.                     if(AddDosEntry(dlv))
  322.                     {
  323.                     if(AddDosEntry(dlc))
  324.                     {
  325.                         DOSBase->dl_NulHandler=&emulbase->device;
  326.                         DOSBase->dl_NulLock   =(struct Unit *)fhs;
  327.                         return 0;
  328.                     }
  329.                     RemDosEntry(dlv);
  330.                     }
  331.                     FreeDosEntry(dlc);
  332.                 }
  333.                 FreeDosEntry(dlv);
  334.                 }
  335.                 free_lock(fhs);
  336.             }
  337.             free_lock(fhc);
  338.             }
  339.             free_lock(fhv);
  340.         }
  341.         free(fhe);
  342.         }
  343.         free(fho);
  344.     }
  345.     free(fhi);
  346.     }
  347.     return ret;
  348. }
  349.  
  350. static const ULONG sizes[]=
  351. { 0, offsetof(struct ExAllData,ed_Type), offsetof(struct ExAllData,ed_Size),
  352.   offsetof(struct ExAllData,ed_Prot), offsetof(struct ExAllData,ed_Days),
  353.   offsetof(struct ExAllData,ed_Comment), offsetof(struct ExAllData,ed_OwnerUID),
  354.   sizeof(struct ExAllData) };
  355.  
  356. static LONG examine(struct filehandle *fh,struct ExAllData *ead,ULONG size,ULONG type)
  357. {
  358.     STRPTR next, end, last, name;
  359.     struct stat st;
  360.     if(type>ED_OWNER)
  361.     return ERROR_BAD_NUMBER;
  362.     next=(STRPTR)ead+sizes[type];
  363.     end =(STRPTR)ead+size;
  364.     if(next>=end)
  365.     return ERROR_BUFFER_OVERFLOW;
  366.     if(lstat(*fh->name?fh->name:".",&st))
  367.     return err_u2a();
  368.     switch(type)
  369.     {
  370.     default:
  371.     case ED_OWNER:
  372.         ead->ed_OwnerUID=st.st_uid;
  373.         ead->ed_OwnerGID=st.st_gid;
  374.     case ED_COMMENT:
  375.         ead->ed_Comment=NULL;
  376.     case ED_DATE:
  377.         ead->ed_Days=st.st_ctime/(60*60*24)-(6*365+2*366);
  378.         ead->ed_Mins=(st.st_ctime/60)%(60*24);
  379.         ead->ed_Ticks=(st.st_ctime%60)*TICKS_PER_SECOND;
  380.     case ED_PROTECTION:
  381.         ead->ed_Prot=(st.st_mode&S_IRUSR?FIBF_READ:0)|
  382.              (st.st_mode&S_IWUSR?FIBF_WRITE:0)|
  383.              (st.st_mode&S_IXUSR?FIBF_EXECUTE:0)|
  384.              FIBF_SCRIPT|FIBF_DELETE;
  385.     case ED_SIZE:
  386.         ead->ed_Size=st.st_size;
  387.     case ED_TYPE:
  388.         ead->ed_Type=S_ISREG(st.st_mode)?ST_FILE:
  389.              S_ISDIR(st.st_mode)?(*fh->name?ST_USERDIR:ST_ROOT):0;
  390.     case ED_NAME:
  391.         ead->ed_Name=next;
  392.         last=name=*fh->name?fh->name:"Workbench";
  393.         while(*name)
  394.         if(*name++=='/')
  395.             last=name;
  396.         for(;;)
  397.         {
  398.         if(next>=end)
  399.             return ERROR_BUFFER_OVERFLOW;
  400.         if(!(*next++=*last++))
  401.             break;
  402.         }
  403.     case 0:
  404.         ead->ed_Next=(struct ExAllData *)(((IPTR)next+AROS_PTRALIGN-1)&~(AROS_PTRALIGN-1));
  405.         return 0;
  406.     }
  407. }
  408.  
  409. static LONG examine_all(struct filehandle *fh,struct ExAllData *ead,ULONG size,ULONG type)
  410. {
  411.     struct ExAllData *last=NULL;
  412.     STRPTR end=(STRPTR)ead+size, name, old;
  413.     off_t oldpos;
  414.     struct dirent *dir;
  415.     LONG error;
  416.     if(fh->type!=FHD_DIRECTORY)
  417.     return ERROR_OBJECT_WRONG_TYPE;
  418.     for(;;)
  419.     {
  420.     oldpos=telldir((DIR *)fh->fd);
  421.     errno=0;
  422.     dir=readdir((DIR *)fh->fd);
  423.     if(dir==NULL)
  424.     {
  425.         error=err_u2a();
  426.         break;
  427.     }
  428.     if(dir->d_name[0]=='.'&&(!dir->d_name[1]||(dir->d_name[1]=='.'&&!dir->d_name[2])))
  429.         continue;
  430.     name=(STRPTR)malloc(strlen(fh->name)+strlen(dir->d_name)+2);
  431.     if(name==NULL)
  432.     {
  433.         error=ERROR_NO_FREE_STORE;
  434.         break;
  435.     }
  436.     strcpy(name,fh->name);
  437.     if(*name)
  438.         strcat(name,"/");
  439.     strcat(name,dir->d_name);
  440.     old=fh->name;
  441.     fh->name=name;
  442.     error=examine(fh,ead,end-(STRPTR)ead,type);
  443.     fh->name=old;
  444.     free(name);
  445.     if(error)
  446.         break;
  447.     last=ead;
  448.     ead=ead->ed_Next;
  449.     }
  450.     if((!error||error==ERROR_BUFFER_OVERFLOW)&&last!=NULL)
  451.     {
  452.     last->ed_Next=NULL;
  453.     seekdir((DIR *)fh->fd,oldpos);
  454.     return 0;
  455.     }
  456.     if(!error)
  457.     error=ERROR_NO_MORE_ENTRIES;
  458.     rewinddir((DIR *)fh->fd);
  459.     return error;
  460. }
  461.  
  462. AROS_LH2(struct emulbase *, init,
  463.  AROS_LHA(struct emulbase *, emulbase, D0),
  464.  AROS_LHA(BPTR,              segList,   A0),
  465.        struct ExecBase *, sysBase, 0, emul_handler)
  466. {
  467.     AROS_LIBFUNC_INIT
  468.  
  469.     /* Store arguments */
  470.     emulbase->sysbase=sysBase;
  471.     emulbase->seglist=segList;
  472.     emulbase->device.dd_Library.lib_OpenCnt=1;
  473.     emulbase->dosbase=(struct DosLibrary *)OpenLibrary("dos.library",39);
  474.     if(emulbase->dosbase!=NULL)
  475.     {
  476.     if(AttemptLockDosList(LDF_ALL|LDF_WRITE))
  477.     {
  478.         if(!startup(emulbase))
  479.         {
  480.         UnLockDosList(LDF_ALL|LDF_WRITE);
  481.         return emulbase;
  482.         }
  483.         UnLockDosList(LDF_ALL|LDF_WRITE);
  484.     }
  485.     CloseLibrary((struct Library *)emulbase->dosbase);
  486.     }
  487.  
  488.     return NULL;
  489.     AROS_LIBFUNC_EXIT
  490. }
  491.  
  492. AROS_LH3(void, open,
  493.  AROS_LHA(struct IOFileSys *, iofs, A1),
  494.  AROS_LHA(ULONG,              unitnum, D0),
  495.  AROS_LHA(ULONG,              flags, D1),
  496.        struct emulbase *, emulbase, 1, emul_handler)
  497. {
  498.     AROS_LIBFUNC_INIT
  499.  
  500.     /* Keep compiler happy */
  501.     unitnum=0;
  502.     flags=0;
  503.  
  504.     /* I have one more opener. */
  505.     emulbase->device.dd_Library.lib_Flags&=~LIBF_DELEXP;
  506.  
  507.     /* Set returncode */
  508.     iofs->IOFS.io_Error=0;
  509.  
  510.     /* Mark Message as recently used. */
  511.     iofs->IOFS.io_Message.mn_Node.ln_Type=NT_REPLYMSG;
  512.     AROS_LIBFUNC_EXIT
  513. }
  514.  
  515. AROS_LH1(BPTR, close,
  516.  AROS_LHA(struct IOFileSys *, iofs, A1),
  517.        struct emulbase *, emulbase, 2, emul_handler)
  518. {
  519.     AROS_LIBFUNC_INIT
  520.  
  521.     /* Let any following attemps to use the device crash hard. */
  522.     iofs->IOFS.io_Device=(struct Device *)-1;
  523.     return 0;
  524.     AROS_LIBFUNC_EXIT
  525. }
  526.  
  527. AROS_LH0(BPTR, expunge, struct emulbase *, emulbase, 3, emul_handler)
  528. {
  529.     AROS_LIBFUNC_INIT
  530.  
  531.     /* Do not expunge the device. Set the delayed expunge flag and return. */
  532.     emulbase->device.dd_Library.lib_Flags|=LIBF_DELEXP;
  533.     return 0;
  534.     AROS_LIBFUNC_EXIT
  535. }
  536.  
  537. AROS_LH0I(int, null, struct emulbase *, emulbase, 4, emul_handler)
  538. {
  539.     AROS_LIBFUNC_INIT
  540.     return 0;
  541.     AROS_LIBFUNC_EXIT
  542. }
  543.  
  544. AROS_LH1(void, beginio,
  545.  AROS_LHA(struct IOFileSys *, iofs, A1),
  546.        struct emulbase *, emulbase, 5, emul_handler)
  547. {
  548.     AROS_LIBFUNC_INIT
  549.     LONG error=0;
  550.  
  551.     /* WaitIO will look into this */
  552.     iofs->IOFS.io_Message.mn_Node.ln_Type=NT_MESSAGE;
  553.  
  554.     Disable();
  555.  
  556.     /*
  557.     Do everything quick no matter what. This is possible
  558.     because I never need to Wait().
  559.     */
  560.     switch(iofs->IOFS.io_Command)
  561.     {
  562.     case FSA_OPEN:
  563.         error=open_((struct filehandle **)&iofs->IOFS.io_Unit,
  564.              (char *)iofs->io_Args[0],iofs->io_Args[1]);
  565.         break;
  566.  
  567.     case FSA_OPEN_FILE:
  568.         error=open_file((struct filehandle **)&iofs->IOFS.io_Unit,
  569.              (char *)iofs->io_Args[0],
  570.              iofs->io_Args[1],iofs->io_Args[2]);
  571.         break;
  572.  
  573.     case FSA_CLOSE:
  574.         error=free_lock((struct filehandle *)iofs->IOFS.io_Unit);
  575.         break;
  576.  
  577.     case FSA_IS_INTERACTIVE:
  578.     {
  579.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  580.         if(fh->type==FHD_FILE)
  581.         iofs->io_Args[0]=isatty(fh->fd);
  582.         else
  583.         iofs->io_Args[0]=0;
  584.         break;
  585.     }
  586.  
  587.     case FSA_READ:
  588.     {
  589.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  590.         if(fh->type==FHD_FILE)
  591.         {
  592.         if(fh->fd==STDOUT_FILENO)
  593.             fh->fd=STDIN_FILENO;
  594.         for(;;)
  595.         {
  596.             fd_set rfds;
  597.             struct sys_timeval tv;
  598.             FD_ZERO(&rfds);
  599.             FD_SET(fh->fd,&rfds);
  600.             tv.tv_sec=0;
  601.             tv.tv_usec=100000;
  602.             if(select(fh->fd+1,&rfds,NULL,NULL,&tv))
  603.             break;
  604.             SysBase->ThisTask->tc_State=TS_READY;
  605.             AddTail(&SysBase->TaskReady,&SysBase->ThisTask->tc_Node);
  606.             Switch();
  607.         }
  608.  
  609.         iofs->io_Args[1]=read(fh->fd,(APTR)iofs->io_Args[0],iofs->io_Args[1]);
  610.         if(iofs->io_Args[1]<0)
  611.             error=err_u2a();
  612.         }else
  613.         error=ERROR_OBJECT_WRONG_TYPE;
  614.         break;
  615.     }
  616.  
  617.     case FSA_WRITE:
  618.     {
  619.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  620.         if(fh->type==FHD_FILE)
  621.         {
  622.         if(fh->fd==STDIN_FILENO)
  623.             fh->fd=STDOUT_FILENO;
  624.         iofs->io_Args[1]=write(fh->fd,(APTR)iofs->io_Args[0],iofs->io_Args[1]);
  625.         if(iofs->io_Args[1]<0)
  626.             error=err_u2a();
  627.         }else
  628.         error=ERROR_OBJECT_WRONG_TYPE;
  629.         break;
  630.     }
  631.  
  632.     case FSA_SEEK:
  633.     {
  634.         struct filehandle *fh=(struct filehandle *)iofs->IOFS.io_Unit;
  635.         LONG mode=iofs->io_Args[2];
  636.         LONG oldpos;
  637.         if(fh->type==FHD_FILE)
  638.         {
  639.         oldpos=lseek(fh->fd,0,SEEK_CUR);
  640.  
  641.         if (mode == OFFSET_BEGINNING)
  642.             mode = SEEK_SET;
  643.         else if (mode == OFFSET_CURRENT)
  644.             mode = SEEK_CUR;
  645.         else
  646.             mode = SEEK_END;
  647.  
  648.         if(lseek(fh->fd,iofs->io_Args[1],mode)<0)
  649.             error=err_u2a();
  650.         iofs->io_Args[0]=0;
  651.         iofs->io_Args[1]=oldpos;
  652.         }else
  653.         error=ERROR_OBJECT_WRONG_TYPE;
  654.         break;
  655.     }
  656.  
  657.     case FSA_EXAMINE:
  658.         error=examine((struct filehandle *)iofs->IOFS.io_Unit,
  659.               (struct ExAllData *)iofs->io_Args[0],
  660.               iofs->io_Args[1],iofs->io_Args[2]);
  661.         break;
  662.  
  663.     case FSA_EXAMINE_ALL:
  664.         error=examine_all((struct filehandle *)iofs->IOFS.io_Unit,
  665.               (struct ExAllData *)iofs->io_Args[0],
  666.               iofs->io_Args[1],iofs->io_Args[2]);
  667.         break;
  668.  
  669.     default:
  670.         error=ERROR_NOT_IMPLEMENTED;
  671.         break;
  672.     }
  673.  
  674.     Enable();
  675.  
  676.     /* Set error code */
  677.     iofs->io_DosError=error;
  678.  
  679.     /* If the quick bit is not set send the message to the port */
  680.     if(!(iofs->IOFS.io_Flags&IOF_QUICK))
  681.     ReplyMsg(&iofs->IOFS.io_Message);
  682.  
  683.     AROS_LIBFUNC_EXIT
  684. }
  685.  
  686. AROS_LH1(LONG, abortio,
  687.  AROS_LHA(struct IOFileSys *, iofs, A1),
  688.        struct emulbase *, emulbase, 6, emul_handler)
  689. {
  690.     AROS_LIBFUNC_INIT
  691.     /* Everything already done. */
  692.     return 0;
  693.     AROS_LIBFUNC_EXIT
  694. }
  695.  
  696. static const char end=0;
  697.