2 Copyright 1995-2009, The AROS Development Team. All rights reserved.
5 Desc: Filesystem that accesses an underlying Windows filesystem.
8 Please always update the version-string below, if you modify the code!
11 /*********************************************************************************************/
22 #define __DOS_NOLIBBASE__
23 #define __HOSTLIB_NOLIBBASE__
24 #define __KERNEL_NOLIBBASE__
26 #include <aros/debug.h>
27 #include <aros/kernel.h>
28 #include <aros/system.h>
29 #include <aros/symbolsets.h>
30 #include <exec/resident.h>
31 #include <exec/memory.h>
32 #include <exec/alerts.h>
33 #include <devices/input.h>
34 #include <devices/inputevent.h>
35 #include <proto/exec.h>
36 #include <utility/tagitem.h>
37 #include <utility/hooks.h>
38 #include <dos/filesystem.h>
39 #include <dos/exall.h>
40 #include <dos/dosasl.h>
42 #include <proto/dos.h>
43 #include <proto/arossupport.h>
44 #include <proto/expansion.h>
45 #include <proto/hostlib.h>
46 #include <proto/kernel.h>
47 #include <libraries/expansion.h>
48 #include <libraries/configvars.h>
49 #include <libraries/expansionbase.h>
51 #include <aros/host-conf.h>
55 #include "emul_handler_intern.h"
59 #include LC_LIBDEFS_FILE
61 /*********************************************************************************************/
63 /* Init DOSBase ourselves because emul_handler is initialized before dos.library */
64 static struct DosLibrary
*DOSBase
;
65 static APTR HostLibBase
, KernelBase
;
66 static struct EmulInterface
*EmulIFace
;
67 static struct KernelInterface
*KernelIFace
;
69 /*********************************** Support *******************************/
71 static void SendEvent(struct emulbase
*emulbase
, LONG event
) {
72 struct IOStdReq
*InputRequest
;
73 struct MsgPort
*InputPort
;
74 struct InputEvent
*ie
;
75 D(bug("[emul] SendEvent\n"));
76 if ((InputPort
= (struct MsgPort
*)CreateMsgPort())) {
78 if ((InputRequest
= (struct IOStdReq
*)CreateIORequest(InputPort
, sizeof(struct IOStdReq
)))) {
80 if (!OpenDevice("input.device", 0, (struct IORequest
*)InputRequest
, 0)) {
82 if ((ie
= AllocVec(sizeof(struct InputEvent
), MEMF_PUBLIC
|MEMF_CLEAR
))) {
84 InputRequest
->io_Command
= IND_WRITEEVENT
;
85 InputRequest
->io_Data
= ie
;
86 InputRequest
->io_Length
= sizeof(struct InputEvent
);
88 DoIO((struct IORequest
*)InputRequest
);
92 CloseDevice((struct IORequest
*)InputRequest
);
94 DeleteIORequest ((APTR
)InputRequest
);
96 DeleteMsgPort (InputPort
);
100 /*********************************************************************************************/
102 static APTR
emul_malloc(struct emulbase
*emulbase
, ULONG size
)
106 // kprintf("** emul_malloc: size = %d **\n",size);
107 ObtainSemaphore(&emulbase
->memsem
);
109 size
+= sizeof(ULONG
);
110 res
= AllocPooled(emulbase
->mempool
, size
);
111 if (res
) *res
++ = size
;
113 ReleaseSemaphore(&emulbase
->memsem
);
115 // kprintf("** emul_malloc: size = %d result = %x **\n",size-sizeof(ULONG),res);
120 /*********************************************************************************************/
122 static void emul_free(struct emulbase
*emulbase
, APTR mem
)
126 ULONG
*m
= (ULONG
*)mem
;
129 // kprintf("** emul_free: size = %d memory = %x **\n",size-sizeof(ULONG),mem);
131 ObtainSemaphore(&emulbase
->memsem
);
132 FreePooled(emulbase
->mempool
, m
, size
);
133 ReleaseSemaphore(&emulbase
->memsem
);
135 D(else kprintf("*** emul_handler: tried to free NULL mem ***\n");)
138 /*********************************************************************************************/
140 /* Create a plain path out of the supplied filename.
141 Eg 'path1\path2\\path3\' becomes 'path1\path3'.
143 BOOL
shrink(struct emulbase
*emulbase
, char *filename
)
148 /* We skip the first slash because it separates volume root prefix and the actual pathname */
155 /* leading slashes? --> return FALSE. */
156 if(*s
== '\\') return FALSE
;
158 /* remove superflous paths (ie paths that are followed by '\') */
159 s1
= strstr(s
, "\\\\");
165 if (s2
[-1] == '\\') break;
169 memmove(s2
,s1
+2,strlen(s1
+1));
172 /* strip trailing slash */
173 len
= strlen(filename
);
174 if (len
&& (filename
[len
-1] == '\\'))
180 /*********************************************************************************************/
182 /* Allocate a buffer, in which the filename is appended to the pathname. */
183 static LONG
makefilename(struct emulbase
*emulbase
, char **dest
, char **part
, struct filehandle
* fh
, STRPTR filename
)
186 int len
, flen
, dirlen
;
189 DFNAME(bug("[emul] makefilename(): directory \"%s\", file \"%s\")\n", fh
->hostname
, filename
));
197 if ((*s
== '/') || (!*s
)) {
198 DFNAME(bug("[emul] Bad file name, contains dots-only component\n"));
199 return ERROR_INVALID_COMPONENT_NAME
;
204 DFNAME(bug("[emul] Bad file name, contains backslash\n"));
205 return ERROR_INVALID_COMPONENT_NAME
;
208 } while ((*s
!= '/') && *s
);
213 dirlen
= strlen(fh
->hostname
);
214 flen
= strlen(filename
);
215 len
= flen
+ dirlen
+ 2;
216 *dest
=(char *)emul_malloc(emulbase
, len
);
218 CopyMem(fh
->hostname
, *dest
, dirlen
);
222 /* We are on Windows, so we have to revert slashes while copying filename */
223 for (s
= filename
; *s
; s
++)
224 *c
++ = (*s
== '/') ? '\\' : *s
;
228 c
= *dest
+ (fh
->name
- fh
->hostname
);
229 DFNAME(bug("[emul] Shrinking filename: \"%s\"\n", c
));
230 if (!shrink(emulbase
, c
))
232 emul_free(emulbase
, *dest
);
234 ret
= ERROR_OBJECT_NOT_FOUND
;
236 DFNAME(bug("[emul] resulting host filename: \"%s\"\n", *dest
));
239 DFNAME(bug("[emul] resulting AROS filename: \"%s\"\n", c
));
243 ret
= ERROR_NO_FREE_STORE
;
247 /*********************************************************************************************/
249 /* Make Windows protection bits out of AROS protection bits. */
250 ULONG
prot_a2w(ULONG protect
)
254 /* The following flags are low-active! */
255 if ((protect
& (FIBF_WRITE
|FIBF_DELETE
)) == (FIBF_WRITE
|FIBF_DELETE
))
256 uprot
= FILE_ATTRIBUTE_READONLY
;
257 /* The following flags are high-active again. */
258 if (protect
& FIBF_ARCHIVE
)
259 uprot
|= FILE_ATTRIBUTE_ARCHIVE
;
260 if (protect
& FIBF_SCRIPT
)
261 uprot
|= FILE_ATTRIBUTE_SYSTEM
;
263 /* TODO: 1) Support more NT-specific attributes ('Executable')
264 2) Write complete AROS protection bits support using NTFS streams */
269 /*********************************************************************************************/
271 /* Make AROS protection bits out of Windows protection bits. */
272 ULONG
prot_w2a(ULONG protect
)
276 /* The following three flags are low-active! */
277 if (protect
& FILE_ATTRIBUTE_READONLY
)
278 uprot
= FIBF_WRITE
|FIBF_DELETE
;
279 if (protect
& FILE_ATTRIBUTE_DIRECTORY
)
280 uprot
|= FIBF_EXECUTE
;
281 /* The following flags are high-active again. */
282 if (protect
& FILE_ATTRIBUTE_ARCHIVE
)
283 uprot
|= FIBF_ARCHIVE
;
284 if (protect
& FILE_ATTRIBUTE_SYSTEM
)
285 uprot
|= FIBF_SCRIPT
;
287 /* TODO: 1) Support more NT-specific attributes ('Executable')
288 2) Write complete AROS protection bits support using NTFS streams */
293 /*********************************************************************************************/
295 static void FileTime2DateStamp(struct DateStamp
*ds
, UQUAD ft
)
299 /* Adjust from 01.01.1601 to 01.01.1978. This offset was calculated using a specially written program
300 which puts "01.01.1978 00:00:00" into SYSTEMTIME structure and converts it into FILETIME. */
301 ft
-= 118969344000000000LL;
302 /* Adjust interval from 100 ns to 1/50 sec */
304 totalmins
= ft
/ (60*50);
305 ds
->ds_Days
= totalmins
/ (24*60);
306 ds
->ds_Minute
= totalmins
% (24*60);
307 ds
->ds_Tick
= ft
% (60*50);
310 /*********************************************************************************************/
312 /* Make an AROS error-code (<dos/dos.h>) out of a Windows error-code. */
313 static ULONG u2a
[][2]=
315 { ERROR_PATH_NOT_FOUND
, ERROR_OBJECT_NOT_FOUND
},
316 { ERROR_ACCESS_DENIED
, ERROR_OBJECT_WRONG_TYPE
},
317 { ERROR_NO_MORE_FILES
, ERROR_NO_MORE_ENTRIES
},
318 { ERROR_NOT_ENOUGH_MEMORY
, ERROR_NO_FREE_STORE
},
319 { ERROR_FILE_NOT_FOUND
, ERROR_OBJECT_NOT_FOUND
},
320 { ERROR_FILE_EXISTS
, ERROR_OBJECT_EXISTS
},
321 { ERROR_WRITE_PROTECT
, ERROR_WRITE_PROTECTED
},
322 { WIN32_ERROR_DISK_FULL
, ERROR_DISK_FULL
},
323 { ERROR_DIR_NOT_EMPTY
, ERROR_DIRECTORY_NOT_EMPTY
},
324 { ERROR_SHARING_VIOLATION
, ERROR_OBJECT_IN_USE
},
325 { ERROR_LOCK_VIOLATION
, ERROR_OBJECT_IN_USE
},
326 { WIN32_ERROR_BUFFER_OVERFLOW
, ERROR_OBJECT_TOO_LARGE
},
327 { ERROR_INVALID_NAME
, ERROR_OBJECT_NOT_FOUND
},
331 ULONG
Errno_w2a(ULONG e
)
335 DERROR(printf("[EmulHandler] Windows error code: %lu\n", e
));
336 for(i
=0;i
<sizeof(u2a
)/sizeof(u2a
[0]);i
++)
338 DERROR(printf("[EmulHandler] Translated to AROS error code: %lu\n", u2a
[i
][1]));
341 DERROR(printf("[EmulHandler] Unknown error code\n"));
342 return ERROR_UNKNOWN
;
345 #define Errno() Errno_w2a(GetLastError())
347 /*********************************************************************************************/
349 void *DoOpen(char *path
, int mode
, int protect
)
356 D(bug("[emul] DoOpen(): mode 0x%08lX\n", mode
));
357 if (mode
& FMF_WRITE
)
358 flags
= GENERIC_WRITE
;
360 flags
|= GENERIC_READ
;
361 /* FILE_SHARE_WRITE looks strange here, however without it i can't reopen file which
362 is already open with MODE_OLDFILE, even just for reading with FMF_READ */
363 lock
= (mode
& FMF_LOCK
) ? 0 : FILE_SHARE_READ
|FILE_SHARE_WRITE
;
364 if (mode
& FMF_CREATE
)
365 create
= (flags
& FMF_CLEAR
) ? CREATE_ALWAYS
: OPEN_ALWAYS
;
367 create
= (flags
& FMF_CLEAR
) ? TRUNCATE_EXISTING
: OPEN_EXISTING
;
368 D(bug("[emul] CreateFile: name \"%s\", flags 0x%08lX, lock 0x%08lX, create %lu\n", path
, flags
, lock
, create
));
370 res
= OpenFile(path
, flags
, lock
, NULL
, create
, prot_a2w(protect
), NULL
);
372 DB2(bug("[emul] FileHandle = 0x%08lX\n", res
));
376 /*********************************************************************************************/
378 /* Free a filehandle */
379 static LONG
free_lock(struct emulbase
*emulbase
, struct filehandle
*current
)
381 D(bug("[emul] Lock type = %lu\n", current
->type
));
382 switch(current
->type
)
385 if((current
->fd
!= emulbase
->stdin_handle
) && (current
->fd
!= emulbase
->stdout_handle
) &&
386 (current
->fd
!= emulbase
->stderr_handle
))
388 DB2(bug("[emul] CloseHandle(), fd = 0x%08lX\n", current
->fd
));
390 DoClose(current
->fd
);
395 if (current
->fd
!= INVALID_HANDLE_VALUE
)
397 D(bug("[emul] Closing directory search handle\n"));
399 FindEnd(current
->fd
);
404 if (current
->pathname
) {
405 D(bug("[emul] Freeing pathname: \"%s\"\n", current
->pathname
));
406 emul_free(emulbase
, current
->pathname
);
408 D(bug("[emul] Freeing name: \"%s\"\n", current
->hostname
));
409 emul_free(emulbase
, current
->hostname
);
410 D(bug("[emul] Freeing filehandle\n"));
411 FreeMem(current
, sizeof(struct filehandle
));
412 D(bug("[emul] Done\n"));
416 /*********************************************************************************************/
418 static LONG
open_(struct emulbase
*emulbase
, struct filehandle
**handle
, STRPTR name
, LONG mode
, LONG protect
, BOOL AllowDir
)
421 struct filehandle
*fh
;
423 DOPEN(bug("[emul] open_(\"%s\"), directories allowed: %lu\n", name
, AllowDir
));
425 fh
=(struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
);
427 fh
->pathname
= NULL
; /* just to make sure... */
428 fh
->dl
= (*handle
)->dl
;
429 /* If no filename is given and the file-descriptor is one of the
430 standard filehandles (stdin, stdout, stderr) ... */
431 if((!name
[0]) && ((*handle
)->type
== FHD_FILE
) &&
432 (((*handle
)->fd
== emulbase
->stdin_handle
) || ((*handle
)->fd
== emulbase
->stdout_handle
) || ((*handle
)->fd
== emulbase
->stderr_handle
)))
434 /* ... then just reopen that standard filehandle. */
436 fh
->fd
= (*handle
)->fd
;
439 fh
->volumename
= NULL
;
444 fh
->volumename
=(*handle
)->volumename
;
446 ret
= makefilename(emulbase
, &fh
->hostname
, &fh
->name
, *handle
, name
);
451 DOPEN(bug("[emul] Host object name: %s\n", fh
->hostname
));
452 kind
= Stat(fh
->hostname
, NULL
);
453 DOPEN(bug("[emul] object type: %ld\n", kind
));
457 ret
= ERROR_IS_SOFT_LINK
;
459 case 0: /* Non-existing objects can be files opened for writing */
462 fh
->fd
= DoOpen(fh
->hostname
, mode
, protect
);
463 if(fh
->fd
!= INVALID_HANDLE_VALUE
)
471 /* file is a directory */
473 fh
->type
= FHD_DIRECTORY
;
474 fh
->fd
= INVALID_HANDLE_VALUE
;
479 ret
= ERROR_OBJECT_WRONG_TYPE
;
482 ret
= ERROR_OBJECT_WRONG_TYPE
;
484 D(bug("[emul] Freeing pathname\n"));
485 emul_free(emulbase
, fh
->hostname
);
487 D(bug("[emul] Freeing filehandle\n"));
488 FreeMem(fh
, sizeof(struct filehandle
));
490 ret
= ERROR_NO_FREE_STORE
;
491 DOPEN(bug("[emul] open_() returns %lu\n", ret
));
495 /*********************************************************************************************/
497 static LONG
seek_file(struct filehandle
*fh
, struct IFS_SEEK
*io_SEEK
, UQUAD
*newpos
)
503 if (fh
->type
== FHD_FILE
) {
504 DB2(bug("[emul] LSeek() - getting current position\n"));
506 oldpos
= LSeek(fh
->fd
, 0, &pos_high
, FILE_CURRENT
);
508 oldpos
|= (UQUAD
)pos_high
<< 32;
509 D(bug("[emul] Original position: %llu\n", oldpos
));
511 switch(io_SEEK
->io_SeekMode
) {
512 case OFFSET_BEGINNING
:
521 pos_high
= io_SEEK
->io_Offset
>> 32;
522 DB2(bug("[emul] LSeek() - setting new position\n"));
524 error
= LSeek(fh
->fd
, io_SEEK
->io_Offset
, &pos_high
, mode
);
526 if (error
== (ULONG
)-1)
531 *newpos
|= (UQUAD
)pos_high
<< 32;
536 io_SEEK
->io_Offset
= oldpos
;
538 error
= ERROR_OBJECT_WRONG_TYPE
;
542 /*********************************************************************************************/
544 static LONG
create_dir(struct emulbase
*emulbase
, struct filehandle
**handle
,
545 STRPTR filename
, IPTR protect
)
548 struct filehandle
*fh
;
550 fh
= (struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
);
553 fh
->pathname
= NULL
; /* just to make sure... */
554 fh
->type
= FHD_DIRECTORY
;
555 fh
->fd
= INVALID_HANDLE_VALUE
;
557 fh
->volumename
= (*handle
)->volumename
;
558 fh
->dl
= (*handle
)->dl
;
560 ret
= makefilename(emulbase
, &fh
->hostname
, &fh
->name
, *handle
, filename
);
564 ret
= MKDir(fh
->hostname
, NULL
);
569 Chmod(fh
->hostname
, prot_a2w(protect
));
575 free_lock(emulbase
, fh
);
577 ret
= ERROR_NO_FREE_STORE
;
582 /*********************************************************************************************/
584 static LONG
delete_object(struct emulbase
*emulbase
, struct filehandle
* fh
,
588 char *filename
= NULL
;
590 ret
= makefilename(emulbase
, &filename
, NULL
, fh
, file
);
593 if (!Delete(filename
))
595 emul_free(emulbase
, filename
);
601 /*********************************************************************************************/
603 static LONG
set_protect(struct emulbase
*emulbase
, struct filehandle
* fh
,
604 STRPTR file
, ULONG aprot
)
607 char *filename
= NULL
;
609 if ((ret
= makefilename(emulbase
, &filename
, NULL
, fh
, file
)))
613 ret
= Chmod(filename
, prot_a2w(aprot
));
615 ret
= ret
? 0 : Errno();
617 emul_free(emulbase
, filename
);
622 /*********************************************************************************************/
624 static void EmulIntHandler(struct AsyncReaderControl
*msg
, void *d
)
626 DASYNC(bug("[emul] Interrupt on request 0x%p, task 0x%p, signal 0x%08lX\n", msg
, msg
->task
, msg
->sig
));
627 Signal(msg
->task
, msg
->sig
);
630 /*********************************************************************************************/
631 static LONG
startup(struct emulbase
*emulbase
)
633 struct Library
*ExpansionBase
;
634 struct filehandle
*fhi
= NULL
;
635 struct filehandle
*fho
= NULL
;
636 struct filehandle
*fhe
= NULL
;
637 struct filehandle
*fhv
;
638 struct DeviceNode
*dlv
, *dlv2
;
639 LONG ret
= ERROR_NO_FREE_STORE
;
642 D(kprintf("[Emulhandler] startup\n"));
643 ExpansionBase
= OpenLibrary("expansion.library",0);
644 if(ExpansionBase
!= NULL
)
646 D(kprintf("[Emulhandler] startup: got ExpansionBase\n"));
647 fhv
=(struct filehandle
*)AllocMem(sizeof(struct filehandle
) + 256 + AROS_WORSTALIGN
, MEMF_PUBLIC
);
650 D(kprintf("[Emulhandler] startup allocated fhv\n"));
651 fhv
->hostname
= (char *)(fhv
+ 1);
652 fhv
->type
= FHD_DIRECTORY
;
653 fhv
->fd
= INVALID_HANDLE_VALUE
;
655 fhv
->pathname
= NULL
; /* just to make sure... */
658 res
= GetCWD(256, fhv
->hostname
);
664 D(bug("[Emulhandler] startup got directory %s\n", fhv
->hostname
));
665 fhv
->name
= fhv
->hostname
+ res
;
666 #define DEVNAME "EMU"
667 #define VOLNAME "System"
669 static const char *devname
= DEVNAME
;
670 static const char *volname
= VOLNAME
;
672 fhv
->volumename
= VOLNAME
;
675 emulbase
->stdin_handle
= GetStdFile(STD_INPUT_HANDLE
);
676 emulbase
->stdout_handle
= GetStdFile(STD_OUTPUT_HANDLE
);
677 emulbase
->stderr_handle
= GetStdFile(STD_ERROR_HANDLE
);
679 if (!emulbase
->stdin_handle
)
680 emulbase
->stdin_handle
= INVALID_HANDLE_VALUE
;
681 if (!emulbase
->stdout_handle
)
682 emulbase
->stdout_handle
= INVALID_HANDLE_VALUE
;
683 if (!emulbase
->stderr_handle
)
684 emulbase
->stderr_handle
= INVALID_HANDLE_VALUE
;
686 if (emulbase
->stdin_handle
!= INVALID_HANDLE_VALUE
) {
687 fhi
=(struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
|MEMF_CLEAR
);
690 D(kprintf("[Emulhandler] allocated fhi\n"));
691 fhi
->type
= FHD_FILE
;
692 fhi
->fd
= emulbase
->stdin_handle
;
693 emulbase
->eb_stdin
= fhi
;
696 if (emulbase
->stdout_handle
!= INVALID_HANDLE_VALUE
) {
697 fho
=(struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
|MEMF_CLEAR
);
700 D(kprintf("[Emulhandler] startup allocated fho\n"));
701 fho
->type
= FHD_FILE
;
702 fho
->fd
= emulbase
->stdout_handle
;
703 emulbase
->eb_stdout
= fho
;
706 if (emulbase
->stderr_handle
!= INVALID_HANDLE_VALUE
) {
707 fhe
=(struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
|MEMF_CLEAR
);
710 D(kprintf("[Emulhandler] startup allocated fhe\n"));
711 fhe
->type
= FHD_FILE
;
712 fhe
->fd
= emulbase
->stderr_handle
;
713 emulbase
->eb_stderr
= fhe
;
717 ret
= ERROR_NO_FREE_STORE
;
719 D(bug("[Emulhandler] Creating console reader\n"));
721 emulbase
->ConsoleReader
= InitNative();
723 if (emulbase
->ConsoleReader
) {
724 D(bug("[Emulhandler] Created console reader %p\n", emulbase
->ConsoleReader
));
725 emulbase
->ConsoleInt
= KrnAddIRQHandler(1, EmulIntHandler
, emulbase
->ConsoleReader
, NULL
);
726 D(bug("[Emulhandler] Added console interrupt %p\n", emulbase
->ConsoleReader
));
727 if (emulbase
->ConsoleInt
) {
730 Allocate space for the string from same mem,
731 Use AROS_BSTR_MEMSIZE4LEN macro for space to
732 to allocate and add an extra 4 for alignment
736 dlv
= AllocMem(sizeof(struct DeviceNode
) + 4 + AROS_BSTR_MEMSIZE4LEN(strlen(DEVNAME
)), MEMF_CLEAR
|MEMF_PUBLIC
);
738 dlv2
= AllocMem(sizeof(struct DeviceNode
) + 4 + AROS_BSTR_MEMSIZE4LEN(strlen(VOLNAME
)), MEMF_CLEAR
|MEMF_PUBLIC
);
745 D(kprintf("[Emulhandler] startup allocated dlv/dlv2\n"));
746 /* We want s to point to the first 4-byte
747 aligned memory after the structure.
749 s
= (BSTR
)MKBADDR(((IPTR
)dlv
+ sizeof(struct DeviceNode
) + 3) & ~3);
750 s2
= (BSTR
)MKBADDR(((IPTR
)dlv2
+ sizeof(struct DeviceNode
) + 3) & ~3);
752 for(i
= 0; i
< sizeof(DEVNAME
) - 1; i
++)
754 AROS_BSTR_putchar(s
, i
, devname
[i
]);
756 AROS_BSTR_setstrlen(s
, sizeof(DEVNAME
) - 1);
758 dlv
->dn_Type
= DLT_DEVICE
;
759 dlv
->dn_Ext
.dn_AROS
.dn_Unit
= (struct Unit
*)fhv
;
760 dlv
->dn_Ext
.dn_AROS
.dn_Device
= &emulbase
->device
;
761 dlv
->dn_Handler
= NULL
;
762 dlv
->dn_Startup
= NULL
;
764 dlv
->dn_Ext
.dn_AROS
.dn_DevName
= AROS_BSTR_ADDR(dlv
->dn_Name
);
766 AddBootNode(5, 0, dlv
, NULL
);
769 /* Unfortunately, we cannot do the stuff below
770 as dos is not yet initialized... */
771 // AddDosEntry(MakeDosEntry("System", DLT_VOLUME));
773 for(i
= 0; i
< sizeof(VOLNAME
) - 1; i
++)
775 AROS_BSTR_putchar(s2
, i
, volname
[i
]);
777 AROS_BSTR_setstrlen(s2
, sizeof(VOLNAME
) - 1);
779 dlv2
->dn_Type
= DLT_VOLUME
;
780 dlv2
->dn_Ext
.dn_AROS
.dn_Unit
= (struct Unit
*)fhv
;
781 dlv2
->dn_Ext
.dn_AROS
.dn_Device
= &emulbase
->device
;
782 dlv2
->dn_Handler
= NULL
;
783 dlv2
->dn_Startup
= NULL
;
785 dlv2
->dn_Ext
.dn_AROS
.dn_DevName
= AROS_BSTR_ADDR(dlv2
->dn_Name
);
787 /* Make sure this is not booted from */
788 AddBootNode(-128, 0, dlv2
, NULL
);
791 /* Increment our open counter because we use ourselves */
792 emulbase
->device
.dd_Library
.lib_OpenCnt
++;
795 FreeMem(dlv
, sizeof(struct DeviceNode
) + 4 + AROS_BSTR_MEMSIZE4LEN(strlen(DEVNAME
)));
800 FreeMem(fhe
, sizeof(struct filehandle
));
802 FreeMem(fho
, sizeof(struct filehandle
));
804 FreeMem(fhi
, sizeof(struct filehandle
));
805 } /* valid directory */
808 Alert(AT_DeadEnd
|AO_Unknown
|AN_Unknown
);
810 free_lock(emulbase
, fhv
);
812 CloseLibrary(ExpansionBase
);
818 /*********************************************************************************************/
820 static const ULONG sizes
[]=
821 { 0, offsetof(struct ExAllData
,ed_Type
), offsetof(struct ExAllData
,ed_Size
),
822 offsetof(struct ExAllData
,ed_Prot
), offsetof(struct ExAllData
,ed_Days
),
823 offsetof(struct ExAllData
,ed_Comment
), offsetof(struct ExAllData
,ed_OwnerUID
),
824 sizeof(struct ExAllData
) };
826 /*********************************************************************************************/
828 /* Returns a emul_malloc()'ed buffer, containing a pathname, stripped by the
831 char *pathname_from_name (struct emulbase
*emulbase
, char *name
)
833 long len
= strlen(name
);
838 /* look for the first '\' in the filename starting at the end */
839 while (i
!= 0 && name
[i
] != '\\')
844 result
= (char *)emul_malloc(emulbase
, i
+ 1);
848 for (c
= 0; c
< i
; c
++)
849 result
[c
] = (name
[c
] == '\\') ? '/' : name
[c
];
855 /*********************************************************************************************/
857 ULONG
examine_start(struct emulbase
*emulbase
, struct filehandle
*fh
)
862 if (fh
->type
!= FHD_DIRECTORY
)
863 return ERROR_OBJECT_WRONG_TYPE
;
866 len
= strlen(fh
->hostname
);
867 fh
->pathname
= emul_malloc(emulbase
, len
+ 3);
869 return ERROR_NO_FREE_STORE
;
870 CopyMem(fh
->hostname
, fh
->pathname
, len
);
871 c
= fh
->pathname
+ len
;
874 D(bug("[emul] Created search path: %s\n", fh
->pathname
));
878 /*********************************************************************************************/
880 /* Resets dirpos in directory handle and close existing search handle */
881 static LONG
CloseDir(struct filehandle
*fh
)
885 if (fh
->fd
!= INVALID_HANDLE_VALUE
) {
891 fh
->fd
= INVALID_HANDLE_VALUE
;
897 /*********************************************************************************************/
899 #define is_special_dir(x) (x[0] == '.' && (!x[1] || (x[1] == '.' && !x[2])))
901 /* Positions to dirpos in directory, retrieves next item in it and updates dirpos */
902 ULONG
ReadDir(struct filehandle
*fh
, LPWIN32_FIND_DATA FindData
, ULONG
*dirpos
)
907 * Windows does not support positioning within directory. The only thing i can do is to
908 * scan the directory in forward direction. In order to bypass this limitation we do the
910 * 1. Before starting we explicitly set current position (dirpos) to 0. Examine() will place
911 * it into our fib_DiskKey; in case of ExAll() this is eac_LastKey. We also maintain second
912 * directory position counter - in our directory handle. It reflects the real position of
913 * our file search handle.
914 * 2. Here we compare position in dirpos with position in the handle. If dirpos is smaller than
915 * filehandle's counter, we have to rewind the directory. This is done by closing the search
916 * handle in order to be able to restart from the beginning and setting handle's counter to 0.
918 D(bug("[emul] Current dirpos %lu, requested %lu\n", fh
->dirpos
, *dirpos
));
919 if (fh
->dirpos
> *dirpos
) {
920 D(bug("[emul] Resetting search handle\n"));
926 * 3. Now we will scan the next directory entry until its index is greater than original index
927 * in dirpos. This means that we've repositioned and scanned the next entry. After this we
931 if (fh
->fd
== INVALID_HANDLE_VALUE
) {
932 D(bug("[emul] Finding first file\n"));
934 fh
->fd
= FindFirst(fh
->pathname
, FindData
);
936 res
= (fh
->fd
!= INVALID_HANDLE_VALUE
);
939 res
= FindNext(fh
->fd
, FindData
);
945 D(bug("[emul] Found %s, position %lu\n", FindData
->cFileName
, fh
->dirpos
));
946 } while (fh
->dirpos
<= *dirpos
);
948 D(bug("[emul] New dirpos: %lu\n", *dirpos
));
950 * We also skip "." and ".." entries (however we count their indexes - just in case), because
951 * AmigaOS donesn't have them.
953 } while (is_special_dir(FindData
->cFileName
));
958 /*********************************************************************************************/
960 ULONG
examine_entry_sub(struct emulbase
*emulbase
, struct filehandle
*fh
, STRPTR FoundName
, WIN32_FILE_ATTRIBUTE_DATA
*FIB
, LONG
*kind
)
962 STRPTR filename
, name
;
966 D(bug("[emul] examine_entry_sub(): filehandle's path: %s\n", fh
->hostname
));
968 D(bug("[emul] ...containing object: %s\n", FoundName
));
969 plen
= strlen(fh
->hostname
);
970 flen
= strlen(FoundName
);
971 name
= emul_malloc(emulbase
, plen
+ flen
+ 2);
973 return ERROR_NO_FREE_STORE
;
974 strcpy(name
, fh
->hostname
);
975 filename
= name
+ plen
;
977 strcpy(filename
, FoundName
);
981 D(bug("[emul] Full name: %s\n", name
));
982 *kind
= Stat(name
, FIB
);
986 D(bug("[emul] Freeing full name\n"));
987 emul_free(emulbase
, name
);
992 /*********************************************************************************************/
994 ULONG
examine_entry(struct emulbase
*emulbase
, struct filehandle
*fh
, STRPTR FoundName
,
995 struct ExAllData
*ead
, ULONG size
, ULONG type
)
997 STRPTR next
, last
, end
, name
;
998 WIN32_FILE_ATTRIBUTE_DATA FIB
;
1002 /* Check, if the supplied buffer is large enough. */
1003 next
=(STRPTR
)ead
+sizes
[type
];
1004 end
=(STRPTR
)ead
+size
;
1007 D(bug("[emul] examine_entry(): end of buffer\n"));
1008 return ERROR_BUFFER_OVERFLOW
;
1011 error
= examine_entry_sub(emulbase
, fh
, FoundName
, &FIB
, &kind
);
1015 D(bug("[emul] Filling in object information\n"));
1020 ead
->ed_OwnerUID
= 0;
1021 ead
->ed_OwnerGID
= 0;
1023 ead
->ed_Comment
= NULL
;
1024 /* TODO: Write Windows shell-compatible comments support using NTFS streams */
1026 FileTime2DateStamp((struct DateStamp
*)&ead
->ed_Days
, FIB
.ftLastWriteTime
);
1028 ead
->ed_Prot
= prot_w2a(FIB
.dwFileAttributes
);
1030 ead
->ed_Size
= FIB
.nFileSizeLow
;
1032 if ((kind
== ST_USERDIR
) && (!fh
->name
[0]))
1034 ead
->ed_Type
= kind
;
1038 else if (*fh
->name
) {
1045 last
= fh
->volumename
;
1050 return ERROR_BUFFER_OVERFLOW
;
1051 if(!(*next
++=*last
++))
1055 ead
->ed_Next
=(struct ExAllData
*)(((IPTR
)next
+AROS_PTRALIGN
-1)&~(AROS_PTRALIGN
-1));
1061 /*********************************************************************************************/
1063 static LONG
examine(struct emulbase
*emulbase
, struct filehandle
*fh
,
1064 struct ExAllData
*ead
,
1071 /* Return an error, if supplied type is not supported. */
1073 return ERROR_BAD_NUMBER
;
1075 /* Reset fh->dirpos to 0. If there is already a directory scan handle, it will be closed in order to start from the beginning */
1076 if (fh
->type
== FHD_DIRECTORY
) {
1077 D(bug("[emul] examine(): Resetting search handle\n"));
1078 error
= CloseDir(fh
);
1084 return examine_entry(emulbase
, fh
, NULL
, ead
, size
, type
);
1087 /*********************************************************************************************/
1089 static LONG
examine_next(struct emulbase
*emulbase
, struct filehandle
*fh
, struct FileInfoBlock
*FIB
)
1093 WIN32_FIND_DATA FindData
;
1094 WIN32_FILE_ATTRIBUTE_DATA AttrData
;
1096 res
= examine_start(emulbase
, fh
);
1100 res
= ReadDir(fh
, &FindData
, &FIB
->fib_DiskKey
);
1102 res
= examine_entry_sub(emulbase
, fh
, FindData
.cFileName
, &AttrData
, &FIB
->fib_DirEntryType
);
1108 FIB
->fib_OwnerUID
= 0;
1109 FIB
->fib_OwnerGID
= 0;
1110 FIB
->fib_Comment
[0] = '\0'; /* TODO: no comments available yet! */
1111 FIB
->fib_Protection
= prot_w2a(AttrData
.dwFileAttributes
);
1112 FIB
->fib_Size
= AttrData
.nFileSizeLow
;
1113 FileTime2DateStamp(&FIB
->fib_Date
, AttrData
.ftLastWriteTime
);
1115 src
= FindData
.cFileName
;
1116 dest
= FIB
->fib_FileName
;
1117 for (res
= 0; res
<MAXFILENAMELENGTH
-1; res
++)
1119 if(! (*dest
++=*src
++) )
1128 /*********************************************************************************************/
1130 static LONG
examine_all(struct emulbase
*emulbase
, struct filehandle
*fh
,
1131 struct ExAllData
*ead
,
1132 struct ExAllControl
*eac
,
1136 struct ExAllData
*last
= NULL
;
1137 STRPTR end
= (STRPTR
)ead
+ size
;
1139 WIN32_FIND_DATA FindData
;
1141 eac
->eac_Entries
= 0;
1142 error
= examine_start(emulbase
, fh
);
1148 error
= ReadDir(fh
, &FindData
, &eac
->eac_LastKey
);
1150 D(bug("[emul] ReadDir() returned %lu\n", error
));
1153 /* Try to match the filename, if required. */
1154 D(bug("[emul] Checking against MatchString\n"));
1155 if (eac
->eac_MatchString
&& !MatchPatternNoCase(eac
->eac_MatchString
, FindData
.cFileName
))
1157 D(bug("[emul] Examining object\n"));
1158 error
= examine_entry(emulbase
, fh
, FindData
.cFileName
, ead
, end
-(STRPTR
)ead
, type
);
1161 /* Do some more matching... */
1162 if ((eac
->eac_MatchFunc
) && !CALLHOOKPKT(eac
->eac_MatchFunc
, ead
, &type
))
1170 if((error
==ERROR_BUFFER_OVERFLOW
)&&last
!=NULL
)
1178 /*********************************************************************************************/
1180 static LONG
create_hardlink(struct emulbase
*emulbase
, struct filehandle
*handle
, STRPTR name
, struct filehandle
*oldfile
)
1185 if (!KernelIFace
->CreateHardLink
)
1186 return ERROR_ACTION_NOT_KNOWN
;
1188 error
= makefilename(emulbase
, &fn
, NULL
, handle
, name
);
1191 D(bug("[emul] Creating hardlink %s to file %s\n", fn
, oldfile
->hostname
));
1193 error
= Link(fn
, oldfile
->hostname
, NULL
);
1195 error
= error
? 0 : Errno();
1196 emul_free(emulbase
, fn
);
1202 /*********************************************************************************************/
1204 static LONG
create_softlink(struct emulbase
* emulbase
,
1205 struct filehandle
*handle
, STRPTR name
, STRPTR ref
)
1210 /* TODO: implement symbolic links on earlier Windows versions using shell shortcuts */
1211 if (!KernelIFace
->CreateSymbolicLink
)
1212 return ERROR_ACTION_NOT_KNOWN
;
1214 /* TODO: currently relative paths are converted to absolute one, this needs to be improved */
1215 error
= makefilename(emulbase
, &src
, NULL
, handle
, name
);
1218 error
= makefilename(emulbase
, &dest
, NULL
, handle
, ref
);
1221 error
= SymLink(src
, dest
, 0);
1223 error
= error
? 0 : Errno();
1224 emul_free(emulbase
, dest
);
1226 emul_free(emulbase
, src
);
1232 /*********************************************************************************************/
1234 static LONG
rename_object(struct emulbase
* emulbase
,
1235 struct filehandle
*fh
, STRPTR file
, STRPTR newname
)
1239 char *filename
= NULL
, *newfilename
= NULL
;
1241 ret
= makefilename(emulbase
, &filename
, NULL
, fh
, file
);
1244 ret
= makefilename(emulbase
, &newfilename
, NULL
, fh
, newname
);
1248 ret
= DoRename(filename
,newfilename
);
1250 ret
= ret
? 0 : Errno();
1251 emul_free(emulbase
, newfilename
);
1253 emul_free(emulbase
, filename
);
1260 static LONG
read_softlink(struct emulbase
*emulbase
,
1261 struct filehandle
*fh
,
1265 /* TODO: implement symbolic links on pre-Vista using shell shortcuts
1267 if (DoReadLink(fh->name, buffer, size-1) == -1)
1271 return ERROR_ACTION_NOT_KNOWN
;
1274 /*********************************************************************************************/
1276 ULONG
parent_dir(struct emulbase
*emulbase
,
1277 struct filehandle
*fh
,
1278 char ** DirectoryName
)
1280 *DirectoryName
= pathname_from_name(emulbase
, fh
->name
);
1281 D(bug("[emul] Parent directory: \"%s\"\n", *DirectoryName
));
1285 /*********************************************************************************************/
1287 void parent_dir_post(struct emulbase
*emulbase
, char ** DirectoryName
)
1289 /* free the previously allocated memory */
1290 emul_free(emulbase
, *DirectoryName
);
1291 **DirectoryName
= 0;
1294 /*********************************************************************************************/
1296 /************************ Library entry points ************************/
1298 int loadhooks(struct emulbase
*emulbase
);
1300 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR emulbase
)
1302 D(bug("Initializing emul_handler\n"));
1304 if (loadhooks(emulbase
) != 0)
1307 InitSemaphore(&emulbase
->memsem
);
1309 emulbase
->mempool
= CreatePool(MEMF_ANY
, 4096, 2000);
1310 if (!emulbase
->mempool
) return FALSE
;
1312 if(!startup(emulbase
))
1314 D(bug("emul_handler initialized OK\n"));
1318 DeletePool(emulbase
->mempool
);
1320 D(bug("emul_handler startup failed\n"));
1325 /*********************************************************************************************/
1327 static BOOL
new_volume(struct IOFileSys
*iofs
, struct emulbase
*emulbase
)
1329 struct filehandle
*fhv
;
1330 struct DosList
*doslist
;
1333 /* Volume name and Unix path are encoded into DEVICE entry of
1334 MountList like this: <volumename>:<unixpath> */
1336 unixpath
= iofs
->io_Union
.io_OpenDevice
.io_DeviceName
;
1337 unixpath
= strchr(unixpath
, ':');
1345 if ((sp
= strchr(unixpath
, '~')))
1348 char *newunixpath
= 0;
1355 /* "~<name>" means home of user <name> */
1357 for(sp_end
= sp
+ 1;
1358 sp_end
[0] != '\0' && sp_end
[0] != '\\';
1361 cmplen
= sp_end
- sp
- 1;
1362 /* temporariliy zero terminate name */
1363 tmp
= sp
[cmplen
+1]; sp
[cmplen
+1] = '\0';
1365 err
= GetHome(sp
+1, home
);
1370 err
= Errno_w2a(err
);
1372 newunixpath
= AllocVec(strlen(unixpath
) + strlen(home
) + 1, MEMF_CLEAR
);
1375 strncpy(newunixpath
, unixpath
, sp
- unixpath
);
1376 strcat(newunixpath
, home
);
1377 strcat(newunixpath
, sp_end
);
1380 unixpath
= newunixpath
;
1387 if (newunixpath
) FreeVec(newunixpath
);
1393 if (Stat(unixpath
, NULL
)>0)
1395 fhv
=(struct filehandle
*)AllocMem(sizeof(struct filehandle
), MEMF_PUBLIC
);
1398 fhv
->hostname
= unixpath
;
1399 fhv
->name
= unixpath
+ strlen(unixpath
);
1400 fhv
->type
= FHD_DIRECTORY
;
1401 fhv
->pathname
= NULL
; /* just to make sure... */
1402 fhv
->volumename
= iofs
->io_Union
.io_OpenDevice
.io_DeviceName
;
1404 if ((doslist
= MakeDosEntry(fhv
->volumename
, DLT_VOLUME
)))
1407 doslist
->dol_Ext
.dol_AROS
.dol_Unit
=(struct Unit
*)fhv
;
1408 doslist
->dol_Ext
.dol_AROS
.dol_Device
=&emulbase
->device
;
1409 AddDosEntry(doslist
);
1411 iofs
->IOFS
.io_Unit
= (struct Unit
*)fhv
;
1412 iofs
->IOFS
.io_Device
= &emulbase
->device
;
1414 SendEvent(emulbase
, IECLASS_DISKINSERTED
);
1418 } /* if ((doslist = MakeDosEntry(fhv->volumename, DLT_VOLUME))) */
1420 FreeMem(fhv
, sizeof(struct filehandle
));
1422 } /* if (fhv != NULL)*/
1424 } /* if (!Stat(unixpath, &st)) */
1426 } /* if (unixpath) */
1428 } /* if (unixpath) */
1432 /*********************************************************************************************/
1434 static int GM_UNIQUENAME(Open
)
1436 LIBBASETYPEPTR emulbase
,
1437 struct IOFileSys
*iofs
,
1442 /* Keep compiler happy */
1446 if (DOSBase
== NULL
)
1447 DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 41);
1449 if (DOSBase
== NULL
|| !new_volume(iofs
, emulbase
))
1451 iofs
->IOFS
.io_Error
= -1;
1455 /* Set returncode */
1456 iofs
->IOFS
.io_Error
=0;
1460 /*********************************************************************************************/
1462 ADD2INITLIB(GM_UNIQUENAME(Init
), 0)
1463 ADD2OPENDEV(GM_UNIQUENAME(Open
), 0)
1465 /*********************************************************************************************/
1467 AROS_LH1(void, beginio
,
1468 AROS_LHA(struct IOFileSys
*, iofs
, A1
),
1469 struct emulbase
*, emulbase
, 5, emul_handler
)
1475 /* WaitIO will look into this */
1476 iofs
->IOFS
.io_Message
.mn_Node
.ln_Type
=NT_MESSAGE
;
1479 Do everything quick no matter what. This is possible
1480 because I never need to Wait().
1482 switch(iofs
->IOFS
.io_Command
)
1485 D(bug("[emul] FSA_OPEN(\"%s\")\n", iofs
->io_Union
.io_OPEN
.io_Filename
));
1486 error
= open_(emulbase
, (struct filehandle
**)&iofs
->IOFS
.io_Unit
,
1487 iofs
->io_Union
.io_OPEN
.io_Filename
, iofs
->io_Union
.io_OPEN
.io_FileMode
, 0, TRUE
);
1489 (error
== ERROR_WRITE_PROTECTED
) &&
1490 (iofs
->io_Union
.io_OPEN
.io_FileMode
& FMF_AMIGADOS
)
1493 D(bug("[emul] Retrying in read mode\n"));
1494 error
= open_(emulbase
, (struct filehandle
**)&iofs
->IOFS
.io_Unit
,
1495 iofs
->io_Union
.io_OPEN
.io_Filename
, iofs
->io_Union
.io_OPEN
.io_FileMode
& (~FMF_WRITE
), 0, TRUE
);
1497 D(bug("[emul] FSA_OPEN returning %lu\n", error
));
1502 D(bug("[emul] FSA_CLOSE\n"));
1503 error
= free_lock(emulbase
, (struct filehandle
*)iofs
->IOFS
.io_Unit
);
1504 D(bug("[emul] FSA_CLOSE returning %lu\n", error
));
1509 struct filehandle
*fh
= (struct filehandle
*)iofs
->IOFS
.io_Unit
;
1511 if (fh
->type
== FHD_FILE
)
1513 if (fh
->fd
== emulbase
->stdout_handle
)
1514 fh
->fd
= emulbase
->stdin_handle
;
1515 if (fh
->fd
== emulbase
->stdin_handle
) {
1516 DASYNC(bug("[emul] Reading %lu bytes asynchronously \n", iofs
->io_Union
.io_READ
.io_Length
));
1517 emulbase
->ConsoleReader
->fh
= fh
->fd
;
1518 emulbase
->ConsoleReader
->addr
= iofs
->io_Union
.io_READ
.io_Buffer
;
1519 emulbase
->ConsoleReader
->len
= iofs
->io_Union
.io_READ
.io_Length
;
1520 emulbase
->ConsoleReader
->sig
= SIGF_DOS
;
1521 emulbase
->ConsoleReader
->task
= FindTask(NULL
);
1522 emulbase
->ConsoleReader
->cmd
= ASYNC_CMD_READ
;
1523 SetSignal(0, emulbase
->ConsoleReader
->sig
);
1524 if (RaiseEvent(emulbase
->ConsoleReader
->CmdEvent
)) {
1525 Wait(emulbase
->ConsoleReader
->sig
);
1526 DASYNC(bug("[emul] Read %ld bytes, error %lu\n", emulbase
->EmulMsg
.actual
, emulbase
->EmulMsg
.error
));
1527 iofs
->io_Union
.io_READ
.io_Length
= emulbase
->ConsoleReader
->actual
;
1528 error
= Errno_w2a(emulbase
->ConsoleReader
->error
);
1532 c
= iofs
->io_Union
.io_READ
.io_Buffer
;
1535 if ((c
[0] == '\r') && (c
[1] == '\n')) {
1537 iofs
->io_Union
.io_READ
.io_Length
--;
1543 DASYNC(bug("[emul] FSA_READ: RaiseEvent() failed!\n"));
1544 error
= ERROR_UNKNOWN
;
1548 error
= DoRead(fh
->fd
, iofs
->io_Union
.io_READ
.io_Buffer
, iofs
->io_Union
.io_READ
.io_Length
, &iofs
->io_Union
.io_READ
.io_Length
, NULL
);
1550 error
= error
? 0 : Errno();
1555 error
= ERROR_OBJECT_WRONG_TYPE
;
1563 struct filehandle
*fh
= (struct filehandle
*)iofs
->IOFS
.io_Unit
;
1565 if (fh
->type
== FHD_FILE
)
1567 if (fh
->fd
== emulbase
->stdin_handle
)
1568 fh
->fd
=emulbase
->stdout_handle
;
1570 error
= DoWrite(fh
->fd
, iofs
->io_Union
.io_WRITE
.io_Buffer
, iofs
->io_Union
.io_WRITE
.io_Length
, &iofs
->io_Union
.io_WRITE
.io_Length
, NULL
);
1572 error
= error
? 0 : Errno();
1576 error
= ERROR_OBJECT_WRONG_TYPE
;
1584 struct filehandle
*fh
= (struct filehandle
*)iofs
->IOFS
.io_Unit
;
1586 DSEEK(bug("[emul] FSA_SEEK, mode %ld, offset %llu\n", iofs
->io_Union
.io_SEEK
.io_SeekMode
, iofs
->io_Union
.io_SEEK
.io_Offset
));
1587 error
= seek_file(fh
, &iofs
->io_Union
.io_SEEK
, NULL
);
1588 DSEEK(bug("[emul] FSA_SEEK returning %lu\n", error
));
1591 case FSA_SET_FILE_SIZE
:
1593 struct filehandle
*fh
= (struct filehandle
*)iofs
->IOFS
.io_Unit
;
1597 DFSIZE(bug("[emul] FSA_SET_FILE_SIZE, mode %ld, offset %llu\n", iofs
->io_Union
.io_SET_FILE_SIZE
.io_SeekMode
, iofs
->io_Union
.io_SET_FILE_SIZE
.io_Offset
));
1598 /* First seek to the requested position. io_Offset will contain OLD position after that. NEW position will be in newpos */
1599 error
= seek_file(fh
, &iofs
->io_Union
.io_SEEK
, &newpos
);
1601 /* Set EOF to NEW position */
1603 error
= SetEOF(fh
->fd
);
1605 error
= error
? 0 : Errno();
1606 /* If our OLD position was less than new file size, we seek back to it. io_Offset will again contain
1607 position before this seek - i. e. our NEW file size. */
1608 if (iofs
->io_Union
.io_SEEK
.io_Offset
< newpos
) {
1609 iofs
->io_Union
.io_SEEK
.io_SeekMode
= OFFSET_BEGINNING
;
1610 error2
= seek_file(fh
, &iofs
->io_Union
.io_SEEK
, NULL
);
1614 iofs
->io_Union
.io_SEEK
.io_Offset
= newpos
;
1616 D(bug("[emul] FSA_SET_FILE_SIZE returning %lu\n", error
));
1619 case FSA_IS_INTERACTIVE
:
1621 struct filehandle
*fh
= (struct filehandle
*)iofs
->IOFS
.io_Unit
;
1623 if (fh
->type
== FHD_FILE
)
1625 DB2(bug("[emul] GetFileType()\n"));
1627 iofs
->io_Union
.io_IS_INTERACTIVE
.io_IsInteractive
= (GetFileType(fh
->fd
) == FILE_TYPE_CHAR
) ? TRUE
: FALSE
;
1632 iofs
->io_Union
.io_IS_INTERACTIVE
.io_IsInteractive
= FALSE
;
1640 struct filehandle
*lock1
= iofs
->io_Union
.io_SAME_LOCK
.io_Lock
[0],
1641 *lock2
= iofs
->io_Union
.io_SAME_LOCK
.io_Lock
[1];
1643 if (strcmp(lock1
->hostname
, lock2
->hostname
))
1645 iofs
->io_Union
.io_SAME_LOCK
.io_Same
= LOCK_DIFFERENT
;
1649 iofs
->io_Union
.io_SAME_LOCK
.io_Same
= LOCK_SAME
;
1656 D(bug("[emul] FSA_EXAMINE\n"));
1657 error
= examine(emulbase
,
1658 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1659 iofs
->io_Union
.io_EXAMINE
.io_ead
,
1660 iofs
->io_Union
.io_EXAMINE
.io_Size
,
1661 iofs
->io_Union
.io_EXAMINE
.io_Mode
,
1662 &(iofs
->io_DirPos
));
1665 case FSA_EXAMINE_NEXT
:
1666 D(bug("[emul] FSA_EXAMINE_NEXT\n"));
1667 error
= examine_next(emulbase
,
1668 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1669 iofs
->io_Union
.io_EXAMINE_NEXT
.io_fib
);
1672 case FSA_EXAMINE_ALL
:
1673 D(bug("[emul] FSA_EXAMINE_ALL\n"));
1674 error
= examine_all(emulbase
,
1675 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1676 iofs
->io_Union
.io_EXAMINE_ALL
.io_ead
,
1677 iofs
->io_Union
.io_EXAMINE_ALL
.io_eac
,
1678 iofs
->io_Union
.io_EXAMINE_ALL
.io_Size
,
1679 iofs
->io_Union
.io_EXAMINE_ALL
.io_Mode
);
1682 case FSA_EXAMINE_ALL_END
:
1683 CloseDir((struct filehandle
*)iofs
->IOFS
.io_Unit
);
1688 D(bug("[emul] FSA_OPEN_FILE: name \"%s\", mode 0x%08lX)\n", iofs
->io_Union
.io_OPEN_FILE
.io_Filename
, iofs
->io_Union
.io_OPEN_FILE
.io_FileMode
));
1689 error
= open_(emulbase
, (struct filehandle
**)&iofs
->IOFS
.io_Unit
,
1690 iofs
->io_Union
.io_OPEN_FILE
.io_Filename
, iofs
->io_Union
.io_OPEN_FILE
.io_FileMode
,
1691 iofs
->io_Union
.io_OPEN_FILE
.io_Protection
, FALSE
);
1693 (error
== ERROR_WRITE_PROTECTED
) &&
1694 (iofs
->io_Union
.io_OPEN_FILE
.io_FileMode
& FMF_AMIGADOS
)
1697 D(bug("[emul] Retrying in read-only mode\n"));
1698 error
= open_(emulbase
,(struct filehandle
**)&iofs
->IOFS
.io_Unit
,
1699 iofs
->io_Union
.io_OPEN_FILE
.io_Filename
, iofs
->io_Union
.io_OPEN_FILE
.io_FileMode
& (~FMF_WRITE
),
1700 iofs
->io_Union
.io_OPEN_FILE
.io_Protection
, FALSE
);
1702 D(bug("[emul] FSA_OPEN_FILE returning %lu\n", error
));
1705 case FSA_CREATE_DIR
:
1706 error
= create_dir(emulbase
,
1707 (struct filehandle
**)&iofs
->IOFS
.io_Unit
,
1708 iofs
->io_Union
.io_CREATE_DIR
.io_Filename
,
1709 iofs
->io_Union
.io_CREATE_DIR
.io_Protection
);
1712 case FSA_CREATE_HARDLINK
:
1713 D(bug("[emul] FSA_CREATE_HARDLINK: link name \"%s\"\n", iofs
->io_Union
.io_CREATE_HARDLINK
.io_Filename
));
1714 error
= create_hardlink(emulbase
,
1715 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1716 iofs
->io_Union
.io_CREATE_HARDLINK
.io_Filename
,
1717 (struct filehandle
*)iofs
->io_Union
.io_CREATE_HARDLINK
.io_OldFile
);
1718 D(bug("[emul] FSA_CREATE_HARDLINK returning %lu\n", error
));
1721 case FSA_CREATE_SOFTLINK
:
1722 error
= create_softlink(emulbase
,
1723 (struct filehandle
*)&iofs
->IOFS
.io_Unit
,
1724 iofs
->io_Union
.io_CREATE_SOFTLINK
.io_Filename
,
1725 iofs
->io_Union
.io_CREATE_SOFTLINK
.io_Reference
);
1729 error
= rename_object(emulbase
,
1730 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1731 iofs
->io_Union
.io_RENAME
.io_Filename
,
1732 iofs
->io_Union
.io_RENAME
.io_NewName
);
1735 case FSA_READ_SOFTLINK
:
1736 error
= read_softlink(emulbase
,
1737 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1738 iofs
->io_Union
.io_READ_SOFTLINK
.io_Buffer
,
1739 iofs
->io_Union
.io_READ_SOFTLINK
.io_Size
);
1742 case FSA_DELETE_OBJECT
:
1743 error
= delete_object(emulbase
,
1744 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1745 iofs
->io_Union
.io_DELETE_OBJECT
.io_Filename
);
1748 case FSA_SET_PROTECT
:
1749 error
= set_protect(emulbase
,
1750 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1751 iofs
->io_Union
.io_SET_PROTECT
.io_Filename
,
1752 iofs
->io_Union
.io_SET_PROTECT
.io_Protection
);
1755 case FSA_PARENT_DIR
:
1756 /* error will always be 0 */
1757 error
= parent_dir(emulbase
,
1758 (struct filehandle
*)iofs
->IOFS
.io_Unit
,
1759 &(iofs
->io_Union
.io_PARENT_DIR
.io_DirName
));
1762 case FSA_PARENT_DIR_POST
:
1763 /* error will always be 0 */
1765 parent_dir_post(emulbase
, &(iofs
->io_Union
.io_PARENT_DIR
.io_DirName
));
1768 case FSA_IS_FILESYSTEM
:
1769 iofs
->io_Union
.io_IS_FILESYSTEM
.io_IsFilesystem
= TRUE
;
1775 struct filehandle
*fh
= (struct filehandle
*)iofs
->IOFS
.io_Unit
;
1776 struct InfoData
*id
= iofs
->io_Union
.io_INFO
.io_Info
;
1778 error
= StatFS(fh
->hostname
, id
);
1780 error
= Errno_w2a(error
);
1782 id
->id_VolumeNode
= fh
->dl
;
1785 /* FIXME: not supported yet
1786 case FSA_SET_COMMENT:
1789 case FSA_MORE_CACHE:
1790 case FSA_MOUNT_MODE:
1792 case FSA_FILE_MODE:*/
1794 DCMD(bug("[emul] Unknown action %lu\n", iofs
->IOFS
.io_Command
));
1795 error
= ERROR_ACTION_NOT_KNOWN
;
1799 /* Set error code */
1800 iofs
->io_DosError
= error
;
1802 /* If the quick bit is not set send the message to the port */
1803 if(!(iofs
->IOFS
.io_Flags
& IOF_QUICK
))
1805 ReplyMsg(&iofs
->IOFS
.io_Message
);
1811 /*********************************************************************************************/
1813 AROS_LH1(LONG
, abortio
,
1814 AROS_LHA(struct IOFileSys
*, iofs
, A1
),
1815 struct emulbase
*, emulbase
, 6, emul_handler
)
1819 /* Everything already done. */
1825 /*********************************************************************************************/
1827 const char *EmulSymbols
[] = {
1836 const char *KernelSymbols
[] = {
1846 "GetCurrentDirectoryA",
1851 "SetFileAttributesA",
1854 "CreateSymbolicLinkA",
1859 int loadhooks(struct emulbase
*emulbase
)
1863 HostLibBase
= OpenResource("hostlib.resource");
1866 D(kprintf("[EmulHandler] got hostlib.resource HostLibBase=%p\n", HostLibBase
));
1868 emulbase
->EmulHandle
= HostLib_Open("Libs\\Host\\emul_handler.dll", NULL
);
1869 if (emulbase
->EmulHandle
) {
1870 EmulIFace
= (struct EmulInterface
*)HostLib_GetInterface(emulbase
->EmulHandle
, EmulSymbols
, &r
);
1871 D(bug("[EmulHandler] Native library interface: 0x%08lX\n", EmulIFace
));
1874 emulbase
->KernelHandle
= HostLib_Open("kernel32.dll", NULL
);
1875 if (emulbase
->KernelHandle
) {
1876 KernelIFace
= (struct KernelInterface
*)HostLib_GetInterface(emulbase
->KernelHandle
, KernelSymbols
, &r
);
1878 D(bug("[EmulHandler] %lu unresolved symbols in kernel32.dll\n", r
));
1880 D(bug("[EmulHandler] CreateHardLink() : 0x%08lX\n", KernelIFace
->CreateHardLink
));
1881 D(bug("[EmulHandler] CreateSymbolicLink() : 0x%08lX\n", KernelIFace
->CreateSymbolicLink
));
1882 KernelBase
= OpenResource("kernel.resource");
1886 HostLib_DropInterface((APTR
*)KernelIFace
);
1888 D(else bug("[EmulHandler] Unable to get kernel32.dll interface!\n");)
1889 HostLib_Close(emulbase
->KernelHandle
, NULL
);
1892 D(else bug("[EmulHandler] %lu unresolved symbols!\n", r
);)
1893 HostLib_DropInterface((APTR
*)EmulIFace
);
1895 D(else bug("[EmulHandler] Unable go get host-side library interface!\n"));
1896 HostLib_Close(emulbase
->EmulHandle
, NULL
);
1898 D(else bug("[EmulHandler] Unable to open emul.handler host-side library!\n"));