make fat.handler build again with debug enabled
[tangerine.git] / arch / i386-darwin / devs / filesys / emul_handler / emul_handler.c
blob54e0180baf05c8e4b1c1cc3bb8fede2a90d7f519
1 /*
2 Copyright © 1995-2008, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Filesystem that accesses an underlying POSIX filesystem.
6 Lang: english
7 */
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 /*********************************************************************************************/
18 /* AROS includes */
20 # define DEBUG 1
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>
37 #include <dos/bptr.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>
46 #include <oop/oop.h>
48 #include <aros/host-conf.h>
50 #include <unistd.h>
51 #include <string.h>
52 #include <stddef.h>
53 #include <sys/stat.h>
55 #include "emul_handler_intern.h"
56 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
57 # include "emul_handler_gcc.h"
58 #endif
60 #include <string.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);
166 FreeVec(ie);
168 CloseDevice((struct IORequest*)InputRequest);
170 DeleteIORequest ((APTR)InputRequest);
172 DeleteMsgPort (InputPort);
176 /*********************************************************************************************/
178 static APTR emul_malloc(struct emulbase *emulbase, ULONG size)
180 ULONG *res;
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);
193 return res;
196 /*********************************************************************************************/
198 static void emul_free(struct emulbase *emulbase, APTR mem)
200 if (!mem)
202 kprintf("*** emul_handler: tried to free NULL mem ***\n");
203 } else {
204 ULONG *m = (ULONG *)mem;
205 ULONG size = *--m;
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)
219 BOOL result = FALSE;
221 if ((*filename == '\0') ||
222 (!strcmp(filename, ".")) ||
223 (!strcmp(filename, "./")))
225 result = TRUE;
228 return result;
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)
238 char *s1,*s2;
239 unsigned long len;
241 if (filename[0] == '.')
242 if (filename[1] == '/') filename += 2;
244 for(;;)
246 /* leading slashes? --> return FALSE. */
247 if(*filename=='/') return FALSE;
249 /* remove superflous paths (ie paths that are followed by '//') */
250 s1=strstr(filename,"//");
251 if(s1==NULL)
252 break;
253 s2=s1;
254 while(s2 > filename)
256 if (s2[-1] == '/') break;
257 s2--;
260 memmove(s2,s1+2,strlen(s1+1));
263 /* strip trailing slash */
264 len=strlen(filename);
265 if(len&&filename[len-1]=='/')
266 filename[len-1]=0;
268 return TRUE;
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)
277 LONG ret = 0;
278 int len, dirlen;
279 dirlen = strlen(dirname) + 1;
280 len = strlen(filename) + dirlen + 1 + /*safety*/ 1;
281 *dest=(char *)emul_malloc(emulbase, len);
282 if ((*dest))
284 CopyMem(dirname, *dest, dirlen);
285 if (dirlen > 1)
287 if ((*dest)[dirlen - 2] != '/') strcat(*dest, "/");
290 strcat(*dest, filename);
292 if (!shrink(emulbase, *dest))
294 emul_free(emulbase, *dest);
295 *dest = NULL;
296 ret = ERROR_OBJECT_NOT_FOUND;
298 } else
299 ret = ERROR_NO_FREE_STORE;
301 return ret;
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;
317 return TRUE;
320 return FALSE;
323 /*********************************************************************************************/
325 /* Free a filehandle */
326 static LONG free_lock(struct emulbase *emulbase, struct filehandle *current)
328 switch(current->type)
330 case FHD_FILE:
331 if(current->fd!=STDIN_FILENO&&current->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);
342 if (current->DIR)
344 CloseDir(current->DIR);
347 break;
348 case FHD_DIRECTORY:
349 if (current->fd)
351 CloseDir(current->fd);
354 if (current->name)
355 emul_free(emulbase, current->name);
356 break;
358 FreeMem(current, sizeof(struct filehandle));
359 return 0;
362 /*********************************************************************************************/
364 static LONG open_(struct emulbase *emulbase, struct filehandle **handle,STRPTR name,LONG mode)
366 LONG ret = 0;
367 struct filehandle *fh;
368 long flags;
370 if (!check_volume(*handle, emulbase)) return ERROR_OBJECT_NOT_FOUND;
372 fh=(struct filehandle *)AllocMem(sizeof(struct filehandle), MEMF_PUBLIC);
373 if(fh!=NULL)
375 fh->pathname = NULL; /* just to make sure... */
376 fh->DIR = NULL;
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. */
383 fh->type=FHD_FILE;
384 fh->fd=(*handle)->fd;
385 fh->name="";
386 fh->volume=NULL;
387 fh->volumename=NULL;
388 *handle=fh;
389 return 0;
392 fh->volume=(*handle)->volume;
393 fh->volumename=(*handle)->volumename;
395 ret = makefilename(emulbase, &fh->name, (*handle)->name, name);
396 if (!ret)
398 int kind;
399 if(0<(kind = Stat(*fh->name?fh->name:".",0)))
401 if(kind == 1)
403 //FIXME: this should be aros flags, not unix
404 fh->fd = DoOpen(*fh->name?fh->name:".",flags,0770);
405 if(fh->fd >= 0)
407 *handle=fh;
408 return 0;
410 }else if(kind == 2)
412 /* file is a directory */
413 fh->type=FHD_DIRECTORY;
414 fh->fd=(long)OpenDir(*fh->name?fh->name:".");
415 if(fh->fd)
417 *handle=fh;
418 return 0;
420 }else
421 ret = ERROR_OBJECT_WRONG_TYPE;
423 /* Stat() failed. If ret is unset, generate it from errno. */
424 if (!ret)
425 ret = Errno();
427 emul_free(emulbase, fh->name);
429 FreeMem(fh, sizeof(struct filehandle));
430 } else
431 ret = ERROR_NO_FREE_STORE;
432 return ret;
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);
445 if(fh!=NULL)
447 fh->pathname = NULL; /* just to make sure... */
448 fh->DIR = NULL;
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. */
455 fh->type=FHD_FILE;
456 fh->fd=(*handle)->fd;
457 fh->name="";
458 fh->volume=0;
459 *handle=fh;
460 return 0;
463 fh->volume=(*handle)->volume;
464 fh->volumename=(*handle)->volumename;
466 ret = makefilename(emulbase, &fh->name, (*handle)->name, name);
467 if (!ret)
469 fh->type=FHD_FILE;
470 fh->fd=DoOpen(fh->name,mode,protect);
471 if (fh->fd != -1)
473 *handle=fh;
474 return 0;
476 ret=Errno();
477 emul_free(emulbase, fh->name);
479 FreeMem(fh, sizeof(struct filehandle));
481 return ret;
484 /*********************************************************************************************/
486 static LONG create_dir(struct emulbase *emulbase, struct filehandle **handle,
487 STRPTR filename, IPTR protect)
489 LONG ret = 0;
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);
495 if (fh)
497 fh->pathname = NULL; /* just to make sure... */
498 fh->name = NULL;
499 fh->DIR = NULL;
500 fh->fd = 0;
501 fh->volume = (*handle)->volume;
502 fh->volumename =(*handle)->volumename;
504 ret = makefilename(emulbase, &fh->name, (*handle)->name, filename);
505 if (!ret)
507 fh->type = FHD_DIRECTORY;
509 if (!MKDir(fh->name, protect))
511 *handle = fh;
512 (*handle)->fd = (long)OpenDir((*handle)->name);
513 if ((*handle)->fd)
514 return 0;
516 ret = Errno();
518 free_lock(emulbase, fh);
519 } else
520 ret = ERROR_NO_FREE_STORE;
522 return ret;
525 /*********************************************************************************************/
527 static LONG delete_object(struct emulbase *emulbase, struct filehandle* fh,
528 STRPTR file)
530 LONG ret = 0;
531 char *filename = NULL;
533 if (!check_volume(fh, emulbase)) return ERROR_OBJECT_NOT_FOUND;
535 ret = makefilename(emulbase, &filename, fh->name, file);
536 if (!ret)
538 Delete(filename);
539 ret = Errno();
540 emul_free(emulbase, filename);
543 return ret;
546 /*********************************************************************************************/
548 static LONG set_protect(struct emulbase *emulbase, struct filehandle* fh,
549 STRPTR file, ULONG aprot)
551 LONG ret = 0;
552 char *filename = NULL;
554 if (!check_volume(fh, emulbase)) return ERROR_OBJECT_NOT_FOUND;
556 if ((ret = makefilename(emulbase, &filename, fh->name, file)))
557 return ret;
559 if (Chmod(filename, aprot))
560 ret = Errno();
562 emul_free(emulbase, filename);
564 return ret;
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);
582 if(fhi!=NULL)
584 kprintf("[Emulhandler] allocated fhi\n");
585 fhi->pathname = NULL; /* just to make sure... */
586 fhi->DIR = NULL;
587 fhi->volume = NULL;
588 fhi->volumename = NULL;
590 fho=(struct filehandle *)AllocMem(sizeof(struct filehandle), MEMF_PUBLIC);
591 if(fho!=NULL)
593 kprintf("[Emulhandler] startup allocated fho\n");
594 fho->pathname = NULL; /* just to make sure... */
595 fho->DIR = NULL;
596 fho->volume = NULL;
597 fho->volumename = NULL;
599 fhe=(struct filehandle *)AllocMem(sizeof(struct filehandle), MEMF_PUBLIC);
600 if(fhe!=NULL)
602 kprintf("[Emulhandler] startup allocated fhe\n");
603 fhe->pathname = NULL; /* just to make sure... */
604 fhe->DIR = NULL;
605 fhe->volume = NULL;
606 fhe->volumename = NULL;
608 fhv=(struct filehandle *)AllocMem(sizeof(struct filehandle) + 256 + AROS_WORSTALIGN, MEMF_PUBLIC);
609 if(fhv != NULL)
611 kprintf("[Emulhandler] startup allocated fhv\n");
612 fhv->name = ".";
613 fhv->type = FHD_DIRECTORY;
614 fhv->pathname = NULL; /* just to make sure... */
615 fhv->DIR = NULL;
616 fhv->volume=(char *)(fhv + 1);
618 /* Make sure that the root directory is valid */
619 int kind;
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;
636 fhi->name = "";
637 fho->type = FHD_FILE;
638 fho->fd = STDOUT_FILENO;
639 fho->name = "";
640 fhe->type = FHD_FILE;
641 fhe->fd = STDERR_FILENO;
642 fhe->name = "";
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
652 purposes.
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");
665 BSTR s;
666 BSTR s2;
667 WORD i;
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;
686 dlv->dn_Name = s;
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",
695 // DLT_VOLUME));
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;
708 dlv2->dn_Name = s2;
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);
714 return 0;
716 } /* valid directory */
717 else
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);
732 return ret;
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
746 filename.
748 char * pathname_from_name (struct emulbase *emulbase, char * name)
750 long len = strlen(name);
751 long i = len;
752 char * result = NULL;
753 /* look for the first '/' in the filename starting at the end */
754 while (i != 0 && name[i] != '/')
755 i--;
757 if (0 != i)
759 result = (char *)emul_malloc(emulbase, i+1);
760 if(!result)
761 return NULL;
762 strncpy(result, name, i);
763 result[i]=0x0;
765 return result;
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);
774 long i = len;
775 char * result = NULL;
776 /* look for the first '/' in the filename starting at the end */
777 while (i != 0 && name[i] != '/')
778 i--;
780 if (0 != i)
782 result = (char *)emul_malloc(emulbase, len-i);
783 if(!result)
784 return NULL;
785 strncpy(result, &name[i+1], len-i);
786 result[len-i-1]=0x0;
788 return result;
791 /*********************************************************************************************/
793 static LONG examine(struct emulbase *emulbase,
794 struct filehandle *fh,
795 struct ExAllData *ead,
796 ULONG size,
797 ULONG type,
798 off_t *dirpos)
800 STRPTR next, end, last, name;
802 /* Return an error, if supplied type is not supported. */
803 if(type>ED_OWNER)
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);
817 if(kind>0)
818 return Errno();
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)
829 char * filename;
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);
839 if(!fh->DIR)
841 emul_free(emulbase, filename);
842 return Errno();
846 dirname = DirName(fh->DIR);
848 while (NULL != dirname &&
849 0 != strcmp(dirname, filename));
850 emul_free(emulbase, filename);
851 if(!dirname)
853 int errno = Errno();
854 if(!errno)
855 return ERROR_NO_MORE_ENTRIES;
856 else
857 return errno;
860 *dirpos = (LONG)TellDir(fh->DIR);
864 else
866 *dirpos = (LONG)TellDir(fh->fd);
868 switch(type)
870 default:
871 case ED_OWNER:
872 ead->ed_OwnerUID = FIB.fib_OwnerUID;
873 ead->ed_OwnerGID = FIB.fib_OwnerGID;
874 case ED_COMMENT:
875 ead->ed_Comment=NULL;
876 case ED_DATE:
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;
880 case ED_PROTECTION:
881 ead->ed_Prot = FIB.fib_Protection;
882 case ED_SIZE:
883 ead->ed_Size = FIB.fib_Size;
884 case ED_TYPE:
885 if (kind == 2)
887 if (is_root_filename(fh->name))
889 ead->ed_Type = ST_ROOT;
890 } else {
891 ead->ed_Type = ST_USERDIR;
893 } else {
894 ead->ed_Type = ST_FILE;
897 case ED_NAME:
898 ead->ed_Name=next;
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')
903 last=name="";
905 while(*name)
906 if(*name++=='/')
907 last=name;
908 for(;;)
910 if(next>=end)
911 return ERROR_BUFFER_OVERFLOW;
912 if(!(*next++=*last++))
913 break;
915 case 0:
916 ead->ed_Next=(struct ExAllData *)(((IPTR)next+AROS_PTRALIGN-1)&~(AROS_PTRALIGN-1));
917 return 0;
921 /*********************************************************************************************/
923 static LONG examine_next(struct emulbase *emulbase,
924 struct filehandle *fh,
925 struct FileInfoBlock *FIB)
927 int i;
928 const char * dirname;
929 char *name, *src, *dest, *pathname;
930 IPTR ReadDIR;
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;
936 switch(fh->type)
938 case FHD_DIRECTORY:
939 SeekDir(fh->fd, FIB->fib_DiskKey);
940 pathname = fh->name; /* it's just a directory! */
941 ReadDIR = fh->fd;
942 break;
944 case FHD_FILE:
945 SeekDir(fh->DIR, FIB->fib_DiskKey);
946 pathname = fh->pathname;
947 ReadDIR = fh->DIR;
948 break;
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
954 ./././ etc. */
955 /*#undef kprintf*/
958 dirname = DirName(ReadDIR);
960 if (NULL == dirname)
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);
969 if (NULL == name)
970 return ERROR_NO_FREE_STORE;
972 strcpy(name, pathname);
974 if (*name)
975 strcat(name, "/");
977 strcat(name, dirname);
979 if (0<Stat(name,FIB))
981 D(bug("Stat() failed for %s\n", name));
983 emul_free(emulbase, name);
985 return Errno();
988 emul_free(emulbase, name);
990 /* fast copying of the filename */
991 src = dirname;
992 dest = FIB->fib_FileName;
994 for (i =0; i<MAXFILENAMELENGTH-1;i++)
996 if(! (*dest++=*src++) )
998 break;
1002 FIB->fib_DiskKey = (LONG)TellDir(ReadDIR);
1004 return 0;
1007 /*********************************************************************************************/
1009 static LONG examine_all(struct emulbase *emulbase,
1010 struct filehandle *fh,
1011 struct ExAllData *ead,
1012 struct ExAllControl *eac,
1013 ULONG size,
1014 ULONG type)
1016 struct ExAllData *last=NULL;
1017 STRPTR end=(STRPTR)ead+size, name, old;
1018 off_t oldpos;
1019 const char * dirname;
1020 LONG error;
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;
1029 for(;;)
1031 oldpos=TellDir(fh->fd);
1032 dirname=DirName(fh->fd);
1033 error = Errno();
1034 if(dirname==NULL)
1036 break;
1038 if(dirname[0]=='.'&&(!dirname[1]||(dirname[1]=='.'&&!dirname[2])))
1039 continue;
1040 name=(STRPTR)emul_malloc(emulbase, strlen(fh->name)+strlen(dirname)+2);
1041 if(name==NULL)
1043 error=ERROR_NO_FREE_STORE;
1044 break;
1046 strcpy(name,fh->name);
1047 if(*name)
1048 strcat(name,"/");
1049 strcat(name,dirname);
1050 old=fh->name;
1051 fh->name=name;
1052 error=examine(emulbase,fh,ead,end-(STRPTR)ead,type,&dummy);
1053 fh->name=old;
1054 emul_free(emulbase, name);
1055 if(error)
1056 break;
1057 eac->eac_Entries++;
1058 last=ead;
1059 ead=ead->ed_Next;
1061 if (last!=NULL)
1062 last->ed_Next=NULL;
1063 if((error==ERROR_BUFFER_OVERFLOW)&&last!=NULL)
1065 SeekDir(fh->fd,oldpos);
1066 return 0;
1068 if(!error)
1069 error=ERROR_NO_MORE_ENTRIES;
1070 RewindDir(fh->fd);
1071 return error;
1074 /*********************************************************************************************/
1076 static LONG create_hardlink(struct emulbase *emulbase,
1077 struct filehandle **handle,STRPTR name,struct filehandle *oldfile)
1079 LONG error=0L;
1080 struct filehandle *fh;
1082 if (!check_volume(*handle, emulbase)) return ERROR_OBJECT_NOT_FOUND;
1084 fh = AllocMem(sizeof(struct filehandle), MEMF_PUBLIC);
1085 if (!fh)
1086 return ERROR_NO_FREE_STORE;
1088 fh->pathname = NULL; /* just to make sure... */
1089 fh->DIR = NULL;
1091 error = makefilename(emulbase, &fh->name, (*handle)->name, name);
1092 if (!error)
1094 if (!Link(oldfile->name, fh->name))
1095 *handle = fh;
1096 else
1097 error = Errno();
1098 } else
1100 error = ERROR_NO_FREE_STORE;
1101 FreeMem(fh, sizeof(struct filehandle));
1104 return error;
1107 /*********************************************************************************************/
1109 static LONG create_softlink(struct emulbase * emulbase,
1110 struct filehandle **handle, STRPTR name, STRPTR ref)
1112 LONG error=0L;
1113 struct filehandle *fh;
1115 if (!check_volume(*handle, emulbase)) return ERROR_OBJECT_NOT_FOUND;
1117 fh = AllocMem(sizeof(struct filehandle), MEMF_PUBLIC);
1118 if(!fh)
1119 return ERROR_NO_FREE_STORE;
1121 fh->pathname = NULL; /* just to make sure... */
1122 fh->DIR = NULL;
1124 error = makefilename(emulbase, &fh->name, (*handle)->name, name);
1125 if (!error)
1127 if (!SymLink(ref, fh->name))
1128 *handle = fh;
1129 else
1130 error = Errno();
1131 } else
1133 error = ERROR_NO_FREE_STORE;
1134 FreeMem(fh, sizeof(struct filehandle));
1137 return error;
1140 /*********************************************************************************************/
1142 static LONG rename_object(struct emulbase * emulbase,
1143 struct filehandle *fh, STRPTR file, STRPTR newname)
1145 LONG ret = 0L;
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);
1152 if (!ret)
1154 ret = makefilename(emulbase, &newfilename, fh->name, newname);
1155 if (!ret)
1157 if (DoRename(filename,newfilename))
1158 ret = Errno();
1159 emul_free(emulbase, newfilename);
1161 emul_free(emulbase, filename);
1164 return ret;
1168 static LONG read_softlink(struct emulbase *emulbase,
1169 struct filehandle *fh,
1170 STRPTR buffer,
1171 ULONG size)
1173 if (!check_volume(fh, emulbase)) return ERROR_OBJECT_NOT_FOUND;
1175 if (DoReadLink(fh->name, buffer, size-1) == -1)
1176 return Errno();
1178 return 0L;
1181 /*********************************************************************************************/
1183 ULONG parent_dir(struct emulbase *emulbase,
1184 struct filehandle *fh,
1185 char ** DirName)
1187 *DirName = pathname_from_name(emulbase, fh->name);
1188 return 0;
1191 /*********************************************************************************************/
1193 void parent_dir_post(struct emulbase *emulbase, char ** DirName)
1195 /* free the previously allocated memory */
1196 emul_free(emulbase, *DirName);
1197 **DirName = 0;
1200 /*********************************************************************************************/
1202 /************************ Library entry points ************************/
1204 int loadhooks();
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)
1213 return FALSE;
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);
1228 return FALSE;
1230 #endif
1232 if(!startup(emulbase))
1234 D(bug("emul_handler initialized OK\n"));
1235 return TRUE;
1238 #ifdef EMUL_HANDLER_USE_UNIXIO
1239 OOP_DisposeObject (emulbase->unixio);
1240 #endif
1242 DeletePool(emulbase->mempool);
1244 D(bug("emul_handler startup failed\n"));
1246 return FALSE;
1249 /*********************************************************************************************/
1251 static BOOL new_volume(struct IOFileSys *iofs, struct emulbase *emulbase)
1253 struct filehandle *fhv;
1254 struct DosList *doslist;
1255 char *unixpath;
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, ':');
1265 if (unixpath)
1267 char *sp;
1269 *unixpath++ = '\0';
1271 if ((sp = strchr(unixpath, '~')))
1273 char *home = NULL;
1274 char *newunixpath = 0;
1275 char *sp_end;
1276 BOOL do_endpwent = FALSE;
1277 BOOL ok = FALSE;
1279 /* "~<name>" means home of user <name> */
1281 if ((sp[1] == '\0') || (sp[1] == '/'))
1283 sp_end = sp + 1;
1284 home = GetEnv("HOME");
1286 else
1288 struct passwd *pwd;
1289 WORD cmplen;
1290 char tmp;
1292 for(sp_end = sp + 1;
1293 sp_end[0] != '\0' && sp_end[0] != '/';
1294 sp_end++);
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);
1303 sp[cmplen+1] = tmp;
1307 if (home)
1309 newunixpath = AllocVec(strlen(unixpath) + strlen(home) + 1, MEMF_CLEAR);
1310 if (newunixpath)
1312 strncpy(newunixpath, unixpath, sp - unixpath);
1313 strcat(newunixpath, home);
1314 strcat(newunixpath, sp_end);
1316 ok = TRUE;
1317 unixpath = newunixpath;
1321 ClosePW();
1323 if (!ok)
1325 unixpath = 0;
1326 if (newunixpath) FreeVec(newunixpath);
1330 if (unixpath)
1332 if (Stat(unixpath,0)>0)
1334 fhv=(struct filehandle *)AllocMem(sizeof(struct filehandle), MEMF_PUBLIC);
1335 if (fhv != NULL)
1337 fhv->name = ".";
1338 fhv->type = FHD_DIRECTORY;
1339 fhv->pathname = NULL; /* just to make sure... */
1340 fhv->DIR = NULL;
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);
1356 return TRUE;
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);
1372 return FALSE;
1376 /*********************************************************************************************/
1378 static int GM_UNIQUENAME(Open)
1380 LIBBASETYPEPTR emulbase,
1381 struct IOFileSys *iofs,
1382 ULONG unitnum,
1383 ULONG flags
1386 /* Keep compiler happy */
1387 unitnum=0;
1388 flags=0;
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;
1396 return FALSE;
1399 /* Set returncode */
1400 iofs->IOFS.io_Error=0;
1401 return TRUE;
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)
1415 AROS_LIBFUNC_INIT
1417 LONG error = 0;
1419 /* WaitIO will look into this */
1420 iofs->IOFS.io_Message.mn_Node.ln_Type=NT_MESSAGE;
1422 /* Disable(); */
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)
1431 case FSA_OPEN:
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);
1436 if (
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));
1447 break;
1449 case FSA_CLOSE:
1450 error = free_lock(emulbase, (struct filehandle *)iofs->IOFS.io_Unit);
1451 break;
1453 case FSA_READ:
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,
1468 SysBase);
1469 #endif
1471 if (error == 0)
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)
1477 error = Errno();
1480 else
1482 error = Errno();
1485 else
1487 error = ERROR_OBJECT_WRONG_TYPE;
1490 break;
1493 case FSA_WRITE:
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)
1508 error = Errno();
1511 else
1513 error = ERROR_OBJECT_WRONG_TYPE;
1516 break;
1519 case FSA_SEEK:
1521 struct filehandle *fh = (struct filehandle *)iofs->IOFS.io_Unit;
1522 LONG mode = iofs->io_Union.io_SEEK.io_SeekMode;
1523 LONG oldpos;
1525 if (fh->type == FHD_FILE)
1527 oldpos = LSeek(fh->fd, 0, SEEK_CUR);
1529 if (mode == OFFSET_BEGINNING)
1531 mode = SEEK_SET;
1533 else if (mode == OFFSET_CURRENT)
1535 mode = SEEK_CUR;
1537 else
1539 mode = SEEK_END;
1542 if (LSeek(fh->fd, iofs->io_Union.io_SEEK.io_Offset, mode) < 0)
1544 error = Errno();
1547 iofs->io_Union.io_SEEK.io_Offset = oldpos;
1549 else
1551 error = ERROR_OBJECT_WRONG_TYPE;
1554 break;
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 */
1561 case FSA_WAIT_CHAR:
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 */
1565 case FSA_FILE_MODE:
1566 #warning FIXME: Implement FSA_FILE_MODE
1567 error=ERROR_ACTION_NOT_KNOWN;
1568 break;
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);
1578 else
1580 iofs->io_Union.io_IS_INTERACTIVE.io_IsInteractive = 0;
1583 break;
1586 case FSA_SAME_LOCK:
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;
1595 else
1597 iofs->io_Union.io_SAME_LOCK.io_Same = LOCK_SAME;
1600 break;
1603 case FSA_EXAMINE:
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));
1610 break;
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);
1616 break;
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);
1625 break;
1627 case FSA_EXAMINE_ALL_END:
1628 error = 0;
1629 break;
1631 case FSA_OPEN_FILE:
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);
1637 if (
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);
1648 break;
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);
1655 break;
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);
1662 break;
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);
1669 break;
1671 case FSA_RENAME:
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);
1676 break;
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);
1683 break;
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);
1689 break;
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);
1696 break;
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));
1703 break;
1705 case FSA_PARENT_DIR_POST:
1706 /* error will always be 0 */
1707 error = 0;
1708 parent_dir_post(emulbase, &(iofs->io_Union.io_PARENT_DIR.io_DirName));
1709 break;
1711 case FSA_IS_FILESYSTEM:
1712 iofs->io_Union.io_IS_FILESYSTEM.io_IsFilesystem = TRUE;
1713 error = 0;
1714 break;
1716 case FSA_DISK_INFO:
1718 struct InfoData *id = iofs->io_Union.io_INFO.io_Info;
1720 StatFS(".",id);
1722 break;
1725 case FSA_SET_COMMENT:
1726 case FSA_SET_OWNER:
1727 case FSA_SET_DATE:
1728 case FSA_MORE_CACHE:
1729 case FSA_FORMAT:
1730 case FSA_MOUNT_MODE:
1731 #warning FIXME: not supported yet
1733 default:
1734 error = ERROR_ACTION_NOT_KNOWN;
1735 break;
1738 /*Enable();*/
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);
1750 AROS_LIBFUNC_EXIT
1753 /*********************************************************************************************/
1755 AROS_LH1(LONG, abortio,
1756 AROS_LHA(struct IOFileSys *, iofs, A1),
1757 struct emulbase *, emulbase, 6, emul_handler)
1759 AROS_LIBFUNC_INIT
1761 /* Everything already done. */
1762 return 0;
1764 AROS_LIBFUNC_EXIT
1767 /*********************************************************************************************/
1768 #include <proto/kernel.h>
1770 struct TagItem * EmulHandlerHooks;
1771 int loadhooks()
1773 APTR KernelBase = OpenResource("kernel.resource");
1775 if (KernelBase)
1776 kprintf("[EmulHandler] got kernel.resource KernelBase=%p\n",KernelBase);
1777 else
1778 return 1;
1780 EmulHandlerHooks = KrnGetHooks("emul_handler");
1782 if (EmulHandlerHooks == 0)
1783 return 1;
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;\
1790 break;
1791 switch(tag->ti_Tag) {
1792 GETHOOK(Stat);
1793 GETHOOK(LStat);
1794 GETHOOK(CloseDir);
1795 GETHOOK(Close);
1796 GETHOOK(OpenDir);
1797 GETHOOK(Open);
1798 GETHOOK(ChDir);
1799 GETHOOK(DirName);
1800 GETHOOK(TellDir);
1801 GETHOOK(SeekDir);
1802 GETHOOK(RewindDir);
1803 GETHOOK(Delete);
1804 GETHOOK(Rename);
1805 GETHOOK(GetEnv);
1806 GETHOOK(GetCWD);
1807 GETHOOK(GetHome);
1808 GETHOOK(ClosePW);
1809 GETHOOK(StatFS);
1810 GETHOOK(Chmod);
1811 GETHOOK(Isatty);
1812 GETHOOK(Link);
1813 GETHOOK(MKDir);
1814 GETHOOK(LSeek);
1815 GETHOOK(Read);
1816 GETHOOK(ReadLink);
1817 GETHOOK(SymLink);
1818 GETHOOK(Write);
1819 default: kprintf("[EmulHandler] unknown hook tag %i\n",tag->ti_Tag);
1822 return 0;