r26220@plastic: rob | 2007-04-29 17:32:27 +1000
[cake.git] / workbench / fs / fat / packet.c
bloba0cceb60e8ac5790cd128ae635ca50a46ef77863
1 /*
2 * fat.handler - FAT12/16/32 filesystem handler
4 * Copyright © 2006 Marek Szyprowski
5 * Copyright © 2007 The AROS Development Team
7 * This program is free software; you can redistribute it and/or modify it
8 * under the same terms as AROS itself.
10 * $Id$
13 #include <exec/types.h>
14 #include <exec/execbase.h>
15 #include <dos/dosextens.h>
16 #include <dos/filehandler.h>
17 #include <devices/inputevent.h>
19 #include <proto/exec.h>
20 #include <proto/dos.h>
22 #include <string.h>
24 #include "fat_fs.h"
25 #include "fat_protos.h"
27 void ProcessPackets(void) {
28 struct Message *msg;
29 struct DosPacket *pkt;
30 struct MsgPort *rp;
32 while ((msg = GetMsg(glob->ourport)) != NULL) {
33 LONG res = DOSFALSE;
34 LONG err = 0;
36 pkt = (struct DosPacket *) msg->mn_Node.ln_Name;
38 switch(pkt->dp_Type) {
39 case ACTION_LOCATE_OBJECT: {
40 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
41 UBYTE *path = BADDR(pkt->dp_Arg2);
42 LONG access = pkt->dp_Arg3;
44 D(bug("[fat] LOCATE_OBJECT: lock 0x%08x (dir %ld/%ld) name '%.*s' type %s\n",
45 pkt->dp_Arg1,
46 fl != NULL ? fl->dir_cluster : 0, fl != NULL ? fl->dir_entry : 0,
47 path[0], &path[1],
48 pkt->dp_Arg3 == EXCLUSIVE_LOCK ? "EXCLUSIVE" : "SHARED"));
50 if ((err = TestLock(fl)))
51 break;
53 if (path[0] != 0) {
54 err = TryLockObj(fl, &path[1], path[0], access, &res);
57 else if (fl != NULL) {
58 D(bug("\tCopying lock\n"));
59 err = CopyLock(fl, &res);
62 else {
63 D(bug("\tLocking root directory.\n"));
64 err = LockRoot(access, &res);
67 break;
70 case ACTION_FREE_LOCK: {
71 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
73 D(bug("[fat] FREE_LOCK: lock 0x%08x (dir %ld/%ld)\n",
74 pkt->dp_Arg1,
75 fl != NULL ? fl->dir_cluster : 0, fl != NULL ? fl->dir_entry : 0));
77 if(fl)
78 FreeLock(fl);
80 res = DOSTRUE;
81 break;
84 case ACTION_COPY_DIR:
85 case ACTION_COPY_DIR_FH: {
86 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
88 D(bug("[fat] COPY_DIR: lock 0x%08x (dir %ld/%ld)\n",
89 pkt->dp_Arg1,
90 fl != NULL ? fl->dir_cluster : 0, fl != NULL ? fl->dir_entry : 0));
92 if ((err = TestLock(fl)))
93 break;
95 if (fl)
96 err = CopyLock(fl, &res);
97 else
98 err = LockRoot(SHARED_LOCK, &res);
100 break;
103 case ACTION_PARENT:
104 case ACTION_PARENT_FH: {
105 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
107 D(bug("[fat] ACTION_PARENT: lock 0x%08x (dir %ld/%ld)\n",
108 pkt->dp_Arg1,
109 fl != NULL ? fl->dir_cluster : 0, fl != NULL ? fl->dir_entry : 0));
111 if ((err = TestLock(fl)))
112 break;
114 if (fl && fl->fl_Key != FAT_ROOTDIR_MARK)
115 err = LockParent(fl, SHARED_LOCK, &res);
116 else
117 err = ERROR_OBJECT_NOT_FOUND;
119 break;
122 case ACTION_SAME_LOCK: {
123 struct ExtFileLock *fl1 = BADDR(pkt->dp_Arg1);
124 struct ExtFileLock *fl2 = BADDR(pkt->dp_Arg2);
126 D(bug("[fat] ACTION_SAME_LOCK: lock #1 0x%08x (dir %ld/%ld) lock #2 0x%08x (dir %ld/%ld)\n",
127 pkt->dp_Arg1,
128 fl1 != NULL ? fl1->dir_cluster : 0, fl1 != NULL ? fl1->dir_entry : 0,
129 pkt->dp_Arg2,
130 fl2 != NULL ? fl2->dir_cluster : 0, fl2 != NULL ? fl2->dir_entry : 0));
132 err = 0;
134 if (fl1 == fl2 || ((fl1->fl_Volume == fl2->fl_Volume) && fl1->fl_Key == fl2->fl_Key))
135 res = DOSTRUE;
137 break;
140 case ACTION_EXAMINE_OBJECT:
141 case ACTION_EXAMINE_FH: {
142 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
143 struct FileInfoBlock *fib = BADDR(pkt->dp_Arg2);
145 D(bug("[fat] EXAMINE_OBJECT: lock 0x%08x (dir %ld/%ld)\n",
146 pkt->dp_Arg1,
147 fl != NULL ? fl->dir_cluster : 0, fl != NULL ? fl->dir_entry : 0));
149 if ((err = TestLock(fl)))
150 break;
152 if ((err = FillFIB(fl, fib)) == 0)
153 res = DOSTRUE;
155 break;
158 case ACTION_EXAMINE_NEXT: {
159 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
160 struct FileInfoBlock *fib = BADDR(pkt->dp_Arg2);
161 struct DirHandle dh;
162 struct DirEntry de;
163 BPTR b; struct ExtFileLock *temp_lock;
165 D(bug("[fat] EXAMINE_NEXT: lock 0x%08x (dir %ld/%ld)\n",
166 pkt->dp_Arg1,
167 fl != NULL ? fl->dir_cluster : 0, fl != NULL ? fl->dir_entry : 0));
169 if ((err = TestLock(fl)))
170 break;
172 if ((err = InitDirHandle(glob->sb, fl->ioh.first_cluster, &dh)))
173 break;
175 dh.cur_index = fib->fib_DiskKey;
177 if ((err = GetNextDirEntry(&dh, &de))) {
178 if (err == ERROR_OBJECT_NOT_FOUND)
179 err = ERROR_NO_MORE_ENTRIES;
180 ReleaseDirHandle(&dh);
181 break;
184 if ((err = LockFile(dh.cur_index, fl->ioh.first_cluster, SHARED_LOCK, &b))) {
185 ReleaseDirHandle(&dh);
186 break;
188 temp_lock = BADDR(b);
190 if ((err = FillFIB(temp_lock, fib))) {
191 FreeLock(temp_lock);
192 ReleaseDirHandle(&dh);
193 break;
196 fib->fib_DiskKey = dh.cur_index;
198 FreeLock(temp_lock);
200 ReleaseDirHandle(&dh);
202 res = DOSTRUE;
204 break;
207 case ACTION_FINDINPUT:
208 case ACTION_FINDOUTPUT:
209 case ACTION_FINDUPDATE: {
210 struct FileHandle *fh = BADDR(pkt->dp_Arg1);
211 struct ExtFileLock *fl = BADDR(pkt->dp_Arg2);
212 UBYTE *path = BADDR(pkt->dp_Arg3);
213 struct ExtFileLock *lock;
215 D(bug("[fat] %s: lock 0x%08x (dir %ld/%ld) path '%.*s'\n",
216 pkt->dp_Type == ACTION_FINDINPUT ? "FINDINPUT" :
217 pkt->dp_Type == ACTION_FINDOUTPUT ? "FINDOUTPUT" :
218 "FINDUPDATE",
219 pkt->dp_Arg2,
220 fl != NULL ? fl->dir_cluster : 0, fl != NULL ? fl->dir_entry : 0,
221 path[0], &path[1]));
223 if ((err = TestLock(fl)))
224 break;
226 if ((err = OpOpenFile(fl, &path[1], path[0], pkt->dp_Type, &lock)) != 0)
227 break;
229 fh->fh_Arg1 = MKBADDR(lock);
230 fh->fh_Port = DOSFALSE;
232 res = DOSTRUE;
234 break;
237 case ACTION_READ: {
238 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
239 APTR buffer = (APTR)pkt->dp_Arg2;
240 ULONG want = pkt->dp_Arg3;
242 D(bug("[fat] READ: lock 0x%08x (dir %ld/%ld pos %ld) want %ld\n",
243 pkt->dp_Arg1,
244 fl != NULL ? fl->dir_cluster : 0, fl != NULL ? fl->dir_entry : 0,
245 fl->pos,
246 want));
248 if ((err = TestLock(fl))) {
249 res = -1;
250 break;
253 if ((err = OpRead(fl, buffer, want, &res)) != 0)
254 res = -1;
256 break;
259 case ACTION_WRITE: {
260 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
261 APTR buffer = (APTR)pkt->dp_Arg2;
262 ULONG want = pkt->dp_Arg3;
264 D(bug("[fat] WRITE: lock 0x%08x (dir %ld/%ld pos %ld) want %ld\n",
265 pkt->dp_Arg1,
266 fl != NULL ? fl->dir_cluster : 0, fl != NULL ? fl->dir_entry : 0,
267 fl->pos,
268 want));
270 if ((err = TestLock(fl))) {
271 res = -1;
272 break;
275 if ((err = OpWrite(fl, buffer, want, &res)) != 0)
276 res = -1;
278 break;
281 case ACTION_SEEK: {
282 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
283 LONG offset = pkt->dp_Arg2;
284 ULONG whence = pkt->dp_Arg3;
286 D(bug("[fat] SEEK: lock 0x%08x (dir %ld/%ld pos %ld) offset %ld whence %s\n",
287 pkt->dp_Arg1,
288 fl != NULL ? fl->dir_cluster : 0, fl != NULL ? fl->dir_entry : 0,
289 fl->pos,
290 offset,
291 whence == OFFSET_BEGINNING ? "BEGINNING" :
292 whence == OFFSET_END ? "END" :
293 whence == OFFSET_CURRENT ? "CURRENT" :
294 "(unknown)"));
295 if ((err = TestLock(fl))) {
296 res = -1;
297 break;
300 res = fl->pos;
301 err = 0;
303 if (whence == OFFSET_BEGINNING && offset >= 0 && offset <= fl->size)
304 fl->pos = offset;
305 else if (whence == OFFSET_CURRENT && offset + fl->pos >= 0 && offset + fl->pos <= fl->size)
306 fl->pos += offset;
307 else if (whence == OFFSET_END && offset <= 0 && fl->size + offset >= 0)
308 fl->pos = fl->size + offset;
309 else {
310 res = -1;
311 err = ERROR_SEEK_ERROR;
314 break;
317 case ACTION_END: {
318 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
320 D(bug("[fat] END: lock 0x%08x (dir %ld/%ld)\n",
321 pkt->dp_Arg1,
322 fl != NULL ? fl->dir_cluster : 0, fl != NULL ? fl->dir_entry : 0));
324 if ((err = TestLock(fl)))
325 break;
327 FreeLock(fl);
329 res = DOSTRUE;
330 break;
333 case ACTION_IS_FILESYSTEM:
334 D(bug("[fat] IS_FILESYSTEM\n"));
336 res = DOSTRUE;
337 break;
339 case ACTION_CURRENT_VOLUME: {
340 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
342 D(bug("[fat] CURRENT_VOLUME: lock 0x%08x\n",
343 pkt->dp_Arg1));
345 res = (fl) ? fl->fl_Volume : ((glob->sb != NULL) ? MKBADDR(glob->sb->doslist) : NULL);
346 break;
349 case ACTION_INFO:
350 case ACTION_DISK_INFO: {
351 struct InfoData *id;
353 if (pkt->dp_Type == ACTION_INFO) {
354 struct FileLock *fl = BADDR(pkt->dp_Arg1);
356 D(bug("[fat] INFO: lock 0x%08x\n",
357 pkt->dp_Arg1));
359 if (fl && (glob->sb == NULL || fl->fl_Volume != MKBADDR(glob->sb->doslist))) {
360 err = ERROR_DEVICE_NOT_MOUNTED;
361 break;
364 id = BADDR(pkt->dp_Arg2);
366 else {
367 D(bug("[fat] DISK_INFO\n"));
369 id = BADDR(pkt->dp_Arg1);
372 FillDiskInfo(id);
374 res = DOSTRUE;
375 break;
378 case ACTION_INHIBIT: {
379 LONG inhibit = pkt->dp_Arg1;
381 D(bug("[fat] INHIBIT: %sinhibit\n",
382 inhibit == DOSTRUE ? "" : "un"));
384 if (inhibit == DOSTRUE) {
385 glob->disk_inhibited++;
386 if (glob->disk_inhibited == 1)
387 DoDiskRemove();
389 else {
390 glob->disk_inhibited--;
391 if (glob->disk_inhibited == 0)
392 ProcessDiskChange();
395 res = DOSTRUE;
396 break;
399 case ACTION_DIE: {
400 D(bug("[fat] DIE\n"));
402 if (glob->sblist != NULL || (glob->sb != NULL && glob->sb->doslist->dol_misc.dol_volume.dol_LockList != NULL)) {
403 D(bug("\tThere are some locks/volumes left. Shutting down is not possible\n"));
404 err = ERROR_OBJECT_IN_USE;
405 break;
408 D(bug("\tNo locks pending. Shutting down the handler\n"));
410 DoDiskRemove(); /* risky, because of async. volume remove, but works */
412 glob->quit = TRUE;
413 glob->devnode->dol_Task = NULL;
415 res = DOSTRUE;
416 break;
419 #if 0
420 /* XXX AROS needs these ACTION_ headers defined in dos/dosextens.h */
422 case ACTION_GET_DISK_FSSM: {
423 D(bug("\nGot ACTION_GET_DISK_FSSM\n"));
425 res = (ULONG) glob->fssm;
426 break;
429 case ACTION_FREE_DISK_FSSM: {
430 D(bug("\nGot ACTION_FREE_DISK_FSSM\n"));
432 res = DOSTRUE;
433 break;
436 #endif
438 case ACTION_DISK_CHANGE: { /* internal */
439 struct DosList *vol = (struct DosList *)pkt->dp_Arg2;
440 ULONG type = pkt->dp_Arg3;
442 D(bug("[fat] DISK_CHANGE [INTERNAL]\n"));
444 if (pkt->dp_Arg1 == ID_FAT_DISK) { /* security check */
446 if (AttemptLockDosList(LDF_VOLUMES|LDF_WRITE)) {
448 if (type == ACTION_VOLUME_ADD) {
449 AddDosEntry(vol);
450 UnLockDosList(LDF_VOLUMES|LDF_WRITE);
452 SendEvent(IECLASS_DISKINSERTED);
454 D(bug("\tVolume added successfuly\n"));
456 else if (type == ACTION_VOLUME_REMOVE) {
457 RemDosEntry(vol);
458 FreeVecPooled(glob->mempool, vol);
459 UnLockDosList(LDF_VOLUMES|LDF_WRITE);
461 SendEvent(IECLASS_DISKREMOVED);
463 D(bug("\tVolume removed successfuly.\n"));
466 FreeDosObject(DOS_STDPKT, pkt); /* cleanup */
468 pkt = NULL;
469 D(bug("Packet destroyed\n"));
472 else {
473 D(bug("\tDosList is locked\n"));
474 Delay(5);
475 PutMsg(glob->ourport, pkt->dp_Link);
476 pkt = NULL;
477 D(bug("Message moved to the end of the queue\n"));
480 else
481 err = ERROR_OBJECT_WRONG_TYPE;
483 break;
486 case ACTION_RENAME_DISK: {
487 UBYTE *name = BADDR(pkt->dp_Arg1);
489 D(bug("[fat] RENAME_DISK: name '%.*s'\n",
490 name[0], &name[1]));
492 if (glob->sb->doslist == NULL) {
493 err = glob->disk_inserted ? ERROR_NOT_A_DOS_DISK : ERROR_NO_DISK;
494 break;
497 while (! AttemptLockDosList(LDF_VOLUMES | LDF_WRITE))
498 ProcessPackets();
500 if ((err = SetVolumeName(glob->sb, name)) != 0)
501 break;
503 UnLockDosList(LDF_VOLUMES | LDF_WRITE);
505 SendEvent(IECLASS_DISKINSERTED);
507 res = DOSTRUE;
509 break;
512 case ACTION_DELETE_OBJECT: {
513 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
514 UBYTE *name = BADDR(pkt->dp_Arg2);
516 D(bug("[fat] DELETE_OBJECT: lock 0x%08x (dir %ld/%ld) path '%.*s'\n",
517 pkt->dp_Arg1,
518 fl != NULL ? fl->dir_cluster : 0, fl != NULL ? fl->dir_entry : 0,
519 name[0], &name[1]));
521 if ((err = TestLock(fl)))
522 break;
524 err = OpDeleteFile(fl, &name[1], name[0]);
526 break;
529 case ACTION_RENAME_OBJECT:
530 D(bug("[fat] RENAME_OBJECT [WRITE]\n"));
531 err = ERROR_DISK_WRITE_PROTECTED;
532 break;
534 case ACTION_CREATE_DIR: {
535 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1), *new;
536 UBYTE *name = BADDR(pkt->dp_Arg2);
538 D(bug("[fat] CREATE_DIR: lock 0x%08x (dir %ld/%ld) name '%.*s'\n",
539 pkt->dp_Arg1,
540 fl != NULL ? fl->dir_cluster : 0, fl != NULL ? fl->dir_entry : 0,
541 name[0], &name[1]));
543 if ((err = TestLock(fl)))
544 break;
546 if ((err = OpCreateDir(fl, &name[1], name[0], &new)) == 0)
547 res = MKBADDR(new);
549 break;
552 case ACTION_SET_FILE_SIZE:
553 D(bug("[fat] SET_FILE_SIZE [WRITE]\n"));
554 err = ERROR_DISK_WRITE_PROTECTED;
555 break;
557 default:
558 D(bug("[fat] got unknown packet type %ld\n", pkt->dp_Type));
560 err = ERROR_ACTION_NOT_KNOWN;
563 if (pkt != NULL) {
564 D(bug("[fat] replying to packet: result 0x%x, error 0x%x\n", res, err));
566 rp = pkt->dp_Port;
568 pkt->dp_Port = glob->ourport;
569 pkt->dp_Res1 = res;
570 pkt->dp_Res2 = err;
572 PutMsg(rp, pkt->dp_Link);