2 Copyright 1995-2011, 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 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 FreeMem(fh
, sizeof(*fh
));
205 return ERROR_OBJECT_WRONG_TYPE
;
211 ret
= DoOpen(emulbase
, fh
, mode
, protect
, AllowDir
);
218 DOPEN(bug("[emul] Freeing pathname\n"));
219 FreeVecPooled(emulbase
->mempool
, fh
->hostname
);
221 DOPEN(bug("[emul] Freeing filehandle\n"));
222 FreeMem(fh
, sizeof(struct filehandle
));
224 ret
= ERROR_NO_FREE_STORE
;
225 DOPEN(bug("[emul] open_() returns %lu\n", ret
));
230 /*********************************************************************************************/
232 static LONG
create_dir(struct emulbase
*emulbase
, struct filehandle
**handle
,
233 const char *filename
, ULONG protect
)
236 struct filehandle
*fh
;
238 fh
= (struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
|MEMF_CLEAR
);
241 fh
->volumename
= (*handle
)->volumename
;
242 fh
->dl
= (*handle
)->dl
;
244 ret
= makefilename(emulbase
, &fh
->hostname
, &fh
->name
, *handle
, filename
);
247 ret
= DoMkDir(emulbase
, fh
, protect
);
254 free_lock(emulbase
, fh
);
256 ret
= ERROR_NO_FREE_STORE
;
261 /*********************************************************************************************/
263 static LONG
delete_object(struct emulbase
*emulbase
, struct filehandle
* fh
, const char *file
)
266 char *filename
= NULL
;
268 DDEL(bug("[emul] Deleting object %s in handle 0x%p (%s)\n", file
, fh
, fh
->hostname
));
270 ret
= makefilename(emulbase
, &filename
, NULL
, fh
, file
);
273 ret
= DoDelete(emulbase
, filename
);
274 FreeVecPooled(emulbase
->mempool
, filename
);
280 /*********************************************************************************************/
282 static LONG
set_protect(struct emulbase
*emulbase
, struct filehandle
* fh
,
283 const char *file
, ULONG aprot
)
286 char *filename
= NULL
;
288 if ((ret
= makefilename(emulbase
, &filename
, NULL
, fh
, file
)))
291 ret
= DoChMod(emulbase
, filename
, aprot
);
293 FreeVecPooled(emulbase
->mempool
, filename
);
297 /*********************************************************************************************/
299 const ULONG sizes
[] = {
301 offsetof(struct ExAllData
,ed_Type
),
302 offsetof(struct ExAllData
,ed_Size
),
303 offsetof(struct ExAllData
,ed_Prot
),
304 offsetof(struct ExAllData
,ed_Days
),
305 offsetof(struct ExAllData
,ed_Comment
),
306 offsetof(struct ExAllData
,ed_OwnerUID
),
307 sizeof(struct ExAllData
)
310 static SIPTR
examine(struct emulbase
*emulbase
, struct filehandle
*fh
,
311 struct FileInfoBlock
*fib
)
313 UBYTE buff
[sizeof(struct ExAllData
) +
314 sizeof(fib
->fib_FileName
) + 1 +
315 sizeof(fib
->fib_Comment
) + 1];
316 struct ExAllData
*ead
= (APTR
)&buff
[0];
319 err
= DoExamineEntry(emulbase
, fh
, NULL
, ead
, sizeof(buff
), ED_OWNER
);
323 memset(fib
, 0, sizeof(*fib
));
326 fib
->fib_FileName
[0] = strlen(ead
->ed_Name
) + 1;
327 if (fib
->fib_FileName
[0] > sizeof(fib
->fib_FileName
)-1)
328 fib
->fib_FileName
[0] = sizeof(fib
->fib_FileName
)-1;
329 CopyMem(ead
->ed_Name
, &fib
->fib_FileName
[1], fib
->fib_FileName
[0]);
332 if (ead
->ed_Comment
) {
333 fib
->fib_Comment
[0] = strlen(ead
->ed_Comment
) + 1;
334 if (fib
->fib_Comment
[0] > sizeof(fib
->fib_Comment
)-1)
335 fib
->fib_Comment
[0] = sizeof(fib
->fib_Comment
)-1;
336 CopyMem(ead
->ed_Comment
, &fib
->fib_Comment
[1], fib
->fib_Comment
[0]);
339 fib
->fib_DiskKey
= 0;
340 fib
->fib_DirEntryType
= ead
->ed_Type
;
341 fib
->fib_Protection
= ead
->ed_Prot
;
342 fib
->fib_EntryType
= ead
->ed_Type
;
343 fib
->fib_Size
= ead
->ed_Size
;
344 fib
->fib_NumBlocks
= (ead
->ed_Size
+ 512 - 1) / 512;
345 fib
->fib_Date
.ds_Days
= ead
->ed_Days
;
346 fib
->fib_Date
.ds_Minute
= ead
->ed_Mins
;
347 fib
->fib_Date
.ds_Tick
= ead
->ed_Ticks
;
348 fib
->fib_OwnerUID
= ead
->ed_OwnerUID
;
349 fib
->fib_OwnerGID
= ead
->ed_OwnerGID
;
354 /*********************************************************************************************/
356 /* Returns an allocated buffer, containing a pathname, stripped by the filename. */
357 char *pathname_from_name (struct emulbase
*emulbase
, char *name
)
359 long len
= strlen(name
);
363 /* look for the first '\' in the filename starting at the end */
364 i
= startpos(name
, len
);
368 result
= AllocVecPooled(emulbase
->mempool
, i
+ 1);
372 copyname(result
, name
, i
);
378 /*********************************************************************************************/
380 static LONG
create_hardlink(struct emulbase
*emulbase
, struct filehandle
*handle
, const char *name
, struct filehandle
*oldfile
)
385 DLINK(bug("[emul] Creating hardlink %s to file %s\n", name
, oldfile
->hostname
));
386 error
= makefilename(emulbase
, &fn
, NULL
, handle
, name
);
389 DLINK(bug("[emul] Host name of the link: %s\n", fn
));
390 error
= DoHardLink(emulbase
, fn
, oldfile
->hostname
);
391 FreeVecPooled(emulbase
->mempool
, fn
);
397 /*********************************************************************************************/
399 static LONG
create_softlink(struct emulbase
* emulbase
,
400 struct filehandle
*handle
, const char *name
, const char *ref
)
405 DLINK(bug("[emul] Creating softlink %s to file %s\n", name
, ref
));
406 DLINK(bug("[emul] Handle 0x%p, pathname %s\n", handle
, handle
->hostname
));
407 error
= makefilename(emulbase
, &dest
, NULL
, handle
, name
);
410 char *src
= AllocVecPooled(emulbase
->mempool
, strlen(ref
)+1);
414 DLINK(bug("[emul] Link host name: %s\n", dest
));
415 error
= DoSymLink(emulbase
, src
, dest
);
416 DLINK(bug("[emul] Error: %d\n", error
));
418 FreeVecPooled(emulbase
->mempool
, src
);
421 error
= ERROR_NO_FREE_STORE
;
423 FreeVecPooled(emulbase
->mempool
, dest
);
429 /*********************************************************************************************/
431 static LONG
rename_object(struct emulbase
* emulbase
, struct filehandle
*fh
,
432 const char *file
, struct filehandle
*fh2
, const char *newname
)
436 char *filename
= NULL
, *newfilename
= NULL
;
438 /* FIXME: fh2 is unused! */
439 ret
= makefilename(emulbase
, &filename
, NULL
, fh
, file
);
442 ret
= makefilename(emulbase
, &newfilename
, NULL
, fh
, newname
);
445 ret
= DoRename(emulbase
, filename
, newfilename
);
446 FreeVecPooled(emulbase
->mempool
, newfilename
);
448 FreeVecPooled(emulbase
->mempool
, filename
);
454 /*********************************************************************************************/
456 static LONG
read_softlink(struct emulbase
*emulbase
, struct filehandle
*fh
, CONST_STRPTR link
,
457 STRPTR buffer
, SIPTR
*size
, struct DosLibrary
*DOSBase
)
461 char *filename
= NULL
;
462 long l
= strlen(link
) + 1;
464 DLINK(bug("read_softlink: link %s len %d\n", link
, l
));
466 /* don't mess with link itself */
467 ln
= AllocVecPooled(emulbase
->mempool
, l
);
470 return ERROR_NO_FREE_STORE
;
472 CopyMem(link
, ln
, l
);
474 ret
= makefilename(emulbase
, &filename
, NULL
, fh
, ln
);
477 int targetlen
= DoReadLink(emulbase
, filename
, buffer
, *size
, &ret
);
478 DLINK(bug("read_softlink: targetlen %d\n", targetlen
));
480 FreeVecPooled(emulbase
->mempool
, filename
);
486 buffer
[targetlen
] = '\0';
487 DLINK(bug("read_softlink: buffer after DoReadLink %s\n", buffer
));
488 if (strchr(buffer
, ':') == NULL
)
490 STRPTR source
= FilePart(ln
);
492 /* strip file part of link */
494 if (strlen(ln
) + targetlen
>= *size
)
496 DLINK(bug("read_softlink: buffer too small %d>=%u\n", strlen(ln
) + targetlen
, *size
));
497 /* Buffer was too small */
502 /* copy buffer to create resolved link path in it */
503 char* target
= AllocVecPooled(emulbase
->mempool
, targetlen
+1);
506 strcpy(target
, buffer
);
510 strcat(buffer
, target
);
511 *size
= strlen(buffer
);
514 FreeVecPooled(emulbase
->mempool
, target
);
517 ret
= ERROR_NO_FREE_STORE
;
522 *size
= targetlen
>= *size
? -2 : strlen(buffer
);
527 DLINK(if (!ret
) bug("read_softlink: buffer %s\n", buffer
));
528 FreeVecPooled(emulbase
->mempool
, ln
);
533 /*********************************************************************************************/
535 static SIPTR
parent_dir(struct emulbase
*emulbase
,
536 struct filehandle
*fhv
,
537 struct filehandle
**fhp
)
541 DCHDIR(bug("[emul] Original directory: \"%s\"\n", (*fhp
)->name
));
542 err
= open_(emulbase
, fhv
, fhp
, "/", MODE_OLDFILE
, 0, TRUE
);
543 DCHDIR(bug("[emul] Parent directory: \"%s\"\n", err
? NULL
: (*fhp
)->name
));
548 /*********************************************************************************************/
550 static LONG
set_date(struct emulbase
*emulbase
, struct filehandle
*fh
,
551 const char *FileName
, struct DateStamp
*date
)
556 ret
= makefilename(emulbase
, &fullname
, NULL
, fh
, FileName
);
559 ret
= DoSetDate(emulbase
, fullname
, date
);
561 FreeVecPooled(emulbase
->mempool
, fullname
);
566 static LONG
disk_info(struct emulbase
*emulbase
, struct filehandle
*fh
, struct InfoData
*id
)
568 LONG Res2
= DoStatFS(emulbase
, fh
->hostname
, id
);
572 /* Fill in host-independent part */
573 id
->id_UnitNumber
= 0;
574 id
->id_DiskType
= ID_DOS_DISK
; /* Well, not really true... */
575 id
->id_VolumeNode
= MKBADDR(fh
->dl
);
576 id
->id_InUse
= TRUE
; /* Perhaps we should count locks? */
582 /*********************************************************************************************/
584 #define VOLNAME "System"
585 #define VOLNAME_LEN 6
587 static struct filehandle
*new_volume(struct emulbase
*emulbase
, const char *path
, struct MsgPort
*mp
, struct DosLibrary
*DOSBase
)
589 struct filehandle
*fhv
;
590 struct DosList
*doslist
;
597 * MakeDosNode() creates zero-length fssm_Device instead of BNULL pointer when ParamPkt[1] is zero.
598 * CHECKME: is this correct, or MakeDosNode() needs to be fixed?
602 DMOUNT(bug("[emul] Mounting volume %s\n", path
));
605 * Volume name and Unix path are encoded into DEVICE entry of
606 * MountList like this: <volumename>:<unixpath>
615 } while (*path
++ != ':');
616 DMOUNT(bug("[emul] Host path: %s, volume name length %u\n", path
, vol_len
));
618 sp
= strchr(path
, '~');
621 unixpath
= GetHomeDir(emulbase
, sp
+ 1);
625 unixpath
= AllocVecPooled(emulbase
->mempool
, strlen(path
)+1);
629 CopyMem(path
, unixpath
, strlen(path
)+1);
636 DMOUNT(bug("[emul] Mounting root volume\n"));
638 unixpath
= AllocVecPooled(emulbase
->mempool
, PATH_MAX
);
642 res
= GetCurrentDir(emulbase
, unixpath
, PATH_MAX
);
643 DMOUNT(bug("[emul] GetCurrentDir() returned %d\n", res
));
650 D(bug("[emul] startup directory %s\n", unixpath
));
653 vol_len
= VOLNAME_LEN
+ 1;
656 DMOUNT(bug("[emul] Resolved host path: %s\n", unixpath
));
658 if (CheckDir(emulbase
, unixpath
))
660 FreeVecPooled(emulbase
->mempool
, unixpath
);
664 fhv
= AllocMem(sizeof(struct filehandle
) + vol_len
, MEMF_PUBLIC
|MEMF_CLEAR
);
665 DMOUNT(bug("[emul] Volume file handle: 0x%p\n", fhv
));
668 char *volname
= (char *)fhv
+ sizeof(struct filehandle
);
670 CopyMem(vol
, volname
, vol_len
- 1);
671 volname
[vol_len
- 1] = 0;
673 fhv
->hostname
= unixpath
;
674 fhv
->name
= unixpath
+ strlen(unixpath
);
675 fhv
->type
= FHD_DIRECTORY
;
676 fhv
->volumename
= volname
;
677 if (!DoOpen(emulbase
, fhv
, MODE_OLDFILE
, 0, TRUE
)) {
678 DMOUNT(bug("[emul] Making volume node %s\n", volname
));
680 doslist
= MakeDosEntry(volname
, DLT_VOLUME
);
681 DMOUNT(bug("[emul] Volume node 0x%p\n", doslist
));
685 doslist
->dol_Task
= mp
;
686 AddDosEntry(doslist
);
688 SendEvent(emulbase
, IECLASS_DISKINSERTED
);
690 DMOUNT(bug("[emul] Mounting done\n"));
693 DMOUNT(bug("[emul] DOS Volume add failed, freeing volume node\n"));
696 DMOUNT(bug("[emul] Failed, freeing volume node\n"));
697 FreeVecPooled(emulbase
->mempool
, unixpath
);
698 FreeMem(fhv
, sizeof(struct filehandle
) + vol_len
);
701 DMOUNT(bug("[emul] Mounting failed\n"));
705 #define FH_FROM(x) ((struct filehandle *)(x))
706 #define FH_FROM_LOCK(x) \
707 ({ BPTR _x = (BPTR)x; \
712 _fh = (APTR)(((struct FileLock *)BADDR(_x))->fl_Key); \
714 (struct filehandle *)_fh;\
717 static void handlePacket(struct emulbase
*emulbase
, struct filehandle
*fhv
, struct MsgPort
*mp
, struct DosPacket
*dp
, struct DosLibrary
*DOSBase
)
719 SIPTR Res1
= DOSFALSE
;
720 SIPTR Res2
= ERROR_UNKNOWN
;
721 struct filehandle
*fh
, *fh2
;
722 struct FileHandle
*f
;
723 struct FileLock
*fl
, *fl2
;
726 DB2(bug("[emul] Got command %u\n", dp
->dp_Type
));
730 case ACTION_FINDINPUT
:
731 case ACTION_FINDOUTPUT
:
732 case ACTION_FINDUPDATE
:
733 f
= BADDR(dp
->dp_Arg1
);
734 fh2
= FH_FROM_LOCK(dp
->dp_Arg2
);
736 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
));
737 Res2
= open_(emulbase
, fhv
, &fh2
, AROS_BSTR_ADDR(dp
->dp_Arg3
), dp
->dp_Type
, 0, FALSE
);
741 f
->fh_Arg1
= (SIPTR
)fh2
;
752 fh
= FH_FROM(dp
->dp_Arg1
);
753 DCMD(bug("[emul] %p ACTION_END\n", fhv
, fh
));
757 free_lock(emulbase
, fh
);
764 fh
= FH_FROM(dp
->dp_Arg1
);
765 DCMD(bug("[emul] %p ACTION_READ\n", fhv
, fh
));
767 if (fh
->type
& FHD_FILE
)
769 Res1
= DoRead(emulbase
, fh
, (APTR
)dp
->dp_Arg2
, dp
->dp_Arg3
, &Res2
);
773 Res2
= ERROR_OBJECT_WRONG_TYPE
;
778 fh
= FH_FROM(dp
->dp_Arg1
);
779 DCMD(bug("[emul] %p ACTION_WRITE\n", fhv
, fh
));
781 if (fh
->type
& FHD_FILE
)
783 Res1
= DoWrite(emulbase
, fh
, (APTR
)dp
->dp_Arg2
, dp
->dp_Arg3
, &Res2
);
786 Res2
= ERROR_OBJECT_WRONG_TYPE
;
791 fh
= FH_FROM(dp
->dp_Arg1
);
792 DCMD(bug("[emul] %p ACTION_SEEK %p, mode %ld, offset %lu\n", fhv
, fh
, dp
->dp_Arg3
, dp
->dp_Arg2
));
794 if (fh
->type
== FHD_FILE
)
795 Res1
= DoSeek(emulbase
, fh
, dp
->dp_Arg2
, dp
->dp_Arg3
, &Res2
);
798 Res2
= ERROR_OBJECT_WRONG_TYPE
;
803 case ACTION_SET_FILE_SIZE
:
804 fh
= FH_FROM(dp
->dp_Arg1
);
805 DCMD(bug("[emul] %p ACTION_SET_FILE_SIZE: %p, mode %ld, offset %llu\n", fhv
, fh
, dp
->dp_Arg2
, dp
->dp_Arg3
));
807 Res1
= DoSetSize(emulbase
, fh
, dp
->dp_Arg2
, dp
->dp_Arg3
, &Res2
);
813 case ACTION_SAME_LOCK
:
814 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
815 fh2
= FH_FROM_LOCK(dp
->dp_Arg2
);
817 DCMD(bug("[emul] %p ACTION_SAME_LOCK: %p, %p\n", fhv
, fh
, fh2
));
818 DSAME(bug("[emul] Paths: %s, %s\n", fh
->hostname
, fh2
->hostname
));
821 /* DOSTRUE means 'Same', DOSFALSE means 'Different' */
822 Res1
= strcasecmp(fh
->hostname
, fh2
->hostname
) ? DOSFALSE
: DOSTRUE
;
824 DSAME(bug("[emul] Replying with 0x%p, %ld\n", Res1
, Res2
));
827 case ACTION_EXAMINE_FH
:
828 fh
= FH_FROM(dp
->dp_Arg1
);
829 DCMD(bug("[emul] %p ACTION_EXAMINE_FH: %p, fib %p\n", fhv
, fh
, BADDR(dp
->dp_Arg2
)));
830 Res2
= examine(emulbase
, fh
, (struct FileInfoBlock
*)BADDR(dp
->dp_Arg2
));
831 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
834 case ACTION_EXAMINE_OBJECT
:
835 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
836 DCMD(bug("[emul] %p ACTION_EXAMINE_OBJECT: %p, fib %p\n", fhv
, fh
, BADDR(dp
->dp_Arg2
)));
837 Res2
= examine(emulbase
, fh
, (struct FileInfoBlock
*)BADDR(dp
->dp_Arg2
));
838 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
841 case ACTION_EXAMINE_NEXT
:
842 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
843 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
));
844 Res2
= DoExamineNext(emulbase
, (struct filehandle
*)fh
, (struct FileInfoBlock
*)BADDR(dp
->dp_Arg2
));
845 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
848 case ACTION_EXAMINE_ALL
:
849 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
850 DCMD(bug("[emul] %p ACTION_EXAMINE_ALL: %p\n", fhv
, fh
));
851 Res2
= DoExamineAll(emulbase
, fh
, (APTR
)dp
->dp_Arg2
, BADDR(dp
->dp_Arg5
),
852 dp
->dp_Arg3
, dp
->dp_Arg4
, DOSBase
);
853 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
856 case ACTION_EXAMINE_ALL_END
:
858 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
859 DCMD(bug("[emul] %p ACTION_EXAMINE_ALL_END: %p\n", fhv
, fh
));
860 Res2
= DoRewindDir(emulbase
, (struct filehandle
*)fh
);
861 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
864 case ACTION_CREATE_DIR
:
865 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
866 DCMD(bug("[emul] %p ACTION_CREATE_DIR: %p, %b\n", fhv
, fh
, dp
->dp_Arg2
));
868 fl
= AllocMem(sizeof(*fl
), MEMF_ANY
| MEMF_CLEAR
);
870 Res2
= ERROR_NO_FREE_STORE
;
875 Res2
= create_dir(emulbase
, &fh
, AROS_BSTR_ADDR(dp
->dp_Arg2
),
876 FIBF_GRP_EXECUTE
| FIBF_GRP_READ
|
877 FIBF_OTR_EXECUTE
| FIBF_OTR_READ
);
878 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
879 if (Res1
!= DOSTRUE
) {
880 FreeMem(fl
, sizeof(*fl
));
886 fl
->fl_Key
= (IPTR
)fh
;
887 fl
->fl_Access
= ACCESS_READ
;
889 fl
->fl_Volume
= MKBADDR(fh
->dl
);
895 case ACTION_LOCATE_OBJECT
:
896 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
897 DCMD(bug("[emul] %p ACTION_LOCATE_OBJECT: %p, %b\n", fhv
, fh
, dp
->dp_Arg2
));
899 fl
= AllocMem(sizeof(*fl
), MEMF_ANY
| MEMF_CLEAR
);
901 Res2
= ERROR_NO_FREE_STORE
;
906 Res2
= open_(emulbase
, fhv
, &fh
, AROS_BSTR_ADDR(dp
->dp_Arg2
), (dp
->dp_Arg3
== ACCESS_READ
) ? MODE_OLDFILE
: MODE_NEWFILE
, 0755, TRUE
);
909 FreeMem(fl
, sizeof(*fl
));
915 fl
->fl_Key
= (IPTR
)fh
;
916 fl
->fl_Access
= dp
->dp_Arg3
;
918 fl
->fl_Volume
= MKBADDR(fh
->dl
);
925 case ACTION_FH_FROM_LOCK
:
926 f
= BADDR(dp
->dp_Arg1
);
927 fh2
= FH_FROM_LOCK(dp
->dp_Arg2
);
928 fl
= BADDR(dp
->dp_Arg2
);
929 DCMD(bug("[emul] %p ACTION_FH_FROM_LOCK: %p, lock %p\n", fhv
, fh
, fh2
));
931 f
->fh_Arg1
= (SIPTR
)fh2
;
934 FreeMem(fl
, sizeof(*fl
));
940 case ACTION_COPY_DIR
: /* DupLock */
941 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
942 fl
= BADDR(dp
->dp_Arg1
);
943 DCMD(bug("[emul] %p ACTION_COPY_DIR: %p\n", fhv
, fh
));
945 fl2
= AllocMem(sizeof(*fl2
), MEMF_ANY
| MEMF_CLEAR
);
947 Res2
= ERROR_NO_FREE_STORE
;
952 CopyMem(fl
, fl2
, sizeof(*fl2
));
957 Res1
= (SIPTR
)MKBADDR(fl2
);
960 case ACTION_COPY_DIR_FH
: /* Dup */
961 fh
= FH_FROM(dp
->dp_Arg1
);
962 DCMD(bug("[emul] %p ACTION_COPY_DIR_FH: %p\n", fhv
, fh
));
964 fl
= AllocMem(sizeof(*fl
), MEMF_ANY
| MEMF_CLEAR
);
966 Res2
= ERROR_NO_FREE_STORE
;
973 fl
->fl_Key
= (IPTR
)fh
;
974 fl
->fl_Access
= ACCESS_READ
;
976 fl
->fl_Volume
= MKBADDR(fh
->dl
);
981 Res1
= (SIPTR
)MKBADDR(fl
);
984 case ACTION_FREE_LOCK
:
985 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
986 fl
= BADDR(dp
->dp_Arg1
);
987 DCMD(bug("[emul] %p ACTION_FREE_LOCK: %p\n", fhv
, fh
));
989 /* Don't free the volume's filehandle */
996 FreeMem(fl
, sizeof(*fl
));
1000 free_lock(emulbase
, fh
);
1007 case ACTION_MAKE_LINK
:
1008 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
1010 Res2
= ERROR_UNKNOWN
;
1011 if (dp
->dp_Arg4
== LINK_SOFT
) {
1012 DCMD(bug("[emul] %p ACTION_MAKE_LINK: %p, dest \"%b\", src \"%b\"\n", fhv
, fh
, dp
->dp_Arg2
, dp
->dp_Arg3
));
1013 Res2
= create_softlink(emulbase
, fh
, AROS_BSTR_ADDR(dp
->dp_Arg2
), AROS_BSTR_ADDR(dp
->dp_Arg3
));
1014 } else if (dp
->dp_Arg4
== LINK_HARD
) {
1015 fh2
= FH_FROM_LOCK(dp
->dp_Arg3
);
1016 DCMD(bug("[emul] %p ACTION_MAKE_LINK: %p, dest \"%b\", src %p\n", fhv
, fh
, dp
->dp_Arg2
, fh2
));
1017 Res2
= create_hardlink(emulbase
, fh
, AROS_BSTR_ADDR(dp
->dp_Arg2
), fh2
);
1020 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
1023 case ACTION_RENAME_OBJECT
:
1024 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
1025 fh2
= FH_FROM_LOCK(dp
->dp_Arg3
);
1026 DCMD(bug("[emul] %p ACTION_RENAME_OBJECT: %p, \"%b\" => %p, \"%b\"\n", fhv
, fh
, dp
->dp_Arg2
, fh2
, dp
->dp_Arg4
));
1027 Res2
= rename_object(emulbase
, fh
, AROS_BSTR_ADDR(dp
->dp_Arg2
), fh2
, AROS_BSTR_ADDR(dp
->dp_Arg4
));
1029 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
1032 case ACTION_READ_LINK
:
1033 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
1034 DCMD(bug("[emul] %p ACTION_READ_LINK: %p\n", fhv
, fh
));
1036 Res2
= read_softlink(emulbase
, fh
, (APTR
)dp
->dp_Arg2
, (APTR
)dp
->dp_Arg3
, &Res1
, DOSBase
);
1039 case ACTION_DELETE_OBJECT
:
1040 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
1041 DCMD(bug("[emul] %p ACTION_DELETE_OBJECT: %p\n", fhv
, fh
));
1042 Res2
= delete_object(emulbase
, fh
, AROS_BSTR_ADDR(dp
->dp_Arg2
));
1043 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
1046 case ACTION_SET_PROTECT
:
1047 /* dp_Arg1 is unused */
1048 fh
= FH_FROM_LOCK(dp
->dp_Arg2
);
1049 DCMD(bug("[emul] %p ACTION_SET_PROTECT: %p\n", fhv
, fh
));
1050 Res2
= set_protect(emulbase
, fh
, AROS_BSTR_ADDR(dp
->dp_Arg3
), dp
->dp_Arg4
);
1051 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
1055 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
1056 DCMD(bug("[emul] %p ACTION_PARENT: %p\n", fhv
, fh
));
1064 fl
= AllocMem(sizeof(*fl
), MEMF_ANY
| MEMF_CLEAR
);
1066 Res2
= ERROR_NO_FREE_STORE
;
1071 Res2
= parent_dir(emulbase
, fhv
, &fh
);
1073 FreeMem(fl
, sizeof(*fl
));
1079 fl
->fl_Link
= BNULL
;
1080 fl
->fl_Key
= (IPTR
)fh
;
1081 fl
->fl_Access
= ACCESS_READ
;
1083 fl
->fl_Volume
= MKBADDR(fh
->dl
);
1087 Res1
= (SIPTR
)MKBADDR(fl
);
1091 case ACTION_PARENT_FH
:
1092 fh
= FH_FROM(dp
->dp_Arg1
);
1093 DCMD(bug("[emul] %p ACTION_PARENT_FH: %p\n", fhv
, fh
));
1101 fl
= AllocMem(sizeof(*fl
), MEMF_ANY
| MEMF_CLEAR
);
1103 Res2
= ERROR_NO_FREE_STORE
;
1108 Res2
= parent_dir(emulbase
, fhv
, &fh
);
1110 FreeMem(fl
, sizeof(*fl
));
1116 fl
->fl_Link
= BNULL
;
1117 fl
->fl_Key
= (IPTR
)fh
;
1118 fl
->fl_Access
= ACCESS_READ
;
1120 fl
->fl_Volume
= MKBADDR(fh
->dl
);
1124 Res1
= (SIPTR
)MKBADDR(fl
);
1127 case ACTION_IS_FILESYSTEM
:
1128 DCMD(bug("[emul] %p ACTION_IS_FILESYSTEM:\n", fhv
));
1134 fh
= FH_FROM_LOCK(dp
->dp_Arg1
);
1135 id
= BADDR(dp
->dp_Arg2
);
1136 DCMD(bug("[emul] %p ACTION_INFO:\n", fhv
));
1138 Res2
= disk_info(emulbase
, fh
, id
);
1139 Res1
= Res2
? DOSFALSE
: DOSTRUE
;
1142 case ACTION_DISK_INFO
:
1143 id
= (struct InfoData
*)BADDR(dp
->dp_Arg1
);
1144 DCMD(bug("[emul] %p ACTION_DISK_INFO:\n", fhv
));
1146 Res2
= disk_info(emulbase
, fhv
, id
);
1147 Res1
= Res2
? DOSFALSE
: DOSTRUE
;
1150 case ACTION_SET_DATE
:
1151 /* dp_Arg1 is unused */
1152 fh
= FH_FROM_LOCK(dp
->dp_Arg2
);
1153 DCMD(bug("[emul] %p ACTION_SET_DATE: %p\n", fhv
, fh
));
1154 Res2
= set_date(emulbase
, fh
, AROS_BSTR_ADDR(dp
->dp_Arg3
), (struct DateStamp
*)dp
->dp_Arg4
);
1155 Res1
= (Res2
== 0) ? DOSTRUE
: DOSFALSE
;
1158 case ACTION_SET_OWNER
:
1159 /* pretend to have changed owner, avoids tons of error messages from e.g. tar */
1163 /* FIXME: not supported yet
1164 case ACTION_SET_COMMENT:
1165 case ACTION_MORE_CACHE:
1166 case ACTION_WAIT_CHAR:
1169 DCMD(bug("[emul] Unknown action %lu\n", dp
->dp_Type
));
1170 Res2
= ERROR_ACTION_NOT_KNOWN
;
1175 /* Set error code */
1176 DCMD(bug("[emul] Replying with 0x%p, %ld\n", Res1
, Res2
));
1178 ReplyPkt(dp
, Res1
, Res2
);
1181 static void EmulHandler_work(struct ExecBase
*SysBase
)
1183 struct DosLibrary
*DOSBase
;
1184 struct DosPacket
*dp
;
1185 struct DeviceNode
*dn
;
1186 struct FileSysStartupMsg
*fssm
;
1187 STRPTR devpath
= NULL
;
1189 struct filehandle
*fhv
;
1190 struct emulbase
*emulbase
;
1192 DOSBase
= (APTR
)OpenLibrary("dos.library", 0);
1196 mp
= &((struct Process
*)FindTask(NULL
))->pr_MsgPort
;
1198 /* Wait for startup message. */
1199 D(bug("EMUL: Waiting for startup...\n"));
1201 dp
= (struct DosPacket
*)(GetMsg(mp
)->mn_Node
.ln_Name
);
1203 D(bug("EMUL: Open resource\n"));
1204 emulbase
= OpenResource("emul-handler");
1207 D(bug("EMUL: FATAL - can't find myself\n"));
1208 ReplyPkt(dp
, DOSFALSE
, ERROR_INVALID_RESIDENT_LIBRARY
);
1212 fssm
= BADDR(dp
->dp_Arg2
);
1214 devpath
= AROS_BSTR_ADDR(fssm
->fssm_Device
);
1216 fhv
= new_volume(emulbase
, devpath
, mp
, DOSBase
);
1219 D(bug("EMUL: FATAL - can't create the inital volume \"%s\"\n", devpath
));
1220 ReplyPkt(dp
, DOSFALSE
, ERROR_NO_FREE_STORE
);
1224 /* Now, once we know all is well with the world,
1225 * we tell DOS that we're the handler for this
1228 dn
= BADDR(dp
->dp_Arg3
);
1231 ReplyPkt(dp
, DOSTRUE
, 0);
1237 handlePacket(emulbase
, fhv
, mp
, dp
, DOSBase
);
1240 D(bug("EMUL: Closing volume %s\n", fhv
->volumename
));
1241 RemDosEntry(fhv
->dl
);
1242 free_lock(emulbase
, fhv
);
1243 CloseLibrary((APTR
)DOSBase
);
1246 AROS_PROCH(EmulHandlerMain
, argptr
, argstr
, SysBase
)
1250 EmulHandler_work(SysBase
);