Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8c7c2983d | ||
|
|
91bc0e5ea2 | ||
|
|
2cf879c4b9 | ||
|
|
fcc9809248 | ||
|
|
63b67f5878 | ||
|
|
521633c9a4 | ||
|
|
0cd32a0f64 | ||
|
|
f2e5f3535a | ||
|
|
2159578bdf |
+587
File diff suppressed because it is too large
Load Diff
Generated
+1
@@ -0,0 +1 @@
|
|||||||
|
mnt {device}/sys /sys
|
||||||
@@ -138,7 +138,7 @@ begin
|
|||||||
|
|
||||||
{ Open for writing }
|
{ Open for writing }
|
||||||
debug.tracer.push_trace('edit.SaveFile.openRW');
|
debug.tracer.push_trace('edit.SaveFile.openRW');
|
||||||
fHandle := driver.storage.vfs.OpenFile(FilePath, omReadWrite, wmRewrite, @fError);
|
fHandle := driver.storage.vfs.OpenFile(FilePath, omReadWrite, @fError);
|
||||||
if fHandle <> 0 then begin
|
if fHandle <> 0 then begin
|
||||||
debug.tracer.push_trace('edit.SaveFile.writeFile');
|
debug.tracer.push_trace('edit.SaveFile.writeFile');
|
||||||
driver.storage.vfs.WriteFile(fHandle, 0, puint8(buf), totalLen);
|
driver.storage.vfs.WriteFile(fHandle, 0, puint8(buf), totalLen);
|
||||||
@@ -149,7 +149,7 @@ begin
|
|||||||
end else begin
|
end else begin
|
||||||
{ Try write-only for new file }
|
{ Try write-only for new file }
|
||||||
debug.tracer.push_trace('edit.SaveFile.openWO');
|
debug.tracer.push_trace('edit.SaveFile.openWO');
|
||||||
fHandle := driver.storage.vfs.OpenFile(FilePath, omWriteOnly, wmNew, @fError);
|
fHandle := driver.storage.vfs.OpenFile(FilePath, omCreate, @fError);
|
||||||
if fHandle <> 0 then begin
|
if fHandle <> 0 then begin
|
||||||
debug.tracer.push_trace('edit.SaveFile.writeFileNew');
|
debug.tracer.push_trace('edit.SaveFile.writeFileNew');
|
||||||
driver.storage.vfs.WriteFile(fHandle, 0, puint8(buf), totalLen);
|
driver.storage.vfs.WriteFile(fHandle, 0, puint8(buf), totalLen);
|
||||||
@@ -181,7 +181,7 @@ begin
|
|||||||
if FilePath = nil then exit;
|
if FilePath = nil then exit;
|
||||||
|
|
||||||
debug.tracer.push_trace('edit.LoadFile.openFile');
|
debug.tracer.push_trace('edit.LoadFile.openFile');
|
||||||
fHandle := driver.storage.vfs.OpenFile(FilePath, omReadOnly, wmRewrite, @fError);
|
fHandle := driver.storage.vfs.OpenFile(FilePath, omRead, @fError);
|
||||||
debug.tracer.push_trace('edit.LoadFile.openFile.done');
|
debug.tracer.push_trace('edit.LoadFile.openFile.done');
|
||||||
if (fHandle = 0) or (fError <> eNone) then begin
|
if (fHandle = 0) or (fError <> eNone) then begin
|
||||||
io.syslog.writestringln('New file.');
|
io.syslog.writestringln('New file.');
|
||||||
|
|||||||
@@ -77,12 +77,15 @@ type
|
|||||||
{ Flat name buffer — heap-alloc'd in do_refresh to avoid stack bloat }
|
{ Flat name buffer — heap-alloc'd in do_refresh to avoid stack bloat }
|
||||||
TNameBuf = array[0..ENTRY_MAX - 1] of pchar;
|
TNameBuf = array[0..ENTRY_MAX - 1] of pchar;
|
||||||
PNameBuf = ^TNameBuf;
|
PNameBuf = ^TNameBuf;
|
||||||
|
TSizeBuf = array[0..ENTRY_MAX - 1] of uint32;
|
||||||
|
PSizeBuf = ^TSizeBuf;
|
||||||
|
|
||||||
{ Per-call context passed to the forEach collect callback }
|
{ Per-call context passed to the forEach collect callback }
|
||||||
PFPCollectCtx = ^TFPCollectCtx;
|
PFPCollectCtx = ^TFPCollectCtx;
|
||||||
TFPCollectCtx = record
|
TFPCollectCtx = record
|
||||||
dir_names : PNameBuf;
|
dir_names : PNameBuf;
|
||||||
file_names : PNameBuf;
|
file_names : PNameBuf;
|
||||||
|
file_sizes : PSizeBuf;
|
||||||
dir_count : uint32;
|
dir_count : uint32;
|
||||||
file_count : uint32;
|
file_count : uint32;
|
||||||
filter : pchar;
|
filter : pchar;
|
||||||
@@ -350,6 +353,28 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Insertion sort on name array, swapping a parallel size array in lockstep }
|
||||||
|
procedure sortNamesWithSizes(var names: array of pchar; var sizes: array of uint32; n: uint32);
|
||||||
|
var
|
||||||
|
i, j : uint32;
|
||||||
|
tmpN : pchar;
|
||||||
|
tmpS : uint32;
|
||||||
|
begin
|
||||||
|
if n < 2 then exit;
|
||||||
|
for i := 1 to n - 1 do begin
|
||||||
|
tmpN := names[i];
|
||||||
|
tmpS := sizes[i];
|
||||||
|
j := i;
|
||||||
|
while (j > 0) and strLess(tmpN, names[j - 1]) do begin
|
||||||
|
names[j] := names[j - 1];
|
||||||
|
sizes[j] := sizes[j - 1];
|
||||||
|
j := j - 1;
|
||||||
|
end;
|
||||||
|
names[j] := tmpN;
|
||||||
|
sizes[j] := tmpS;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ ============================================================
|
{ ============================================================
|
||||||
fp_collect_cb
|
fp_collect_cb
|
||||||
core.ds.hashmap.forEach callback: classifies each VFS entry as dir or file
|
core.ds.hashmap.forEach callback: classifies each VFS entry as dir or file
|
||||||
@@ -364,7 +389,7 @@ begin
|
|||||||
obj := PVFSObject(data);
|
obj := PVFSObject(data);
|
||||||
if (ctx = nil) or (obj = nil) then exit;
|
if (ctx = nil) or (obj = nil) then exit;
|
||||||
case obj^.ObjectType of
|
case obj^.ObjectType of
|
||||||
otVDIRECTORY, otDRIVE, otDIRECTORY, otMOUNT:
|
otVDIRECTORY, otDRIVE, otDIRECTORY, otMOUNT, otSYMLINK:
|
||||||
if ctx^.dir_count < ENTRY_MAX then begin
|
if ctx^.dir_count < ENTRY_MAX then begin
|
||||||
ctx^.dir_names^[ctx^.dir_count] := key;
|
ctx^.dir_names^[ctx^.dir_count] := key;
|
||||||
ctx^.dir_count := ctx^.dir_count + 1;
|
ctx^.dir_count := ctx^.dir_count + 1;
|
||||||
@@ -373,6 +398,7 @@ begin
|
|||||||
if matchesFilter(key, ctx^.filter) then
|
if matchesFilter(key, ctx^.filter) then
|
||||||
if ctx^.file_count < ENTRY_MAX then begin
|
if ctx^.file_count < ENTRY_MAX then begin
|
||||||
ctx^.file_names^[ctx^.file_count] := key;
|
ctx^.file_names^[ctx^.file_count] := key;
|
||||||
|
ctx^.file_sizes^[ctx^.file_count] := obj^.FileSize;
|
||||||
ctx^.file_count := ctx^.file_count + 1;
|
ctx^.file_count := ctx^.file_count + 1;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@@ -390,12 +416,14 @@ var
|
|||||||
ctx : TFPCollectCtx;
|
ctx : TFPCollectCtx;
|
||||||
dir_names : PNameBuf; { heap-alloc'd to avoid blowing the core.version stack }
|
dir_names : PNameBuf; { heap-alloc'd to avoid blowing the core.version stack }
|
||||||
file_names : PNameBuf;
|
file_names : PNameBuf;
|
||||||
|
file_sizes : PSizeBuf;
|
||||||
dir_count : uint32;
|
dir_count : uint32;
|
||||||
file_count : uint32;
|
file_count : uint32;
|
||||||
i : uint32;
|
i : uint32;
|
||||||
row, name_lbl, size_lbl : Plv_obj;
|
row, name_lbl, size_lbl : Plv_obj;
|
||||||
sep : pchar;
|
sep : pchar;
|
||||||
copy : pchar;
|
copy : pchar;
|
||||||
|
szStr : pchar;
|
||||||
s1, s2, s3 : pchar;
|
s1, s2, s3 : pchar;
|
||||||
begin
|
begin
|
||||||
debug.tracer.push_trace('filepicker.do_refresh');
|
debug.tracer.push_trace('filepicker.do_refresh');
|
||||||
@@ -408,8 +436,10 @@ begin
|
|||||||
io.syslog.logln('FPCIK', 'do_refresh: kalloc name bufs');
|
io.syslog.logln('FPCIK', 'do_refresh: kalloc name bufs');
|
||||||
dir_names := PNameBuf(kalloc(sizeof(TNameBuf)));
|
dir_names := PNameBuf(kalloc(sizeof(TNameBuf)));
|
||||||
file_names := PNameBuf(kalloc(sizeof(TNameBuf)));
|
file_names := PNameBuf(kalloc(sizeof(TNameBuf)));
|
||||||
|
file_sizes := PSizeBuf(kalloc(sizeof(TSizeBuf)));
|
||||||
memset(uint32(dir_names), 0, sizeof(TNameBuf));
|
memset(uint32(dir_names), 0, sizeof(TNameBuf));
|
||||||
memset(uint32(file_names), 0, sizeof(TNameBuf));
|
memset(uint32(file_names), 0, sizeof(TNameBuf));
|
||||||
|
memset(uint32(file_sizes), 0, sizeof(TSizeBuf));
|
||||||
|
|
||||||
{ Sync path bar }
|
{ Sync path bar }
|
||||||
if p^.path_bar <> nil then
|
if p^.path_bar <> nil then
|
||||||
@@ -429,6 +459,7 @@ begin
|
|||||||
lv_label_set_text(p^.status_label, 'Could not read directory');
|
lv_label_set_text(p^.status_label, 'Could not read directory');
|
||||||
kfree(void(dir_names));
|
kfree(void(dir_names));
|
||||||
kfree(void(file_names));
|
kfree(void(file_names));
|
||||||
|
kfree(void(file_sizes));
|
||||||
debug.tracer.pop_trace;
|
debug.tracer.pop_trace;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@@ -437,6 +468,7 @@ begin
|
|||||||
driver.storage.vfs.FreeDirectoryListing(Map);
|
driver.storage.vfs.FreeDirectoryListing(Map);
|
||||||
kfree(void(dir_names));
|
kfree(void(dir_names));
|
||||||
kfree(void(file_names));
|
kfree(void(file_names));
|
||||||
|
kfree(void(file_sizes));
|
||||||
debug.tracer.pop_trace;
|
debug.tracer.pop_trace;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@@ -444,6 +476,7 @@ begin
|
|||||||
|
|
||||||
ctx.dir_names := dir_names;
|
ctx.dir_names := dir_names;
|
||||||
ctx.file_names := file_names;
|
ctx.file_names := file_names;
|
||||||
|
ctx.file_sizes := file_sizes;
|
||||||
ctx.dir_count := 0;
|
ctx.dir_count := 0;
|
||||||
ctx.file_count := 0;
|
ctx.file_count := 0;
|
||||||
ctx.filter := p^.filter;
|
ctx.filter := p^.filter;
|
||||||
@@ -455,7 +488,7 @@ begin
|
|||||||
|
|
||||||
{ --- Sort both collections alphabetically --- }
|
{ --- Sort both collections alphabetically --- }
|
||||||
if dir_count > 0 then sortNames(dir_names^, dir_count);
|
if dir_count > 0 then sortNames(dir_names^, dir_count);
|
||||||
if file_count > 0 then sortNames(file_names^, file_count);
|
if file_count > 0 then sortNamesWithSizes(file_names^, file_sizes^, file_count);
|
||||||
|
|
||||||
{ --- Build directory rows --- }
|
{ --- Build directory rows --- }
|
||||||
if dir_count > 0 then
|
if dir_count > 0 then
|
||||||
@@ -524,10 +557,11 @@ begin
|
|||||||
lv_obj_set_style_text_color(name_lbl, lv_color_make(210, 215, 230), 0);
|
lv_obj_set_style_text_color(name_lbl, lv_color_make(210, 215, 230), 0);
|
||||||
lv_obj_set_style_text_font(name_lbl, @lv_font_montserrat_14, 0);
|
lv_obj_set_style_text_font(name_lbl, @lv_font_montserrat_14, 0);
|
||||||
|
|
||||||
{ File size column: skipped here to avoid blocking disk I/O
|
{ File size column: use metadata from directory listing }
|
||||||
inside the LVGL timer callback context. }
|
|
||||||
size_lbl := lv_label_create(row);
|
size_lbl := lv_label_create(row);
|
||||||
lv_label_set_text(size_lbl, '--');
|
szStr := fmtFileSize(file_sizes^[i]);
|
||||||
|
lv_label_set_text(size_lbl, szStr);
|
||||||
|
kfree(void(szStr));
|
||||||
lv_obj_set_width(size_lbl, 70);
|
lv_obj_set_width(size_lbl, 70);
|
||||||
lv_obj_set_style_text_color(size_lbl, lv_color_make(100, 110, 130), 0);
|
lv_obj_set_style_text_color(size_lbl, lv_color_make(100, 110, 130), 0);
|
||||||
lv_obj_set_style_text_font(size_lbl, @lv_font_montserrat_14, 0);
|
lv_obj_set_style_text_font(size_lbl, @lv_font_montserrat_14, 0);
|
||||||
@@ -543,6 +577,7 @@ begin
|
|||||||
|
|
||||||
kfree(void(dir_names));
|
kfree(void(dir_names));
|
||||||
kfree(void(file_names));
|
kfree(void(file_names));
|
||||||
|
kfree(void(file_sizes));
|
||||||
|
|
||||||
{ Update status label: "X dirs, Y files" }
|
{ Update status label: "X dirs, Y files" }
|
||||||
if p^.status_label <> nil then begin
|
if p^.status_label <> nil then begin
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ begin
|
|||||||
|
|
||||||
{ ---- READ ---- }
|
{ ---- READ ---- }
|
||||||
if op[0] = '<' then begin
|
if op[0] = '<' then begin
|
||||||
fHandle := driver.storage.vfs.OpenFile(absPath, omReadOnly, wmRewrite, @fError);
|
fHandle := driver.storage.vfs.OpenFile(absPath, omRead, @fError);
|
||||||
if (fHandle = 0) or (fError <> eNone) then begin
|
if (fHandle = 0) or (fError <> eNone) then begin
|
||||||
io.syslog.writestringln('Error: cannot open file for reading.');
|
io.syslog.writestringln('Error: cannot open file for reading.');
|
||||||
kfree(void(absPath));
|
kfree(void(absPath));
|
||||||
@@ -112,10 +112,10 @@ begin
|
|||||||
contentLen := stringSize(content);
|
contentLen := stringSize(content);
|
||||||
|
|
||||||
{ Try read-write rewrite first (existing file) }
|
{ Try read-write rewrite first (existing file) }
|
||||||
fHandle := driver.storage.vfs.OpenFile(absPath, omReadWrite, wmRewrite, @fError);
|
fHandle := driver.storage.vfs.OpenFile(absPath, omReadWrite, @fError);
|
||||||
if (fHandle = 0) or (fError <> eNone) then begin
|
if (fHandle = 0) or (fError <> eNone) then begin
|
||||||
{ Try creating new file }
|
{ Try creating new file }
|
||||||
fHandle := driver.storage.vfs.OpenFile(absPath, omWriteOnly, wmNew, @fError);
|
fHandle := driver.storage.vfs.OpenFile(absPath, omCreate, @fError);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (fHandle = 0) or (fError <> eNone) then begin
|
if (fHandle = 0) or (fError <> eNone) then begin
|
||||||
|
|||||||
@@ -372,9 +372,9 @@ begin
|
|||||||
buf := pchar(kalloc(FILE_BUF_SIZE));
|
buf := pchar(kalloc(FILE_BUF_SIZE));
|
||||||
memset(uint32(buf), 0, FILE_BUF_SIZE);
|
memset(uint32(buf), 0, FILE_BUF_SIZE);
|
||||||
memcpy(uint32(txt), uint32(buf), len);
|
memcpy(uint32(txt), uint32(buf), len);
|
||||||
fHandle := driver.storage.vfs.OpenFile(state^.currentPath, omReadWrite, wmRewrite, @fError);
|
fHandle := driver.storage.vfs.OpenFile(state^.currentPath, omReadWrite, @fError);
|
||||||
if fHandle = 0 then
|
if fHandle = 0 then
|
||||||
fHandle := driver.storage.vfs.OpenFile(state^.currentPath, omWriteOnly, wmNew, @fError);
|
fHandle := driver.storage.vfs.OpenFile(state^.currentPath, omCreate, @fError);
|
||||||
if fHandle = 0 then begin
|
if fHandle = 0 then begin
|
||||||
kfree(void(buf));
|
kfree(void(buf));
|
||||||
io.syslog.logln('NOTEPAD', 'saveFile: OpenFile failed');
|
io.syslog.logln('NOTEPAD', 'saveFile: OpenFile failed');
|
||||||
@@ -413,7 +413,7 @@ var
|
|||||||
buf : pchar;
|
buf : pchar;
|
||||||
begin
|
begin
|
||||||
debug.tracer.push_trace('notepad.loadFile');
|
debug.tracer.push_trace('notepad.loadFile');
|
||||||
fHandle := driver.storage.vfs.OpenFile(path, omReadOnly, wmRewrite, @fError);
|
fHandle := driver.storage.vfs.OpenFile(path, omRead, @fError);
|
||||||
if (fHandle = 0) or (fError <> eNone) then begin
|
if (fHandle = 0) or (fError <> eNone) then begin
|
||||||
io.syslog.logln('NOTEPAD', 'loadFile: could not open file');
|
io.syslog.logln('NOTEPAD', 'loadFile: could not open file');
|
||||||
showErrorMsgbox('Open Failed', 'Could not open file for reading.');
|
showErrorMsgbox('Open Failed', 'Could not open file for reading.');
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{ Resolve relative to per-terminal cwd }
|
{ Resolve relative to per-terminal cwd }
|
||||||
Validity := driver.storage.vfs.changeDirectoryFrom(Path, state^.cwd, NewDir);
|
Validity := driver.storage.vfs.ChangeDirectoryFrom(Path, state^.cwd, NewDir);
|
||||||
case Validity of
|
case Validity of
|
||||||
pvDirectory: begin
|
pvDirectory: begin
|
||||||
kfree(void(state^.cwd));
|
kfree(void(state^.cwd));
|
||||||
@@ -410,7 +410,7 @@ var
|
|||||||
begin
|
begin
|
||||||
if STRLL_Size(state^.dir_stack) > 0 then begin
|
if STRLL_Size(state^.dir_stack) > 0 then begin
|
||||||
wd := STRLL_Get(state^.dir_stack, STRLL_Size(state^.dir_stack) - 1);
|
wd := STRLL_Get(state^.dir_stack, STRLL_Size(state^.dir_stack) - 1);
|
||||||
Validity := driver.storage.vfs.changeDirectoryFrom(wd, state^.cwd, NewDir);
|
Validity := driver.storage.vfs.ChangeDirectoryFrom(wd, state^.cwd, NewDir);
|
||||||
if Validity = pvDirectory then begin
|
if Validity = pvDirectory then begin
|
||||||
kfree(void(state^.cwd));
|
kfree(void(state^.cwd));
|
||||||
state^.cwd := NewDir;
|
state^.cwd := NewDir;
|
||||||
@@ -696,7 +696,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end else begin
|
end else begin
|
||||||
{ No built-in command found — try file dispatch }
|
{ No built-in command found — try file dispatch }
|
||||||
absPath := driver.storage.vfs.makeAbsolutePathFrom(params^.Param, state^.cwd);
|
absPath := driver.storage.vfs.MakeAbsolutePathFrom(params^.Param, state^.cwd);
|
||||||
if absPath <> nil then begin
|
if absPath <> nil then begin
|
||||||
if is_bg then begin
|
if is_bg then begin
|
||||||
{ Background file dispatch }
|
{ Background file dispatch }
|
||||||
|
|||||||
@@ -152,36 +152,35 @@ var
|
|||||||
fh : TFileHandle;
|
fh : TFileHandle;
|
||||||
err : TError;
|
err : TError;
|
||||||
fsize : uint32;
|
fsize : uint32;
|
||||||
errb : uint8;
|
|
||||||
bytesRead : uint32;
|
bytesRead : uint32;
|
||||||
processCtx : PProcessContext;
|
processCtx : PProcessContext;
|
||||||
begin
|
begin
|
||||||
debug.tracer.push_trace('wasmrunner.handler');
|
debug.tracer.push_trace('wasmrunner.handler');
|
||||||
wasm_file_handler := 0;
|
wasm_file_handler := 0;
|
||||||
|
|
||||||
{ 1. Get file size }
|
{ 1. Open file once — omRead pre-loads the data and gives us the size }
|
||||||
errb := 0;
|
err := eNone;
|
||||||
fsize := driver.storage.vfs.FileSize(path, @errb);
|
fh := driver.storage.vfs.OpenFile(path, omRead, @err);
|
||||||
if (fsize = 0) or (errb <> 0) then begin
|
if (fh = 0) or (err <> eNone) then begin
|
||||||
io.stdio.bufWriteStrLn(stderr_buf, 'WASM: cannot determine file size');
|
io.stdio.bufWriteStrLn(stderr_buf, 'WASM: cannot open file');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
fsize := driver.storage.vfs.FileSizeFromHandle(fh);
|
||||||
|
if fsize = 0 then begin
|
||||||
|
driver.storage.vfs.CloseFile(fh);
|
||||||
|
io.stdio.bufWriteStrLn(stderr_buf, 'WASM: file is empty or cannot determine size');
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ 2. Allocate buffer and read file }
|
{ 2. Allocate buffer and read file }
|
||||||
buf := puint8(kalloc(fsize));
|
buf := puint8(kalloc(fsize));
|
||||||
if buf = nil then begin
|
if buf = nil then begin
|
||||||
|
driver.storage.vfs.CloseFile(fh);
|
||||||
io.stdio.bufWriteStrLn(stderr_buf, 'WASM: out of memory');
|
io.stdio.bufWriteStrLn(stderr_buf, 'WASM: out of memory');
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
err := eNone;
|
|
||||||
fh := driver.storage.vfs.OpenFile(path, omReadOnly, wmRewrite, @err);
|
|
||||||
if fh = 0 then begin
|
|
||||||
kfree(void(buf));
|
|
||||||
io.stdio.bufWriteStrLn(stderr_buf, 'WASM: cannot open file');
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
bytesRead := driver.storage.vfs.ReadFile(fh, 0, buf, fsize);
|
bytesRead := driver.storage.vfs.ReadFile(fh, 0, buf, fsize);
|
||||||
driver.storage.vfs.CloseFile(fh);
|
driver.storage.vfs.CloseFile(fh);
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,9 @@ uses
|
|||||||
driver.storage.vfs,
|
driver.storage.vfs,
|
||||||
driver.video,
|
driver.video,
|
||||||
arch.x86.memory.virtual,
|
arch.x86.memory.virtual,
|
||||||
|
core.enc.fnv1a,
|
||||||
|
core.enc.djb2,
|
||||||
|
core.ds.bloom,
|
||||||
app.volcmd,
|
app.volcmd,
|
||||||
driver.storage.vol.mgr,
|
driver.storage.vol.mgr,
|
||||||
app.vterminal,
|
app.vterminal,
|
||||||
@@ -349,6 +352,9 @@ begin
|
|||||||
core.ds.prio.UnitTest;
|
core.ds.prio.UnitTest;
|
||||||
driver.storage.vfs.UnitTest;
|
driver.storage.vfs.UnitTest;
|
||||||
driver.storage.test.UnitTest;
|
driver.storage.test.UnitTest;
|
||||||
|
core.enc.fnv1a.UnitTest;
|
||||||
|
core.enc.djb2.UnitTest;
|
||||||
|
core.ds.bloom.UnitTest;
|
||||||
|
|
||||||
{ Initialize driver.video.desktop environment }
|
{ Initialize driver.video.desktop environment }
|
||||||
boot.splash.update(100, 'Booting desktop...');
|
boot.splash.update(100, 'Booting desktop...');
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@
|
|||||||
Include->Hashmap - Basic Hashmap Implementation.
|
Include->Hashmap - Basic Hashmap Implementation.
|
||||||
|
|
||||||
@author(Kieron Morris <[email protected]>)
|
@author(Kieron Morris <[email protected]>)
|
||||||
|
@author(Aaron Hance <[email protected]>)
|
||||||
}
|
}
|
||||||
unit core.ds.hashmap;
|
unit core.ds.hashmap;
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
memory.heap,
|
memory.heap,
|
||||||
core.enc.md5,
|
core.enc.fnv1a,
|
||||||
core.strings,
|
core.strings,
|
||||||
io.syslog,
|
io.syslog,
|
||||||
debug.tracer,
|
debug.tracer,
|
||||||
@@ -64,19 +65,8 @@ procedure forEach(map : PHashMap; cb : THashForEachCb; ud : void);
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
function KeyHash(key : pchar) : uint32;
|
function KeyHash(key : pchar) : uint32;
|
||||||
var
|
|
||||||
KeyLength : uint32;
|
|
||||||
MD5_Hash : PMD5Digest;
|
|
||||||
Hash128 : puint128;
|
|
||||||
Hash32 : uint32;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
KeyLength:= StringSize(key);
|
KeyHash := Hash_FNV1a32(void(uint32(key)), StringSize(key));
|
||||||
MD5_Hash:= MD5Buffer(puint8(key), KeyLength);
|
|
||||||
Hash128:= puint128(MD5_Hash);
|
|
||||||
Hash32:= MD5To32(Hash128);
|
|
||||||
KeyHash:= Hash32;
|
|
||||||
kfree(void(MD5_Hash));
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function hashIndex(size : uint32; hash : uint32) : uint32;
|
function hashIndex(size : uint32; hash : uint32) : uint32;
|
||||||
|
|||||||
@@ -195,6 +195,32 @@ type
|
|||||||
IsMinHeap : boolean;
|
IsMinHeap : boolean;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ ------ Bloom Filter ------ }
|
||||||
|
|
||||||
|
{**
|
||||||
|
@abstract Pointer to a bloom filter.
|
||||||
|
**}
|
||||||
|
PBloomFilter = ^TBloomFilter;
|
||||||
|
|
||||||
|
{**
|
||||||
|
@abstract Probabilistic set-membership filter using double hashing.
|
||||||
|
@discussion The bit array is a flat kalloc'd byte buffer of
|
||||||
|
ceil(BitCount / 8) bytes. Membership tests use k independent
|
||||||
|
hash positions derived from two base hashes (FNV-1a + DJB2)
|
||||||
|
via double hashing: h_i(x) = (h1(x) + i * h2(x)) mod BitCount.
|
||||||
|
False positives are possible; false negatives are not.
|
||||||
|
@field Bits Pointer to the flat bit-array buffer.
|
||||||
|
@field BitCount Total number of bits in the filter (m).
|
||||||
|
@field HashCount Number of hash functions applied per element (k).
|
||||||
|
@field Count Number of elements inserted.
|
||||||
|
**}
|
||||||
|
TBloomFilter = record
|
||||||
|
Bits : void;
|
||||||
|
BitCount : uint32;
|
||||||
|
HashCount : uint32;
|
||||||
|
Count : uint32;
|
||||||
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
end.
|
end.
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -148,6 +148,10 @@ begin
|
|||||||
entry := PDirectory_Entry(LL_Add(dirList));
|
entry := PDirectory_Entry(LL_Add(dirList));
|
||||||
entry^.fileName := stringCopy(Files[i].Name);
|
entry^.fileName := stringCopy(Files[i].Name);
|
||||||
entry^.entryType := fileEntry;
|
entry^.entryType := fileEntry;
|
||||||
|
entry^.fileSize := Files[i].Size;
|
||||||
|
entry^.modifiedDate := 0;
|
||||||
|
entry^.modifiedTime := 0;
|
||||||
|
entry^.attributes := 0;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
if status <> nil then status^ := 0;
|
if status <> nil then status^ := 0;
|
||||||
|
|||||||
@@ -41,11 +41,12 @@ type
|
|||||||
Directory : pchar; { directory path within the volume }
|
Directory : pchar; { directory path within the volume }
|
||||||
FileName : pchar; { filename within that directory }
|
FileName : pchar; { filename within that directory }
|
||||||
OpenMode : uint8; { TOpenMode ordinal — avoids VFS type dependency }
|
OpenMode : uint8; { TOpenMode ordinal — avoids VFS type dependency }
|
||||||
WriteMode : uint8; { TWriteMode ordinal }
|
|
||||||
DataBuffer : puint32; { pre-loaded data for small files, nil otherwise }
|
DataBuffer : puint32; { pre-loaded data for small files, nil otherwise }
|
||||||
DataSize : uint32; { size of pre-loaded data in bytes }
|
DataSize : uint32; { size of pre-loaded data in bytes }
|
||||||
Loaded : boolean; { true if pre-loaded into DataBuffer }
|
Loaded : boolean; { true if pre-loaded into DataBuffer }
|
||||||
StreamOff : uint32; { current byte offset for streaming / on-demand reads }
|
StreamOff : uint32; { current byte offset for streaming / on-demand reads }
|
||||||
|
DeviceOps : pointer; { PVFSDeviceOps — non-nil for device FDs }
|
||||||
|
DeviceData : pointer; { opaque data passed to device callbacks }
|
||||||
end;
|
end;
|
||||||
|
|
||||||
PFDTable = ^TFDTable;
|
PFDTable = ^TFDTable;
|
||||||
@@ -113,6 +114,8 @@ begin
|
|||||||
entry^.Loaded := false;
|
entry^.Loaded := false;
|
||||||
entry^.DataSize := 0;
|
entry^.DataSize := 0;
|
||||||
entry^.StreamOff := 0;
|
entry^.StreamOff := 0;
|
||||||
|
entry^.DeviceOps := nil;
|
||||||
|
entry^.DeviceData := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure fd_table_free(table : PFDTable);
|
procedure fd_table_free(table : PFDTable);
|
||||||
|
|||||||
@@ -133,9 +133,10 @@ begin
|
|||||||
validity := driver.storage.vfs.PathValid(absPath);
|
validity := driver.storage.vfs.PathValid(absPath);
|
||||||
if validity <> pvFile then exit;
|
if validity <> pvFile then exit;
|
||||||
|
|
||||||
{ 2. Open the file and read the header bytes }
|
{ 2. Open the file in stream mode — only reads the bytes we ask for,
|
||||||
|
avoids pre-loading the entire file just to check a few magic bytes. }
|
||||||
err := eNone;
|
err := eNone;
|
||||||
fh := driver.storage.vfs.OpenFile(absPath, omReadOnly, wmRewrite, @err);
|
fh := driver.storage.vfs.OpenFile(absPath, omStream, @err);
|
||||||
if fh = 0 then exit;
|
if fh = 0 then exit;
|
||||||
|
|
||||||
memset(uint32(@headerBuf[0]), 0, MAX_MAGIC_LEN);
|
memset(uint32(@headerBuf[0]), 0, MAX_MAGIC_LEN);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -90,6 +90,8 @@ type
|
|||||||
eTooManyOpenFiles, { per-process FD table full }
|
eTooManyOpenFiles, { per-process FD table full }
|
||||||
eInvalidHandle, { TFileHandle does not refer to an open FD }
|
eInvalidHandle, { TFileHandle does not refer to an open FD }
|
||||||
eNotStreamMode, { SeekFile called on a non-omStream handle }
|
eNotStreamMode, { SeekFile called on a non-omStream handle }
|
||||||
|
eFileNotLoaded, { ReadFile on a pre-load handle whose data is not yet loaded }
|
||||||
|
eAlreadyExists, { generic: target name already exists (symlink, file, etc.) }
|
||||||
|
|
||||||
{ Disk / capacity errors }
|
{ Disk / capacity errors }
|
||||||
eDiskFull, { FS reports no free clusters/blocks }
|
eDiskFull, { FS reports no free clusters/blocks }
|
||||||
@@ -148,11 +150,17 @@ type
|
|||||||
PPDeleteFileHook = procedure(volume : PStorage_Volume; filePath : pchar; status : puint32);
|
PPDeleteFileHook = procedure(volume : PStorage_Volume; filePath : pchar; status : puint32);
|
||||||
PPDeleteDirHook = procedure(volume : PStorage_Volume; path : pchar; status : puint32);
|
PPDeleteDirHook = procedure(volume : PStorage_Volume; path : pchar; status : puint32);
|
||||||
PPIdentifyHook = function(volume : PStorage_Volume) : boolean;
|
PPIdentifyHook = function(volume : PStorage_Volume) : boolean;
|
||||||
|
PPRenameFileHook = procedure(volume : PStorage_Volume; filePath : pchar; newName : pchar; status : puint32);
|
||||||
{ Offset-based read: reads byteCount bytes starting at byte offset into the file.
|
{ Offset-based read: reads byteCount bytes starting at byte offset into the file.
|
||||||
Returns the number of bytes actually read.
|
Returns the number of bytes actually read.
|
||||||
Filesystems that do not implement this leave the field nil and VFS falls back
|
Filesystems that do not implement this leave the field nil and VFS falls back
|
||||||
to the load-all readCallback behaviour. }
|
to the load-all readCallback behaviour. }
|
||||||
PPReadOffsetHook = function(volume : PStorage_Volume; directory : pchar; fileName : pchar; offset : uint32; buffer : puint32; byteCount : uint32) : uint32;
|
PPReadOffsetHook = function(volume : PStorage_Volume; directory : pchar; fileName : pchar; offset : uint32; buffer : puint32; byteCount : uint32) : uint32;
|
||||||
|
{ Offset-based write: writes byteCount bytes starting at byte offset into the file.
|
||||||
|
Returns the number of bytes actually written.
|
||||||
|
Filesystems that do not implement this leave the field nil; VFS returns 0
|
||||||
|
for stream-mode writes on volume FDs. }
|
||||||
|
PPWriteOffsetHook = function(volume : PStorage_Volume; directory : pchar; fileName : pchar; offset : uint32; buffer : puint32; byteCount : uint32) : uint32;
|
||||||
|
|
||||||
{ === Async filesystem hook core.types ===
|
{ === Async filesystem hook core.types ===
|
||||||
Each mirrors the corresponding sync hook but receives a TIOCallback + callbackData.
|
Each mirrors the corresponding sync hook but receives a TIOCallback + callbackData.
|
||||||
@@ -227,6 +235,8 @@ type
|
|||||||
identifyCallback : PPIdentifyHook;
|
identifyCallback : PPIdentifyHook;
|
||||||
{ Offset-based read for streaming mode — nil if not implemented }
|
{ Offset-based read for streaming mode — nil if not implemented }
|
||||||
readOffsetCallback : PPReadOffsetHook;
|
readOffsetCallback : PPReadOffsetHook;
|
||||||
|
{ Offset-based write for streaming mode — nil if not implemented }
|
||||||
|
writeOffsetCallback : PPWriteOffsetHook;
|
||||||
{ Async format — nil if FS only supports synchronous create }
|
{ Async format — nil if FS only supports synchronous create }
|
||||||
createAsyncCallback : PPCreateAsyncHook;
|
createAsyncCallback : PPCreateAsyncHook;
|
||||||
{ Async variants of the main I/O hooks — nil if FS only supports sync.
|
{ Async variants of the main I/O hooks — nil if FS only supports sync.
|
||||||
@@ -237,6 +247,7 @@ type
|
|||||||
readDirAsyncCallback : PPReadDirAsyncHook;
|
readDirAsyncCallback : PPReadDirAsyncHook;
|
||||||
deleteFileAsyncCallback : PPDeleteFileAsyncHook;
|
deleteFileAsyncCallback : PPDeleteFileAsyncHook;
|
||||||
deleteDirAsyncCallback : PPDeleteDirAsyncHook;
|
deleteDirAsyncCallback : PPDeleteDirAsyncHook;
|
||||||
|
renameFileCallback : PPRenameFileHook;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Generic storage volume }
|
{ Generic storage volume }
|
||||||
@@ -253,8 +264,12 @@ type
|
|||||||
|
|
||||||
{ Generic directory entry }
|
{ Generic directory entry }
|
||||||
TDirectory_Entry = record
|
TDirectory_Entry = record
|
||||||
fileName : pchar;
|
fileName : pchar;
|
||||||
entryType : TDirectory_Entry_Type;
|
entryType : TDirectory_Entry_Type;
|
||||||
|
fileSize : uint32;
|
||||||
|
modifiedDate : uint16; { FAT-style: bits 15-9=year-1980, 8-5=month, 4-0=day }
|
||||||
|
modifiedTime : uint16; { FAT-style: bits 15-11=hour, 10-5=min, 4-0=sec/2 }
|
||||||
|
attributes : uint8; { FS-specific attribute bits }
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TDrive_Error = record
|
TDrive_Error = record
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user