2 * packet.handler - Proxy filesystem for DOS packet handlers
4 * Copyright © 2007-2008 The AROS Development Team
6 * This program is free software; you can redistribute it and/or modify it
7 * under the same terms as AROS itself.
14 /* places we might find handlers */
15 const char *search_path
[] = {
18 "DEVS:Filesystems/%s",
23 static int GM_UNIQUENAME(init
)(struct PacketBase
*pb
) {
24 D(bug("[packet] in init\n"));
26 NEWLIST(&(pb
->mounts
));
31 static int GM_UNIQUENAME(expunge
)(struct PacketBase
*pb
) {
32 D(bug("[packet] in expunge\n"));
37 AROS_UFH3(void, packet_startup
,
38 AROS_UFHA(STRPTR
, argPtr
, A0
),
39 AROS_UFHA(ULONG
, argSize
, D0
),
40 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)) {
43 struct Process
*me
= (struct Process
*) FindTask(NULL
);
44 BPTR seglist
= (BPTR
) me
->pr_Task
.tc_UserData
;
46 D(bug("[packet] in packet_startup\n"));
48 WaitPort(&(me
->pr_MsgPort
));
49 ReplyMsg(GetMsg(&(me
->pr_MsgPort
)));
51 D(bug("[packet] calling handler\n"));
53 AROS_UFC1(void, (LONG_FUNC
) ((BPTR
*) BADDR(seglist
) + 1),
54 AROS_UFCA(struct ExecBase
*, SysBase
, A6
));
56 D(bug("[packet] handler returned\n"));
61 void packet_reply(struct ph_mount
*, APTR
, struct ExecBase
*);
63 static int GM_UNIQUENAME(open
)(struct PacketBase
*pb
, struct IOFileSys
*iofs
, ULONG unitnum
, ULONG flags
) {
64 struct ph_mount
*scan
, *mount
;
65 struct DeviceNode
*dn
;
66 char filename
[MAXFILENAMELENGTH
];
72 struct MsgPort
*reply_port
;
75 D(bug("[packet] in open\n"));
77 dn
= iofs
->io_Union
.io_OpenDevice
.io_DeviceNode
;
79 D(bug("[packet] devicename '%s' unit %d dosname '%s' handler '%s'\n",
80 iofs
->io_Union
.io_OpenDevice
.io_DeviceName
,
81 iofs
->io_Union
.io_OpenDevice
.io_Unit
,
82 iofs
->io_Union
.io_OpenDevice
.io_DosName
,
87 ForeachNode(&(pb
->mounts
), scan
) {
88 /* XXX what happens if the mount point matches but the handler doesn't? */
89 if (strcmp(scan
->handler_name
, dn
->dn_Handler
) == 0 &&
90 strcmp(scan
->mount_point
, iofs
->io_Union
.io_OpenDevice
.io_DosName
) == 0) {
96 /* if we didn't find it then we have to set it up */
99 /* try to load the named handler from each dir in the search path if
100 * not already loaded */
101 seglist
= dn
->dn_SegList
;
102 for (i
= 0; seglist
== NULL
&& search_path
[i
] != NULL
; i
++) {
103 snprintf(filename
, MAXFILENAMELENGTH
, search_path
[i
], dn
->dn_Handler
);
104 seglist
= LoadSeg(filename
);
105 if (seglist
!= NULL
) {
107 D(bug("[packet] loaded %s\n", filename
));
110 D(bug("[packet] couldn't load %s\n", filename
));
113 if (seglist
== NULL
) {
114 kprintf("[packet] couldn't open %s\n", dn
->dn_Handler
);
115 iofs
->IOFS
.io_Error
= IOERR_OPENFAIL
;
119 /* got it, create our mount struct */
120 mount
= (struct ph_mount
*) AllocVec(sizeof(struct ph_mount
), MEMF_PUBLIC
| MEMF_CLEAR
);
122 strncpy(mount
->handler_name
, dn
->dn_Handler
, MAXFILENAMELENGTH
);
123 strncpy(mount
->mount_point
, iofs
->io_Union
.io_OpenDevice
.io_DosName
, MAXFILENAMELENGTH
);
125 /* only store seg list for later unloading if we loaded it ourselves */
127 mount
->seglist
= seglist
;
129 D(bug("[packet] starting handler process\n"));
132 snprintf(pr_name
, sizeof(pr_name
), "filesys process for %s", mount
->mount_point
);
133 mount
->process
= CreateNewProcTags(NP_Entry
, (IPTR
) packet_startup
,
135 NP_StackSize
, dn
->dn_StackSize
,
136 NP_Priority
, dn
->dn_Priority
,
137 NP_UserData
, (IPTR
) seglist
,
140 reply_port
= CreateMsgPort();
142 msg
= (struct Message
*) AllocVec(sizeof(struct Message
), MEMF_PUBLIC
| MEMF_CLEAR
);
143 msg
->mn_ReplyPort
= reply_port
;
144 msg
->mn_Length
= sizeof(struct Message
);
146 PutMsg(&(mount
->process
->pr_MsgPort
), msg
);
147 WaitPort(reply_port
);
152 /* something went horribly wrong? */
153 if (mount
->process
== NULL
) {
154 kprintf("[packet] couldn't start filesys process for %s\n", mount
->mount_point
);
160 iofs
->IOFS
.io_Error
= IOERR_OPENFAIL
;
164 D(bug("[packet] started, process structure is 0x%08x\n", mount
->process
));
166 /* build the startup packet */
167 /* XXX gurubook p645 suggests dp_Arg1 may be "BPTR TO BSTR (file name)",
168 * but I can't confirm this */
169 dp
= (struct DosPacket
*) AllocDosObject(DOS_STDPKT
, NULL
);
170 dp
->dp_Arg2
= (SIPTR
)MKBADDR(dn
->dn_Startup
);
171 dp
->dp_Arg3
= (SIPTR
)MKBADDR(dn
);
172 dp
->dp_Port
= reply_port
;
174 /* Set up device and unit in device node so handler can add volume
175 * node during start-up */
176 dn
->dn_Ext
.dn_AROS
.dn_Device
= iofs
->IOFS
.io_Device
;
177 dn
->dn_Ext
.dn_AROS
.dn_Unit
= (struct Unit
*) &(mount
->root_handle
);
178 D(bug("[packet] sending startup packet\n"));
180 PutMsg(&(mount
->process
->pr_MsgPort
), dp
->dp_Link
);
181 WaitPort(reply_port
);
184 DeleteMsgPort(reply_port
);
186 if (dp
->dp_Res1
== DOSFALSE
) {
187 D(bug("[packet] handler failed startup [%d]\n", dp
->dp_Res2
));
189 iofs
->IOFS
.io_Error
= dp
->dp_Res2
;
190 dn
->dn_Ext
.dn_AROS
.dn_Device
= NULL
;
191 dn
->dn_Ext
.dn_AROS
.dn_Unit
= NULL
;
195 /* hook the process up to the device node */
196 dn
->dn_Task
= &(mount
->process
->pr_MsgPort
);
198 /* setup a handler function and port for replies */
199 mount
->reply_int
.is_Code
= packet_reply
;
200 mount
->reply_int
.is_Data
= mount
;
202 NEWLIST(&(mount
->reply_port
.mp_MsgList
));
203 mount
->reply_port
.mp_Flags
= PA_SOFTINT
;
204 mount
->reply_port
.mp_SigTask
= &(mount
->reply_int
);
206 /* remember this mount */
208 AddTail((struct List
*) &(pb
->mounts
), (struct Node
*) mount
);
211 /* setup the root "handle" to hand back to the caller */
212 mount
->root_handle
.mount
= mount
;
213 iofs
->IOFS
.io_Unit
= (struct Unit
*) &(mount
->root_handle
);
215 iofs
->IOFS
.io_Error
= 0;
217 D(bug("[packet] handler %s for mount %s now online\n", mount
->handler_name
, mount
->mount_point
));
220 FreeDosObject(DOS_STDPKT
, dp
);
223 return iofs
->IOFS
.io_Error
!= 0 ? FALSE
: TRUE
;
226 static int GM_UNIQUENAME(close
)(struct PacketBase
*pb
, struct IOFileSys
*iofs
) {
227 D(bug("[packet] in close\n"));
232 ADD2INITLIB(GM_UNIQUENAME(init
),0)
233 ADD2EXPUNGELIB(GM_UNIQUENAME(expunge
),0)
234 ADD2OPENDEV(GM_UNIQUENAME(open
),0)
235 ADD2CLOSEDEV(GM_UNIQUENAME(close
),0)
237 void packet_handle_request(struct IOFileSys
*, struct PacketBase
*);
239 AROS_LH1(void, beginio
, AROS_LHA(struct IOFileSys
*, iofs
, A1
), struct PacketBase
*, pb
, 5, Packet
) {
242 D(bug("[packet] in begin_io\n"));
244 packet_handle_request(iofs
, pb
);
249 AROS_LH1(long, abortio
, AROS_LHA(struct IOFileSys
*, iofs
, A1
), struct PacketBase
*, pb
, 6, Packet
) {
252 D(bug("[packet] in abort_io\n"));