r27161@plastic: rob | 2007-09-03 21:02:17 +1000
[cake.git] / rom / devs / filesys / packet / command.c
blob3aa95875ff826f2929b6a7d6256f96f0f0101a1b
1 /*
2 * packet.handler - Proxy filesystem for DOS packet handlers
4 * Copyright © 2007 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.
9 * $Id$
12 #include "packet.h"
14 #if defined(DEBUG) && DEBUG != 0
15 #define fsa_str(cmd) ( \
16 cmd == FSA_OPEN ? "FSA_OPEN" : \
17 cmd == FSA_CLOSE ? "FSA_CLOSE" : \
18 cmd == FSA_READ ? "FSA_READ" : \
19 cmd == FSA_WRITE ? "FSA_WRITE" : \
20 cmd == FSA_SEEK ? "FSA_SEEK" : \
21 cmd == FSA_SET_FILE_SIZE ? "FSA_SET_FILE_SIZE" : \
22 cmd == FSA_WAIT_CHAR ? "FSA_WAIT_CHAR" : \
23 cmd == FSA_FILE_MODE ? "FSA_FILE_MODE" : \
24 cmd == FSA_IS_INTERACTIVE ? "FSA_IS_INTERACTIVE" : \
25 cmd == FSA_SAME_LOCK ? "FSA_SAME_LOCK" : \
26 cmd == FSA_EXAMINE ? "FSA_EXAMINE" : \
27 cmd == FSA_EXAMINE_NEXT ? "FSA_EXAMINE_NEXT" : \
28 cmd == FSA_EXAMINE_ALL ? "FSA_EXAMINE_ALL" : \
29 cmd == FSA_EXAMINE_ALL_END ? "FSA_EXAMINE_ALL_END" : \
30 cmd == FSA_OPEN_FILE ? "FSA_OPEN_FILE" : \
31 cmd == FSA_CREATE_DIR ? "FSA_CREATE_DIR" : \
32 cmd == FSA_CREATE_HARDLINK ? "FSA_CREATE_HARDLINK" : \
33 cmd == FSA_CREATE_SOFTLINK ? "FSA_CREATE_SOFTLINK" : \
34 cmd == FSA_RENAME ? "FSA_RENAME" : \
35 cmd == FSA_READ_SOFTLINK ? "FSA_READ_SOFTLINK" : \
36 cmd == FSA_DELETE_OBJECT ? "FSA_DELETE_OBJECT" : \
37 cmd == FSA_SET_COMMENT ? "FSA_SET_COMMENT" : \
38 cmd == FSA_SET_PROTECT ? "FSA_SET_PROTECT" : \
39 cmd == FSA_SET_OWNER ? "FSA_SET_OWNER" : \
40 cmd == FSA_SET_DATE ? "FSA_SET_DATE" : \
41 cmd == FSA_IS_FILESYSTEM ? "FSA_IS_FILESYSTEM" : \
42 cmd == FSA_MORE_CACHE ? "FSA_MORE_CACHE" : \
43 cmd == FSA_FORMAT ? "FSA_FORMAT" : \
44 cmd == FSA_MOUNT_MODE ? "FSA_MOUNT_MODE" : \
45 cmd == FSA_INHIBIT ? "FSA_INHIBIT" : \
46 cmd == FSA_ADD_NOTIFY ? "FSA_ADD_NOTIFY" : \
47 cmd == FSA_REMOVE_NOTIFY ? "FSA_REMOVE_NOTIFY" : \
48 cmd == FSA_DISK_INFO ? "FSA_DISK_INFO" : \
49 cmd == FSA_CHANGE_SIGNAL ? "FSA_CHANGE_SIGNAL" : \
50 cmd == FSA_LOCK_RECORD ? "FSA_LOCK_RECORD" : \
51 cmd == FSA_UNLOCK_RECORD ? "FSA_UNLOCK_RECORD" : \
52 cmd == FSA_PARENT_DIR ? "FSA_PARENT_DIR" : \
53 cmd == FSA_PARENT_DIR_POST ? "FSA_PARENT_DIR_POST" : \
54 cmd == FSA_CONSOLE_MODE ? "FSA_CONSOLE_MODE" : \
55 cmd == FSA_RELABEL ? "FSA_RELABEL" : \
56 "unknown")
58 #define act_str(cmd) ( \
59 cmd == ACTION_NIL ? "ACTION_NIL" : \
60 cmd == ACTION_STARTUP ? "ACTION_STARTUP" : \
61 cmd == ACTION_GET_BLOCK ? "ACTION_GET_BLOCK" : \
62 cmd == ACTION_SET_MAP ? "ACTION_SET_MAP" : \
63 cmd == ACTION_DIE ? "ACTION_DIE" : \
64 cmd == ACTION_EVENT ? "ACTION_EVENT" : \
65 cmd == ACTION_CURRENT_VOLUME ? "ACTION_CURRENT_VOLUME" : \
66 cmd == ACTION_LOCATE_OBJECT ? "ACTION_LOCATE_OBJECT" : \
67 cmd == ACTION_RENAME_DISK ? "ACTION_RENAME_DISK" : \
68 cmd == ACTION_FREE_LOCK ? "ACTION_FREE_LOCK" : \
69 cmd == ACTION_DELETE_OBJECT ? "ACTION_DELETE_OBJECT" : \
70 cmd == ACTION_RENAME_OBJECT ? "ACTION_RENAME_OBJECT" : \
71 cmd == ACTION_MORE_CACHE ? "ACTION_MORE_CACHE" : \
72 cmd == ACTION_COPY_DIR ? "ACTION_COPY_DIR" : \
73 cmd == ACTION_WAIT_CHAR ? "ACTION_WAIT_CHAR" : \
74 cmd == ACTION_SET_PROTECT ? "ACTION_SET_PROTECT" : \
75 cmd == ACTION_CREATE_DIR ? "ACTION_CREATE_DIR" : \
76 cmd == ACTION_EXAMINE_OBJECT ? "ACTION_EXAMINE_OBJECT" : \
77 cmd == ACTION_EXAMINE_NEXT ? "ACTION_EXAMINE_NEXT" : \
78 cmd == ACTION_DISK_INFO ? "ACTION_DISK_INFO" : \
79 cmd == ACTION_INFO ? "ACTION_INFO" : \
80 cmd == ACTION_FLUSH ? "ACTION_FLUSH" : \
81 cmd == ACTION_SET_COMMENT ? "ACTION_SET_COMMENT" : \
82 cmd == ACTION_PARENT ? "ACTION_PARENT" : \
83 cmd == ACTION_TIMER ? "ACTION_TIMER" : \
84 cmd == ACTION_INHIBIT ? "ACTION_INHIBIT" : \
85 cmd == ACTION_DISK_TYPE ? "ACTION_DISK_TYPE" : \
86 cmd == ACTION_DISK_CHANGE ? "ACTION_DISK_CHANGE" : \
87 cmd == ACTION_SET_DATE ? "ACTION_SET_DATE" : \
88 cmd == ACTION_SAME_LOCK ? "ACTION_SAME_LOCK" : \
89 cmd == ACTION_WRITE ? "ACTION_WRITE" : \
90 cmd == ACTION_READ ? "ACTION_READ" : \
91 cmd == ACTION_SCREEN_MODE ? "ACTION_SCREEN_MODE" : \
92 cmd == ACTION_CHANGE_SIGNAL ? "ACTION_CHANGE_SIGNAL" : \
93 cmd == ACTION_READ_RETURN ? "ACTION_READ_RETURN" : \
94 cmd == ACTION_WRITE_RETURN ? "ACTION_WRITE_RETURN" : \
95 cmd == ACTION_FINDUPDATE ? "ACTION_FINDUPDATE" : \
96 cmd == ACTION_FINDINPUT ? "ACTION_FINDINPUT" : \
97 cmd == ACTION_FINDOUTPUT ? "ACTION_FINDOUTPUT" : \
98 cmd == ACTION_END ? "ACTION_END" : \
99 cmd == ACTION_SEEK ? "ACTION_SEEK" : \
100 cmd == ACTION_FORMAT ? "ACTION_FORMAT" : \
101 cmd == ACTION_MAKE_LINK ? "ACTION_MAKE_LINK" : \
102 cmd == ACTION_SET_FILE_SIZE ? "ACTION_SET_FILE_SIZE" : \
103 cmd == ACTION_WRITE_PROTECT ? "ACTION_WRITE_PROTECT" : \
104 cmd == ACTION_READ_LINK ? "ACTION_READ_LINK" : \
105 cmd == ACTION_FH_FROM_LOCK ? "ACTION_FH_FROM_LOCK" : \
106 cmd == ACTION_IS_FILESYSTEM ? "ACTION_IS_FILESYSTEM" : \
107 cmd == ACTION_CHANGE_MODE ? "ACTION_CHANGE_MODE" : \
108 cmd == ACTION_COPY_DIR_FH ? "ACTION_COPY_DIR_FH" : \
109 cmd == ACTION_PARENT_FH ? "ACTION_PARENT_FH" : \
110 cmd == ACTION_EXAMINE_ALL ? "ACTION_EXAMINE_ALL" : \
111 cmd == ACTION_EXAMINE_FH ? "ACTION_EXAMINE_FH" : \
112 cmd == ACTION_EXAMINE_ALL_END ? "ACTION_EXAMINE_ALL_END" : \
113 cmd == ACTION_SET_OWNER ? "ACTION_SET_OWNER" : \
114 cmd == ACTION_LOCK_RECORD ? "ACTION_LOCK_RECORD" : \
115 cmd == ACTION_FREE_RECORD ? "ACTION_FREE_RECORD" : \
116 cmd == ACTION_ADD_NOTIFY ? "ACTION_ADD_NOTIFY" : \
117 cmd == ACTION_REMOVE_NOTIFY ? "ACTION_REMOVE_NOTIFY" : \
118 cmd == ACTION_SERIALIZE_DISK ? "ACTION_SERIALIZE_DISK" : \
119 "unknown")
120 #endif
122 static BSTR mkbstr(APTR pool, STRPTR str) {
123 UBYTE *buf;
124 UBYTE len;
126 len = strlen(str) & 0xff;
128 buf = AllocPooled(pool, len + 1);
129 CopyMem(str, &(buf[1]), len);
130 buf[0] = len;
132 return (BSTR) MKBADDR(buf);
135 static STRPTR mkcstr(APTR pool, BSTR bstr) {
136 UBYTE *str = BADDR(bstr);
137 UBYTE *buf;
138 UBYTE len = str[0];
140 buf = AllocPooled(pool, len + 1);
141 CopyMem(&(str[1]), buf, len);
142 buf[len] = 0;
144 return buf;
147 static struct ph_packet *packet_alloc(void) {
148 APTR pool;
149 struct ph_packet *pkt;
151 pool = CreatePool(MEMF_PUBLIC | MEMF_CLEAR, 1024, 256);
152 if (pool == NULL) {
153 SetIoErr(ERROR_NO_FREE_STORE);
154 return NULL;
157 pkt = AllocPooled(pool, sizeof(struct ph_packet));
159 pkt->dp.dp_Link = (struct Message *) pkt;
160 pkt->msg.mn_Node.ln_Name = (char *) &(pkt->dp);
162 pkt->pool = pool;
164 return pkt;
167 void packet_handle_request(struct IOFileSys *iofs, struct PacketBase *PacketBase) {
168 struct ph_handle *handle = (struct ph_handle *) iofs->IOFS.io_Unit;
169 struct ph_packet *pkt;
170 struct DosPacket *dp;
172 D(bug("[packet] got io request %d (%s)\n", iofs->IOFS.io_Command, fsa_str(iofs->IOFS.io_Command)));
174 /* get our data back */
175 handle = (struct ph_handle *) iofs->IOFS.io_Unit;
177 /* make a fresh new packet */
178 pkt = packet_alloc();
179 dp = &(pkt->dp);
181 /* hook the iofs up to the packet so we can find it on return
182 * dp_Arg7 should be unused; DoPkt() doesn't touch it */
183 dp->dp_Arg7 = (IPTR) iofs;
185 /* our reply port will cause packet_reply() to be called when they reply */
186 dp->dp_Port = &(handle->mount->reply_port);
188 /* convert the command */
189 switch (iofs->IOFS.io_Command) {
191 case FSA_OPEN:
192 D(bug("[packet] OPEN: lock 0x%08x (%s) name '%s' type %s\n",
193 handle->actual,
194 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle"),
195 iofs->io_Union.io_OPEN.io_Filename,
196 (iofs->io_Union.io_OPEN.io_FileMode & FMF_LOCK) ? "EXCLUSIVE" : "SHARED"));
199 * NameFromLock() can call FSA_OPEN with a handle to a file rather
200 * than a directory. That seems like a bug, but it doesn't affect
201 * existing handlers because they naively concat the lock name and
202 * the file name, then look backwards through the full name
203 * looking for '/' and going up the tree based on that.
204 * FATFileSystem instead checks a flag inside the lock structure
205 * to see if the lock is a directory, and fails outright if its
206 * not.
208 * Here we intercept this special case and explicitly request the
209 * current/parent directory. Unfortunately ACTION_PARENT can't
210 * take an lock parameter - it always returns a shared lock. Thats
211 * sufficient for this case but is technically incorrect. The
212 * real solution is for something other than FSA_OPEN to be used
213 * to do this.
215 if (iofs->io_Union.io_OPEN.io_Filename[0] == '/' &&
216 iofs->io_Union.io_OPEN.io_Filename[1] == '\0') {
218 /* if they asked for the parent of the root, give it to them */
219 if (handle == &(handle->mount->root_handle)) {
220 iofs->IOFS.io_Unit = (struct Unit *) &(handle->mount->root_handle);
221 goto reply;
224 dp->dp_Type = ACTION_PARENT;
225 dp->dp_Arg1 = (IPTR) (handle->is_lock ? handle->actual : NULL);
228 else {
229 dp->dp_Type = ACTION_LOCATE_OBJECT;
230 dp->dp_Arg1 = (IPTR) (handle->is_lock ? handle->actual : NULL);
231 dp->dp_Arg2 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_OPEN.io_Filename);
232 dp->dp_Arg3 = (iofs->io_Union.io_OPEN.io_FileMode & FMF_LOCK) ? EXCLUSIVE_LOCK : SHARED_LOCK;
235 break;
237 case FSA_OPEN_FILE: {
238 ULONG mode = iofs->io_Union.io_OPEN_FILE.io_FileMode;
239 struct FileHandle *fh;
241 D(bug("[packet] OPEN_FILE: lock 0x%08x (%s) name '%s' mode 0x%x prot 0x%x\n",
242 handle->actual,
243 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle"),
244 iofs->io_Union.io_OPEN_FILE.io_Filename,
245 mode,
246 iofs->io_Union.io_OPEN_FILE.io_Protection));
248 /* convert modes to the proper packet type */
249 if (mode == FMF_MODE_OLDFILE || mode == FMF_READ)
250 dp->dp_Type = ACTION_FINDINPUT;
251 else if (mode == FMF_MODE_READWRITE)
252 dp->dp_Type = ACTION_FINDUPDATE;
253 else if (mode == FMF_MODE_NEWFILE)
254 dp->dp_Type = ACTION_FINDOUTPUT;
255 else {
256 /* XXX do we need to handle other combinations? */
257 iofs->io_DosError = ERROR_BAD_NUMBER;
258 goto reply;
261 /* make a new filehandle */
262 fh = (struct FileHandle *) AllocMem(sizeof(struct FileHandle), MEMF_PUBLIC | MEMF_CLEAR);
263 if (fh == NULL) {
264 iofs->io_DosError = ERROR_NO_FREE_STORE;
265 goto reply;
268 /* dos.lib buffer stuff, must be initialised this way */
269 fh->fh_Pos = fh->fh_End = (UBYTE *) -1;
271 dp->dp_Arg1 = (IPTR) MKBADDR(fh);
272 dp->dp_Arg2 = (IPTR) (handle->is_lock ? handle->actual : NULL);
273 dp->dp_Arg3 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_OPEN.io_Filename);
275 break;
278 case FSA_CLOSE:
279 D(bug("[packet] CLOSE: lock 0x%08x (%s)\n",
280 handle->actual,
281 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle")));
283 /* if this is the root handle, then we previously intercepted a
284 * call and returned it (eg FSA_OPEN/ACTION_PARENT), so we don't
285 * want the handler to do anything */
286 if (handle == &(handle->mount->root_handle)) {
287 iofs->IOFS.io_Unit = NULL;
288 goto reply;
291 dp->dp_Type = (handle->is_lock) ? ACTION_FREE_LOCK : ACTION_END;
292 dp->dp_Arg1 = (IPTR) handle->actual;
293 break;
295 case FSA_READ:
296 D(bug("[packet] READ: handle 0x%08x buf 0x%08x len %ld\n",
297 handle->actual,
298 iofs->io_Union.io_READ.io_Buffer,
299 iofs->io_Union.io_READ.io_Length));
301 dp->dp_Type = ACTION_READ;
302 dp->dp_Arg1 = (IPTR) handle->actual;
303 dp->dp_Arg2 = (IPTR) iofs->io_Union.io_READ.io_Buffer;
304 dp->dp_Arg3 = (IPTR) iofs->io_Union.io_READ.io_Length;
306 /* DOSFALSE == 0, so we can't distinguish between a zero-length
307 * read an actual error. So, we reset the length here. If the
308 * returned packet is DOSFALSE, but no error, this will make sure
309 * DOS gets the right length back */
310 iofs->io_Union.io_READ.io_Length = 0;
311 break;
313 case FSA_WRITE:
314 D(bug("[packet] WRITE: handle 0x%08x buf 0x%08x len %ld\n",
315 handle->actual,
316 iofs->io_Union.io_WRITE.io_Buffer,
317 iofs->io_Union.io_WRITE.io_Length));
319 dp->dp_Type = ACTION_WRITE;
320 dp->dp_Arg1 = (IPTR) handle->actual;
321 dp->dp_Arg2 = (IPTR) iofs->io_Union.io_WRITE.io_Buffer;
322 dp->dp_Arg3 = (IPTR) iofs->io_Union.io_WRITE.io_Length;
324 iofs->io_Union.io_WRITE.io_Length = 0;
325 break;
327 case FSA_SEEK:
328 #if defined(DEBUG) && DEBUG != 0
330 ULONG mode = iofs->io_Union.io_SEEK.io_SeekMode;
332 bug("[packet] SEEK: handle 0x%08x offset %ld mode %ld (%s)\n",
333 handle->actual,
334 (LONG) iofs->io_Union.io_SEEK.io_Offset,
335 mode,
336 mode == OFFSET_BEGINNING ? "OFFSET_BEGINNING" :
337 mode == OFFSET_CURRENT ? "OFFSET_CURRENT" :
338 mode == OFFSET_END ? "OFFSET_END" :
339 "[unknown]");
341 #endif
343 dp->dp_Type = ACTION_SEEK;
344 dp->dp_Arg1 = (IPTR) handle->actual;
345 dp->dp_Arg2 = (IPTR) iofs->io_Union.io_SEEK.io_Offset;
346 dp->dp_Arg3 = (IPTR) iofs->io_Union.io_SEEK.io_SeekMode;
347 break;
349 case FSA_SET_FILE_SIZE:
350 #if defined(DEBUG) && DEBUG != 0
352 ULONG mode = iofs->io_Union.io_SET_FILE_SIZE.io_SeekMode;
354 bug("[packet] SET_FILE_SIZE: handle 0x%08x offset %ld mode %ld (%s)\n",
355 handle->actual,
356 (LONG) iofs->io_Union.io_SET_FILE_SIZE.io_Offset,
357 mode,
358 mode == OFFSET_BEGINNING ? "OFFSET_BEGINNING" :
359 mode == OFFSET_CURRENT ? "OFFSET_CURRENT" :
360 mode == OFFSET_END ? "OFFSET_END" :
361 "[unknown]");
363 #endif
365 dp->dp_Type = ACTION_SET_FILE_SIZE;
366 dp->dp_Arg1 = (IPTR) handle->actual;
367 dp->dp_Arg2 = (IPTR) iofs->io_Union.io_SET_FILE_SIZE.io_Offset;
368 dp->dp_Arg3 = (IPTR) iofs->io_Union.io_SET_FILE_SIZE.io_SeekMode;
369 break;
371 case FSA_FILE_MODE: /* XXX untested */
372 D(bug("[packet] FILE_MODE: lock 0x%08x (%s) mode 0x%x\b\n",
373 handle->actual,
374 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle"),
375 iofs->io_Union.io_FILE_MODE.io_FileMode));
377 dp->dp_Type = ACTION_CHANGE_MODE;
379 if (handle->is_lock) {
380 dp->dp_Arg1 = CHANGE_LOCK;
381 dp->dp_Arg3 = (IPTR) iofs->io_Union.io_FILE_MODE.io_FileMode;
383 else {
384 dp->dp_Arg1 = CHANGE_FH;
385 dp->dp_Arg3 = iofs->io_Union.io_FILE_MODE.io_FileMode & FMF_LOCK ? EXCLUSIVE_LOCK : SHARED_LOCK;
388 break;
390 case FSA_IS_INTERACTIVE:
391 /* XXX is there some other way to query this? how does (eg) aos
392 * console handler do it? */
393 iofs->io_Union.io_IS_INTERACTIVE.io_IsInteractive = FALSE;
394 iofs->io_DosError = 0;
395 goto reply;
397 case FSA_SAME_LOCK: {
398 struct ph_handle *h1, *h2;
399 h1 = (struct ph_handle *) iofs->io_Union.io_SAME_LOCK.io_Lock[0];
400 h2 = (struct ph_handle *) iofs->io_Union.io_SAME_LOCK.io_Lock[1];
402 D(bug("[packet] SAME_LOCK: lock1 0x%08x (%s) lock2 0x%08x (%s)\n",
403 h1->actual,
404 h1 == &(h1->mount->root_handle) ? "root" : (h1->is_lock ? "lock" : "handle"),
405 h2->actual,
406 h2 == &(h2->mount->root_handle) ? "root" : (h2->is_lock ? "lock" : "handle")));
408 dp->dp_Type = ACTION_SAME_LOCK;
409 dp->dp_Arg1 = (IPTR) h1->actual;
410 dp->dp_Arg2 = (IPTR) h2->actual;
411 break;
414 case FSA_EXAMINE: {
415 struct FileInfoBlock *fib;
417 D(bug("[packet] EXAMINE: lock 0x%08x (%s)\n",
418 handle->actual,
419 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle")));
421 fib = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC | MEMF_CLEAR);
423 dp->dp_Type = (handle->is_lock) ? ACTION_EXAMINE_OBJECT : ACTION_EXAMINE_FH;
424 dp->dp_Arg1 = (IPTR) handle->actual;
425 dp->dp_Arg2 = (IPTR) MKBADDR(fib);
426 break;
429 case FSA_EXAMINE_NEXT:
430 D(bug("[packet] EXAMINE_NEXT: lock 0x%08x (%s) fib 0x%08x\n",
431 handle->actual,
432 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle"),
433 iofs->io_Union.io_EXAMINE_NEXT.io_fib));
435 dp->dp_Type = ACTION_EXAMINE_NEXT;
436 dp->dp_Arg1 = (IPTR) handle->actual;
437 dp->dp_Arg2 = (IPTR) MKBADDR(iofs->io_Union.io_EXAMINE_NEXT.io_fib);
438 break;
440 case FSA_CREATE_DIR:
441 D(bug("[packet] CREATE_DIR: lock 0x%08x (%s) name '%s'\n",
442 handle->actual,
443 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle"),
444 iofs->io_Union.io_CREATE_DIR.io_Filename));
446 dp->dp_Type = ACTION_CREATE_DIR;
447 dp->dp_Arg1 = (IPTR) (handle->is_lock ? handle->actual : NULL);
448 dp->dp_Arg2 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_CREATE_DIR.io_Filename);
449 break;
451 case FSA_IS_FILESYSTEM:
452 dp->dp_Type = ACTION_IS_FILESYSTEM;
453 break;
455 case FSA_DISK_INFO:
456 dp->dp_Type = ACTION_DISK_INFO;
457 dp->dp_Arg1 = (IPTR) MKBADDR(iofs->io_Union.io_INFO.io_Info);
458 break;
460 case FSA_CREATE_HARDLINK: /* XXX untested */
461 D(bug("[packet] CREATE_HARDLINK: lock 0x%08x (%s) name '%s' target '%s'\n",
462 handle->actual,
463 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle"),
464 iofs->io_Union.io_CREATE_HARDLINK.io_Filename,
465 iofs->io_Union.io_CREATE_HARDLINK.io_OldFile));
467 dp->dp_Type = ACTION_MAKE_LINK;
468 dp->dp_Arg1 = (IPTR) handle->actual;
469 dp->dp_Arg2 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_CREATE_HARDLINK.io_Filename);
470 dp->dp_Arg3 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_CREATE_HARDLINK.io_OldFile);
471 dp->dp_Arg4 = LINK_HARD;
472 break;
474 case FSA_CREATE_SOFTLINK: /* XXX untested */
475 D(bug("[packet] CREATE_SOFTLINK: lock 0x%08x (%s) name '%s' target '%s'\n",
476 handle->actual,
477 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle"),
478 iofs->io_Union.io_CREATE_SOFTLINK.io_Filename,
479 iofs->io_Union.io_CREATE_SOFTLINK.io_Reference));
481 dp->dp_Type = ACTION_MAKE_LINK;
482 dp->dp_Arg1 = (IPTR) handle->actual;
483 dp->dp_Arg2 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_CREATE_SOFTLINK.io_Filename);
484 dp->dp_Arg3 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_CREATE_SOFTLINK.io_Reference);
485 dp->dp_Arg4 = LINK_SOFT;
486 break;
488 case FSA_RENAME:
489 D(bug("[packet] RENAME: lock 0x%08x (%s) name '%s' target '%s'\n",
490 handle->actual,
491 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle"),
492 iofs->io_Union.io_RENAME.io_Filename,
493 iofs->io_Union.io_RENAME.io_NewName));
495 /* XXX the two paths from FSA_RENAME are copied directly from the
496 * arguments to rename with no changes, so they may contain volume
497 * specifiers, path seperators, etc. both can be calculated
498 * relative to the handle. here we just pass them through to the
499 * handler as-is, but I'm not sure if thats right. fat.handler at
500 * least will do the right thing. this probably needs to be
501 * revisited if another packet-based handler is ported */
503 dp->dp_Type = ACTION_RENAME_OBJECT;
504 dp->dp_Arg1 = (IPTR) handle->actual;
505 dp->dp_Arg2 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_RENAME.io_Filename);
506 dp->dp_Arg3 = (IPTR) handle->actual;
507 dp->dp_Arg4 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_RENAME.io_NewName);
508 break;
510 case FSA_READ_SOFTLINK: /* XXX untested */
511 D(bug("[packet] READ_SOFTLINK: lock 0x%08x (%s)\n",
512 handle->actual,
513 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle")));
515 dp->dp_Type = ACTION_READ_LINK;
516 dp->dp_Arg1 = (IPTR) handle->actual;
517 dp->dp_Arg2 = 0; /* XXX we don't have this (path that caused ERROR_IS_SOFT_LINK) */
518 dp->dp_Arg3 = (IPTR) iofs->io_Union.io_READ_SOFTLINK.io_Buffer;
519 dp->dp_Arg4 = (IPTR) iofs->io_Union.io_READ_SOFTLINK.io_Size;
520 break;
522 case FSA_DELETE_OBJECT:
523 D(bug("[packet] DELETE: lock 0x%08x (%s) name '%s'\n",
524 handle->actual,
525 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle"),
526 iofs->io_Union.io_DELETE_OBJECT.io_Filename));
528 dp->dp_Type = ACTION_DELETE_OBJECT;
529 dp->dp_Arg1 = (IPTR) handle->actual;
530 dp->dp_Arg2 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_DELETE_OBJECT.io_Filename);
531 break;
533 case FSA_SET_COMMENT: /* XXX untested */
534 D(bug("[packet] SET_COMMENT: lock 0x%08x (%s) name '%s' comment '%s'\n",
535 handle->actual,
536 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle"),
537 iofs->io_Union.io_SET_COMMENT.io_Filename,
538 iofs->io_Union.io_SET_COMMENT.io_Comment));
540 dp->dp_Type = ACTION_SET_COMMENT;
541 dp->dp_Arg1 = 0;
542 dp->dp_Arg2 = (IPTR) handle->actual;
543 dp->dp_Arg3 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_SET_COMMENT.io_Filename);
544 dp->dp_Arg4 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_SET_COMMENT.io_Comment);
545 break;
547 case FSA_SET_PROTECT:
548 D(bug("[packet] SET_PROTECT: lock 0x%08x (%s) name '%s' attrs 0x%x\n",
549 handle->actual,
550 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle"),
551 iofs->io_Union.io_SET_PROTECT.io_Filename,
552 iofs->io_Union.io_SET_PROTECT.io_Protection));
554 dp->dp_Type = ACTION_SET_PROTECT;
555 dp->dp_Arg1 = 0;
556 dp->dp_Arg2 = (IPTR) handle->actual;
557 dp->dp_Arg3 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_SET_PROTECT.io_Filename);
558 dp->dp_Arg4 = (IPTR) iofs->io_Union.io_SET_PROTECT.io_Protection;
559 break;
561 case FSA_SET_OWNER: /* XXX untested */
562 D(bug("[packet] SET_OWNER: lock 0x%08x (%s) name '%s' uid 0x%x gid 0x%x\n",
563 handle->actual,
564 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle"),
565 iofs->io_Union.io_SET_OWNER.io_Filename,
566 iofs->io_Union.io_SET_OWNER.io_UID,
567 iofs->io_Union.io_SET_OWNER.io_GID));
569 dp->dp_Type = ACTION_SET_OWNER;
570 dp->dp_Arg1 = 0;
571 dp->dp_Arg2 = (IPTR) handle->actual;
572 dp->dp_Arg3 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_SET_OWNER.io_Filename);
573 dp->dp_Arg4 = (IPTR) iofs->io_Union.io_SET_OWNER.io_GID << 16 |
574 iofs->io_Union.io_SET_OWNER.io_UID;
575 break;
577 case FSA_SET_DATE: /* XXX untested */
578 #if defined(DEBUG) && DEBUG != 0
580 struct DateTime dt;
581 char datestr[LEN_DATSTRING];
583 dt.dat_Stamp = iofs->io_Union.io_SET_DATE.io_Date;
584 dt.dat_Format = FORMAT_DOS;
585 dt.dat_Flags = 0;
586 dt.dat_StrDay = NULL;
587 dt.dat_StrDate = datestr;
588 dt.dat_StrTime = NULL;
589 DateToStr(&dt);
591 bug("[packet] SET_DATE: lock 0x%08x (%s) name '%s' date '%s'\n",
592 handle->actual,
593 handle == &(handle->mount->root_handle) ? "root" : (handle->is_lock ? "lock" : "handle"),
594 iofs->io_Union.io_SET_DATE.io_Filename,
595 datestr);
597 #endif
599 dp->dp_Type = ACTION_SET_DATE;
600 dp->dp_Arg1 = 0;
601 dp->dp_Arg2 = (IPTR) handle->actual;
602 dp->dp_Arg3 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_SET_DATE.io_Filename);
603 dp->dp_Arg4 = (IPTR) &iofs->io_Union.io_SET_DATE.io_Date;
604 break;
606 case FSA_MORE_CACHE: /* XXX untested */
607 D(bug("[packet] MORE_CACHE: buffers '0x%x'\n", iofs->io_Union.io_MORE_CACHE.io_NumBuffers));
609 dp->dp_Type = ACTION_MORE_CACHE;
610 dp->dp_Arg1 = (IPTR) iofs->io_Union.io_MORE_CACHE.io_NumBuffers;
611 break;
613 case FSA_FORMAT: /* XXX untested */
614 D(bug("[packet] FSA_FORMAT: name '%s' type 0x%x\n",
615 iofs->io_Union.io_FORMAT.io_VolumeName,
616 iofs->io_Union.io_FORMAT.io_DosType));
618 dp->dp_Type = ACTION_FORMAT;
619 dp->dp_Arg1 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_FORMAT.io_VolumeName);
620 dp->dp_Arg2 = (IPTR) iofs->io_Union.io_FORMAT.io_DosType;
621 break;
623 case FSA_INHIBIT: /* XXX untested */
624 D(bug("[packet] FSA_INHIBIT: %sinhibit\n", iofs->io_Union.io_INHIBIT.io_Inhibit == 0 ? "un" : ""));
626 dp->dp_Type = ACTION_INHIBIT;
627 dp->dp_Arg1 = (IPTR) iofs->io_Union.io_INHIBIT.io_Inhibit;
628 break;
630 case FSA_RELABEL:
631 D(bug("[packet] FSA_RELABEL: name '%s'\n", iofs->io_Union.io_RELABEL.io_NewName));
633 dp->dp_Type = ACTION_RENAME_DISK;
634 dp->dp_Arg1 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_RELABEL.io_NewName);
635 break;
637 case FSA_LOCK_RECORD: /* XXX untested */
638 #if defined(DEBUG) && DEBUG != 0
640 ULONG mode = iofs->io_Union.io_RECORD.io_RecordMode;
642 bug("[packet] FSA_LOCK_RECORD: handle 0x%08x offset %ld size %ld mode %d (%s) timeout %d\n",
643 handle->actual,
644 (LONG) iofs->io_Union.io_RECORD.io_Offset,
645 iofs->io_Union.io_RECORD.io_Size,
646 mode,
647 mode == REC_EXCLUSIVE ? "REC_EXCLUSIVE" :
648 mode == REC_EXCLUSIVE_IMMED ? "REC_EXCLUSIVE_IMMED" :
649 mode == REC_SHARED ? "REC_SHARED" :
650 mode == REC_SHARED_IMMED ? "REC_SHARED_IMMED" :
651 "[unknown]",
652 iofs->io_Union.io_RECORD.io_Timeout);
654 #endif
656 dp->dp_Type = ACTION_LOCK_RECORD;
657 dp->dp_Arg1 = (IPTR) handle->actual;
658 dp->dp_Arg2 = (IPTR) iofs->io_Union.io_RECORD.io_Offset;
659 dp->dp_Arg3 = (IPTR) iofs->io_Union.io_RECORD.io_Size;
660 dp->dp_Arg4 = (IPTR) iofs->io_Union.io_RECORD.io_RecordMode;
661 dp->dp_Arg5 = (IPTR) iofs->io_Union.io_RECORD.io_Timeout;
662 break;
664 case FSA_UNLOCK_RECORD: /* XXX untested */
665 D(bug("[packet] FSA_UNLOCK_RECORD: handle 0x%08x offset %ld size %ld\n",
666 handle->actual,
667 (LONG) iofs->io_Union.io_RECORD.io_Offset,
668 iofs->io_Union.io_RECORD.io_Size));
670 dp->dp_Type = ACTION_FREE_RECORD;
671 dp->dp_Arg1 = (IPTR) handle->actual;
672 dp->dp_Arg2 = (IPTR) iofs->io_Union.io_RECORD.io_Offset;
673 dp->dp_Arg3 = (IPTR) iofs->io_Union.io_RECORD.io_Size;
674 break;
676 case FSA_ADD_NOTIFY:
677 D(bug("[packet] FSA_ADD_NOTIFY: nr 0x%08x name '%s'\n",
678 iofs->io_Union.io_NOTIFY.io_NotificationRequest,
679 iofs->io_Union.io_NOTIFY.io_NotificationRequest->nr_FullName));
681 dp->dp_Type = ACTION_ADD_NOTIFY;
682 dp->dp_Arg1 = iofs->io_Union.io_NOTIFY.io_NotificationRequest;
683 break;
685 case FSA_REMOVE_NOTIFY:
686 D(bug("[packet] FSA_REMOVE_NOTIFY: nr 0x%08x name '%s'\n",
687 iofs->io_Union.io_NOTIFY.io_NotificationRequest,
688 iofs->io_Union.io_NOTIFY.io_NotificationRequest->nr_FullName));
690 dp->dp_Type = ACTION_REMOVE_NOTIFY;
691 dp->dp_Arg1 = iofs->io_Union.io_NOTIFY.io_NotificationRequest;
692 break;
694 /* XXX implement */
695 case FSA_EXAMINE_ALL:
696 case FSA_EXAMINE_ALL_END:
697 case FSA_MOUNT_MODE:
698 case FSA_CHANGE_SIGNAL:
699 case FSA_PARENT_DIR:
700 case FSA_PARENT_DIR_POST:
701 case FSA_CONSOLE_MODE:
702 D(bug("[packet] command not implemented\n"));
703 iofs->io_DosError = ERROR_NOT_IMPLEMENTED;
704 goto reply;
706 default:
707 D(bug("[packet] unknown command\n"));
708 iofs->io_DosError = ERROR_ACTION_NOT_KNOWN;
709 goto reply;
712 D(bug("[packet] converted to %s packet\n", act_str(dp->dp_Type)));
714 /* WaitIO() will look into this */
715 iofs->IOFS.io_Message.mn_Node.ln_Type = NT_MESSAGE;
717 /* since these all go to the packet handler process, they can't be done now */
718 iofs->IOFS.io_Flags &= ~IOF_QUICK;
720 /* send the packet */
721 PutMsg(&(handle->mount->process->pr_MsgPort), dp->dp_Link);
723 return;
725 /* jump here to reply to the packet now, handling IOF_QUICK appropriately */
726 reply:
727 D(bug("[packet] replying directly with error %d\n", iofs->io_DosError));
729 /* kill the packet */
730 DeletePool(pkt->pool);
732 /* if they can handle quick replies, just bail out */
733 if (iofs->IOFS.io_Flags & IOF_QUICK)
734 return;
736 /* otherwise tell them properly */
737 ReplyMsg((APTR) iofs);
740 AROS_UFH3(void, packet_reply,
741 AROS_UFHA(struct ph_mount *, mount, A1),
742 AROS_UFHA(APTR, dummy, A5),
743 AROS_UFHA(struct ExecBase *, SysBase, A6)) {
745 AROS_USERFUNC_INIT
747 struct DosPacket *dp;
748 struct ph_packet *pkt;
749 struct IOFileSys *iofs;
750 struct ph_handle *handle;
752 /* retrieve the message and fish the packet out */
753 dp = (struct DosPacket *) GetMsg(&(mount->reply_port))->mn_Node.ln_Name;
754 pkt = (struct ph_packet *) dp->dp_Link;
756 D(bug("[packet] got reply packet %d (%s)\n", dp->dp_Type, act_str(dp->dp_Type)));
758 /* get the iofs back */
759 iofs = (struct IOFileSys *) dp->dp_Arg7;
761 /* dos error code comes back in Res2 */
762 if (dp->dp_Res1 == DOSFALSE) {
763 iofs->io_DosError = dp->dp_Res2;
765 /* do any cleanup from the request (eg freeing memory) */
766 switch (dp->dp_Type) {
767 case ACTION_FINDINPUT:
768 case ACTION_FINDOUTPUT:
769 case ACTION_FINDUPDATE:
770 FreeMem((APTR) BADDR(dp->dp_Arg1), sizeof(struct FileHandle));
771 break;
773 case ACTION_SAME_LOCK:
774 /* DOSFALSE & no error means the locks are different */
775 if (iofs->io_DosError == 0)
776 iofs->io_Union.io_SAME_LOCK.io_Same = LOCK_DIFFERENT;
777 break;
779 case ACTION_PARENT:
780 /* no error means they tried to go up past the root. The
781 * packet system allows this, IOFS does not */
782 if (iofs->io_DosError == 0)
783 iofs->io_DosError = ERROR_OBJECT_NOT_FOUND;
784 break;
787 /* kill the packet */
788 DeletePool(pkt->pool);
790 D(bug("[packet] returning error %ld\n", iofs->io_DosError));
792 /* and tell them */
793 ReplyMsg((APTR) iofs);
795 return;
798 /* no error */
799 iofs->io_DosError = 0;
801 /* populate the iofs with the results. note that for packets that only
802 * return success/failure we have nothing to do, so they're not listed here */
803 switch (dp->dp_Type) {
805 case ACTION_LOCATE_OBJECT:
806 case ACTION_PARENT:
807 handle = (struct ph_handle *) AllocMem(sizeof(struct ph_handle), MEMF_PUBLIC | MEMF_CLEAR);
808 if (handle == NULL) {
809 iofs->io_DosError = ERROR_NO_FREE_STORE;
810 break;
813 /* we'll need the lock they gave us for future operations */
814 handle->actual = (void *) dp->dp_Res1;
815 handle->is_lock = TRUE;
816 handle->mount = mount;
818 iofs->IOFS.io_Unit = (struct Unit *) handle;
820 break;
822 case ACTION_FINDINPUT:
823 case ACTION_FINDOUTPUT:
824 case ACTION_FINDUPDATE: {
825 struct FileHandle *fh = (struct FileHandle *) BADDR(dp->dp_Arg1);
827 handle = (struct ph_handle *) AllocMem(sizeof(struct ph_handle), MEMF_PUBLIC | MEMF_CLEAR);
828 if (handle == NULL) {
829 iofs->io_DosError = ERROR_NO_FREE_STORE;
830 FreeMem((APTR) fh, sizeof(struct FileHandle));
831 break;
834 /* handlers return "internal data" (typically a lock, though we
835 * can't assume that) in fh_Arg1. we need to keep it for later
836 * filehandle operations. the filehandle itself is expendable -
837 * the calls that need this data (eg ACTION_READ/WRITE/SEEK) take
838 * it directly in dp_Arg1 */
839 handle->actual = (void *) fh->fh_Arg1;
840 handle->is_lock = FALSE;
841 handle->mount = mount;
843 iofs->IOFS.io_Unit = (struct Unit *) handle;
845 FreeMem((APTR) fh, sizeof(struct FileHandle));
847 break;
850 case ACTION_FREE_LOCK:
851 case ACTION_END:
852 /* free up our data */
853 handle = (struct ph_handle *) iofs->IOFS.io_Unit;
854 FreeMem((APTR) handle, sizeof(struct ph_handle));
855 iofs->IOFS.io_Unit = NULL;
856 break;
858 case ACTION_READ:
859 iofs->io_Union.io_READ.io_Length = dp->dp_Res1;
860 break;
862 case ACTION_WRITE:
863 iofs->io_Union.io_WRITE.io_Length = dp->dp_Res1;
864 break;
866 case ACTION_SEEK:
867 iofs->io_Union.io_SEEK.io_Offset = dp->dp_Res1;
868 break;
870 case ACTION_SAME_LOCK:
871 iofs->io_Union.io_SAME_LOCK.io_Same = LOCK_SAME;
872 break;
874 case ACTION_EXAMINE_OBJECT:
875 case ACTION_EXAMINE_FH: {
876 struct FileInfoBlock *fib = (struct FileInfoBlock *) BADDR(dp->dp_Arg2);
877 struct ExAllData *ead = iofs->io_Union.io_EXAMINE.io_ead;
878 ULONG size = iofs->io_Union.io_EXAMINE.io_Size;
879 ULONG mode = iofs->io_Union.io_EXAMINE.io_Mode;
880 ULONG comment_len = 0, filename_len = 0;
882 iofs->io_DirPos = fib->fib_DiskKey;
884 /* make sure we have enough room for everything that came back */
885 if (size < sizeof(struct ExAllData) +
886 (mode >= ED_COMMENT ? (comment_len = strlen(fib->fib_Comment)) : 0) +
887 (mode >= ED_NAME ? (filename_len = strlen(fib->fib_FileName)) : 0)) {
888 iofs->io_DosError = ERROR_BUFFER_OVERFLOW;
889 FreeMem(fib, sizeof(struct FileInfoBlock));
890 break;
893 /* copy stuff from the fib to the ead */
894 switch (mode) {
895 case ED_OWNER:
896 ead->ed_OwnerUID = fib->fib_OwnerUID;
897 ead->ed_OwnerGID = fib->fib_OwnerGID;
899 case ED_COMMENT:
900 /* store the comment in the spare space after the ead and
901 * the filename */
902 ead->ed_Comment = (UBYTE *) ead + sizeof(struct ExAllData) + filename_len + 1;
903 strcpy(ead->ed_Comment, fib->fib_Comment);
905 case ED_DATE:
906 ead->ed_Days = fib->fib_Date.ds_Days;
907 ead->ed_Mins = fib->fib_Date.ds_Minute;
908 ead->ed_Ticks = fib->fib_Date.ds_Tick;
910 case ED_PROTECTION:
911 ead->ed_Prot = fib->fib_Protection;
913 case ED_SIZE:
914 ead->ed_Size = fib->fib_Size;
916 case ED_TYPE:
917 ead->ed_Type = fib->fib_EntryType;
919 case ED_NAME:
920 /* store the name in the spare space after the ead */
921 ead->ed_Name = (UBYTE *) ead + sizeof(struct ExAllData);
922 strcpy(ead->ed_Name, fib->fib_FileName);
924 case 0:
925 ead->ed_Next = NULL;
926 break;
928 default:
929 iofs->io_DosError = ERROR_BAD_NUMBER;
930 break;
933 FreeMem(fib, sizeof(struct FileInfoBlock));
935 break;
938 case ACTION_IS_FILESYSTEM:
939 iofs->io_Union.io_IS_FILESYSTEM.io_IsFilesystem = TRUE;
940 break;
942 case ACTION_CREATE_DIR:
943 handle = (struct ph_handle *) AllocMem(sizeof(struct ph_handle), MEMF_PUBLIC | MEMF_CLEAR);
944 if (handle == NULL) {
945 iofs->io_DosError = ERROR_NO_FREE_STORE;
946 break;
949 /* we'll need the lock they gave us for future operations */
950 handle->actual = (void *) dp->dp_Res1;
951 handle->is_lock = TRUE;
952 handle->mount = mount;
954 iofs->IOFS.io_Unit = (struct Unit *) handle;
956 break;
958 case ACTION_READ_LINK:
959 iofs->io_Union.io_READ_SOFTLINK.io_Size = dp->dp_Res1;
960 break;
962 case ACTION_MORE_CACHE:
963 iofs->io_Union.io_MORE_CACHE.io_NumBuffers = dp->dp_Res1;
966 /* done with the packet */
967 DeletePool(pkt->pool);
969 /* send it back */
970 ReplyMsg((APTR) iofs);
972 AROS_USERFUNC_EXIT