erwvegm@cs.vu.nl (Erwin van Egmond) (04/22/91)
Hi, I'm using TP5.5 and I want to know if and how I can find out on wich sector/cluster a file is placed. I must probably readout my FAT, but how do I do that? Is there someone out there who can help me? Please? Thankx in advance Erwin van Egmond <erwvegm@cs.vu.nl> P.S A while ago I asked something about GIF-pictures in een .EXE file. Someone asked me to pass along any info. Unfortunately I lost has email adress, so could that someone please send me his email adress again? -- ++ Erwin van Egmond UUCP: ...!mcsun!cs.vu.nl!erwvegm ++ ++ ++ ++ With a rubber duck, one's never alone ++ ++ -- "The Hitchhiker's Guide to the Galaxy" ++
focke@gmdzi.gmd.de (Stefan Focke) (04/22/91)
erwvegm@cs.vu.nl (Erwin van Egmond) writes: >Hi, > I'm using TP5.5 and I want to know if and how I can find out > on wich sector/cluster a file is placed. > I must probably readout my FAT, but how do I do that? > Is there someone out there who can help me? Please? Hello, it is not too hard to do that: - Read the boot-sektor to find out where your directory and FAT is - From the directory you get the first cluster of your file - Than you have to follow the FAT to find all clusters of your file - You have to find out if you have a 12-bit or a 16-Bit FAT (DOS 4.x) I do not know where you can find this information. Who can help? mfg Stefan ------------------------------------------------------------------- Stefan Focke Tel. 02241-14-2265 GMD-Z2.W e-mail: focke@gmdzi.uucp Postfach 1240 focke@gmdzi.gmd.de 5205 St. Augustin 1 ...!{uunet!mcvax!}unido!gmdzi!focke
campbell@cutmcvax.cs.curtin.edu.au (Trevor George Campbell CC361) (04/24/91)
focke@gmdzi.gmd.de (Stefan Focke) writes: >erwvegm@cs.vu.nl (Erwin van Egmond) writes: >> I must probably readout my FAT, but how do I do that? >- You have to find out if you have a 12-bit or a 16-Bit FAT (DOS 4.x) > I do not know where you can find this information. Who can help? you can tell if it is a 12 bit FAT by the fact that with a you can only access at most 4087 clusters (?? sectors) using a 12 bits.. (ie: 4096 - the flags that indicate end of file... = 4087). If on the other hand the disk has more than 4087 (strictly greater) then it must be a 16 bit FAT .... you can find out how many allocation units the disk has by checking the DPB (Drive Parameter Block) part of the boot block.... I don't have more info on me at this stage... but if you want I may be able to e-mail (or post if enough interest) the source for such a program (limited capabilities) in TURBO ASSEMBLER (with a bit more time I could probably do a quick program in TURBO PASCAL).... Trevor alias <**<TOMCAT>**>
Kai_Henningsen@ms.maus.de (Kai Henningsen) (04/27/91)
Stefan Focke focke @ gmdzi.gmd.de schrieb am 22.04.1991, 08:33
SF>Hello,
SF>
SF>it is not too hard to do that:
SF>
SF>- Read the boot-sektor to find out where your directory and FAT is
SF>- From the directory you get the first cluster of your file
SF>- Than you have to follow the FAT to find all clusters of your file
SF>- You have to find out if you have a 12-bit or a 16-Bit FAT (DOS 4.x)
SF> I do not know where you can find this information. Who can help?
Well, looks like it's time to post a program I wrote. The purpose is to set the
date of every directory on a disk to that of the youngest file within. Be
warned that, while the program runs without a problem on *my* harddisk (DOS 4),
I do not make any claims that the same will be true elsewhere - the risk is
yours, completely; I wrote this only for myself. You better make a backup
first!!
Also, the code is for TP 6.0, I use the inline assembler. As for comments, well
... Pascal is supposed to be selfdocumenting, no? But ask me if you don't
understand something ...
So, first a support unit ...
unit DosAbsUt;
interface
uses Dos;
type
BootRec = record
jmp: array[1..3] of byte;
OEM: array[1..8] of char;
bps: word;
spc: byte;
res: word;
nFAT: byte;
RootSz: word;
Size: word;
Media: byte;
spFAT: word;
spt: word;
nHeads: word;
res40: longint;
Size40: longint;
Phys: byte;
nix: byte;
Sig: byte; { $29 }
ID: longint;
Volume: array [1..11] of char;
nix2: array[1..8] of char;
end;
function AbsRead(Drive: byte; nSecs: word; Start: longint; var Buffer): word;
function AbsWrite(Drive: byte; nSecs: word; Start: longint; var Buffer): word;
function SecSize(Drive: byte): word;
procedure ResetDisk;
implementation
var
r: registers;
Dos4Abs : record
First: longint;
Count: word;
Buf: pointer;
end;
function AbsRead(Drive: byte; nSecs: word; Start: longint; var Buffer): word;
begin
if lo(dosversion)<4 then begin
asm {[f-]}
mov al, [Drive];
mov cx, [nSecs];
mov dx, word ptr [Start];
push ds;
lds bx, [Buffer];
int $25;
jc @Err;
xor ax, ax;
@Err:
popf;
pop ds;
mov [@Result], ax
end {[f+]};
end
else begin
with Dos4Abs do begin
First:=Start;
Count:=nSecs;
Buf:=@Buffer;
end;
asm {[f-]}
mov al, [Drive];
mov cx, -1;
push ds;
mov bx, seg Dos4Abs;
mov ds, bx;
mov bx, offset Dos4Abs;
int $25;
jc @Err;
xor ax, ax;
@Err:
popf;
pop ds;
mov [@Result], ax
end {[f+]};
end;
end;
function AbsWrite(Drive: byte; nSecs: word; Start: longint; var Buffer): word;
begin
if lo(dosversion)<4 then begin
asm {[f-]}
mov al, [Drive];
mov cx, [nSecs];
mov dx, word ptr [Start];
push ds;
lds bx, [Buffer];
int $26;
jc @Err;
xor ax, ax;
@Err:
popf;
pop ds;
mov [@Result], ax
end {[f+]};
end
else begin
with Dos4Abs do begin
First:=Start;
Count:=nSecs;
Buf:=@Buffer;
end;
asm {[f-]}
mov al, [Drive];
mov cx, -1;
push ds;
mov bx, seg Dos4Abs;
mov ds, bx;
mov bx, offset Dos4Abs;
int $26;
jc @Err;
xor ax, ax;
@Err:
popf;
pop ds;
mov [@Result], ax
end {[f+]};
end;
end;
function SecSize(Drive: byte): word;
begin
with r do begin
ah:=$1c;
dl:=drive+1;
msdos(r);
secsize:=cx;
end;
end;
procedure ResetDisk;
begin
r.ah:=$0d;
msdos(r);
end;
end.
MfG KaiKai_Henningsen@ms.maus.de (Kai Henningsen) (04/27/91)
... and now for the program proper ...
program DirDate;
uses Dos, DosAbsUt, m7utillo;
type
FATbuf= array[0..65520] of byte;
FATarray= array[0..16380] of ^FATbuf;
DIRent = record
Fn: array[1..8] of char;
Fe: array[1..3] of char;
Attr: byte;
Res: array[$0c..$15] of byte;
Timestamp: longint;
Start: word;
Size: longint;
end;
Direct= array[0..2046] of DIRent;
var
BootSec: ^BootRec;
p: string;
dr: byte;
err: word;
ss: word;
Clust: word;
DskSz: longint;
FAT0, ROOT0, DATA0: longint;
FATbytes: longint;
FATsecs: longint;
shortFAT: boolean;
FAT: ^FATarray;
i: longint;
dps, dpc: word;
Indent: word;
function FATentry(n: word): word;
type
wp = ^word;
var
b, bm, bd: longint;
w: word;
begin
if shortFAT then b:=n*longint(3) div 2
else b:=n*longint(2);
bm:=b mod ss;
bd:=b div ss;
if bm+1<ss then w:=wp(@FAT^[bd]^[bm])^
else w:=FAT^[bd]^[bm] or swap(FAT^[bd+1]^[0]);
if shortFAT then begin
if odd(n) then w:=w shr 4
else w:=w and $FFF;
if w>=$ff8 then w:=w or $f000;
end;
FATentry:=w;
end;
procedure WriteName(n,e: string);
begin
trim(n);
trim(e);
if e='' then write(n,'':12-length(n))
else write(n,'.',e,'':11-length(n)-length(e));
end;
procedure WriteDate(ts: longint);
var
dt : DateTime; { For Pack/UnpackTime}
function LeadingZero(w : Word) : String;
var
s : String;
begin
Str(w:0,s);
if Length(s) = 1 then
s := '0' + s;
LeadingZero := s;
end;
begin
UnpackTime(ts,dt);
with dt do
begin
Write(day:2,'.',month:2,'.',year,' ',
LeadingZero(hour),':',LeadingZero(min),':',LeadingZero(sec));
end;
end;
function TraverseSubdir(Start: word): longint;
forward;
function Process(var D: DIRent; var dt0: longint): boolean;
var
dt: longint;
begin
Process:=false;
with D do begin
case Fn[1] of
#0: Process:=true;
#$E5: ;
else begin
write('':indent*2);
writename(Fn,Fe);
write(' ');
writedate(Timestamp);
writeln;
if Fn[1]<>'.' then begin
if (attr and directory)=directory then begin
dt:=TraverseSubdir(Start);
{ if Timestamp<dt then}
Timestamp:=dt;
write('':indent*2);
writename(Fn,Fe);
write(' ');
writedate(Timestamp);
writeln;
end;
if Timestamp>dt0 then dt0:=Timestamp;
end
else Timestamp:=0;
end;
end;
end;
end;
procedure TraverseRoot;
var
CurDir: ^Direct;
i: word;
cur: word;
var dt: longint;
begin
dt:=0;
Indent:=0;
getmem(CurDir, ss);
i:=0;
cur:=$ffff;
while (i<BootSec^.RootSz) do begin
if (i div dps)<>cur then begin
if cur<>$ffff then begin
err:=AbsWrite(dr, 1, ROOT0+cur, CurDir^);
if err<>0 then runerror(err);
end;
cur:=i div dps;
err:=AbsRead(dr, 1, ROOT0+cur, CurDir^);
if err<>0 then runerror(err);
end;
if Process(CurDir^[i mod dps], dt) then i:=$ffff
else inc(i);
end;
err:=AbsWrite(dr, 1, ROOT0+cur, CurDir^);
if err<>0 then runerror(err);
freemem(CurDir, ss);
end;
function TraverseSubdir(Start: word): longint;
var
CurDir: ^Direct;
i: word;
cur: word;
dt: longint;
Last: word;
begin
dt:=0;
inc(Indent);
getmem(CurDir, Clust*ss);
i:=0;
cur:=$ffff;
Last:=0;
while (i<$FFFF) do begin
if (i div dpc)<>cur then begin
if cur<>$ffff then begin
err:=AbsWrite(dr, Clust, DATA0+longint(Last)*Clust, CurDir^);
if err<>0 then runerror(err);
end;
cur:=i div dpc;
if (Start>=$FFF8) or (Start<2) then begin
fillchar(CurDir^, Clust*ss, 0);
Last:=0;
end
else begin
err:=AbsRead(dr, Clust, DATA0+longint(Start)*Clust, CurDir^);
if err<>0 then runerror(err);
Last:=Start;
Start:=FATentry(Start);
end;
end;
if Process(CurDir^[i mod dpc], dt) then i:=$ffff
else inc(i);
end;
if Last<>0 then begin
err:=AbsWrite(dr, Clust, DATA0+longint(Last)*Clust, CurDir^);
if err<>0 then runerror(err);
end;
freemem(CurDir, Clust*ss);
dec(Indent);
TraverseSubdir:=dt;
end;
... rest follows ...
MfG KaiKai_Henningsen@ms.maus.de (Kai Henningsen) (04/27/91)
... last part ...
begin
writeln; writeln;
ResetDisk;
p:=paramstr(1);
if (paramcount<>1) or (length(p)<>1) then runerror;
dr:=ord(upcase(p[1]))-ord('A');
ss:=SecSize(dr);
getmem(bootsec, ss);
err:=absread(dr, 1, 0, bootsec^);
if err<>0 then runerror(err);
with bootsec^do begin
writeln(OEM);
FAT0:=res;
ROOT0:=FAT0+(longint(nFAT)*spFAT);
DATA0:=ROOT0+(RootSz*longint(sizeof(DIRent))+ss-1) div ss - 2*spc;
dps:=ss div sizeof(DIRent);
dpc:=ss*spc div sizeof(DIRent);
Clust:=spc;
DskSz:=size;
if size=0 then begin
dsksz:=size40;
if sig=$29 then begin
writeln(volume,' ',nix2);
end;
end;
FATbytes:=((DskSz-DATA0) div spc)*2;
if fatbytes<8000 then shortFAT:=true
else begin
FATsecs:=(FATbytes+(ss-1)) div ss;
shortFAT:=FATsecs<>spFAT;
end;
if shortFAT then begin
FATbytes:=(((DskSz-DATA0) div spc)*3+1) div 2;
FATsecs:=(FATbytes+(ss-1)) div ss;
end;
writeln(shortFAT,' ',FATsecs,' ',spFAT);
if FATsecs<>spFAT then runerror;
FATsecs:=spFAT;
FATbytes:=FATsecs*ss;
end;
writeln(FAT0,' ',ROOT0,' ',DATA0);
getmem(FAT, sizeof(pointer)*FATsecs);
for i:=0 to FATsecs-1 do begin
getmem(FAT^[i], ss);
err:=AbsRead(dr, 1, i+FAT0, FAT^[i]^);
if err<>0 then runerror(err);
end;
if FATentry(0)<>($ff00 or BootSec^.Media) then runerror;
if FATentry(1)<>$ffff then runerror;
TraverseRoot;
ResetDisk;
end.
MfG Kai