2 Copyright © 1995-2008, The AROS Development Team. All rights reserved.
5 Desc: Filesystem that accesses an underlying POSIX filesystem.
9 /* Implementing this handler is quite complicated as it uses AROS system-calls
10 as well as POSIX calls of the underlying operating system. This easily
11 leads to complications. So take care, when updating this handler!
13 Please always update the version-string below, if you modify the code!
16 /*********************************************************************************************/
21 # include <aros/debug.h>
24 #include <aros/system.h>
25 #include <aros/symbolsets.h>
26 #include <exec/resident.h>
27 #include <exec/memory.h>
28 #include <exec/alerts.h>
29 #include <devices/input.h>
30 #include <devices/inputevent.h>
31 #include <proto/exec.h>
32 #include <utility/tagitem.h>
33 #include <utility/hooks.h>
34 #include <dos/filesystem.h>
35 #include <dos/exall.h>
36 #include <dos/dosasl.h>
38 #define __DOS_NOLIBBASE__
39 #include <proto/dos.h>
40 #include <proto/arossupport.h>
41 #include <proto/expansion.h>
42 #include <libraries/expansion.h>
43 #include <libraries/configvars.h>
44 #include <libraries/expansionbase.h>
45 #include <proto/oop.h>
48 #include <aros/host-conf.h>
55 #include "emul_handler_intern.h"
56 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
57 # include "emul_handler_gcc.h"
62 #include LC_LIBDEFS_FILE
64 #define HookInterface1(ret,Pfx,HName,arg1,harg1,harg2) \
65 struct Hook * Pfx ## HName ## Impl; \
66 ret HName (arg1) {return (ret)CALLHOOKPKT(Pfx ## HName ## Impl,harg1,harg2); }
67 #define HookInterface2(ret,Pfx,HName,arg1,arg2,harg1,harg2) \
68 struct Hook * Pfx ## HName ## Impl; \
69 ret HName (arg1,arg2) {return (ret)CALLHOOKPKT(Pfx ## HName ## Impl,harg1,harg2); }
70 #define HookInterface3(ret,Pfx,HName,arg1,arg2,arg3,harg1,harg2) \
71 struct Hook * Pfx ## HName ## Impl; \
72 ret HName (arg1,arg2,arg3) {return (ret)CALLHOOKPKT(Pfx ## HName ## Impl,harg1,harg2); }
73 #define HookInterface3Rename(ret,Pfx,HName,FName,arg1,arg2,arg3,harg1,harg2) \
74 struct Hook * Pfx ## HName ## Impl; \
75 ret FName (arg1,arg2,arg3) {return (ret)CALLHOOKPKT(Pfx ## HName ## Impl,harg1,harg2); }
77 HookInterface2(int,Emul
,Chmod
,const char* filename
, int prot
, filename
, prot
);
78 HookInterface1(int,Emul
,Isatty
,const char* filename
, filename
, 0);
79 HookInterface2(int,Emul
,Link
,const char* filename1
, const char* filename2
, filename1
, filename1
);
80 HookInterface3(int,Emul
,LSeek
,long fd
, long offset
, long base
, fd
, TAGLIST(TAG_USER
,offset
,TAG_USER
+1,base
));
81 HookInterface2(int,Emul
,SymLink
,const char* filename1
, const char* filename2
, filename1
, filename1
);
82 HookInterface2(int,Emul
,MKDir
,const char* filename
, int prot
, filename
, prot
);
83 HookInterface3Rename(int,Emul
,Read
,DoRead
,long fd
, char* buf
, long len
, fd
, TAGLIST(TAG_USER
,buf
,TAG_USER
+1,len
));
84 HookInterface3Rename(int,Emul
,Write
,DoWrite
,long fd
, char* buf
, long len
, fd
, TAGLIST(TAG_USER
,buf
,TAG_USER
+1,len
));
85 HookInterface3Rename(int,Emul
,ReadLink
,DoReadLink
,long fd
, char* buf
, long len
, fd
, TAGLIST(TAG_USER
,buf
,TAG_USER
+1,len
));
87 struct Hook * EmulReadImpl;
88 int Read (long fd, char* buf, long len)
90 return (int)CALLHOOKPKT(EmulReadImpl,fd, TAGLIST(TAG_USER,buf,TAG_USER+1,len));
92 struct Hook * EmulWriteImpl;
93 int DoWrite (long fd, char* buf, long len)
95 return (int)CALLHOOKPKT(EmulWriteImpl,fd, TAGLIST(TAG_USER,buf,TAG_USER+1,len));
98 struct Hook
* EmulStatImpl
;
99 #define Stat(path,pFIB) ((int)CALLHOOKPKT(EmulStatImpl,path,pFIB))
100 struct Hook
* EmulLStatImpl
;
101 #define LStat(path,pFIB) ((int)CALLHOOKPKT(EmulLStatImpl,path,pFIB))
102 struct Hook
* EmulErrnoImpl
;
103 #define Errno() ((int)CALLHOOKPKT(EmulErrnoImpl,0,0))
104 struct Hook
* EmulCloseDirImpl
;
105 #define CloseDir(dir) ((int)CALLHOOKPKT(EmulCloseDirImpl,dir,0))
106 struct Hook
* EmulCloseImpl
;
107 #define DoClose(fd) ((int)CALLHOOKPKT(EmulCloseImpl,fd,0))
108 struct Hook
* EmulOpenImpl
;
109 #define DoOpen(path,mode,protect) ((int)CALLHOOKPKT(EmulOpenImpl,path,TAGLIST(TAG_USER,mode,TAG_USER+1,protect,TAG_DONE)))
110 struct Hook
* EmulOpenDirImpl
;
111 #define OpenDir(path) ((int)CALLHOOKPKT(EmulOpenDirImpl,path,0))
112 struct Hook
* EmulChDirImpl
;
113 #define ChDir(path) ((int)CALLHOOKPKT(EmulChDirImpl,path,0))
114 struct Hook
* EmulDirNameImpl
;
115 #define DirName(dir) ((const char*)CALLHOOKPKT(EmulDirNameImpl,dir,0))
116 struct Hook
* EmulTellDirImpl
;
117 #define TellDir(dir) ((long)CALLHOOKPKT(EmulTellDirImpl,dir,0))
118 struct Hook
* EmulSeekDirImpl
;
119 #define SeekDir(dir,pos) ((long)CALLHOOKPKT(EmulSeekDirImpl,dir,pos))
120 struct Hook
* EmulRewindDirImpl
;
121 #define RewindDir(dir) ((long)CALLHOOKPKT(EmulRewindDirImpl,dir,0))
122 struct Hook
* EmulDeleteImpl
;
123 #define Delete(path) ((int)CALLHOOKPKT(EmulDeleteImpl,path,0))
124 struct Hook
* EmulRenameImpl
;
125 #define DoRename(spath,dpath) ((int)CALLHOOKPKT(EmulRenameImpl,spath,dpath))
126 struct Hook
* EmulGetEnvImpl
;
127 #define GetEnv(name) ((const char*)CALLHOOKPKT(EmulGetEnvImpl,name,0))
128 struct Hook
* EmulGetCWDImpl
;
129 #define GetCWD(buf,len) ((char*)CALLHOOKPKT(EmulGetCWDImpl,buf,len))
130 struct Hook
* EmulGetHomeImpl
;
131 #define GetHome(name) ((const char*)CALLHOOKPKT(EmulGetHomeImpl,name,0))
132 struct Hook
* EmulClosePWImpl
;
133 #define ClosePW() ((const char*)CALLHOOKPKT(EmulClosePWImpl,0,0))
134 struct Hook
* EmulStatFSImpl
;
135 #define StatFS(name,id) ((int)CALLHOOKPKT(EmulStatFSImpl,name,id))
137 /*********************************************************************************************/
139 /* Init DOSBase ourselves because emul_handler is initialized before dos.library */
140 static struct DosLibrary
*DOSBase
;
142 #define malloc you_must_change_malloc_to__emul_malloc
143 #define free you_must_change_free_to__emul_free
145 /*********************************** Support *******************************/
147 static void SendEvent(struct emulbase
*emulbase
, LONG event
) {
148 struct IOStdReq
*InputRequest
;
149 struct MsgPort
*InputPort
;
150 struct InputEvent
*ie
;
151 D(bug("[afs] os_aros_support/SendEvent\n"));
152 if ((InputPort
= (struct MsgPort
*)CreateMsgPort())) {
154 if ((InputRequest
= (struct IOStdReq
*)CreateIORequest(InputPort
, sizeof(struct IOStdReq
)))) {
156 if (!OpenDevice("input.device", 0, (struct IORequest
*)InputRequest
, 0)) {
158 if ((ie
= AllocVec(sizeof(struct InputEvent
), MEMF_PUBLIC
|MEMF_CLEAR
))) {
159 ie
->ie_Class
= event
;
160 InputRequest
->io_Command
= IND_WRITEEVENT
;
161 InputRequest
->io_Data
= ie
;
162 InputRequest
->io_Length
= sizeof(struct InputEvent
);
164 DoIO((struct IORequest
*)InputRequest
);
168 CloseDevice((struct IORequest
*)InputRequest
);
170 DeleteIORequest ((APTR
)InputRequest
);
172 DeleteMsgPort (InputPort
);
176 /*********************************************************************************************/
178 static APTR
emul_malloc(struct emulbase
*emulbase
, ULONG size
)
182 // kprintf("** emul_malloc: size = %d **\n",size);
183 ObtainSemaphore(&emulbase
->memsem
);
185 size
+= sizeof(ULONG
);
186 res
= AllocPooled(emulbase
->mempool
, size
);
187 if (res
) *res
++ = size
;
189 ReleaseSemaphore(&emulbase
->memsem
);
191 // kprintf("** emul_malloc: size = %d result = %x **\n",size-sizeof(ULONG),res);
196 /*********************************************************************************************/
198 static void emul_free(struct emulbase
*emulbase
, APTR mem
)
202 kprintf("*** emul_handler: tried to free NULL mem ***\n");
204 ULONG
*m
= (ULONG
*)mem
;
207 // kprintf("** emul_free: size = %d memory = %x **\n",size-sizeof(ULONG),mem);
209 ObtainSemaphore(&emulbase
->memsem
);
210 FreePooled(emulbase
->mempool
, m
, size
);
211 ReleaseSemaphore(&emulbase
->memsem
);
215 /*********************************************************************************************/
217 static BOOL
is_root_filename(char *filename
)
221 if ((*filename
== '\0') ||
222 (!strcmp(filename
, ".")) ||
223 (!strcmp(filename
, "./")))
231 /*********************************************************************************************/
233 /* Create a plain path out of the supplied filename.
234 Eg 'path1/path2//path3/' becomes 'path1/path3'.
236 BOOL
shrink(struct emulbase
*emulbase
, char *filename
)
241 if (filename
[0] == '.')
242 if (filename
[1] == '/') filename
+= 2;
246 /* leading slashes? --> return FALSE. */
247 if(*filename
=='/') return FALSE
;
249 /* remove superflous paths (ie paths that are followed by '//') */
250 s1
=strstr(filename
,"//");
256 if (s2
[-1] == '/') break;
260 memmove(s2
,s1
+2,strlen(s1
+1));
263 /* strip trailing slash */
264 len
=strlen(filename
);
265 if(len
&&filename
[len
-1]=='/')
271 /*********************************************************************************************/
273 /* Allocate a buffer, in which the filename is appended to the pathname. */
274 static LONG
makefilename(struct emulbase
*emulbase
,
275 char **dest
, STRPTR dirname
, STRPTR filename
)
279 dirlen
= strlen(dirname
) + 1;
280 len
= strlen(filename
) + dirlen
+ 1 + /*safety*/ 1;
281 *dest
=(char *)emul_malloc(emulbase
, len
);
284 CopyMem(dirname
, *dest
, dirlen
);
287 if ((*dest
)[dirlen
- 2] != '/') strcat(*dest
, "/");
290 strcat(*dest
, filename
);
292 if (!shrink(emulbase
, *dest
))
294 emul_free(emulbase
, *dest
);
296 ret
= ERROR_OBJECT_NOT_FOUND
;
299 ret
= ERROR_NO_FREE_STORE
;
305 /*********************************************************************************************/
308 /*********************************************************************************************/
310 static BOOL
check_volume(struct filehandle
*fh
, struct emulbase
*emulbase
)
312 if (fh
->volume
== emulbase
->current_volume
) return TRUE
;
314 if (ChDir(fh
->volume
))
316 emulbase
->current_volume
= fh
->volume
;
323 /*********************************************************************************************/
325 /* Free a filehandle */
326 static LONG
free_lock(struct emulbase
*emulbase
, struct filehandle
*current
)
328 switch(current
->type
)
331 if(current
->fd
!=STDIN_FILENO
&¤t
->fd
!=STDOUT_FILENO
&&
332 current
->fd
!=STDERR_FILENO
)
334 DoClose(current
->fd
);
335 emul_free(emulbase
, current
->name
);
337 if (current
->pathname
)
339 emul_free(emulbase
, current
->pathname
);
344 CloseDir(current
->DIR);
351 CloseDir(current
->fd
);
355 emul_free(emulbase
, current
->name
);
358 FreeMem(current
, sizeof(struct filehandle
));
362 /*********************************************************************************************/
364 static LONG
open_(struct emulbase
*emulbase
, struct filehandle
**handle
,STRPTR name
,LONG mode
)
367 struct filehandle
*fh
;
370 if (!check_volume(*handle
, emulbase
)) return ERROR_OBJECT_NOT_FOUND
;
372 fh
=(struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
);
375 fh
->pathname
= NULL
; /* just to make sure... */
377 /* If no filename is given and the file-descriptor is one of the
378 standard filehandles (stdin, stdout, stderr) ... */
379 if((!name
[0]) && ((*handle
)->type
== FHD_FILE
) &&
380 (((*handle
)->fd
== STDIN_FILENO
) || ((*handle
)->fd
== STDOUT_FILENO
) || ((*handle
)->fd
== STDERR_FILENO
)))
382 /* ... then just reopen that standard filehandle. */
384 fh
->fd
=(*handle
)->fd
;
392 fh
->volume
=(*handle
)->volume
;
393 fh
->volumename
=(*handle
)->volumename
;
395 ret
= makefilename(emulbase
, &fh
->name
, (*handle
)->name
, name
);
399 if(0<(kind
= Stat(*fh
->name
?fh
->name
:".",0)))
403 //FIXME: this should be aros flags, not unix
404 fh
->fd
= DoOpen(*fh
->name
?fh
->name
:".",flags
,0770);
412 /* file is a directory */
413 fh
->type
=FHD_DIRECTORY
;
414 fh
->fd
=(long)OpenDir(*fh
->name
?fh
->name
:".");
421 ret
= ERROR_OBJECT_WRONG_TYPE
;
423 /* Stat() failed. If ret is unset, generate it from errno. */
427 emul_free(emulbase
, fh
->name
);
429 FreeMem(fh
, sizeof(struct filehandle
));
431 ret
= ERROR_NO_FREE_STORE
;
435 /*********************************************************************************************/
437 static LONG
open_file(struct emulbase
*emulbase
, struct filehandle
**handle
,STRPTR name
,LONG mode
,LONG protect
)
439 LONG ret
=ERROR_NO_FREE_STORE
;
440 struct filehandle
*fh
;
442 if (!check_volume(*handle
, emulbase
)) return ERROR_OBJECT_NOT_FOUND
;
444 fh
=(struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
);
447 fh
->pathname
= NULL
; /* just to make sure... */
449 /* If no filename is given and the file-descriptor is one of the
450 standard filehandles (stdin, stdout, stderr) ... */
451 if ((!name
[0]) && ((*handle
)->type
==FHD_FILE
) &&
452 (((*handle
)->fd
==STDIN_FILENO
) || ((*handle
)->fd
==STDOUT_FILENO
) || ((*handle
)->fd
==STDERR_FILENO
)))
454 /* ... then just reopen that standard filehandle. */
456 fh
->fd
=(*handle
)->fd
;
463 fh
->volume
=(*handle
)->volume
;
464 fh
->volumename
=(*handle
)->volumename
;
466 ret
= makefilename(emulbase
, &fh
->name
, (*handle
)->name
, name
);
470 fh
->fd
=DoOpen(fh
->name
,mode
,protect
);
477 emul_free(emulbase
, fh
->name
);
479 FreeMem(fh
, sizeof(struct filehandle
));
484 /*********************************************************************************************/
486 static LONG
create_dir(struct emulbase
*emulbase
, struct filehandle
**handle
,
487 STRPTR filename
, IPTR protect
)
490 struct filehandle
*fh
;
492 if (!check_volume(*handle
, emulbase
)) return ERROR_OBJECT_NOT_FOUND
;
494 fh
= (struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
);
497 fh
->pathname
= NULL
; /* just to make sure... */
501 fh
->volume
= (*handle
)->volume
;
502 fh
->volumename
=(*handle
)->volumename
;
504 ret
= makefilename(emulbase
, &fh
->name
, (*handle
)->name
, filename
);
507 fh
->type
= FHD_DIRECTORY
;
509 if (!MKDir(fh
->name
, protect
))
512 (*handle
)->fd
= (long)OpenDir((*handle
)->name
);
518 free_lock(emulbase
, fh
);
520 ret
= ERROR_NO_FREE_STORE
;
525 /*********************************************************************************************/
527 static LONG
delete_object(struct emulbase
*emulbase
, struct filehandle
* fh
,
531 char *filename
= NULL
;
533 if (!check_volume(fh
, emulbase
)) return ERROR_OBJECT_NOT_FOUND
;
535 ret
= makefilename(emulbase
, &filename
, fh
->name
, file
);
540 emul_free(emulbase
, filename
);
546 /*********************************************************************************************/
548 static LONG
set_protect(struct emulbase
*emulbase
, struct filehandle
* fh
,
549 STRPTR file
, ULONG aprot
)
552 char *filename
= NULL
;
554 if (!check_volume(fh
, emulbase
)) return ERROR_OBJECT_NOT_FOUND
;
556 if ((ret
= makefilename(emulbase
, &filename
, fh
->name
, file
)))
559 if (Chmod(filename
, aprot
))
562 emul_free(emulbase
, filename
);
567 /*********************************************************************************************/
569 static LONG
startup(struct emulbase
*emulbase
)
571 struct Library
*ExpansionBase
;
572 struct filehandle
*fhi
, *fho
, *fhe
, *fhv
;
573 struct DeviceNode
*dlv
, *dlv2
;
574 LONG ret
= ERROR_NO_FREE_STORE
;
576 kprintf("[Emulhandler] startup\n");
577 ExpansionBase
= OpenLibrary("expansion.library",0);
578 if(ExpansionBase
!= NULL
)
580 kprintf("[Emulhandler] startup: got ExpansionBase\n");
581 fhi
=(struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
);
584 kprintf("[Emulhandler] allocated fhi\n");
585 fhi
->pathname
= NULL
; /* just to make sure... */
588 fhi
->volumename
= NULL
;
590 fho
=(struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
);
593 kprintf("[Emulhandler] startup allocated fho\n");
594 fho
->pathname
= NULL
; /* just to make sure... */
597 fho
->volumename
= NULL
;
599 fhe
=(struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
);
602 kprintf("[Emulhandler] startup allocated fhe\n");
603 fhe
->pathname
= NULL
; /* just to make sure... */
606 fhe
->volumename
= NULL
;
608 fhv
=(struct filehandle
*)AllocMem(sizeof(struct filehandle
) + 256 + AROS_WORSTALIGN
, MEMF_PUBLIC
);
611 kprintf("[Emulhandler] startup allocated fhv\n");
613 fhv
->type
= FHD_DIRECTORY
;
614 fhv
->pathname
= NULL
; /* just to make sure... */
616 fhv
->volume
=(char *)(fhv
+ 1);
618 /* Make sure that the root directory is valid */
620 if(GetCWD(fhv
->volume
, 256) && (kind
=Stat(fhv
->name
,0))==2)
622 kprintf("[Emulhandler] startup got valid directory\n");
623 #define DEVNAME "EMU"
624 #define VOLNAME "System"
626 static const char *devname
= DEVNAME
;
627 static const char *volname
= VOLNAME
;
629 fhv
->volumename
= VOLNAME
;
630 emulbase
->current_volume
= fhv
->volume
;
632 fhv
->fd
= (long)OpenDir(fhv
->name
);
634 fhi
->type
= FHD_FILE
;
635 fhi
->fd
= STDIN_FILENO
;
637 fho
->type
= FHD_FILE
;
638 fho
->fd
= STDOUT_FILENO
;
640 fhe
->type
= FHD_FILE
;
641 fhe
->fd
= STDERR_FILENO
;
644 emulbase
->eb_stdin
= (struct Unit
*)fhi
;
645 emulbase
->eb_stdout
= (struct Unit
*)fho
;
646 emulbase
->eb_stderr
= (struct Unit
*)fhe
;
649 Allocate space for the string from same mem,
650 Use AROS_BSTR_MEMSIZE4LEN macro for space to
651 to allocate and add an extra 4 for alignment
654 ret
= ERROR_NO_FREE_STORE
;
656 dlv
= AllocMem(sizeof(struct DeviceNode
) + 4 + AROS_BSTR_MEMSIZE4LEN(strlen(DEVNAME
)),
657 MEMF_CLEAR
| MEMF_PUBLIC
);
659 dlv2
= AllocMem(sizeof(struct DeviceNode
) + 4 + AROS_BSTR_MEMSIZE4LEN(strlen(VOLNAME
)),
660 MEMF_CLEAR
| MEMF_PUBLIC
);
662 if(dlv
!= NULL
&& dlv2
!= NULL
)
664 kprintf("[Emulhandler] startup allocated dlv/dlv2\n");
669 /* We want s to point to the first 4-byte
670 aligned memory after the structure.
672 s
= (BSTR
)MKBADDR(((IPTR
)dlv
+ sizeof(struct DeviceNode
) + 3) & ~3);
673 s2
= (BSTR
)MKBADDR(((IPTR
)dlv2
+ sizeof(struct DeviceNode
) + 3) & ~3);
675 for(i
= 0; i
< sizeof(DEVNAME
) - 1; i
++)
677 AROS_BSTR_putchar(s
, i
, devname
[i
]);
679 AROS_BSTR_setstrlen(s
, sizeof(DEVNAME
) - 1);
681 dlv
->dn_Type
= DLT_DEVICE
;
682 dlv
->dn_Ext
.dn_AROS
.dn_Unit
= (struct Unit
*)fhv
;
683 dlv
->dn_Ext
.dn_AROS
.dn_Device
= &emulbase
->device
;
684 dlv
->dn_Handler
= NULL
;
685 dlv
->dn_Startup
= NULL
;
687 dlv
->dn_Ext
.dn_AROS
.dn_DevName
= AROS_BSTR_ADDR(dlv
->dn_Name
);
689 AddBootNode(0, 0, dlv
, NULL
);
692 /* Unfortunately, we cannot do the stuff below
693 as dos is not yet initialized... */
694 // AddDosEntry(MakeDosEntry("System",
697 for(i
= 0; i
< sizeof(VOLNAME
) - 1; i
++)
699 AROS_BSTR_putchar(s2
, i
, volname
[i
]);
701 AROS_BSTR_setstrlen(s2
, sizeof(VOLNAME
) - 1);
703 dlv2
->dn_Type
= DLT_VOLUME
;
704 dlv2
->dn_Ext
.dn_AROS
.dn_Unit
= (struct Unit
*)fhv
;
705 dlv2
->dn_Ext
.dn_AROS
.dn_Device
= &emulbase
->device
;
706 dlv2
->dn_Handler
= NULL
;
707 dlv2
->dn_Startup
= NULL
;
709 dlv2
->dn_Ext
.dn_AROS
.dn_DevName
= AROS_BSTR_ADDR(dlv2
->dn_Name
);
711 /* Make sure this is not booted from */
712 AddBootNode(-128, 0, dlv2
, NULL
);
716 } /* valid directory */
719 Alert(AT_DeadEnd
|AO_Unknown
|AN_Unknown
);
721 free_lock(emulbase
, fhv
);
723 FreeMem(fhe
, sizeof(struct filehandle
));
725 FreeMem(fho
, sizeof(struct filehandle
));
727 FreeMem(fhi
, sizeof(struct filehandle
));
730 CloseLibrary(ExpansionBase
);
735 /*********************************************************************************************/
737 static const ULONG sizes
[]=
738 { 0, offsetof(struct ExAllData
,ed_Type
), offsetof(struct ExAllData
,ed_Size
),
739 offsetof(struct ExAllData
,ed_Prot
), offsetof(struct ExAllData
,ed_Days
),
740 offsetof(struct ExAllData
,ed_Comment
), offsetof(struct ExAllData
,ed_OwnerUID
),
741 sizeof(struct ExAllData
) };
743 /*********************************************************************************************/
745 /* Returns a emul_malloc()'ed buffer, containing a pathname, stripped by the
748 char * pathname_from_name (struct emulbase
*emulbase
, char * name
)
750 long len
= strlen(name
);
752 char * result
= NULL
;
753 /* look for the first '/' in the filename starting at the end */
754 while (i
!= 0 && name
[i
] != '/')
759 result
= (char *)emul_malloc(emulbase
, i
+1);
762 strncpy(result
, name
, i
);
768 /*********************************************************************************************/
770 /* Returns a emul_malloc()'ed buffer, containing the filename without its path. */
771 char * filename_from_name(struct emulbase
*emulbase
, char * name
)
773 long len
= strlen(name
);
775 char * result
= NULL
;
776 /* look for the first '/' in the filename starting at the end */
777 while (i
!= 0 && name
[i
] != '/')
782 result
= (char *)emul_malloc(emulbase
, len
-i
);
785 strncpy(result
, &name
[i
+1], len
-i
);
791 /*********************************************************************************************/
793 static LONG
examine(struct emulbase
*emulbase
,
794 struct filehandle
*fh
,
795 struct ExAllData
*ead
,
800 STRPTR next
, end
, last
, name
;
802 /* Return an error, if supplied type is not supported. */
804 return ERROR_BAD_NUMBER
;
806 /* Check, if the supplied buffer is large enough. */
807 next
=(STRPTR
)ead
+sizes
[type
];
808 end
=(STRPTR
)ead
+size
;
810 if(next
>end
) /* > is correct. Not >= */
811 return ERROR_BUFFER_OVERFLOW
;
813 if (!check_volume(fh
, emulbase
)) return ERROR_OBJECT_NOT_FOUND
;
815 struct FileInfoBlock FIB
;
816 int kind
= LStat(*fh
->name
?fh
->name
:".",&FIB
);
820 if (FHD_FILE
== fh
->type
)
821 /* What we have here is a file, so it's no that easy to
822 deal with it when the user is calling ExNext() after
823 Examine(). So I better prepare it now. */
825 /* We're going to opendir the directory where the file is in
826 and then actually start searching for the file. Yuk! */
827 if (NULL
== fh
->pathname
)
830 const char * dirname
;
831 fh
->pathname
= pathname_from_name(emulbase
, fh
->name
);
832 filename
= filename_from_name(emulbase
, fh
->name
);
833 if(!fh
->pathname
|| !filename
)
835 emul_free(emulbase
, filename
);
836 return ERROR_NO_FREE_STORE
;
838 fh
->DIR = OpenDir(fh
->pathname
);
841 emul_free(emulbase
, filename
);
846 dirname
= DirName(fh
->DIR);
848 while (NULL
!= dirname
&&
849 0 != strcmp(dirname
, filename
));
850 emul_free(emulbase
, filename
);
855 return ERROR_NO_MORE_ENTRIES
;
860 *dirpos
= (LONG
)TellDir(fh
->DIR);
866 *dirpos
= (LONG
)TellDir(fh
->fd
);
872 ead
->ed_OwnerUID
= FIB
.fib_OwnerUID
;
873 ead
->ed_OwnerGID
= FIB
.fib_OwnerGID
;
875 ead
->ed_Comment
=NULL
;
877 ead
->ed_Days
= FIB
.fib_Date
.ds_Days
;
878 ead
->ed_Mins
= FIB
.fib_Date
.ds_Minute
;
879 ead
->ed_Ticks
= FIB
.fib_Date
.ds_Tick
;
881 ead
->ed_Prot
= FIB
.fib_Protection
;
883 ead
->ed_Size
= FIB
.fib_Size
;
887 if (is_root_filename(fh
->name
))
889 ead
->ed_Type
= ST_ROOT
;
891 ead
->ed_Type
= ST_USERDIR
;
894 ead
->ed_Type
= ST_FILE
;
899 last
=name
=is_root_filename(fh
->name
)?fh
->volumename
:fh
->name
;
901 /* do not show the "." but "" instead */
902 if (last
[0] == '.' && last
[1] == '\0')
911 return ERROR_BUFFER_OVERFLOW
;
912 if(!(*next
++=*last
++))
916 ead
->ed_Next
=(struct ExAllData
*)(((IPTR
)next
+AROS_PTRALIGN
-1)&~(AROS_PTRALIGN
-1));
921 /*********************************************************************************************/
923 static LONG
examine_next(struct emulbase
*emulbase
,
924 struct filehandle
*fh
,
925 struct FileInfoBlock
*FIB
)
928 const char * dirname
;
929 char *name
, *src
, *dest
, *pathname
;
931 /* first of all we have to go to the position where Examine() or
932 ExamineNext() stopped the previous time so we can read the next entry! */
934 if (!check_volume(fh
, emulbase
)) return ERROR_OBJECT_NOT_FOUND
;
939 SeekDir(fh
->fd
, FIB
->fib_DiskKey
);
940 pathname
= fh
->name
; /* it's just a directory! */
945 SeekDir(fh
->DIR, FIB
->fib_DiskKey
);
946 pathname
= fh
->pathname
;
950 /* hm, let's read the data now!
951 but skip '.' and '..' (they're not available on Amigas and
952 Amiga progs wouldn't know how to treat '.' and '..', i.e. they
953 might want to scan recursively the directory and end up scanning
958 dirname
= DirName(ReadDIR
);
961 return ERROR_NO_MORE_ENTRIES
;
963 } while ( 0 == strcmp(dirname
,"." ) ||
964 0 == strcmp(dirname
,"..") );
967 name
= (STRPTR
)emul_malloc(emulbase
, strlen(pathname
) + strlen(dirname
) + 2);
970 return ERROR_NO_FREE_STORE
;
972 strcpy(name
, pathname
);
977 strcat(name
, dirname
);
979 if (0<Stat(name
,FIB
))
981 D(bug("Stat() failed for %s\n", name
));
983 emul_free(emulbase
, name
);
988 emul_free(emulbase
, name
);
990 /* fast copying of the filename */
992 dest
= FIB
->fib_FileName
;
994 for (i
=0; i
<MAXFILENAMELENGTH
-1;i
++)
996 if(! (*dest
++=*src
++) )
1002 FIB
->fib_DiskKey
= (LONG
)TellDir(ReadDIR
);
1007 /*********************************************************************************************/
1009 static LONG
examine_all(struct emulbase
*emulbase
,
1010 struct filehandle
*fh
,
1011 struct ExAllData
*ead
,
1012 struct ExAllControl
*eac
,
1016 struct ExAllData
*last
=NULL
;
1017 STRPTR end
=(STRPTR
)ead
+size
, name
, old
;
1019 const char * dirname
;
1021 off_t dummy
; /* not anything is done with this value but passed to examine */
1023 eac
->eac_Entries
= 0;
1024 if(fh
->type
!=FHD_DIRECTORY
)
1025 return ERROR_OBJECT_WRONG_TYPE
;
1027 if (!check_volume(fh
, emulbase
)) return ERROR_OBJECT_NOT_FOUND
;
1031 oldpos
=TellDir(fh
->fd
);
1032 dirname
=DirName(fh
->fd
);
1038 if(dirname
[0]=='.'&&(!dirname
[1]||(dirname
[1]=='.'&&!dirname
[2])))
1040 name
=(STRPTR
)emul_malloc(emulbase
, strlen(fh
->name
)+strlen(dirname
)+2);
1043 error
=ERROR_NO_FREE_STORE
;
1046 strcpy(name
,fh
->name
);
1049 strcat(name
,dirname
);
1052 error
=examine(emulbase
,fh
,ead
,end
-(STRPTR
)ead
,type
,&dummy
);
1054 emul_free(emulbase
, name
);
1063 if((error
==ERROR_BUFFER_OVERFLOW
)&&last
!=NULL
)
1065 SeekDir(fh
->fd
,oldpos
);
1069 error
=ERROR_NO_MORE_ENTRIES
;
1074 /*********************************************************************************************/
1076 static LONG
create_hardlink(struct emulbase
*emulbase
,
1077 struct filehandle
**handle
,STRPTR name
,struct filehandle
*oldfile
)
1080 struct filehandle
*fh
;
1082 if (!check_volume(*handle
, emulbase
)) return ERROR_OBJECT_NOT_FOUND
;
1084 fh
= AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
);
1086 return ERROR_NO_FREE_STORE
;
1088 fh
->pathname
= NULL
; /* just to make sure... */
1091 error
= makefilename(emulbase
, &fh
->name
, (*handle
)->name
, name
);
1094 if (!Link(oldfile
->name
, fh
->name
))
1100 error
= ERROR_NO_FREE_STORE
;
1101 FreeMem(fh
, sizeof(struct filehandle
));
1107 /*********************************************************************************************/
1109 static LONG
create_softlink(struct emulbase
* emulbase
,
1110 struct filehandle
**handle
, STRPTR name
, STRPTR ref
)
1113 struct filehandle
*fh
;
1115 if (!check_volume(*handle
, emulbase
)) return ERROR_OBJECT_NOT_FOUND
;
1117 fh
= AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
);
1119 return ERROR_NO_FREE_STORE
;
1121 fh
->pathname
= NULL
; /* just to make sure... */
1124 error
= makefilename(emulbase
, &fh
->name
, (*handle
)->name
, name
);
1127 if (!SymLink(ref
, fh
->name
))
1133 error
= ERROR_NO_FREE_STORE
;
1134 FreeMem(fh
, sizeof(struct filehandle
));
1140 /*********************************************************************************************/
1142 static LONG
rename_object(struct emulbase
* emulbase
,
1143 struct filehandle
*fh
, STRPTR file
, STRPTR newname
)
1147 char *filename
= NULL
, *newfilename
= NULL
;
1149 if (!check_volume(fh
, emulbase
)) return ERROR_OBJECT_NOT_FOUND
;
1151 ret
= makefilename(emulbase
, &filename
, fh
->name
, file
);
1154 ret
= makefilename(emulbase
, &newfilename
, fh
->name
, newname
);
1157 if (DoRename(filename
,newfilename
))
1159 emul_free(emulbase
, newfilename
);
1161 emul_free(emulbase
, filename
);
1168 static LONG
read_softlink(struct emulbase
*emulbase
,
1169 struct filehandle
*fh
,
1173 if (!check_volume(fh
, emulbase
)) return ERROR_OBJECT_NOT_FOUND
;
1175 if (DoReadLink(fh
->name
, buffer
, size
-1) == -1)
1181 /*********************************************************************************************/
1183 ULONG
parent_dir(struct emulbase
*emulbase
,
1184 struct filehandle
*fh
,
1187 *DirName
= pathname_from_name(emulbase
, fh
->name
);
1191 /*********************************************************************************************/
1193 void parent_dir_post(struct emulbase
*emulbase
, char ** DirName
)
1195 /* free the previously allocated memory */
1196 emul_free(emulbase
, *DirName
);
1200 /*********************************************************************************************/
1202 /************************ Library entry points ************************/
1206 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR emulbase
)
1208 static const struct TagItem tags
[] = {{ TAG_END
, 0 }};
1210 D(bug("Initializing emul_handler\n"));
1212 if (loadhooks() != 0)
1215 InitSemaphore(&emulbase
->sem
);
1216 InitSemaphore(&emulbase
->memsem
);
1218 emulbase
->mempool
= CreatePool(MEMF_ANY
, 4096, 2000);
1219 if (!emulbase
->mempool
) return FALSE
;
1221 #ifdef EMUL_HANDLER_USE_UNIXIO
1222 emulbase
->unixio
= OOP_NewObject (NULL
, CLID_Hidd_UnixIO
, (struct TagItem
*)tags
);
1224 if (!emulbase
->unixio
)
1226 D(bug("Could not get UnixIO object\n"));
1227 DeletePool(emulbase
->mempool
);
1232 if(!startup(emulbase
))
1234 D(bug("emul_handler initialized OK\n"));
1238 #ifdef EMUL_HANDLER_USE_UNIXIO
1239 OOP_DisposeObject (emulbase
->unixio
);
1242 DeletePool(emulbase
->mempool
);
1244 D(bug("emul_handler startup failed\n"));
1249 /*********************************************************************************************/
1251 static BOOL
new_volume(struct IOFileSys
*iofs
, struct emulbase
*emulbase
)
1253 struct filehandle
*fhv
;
1254 struct DosList
*doslist
;
1257 ObtainSemaphore(&emulbase
->sem
);
1259 /* Volume name and Unix path are encoded into DEVICE entry of
1260 MountList like this: <volumename>:<unixpath> */
1262 unixpath
= iofs
->io_Union
.io_OpenDevice
.io_DeviceName
;
1263 unixpath
= strchr(unixpath
, ':');
1271 if ((sp
= strchr(unixpath
, '~')))
1274 char *newunixpath
= 0;
1276 BOOL do_endpwent
= FALSE
;
1279 /* "~<name>" means home of user <name> */
1281 if ((sp
[1] == '\0') || (sp
[1] == '/'))
1284 home
= GetEnv("HOME");
1292 for(sp_end
= sp
+ 1;
1293 sp_end
[0] != '\0' && sp_end
[0] != '/';
1297 cmplen
= sp_end
- sp
- 1;
1298 /* temporariliy zero terminate name */
1299 tmp
= sp
[cmplen
+1]; sp
[cmplen
+1] = '\0';
1301 home
= GetHome(sp
+1);
1309 newunixpath
= AllocVec(strlen(unixpath
) + strlen(home
) + 1, MEMF_CLEAR
);
1312 strncpy(newunixpath
, unixpath
, sp
- unixpath
);
1313 strcat(newunixpath
, home
);
1314 strcat(newunixpath
, sp_end
);
1317 unixpath
= newunixpath
;
1326 if (newunixpath
) FreeVec(newunixpath
);
1332 if (Stat(unixpath
,0)>0)
1334 fhv
=(struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
);
1338 fhv
->type
= FHD_DIRECTORY
;
1339 fhv
->pathname
= NULL
; /* just to make sure... */
1341 fhv
->volume
= unixpath
;
1342 fhv
->volumename
= iofs
->io_Union
.io_OpenDevice
.io_DeviceName
;
1344 if ((doslist
= MakeDosEntry(fhv
->volumename
, DLT_VOLUME
)))
1346 doslist
->dol_Ext
.dol_AROS
.dol_Unit
=(struct Unit
*)fhv
;
1347 doslist
->dol_Ext
.dol_AROS
.dol_Device
=&emulbase
->device
;
1348 AddDosEntry(doslist
);
1350 iofs
->IOFS
.io_Unit
= (struct Unit
*)fhv
;
1351 iofs
->IOFS
.io_Device
= &emulbase
->device
;
1353 ReleaseSemaphore(&emulbase
->sem
);
1354 SendEvent(emulbase
, IECLASS_DISKINSERTED
);
1358 } /* if ((doslist = MakeDosEntry(fhv->volumename, DLT_VOLUME))) */
1360 FreeMem(fhv
, sizeof(struct filehandle
));
1362 } /* if (fhv != NULL)*/
1364 } /* if (!Stat(unixpath, &st)) */
1366 } /* if (unixpath) */
1368 } /* if (unixpath) */
1370 ReleaseSemaphore(&emulbase
->sem
);
1376 /*********************************************************************************************/
1378 static int GM_UNIQUENAME(Open
)
1380 LIBBASETYPEPTR emulbase
,
1381 struct IOFileSys
*iofs
,
1386 /* Keep compiler happy */
1390 if (DOSBase
== NULL
)
1391 DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 41);
1393 if (DOSBase
== NULL
|| !new_volume(iofs
, emulbase
))
1395 iofs
->IOFS
.io_Error
= -1;
1399 /* Set returncode */
1400 iofs
->IOFS
.io_Error
=0;
1404 /*********************************************************************************************/
1406 ADD2INITLIB(GM_UNIQUENAME(Init
), 0)
1407 ADD2OPENDEV(GM_UNIQUENAME(Open
), 0)
1409 /*********************************************************************************************/
1411 AROS_LH1(void, beginio
,
1412 AROS_LHA(struct IOFileSys
*, iofs
, A1
),
1413 struct emulbase
*, emulbase
, 5, emul_handler
)
1419 /* WaitIO will look into this */
1420 iofs
->IOFS
.io_Message
.mn_Node
.ln_Type
=NT_MESSAGE
;
1423 ObtainSemaphore(&emulbase
->sem
);
1426 Do everything quick no matter what. This is possible
1427 because I never need to Wait().
1429 switch(iofs
->IOFS
.io_Command
)
1432 error
= open_(emulbase
,
1433 (struct filehandle
**)&iofs
->IOFS
.io_Unit
,
1434 iofs
->io_Union
.io_OPEN
.io_Filename
,
1435 iofs
->io_Union
.io_OPEN
.io_FileMode
);
1437 (error
== ERROR_WRITE_PROTECTED
) &&
1438 (iofs
->io_Union
.io_OPEN
.io_FileMode
& FMF_AMIGADOS
)
1441 error
= open_(emulbase
,
1442 (struct filehandle
**)&iofs
->IOFS
.io_Unit
,
1443 iofs
->io_Union
.io_OPEN
.io_Filename
,
1444 iofs
->io_Union
.io_OPEN
.io_FileMode
& (~FMF_WRITE
));
1450 error
= free_lock(emulbase
, (struct filehandle
*)iofs
->IOFS
.io_Unit
);
1455 struct filehandle
*fh
= (struct filehandle
*)iofs
->IOFS
.io_Unit
;
1457 if (fh
->type
== FHD_FILE
)
1459 if (fh
->fd
== STDOUT_FILENO
)
1461 fh
->fd
= STDIN_FILENO
;
1464 #ifdef EMUL_HANDLER_USE_UNIXIO
1465 //i am not sure what it is good for, looks like a kind of yield until data is available
1466 error
= Hidd_UnixIO_Wait(emulbase
->unixio
, fh
->fd
,
1467 vHidd_UnixIO_Read
, NULL
, NULL
,
1473 iofs
->io_Union
.io_READ
.io_Length
= DoRead(fh
->fd
, iofs
->io_Union
.io_READ
.io_Buffer
, iofs
->io_Union
.io_READ
.io_Length
);
1475 if (iofs
->io_Union
.io_READ
.io_Length
< 0)
1487 error
= ERROR_OBJECT_WRONG_TYPE
;
1495 struct filehandle
*fh
= (struct filehandle
*)iofs
->IOFS
.io_Unit
;
1497 if (fh
->type
== FHD_FILE
)
1499 if (fh
->fd
== STDIN_FILENO
)
1501 fh
->fd
=STDOUT_FILENO
;
1504 iofs
->io_Union
.io_WRITE
.io_Length
= DoWrite(fh
->fd
, iofs
->io_Union
.io_WRITE
.io_Buffer
, iofs
->io_Union
.io_WRITE
.io_Length
);
1506 if (iofs
->io_Union
.io_WRITE
.io_Length
< 0)
1513 error
= ERROR_OBJECT_WRONG_TYPE
;
1521 struct filehandle
*fh
= (struct filehandle
*)iofs
->IOFS
.io_Unit
;
1522 LONG mode
= iofs
->io_Union
.io_SEEK
.io_SeekMode
;
1525 if (fh
->type
== FHD_FILE
)
1527 oldpos
= LSeek(fh
->fd
, 0, SEEK_CUR
);
1529 if (mode
== OFFSET_BEGINNING
)
1533 else if (mode
== OFFSET_CURRENT
)
1542 if (LSeek(fh
->fd
, iofs
->io_Union
.io_SEEK
.io_Offset
, mode
) < 0)
1547 iofs
->io_Union
.io_SEEK
.io_Offset
= oldpos
;
1551 error
= ERROR_OBJECT_WRONG_TYPE
;
1557 case FSA_SET_FILE_SIZE
:
1558 #warning FIXME: Implement FSA_SET_FILE_SIZE
1559 /* We could manually change the size, but this is currently not
1560 implemented. FIXME */
1562 #warning FIXME: Implement FSA_WAIT_CHAR
1563 /* We could manually wait for a character to arrive, but this is
1564 currently not implemented. FIXME */
1566 #warning FIXME: Implement FSA_FILE_MODE
1567 error
=ERROR_ACTION_NOT_KNOWN
;
1570 case FSA_IS_INTERACTIVE
:
1572 struct filehandle
*fh
= (struct filehandle
*)iofs
->IOFS
.io_Unit
;
1574 if (fh
->type
== FHD_FILE
)
1576 iofs
->io_Union
.io_IS_INTERACTIVE
.io_IsInteractive
= Isatty(fh
->fd
);
1580 iofs
->io_Union
.io_IS_INTERACTIVE
.io_IsInteractive
= 0;
1588 struct filehandle
*lock1
= iofs
->io_Union
.io_SAME_LOCK
.io_Lock
[0],
1589 *lock2
= iofs
->io_Union
.io_SAME_LOCK
.io_Lock
[1];
1591 if ((lock1
->volume
!= lock2
->volume
) || strcmp(lock1
->name
, lock2
->name
))
1593 iofs
->io_Union
.io_SAME_LOCK
.io_Same
= LOCK_DIFFERENT
;
1597 iofs
->io_Union
.io_SAME_LOCK
.io_Same
= LOCK_SAME
;
1604 error
= examine(emulbase
,
1605 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1606 iofs
->io_Union
.io_EXAMINE
.io_ead
,
1607 iofs
->io_Union
.io_EXAMINE
.io_Size
,
1608 iofs
->io_Union
.io_EXAMINE
.io_Mode
,
1609 &(iofs
->io_DirPos
));
1612 case FSA_EXAMINE_NEXT
:
1613 error
= examine_next(emulbase
,
1614 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1615 iofs
->io_Union
.io_EXAMINE_NEXT
.io_fib
);
1618 case FSA_EXAMINE_ALL
:
1619 error
= examine_all(emulbase
,
1620 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1621 iofs
->io_Union
.io_EXAMINE_ALL
.io_ead
,
1622 iofs
->io_Union
.io_EXAMINE_ALL
.io_eac
,
1623 iofs
->io_Union
.io_EXAMINE_ALL
.io_Size
,
1624 iofs
->io_Union
.io_EXAMINE_ALL
.io_Mode
);
1627 case FSA_EXAMINE_ALL_END
:
1632 error
= open_file(emulbase
,
1633 (struct filehandle
**)&iofs
->IOFS
.io_Unit
,
1634 iofs
->io_Union
.io_OPEN_FILE
.io_Filename
,
1635 iofs
->io_Union
.io_OPEN_FILE
.io_FileMode
,
1636 iofs
->io_Union
.io_OPEN_FILE
.io_Protection
);
1638 (error
== ERROR_WRITE_PROTECTED
) &&
1639 (iofs
->io_Union
.io_OPEN_FILE
.io_FileMode
& FMF_AMIGADOS
)
1642 error
= open_file(emulbase
,
1643 (struct filehandle
**)&iofs
->IOFS
.io_Unit
,
1644 iofs
->io_Union
.io_OPEN_FILE
.io_Filename
,
1645 iofs
->io_Union
.io_OPEN_FILE
.io_FileMode
& (~FMF_WRITE
),
1646 iofs
->io_Union
.io_OPEN_FILE
.io_Protection
);
1650 case FSA_CREATE_DIR
:
1651 error
= create_dir(emulbase
,
1652 (struct filehandle
**)&iofs
->IOFS
.io_Unit
,
1653 iofs
->io_Union
.io_CREATE_DIR
.io_Filename
,
1654 iofs
->io_Union
.io_CREATE_DIR
.io_Protection
);
1657 case FSA_CREATE_HARDLINK
:
1658 error
= create_hardlink(emulbase
,
1659 (struct filehandle
**)&iofs
->IOFS
.io_Unit
,
1660 iofs
->io_Union
.io_CREATE_HARDLINK
.io_Filename
,
1661 (struct filehandle
*)iofs
->io_Union
.io_CREATE_HARDLINK
.io_OldFile
);
1664 case FSA_CREATE_SOFTLINK
:
1665 error
= create_softlink(emulbase
,
1666 (struct filehandle
**)&iofs
->IOFS
.io_Unit
,
1667 iofs
->io_Union
.io_CREATE_SOFTLINK
.io_Filename
,
1668 iofs
->io_Union
.io_CREATE_SOFTLINK
.io_Reference
);
1672 error
= rename_object(emulbase
,
1673 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1674 iofs
->io_Union
.io_RENAME
.io_Filename
,
1675 iofs
->io_Union
.io_RENAME
.io_NewName
);
1678 case FSA_READ_SOFTLINK
:
1679 error
= read_softlink(emulbase
,
1680 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1681 iofs
->io_Union
.io_READ_SOFTLINK
.io_Buffer
,
1682 iofs
->io_Union
.io_READ_SOFTLINK
.io_Size
);
1685 case FSA_DELETE_OBJECT
:
1686 error
= delete_object(emulbase
,
1687 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1688 iofs
->io_Union
.io_DELETE_OBJECT
.io_Filename
);
1691 case FSA_SET_PROTECT
:
1692 error
= set_protect(emulbase
,
1693 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1694 iofs
->io_Union
.io_SET_PROTECT
.io_Filename
,
1695 iofs
->io_Union
.io_SET_PROTECT
.io_Protection
);
1698 case FSA_PARENT_DIR
:
1699 /* error will always be 0 */
1700 error
= parent_dir(emulbase
,
1701 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1702 &(iofs
->io_Union
.io_PARENT_DIR
.io_DirName
));
1705 case FSA_PARENT_DIR_POST
:
1706 /* error will always be 0 */
1708 parent_dir_post(emulbase
, &(iofs
->io_Union
.io_PARENT_DIR
.io_DirName
));
1711 case FSA_IS_FILESYSTEM
:
1712 iofs
->io_Union
.io_IS_FILESYSTEM
.io_IsFilesystem
= TRUE
;
1718 struct InfoData
*id
= iofs
->io_Union
.io_INFO
.io_Info
;
1725 case FSA_SET_COMMENT
:
1728 case FSA_MORE_CACHE
:
1730 case FSA_MOUNT_MODE
:
1731 #warning FIXME: not supported yet
1734 error
= ERROR_ACTION_NOT_KNOWN
;
1739 ReleaseSemaphore(&emulbase
->sem
);
1741 /* Set error code */
1742 iofs
->io_DosError
= error
;
1744 /* If the quick bit is not set send the message to the port */
1745 if(!(iofs
->IOFS
.io_Flags
& IOF_QUICK
))
1747 ReplyMsg(&iofs
->IOFS
.io_Message
);
1753 /*********************************************************************************************/
1755 AROS_LH1(LONG
, abortio
,
1756 AROS_LHA(struct IOFileSys
*, iofs
, A1
),
1757 struct emulbase
*, emulbase
, 6, emul_handler
)
1761 /* Everything already done. */
1767 /*********************************************************************************************/
1768 #include <proto/kernel.h>
1770 struct TagItem
* EmulHandlerHooks
;
1773 APTR KernelBase
= OpenResource("kernel.resource");
1776 kprintf("[EmulHandler] got kernel.resource KernelBase=%p\n",KernelBase
);
1780 EmulHandlerHooks
= KrnGetHooks("emul_handler");
1782 if (EmulHandlerHooks
== 0)
1785 struct TagItem
* tag
;
1786 for (tag
= EmulHandlerHooks
; tag
->ti_Tag
!= TAG_DONE
; ++tag
)
1788 #define GETHOOK(HName) case EHND_ ## HName ## Impl: \
1789 Emul ## HName ## Impl = (struct Hook*)tag->ti_Data;\
1791 switch(tag
->ti_Tag
) {
1819 default: kprintf("[EmulHandler] unknown hook tag %i\n",tag
->ti_Tag
);