2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
5 Desc: Filesystem that accesses an underlying host OS filesystem.
9 /*********************************************************************************************/
26 #include <aros/debug.h>
27 #include <aros/symbolsets.h>
28 #include <exec/memory.h>
29 #include <devices/input.h>
30 #include <devices/inputevent.h>
31 #include <libraries/expansion.h>
32 #include <proto/exec.h>
33 #include <utility/tagitem.h>
34 #include <dos/exall.h>
35 #include <dos/dosasl.h>
36 #include <proto/arossupport.h>
37 #include <proto/dos.h>
38 #include <proto/expansion.h>
40 #include "emul_intern.h"
48 #define bstrcpy strcpy
52 #define bstrcpy(d, s) \
59 /*********************************************************************************************/
61 static void SendEvent(struct emulbase
*emulbase
, LONG event
)
63 struct IOStdReq
*InputRequest
;
64 struct MsgPort
*InputPort
;
65 struct InputEvent
*ie
;
67 D(bug("[emul] SendEvent\n"));
68 if ((InputPort
= (struct MsgPort
*)CreateMsgPort())) {
70 if ((InputRequest
= (struct IOStdReq
*)CreateIORequest(InputPort
, sizeof(struct IOStdReq
)))) {
72 if (!OpenDevice("input.device", 0, (struct IORequest
*)InputRequest
, 0)) {
74 if ((ie
= AllocVec(sizeof(struct InputEvent
), MEMF_PUBLIC
|MEMF_CLEAR
))) {
76 InputRequest
->io_Command
= IND_WRITEEVENT
;
77 InputRequest
->io_Data
= ie
;
78 InputRequest
->io_Length
= sizeof(struct InputEvent
);
80 DoIO((struct IORequest
*)InputRequest
);
84 CloseDevice((struct IORequest
*)InputRequest
);
86 DeleteIORequest ((APTR
)InputRequest
);
88 DeleteMsgPort (InputPort
);
92 /*********************************************************************************************/
94 /* Allocate a buffer, in which the filename is appended to the pathname. */
95 static LONG
makefilename(struct emulbase
*emulbase
, char **dest
, char **part
, struct filehandle
*fh
, const char *filename
)
98 int len
, flen
, dirlen
;
101 DFNAME(bug("[emul] makefilename(): directory \"%s\", file \"%s\")\n", fh
->hostname
, filename
));
104 * dos.library will give us whatever the user typed. It won't strip away device prefix.
105 * Here we have to do it ourselves.
107 c
= strrchr(filename
, ':');
111 ret
= validate(filename
);
115 dirlen
= strlen(fh
->hostname
);
116 flen
= strlen(filename
);
117 len
= flen
+ dirlen
+ 2;
119 *dest
= AllocVecPooled(emulbase
->mempool
, len
);
122 CopyMem(fh
->hostname
, *dest
, dirlen
);
125 c
= append(c
, filename
);
128 c
= *dest
+ (fh
->name
- fh
->hostname
);
129 DFNAME(bug("[emul] Shrinking filename: \"%s\"\n", c
));
132 FreeVecPooled(emulbase
->mempool
, *dest
);
134 ret
= ERROR_OBJECT_NOT_FOUND
;
136 DFNAME(bug("[emul] resulting host filename: \"%s\"\n", *dest
));
139 DFNAME(bug("[emul] resulting AROS filename: \"%s\"\n", c
));
143 ret
= ERROR_NO_FREE_STORE
;
147 /*********************************************************************************************/
149 /* Free a filehandle */
150 static void free_lock(struct emulbase
*emulbase
, struct filehandle
*current
)
152 DLOCK(bug("[emul] Lock type = %lu\n", current
->type
));
153 DoClose(emulbase
, current
);
155 DLOCK(bug("[emul] Freeing name: \"%s\"\n", current
->hostname
));
156 FreeVecPooled(emulbase
->mempool
, current
->hostname
);
158 DLOCK(bug("[emul] Freeing filehandle\n"));
159 FreeMem(current
, sizeof(struct filehandle
));
161 DLOCK(bug("[emul] Done\n"));
164 /*********************************************************************************************/
166 static LONG
open_(struct emulbase
*emulbase
, struct filehandle
*fhv
, struct filehandle
**handle
, const char *name
, LONG access
, LONG mode
, LONG protect
, BOOL AllowDir
)
169 struct filehandle
*fh
;
171 DOPEN(bug("[emul] open_(\"%s\", 0x%lx), directories allowed: %lu\n", name
, mode
, AllowDir
));
173 fh
= (struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
|MEMF_CLEAR
);
176 fh
->dl
= (*handle
)->dl
;
178 /* If no filename is given and the file-descriptor is one of the
179 standard filehandles (stdin, stdout, stderr) ... */
180 if((!name
[0]) && ((*handle
)->type
& FHD_STDIO
))
182 /* ... then just reopen that standard filehandle. */
183 fh
->type
= FHD_FILE
|FHD_STDIO
;
184 fh
->fd
= (*handle
)->fd
;
187 fh
->volumename
= NULL
;
193 fh
->volumename
=(*handle
)->volumename
;
195 ret
= makefilename(emulbase
, &fh
->hostname
, &fh
->name
, *handle
, name
);
198 /* If the name is empty, this is an alias of the root
201 if (fh
->name
[0] == 0) {
202 FreeVecPooled(emulbase
->mempool
, fh
->hostname
);
203 FreeMem(fh
, sizeof(*fh
));
206 return ERROR_OBJECT_WRONG_TYPE
;
212 ret
= DoOpen(emulbase
, fh
, access
, mode
, protect
, AllowDir
);
219 DOPEN(bug("[emul] Freeing pathname\n"));
220 FreeVecPooled(emulbase
->mempool
, fh
->hostname
);
222 DOPEN(bug("[emul] Freeing filehandle\n"));
223 FreeMem(fh
, sizeof(struct filehandle
));
225 ret
= ERROR_NO_FREE_STORE
;
226 DOPEN(bug("[emul] open_() returns %lu\n", ret
));
231 /*********************************************************************************************/
233 static LONG
create_dir(struct emulbase
*emulbase
, struct filehandle
**handle
,
234 const char *filename
, ULONG protect
)
237 struct filehandle
*fh
;
239 fh
= (struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
|MEMF_CLEAR
);
242 fh
->volumename
= (*handle
)->volumename
;
243 fh
->dl
= (*handle
)->dl
;
245 ret
= makefilename(emulbase
, &fh
->hostname
, &fh
->name
, *handle
, filename
);
248 ret
= DoMkDir(emulbase
, fh
, protect
);
255 free_lock(emulbase
, fh
);
257 ret
= ERROR_NO_FREE_STORE
;
262 /*********************************************************************************************/
264 static LONG
delete_object(struct emulbase
*emulbase
, struct filehandle
* fh
, const char *file
)
267 char *filename
= NULL
;
269 DDEL(bug("[emul] Deleting object %s in handle 0x%p (%s)\n", file
, fh
, fh
->hostname
));
271 ret
= makefilename(emulbase
, &filename
, NULL
, fh
, file
);
274 ret
= DoDelete(emulbase
, filename
);
275 FreeVecPooled(emulbase
->mempool
, filename
);
281 /*********************************************************************************************/
283 static LONG
set_protect(struct emulbase
*emulbase
, struct filehandle
* fh
,
284 const char *file
, ULONG aprot
)
287 char *filename
= NULL
;
289 if ((ret
= makefilename(emulbase
, &filename
, NULL
, fh
, file
)))
292 ret
= DoChMod(emulbase
, filename
, aprot
);
294 FreeVecPooled(emulbase
->mempool
, filename
);
298 /*********************************************************************************************/
300 const ULONG sizes
[] = {
302 offsetof(struct ExAllData
,ed_Type
),
303 offsetof(struct ExAllData
,ed_Size
),
304 offsetof(struct ExAllData
,ed_Prot
),
305 offsetof(struct ExAllData
,ed_Days
),
306 offsetof(struct ExAllData
,ed_Comment
),
307 offsetof(struct ExAllData
,ed_OwnerUID
),
308 sizeof(struct ExAllData
)
311 static SIPTR
examine(struct emulbase
*emulbase
, struct filehandle
*fh
,
312 struct FileInfoBlock
*fib
)
314 UBYTE buff
[sizeof(struct ExAllData
) +
315 sizeof(fib
->fib_FileName
) + 1 +
316 sizeof(fib
->fib_Comment
) + 1];
317 struct ExAllData
*ead
= (APTR
)&buff
[0];
320 err
= DoExamineEntry(emulbase
, fh
, NULL
, ead
, sizeof(buff
), ED_OWNER
);
324 memset(fib
, 0, sizeof(*fib
));
327 fib
->fib_FileName
[0] = strlen(ead
->ed_Name
) + 1;
328 if (fib
->fib_FileName
[0] > sizeof(fib
->fib_FileName
)-1)
329 fib
->fib_FileName
[0] = sizeof(fib
->fib_FileName
)-1;
330 CopyMem(ead
->ed_Name
, &fib
->fib_FileName
[1], fib
->fib_FileName
[0]);
333 if (ead
->ed_Comment
) {
334 fib
->fib_Comment
[0] = strlen(ead
->ed_Comment
) + 1;
335 if (fib
->fib_Comment
[0] > sizeof(fib
->fib_Comment
)-1)
336 fib
->fib_Comment
[0] = sizeof(fib
->fib_Comment
)-1;
337 CopyMem(ead
->ed_Comment
, &fib
->fib_Comment
[1], fib
->fib_Comment
[0]);
340 fib
->fib_DiskKey
= 0;
341 fib
->fib_DirEntryType
= ead
->ed_Type
;
342 fib
->fib_Protection
= ead
->ed_Prot
;
343 fib
->fib_EntryType
= ead
->ed_Type
;
344 fib
->fib_Size
= ead
->ed_Size
;
345 fib
->fib_NumBlocks
= (ead
->ed_Size
+ 512 - 1) / 512;
346 fib
->fib_Date
.ds_Days
= ead
->ed_Days
;
347 fib
->fib_Date
.ds_Minute
= ead
->ed_Mins
;
348 fib
->fib_Date
.ds_Tick
= ead
->ed_Ticks
;
349 fib
->fib_OwnerUID
= ead
->ed_OwnerUID
;
350 fib
->fib_OwnerGID
= ead
->ed_OwnerGID
;
355 /*********************************************************************************************/
357 static LONG
create_hardlink(struct emulbase
*emulbase
, struct filehandle
*handle
, const char *name
, struct filehandle
*oldfile
)
362 DLINK(bug("[emul] Creating hardlink %s to file %s\n", name
, oldfile
->hostname
));
363 error
= makefilename(emulbase
, &fn
, NULL
, handle
, name
);
366 DLINK(bug("[emul] Host name of the link: %s\n", fn
));
367 error
= DoHardLink(emulbase
, fn
, oldfile
->hostname
);
368 FreeVecPooled(emulbase
->mempool
, fn
);
374 /*********************************************************************************************/
376 static LONG
create_softlink(struct emulbase
* emulbase
,
377 struct filehandle
*handle
, const char *name
, const char *ref
)
382 DLINK(bug("[emul] Creating softlink %s to file %s\n", name
, ref
));
383 DLINK(bug("[emul] Handle 0x%p, pathname %s\n", handle
, handle
->hostname
));
384 error
= makefilename(emulbase
, &dest
, NULL
, handle
, name
);
387 char *src
= AllocVecPooled(emulbase
->mempool
, strlen(ref
)+1);
391 DLINK(bug("[emul] Link host name: %s\n", dest
));
392 error
= DoSymLink(emulbase
, src
, dest
);
393 DLINK(bug("[emul] Error: %d\n", error
));
395 FreeVecPooled(emulbase
->mempool
, src
);
398 error
= ERROR_NO_FREE_STORE
;
400 FreeVecPooled(emulbase
->mempool
, dest
);
406 /*********************************************************************************************/
408 static LONG
rename_object(struct emulbase
* emulbase
, struct filehandle
*fh
,
409 const char *file
, struct filehandle
*fh2
, const char *newname
)
413 char *filename
= NULL
, *newfilename
= NULL
;
415 /* FIXME: fh2 is unused! */
416 ret
= makefilename(emulbase
, &filename
, NULL
, fh
, file
);
419 ret
= makefilename(emulbase
, &newfilename
, NULL
, fh
, newname
);
422 ret
= DoRename(emulbase
, filename
, newfilename
);
423 FreeVecPooled(emulbase
->mempool
, newfilename
);
425 FreeVecPooled(emulbase
->mempool
, filename
);
431 /*********************************************************************************************/
433 static LONG
read_softlink(struct emulbase
*emulbase
, struct filehandle
*fh
, CONST_STRPTR link
,
434 STRPTR buffer
, SIPTR
*size
, struct DosLibrary
*DOSBase
)
438 char *filename
= NULL
;
439 long l
= strlen(link
) + 1;
441 DLINK(bug("read_softlink: link %s len %d\n", link
, l
));
443 /* don't mess with link itself */
444 ln
= AllocVecPooled(emulbase
->mempool
, l
);
447 return ERROR_NO_FREE_STORE
;
449 CopyMem(link
, ln
, l
);
451 ret
= makefilename(emulbase
, &filename
, NULL
, fh
, ln
);
454 int targetlen
= DoReadLink(emulbase
, filename
, buffer
, *size
, &ret
);
455 DLINK(bug("read_softlink: targetlen %d\n", targetlen
));
457 FreeVecPooled(emulbase
->mempool
, filename
);
463 buffer
[targetlen
] = '\0';
464 DLINK(bug("read_softlink: buffer after DoReadLink %s\n", buffer
));
465 if (strchr(buffer
, ':') == NULL
)
467 STRPTR source
= FilePart(ln
);
469 /* strip file part of link */
471 if (strlen(ln
) + targetlen
>= *size
)
473 DLINK(bug("read_softlink: buffer too small %d>=%u\n", strlen(ln
) + targetlen
, *size
));
474 /* Buffer was too small */
479 /* copy buffer to create resolved link path in it */
480 char* target
= AllocVecPooled(emulbase
->mempool
, targetlen
+1);
483 strcpy(target
, buffer
);
487 strcat(buffer
, target
);
488 *size
= strlen(buffer
);
491 FreeVecPooled(emulbase
->mempool
, target
);
494 ret
= ERROR_NO_FREE_STORE
;
499 *size
= targetlen
>= *size
? -2 : strlen(buffer
);
504 DLINK(if (!ret
) bug("read_softlink: buffer %s\n", buffer
));
505 FreeVecPooled(emulbase
->mempool
, ln
);
510 /*********************************************************************************************/
512 static SIPTR
parent_dir(struct emulbase
*emulbase
,
513 struct filehandle
*fhv
,
514 struct filehandle
**fhp
)
518 DCHDIR(bug("[emul] Original directory: \"%s\"\n", (*fhp
)->name
));
519 err
= open_(emulbase
, fhv
, fhp
, "/", ACCESS_READ
, MODE_OLDFILE
, 0, TRUE
);
520 DCHDIR(bug("[emul] Parent directory: \"%s\"\n", err
? NULL
: (*fhp
)->name
));
525 /*********************************************************************************************/
527 static LONG
set_date(struct emulbase
*emulbase
, struct filehandle
*fh
,
528 const char *FileName
, struct DateStamp
*date
)
533 ret
= makefilename(emulbase
, &fullname
, NULL
, fh
, FileName
);
536 ret
= DoSetDate(emulbase
, fullname
, date
);
538 FreeVecPooled(emulbase
->mempool
, fullname
);
543 static LONG
disk_info(struct emulbase
*emulbase
, struct filehandle
*fh
, struct InfoData
*id
)
545 LONG Res2
= DoStatFS(emulbase
, fh
->hostname
, id
);
549 /* Fill in host-independent part */
550 id
->id_UnitNumber
= 0;
551 id
->id_DiskType
= ID_DOS_DISK
; /* Well, not really true... */
552 id
->id_VolumeNode
= MKBADDR(fh
->dl
);
553 id
->id_InUse
= TRUE
; /* Perhaps we should count locks? */
559 /*********************************************************************************************/
561 #define VOLNAME "System"
562 #define VOLNAME_LEN 6
564 static struct filehandle
*new_volume(struct emulbase
*emulbase
, const char *path
, struct MsgPort
*mp
, struct DosLibrary
*DOSBase
)
566 struct filehandle
*fhv
;
567 struct DosList
*doslist
;
574 * MakeDosNode() creates zero-length fssm_Device instead of BNULL pointer when ParamPkt[1] is zero.
575 * CHECKME: is this correct, or MakeDosNode() needs to be fixed?
579 DMOUNT(bug("[emul] Mounting volume %s\n", path
));
582 * Volume name and Unix path are encoded into DEVICE entry of
583 * MountList like this: <volumename>:<unixpath>
592 } while (*path
++ != ':');
593 DMOUNT(bug("[emul] Host path: %s, volume name length %u\n", path
, vol_len
));
595 sp
= strchr(path
, '~');
598 unixpath
= GetHomeDir(emulbase
, sp
+ 1);
602 unixpath
= AllocVecPooled(emulbase
->mempool
, strlen(path
)+1);
606 CopyMem(path
, unixpath
, strlen(path
)+1);
613 DMOUNT(bug("[emul] Mounting root volume\n"));
615 unixpath
= AllocVecPooled(emulbase
->mempool
, PATH_MAX
);
619 res
= GetCurrentDir(emulbase
, unixpath
, PATH_MAX
);
620 DMOUNT(bug("[emul] GetCurrentDir() returned %d\n", res
));
627 D(bug("[emul] startup directory %s\n", unixpath
));
630 vol_len
= VOLNAME_LEN
+ 1;
633 DMOUNT(bug("[emul] Resolved host path: %s\n", unixpath
));
635 if (CheckDir(emulbase
, unixpath
))
637 FreeVecPooled(emulbase
->mempool
, unixpath
);
641 fhv
= AllocMem(sizeof(struct filehandle
) + vol_len
, MEMF_PUBLIC
|MEMF_CLEAR
);
642 DMOUNT(bug("[emul] Volume file handle: 0x%p\n", fhv
));
645 char *volname
= (char *)fhv
+ sizeof(struct filehandle
);
647 CopyMem(vol
, volname
, vol_len
- 1);
648 volname
[vol_len
- 1] = 0;
650 fhv
->hostname
= unixpath
;
651 fhv
->name
= unixpath
+ strlen(unixpath
);
652 fhv
->type
= FHD_DIRECTORY
;
653 fhv
->volumename
= volname
;
654 if (!DoOpen(emulbase
, fhv
, ACCESS_READ
, MODE_OLDFILE
, 0, TRUE
)) {
655 DMOUNT(bug("[emul] Making volume node %s\n", volname
));
657 doslist
= MakeDosEntry(volname
, DLT_VOLUME
);
658 DMOUNT(bug("[emul] Volume node 0x%p\n", doslist
));
662 doslist
->dol_Task
= mp
;
663 AddDosEntry(doslist
);
665 SendEvent(emulbase
, IECLASS_DISKINSERTED
);
667 DMOUNT(bug("[emul] Mounting done\n"));
670 DMOUNT(bug("[emul] DOS Volume add failed, freeing volume node\n"));
673 DMOUNT(bug("[emul] Failed, freeing volume node\n"));
674 FreeVecPooled(emulbase
->mempool
, unixpath
);
675 FreeMem(fhv
, sizeof(struct filehandle
) + vol_len
);
678 DMOUNT(bug("[emul] Mounting failed\n"));
682 #define FH_FROM(x) ((struct filehandle *)(x))
683 #define FH_FROM_LOCK(x) \
684 ({ BPTR _x = (BPTR)x; \
689 _fh = (APTR)(((struct FileLock *)BADDR(_x))->fl_Key); \
691 (struct filehandle *)_fh;\
694 static void handlePacket(struct emulbase
*emulbase
, struct filehandle
*fhv
, struct MsgPort
*mp
, struct DosPacket
*dp
, struct DosLibrary
*DOSBase
)
696 SIPTR Res1
= DOSFALSE
;
697 SIPTR Res2
= ERROR_UNKNOWN
;
698 struct filehandle
*fh
, *fh2
;
699 struct FileHandle
*f
;
700 struct FileLock
*fl
, *fl2
;
703 DB2(bug("[emul] Got command %u\n", dp
->dp_Type
));
707 case ACTION_FINDINPUT
:
708 case ACTION_FINDOUTPUT
:
709 case ACTION_FINDUPDATE
:
710 f
= BADDR(dp
->dp_Arg1
);
711 fh2
= FH_FROM_LOCK(dp
->dp_Arg2
);
713 DCMD(bug("[emul] %p ACTION_FIND%s: %p, %p, %b\n", fhv
, (dp
->dp_Type
== ACTION_FINDINPUT
) ? "INPUT" : ((dp
->dp_Type
== ACTION_FINDOUTPUT
) ? "OUTPUT" : "UPDATE"), fh
, fh2
, dp
->dp_Arg3
));
714 Res2
= open_(emulbase
, fhv
, &fh2
, AROS_BSTR_ADDR(dp
->dp_Arg3
), ACCESS_WRITE
, dp
->dp_Type
, 0, FALSE
);
718 f
->fh_Arg1
= (SIPTR
)fh2
;
729 fh
= FH_FROM(dp
->dp_Arg1
);
730 DCMD(bug("[emul] %p ACTION_END\n", fhv
, fh
));
734 free_lock(emulbase
, fh
);
741 fh
= FH_FROM(dp
->dp_Arg1
);
742 DCMD(bug("[emul] %p ACTION_READ\n", fhv
, fh
));
744 if (fh
->type
& FHD_FILE
)
746 Res1
= DoRead(emulbase
, fh
, (APTR
)dp
->dp_Arg2
, dp
->dp_Arg3
, &Res2
);
750 Res2
= ERROR_OBJECT_WRONG_TYPE
;
755 fh
= FH_FROM(dp
->dp_Arg1
);
756 DCMD(bug("[emul] %p ACTION_WRITE\n", fhv
, fh
));
758 if (fh
->type
& FHD_FILE
)
760 Res1
= DoWrite(emulbase
, fh
, (APTR
)dp
->dp_Arg2
, dp
->dp_Arg3
, &Res2
);
763 Res2
= ERROR_OBJECT_WRONG_TYPE
;
768 fh
= FH_FROM(dp
->dp_Arg1
);
769 DCMD(bug("[emul] %p ACTION_SEEK %p, mode %ld, offset %lu\n", fhv
, fh
, dp
->dp_Arg3
, dp
->dp_Arg2
));
771 if (fh
->type
== FHD_FILE
)
772 Res1
= DoSeek(emulbase
, fh
, dp
->dp_Arg2
, dp
->dp_Arg3
, &Res2
);
775 Res2
= ERROR_OBJECT_WRONG_TYPE
;
780 case ACTION_SET_FILE_SIZE
:
781 fh
= FH_FROM(dp
->dp_Arg1
);
782 DCMD(bug("[emul] %p ACTION_SET_FILE_SIZE: %p, mode %ld, offset %llu\n", fhv
, fh
, dp
->dp_Arg2
, dp
->dp_Arg3
));
784 Res1
= DoSetSize(emulbase
, fh
, dp
->dp_Arg2
, dp
->dp_Arg3
, &Res2
);
790 case ACTION_SAME_LOCK
:
791 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
792 fh2
= FH_FROM_LOCK(dp
->dp_Arg2
);
794 DCMD(bug("[emul] %p ACTION_SAME_LOCK: %p, %p\n", fhv
, fh
, fh2
));
795 DSAME(bug("[emul] Paths: %s, %s\n", fh
->hostname
, fh2
->hostname
));
798 /* DOSTRUE means 'Same', DOSFALSE means 'Different' */
799 Res1
= strcasecmp(fh
->hostname
, fh2
->hostname
) ? DOSFALSE
: DOSTRUE
;
801 DSAME(bug("[emul] Replying with 0x%p, %ld\n", Res1
, Res2
));
804 case ACTION_EXAMINE_FH
:
805 fh
= FH_FROM(dp
->dp_Arg1
);
806 DCMD(bug("[emul] %p ACTION_EXAMINE_FH: %p, fib %p\n", fhv
, fh
, BADDR(dp
->dp_Arg2
)));
807 Res2
= examine(emulbase
, fh
, (struct FileInfoBlock
*)BADDR(dp
->dp_Arg2
));
808 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
811 case ACTION_EXAMINE_OBJECT
:
812 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
813 DCMD(bug("[emul] %p ACTION_EXAMINE_OBJECT: %p, fib %p\n", fhv
, fh
, BADDR(dp
->dp_Arg2
)));
814 Res2
= examine(emulbase
, fh
, (struct FileInfoBlock
*)BADDR(dp
->dp_Arg2
));
815 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
818 case ACTION_EXAMINE_NEXT
:
819 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
820 DCMD(bug("[emul] %p ACTION_EXAMINE_NEXT: %p, fib %p (key %d)\n", fhv
, fh
, BADDR(dp
->dp_Arg2
), ((struct FileInfoBlock
*)BADDR(dp
->dp_Arg2
))->fib_DiskKey
));
821 Res2
= DoExamineNext(emulbase
, (struct filehandle
*)fh
, (struct FileInfoBlock
*)BADDR(dp
->dp_Arg2
));
822 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
825 case ACTION_EXAMINE_ALL
:
826 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
827 DCMD(bug("[emul] %p ACTION_EXAMINE_ALL: %p\n", fhv
, fh
));
828 Res2
= DoExamineAll(emulbase
, fh
, (APTR
)dp
->dp_Arg2
, BADDR(dp
->dp_Arg5
),
829 dp
->dp_Arg3
, dp
->dp_Arg4
, DOSBase
);
830 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
833 case ACTION_EXAMINE_ALL_END
:
835 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
836 DCMD(bug("[emul] %p ACTION_EXAMINE_ALL_END: %p\n", fhv
, fh
));
837 Res2
= DoRewindDir(emulbase
, (struct filehandle
*)fh
);
838 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
841 case ACTION_CREATE_DIR
:
842 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
843 DCMD(bug("[emul] %p ACTION_CREATE_DIR: %p, %b\n", fhv
, fh
, dp
->dp_Arg2
));
845 fl
= AllocMem(sizeof(*fl
), MEMF_ANY
| MEMF_CLEAR
);
847 Res2
= ERROR_NO_FREE_STORE
;
852 Res2
= create_dir(emulbase
, &fh
, AROS_BSTR_ADDR(dp
->dp_Arg2
),
853 FIBF_GRP_EXECUTE
| FIBF_GRP_READ
|
854 FIBF_OTR_EXECUTE
| FIBF_OTR_READ
);
855 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
856 if (Res1
!= DOSTRUE
) {
857 FreeMem(fl
, sizeof(*fl
));
863 fl
->fl_Key
= (IPTR
)fh
;
864 fl
->fl_Access
= ACCESS_READ
;
866 fl
->fl_Volume
= MKBADDR(fh
->dl
);
872 case ACTION_LOCATE_OBJECT
:
873 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
874 DCMD(bug("[emul] %p ACTION_LOCATE_OBJECT: %p, %b\n", fhv
, fh
, dp
->dp_Arg2
));
876 fl
= AllocMem(sizeof(*fl
), MEMF_ANY
| MEMF_CLEAR
);
878 Res2
= ERROR_NO_FREE_STORE
;
883 Res2
= open_(emulbase
, fhv
, &fh
, AROS_BSTR_ADDR(dp
->dp_Arg2
), dp
->dp_Arg3
, MODE_OLDFILE
, 0755, TRUE
);
886 FreeMem(fl
, sizeof(*fl
));
892 fl
->fl_Key
= (IPTR
)fh
;
893 fl
->fl_Access
= dp
->dp_Arg3
;
895 fl
->fl_Volume
= MKBADDR(fh
->dl
);
902 case ACTION_FH_FROM_LOCK
:
903 f
= BADDR(dp
->dp_Arg1
);
904 fh2
= FH_FROM_LOCK(dp
->dp_Arg2
);
905 fl
= BADDR(dp
->dp_Arg2
);
906 DCMD(bug("[emul] %p ACTION_FH_FROM_LOCK: %p, lock %p\n", fhv
, fh
, fh2
));
908 f
->fh_Arg1
= (SIPTR
)fh2
;
911 FreeMem(fl
, sizeof(*fl
));
917 case ACTION_COPY_DIR
: /* DupLock */
918 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
919 fl
= BADDR(dp
->dp_Arg1
);
920 DCMD(bug("[emul] %p ACTION_COPY_DIR: %p\n", fhv
, fh
));
922 fl2
= AllocMem(sizeof(*fl2
), MEMF_ANY
| MEMF_CLEAR
);
924 Res2
= ERROR_NO_FREE_STORE
;
929 CopyMem(fl
, fl2
, sizeof(*fl2
));
934 Res1
= (SIPTR
)MKBADDR(fl2
);
937 case ACTION_COPY_DIR_FH
: /* Dup */
938 fh
= FH_FROM(dp
->dp_Arg1
);
939 DCMD(bug("[emul] %p ACTION_COPY_DIR_FH: %p\n", fhv
, fh
));
941 fl
= AllocMem(sizeof(*fl
), MEMF_ANY
| MEMF_CLEAR
);
943 Res2
= ERROR_NO_FREE_STORE
;
950 fl
->fl_Key
= (IPTR
)fh
;
951 fl
->fl_Access
= ACCESS_READ
;
953 fl
->fl_Volume
= MKBADDR(fh
->dl
);
958 Res1
= (SIPTR
)MKBADDR(fl
);
961 case ACTION_FREE_LOCK
:
962 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
963 fl
= BADDR(dp
->dp_Arg1
);
964 DCMD(bug("[emul] %p ACTION_FREE_LOCK: %p\n", fhv
, fh
));
966 FreeMem(fl
, sizeof(*fl
));
970 free_lock(emulbase
, fh
);
977 case ACTION_MAKE_LINK
:
978 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
980 Res2
= ERROR_UNKNOWN
;
981 if (dp
->dp_Arg4
== LINK_SOFT
) {
982 DCMD(bug("[emul] %p ACTION_MAKE_LINK: %p, dest \"%b\", src \"%b\"\n", fhv
, fh
, dp
->dp_Arg2
, dp
->dp_Arg3
));
983 Res2
= create_softlink(emulbase
, fh
, AROS_BSTR_ADDR(dp
->dp_Arg2
), AROS_BSTR_ADDR(dp
->dp_Arg3
));
984 } else if (dp
->dp_Arg4
== LINK_HARD
) {
985 fh2
= FH_FROM_LOCK(dp
->dp_Arg3
);
986 DCMD(bug("[emul] %p ACTION_MAKE_LINK: %p, dest \"%b\", src %p\n", fhv
, fh
, dp
->dp_Arg2
, fh2
));
987 Res2
= create_hardlink(emulbase
, fh
, AROS_BSTR_ADDR(dp
->dp_Arg2
), fh2
);
990 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
993 case ACTION_RENAME_OBJECT
:
994 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
995 fh2
= FH_FROM_LOCK(dp
->dp_Arg3
);
996 DCMD(bug("[emul] %p ACTION_RENAME_OBJECT: %p, \"%b\" => %p, \"%b\"\n", fhv
, fh
, dp
->dp_Arg2
, fh2
, dp
->dp_Arg4
));
997 Res2
= rename_object(emulbase
, fh
, AROS_BSTR_ADDR(dp
->dp_Arg2
), fh2
, AROS_BSTR_ADDR(dp
->dp_Arg4
));
999 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
1002 case ACTION_READ_LINK
:
1003 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
1004 DCMD(bug("[emul] %p ACTION_READ_LINK: %p\n", fhv
, fh
));
1006 Res2
= read_softlink(emulbase
, fh
, (APTR
)dp
->dp_Arg2
, (APTR
)dp
->dp_Arg3
, &Res1
, DOSBase
);
1009 case ACTION_DELETE_OBJECT
:
1010 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
1011 DCMD(bug("[emul] %p ACTION_DELETE_OBJECT: %p\n", fhv
, fh
));
1012 Res2
= delete_object(emulbase
, fh
, AROS_BSTR_ADDR(dp
->dp_Arg2
));
1013 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
1016 case ACTION_SET_PROTECT
:
1017 /* dp_Arg1 is unused */
1018 fh
= FH_FROM_LOCK(dp
->dp_Arg2
);
1019 DCMD(bug("[emul] %p ACTION_SET_PROTECT: %p\n", fhv
, fh
));
1020 Res2
= set_protect(emulbase
, fh
, AROS_BSTR_ADDR(dp
->dp_Arg3
), dp
->dp_Arg4
);
1021 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
1025 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
1026 DCMD(bug("[emul] %p ACTION_PARENT: %p\n", fhv
, fh
));
1034 fl
= AllocMem(sizeof(*fl
), MEMF_ANY
| MEMF_CLEAR
);
1036 Res2
= ERROR_NO_FREE_STORE
;
1041 Res2
= parent_dir(emulbase
, fhv
, &fh
);
1043 FreeMem(fl
, sizeof(*fl
));
1049 fl
->fl_Link
= BNULL
;
1050 fl
->fl_Key
= (IPTR
)fh
;
1051 fl
->fl_Access
= ACCESS_READ
;
1053 fl
->fl_Volume
= MKBADDR(fh
->dl
);
1057 Res1
= (SIPTR
)MKBADDR(fl
);
1061 case ACTION_PARENT_FH
:
1062 fh
= FH_FROM(dp
->dp_Arg1
);
1063 DCMD(bug("[emul] %p ACTION_PARENT_FH: %p\n", fhv
, fh
));
1071 fl
= AllocMem(sizeof(*fl
), MEMF_ANY
| MEMF_CLEAR
);
1073 Res2
= ERROR_NO_FREE_STORE
;
1078 Res2
= parent_dir(emulbase
, fhv
, &fh
);
1080 FreeMem(fl
, sizeof(*fl
));
1086 fl
->fl_Link
= BNULL
;
1087 fl
->fl_Key
= (IPTR
)fh
;
1088 fl
->fl_Access
= ACCESS_READ
;
1090 fl
->fl_Volume
= MKBADDR(fh
->dl
);
1094 Res1
= (SIPTR
)MKBADDR(fl
);
1098 case ACTION_IS_FILESYSTEM
:
1099 DCMD(bug("[emul] %p ACTION_IS_FILESYSTEM:\n", fhv
));
1105 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
1106 id
= BADDR(dp
->dp_Arg2
);
1107 DCMD(bug("[emul] %p ACTION_INFO:\n", fhv
));
1109 Res2
= disk_info(emulbase
, fh
, id
);
1110 Res1
= Res2
? DOSFALSE
: DOSTRUE
;
1113 case ACTION_DISK_INFO
:
1114 id
= (struct InfoData
*)BADDR(dp
->dp_Arg1
);
1115 DCMD(bug("[emul] %p ACTION_DISK_INFO:\n", fhv
));
1117 Res2
= disk_info(emulbase
, fhv
, id
);
1118 Res1
= Res2
? DOSFALSE
: DOSTRUE
;
1121 case ACTION_SET_DATE
:
1122 /* dp_Arg1 is unused */
1123 fh
= FH_FROM_LOCK(dp
->dp_Arg2
);
1124 DCMD(bug("[emul] %p ACTION_SET_DATE: %p\n", fhv
, fh
));
1125 Res2
= set_date(emulbase
, fh
, AROS_BSTR_ADDR(dp
->dp_Arg3
), (struct DateStamp
*)dp
->dp_Arg4
);
1126 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
1129 case ACTION_SET_OWNER
:
1130 /* pretend to have changed owner, avoids tons of error messages from e.g. tar */
1134 /* FIXME: not supported yet
1135 case ACTION_SET_COMMENT:
1136 case ACTION_MORE_CACHE:
1137 case ACTION_WAIT_CHAR:
1140 DCMD(bug("[emul] Unknown action %lu\n", dp
->dp_Type
));
1141 Res2
= ERROR_ACTION_NOT_KNOWN
;
1146 /* Set error code */
1147 DCMD(bug("[emul] Replying with 0x%p, %ld\n", Res1
, Res2
));
1149 ReplyPkt(dp
, Res1
, Res2
);
1152 static void EmulHandler_work(struct ExecBase
*SysBase
)
1154 struct DosLibrary
*DOSBase
;
1155 struct DosPacket
*dp
;
1156 struct DeviceNode
*dn
;
1157 struct FileSysStartupMsg
*fssm
;
1158 STRPTR devpath
= NULL
;
1160 struct filehandle
*fhv
;
1161 struct emulbase
*emulbase
;
1162 const STRPTR hname
= "emul-handler";
1164 DOSBase
= (APTR
)OpenLibrary("dos.library", 0);
1168 mp
= &((struct Process
*)FindTask(NULL
))->pr_MsgPort
;
1170 /* Wait for startup message. */
1171 D(bug("EMUL: Waiting for startup...\n"));
1173 dp
= (struct DosPacket
*)(GetMsg(mp
)->mn_Node
.ln_Name
);
1175 D(bug("EMUL: Open resource\n"));
1176 emulbase
= OpenResource(hname
);
1179 D(bug("EMUL: FATAL - can't find myself\n"));
1180 ReplyPkt(dp
, DOSFALSE
, ERROR_INVALID_RESIDENT_LIBRARY
);
1184 /* emul-handler is really a .resource. This causes the problem that the startup code is not put
1185 * at the beginning of module, making RunHandler not being able to "start" the handler if it
1186 * is loaded at a later date (for example by "mount home:"). Making the module resident is
1187 * a workaround for this problem. The full solution would most likely mean separating most of
1188 * the code to real .resource and then building a thin "real handler" emul-handler on top of
1191 if (FindSegment(hname
, NULL
, TRUE
) == BNULL
)
1192 AddSegment(hname
, CreateSegList(EmulHandlerMain
), CMD_INTERNAL
);
1195 fssm
= BADDR(dp
->dp_Arg2
);
1197 devpath
= AROS_BSTR_ADDR(fssm
->fssm_Device
);
1199 fhv
= new_volume(emulbase
, devpath
, mp
, DOSBase
);
1202 D(bug("EMUL: FATAL - can't create the inital volume \"%s\"\n", devpath
));
1203 ReplyPkt(dp
, DOSFALSE
, ERROR_NO_FREE_STORE
);
1207 /* Now, once we know all is well with the world,
1208 * we tell DOS that we're the handler for this
1211 dn
= BADDR(dp
->dp_Arg3
);
1214 ReplyPkt(dp
, DOSTRUE
, 0);
1220 handlePacket(emulbase
, fhv
, mp
, dp
, DOSBase
);
1223 D(bug("EMUL: Closing volume %s\n", fhv
->volumename
));
1224 RemDosEntry(fhv
->dl
);
1225 free_lock(emulbase
, fhv
);
1226 CloseLibrary((APTR
)DOSBase
);
1229 AROS_PROCH(EmulHandlerMain
, argptr
, argstr
, SysBase
)
1233 EmulHandler_work(SysBase
);