c862dca54b675fb32466fe1912e57f4c445c4ec2
[tpg/acess2.git] / KernelLand / Modules / Filesystems / FAT / nodecache.c
1 /*
2  * Acess2 FAT12/16/32 Driver
3  * - By John Hodge (thePowersGang)
4  *
5  * nodecache.c
6  * - FAT-Specific node caching
7  */
8 #include <acess.h>
9 #include <vfs.h>
10 #include "common.h"
11
12 // === PROTOTYPES ===
13 extern tVFS_Node        *FAT_int_CacheNode(tFAT_VolInfo *Disk, const tVFS_Node *Node);
14
15 // === CODE ===
16 /**
17  * \brief Creates a tVFS_Node structure for a given file entry
18  * \param Parent        Parent directory VFS node
19  * \param Entry File table entry for the new node
20  */
21 tVFS_Node *FAT_int_CreateNode(tVFS_Node *Parent, fat_filetable *Entry)
22 {
23         tVFS_Node       node;
24         tVFS_Node       *ret;
25         tFAT_VolInfo    *disk = Parent->ImplPtr;
26
27         ENTER("pParent pEntry", Parent, Entry);
28         LOG("disk = %p", disk);
29         
30         if( (ret = FAT_int_GetNode(disk, Entry->cluster | (Entry->clusterHi<<16))) ) {
31                 LEAVE('p', ret);
32                 return ret;
33         }
34
35         memset(&node, 0, sizeof(tVFS_Node));
36         
37         // Set Other Data
38         // 0-27: Cluster, 32-59: Parent Cluster
39         node.Inode = Entry->cluster | (Entry->clusterHi<<16) | (Parent->Inode << 32);
40         LOG("node.Inode = %llx", node.Inode);
41         node.ImplInt = 0;
42         // Disk Pointer
43         node.ImplPtr = disk;
44         node.Size = Entry->size;
45         LOG("Entry->size = %i", Entry->size);
46         // root:root
47         node.UID = 0;   node.GID = 0;
48         node.NumACLs = 1;
49         
50         node.Flags = 0;
51         if(Entry->attrib & ATTR_DIRECTORY)      node.Flags |= VFS_FFLAG_DIRECTORY;
52         if(Entry->attrib & ATTR_READONLY) {
53                 node.Flags |= VFS_FFLAG_READONLY;
54                 node.ACLs = &gVFS_ACL_EveryoneRX;       // R-XR-XR-X
55         }
56         else {
57                 node.ACLs = &gVFS_ACL_EveryoneRWX;      // RWXRWXRWX
58         }
59         
60         // Create timestamps
61         node.ATime = timestamp(0,0,0,
62                         ((Entry->adate&0x1F) - 1),      // Days
63                         ((Entry->adate&0x1E0) - 1),     // Months
64                         1980+((Entry->adate&0xFF00)>>8) // Years
65                         );
66         
67         node.CTime = Entry->ctimems * 10;       // Miliseconds
68         node.CTime += timestamp(
69                         ((Entry->ctime&0x1F)<<1),       // Seconds
70                         ((Entry->ctime&0x3F0)>>5),      // Minutes
71                         ((Entry->ctime&0xF800)>>11),    // Hours
72                         ((Entry->cdate&0x1F)-1),                // Days
73                         ((Entry->cdate&0x1E0)-1),               // Months
74                         1980+((Entry->cdate&0xFF00)>>8) // Years
75                         );
76                         
77         node.MTime = timestamp(
78                         ((Entry->mtime&0x1F)<<1),       // Seconds
79                         ((Entry->mtime&0x3F0)>>5),      // Minutes
80                         ((Entry->mtime&0xF800)>>11),    // Hours
81                         ((Entry->mdate&0x1F)-1),                // Days
82                         ((Entry->mdate&0x1E0)-1),               // Months
83                         1980+((Entry->mdate&0xFF00)>>8) // Years
84                         );
85         
86         // Set pointers
87         if(node.Flags & VFS_FFLAG_DIRECTORY) {
88                 //Log_Debug("FAT", "Directory %08x has size 0x%x", node.Inode, node.Size);
89                 node.Type = &gFAT_DirType;      
90                 node.Size = -1;
91         }
92         else {
93                 node.Type = &gFAT_FileType;
94         }
95
96         // TODO: Cache node     
97         ret = FAT_int_CacheNode(disk, &node);
98         LEAVE('p', ret);
99         return ret;
100 }
101
102 tVFS_Node *FAT_int_CreateIncompleteDirNode(tFAT_VolInfo *Disk, Uint32 Cluster)
103 {
104         // If the directory isn't in the cache, what do?
105         // - we want to lock it such that we don't collide, but don't want to put crap data in the cache
106         // - Put a temp node in with a flag that indicates it's incomplete?
107         return NULL;
108 }
109
110 tVFS_Node *FAT_int_GetNode(tFAT_VolInfo *Disk, Uint32 Cluster)
111 {
112         if( Cluster == Disk->rootOffset )
113                 return &Disk->rootNode;
114         Mutex_Acquire(&Disk->lNodeCache);
115         tFAT_CachedNode *cnode;
116
117         for(cnode = Disk->NodeCache; cnode; cnode = cnode->Next)
118         {
119                 if( (cnode->Node.Inode & 0xFFFFFFFF) == Cluster ) {
120                         cnode->Node.ReferenceCount ++;
121                         Mutex_Release(&Disk->lNodeCache);
122                         return &cnode->Node;
123                 }
124         }       
125
126         Mutex_Release(&Disk->lNodeCache);
127         return NULL;
128 }
129
130 tVFS_Node *FAT_int_CacheNode(tFAT_VolInfo *Disk, const tVFS_Node *Node)
131 {
132         tFAT_CachedNode *cnode, *prev = NULL;
133         Mutex_Acquire(&Disk->lNodeCache);
134         
135         for(cnode = Disk->NodeCache; cnode; prev = cnode, cnode = cnode->Next )
136         {
137                 if( cnode->Node.Inode == Node->Inode ) {
138                         cnode->Node.ReferenceCount ++;
139                         Mutex_Release(&Disk->lNodeCache);
140                         return &cnode->Node;
141                 }
142         }
143         
144         cnode = malloc(sizeof(tFAT_CachedNode));
145         cnode->Next = NULL;
146         memcpy(&cnode->Node, Node, sizeof(tVFS_Node));
147         cnode->Node.ReferenceCount = 1;
148         
149         if( prev )
150                 prev->Next = cnode;
151         else
152                 Disk->NodeCache = cnode;
153         
154         Mutex_Release(&Disk->lNodeCache);
155         return &cnode->Node;
156 }
157
158 int FAT_int_DerefNode(tVFS_Node *Node)
159 {
160         tFAT_VolInfo    *Disk = Node->ImplPtr;
161         tFAT_CachedNode *cnode, *prev = NULL;
162          int    bFreed = 0;
163
164         if( Node == &Disk->rootNode )
165                 return 0;
166
167         Mutex_Acquire(&Disk->lNodeCache);
168         Node->ReferenceCount --;
169         for(cnode = Disk->NodeCache; cnode; prev = cnode, cnode = cnode->Next )
170         {
171                 if(Node == &cnode->Node) {
172                         if(prev)
173                                 prev->Next = cnode->Next;
174                         else
175                                 Disk->NodeCache = cnode->Next;
176                         break;
177                 }
178         }
179         if(Node->ReferenceCount == 0 && cnode) {
180                 // Already out of the list :)
181                 free(cnode->Node.Data);
182                 free(cnode);
183                 bFreed = 1;
184         }
185         Mutex_Release(&Disk->lNodeCache);
186         if( !cnode ) {
187                 // Not here?
188                 return -1;
189         }
190         
191         return bFreed;
192 }
193
194 void FAT_int_ClearNodeCache(tFAT_VolInfo *Disk)
195 {
196         // TODO: In theory when this is called, all handles will be closed
197 }

UCC git Repository :: git.ucc.asn.au