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.
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>
25 #include "fat_protos.h"
27 void ProcessPackets(void) {
29 struct DosPacket
*pkt
;
32 while ((msg
= GetMsg(glob
->ourport
)) != NULL
) {
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",
46 fl
!= NULL
? fl
->dir_cluster
: 0, fl
!= NULL
? fl
->dir_entry
: 0,
48 pkt
->dp_Arg3
== EXCLUSIVE_LOCK
? "EXCLUSIVE" : "SHARED"));
50 if ((err
= TestLock(fl
)))
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
);
63 D(bug("\tLocking root directory.\n"));
64 err
= LockRoot(access
, &res
);
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",
75 fl
!= NULL
? fl
->dir_cluster
: 0, fl
!= NULL
? fl
->dir_entry
: 0));
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",
90 fl
!= NULL
? fl
->dir_cluster
: 0, fl
!= NULL
? fl
->dir_entry
: 0));
92 if ((err
= TestLock(fl
)))
96 err
= CopyLock(fl
, &res
);
98 err
= LockRoot(SHARED_LOCK
, &res
);
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",
109 fl
!= NULL
? fl
->dir_cluster
: 0, fl
!= NULL
? fl
->dir_entry
: 0));
111 if ((err
= TestLock(fl
)))
114 if (fl
&& fl
->fl_Key
!= FAT_ROOTDIR_MARK
)
115 err
= LockParent(fl
, SHARED_LOCK
, &res
);
117 err
= ERROR_OBJECT_NOT_FOUND
;
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",
128 fl1
!= NULL
? fl1
->dir_cluster
: 0, fl1
!= NULL
? fl1
->dir_entry
: 0,
130 fl2
!= NULL
? fl2
->dir_cluster
: 0, fl2
!= NULL
? fl2
->dir_entry
: 0));
134 if (fl1
== fl2
|| ((fl1
->fl_Volume
== fl2
->fl_Volume
) && fl1
->fl_Key
== fl2
->fl_Key
))
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",
147 fl
!= NULL
? fl
->dir_cluster
: 0, fl
!= NULL
? fl
->dir_entry
: 0));
149 if ((err
= TestLock(fl
)))
152 if ((err
= FillFIB(fl
, fib
)) == 0)
158 case ACTION_EXAMINE_NEXT
: {
159 struct ExtFileLock
*fl
= BADDR(pkt
->dp_Arg1
);
160 struct FileInfoBlock
*fib
= BADDR(pkt
->dp_Arg2
);
163 BPTR b
; struct ExtFileLock
*temp_lock
;
165 D(bug("[fat] EXAMINE_NEXT: lock 0x%08x (dir %ld/%ld)\n",
167 fl
!= NULL
? fl
->dir_cluster
: 0, fl
!= NULL
? fl
->dir_entry
: 0));
169 if ((err
= TestLock(fl
)))
172 if ((err
= InitDirHandle(glob
->sb
, fl
->ioh
.first_cluster
, &dh
)))
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
);
184 if ((err
= LockFile(dh
.cur_index
, fl
->ioh
.first_cluster
, SHARED_LOCK
, &b
))) {
185 ReleaseDirHandle(&dh
);
188 temp_lock
= BADDR(b
);
190 if ((err
= FillFIB(temp_lock
, fib
))) {
192 ReleaseDirHandle(&dh
);
196 fib
->fib_DiskKey
= dh
.cur_index
;
200 ReleaseDirHandle(&dh
);
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" :
220 fl
!= NULL
? fl
->dir_cluster
: 0, fl
!= NULL
? fl
->dir_entry
: 0,
223 if ((err
= TestLock(fl
)))
226 if ((err
= OpOpenFile(fl
, &path
[1], path
[0], pkt
->dp_Type
, &lock
)) != 0)
229 fh
->fh_Arg1
= MKBADDR(lock
);
230 fh
->fh_Port
= DOSFALSE
;
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",
244 fl
!= NULL
? fl
->dir_cluster
: 0, fl
!= NULL
? fl
->dir_entry
: 0,
248 if ((err
= TestLock(fl
))) {
253 if ((err
= OpRead(fl
, buffer
, want
, &res
)) != 0)
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",
266 fl
!= NULL
? fl
->dir_cluster
: 0, fl
!= NULL
? fl
->dir_entry
: 0,
270 if ((err
= TestLock(fl
))) {
275 if ((err
= OpWrite(fl
, buffer
, want
, &res
)) != 0)
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",
288 fl
!= NULL
? fl
->dir_cluster
: 0, fl
!= NULL
? fl
->dir_entry
: 0,
291 whence
== OFFSET_BEGINNING
? "BEGINNING" :
292 whence
== OFFSET_END
? "END" :
293 whence
== OFFSET_CURRENT
? "CURRENT" :
295 if ((err
= TestLock(fl
))) {
303 if (whence
== OFFSET_BEGINNING
&& offset
>= 0 && offset
<= fl
->size
)
305 else if (whence
== OFFSET_CURRENT
&& offset
+ fl
->pos
>= 0 && offset
+ fl
->pos
<= fl
->size
)
307 else if (whence
== OFFSET_END
&& offset
<= 0 && fl
->size
+ offset
>= 0)
308 fl
->pos
= fl
->size
+ offset
;
311 err
= ERROR_SEEK_ERROR
;
318 struct ExtFileLock
*fl
= BADDR(pkt
->dp_Arg1
);
320 D(bug("[fat] END: lock 0x%08x (dir %ld/%ld)\n",
322 fl
!= NULL
? fl
->dir_cluster
: 0, fl
!= NULL
? fl
->dir_entry
: 0));
324 if ((err
= TestLock(fl
)))
333 case ACTION_IS_FILESYSTEM
:
334 D(bug("[fat] IS_FILESYSTEM\n"));
339 case ACTION_CURRENT_VOLUME
: {
340 struct ExtFileLock
*fl
= BADDR(pkt
->dp_Arg1
);
342 D(bug("[fat] CURRENT_VOLUME: lock 0x%08x\n",
345 res
= (fl
) ? fl
->fl_Volume
: ((glob
->sb
!= NULL
) ? MKBADDR(glob
->sb
->doslist
) : NULL
);
350 case ACTION_DISK_INFO
: {
353 if (pkt
->dp_Type
== ACTION_INFO
) {
354 struct FileLock
*fl
= BADDR(pkt
->dp_Arg1
);
356 D(bug("[fat] INFO: lock 0x%08x\n",
359 if (fl
&& (glob
->sb
== NULL
|| fl
->fl_Volume
!= MKBADDR(glob
->sb
->doslist
))) {
360 err
= ERROR_DEVICE_NOT_MOUNTED
;
364 id
= BADDR(pkt
->dp_Arg2
);
367 D(bug("[fat] DISK_INFO\n"));
369 id
= BADDR(pkt
->dp_Arg1
);
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)
390 glob
->disk_inhibited
--;
391 if (glob
->disk_inhibited
== 0)
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
;
408 D(bug("\tNo locks pending. Shutting down the handler\n"));
410 DoDiskRemove(); /* risky, because of async. volume remove, but works */
413 glob
->devnode
->dol_Task
= NULL
;
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
;
429 case ACTION_FREE_DISK_FSSM
: {
430 D(bug("\nGot ACTION_FREE_DISK_FSSM\n"));
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
) {
450 UnLockDosList(LDF_VOLUMES
|LDF_WRITE
);
452 SendEvent(IECLASS_DISKINSERTED
);
454 D(bug("\tVolume added successfuly\n"));
456 else if (type
== ACTION_VOLUME_REMOVE
) {
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 */
469 D(bug("Packet destroyed\n"));
473 D(bug("\tDosList is locked\n"));
475 PutMsg(glob
->ourport
, pkt
->dp_Link
);
477 D(bug("Message moved to the end of the queue\n"));
481 err
= ERROR_OBJECT_WRONG_TYPE
;
486 case ACTION_RENAME_DISK
: {
487 UBYTE
*name
= BADDR(pkt
->dp_Arg1
);
489 D(bug("[fat] RENAME_DISK: name '%.*s'\n",
492 if (glob
->sb
->doslist
== NULL
) {
493 err
= glob
->disk_inserted
? ERROR_NOT_A_DOS_DISK
: ERROR_NO_DISK
;
497 while (! AttemptLockDosList(LDF_VOLUMES
| LDF_WRITE
))
500 if ((err
= SetVolumeName(glob
->sb
, name
)) != 0)
503 UnLockDosList(LDF_VOLUMES
| LDF_WRITE
);
505 SendEvent(IECLASS_DISKINSERTED
);
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",
518 fl
!= NULL
? fl
->dir_cluster
: 0, fl
!= NULL
? fl
->dir_entry
: 0,
521 if ((err
= TestLock(fl
)))
524 err
= OpDeleteFile(fl
, &name
[1], name
[0]);
529 case ACTION_RENAME_OBJECT
:
530 D(bug("[fat] RENAME_OBJECT [WRITE]\n"));
531 err
= ERROR_DISK_WRITE_PROTECTED
;
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",
540 fl
!= NULL
? fl
->dir_cluster
: 0, fl
!= NULL
? fl
->dir_entry
: 0,
543 if ((err
= TestLock(fl
)))
546 if ((err
= OpCreateDir(fl
, &name
[1], name
[0], &new)) == 0)
552 case ACTION_SET_FILE_SIZE
:
553 D(bug("[fat] SET_FILE_SIZE [WRITE]\n"));
554 err
= ERROR_DISK_WRITE_PROTECTED
;
558 D(bug("[fat] got unknown packet type %ld\n", pkt
->dp_Type
));
560 err
= ERROR_ACTION_NOT_KNOWN
;
564 D(bug("[fat] replying to packet: result 0x%x, error 0x%x\n", res
, err
));
568 pkt
->dp_Port
= glob
->ourport
;
572 PutMsg(rp
, pkt
->dp_Link
);