r26035@plastic: rob | 2007-04-16 16:19:31 +1000
[cake.git] / workbench / fs / fat / lock.c
blob07515709dc8b5ef92e2b65e0de41780f594e9645
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 <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>
23 #include <string.h>
25 #include "fat_fs.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)
31 return ERROR_NO_DISK;
32 else
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;
42 return 0;
45 LONG TryLockObj(struct ExtFileLock *fl, UBYTE *name, LONG namelen, LONG access, BPTR *result) {
46 LONG err = ERROR_OBJECT_NOT_FOUND;
47 struct DirHandle dh;
48 struct DirEntry de;
49 ULONG dir_cluster;
50 int i;
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++)
60 if (name[i] == ':') {
61 namelen -= (i+1);
62 name = &name[i+1];
63 break;
66 InitDirHandle(glob->sb, dir_cluster, &dh);
67 err = GetDirEntryByPath(&dh, name, namelen, &de);
69 if (err == 0) {
70 if (FIRST_FILE_CLUSTER(&de) == 0)
71 err = LockRoot(access, result);
72 else
73 err = LockFile(de.index, dh.ioh.first_cluster, access, result);
76 ReleaseDirHandle(&dh);
78 return err;
81 LONG LockFile(ULONG entry, ULONG cluster, LONG axs, BPTR *res) {
82 struct ExtFileLock *fl;
83 struct DirHandle dh;
84 struct DirEntry de;
85 ULONG len;
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);
95 fl->fl_Access = axs;
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);
118 *res = MKBADDR(fl);
119 return 0;
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;
130 fl->fl_Access = axs;
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;
141 fl->size = 0;
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);
150 *res = MKBADDR(fl);
151 return 0;
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);
183 *res = MKBADDR(fl);
184 return 0;
187 LONG LockParent(struct ExtFileLock *fl, LONG axs, BPTR *res) {
188 LONG err;
189 struct DirHandle dh;
190 struct DirEntry de;
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);
201 return err;
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
209 * LockFile() */
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;
215 break;
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);
226 break;
230 ReleaseDirHandle(&dh);
231 return err;
234 LONG FreeLockSB(struct ExtFileLock *fl, struct FSSuper *sb) {
235 LONG found = FALSE;
237 if (sb == NULL)
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;
244 found = TRUE;
246 else {
247 struct ExtFileLock *prev = NULL, *ptr = BADDR(sb->doslist->dol_misc.dol_volume.dol_LockList);
249 while (ptr != NULL) {
250 if (ptr == fl) {
251 prev->fl_Link = fl->fl_Link;
252 found = TRUE;
253 break;
255 prev = ptr;
256 ptr = BADDR(ptr->fl_Link);
260 if (found) {
261 kprintf("\tFreeing lock.\n");
263 fl->fl_Task = NULL;
265 if (fl->ioh.block != NULL)
266 cache_put_block(sb->cache, fl->ioh.block, 0);
268 FreeVecPooled(glob->mempool, fl);
270 return 0;
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)
280 return;
282 while (ptr != NULL) {
283 if (FreeLockSB(fl, ptr) == 0)
284 break;
286 prev = ptr;
287 ptr = ptr->next;
290 if (ptr) {
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);
296 ptr->doslist = NULL;
297 FreeFATSuper(ptr);
299 if (prev)
300 prev->next = ptr->next;
301 else
302 glob->sblist = ptr->next;
304 FreeVecPooled(glob->mempool, ptr);