add program to recover deleted files

This commit is contained in:
slederer 2025-05-31 22:19:10 +02:00
parent 057403b324
commit bde01e402c
4 changed files with 170 additions and 0 deletions

View file

@ -30,6 +30,7 @@ nativeprogs: nativecomp
$(PCOMP) ../progs/dumpdir.pas
$(PCOMP) ../progs/partmgr.pas
$(PCOMP) ../progs/xfer.pas
$(PCOMP) ../progs/recover.pas
$(SASM) ../lib/rommon.s
$(SASM) -A ../lib/rommon.s ../lib/rom.mem

View file

@ -27,6 +27,7 @@ py pcomp.py ..\progs\reclaim.pas
py pcomp.py ..\progs\dumpdir.pas
py pcomp.py ..\progs\partmgr.pas
py pcomp.py ..\progs\xfer.pas
py pcomp.py ..\progs\recover.pas
sasm ..\lib\rommon.s
sasm -A ..\lib\rommon.s ..\lib\rom.mem

167
progs/recover.pas Normal file
View file

@ -0,0 +1,167 @@
(* Copyright 2025 Sebastian Lederer. See the file LICENSE.md for details *)
program recover;
const PageMargin = 4;
var filename:string;
volid:integer;
(* we use some stuff internal to stdlib.pas *)
procedure getdirslot(volumeid:integer;slotNo:integer;var result:DirectorySlot;var error:integer);
external;
procedure openfile(volid:integer; slotno:integer; var dirslot:DirectorySlot; var aFile:File; mode:filemode);
external;
function openvolume:integer;
var volid:integer;
begin
openvolume := -1;
volid := findvolume(DefaultVolume);
if volid < 1 then
writeln('Volume ', DefaultVolume, ' not found.')
else
openvolume := volid;
end;
procedure waitForKey;
var c:char;
begin
writeln;
writeln('-- press any key to continue --');
c := conin;
end;
procedure copyfile(volid:integer;slotno:integer;oldname,newname:string);
var srcfile,destfile:file;
dirslot:DirectorySlot;
error:integer;
ch:char;
count:integer;
begin
(* to open the deleted source file, we emulate parts
of the open procedure from stdlib *)
getdirslot(volid, slotno, dirslot, error);
if not (SlotDeleted in dirslot.flags) or (dirslot.name <> oldname) then
writeln('Invalid slot ', slotno)
else
begin
openfile(volid, slotno, dirslot, srcfile, ModeReadOnly);
if error <> 0 then
writeln('Error opening file from slot ', slotno,
': ', ErrorStr(error))
else
begin
open(destfile, newname, ModeCreate);
if IOResult(destfile) = IOFileExists then
begin
write('File ', newname, ' already exists, overwrite? [y/n] ');
readln(ch);
if ch in ['Y', 'y'] then
open(destfile, newname, ModeOverwrite);
end;
if IOResult(destfile) <> 0 then
writeln('Error opening ', newname, ': ',
ErrorStr(IOResult(destfile)))
else
begin
(* taken from shell.pas copyFile *)
write('Recovering from slot ', slotno, ' to ', newname, '...');
count := 0;
while not eof(srcfile) do
begin
read(srcfile,ch);
write(destfile,ch);
count := count + 1;
if (count and 8191) = 0 then write('.');
end;
writeln;
close(destfile);
end;
close(srcfile);
end;
end;
end;
procedure recoverfile(volid:integer;wantedname:string);
var dirs:DirectorySlot;
i:integer;
lastSlot:integer;
error:integer;
screenW,screenH:integer;
count:integer;
datestr:string;
ftime:DateTime;
wantedslot:integer;
newname:string;
foundsomething:boolean;
begin
writeln('Files available for recovery:');
foundsomething := false;
newname := '';
GetTermSize(screenW, screenH);
count := PageMargin;
lastSlot := volumeTable[volid].part.dirSize - 1;
openvolumeid(volid);
for i := 0 to lastSlot do
begin
getdirslot(volid, i, dirs, error);
with dirs do
begin
if (SlotFirst in flags) or (SlotDeleted in flags) then
if name = wantedname then
begin
ftime := GetDateTime(dirs.modTime);
datestr := DateStr(ftime) + ' ' + TimeStr(ftime, true);
write('slot ', i:4, name:34, sizeBytes:8, datestr:21, ' ');
if SlotFirst in flags then write('Cur');
if SlotExtent in flags then write('Extent');
if SlotReserved in flags then write('Resvd');
if SlotDeleted in flags then write('Del');
if SlotFree in flags then write('Free');
if SlotEndScan in flags then write('End');
writeln;
foundsomething := true;
count := count + 1;
if count >= screenH then
begin
count := PageMargin;
waitForKey;
end;
if SlotEndScan in flags then break;
end;
end;
end;
if foundsomething then
begin
write('Slot no to recover> ');
readln(wantedslot);
if (wantedslot < 1) or (wantedslot >= volumeTable[volid].part.dirSize) then
writeln('Invalid slot number.')
else
begin
write('New filename> ');
readln(newname);
end;
if length(newname) > 0 then
copyfile(volid, wantedslot, wantedname, newname);
end;
closevolumeid(volid);
end;
begin
if ParamCount > 0 then
filename := ParamStr(1)
else
begin
write('Filename to recover> ');
readln(filename);
end;
volid := openvolume;
if volid > 0 then
recoverfile(volid, filename);
end.

View file

@ -535,6 +535,7 @@ def create_image_with_stuff(imgfile):
slotnr = putfile("../progs/editor.pas", None , f, part, partstart, slotnr)
slotnr = putfile("../progs/editor.prog", None , f, part, partstart, slotnr)
slotnr = putfile("../progs/xfer.prog", None , f, part, partstart, slotnr)
slotnr = putfile("../progs/recover.prog", None , f, part, partstart, slotnr)
listdir(f, part)