Files
Asuro/src/driver/storage/fs/driver.storage.fs.flatfs.pas
T

961 lines
29 KiB
ObjectPascal

// Copyright 2021 Aaron Hance
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
{
Driver->Storage->driver.storage.fs.flatfs super simple flat filesystem
@author(Aaron Hance [email protected])
}
unit driver.storage.fs.flatfs;
interface
uses
boot.mgr,
driver.storage.fs.mgr,
core.ds.lists,
memory.heap,
io.stdio,
driver.storage.mgr,
driver.storage.types,
core.strings,
io.syslog,
debug.tracer,
core.util, arch.x86.util,
driver.storage.vol.mbr,
driver.storage.vol.mgr;
type
TDisk_Info = bitpacked record
jmp2boot: ubit24;
OEMName: array[0..7] of char;
version: uint16;
sectorCount : uint16;
fileCount : uint16;
signature : uint32;
end;
PDisk_Info = ^TDisk_Info;
TFile_Entry = bitpacked record
attribues : uint8; // 0x00 = does not exsist, 0x01 = file, 0x02 = hidden, 0x04 = system/read only, 0x10 = directory, 0x20 = archive
name: array[0..53] of char; //max file name length is 54
rsv : uint8;
size: uint32;
start : uint32;
end;
PFile_Entry = ^TFile_Entry;
var
filesystem : TFilesystem;
procedure init;
function create_volume(volume : PStorage_Volume; sectors : uint32; start : uint32; config : PFSFormatParams) : TError;
procedure detect_volumes(disk : PStorage_Device);
function read_directory(volume : PStorage_Volume; directory : pchar; status : PuInt32) : PLinkedListBase;
procedure write_directory(volume : PStorage_Volume; directory : pchar; status : PuInt32);
procedure write_file(volume : PStorage_Volume; fileName : pchar; data : PuInt32; size : uint32; status : PuInt32);
procedure read_file(volume : PStorage_Volume; fileName : pchar; data : PuInt32; status : PuInt32);
implementation
function validate_format(volume : PStorage_Volume; sectors, start : uint32; config : PFSFormatParams) : TError;
begin
validate_format := eInvalidArgument;
if (volume = nil) or (volume^.device = nil) then exit;
if not volume^.device^.writable then begin validate_format := eReadOnly; exit; end;
{ Legacy FlatFS readers use 512-byte sectors and exactly 1000 entries. }
if (volume^.device^.sectorSize <> 512) or (sectors > 65535) or
(sectors <= 126) or (start <> volume^.sectorStart) or
(sectors <> volume^.sectorCount) or (start >= volume^.device^.maxSectorCount) or
(sectors > volume^.device^.maxSectorCount-start) then exit;
if config <> nil then begin
if (config^.Version <> FS_FORMAT_PARAMS_VERSION_1) or
((config^.Flags and (not FS_FORMAT_PARAM_FILE_COUNT)) <> 0) then exit;
if ((config^.Flags and FS_FORMAT_PARAM_FILE_COUNT) <> 0) and
(config^.FileCount <> 1000) then exit;
end;
validate_format := eNone;
end;
function create_volume(volume : PStorage_Volume; sectors : uint32; start : uint32; config : PFSFormatParams) : TError;
var info : PDisk_Info; entries : PFile_Entry; err : TError;
begin
create_volume := validate_format(volume, sectors, start, config);
if create_volume <> eNone then exit;
info := PDisk_Info(kalloc(512)); entries := PFile_Entry(kalloc(125*512));
if (info = nil) or (entries = nil) then begin
if info <> nil then kfree(void(info));
if entries <> nil then kfree(void(entries));
create_volume := eOutOfMemory; exit;
end;
memset(uint32(info), 0, 512); memset(uint32(entries), 0, 125*512);
err := storage_write(volume^.device, start, 1, puint32(info));
if err = eNone then begin
entries[0].attribues := $10;
memcpy(uint32(pchar('/system')), uint32(@entries[0].name[0]), 7);
entries[1].attribues := $10;
memcpy(uint32(pchar('/programs')), uint32(@entries[1].name[0]), 9);
entries[2].attribues := $10;
memcpy(uint32(pchar('/user')), uint32(@entries[2].name[0]), 5);
err := storage_write(volume^.device, start+1, 125, puint32(entries));
end;
if err = eNone then begin
memcpy(uint32(pchar('ASURO ')), uint32(@info^.OEMName[0]), 8);
info^.version := 1; info^.sectorCount := sectors; info^.fileCount := 1000;
info^.signature := $0B00B1E5;
err := storage_write(volume^.device, start, 1, puint32(info));
end;
kfree(void(entries)); kfree(void(info));
create_volume := err;
end;
procedure write_directory(volume : PStorage_Volume; directory : pchar; status : PuInt32);
var
directories : PLinkedListBase;
i : uint32;
fileEntries : PFile_Entry;
fileEntry : PFile_Entry;
buffer : PuInt32;
position : uint32;
offset : uint32;
const
fileCount : uint32 = 1000;
begin
status^ := 0;
//directories := read_directory(volume, directory, status);
fileEntries := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
memset(uint32(fileEntries), 0, sizeof(TFile_Entry) * fileCount + 512);
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart + 1, (sizeof(TFile_Entry) * fileCount) div 512, PuInt32(fileEntries));
if status^ = 0 then begin
for i := 0 to fileCount - 1 do begin
push_trace('write_directory_2');
//fileEntry := PFile_Entry(STRLL_Get(directories, i));
fileEntry := @fileEntries[i];
if fileEntry^.attribues = 0 then begin
fileEntry^.attribues := $10;
fileEntry^.size := 0;
fileEntry^.start := 0;
memcpy(uint32(directory), uint32(@fileEntry^.name), stringSize(directory));
push_trace('write_directory_3');
//write file table
buffer := PuInt32(Kalloc(513));
memset(uint32(buffer), 0, 512);
push_trace('write_directory.b4_read');
//read file table cointaining entry of interest
position := (i * sizeof(TFile_Entry)) div 512;
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart + 1 + position, 1, buffer);
push_trace('write_directory.after_read');
//calculate entry offset into sector
offset := (i * sizeof(TFile_Entry)) mod 512;
offset := offset div sizeof(TFile_Entry);
//set entry in buffer
PFile_Entry(buffer)[offset] := fileEntry^;
//write updated file table sector
driver.storage.mgr.storage_write(volume^.device, volume^.sectorStart + 1 + position, 1, buffer);
Kfree(buffer);
push_trace('write_directory.after_write');
break;
end;
end;
end;
if fileEntry^.attribues = 0 then begin
status^ := 1;
end;
end;
function read_directory(volume : PStorage_Volume; directory : pchar; status : PuInt32) : PLinkedListBase;
var
directories : PLinkedListBase;
fileEntrys : PFile_Entry;
i : uint32;
compString : PChar;
afterString : PChar;
slash : PChar;
compStringLength : uint32;
fileCount : uint32 = 1000;
slashArray : array[0..1] of char = '/';
begin
compString := pchar(kalloc(60));
memset(uint32(compString), 0, 60);
afterString := pchar(kalloc(60));
memset(uint32(afterString), 0, 60);
slash := stringNew(2);
memcpy(uint32(@slashArray), uint32(slash), 1);
directories := STRLL_New();
fileEntrys := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntrys));
for i := 0 to fileCount - 1 do begin
if uint32(fileEntrys[i].name[0]) = 0 then begin
break;
end;
compString := stringSub(fileEntrys[i].name, 0, stringSize(directory));
afterString := stringSub(fileEntrys[i].name, stringSize(directory), stringSize(fileEntrys[i].name)-1);
push_trace('read_directory_2');
if stringEquals(compString, directory) and
(not stringContains(afterString, slash)) then begin
STRLL_Add(directories, afterString);
end;
end;
push_trace('read_directory_3');
Kfree(puint32(fileEntrys));
read_directory := directories;
end;
procedure quicksort_start(list : PFile_Entry; begining : uint32; stop : uint32);
var
pivot : uint32;
i : uint32;
j : uint32;
temp : PLinkedListBase;
tempFileEntry : PFile_Entry;
begin
tempFileEntry := PFile_Entry(Kalloc(sizeof(TFile_Entry)));
memset(uint32(tempFileEntry), 0, sizeof(TFile_Entry));
i:=begining;
j:=stop;
pivot := list[(begining + stop) div 2].start;
while i <= j do begin
while list[i].start < pivot do begin
i := i + 1;
end;
while list[j].start > pivot do begin
j := j - 1;
end;
if i <= j then begin
tempFileEntry^ := list[i];
list[i] := list[j];
list[j] := tempFileEntry^;
i := i + 1;
j := j - 1;
end;
end;
if begining < j then begin
quicksort_start(list, begining, j);
end;
if i < stop then begin
quicksort_start(list, i, stop);
end;
Kfree(puint32(tempFileEntry));
end;
function find_free_space(volume : PStorage_Volume; size : uint32; status : PuInt32) : uint32;
var
fileEntrys : PFile_Entry;
confirmedFileEntrys : PFile_Entry;
confirmedFileEntrysCount : uint32 = 0;
fileEntry : PFile_Entry;
i : uint32;
fileCount : uint32 = 1000;
baseAddress : uint32;
begin
fileEntrys := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
confirmedFileEntrys := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
memset(uint32(fileEntrys), 0, sizeof(TFile_Entry) * fileCount + 512);
memset(uint32(confirmedFileEntrys), 0, sizeof(TFile_Entry) * fileCount + 512);
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntrys));
baseAddress := volume^.sectorStart + 2 + ( (fileCount * sizeof(TFile_Entry)) div 512);
for i := 0 to fileCount - 1 do begin
if fileEntrys[i].attribues <> 0 then begin
confirmedFileEntrys[confirmedFileEntrysCount] := fileEntrys[i];
confirmedFileEntrysCount := confirmedFileEntrysCount + 1;
end;
end;
//sort file table by start address using quicksort
quicksort_start(confirmedFileEntrys, 0, confirmedFileEntrysCount - 1);
//find free space big enough to fit size //TODO: make this work
for i := 0 to confirmedFileEntrysCount - 1 do begin
if confirmedFileEntrys[i+1].attribues = 0 then begin
if confirmedFileEntrys[i].size = 0 then begin
find_free_space := baseAddress;
break;
end else begin
find_free_space := confirmedFileEntrys[i].start + confirmedFileEntrys[i].size;
break;
end;
break;
end;
if confirmedFileEntrys[i].size <> 0 then begin
if confirmedFileEntrys[i+1].start - (confirmedFileEntrys[i].start + confirmedFileEntrys[i].size) > size+1 then begin
find_free_space := confirmedFileEntrys[i].start + confirmedFileEntrys[i].size;
status^ := 0;
break;
end;
end;
end;
Kfree(puint32(fileEntrys));
Kfree(puint32(confirmedFileEntrys));
end;
procedure write_file(volume : PStorage_Volume; fileName : pchar; data : PuInt32; size : uint32; status : PuInt32);
var
directories : PLinkedListBase;
i : uint32;
p : uint32;
fileEntries : PFile_Entry;
fileEntry : PFile_Entry;
buffer : PuInt32;
position : uint32;
offset : uint32;
fileCount : uint32 = 1000;
exsists : boolean;
elm : puint32;
begin
push_trace('driver.storage.fs.flatfs.write_file');
//load file table
fileEntries := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
memset(uint32(fileEntries), 0, sizeof(TFile_Entry) * fileCount);
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntries));
//check if file exists else find free entry
for i := 0 to fileCount - 1 do begin
if stringEquals(fileEntries[i].name, fileName) then begin
exsists := true;
p:= i;
break;
end;
if fileEntries[i].attribues = 0 then begin
exsists := false;
p:= i;
break;
end;
end;
//if entry is directory then exit
if fileEntries[p].attribues and $10 = $10 then begin
status^ := 1;
exit;
end;
// //read file table cointaining entry of interest
position := (p * sizeof(TFile_Entry)) div 512;
//if file exists update entry else create new entry
if exsists then begin
//check if size is greater than current size
if size > fileEntries[p].size then begin
//find free space
fileEntries[p].start := find_free_space(volume, size, status);
fileEntries[p].size := size;
end else begin
//update size
fileEntries[p].size := size;
end;
end else begin
//find free space
fileEntries[p].start := find_free_space(volume, size, status);
fileEntries[p].size := size;
fileEntries[p].attribues := $01;
//add file name
memcpy(uint32(fileName), uint32(@fileEntries[p].name), 14);
end;
//write file table
driver.storage.mgr.storage_write(volume^.device, volume^.sectorStart + 1 , 1, puint32(@fileEntries[position]));
//write file
driver.storage.mgr.storage_write(volume^.device, fileEntries[p].start, size, data);
//free buffer
Kfree(puint32(fileEntries));
end;
procedure read_file(volume : PStorage_Volume; fileName : pchar; data : PuInt32; status : PuInt32);
var
directories : PLinkedListBase;
i : uint32;
p : uint32;
fileEntries : PFile_Entry;
fileEntry : PFile_Entry;
fileCount : uint32 = 1000;
exsists : boolean = false;
size : uint32;
begin
//load file table
fileEntries := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
memset(uint32(fileEntries), 0, sizeof(TFile_Entry) * fileCount);
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntries));
//check if file exists else exit
for i := 0 to fileCount - 1 do begin
if stringEquals(fileEntries[i].name, fileName) then begin
exsists := true;
p:= i;
break;
end;
end;
//if entry is directory then exit
if fileEntries[p].attribues and $10 = $10 then begin
status^ := 1;
exit;
end;
//if entry is not found exit
if fileEntries[i].attribues = 0 then begin
exsists := false;
p:= i;
exit;
end;
//file size rounded up to nearest 512
size := (fileEntries[p].size + 511) and -512;
//read file
data := Kalloc(size);
driver.storage.mgr.storage_read(volume^.device, fileEntries[p].start, size, data);
//free buffer
Kfree(puint32(fileEntries));
status^ := 0;
end;
{ Count free sectors on a FlatFS volume by scanning file entries. }
function countFreeFlatFSSectors(volume : PStorage_Volume) : uint32;
var
buffer : puint32;
diskInfo : PDisk_Info;
sectorCount : uint32;
fileCount : uint32;
tableSectors : uint32;
fileEntries : PFile_Entry;
usedSectors : uint32;
overhead : uint32;
i : uint32;
begin
countFreeFlatFSSectors := 0;
buffer := puint32(kalloc(512));
memset(uint32(buffer), 0, 512);
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart, 1, buffer);
diskInfo := PDisk_Info(buffer);
sectorCount := diskInfo^.sectorCount;
fileCount := diskInfo^.fileCount;
kfree(buffer);
if sectorCount = 0 then exit;
tableSectors := (fileCount * sizeof(TFile_Entry)) div 512;
overhead := 2 + tableSectors; { header + boundary + file table }
usedSectors := 0;
if fileCount > 0 then begin
fileEntries := PFile_Entry(kalloc(sizeof(TFile_Entry) * fileCount + 512));
memset(uint32(fileEntries), 0, sizeof(TFile_Entry) * fileCount);
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart + 1,
tableSectors, puint32(fileEntries));
for i := 0 to fileCount - 1 do begin
if fileEntries[i].attribues <> 0 then
usedSectors := usedSectors + fileEntries[i].size;
end;
kfree(puint32(fileEntries));
end;
if sectorCount > (overhead + usedSectors) then
countFreeFlatFSSectors := sectorCount - overhead - usedSectors
else
countFreeFlatFSSectors := 0;
end;
procedure detect_volumes(disk : PStorage_Device);
var
buffer : puint32;
bufSize : uint32;
volume : PStorage_volume;
begin
push_trace('driver.storage.fs.flatfs.detectVolumes()');
bufSize := disk^.sectorSize;
if bufSize < 512 then bufSize := 512;
buffer := puint32(kalloc(bufSize));
memset(uint32(buffer), 0, bufSize);
if disk^.dispatchRead = nil then begin
io.syslog.writestringln('FlatFS: detect_volumes: device has no read dispatch.');
kfree(buffer);
exit;
end;
driver.storage.mgr.storage_read(disk, 2, 1, buffer);
if (PDisk_Info(buffer)^.signature = $0B00B1E5) then begin
io.syslog.writestringln('FlatFS: volume found!');
volume := PStorage_volume(kalloc(sizeof(TStorage_Volume)));
memset(uint32(volume), 0, sizeof(TStorage_Volume));
volume^.device := disk;
volume^.sectorStart := 2;
volume^.sectorSize := 512;
volume^.sectorCount := PDisk_Info(buffer)^.sectorCount;
volume^.filesystem := @filesystem;
volume^.freeSectors := countFreeFlatFSSectors(volume);
volume^.isBootDrive := false;
driver.storage.vol.mgr.register_volume(disk, volume);
end;
kfree(buffer);
end;
procedure delete_file(volume : PStorage_Volume; fileName : pchar; status : PuInt32);
var
directories : PLinkedListBase;
i : uint32;
p : uint32;
fileEntries : PFile_Entry;
fileEntry : PFile_Entry;
zeroBuffer : PuInt32;
position : uint32;
offset : uint32;
fileCount : uint32 = 1000;
exsists : boolean;
begin
//load file table
fileEntries := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
memset(uint32(fileEntries), 0, sizeof(TFile_Entry) * fileCount);
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntries));
//check if file exists else exit
for i := 0 to fileCount - 1 do begin
if stringEquals(fileEntries[i].name, fileName) then begin
exsists := true;
p:= i;
break;
end;
end;
//set position of entry
position := (p * sizeof(TFile_Entry)) div 512;
//if entry is directory then exit
if fileEntries[p].attribues and $10 = $10 then begin
status^ := 1;
exit;
end;
//if entry is not found exit
if fileEntries[i].attribues = 0 then begin
exsists := false;
p:= i;
exit;
end;
//zero out file
zeroBuffer := Kalloc(fileEntries[p].size);
memset(uint32(zeroBuffer), 0, fileEntries[p].size);
//write file
driver.storage.mgr.storage_write(volume^.device, fileEntries[p].start, fileEntries[p].size, zeroBuffer);
//free buffer
Kfree(puint32(zeroBuffer));
//zero out file table
memset(uint32(@fileEntries[p]), 0, sizeof(TFile_Entry));
//write file table
driver.storage.mgr.storage_write(volume^.device, volume^.sectorStart + 1 , 1, puint32(@fileEntries[position]));
//free buffer
Kfree(puint32(fileEntries));
status^ := 0;
end;
procedure delete_directory(volume : PStorage_Volume; directoryName : pchar; status : PuInt32);
var
directories : PLinkedListBase;
i : uint32;
p : uint32;
fileEntries : PFile_Entry;
fileEntry : PFile_Entry;
zeroBuffer : PuInt32;
position : uint32;
offset : uint32;
fileCount : uint32 = 1000;
exsists : boolean;
begin
//load file table
fileEntries := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
memset(uint32(fileEntries), 0, sizeof(TFile_Entry) * fileCount);
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart + 1, sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntries));
//check if file exists else exit
for i := 0 to fileCount - 1 do begin
if stringEquals(fileEntries[i].name, directoryName) then begin
exsists := true;
p:= i;
break;
end;
end;
//if entry is not directory then exit
if fileEntries[i].attribues and $10 <> $10 then begin
status^ := 1;
exit;
end;
//calculate position of directory in file table
position := (p * sizeof(TFile_Entry)) div 512;
//zero file table
memset(uint32(@fileEntries[p]), 0, sizeof(TFile_Entry));
//write file table
driver.storage.mgr.storage_write(volume^.device, volume^.sectorStart + 1 , 1, puint32(@fileEntries[position]));
//free buffer
Kfree(puint32(fileEntries));
status^ := 0;
end;
function identify_volume(volume : PStorage_Volume) : boolean;
var
buffer : puint32;
bufSize : uint32;
mbr : PMaster_Boot_Record;
freeMbr : boolean;
slot : sint32;
i : uint32;
begin
push_trace('driver.storage.fs.flatfs.identify_volume');
identify_volume := false;
if volume^.device^.dispatchRead = nil then exit;
mbr := driver.storage.mgr.get_cached_mbr(volume^.device);
freeMbr := false;
if mbr = nil then begin
mbr := driver.storage.mgr.read_mbr(volume^.device);
freeMbr := mbr <> nil;
end;
slot := -1;
if mbr <> nil then begin
for i := 0 to 3 do begin
if mbr^.partition[i].LBA_start = volume^.sectorStart then begin
slot := sint32(i);
break;
end;
end;
if (slot >= 0) and (mbr^.partition[slot].system_id <> filesystem.system_id) then begin
if freeMbr then kfree(void(mbr));
exit;
end;
end;
bufSize := volume^.device^.sectorSize;
if bufSize < 512 then bufSize := 512;
buffer := puint32(kalloc(bufSize));
memset(uint32(buffer), 0, bufSize);
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart, 1, buffer);
if (PDisk_Info(buffer)^.signature = $0B00B1E5) then begin
identify_volume := true;
volume^.freeSectors := countFreeFlatFSSectors(volume);
end;
kfree(buffer);
if freeMbr then kfree(void(mbr));
end;
function readDirectoryEntries(volume : PStorage_Volume; directory : pchar; status : PuInt32) : PLinkedListBase;
var
entries : PLinkedListBase;
fileEntrys : PFile_Entry;
i : uint32;
compString : PChar;
afterString : PChar;
slash : PChar;
fileCount : uint32;
dirEntry : PDirectory_Entry;
elm : void;
slashArray : array[0..1] of char;
begin
push_trace('driver.storage.fs.flatfs.readDirectoryEntries');
fileCount := 1000;
slashArray[0] := '/';
slashArray[1] := char(0);
entries := LL_New(sizeof(TDirectory_Entry));
fileEntrys := PFile_Entry(Kalloc(sizeof(TFile_Entry) * fileCount + 512));
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart + 1,
sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntrys));
slash := stringNew(2);
memcpy(uint32(@slashArray), uint32(slash), 1);
for i := 0 to fileCount - 1 do begin
if uint32(fileEntrys[i].name[0]) = 0 then break;
compString := stringSub(fileEntrys[i].name, 0, stringSize(directory));
afterString := stringSub(fileEntrys[i].name, stringSize(directory),
stringSize(fileEntrys[i].name) - 1);
if stringEquals(compString, directory) and
(not stringContains(afterString, slash)) then begin
elm := LL_Add(entries);
dirEntry := PDirectory_Entry(elm);
dirEntry^.fileName := stringCopy(afterString);
if fileEntrys[i].attribues and $10 = $10 then
dirEntry^.entryType := TDirectory_Entry_Type.directoryEntry
else
dirEntry^.entryType := TDirectory_Entry_Type.fileEntry;
dirEntry^.fileSize := fileEntrys[i].size;
dirEntry^.modifiedDate := 0;
dirEntry^.modifiedTime := 0;
dirEntry^.attributes := fileEntrys[i].attribues;
end;
kfree(void(compString));
kfree(void(afterString));
end;
Kfree(puint32(fileEntrys));
kfree(void(slash));
readDirectoryEntries := entries;
end;
function getFileSize(volume : PStorage_Volume; directory : pchar; fileName : pchar) : uint32;
var
fileEntries : PFile_Entry;
fileCount : uint32;
i : uint32;
begin
getFileSize := 0;
fileCount := 1000;
fileEntries := PFile_Entry(kalloc(sizeof(TFile_Entry) * fileCount + 512));
memset(uint32(fileEntries), 0, sizeof(TFile_Entry) * fileCount);
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart + 1,
sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntries));
for i := 0 to fileCount - 1 do begin
if fileEntries[i].attribues = 0 then break;
if stringEquals(fileEntries[i].name, fileName) then begin
getFileSize := fileEntries[i].size;
break;
end;
end;
kfree(puint32(fileEntries));
end;
function readFileAtOffset(volume : PStorage_Volume; directory : pchar;
fileName : pchar; offset : uint32;
buffer : puint32; byteCount : uint32;
ctx : pointer) : uint32;
var
fileEntries : PFile_Entry;
fileCount : uint32;
i : uint32;
fileStart : uint32;
fileSize : uint32;
remaining : uint32;
secOff : uint32;
curSec : uint32;
destPos : uint32;
bytesToCopy : uint32;
secBuf : puint32;
found : boolean;
begin
readFileAtOffset := 0;
fileCount := 1000;
found := false;
fileEntries := PFile_Entry(kalloc(sizeof(TFile_Entry) * fileCount + 512));
memset(uint32(fileEntries), 0, sizeof(TFile_Entry) * fileCount);
driver.storage.mgr.storage_read(volume^.device, volume^.sectorStart + 1,
sizeof(TFile_Entry) * fileCount div 512, puint32(fileEntries));
for i := 0 to fileCount - 1 do begin
if fileEntries[i].attribues = 0 then break;
if stringEquals(fileEntries[i].name, fileName) then begin
fileStart := fileEntries[i].start;
fileSize := fileEntries[i].size;
found := true;
break;
end;
end;
kfree(puint32(fileEntries));
if not found then exit;
{ Clamp to EOF }
if offset >= fileSize then exit;
remaining := fileSize - offset;
if byteCount < remaining then remaining := byteCount;
secBuf := puint32(kalloc(512));
if secBuf = nil then exit;
destPos := 0;
curSec := fileStart + (offset div 512);
secOff := offset mod 512;
while remaining > 0 do begin
driver.storage.mgr.storage_read(volume^.device, curSec, 1, secBuf);
bytesToCopy := 512 - secOff;
if bytesToCopy > remaining then bytesToCopy := remaining;
core.util.memcpy(uint32(secBuf) + secOff, uint32(buffer) + destPos, bytesToCopy);
destPos := destPos + bytesToCopy;
remaining := remaining - bytesToCopy;
secOff := 0;
curSec := curSec + 1;
end;
kfree(secBuf);
readFileAtOffset := destPos;
end;
procedure init();
begin
push_trace('driver.storage.fs.flatfs.init()');
filesystem.sName:= 'driver.storage.fs.flatfs';
filesystem.system_id:= $02;
filesystem.readDirCallback:= @readDirectoryEntries;
filesystem.fileSizeCallback:= @getFileSize;
filesystem.readOffsetCallback:= @readFileAtOffset;
// filesystem.createDirCallback:= @writeDirectoryGen;
filesystem.createcallback:= @create_volume;
filesystem.validateFormat := @validate_format;
filesystem.detectcallback:= @detect_volumes;
filesystem.identifyCallback:= @identify_volume;
filesystem.formatParamFlags := 0; { fixed 1000-entry legacy format }
// filesystem.writecallback:= @writeFile;
// filesystem.readcallback := @readFile;
driver.storage.fs.mgr.register_filesystem(@filesystem);
end;
Initialization
boot.mgr.registerBoot('driver.storage.fs.flatfs', @init, 'FlatFS Filesystem', 'driver.storage.fs.mgr');
end.