Repository navigation
Expand file tree
/
Copy pathFreeSpaceManager.c
More file actions
274 lines (226 loc) · 9.89 KB
/
Copy pathFreeSpaceManager.c
File metadata and controls
274 lines (226 loc) · 9.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
/**************************************************************
* Class:: CSC-415-02 Spring 2024
* Name::Yuiel Gebredngl
* Chia-Tung Liu
* Student IDs::922729168
* 923408847
* GitHub-Name::yuiela
* Mob1001
* Group-Name::Alt+F4
* Project:: Basic File System
*
* File:: FreeSpaceManager.c
*
* Description:: Fat table funcitons
*
**************************************************************/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include "fsLow.h"
#include "FreeSpaceManager.h"
#include "VCB.h"
// Define the structure for FAT entries.
extern VCB_Block *VCBHolder; // Declaration of a global VCB holder, assumed to be defined elsewhere
//FAT_Entry *FATTable; // Global pointer to the FAT table
// Function to initialize the FAT table with a given number of blocks.
FAT_Entry* initFATTable(int numberOfBlocks) {
// Calculate and set the size of the FAT table in the VCB.
VCBHolder->FAT_Table_Size = numberOfBlocks * sizeof(FAT_Entry);
// Allocate memory for the FAT table.
FAT_Entry* FATTableTemp = malloc(VCBHolder->FAT_Table_Size);
if (FATTableTemp == NULL) {
fprintf(stderr, "Error allocating FAT table.\n");
return NULL;
}
// Initialize the FAT table entries.
for (int i = 0; i < numberOfBlocks; i++) {
FATTableTemp[i].nextBlockRef = 0;
FATTableTemp[i].isTaken = 0;
}
// Set the global FATTable pointer to the new table.
FATTable = FATTableTemp;
// Calculate and store the number of blocks needed to store the FAT table itself.
VCBHolder->FAT_Table_Blocks = (VCBHolder->FAT_Table_Size / VCBHolder->block_size) + 1;
// Allocate and write the VCB to the disk at the start.
int startingVCBBlock = allocFAT(1);
writeToLBA(VCBHolder, sizeof(VCB_Block), &startingVCBBlock);
// Allocate space for the FAT table on the disk and update the reference in VCB.
VCBHolder->FAT_reference = allocFAT(VCBHolder->FAT_Table_Blocks);
return FATTable;
}
// Function to read the FAT table from the disk.
FAT_Entry* readFATTable(int FAT_reference) {
// Calculate the size needed to read the FAT table based on the number of blocks it occupies.
size_t fatSize = VCBHolder->FAT_Table_Blocks * VCBHolder->block_size;
// Allocate temporary memory to hold the FAT table.
FAT_Entry* tempFAT = malloc(fatSize);
// Read the FAT table from the disk using the provided reference.
LBAread(tempFAT, VCBHolder->FAT_Table_Blocks, FAT_reference);
return tempFAT;
}
// Function to allocate blocks in the FAT table for file/directory storage.
int allocFAT(int blocks) {
int blockCount = VCBHolder->FAT_Table_Size / sizeof(FAT_Entry);
int startBlock = -1; // To store the first block of the newly allocated space.
int blocksNeeded = blocks; // Number of blocks to allocate.
int lastBlockIndex = 0; // To link the allocated blocks.
// Traverse the FAT table to find free blocks.
for (int i = 0; i < blockCount && blocksNeeded > 0; i++) {
if (FATTable[i].isTaken == 0) { // If the block is free.
if (startBlock == -1) { // First free block found.
startBlock = i;
} else { // Subsequent free blocks.
FATTable[lastBlockIndex].nextBlockRef = i;
}
// Mark the block as taken and continue.
FATTable[i].isTaken = 1;
lastBlockIndex = i;
blocksNeeded--;
}
}
// If all requested blocks are allocated, mark the last block and write the FAT to disk.
if (blocksNeeded == 0) {
FATTable[lastBlockIndex].nextBlockRef = -1; // Mark end of file chain.
LBAwrite(FATTable, VCBHolder->FAT_Table_Blocks, VCBHolder->FAT_reference);
return startBlock;
}
return -1; // Return -1 if not enough space available.
}
// Function to deallocate blocks in the FAT.
int deAllocFAT(int startingBlock) {
int blocksFreed = 0; // Count of freed blocks.
int currentBlock = startingBlock; // Start from the provided block.
// Traverse through the FAT table to free the blocks.
while (currentBlock != -1) {
int nextBlock = FATTable[currentBlock].nextBlockRef;
FATTable[currentBlock].isTaken = 0; // Mark the block as free.
blocksFreed++;
currentBlock = nextBlock; // Move to the next block in the chain.
}
// Write the updated FAT table to the disk.
LBAwrite(FATTable, VCBHolder->FAT_Table_Blocks, VCBHolder->FAT_reference);
return blocksFreed;
}
// Function to write data to logical block addresses (LBAs) on the disk.
int writeToLBA(void* data, int size, int* startBlock) {
char* byteData = (char*)data;
int blocksNeeded = (size + VCBHolder->block_size - 1) / VCBHolder->block_size; // Calculate the number of blocks needed for the data.
int bytesRead = 0; // Count of bytes written.
// Write data to the disk block by block.
for (int i = 0; i < blocksNeeded; i++) {
int blockIndex = (i == 0) ? *startBlock : absoluteLBA(*startBlock, i);
if (blockIndex == -1) break; // Check for no more blocks available.
int bytesToWrite = (i < blocksNeeded - 1) ? VCBHolder->block_size : (size % VCBHolder->block_size);
LBAwrite(byteData + bytesRead, bytesToWrite, blockIndex);
bytesRead += bytesToWrite;
*startBlock = blockIndex; // Update the last written block.
}
return bytesRead;
}
// Function to calculate the absolute block number from a start block and offset.
int absoluteLBA(int start, int block) {
int index = start;
int i = 0;
// Traverse through the FAT table to find the absolute block number.
while (index != -1 && i < block) {
if (FATTable[index].isTaken == 0) {
return -2; // Error if trying to access a free block.
}
index = FATTable[index].nextBlockRef;
i++;
}
return index;
}
// Function to read data from logical block addresses (LBAs) on the disk.
int readFromLBA(void* raw, int bufferSize, int* startBlock) {
char* buffer = (char*)raw;
char blockBuffer[VCBHolder->block_size]; // Temporary buffer to hold data from a block.
int blocksNeeded = (bufferSize + VCBHolder->block_size - 1) / VCBHolder->block_size; // Calculate the number of blocks needed.
int bytesRead = 0; // Count of bytes read.
int relativeBlock = -1; // To track the relative block number.
int absoluteBlock = *startBlock; // Start block number.
// Read data from the disk block by block.
for (int i = 0; i < blocksNeeded; i++) {
relativeBlock = *startBlock + i;
if (absoluteBlock == -1) {
break; // End of file reached.
} else if (absoluteBlock == -2) {
return absoluteBlock; // Error if reading unallocated block.
}
int bytesToRead = (i < blocksNeeded - 1) ? VCBHolder->block_size : (bufferSize % VCBHolder->block_size);
LBAread(blockBuffer, 1, absoluteBlock);
memcpy(buffer + bytesRead, blockBuffer, bytesToRead);
bytesRead += bytesToRead;
absoluteBlock = absoluteLBA(absoluteBlock, 1);
}
*startBlock = relativeBlock; // Update last read block.
return bytesRead;
}
// Extended allocation function to allocate additional blocks to a file after the initial allocation.
int extAllocFAT(int fileBlock, int blocks) {
int reference = fileBlock;
int startBlock = allocFAT(blocks);
if (startBlock == -1) {
return -1; // Error if not enough space.
}
// Find the last block in the current allocation and link the new blocks.
while (FATTable[reference].nextBlockRef != -1) {
reference = FATTable[reference].nextBlockRef;
}
FATTable[reference].nextBlockRef = startBlock;
LBAwrite(FATTable, VCBHolder->FAT_Table_Blocks, VCBHolder->FAT_reference);
return 0;
}
// Function to write data to logical block addresses considering the index within the block.
int writeToLBAI(void* raw, int bufferSize, int* startBlock, int* index) {
char* buffer = (char*)raw;
char blockBuffer[VCBHolder->block_size]; // Temporary buffer to hold a block of data.
int blocksNeeded = (bufferSize + VCBHolder->block_size - 1) / VCBHolder->block_size; // Calculate the number of blocks needed.
int bytesRead = 0; // Count of bytes written.
int lastBlockOn = *startBlock; // Last block written on.
int absoluteBlock = *startBlock; // Absolute block number for writing.
// Handle writing within a block if an index is specified.
if (*index != 0) {
char boof[VCBHolder->block_size];
int position = *startBlock;
readFromLBA(boof, sizeof(boof), &position);
int remainingBytes = VCBHolder->block_size - *index;
if (bufferSize < remainingBytes) {
remainingBytes = bufferSize;
}
memcpy(boof + (*index), buffer, remainingBytes);
*index += remainingBytes;
if (*index == VCBHolder->block_size) {
*index = 0;
}
LBAwrite(boof, 1, position);
bytesRead += remainingBytes;
blocksNeeded--;
if (blocksNeeded == 0) {
return bytesRead;
}
absoluteBlock = absoluteLBA(absoluteBlock, 1);
}
// Write remaining data to the disk.
for (int i = 0; i < blocksNeeded; i++) {
if (absoluteBlock == -1 || absoluteBlock == -2) {
break;
}
if (i + 1 == blocksNeeded) {
int remainingBytes = bufferSize - bytesRead;
memcpy(blockBuffer, buffer + bytesRead, remainingBytes);
LBAwrite(blockBuffer, 1, absoluteBlock);
bytesRead += remainingBytes;
*index = remainingBytes;
break;
}
LBAwrite(buffer + bytesRead, 1, absoluteBlock);
bytesRead += VCBHolder->block_size;
lastBlockOn = absoluteBlock;
absoluteBlock = absoluteLBA(absoluteBlock, 1);
}
*startBlock = lastBlockOn; // Update the last block written.
return bytesRead;
}