Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / fs / fat / packet.c
blob53a7da2693d575e0cc84e1457210eb9decbc7e1c
1 /*
2 * fat.handler - FAT12/16/32 filesystem handler
4 * Copyright © 2006 Marek Szyprowski
5 * Copyright © 2007-2008 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 <dos/notify.h>
18 #include <devices/inputevent.h>
20 #include <proto/exec.h>
21 #include <proto/dos.h>
23 #include <string.h>
25 #include "fat_fs.h"
26 #include "fat_protos.h"
28 #define DEBUG DEBUG_PACKETS
29 #include "debug.h"
31 void ProcessPackets(void) {
32 struct Message *msg;
33 struct DosPacket *pkt;
34 struct MsgPort *rp;
36 while ((msg = GetMsg(glob->ourport)) != NULL) {
37 LONG res = DOSFALSE;
38 LONG err = 0;
40 pkt = (struct DosPacket *) msg->mn_Node.ln_Name;
42 switch(pkt->dp_Type) {
43 case ACTION_LOCATE_OBJECT: {
44 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1), *lock;
45 UBYTE *path = BADDR(pkt->dp_Arg2);
46 LONG access = pkt->dp_Arg3;
48 D(bug("[fat] LOCATE_OBJECT: lock 0x%08x (dir %ld/%ld) name '", pkt->dp_Arg1,
49 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0);
50 RawPutChars(&path[1], path[0]); bug("' type %s\n",
51 pkt->dp_Arg3 == EXCLUSIVE_LOCK ? "EXCLUSIVE" : "SHARED"));
53 if ((err = TestLock(fl)))
54 break;
56 if ((err = OpLockFile(fl, &path[1], path[0], access, &lock)) == 0)
57 res = (LONG)MKBADDR(lock);
59 break;
62 case ACTION_FREE_LOCK: {
63 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
65 D(bug("[fat] FREE_LOCK: lock 0x%08x (dir %ld/%ld)\n",
66 pkt->dp_Arg1,
67 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0));
69 OpUnlockFile(fl);
71 res = DOSTRUE;
72 break;
75 case ACTION_COPY_DIR:
76 case ACTION_COPY_DIR_FH: {
77 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1), *lock;
79 D(bug("[fat] COPY_DIR: lock 0x%08x (dir %ld/%ld)\n",
80 pkt->dp_Arg1,
81 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0));
83 if ((err = TestLock(fl)))
84 break;
86 if ((err = OpCopyLock(fl, &lock)) == 0)
87 res = (LONG)MKBADDR(lock);
89 break;
92 case ACTION_PARENT:
93 case ACTION_PARENT_FH: {
94 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1), *lock;
96 D(bug("[fat] ACTION_PARENT: lock 0x%08x (dir %ld/%ld)\n",
97 pkt->dp_Arg1,
98 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0));
100 if ((err = TestLock(fl)))
101 break;
103 if ((err = OpLockParent(fl, &lock)) == 0)
104 res = (LONG)MKBADDR(lock);
106 break;
109 case ACTION_SAME_LOCK: {
110 struct ExtFileLock *fl1 = BADDR(pkt->dp_Arg1);
111 struct ExtFileLock *fl2 = BADDR(pkt->dp_Arg2);
113 D(bug("[fat] ACTION_SAME_LOCK: lock #1 0x%08x (dir %ld/%ld) lock #2 0x%08x (dir %ld/%ld)\n",
114 pkt->dp_Arg1,
115 fl1 != NULL ? fl1->gl->dir_cluster : 0, fl1 != NULL ? fl1->gl->dir_entry : 0,
116 pkt->dp_Arg2,
117 fl2 != NULL ? fl2->gl->dir_cluster : 0, fl2 != NULL ? fl2->gl->dir_entry : 0));
119 err = 0;
121 if (fl1 == fl2 || fl1->gl == fl2->gl)
122 res = DOSTRUE;
124 break;
127 case ACTION_EXAMINE_OBJECT:
128 case ACTION_EXAMINE_FH: {
129 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
130 struct FileInfoBlock *fib = BADDR(pkt->dp_Arg2);
132 D(bug("[fat] EXAMINE_OBJECT: lock 0x%08x (dir %ld/%ld)\n",
133 pkt->dp_Arg1,
134 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0));
136 if ((err = TestLock(fl)))
137 break;
139 if ((err = FillFIB(fl, fib)) == 0)
140 res = DOSTRUE;
142 break;
145 case ACTION_EXAMINE_NEXT: {
146 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1), *lock;
147 struct FileInfoBlock *fib = BADDR(pkt->dp_Arg2);
148 struct DirHandle dh;
149 struct DirEntry de;
151 D(bug("[fat] EXAMINE_NEXT: lock 0x%08x (dir %ld/%ld)\n",
152 pkt->dp_Arg1,
153 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0));
155 if ((err = TestLock(fl)))
156 break;
158 if ((err = InitDirHandle(glob->sb, fl->ioh.first_cluster, &dh, FALSE)) != 0)
159 break;
161 dh.cur_index = fib->fib_DiskKey;
163 if ((err = GetNextDirEntry(&dh, &de)) != 0) {
164 if (err == ERROR_OBJECT_NOT_FOUND)
165 err = ERROR_NO_MORE_ENTRIES;
166 ReleaseDirHandle(&dh);
167 break;
170 if ((err = LockFile(fl->ioh.first_cluster, dh.cur_index, SHARED_LOCK, &lock)) != 0) {
171 ReleaseDirHandle(&dh);
172 break;
175 if ((err = FillFIB(lock, fib))) {
176 FreeLock(lock);
177 ReleaseDirHandle(&dh);
178 break;
181 fib->fib_DiskKey = dh.cur_index;
183 FreeLock(lock);
185 ReleaseDirHandle(&dh);
187 res = DOSTRUE;
189 break;
192 case ACTION_FINDINPUT:
193 case ACTION_FINDOUTPUT:
194 case ACTION_FINDUPDATE: {
195 struct FileHandle *fh = BADDR(pkt->dp_Arg1);
196 struct ExtFileLock *fl = BADDR(pkt->dp_Arg2);
197 UBYTE *path = BADDR(pkt->dp_Arg3);
198 struct ExtFileLock *lock;
200 D(bug("[fat] %s: lock 0x%08x (dir %ld/%ld) path '",
201 pkt->dp_Type == ACTION_FINDINPUT ? "FINDINPUT" :
202 pkt->dp_Type == ACTION_FINDOUTPUT ? "FINDOUTPUT" :
203 "FINDUPDATE",
204 pkt->dp_Arg2,
205 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0);
206 RawPutChars(&path[1], path[0]); bug("'\n"));
208 if ((err = TestLock(fl)))
209 break;
211 if ((err = OpOpenFile(fl, &path[1], path[0], pkt->dp_Type, &lock)) != 0)
212 break;
214 fh->fh_Arg1 = (LONG)MKBADDR(lock);
215 fh->fh_Port = DOSFALSE;
217 res = DOSTRUE;
219 break;
222 case ACTION_READ: {
223 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
224 APTR buffer = (APTR)pkt->dp_Arg2;
225 ULONG want = pkt->dp_Arg3;
227 D(bug("[fat] READ: lock 0x%08x (dir %ld/%ld pos %ld) want %ld\n",
228 pkt->dp_Arg1,
229 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0,
230 fl->pos,
231 want));
233 if ((err = TestLock(fl))) {
234 res = -1;
235 break;
238 if ((err = OpRead(fl, buffer, want, &res)) != 0)
239 res = -1;
241 break;
244 case ACTION_WRITE: {
245 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
246 APTR buffer = (APTR)pkt->dp_Arg2;
247 ULONG want = pkt->dp_Arg3;
249 D(bug("[fat] WRITE: lock 0x%08x (dir %ld/%ld pos %ld) want %ld\n",
250 pkt->dp_Arg1,
251 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0,
252 fl->pos,
253 want));
255 if ((err = TestLock(fl))) {
256 res = -1;
257 break;
260 if ((err = OpWrite(fl, buffer, want, &res)) != 0)
261 res = -1;
263 break;
266 case ACTION_SEEK: {
267 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
268 LONG offset = pkt->dp_Arg2;
269 ULONG whence = pkt->dp_Arg3;
271 D(bug("[fat] SEEK: lock 0x%08x (dir %ld/%ld pos %ld) offset %ld whence %s\n",
272 pkt->dp_Arg1,
273 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0,
274 fl->pos,
275 offset,
276 whence == OFFSET_BEGINNING ? "BEGINNING" :
277 whence == OFFSET_END ? "END" :
278 whence == OFFSET_CURRENT ? "CURRENT" :
279 "(unknown)"));
281 if ((err = TestLock(fl))) {
282 res = -1;
283 break;
286 res = fl->pos;
287 err = 0;
289 if (whence == OFFSET_BEGINNING &&
290 offset >= 0 &&
291 offset <= fl->gl->size)
292 fl->pos = offset;
293 else if (whence == OFFSET_CURRENT &&
294 offset + fl->pos >= 0 &&
295 offset + fl->pos <= fl->gl->size)
296 fl->pos += offset;
297 else if (whence == OFFSET_END
298 && offset <= 0
299 && fl->gl->size + offset >= 0)
300 fl->pos = fl->gl->size + offset;
301 else {
302 res = -1;
303 err = ERROR_SEEK_ERROR;
306 break;
309 case ACTION_SET_FILE_SIZE: {
310 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
311 LONG offset = pkt->dp_Arg2;
312 LONG whence = pkt->dp_Arg3;
314 D(bug("[fat] SET_FILE_SIZE: lock 0x%08x (dir %ld/%ld pos %ld) offset %ld whence %s\n",
315 pkt->dp_Arg1,
316 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0,
317 fl->pos,
318 offset,
319 whence == OFFSET_BEGINNING ? "BEGINNING" :
320 whence == OFFSET_END ? "END" :
321 whence == OFFSET_CURRENT ? "CURRENT" :
322 "(unknown)"));
324 if ((err = TestLock(fl))) {
325 res = -1;
326 break;
329 if ((err = OpSetFileSize(fl, offset, whence, &res)) != 0)
330 res = -1;
332 break;
335 case ACTION_END: {
336 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
338 D(bug("[fat] END: lock 0x%08x (dir %ld/%ld)\n",
339 pkt->dp_Arg1,
340 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0));
342 if ((err = TestLock(fl)))
343 break;
345 FreeLock(fl);
347 res = DOSTRUE;
348 break;
351 case ACTION_IS_FILESYSTEM:
352 D(bug("[fat] IS_FILESYSTEM\n"));
354 res = DOSTRUE;
355 break;
357 case ACTION_CURRENT_VOLUME: {
358 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
360 D(bug("[fat] CURRENT_VOLUME: lock 0x%08x\n",
361 pkt->dp_Arg1));
363 res = (LONG)((fl) ? fl->fl_Volume : ((glob->sb != NULL) ? MKBADDR(glob->sb->doslist) : NULL));
364 break;
367 case ACTION_INFO:
368 case ACTION_DISK_INFO: {
369 struct InfoData *id;
371 if (pkt->dp_Type == ACTION_INFO) {
372 struct FileLock *fl = BADDR(pkt->dp_Arg1);
374 D(bug("[fat] INFO: lock 0x%08x\n",
375 pkt->dp_Arg1));
377 if (fl && (glob->sb == NULL || fl->fl_Volume != MKBADDR(glob->sb->doslist))) {
378 err = ERROR_DEVICE_NOT_MOUNTED;
379 break;
382 id = BADDR(pkt->dp_Arg2);
384 else {
385 D(bug("[fat] DISK_INFO\n"));
387 id = BADDR(pkt->dp_Arg1);
390 FillDiskInfo(id);
392 res = DOSTRUE;
393 break;
396 case ACTION_INHIBIT: {
397 LONG inhibit = pkt->dp_Arg1;
399 D(bug("[fat] INHIBIT: %sinhibit\n",
400 inhibit == DOSTRUE ? "" : "un"));
402 if (inhibit == DOSTRUE) {
403 glob->disk_inhibited++;
404 if (glob->disk_inhibited == 1)
405 DoDiskRemove();
407 else if (glob->disk_inhibited) {
408 glob->disk_inhibited--;
409 if (glob->disk_inhibited == 0)
410 ProcessDiskChange();
413 res = DOSTRUE;
414 break;
417 case ACTION_DIE: {
418 D(bug("[fat] DIE\n"));
420 if (glob->sblist != NULL || (glob->sb != NULL && glob->sb->doslist->dol_misc.dol_volume.dol_LockList != NULL)) {
421 D(bug("\tThere are some locks/volumes left. Shutting down is not possible\n"));
422 err = ERROR_OBJECT_IN_USE;
423 break;
426 D(bug("\tNo locks pending. Shutting down the handler\n"));
428 DoDiskRemove(); /* risky, because of async. volume remove, but works */
430 glob->quit = TRUE;
431 glob->devnode->dol_Task = NULL;
433 res = DOSTRUE;
434 break;
437 #if 0
438 /* XXX AROS needs these ACTION_ headers defined in dos/dosextens.h */
440 case ACTION_GET_DISK_FSSM: {
441 D(bug("\nGot ACTION_GET_DISK_FSSM\n"));
443 res = (ULONG) glob->fssm;
444 break;
447 case ACTION_FREE_DISK_FSSM: {
448 D(bug("\nGot ACTION_FREE_DISK_FSSM\n"));
450 res = DOSTRUE;
451 break;
454 #endif
456 case ACTION_DISK_CHANGE: { /* internal */
457 struct DosList *vol = (struct DosList *)pkt->dp_Arg2;
458 ULONG type = pkt->dp_Arg3;
460 D(bug("[fat] DISK_CHANGE [INTERNAL]\n"));
462 if (pkt->dp_Arg1 == ID_FAT_DISK) { /* security check */
464 if (AttemptLockDosList(LDF_VOLUMES|LDF_WRITE)) {
466 if (type == ACTION_VOLUME_ADD) {
467 AddDosEntry(vol);
468 UnLockDosList(LDF_VOLUMES|LDF_WRITE);
470 SendEvent(IECLASS_DISKINSERTED);
472 D(bug("\tVolume added successfuly\n"));
474 else if (type == ACTION_VOLUME_REMOVE) {
475 RemDosEntry(vol);
476 FreeVecPooled(glob->mempool, vol);
477 UnLockDosList(LDF_VOLUMES|LDF_WRITE);
479 SendEvent(IECLASS_DISKREMOVED);
481 D(bug("\tVolume removed successfuly.\n"));
484 FreeDosObject(DOS_STDPKT, pkt); /* cleanup */
486 pkt = NULL;
487 D(bug("Packet destroyed\n"));
490 else {
491 D(bug("\tDosList is locked\n"));
492 Delay(5);
493 PutMsg(glob->ourport, pkt->dp_Link);
494 pkt = NULL;
495 D(bug("Message moved to the end of the queue\n"));
498 else
499 err = ERROR_OBJECT_WRONG_TYPE;
501 break;
504 case ACTION_RENAME_DISK: {
505 UBYTE *name = BADDR(pkt->dp_Arg1);
507 D(bug("[fat] RENAME_DISK: name '"); RawPutChars(&name[1], name[0]); bug("'\n"));
509 if (glob->sb->doslist == NULL) {
510 err = glob->disk_inserted ? ERROR_NOT_A_DOS_DISK : ERROR_NO_DISK;
511 break;
514 while (! AttemptLockDosList(LDF_VOLUMES | LDF_WRITE))
515 ProcessPackets();
517 err = SetVolumeName(glob->sb, name);
518 UnLockDosList(LDF_VOLUMES | LDF_WRITE);
519 if (err != 0)
520 break;
522 SendEvent(IECLASS_DISKINSERTED);
524 res = DOSTRUE;
526 break;
529 case ACTION_DELETE_OBJECT: {
530 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1);
531 UBYTE *name = BADDR(pkt->dp_Arg2);
533 D(bug("[fat] DELETE_OBJECT: lock 0x%08x (dir %ld/%ld) path '",
534 pkt->dp_Arg1,
535 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0);
536 RawPutChars(&name[1], name[0]); bug("'\n"));
538 if ((err = TestLock(fl)))
539 break;
541 err = OpDeleteFile(fl, &name[1], name[0]);
543 break;
546 case ACTION_RENAME_OBJECT: {
547 struct ExtFileLock *sfl = BADDR(pkt->dp_Arg1), *dfl = BADDR(pkt->dp_Arg3);
548 UBYTE *sname = BADDR(pkt->dp_Arg2), *dname = BADDR(pkt->dp_Arg4);
550 D(bug("[fat] RENAME_OBJECT: srclock 0x%08x (dir %ld/%ld) name '",
551 pkt->dp_Arg1,
552 sfl != NULL ? sfl->gl->dir_cluster : 0, sfl != NULL ? sfl->gl->dir_entry : 0);
553 RawPutChars(&sname[1], sname[0]); bug("' destlock 0x%08x (dir %ld/%ld) name '",
554 pkt->dp_Arg3,
555 dfl != NULL ? dfl->gl->dir_cluster : 0, dfl != NULL ? dfl->gl->dir_entry : 0);
556 RawPutChars(&dname[1], dname[0]); bug("'\n"));
558 if ((err = TestLock(sfl)) != 0 || (err = TestLock(dfl)) != 0)
559 break;
561 err = OpRenameFile(sfl, &sname[1], sname[0], dfl, &dname[1], dname[0]);
563 break;
566 case ACTION_CREATE_DIR: {
567 struct ExtFileLock *fl = BADDR(pkt->dp_Arg1), *new;
568 UBYTE *name = BADDR(pkt->dp_Arg2);
570 D(bug("[fat] CREATE_DIR: lock 0x%08x (dir %ld/%ld) name '",
571 pkt->dp_Arg1,
572 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0);
573 RawPutChars(&name[1], name[0]); bug("'\n"));
575 if ((err = TestLock(fl)))
576 break;
578 if ((err = OpCreateDir(fl, &name[1], name[0], &new)) == 0)
579 res = (LONG)MKBADDR(new);
581 break;
584 case ACTION_SET_PROTECT: {
585 struct ExtFileLock *fl = BADDR(pkt->dp_Arg2);
586 UBYTE *name = BADDR(pkt->dp_Arg3);
587 ULONG prot = pkt->dp_Arg4;
589 D(bug("[fat] SET_PROTECT: lock 0x%08x (dir %ld/%ld) name '", pkt->dp_Arg2,
590 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0);
591 RawPutChars(&name[1], name[0]); bug("' prot 0x%08x\n", prot));
592 if ((err = TestLock(fl)))
593 break;
595 err = OpSetProtect(fl, &name[1], name[0], prot);
597 break;
600 case ACTION_SET_DATE: {
601 struct ExtFileLock *fl = BADDR(pkt->dp_Arg2);
602 UBYTE *name = BADDR(pkt->dp_Arg3);
603 struct DateStamp *ds = (struct DateStamp *)pkt->dp_Arg4;
605 #if defined(DEBUG) && DEBUG != 0
607 struct DateTime dt;
608 char datestr[LEN_DATSTRING];
610 dt.dat_Stamp = *ds;
611 dt.dat_Format = FORMAT_DOS;
612 dt.dat_Flags = 0;
613 dt.dat_StrDay = NULL;
614 dt.dat_StrDate = datestr;
615 dt.dat_StrTime = NULL;
616 DateToStr(&dt);
618 D(bug("[fat] SET_DATE: lock 0x%08x (dir %ld/%ld) name '",
619 pkt->dp_Arg2,
620 fl != NULL ? fl->gl->dir_cluster : 0, fl != NULL ? fl->gl->dir_entry : 0);
621 RawPutChars(&name[1], name[0]); bug("' ds '%s'\n", datestr));
623 #endif
625 if ((err = TestLock(fl)))
626 break;
628 err = OpSetDate(fl, &name[1], name[0], ds);
630 break;
633 case ACTION_ADD_NOTIFY: {
634 struct NotifyRequest *nr = (struct NotifyRequest *)pkt->dp_Arg1;
636 D(bug("[fat] ADD_NOTIFY: nr 0x%08x name '%s'\n", nr, nr->nr_FullName));
638 err = OpAddNotify(nr);
640 break;
643 case ACTION_REMOVE_NOTIFY: {
644 struct NotifyRequest *nr = (struct NotifyRequest *)pkt->dp_Arg1;
646 D(bug("[fat] REMOVE_NOTIFY: nr 0x%08x name '%s'\n", nr, nr->nr_FullName));
648 err = OpRemoveNotify(nr);
650 break;
653 default:
654 D(bug("[fat] got unknown packet type %ld\n", pkt->dp_Type));
656 err = ERROR_ACTION_NOT_KNOWN;
659 if (pkt != NULL) {
660 D(bug("[fat] replying to packet: result 0x%x, error 0x%x\n", res, err));
662 rp = pkt->dp_Port;
664 pkt->dp_Port = glob->ourport;
665 pkt->dp_Res1 = res;
666 pkt->dp_Res2 = err;
668 PutMsg(rp, pkt->dp_Link);
671 #if defined(DEBUG_CACHESTATS) && DEBUG_CACHESTATS != 0
672 cache_stats(glob->sb->cache);
673 #endif