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 <exec/memory.h>
16 #include <dos/dosextens.h>
17 #include <dos/filehandler.h>
19 #include <proto/exec.h>
20 #include <proto/dos.h>
21 #include <proto/utility.h>
26 #include "fat_protos.h"
28 LONG
TestLock(struct ExtFileLock
*fl
) {
29 if (fl
== 0 && glob
->sb
== NULL
) {
30 if (glob
->disk_inserted
== FALSE
)
33 return ERROR_NOT_A_DOS_DISK
;
36 if (glob
->sb
== NULL
|| glob
->disk_inhibited
|| (fl
&& fl
->fl_Volume
!= MKBADDR(glob
->sb
->doslist
)))
37 return ERROR_DEVICE_NOT_MOUNTED
;
39 if (fl
&& fl
->magic
!= ID_FAT_DISK
)
40 return ERROR_OBJECT_WRONG_TYPE
;
45 LONG
TryLockObj(struct ExtFileLock
*fl
, UBYTE
*name
, LONG namelen
, LONG access
, BPTR
*result
) {
46 LONG err
= ERROR_OBJECT_NOT_FOUND
;
52 if (fl
&& (fl
->attr
& ATTR_DIRECTORY
) == 0)
53 return ERROR_OBJECT_WRONG_TYPE
;
55 dir_cluster
= (fl
) ? fl
->ioh
.first_cluster
: 0;
57 kprintf("\tSearching for: "); knprints(name
, namelen
);
59 for (i
= 0; i
< namelen
; i
++)
66 InitDirHandle(glob
->sb
, dir_cluster
, &dh
);
67 err
= GetDirEntryByPath(&dh
, name
, namelen
, &de
);
70 if (FIRST_FILE_CLUSTER(&de
) == 0)
71 err
= LockRoot(access
, result
);
73 err
= LockFile(de
.index
, dh
.ioh
.first_cluster
, access
, result
);
76 ReleaseDirHandle(&dh
);
81 LONG
LockFile(ULONG entry
, ULONG cluster
, LONG axs
, BPTR
*res
) {
82 struct ExtFileLock
*fl
;
87 kprintf("\tLockFile entry %ld cluster %ld\n", entry
, cluster
);
89 if ((fl
= AllocVecPooled(glob
->mempool
, sizeof(struct ExtFileLock
))) == NULL
)
90 return ERROR_NO_FREE_STORE
;
92 InitDirHandle(glob
->sb
, cluster
, &dh
);
93 GetDirEntry(&dh
, entry
, &de
);
96 fl
->fl_Task
= glob
->ourport
;
97 fl
->fl_Volume
= MKBADDR(glob
->sb
->doslist
);
98 fl
->fl_Link
= glob
->sb
->doslist
->dol_misc
.dol_volume
.dol_LockList
;
99 fl
->magic
= ID_FAT_DISK
;
101 glob
->sb
->doslist
->dol_misc
.dol_volume
.dol_LockList
= MKBADDR(fl
);
103 fl
->dir_entry
= entry
;
104 fl
->dir_cluster
= cluster
;
105 fl
->attr
= de
.e
.entry
.attr
;
106 fl
->size
= AROS_LE2LONG(de
.e
.entry
.file_size
);
108 fl
->ioh
.sb
= glob
->sb
;
109 fl
->ioh
.first_cluster
= FIRST_FILE_CLUSTER(&de
);
110 fl
->ioh
.block
= NULL
;
111 RESET_HANDLE(&(fl
->ioh
));
113 GetDirShortName(&de
, &(fl
->name
[1]), &len
); fl
->name
[0] = (UBYTE
) len
;
114 GetDirLongName(&de
, &(fl
->name
[1]), &len
); fl
->name
[0] = (UBYTE
) len
;
116 ReleaseDirHandle(&dh
);
122 LONG
LockRoot(LONG axs
, BPTR
*res
) {
123 struct ExtFileLock
*fl
;
125 kprintf("\tLockRoot()\n");
127 if ((fl
= AllocVecPooled(glob
->mempool
, sizeof(struct ExtFileLock
))) == NULL
)
128 return ERROR_NO_FREE_STORE
;
131 fl
->fl_Task
= glob
->ourport
;
132 fl
->fl_Volume
= MKBADDR(glob
->sb
->doslist
);
133 fl
->fl_Link
= glob
->sb
->doslist
->dol_misc
.dol_volume
.dol_LockList
;
134 fl
->magic
= ID_FAT_DISK
;
136 glob
->sb
->doslist
->dol_misc
.dol_volume
.dol_LockList
= MKBADDR(fl
);
138 fl
->dir_entry
= FAT_ROOTDIR_MARK
;
139 fl
->dir_cluster
= FAT_ROOTDIR_MARK
;
140 fl
->attr
= ATTR_DIRECTORY
;
143 fl
->ioh
.sb
= glob
->sb
;
144 fl
->ioh
.first_cluster
= 0;
145 fl
->ioh
.block
= NULL
;
146 RESET_HANDLE(&(fl
->ioh
));
148 CopyMem(glob
->sb
->volume
.name
, fl
->name
, 32);
154 LONG
CopyLock(struct ExtFileLock
*src_fl
, BPTR
*res
) {
155 struct ExtFileLock
*fl
;
157 if (src_fl
->fl_Access
== EXCLUSIVE_LOCK
)
158 return ERROR_OBJECT_IN_USE
;
160 if ((fl
= AllocVecPooled(glob
->mempool
, sizeof(struct ExtFileLock
))) == NULL
)
161 return ERROR_NO_FREE_STORE
;
163 fl
->fl_Access
= src_fl
->fl_Access
;
164 fl
->fl_Task
= glob
->ourport
;
165 fl
->fl_Volume
= MKBADDR(glob
->sb
->doslist
);
166 fl
->fl_Link
= glob
->sb
->doslist
->dol_misc
.dol_volume
.dol_LockList
;
167 fl
->magic
= ID_FAT_DISK
;
169 glob
->sb
->doslist
->dol_misc
.dol_volume
.dol_LockList
= MKBADDR(fl
);
171 fl
->dir_entry
= src_fl
->dir_entry
;
172 fl
->dir_cluster
= src_fl
->dir_cluster
;
173 fl
->attr
= src_fl
->attr
;
174 fl
->size
= src_fl
->size
;
176 fl
->ioh
.sb
= glob
->sb
;
177 fl
->ioh
.first_cluster
= src_fl
->ioh
.first_cluster
;
178 fl
->ioh
.block
= NULL
;
179 RESET_HANDLE(&(fl
->ioh
));
181 memcpy(fl
->name
, src_fl
->name
, 108);
187 LONG
LockParent(struct ExtFileLock
*fl
, LONG axs
, BPTR
*res
) {
191 ULONG parent_cluster
;
193 /* if we're in the root directory, then the root is our parent */
194 if (fl
->dir_cluster
== glob
->sb
->rootdir_cluster
)
195 return LockRoot(axs
, res
);
197 /* get the parent dir */
198 InitDirHandle(glob
->sb
, fl
->dir_cluster
, &dh
);
199 if ((err
= GetDirEntryByPath(&dh
, "/", 1, &de
)) != 0) {
200 ReleaseDirHandle(&dh
);
204 /* and its cluster */
205 parent_cluster
= FIRST_FILE_CLUSTER(&de
);
207 /* then we go through the parent dir, looking for a link back to us. we do
208 * this so that we have an entry with the proper name for copying by
210 InitDirHandle(glob
->sb
, parent_cluster
, &dh
);
211 while ((err
= GetDirEntry(&dh
, dh
.cur_index
+ 1, &de
)) == 0) {
212 /* don't go past the end */
213 if (de
.e
.entry
.name
[0] == 0x00) {
214 err
= ERROR_OBJECT_NOT_FOUND
;
218 /* we found it if its not empty, and its not the volume id or a long
219 * name, and it is a directory, and it does point to us */
220 if (de
.e
.entry
.name
[0] != 0xe5 &&
221 !(de
.e
.entry
.attr
& ATTR_VOLUME_ID
) &&
222 de
.e
.entry
.attr
& ATTR_DIRECTORY
&&
223 FIRST_FILE_CLUSTER(&de
) == fl
->dir_cluster
) {
225 err
= LockFile(dh
.cur_index
, parent_cluster
, axs
, res
);
230 ReleaseDirHandle(&dh
);
234 LONG
FreeLockSB(struct ExtFileLock
*fl
, struct FSSuper
*sb
) {
238 return ERROR_OBJECT_NOT_FOUND
;
239 if (fl
->magic
!= ID_FAT_DISK
)
240 return ERROR_OBJECT_WRONG_TYPE
;
242 if (fl
== BADDR(sb
->doslist
->dol_misc
.dol_volume
.dol_LockList
)) {
243 sb
->doslist
->dol_misc
.dol_volume
.dol_LockList
= fl
->fl_Link
;
247 struct ExtFileLock
*prev
= NULL
, *ptr
= BADDR(sb
->doslist
->dol_misc
.dol_volume
.dol_LockList
);
249 while (ptr
!= NULL
) {
251 prev
->fl_Link
= fl
->fl_Link
;
256 ptr
= BADDR(ptr
->fl_Link
);
261 kprintf("\tFreeing lock.\n");
265 if (fl
->ioh
.block
!= NULL
)
266 cache_put_block(sb
->cache
, fl
->ioh
.block
, 0);
268 FreeVecPooled(glob
->mempool
, fl
);
273 return ERROR_OBJECT_NOT_FOUND
;
276 void FreeLock(struct ExtFileLock
*fl
) {
277 struct FSSuper
*ptr
= glob
->sblist
, *prev
=NULL
;
279 if (FreeLockSB(fl
, glob
->sb
) == 0)
282 while (ptr
!= NULL
) {
283 if (FreeLockSB(fl
, ptr
) == 0)
291 if (ptr
->doslist
->dol_misc
.dol_volume
.dol_LockList
== NULL
) { /* check if the device can be removed */
292 kprintf("\tRemoving disk completely\n");
294 SendVolumePacket(ptr
->doslist
, ACTION_VOLUME_REMOVE
);
300 prev
->next
= ptr
->next
;
302 glob
->sblist
= ptr
->next
;
304 FreeVecPooled(glob
->mempool
, ptr
);