Mocka: the stat error
While doing some tests with Mocka, I found out that the stat function cannot be used anymore, due to a change in the C sources in /sys/stat.h, probably due to the changeover to libc several years ago. In the table below you will find the old and the new definitions.
| Field | Type | Offset | Old stat | Offset | New stat |
|---|---|---|---|---|---|
| stDev | devT | 00 | SHORTCARD | 00 | ARRAY [0..1] OF CARDINAL |
| pad1 | SHORTCARD | 02 | SHORTCARD | 08 | SHORTCARD |
| stIno | inoT | 04 | LONGCARD | 0A | LONGCARD |
| stMode | umodeT | 08 | SHORTCARD | 0E | LONGCARD |
| stNlink | nlinkT | 0A | SHORTCARD | 12 | LONGCARD |
| stUid | uidT | 0C | SHORTCARD | 16 | LONGCARD |
| stGid | gidT | 0E | SHORTCARD | 1A | LONGCARD |
| stRdev | devT | 10 | SHORTCARD | 1E | ARRAY [0..1] OF CARDINAL |
| pad2 | SHORTCARD | 12 | SHORTCARD | 26 | SHORTCARD |
| stSize | offT | 14 | LONGINT | 28 | LONGINT |
| stBlksize | LONGCARD | 18 | LONGCARD | 2C | LONGCARD |
| stBlocks | LONGCARD | 1C | LONGCARD | 30 | LONGCARD |
| stAtime | timeT | 20 | LONGINT | 34 | LONGINT |
| unused1 | LONGCARD | 24 | LONGCARD | 38 | LONGCARD |
| stMtime | timeT | 28 | LONGINT | 3C | LONGINT |
| unused2 | LONGCARD | 2C | LONGCARD | 40 | LONGCARD |
| stCtime | timeT | 30 | LONGINT | 44 | LONGINT |
| unused3 | LONGCARD | 34 | LONGCARD | 48 | LONGCARD |
| unused4 | LONGCARD | 38 | LONGCARD | 4C | LONGCARD |
| unused5 | LONGCARD | 3C | LONGCARD | 50 | LONGCARD |
This makes the record, supplied by the 'stat' function considerably larger than what our Mocka stat still expects... The old stat record is 64 bytes, the new one is 84 bytes. Sounds like another buffer overrun to me...
The workaround
I posted the problem to the Mocka mailinglist and to rubino at ipd dot info dot uni-karlsruhe dot de (if you cut and paste these letters into the Kmail address field, you're in for a surprise. Try it!). Still, I wanted to see if I could determine the filesize in another way. So I came up with a follow-up of the 'System command' topic which I published some months ago.
The general idea was to have the command 'ls -l filename' issued and then the letters should be caught by
stdin via InOut.Read commands. But that failed. The letters just seem to get lost, when they march from the
System command towards stdin. If I recall well, /dev/null is also on their road and they might have gotten
curious.
So, if the pipe is broken, another mechanism was used: the temporary file. See it in the sourcecode below:
MODULE fs;
FROM SYSTEM IMPORT ADR;
FROM SysLib IMPORT system;
IMPORT TextIO;
IMPORT InOut;
IMPORT ASCII;
VAR fd : TextIO.File;
ch : CHAR;
ok : BOOLEAN;
str : ARRAY [0..31] OF CHAR;
PROCEDURE SystemCommand (VAR command : ARRAY OF CHAR) : BOOLEAN;
BEGIN
IF system (ADR (command) ) = 0 THEN
RETURN TRUE
ELSE
RETURN FALSE
END
END SystemCommand;
BEGIN
IF SystemCommand ("ls -l fs.mod >.tmp.tmp") = TRUE THEN
TextIO.OpenInput (fd, ".tmp.tmp");
IF NOT TextIO.Done () THEN
InOut.WriteString ("Opening of .tmp.tmp failed"); InOut.WriteLn;
HALT
END;
TextIO.GetString (fd, str);
TextIO.GetString (fd, str);
TextIO.GetString (fd, str);
TextIO.GetString (fd, str);
TextIO.GetString (fd, str);
InOut.WriteString ("Filesize is ");
InOut.WriteString (str);
InOut.WriteLn;
TextIO.Close (fd);
TextIO.Erase (".tmp.tmp", ok);
IF NOT ok THEN InOut.WriteString ("Final error...") END
ELSE
InOut.WriteString ("ls failed"); InOut.WriteLn;
HALT
END
END fs.
I issue an 'ls' command and have the letters disappear in a file called '.tmp.tmp'. Then I open the file, read
five strings from it (the first four are garbage) and extract the filesize from the fifth string.
jan@beryllium:~/modula/test$ ls -l fs.mod -rw-r--r-- 1 jan users 1122 2007-02-25 01:42 fs.modWhen done, I erase the file. It works. To be usefull, the fifth 'TextIO.GetString (fd, str);' should of course be replaced by a 'TextIO.GetCard (fd, num);' command.
When I have an answer from Karlsruhe howmto tackle this problem, I will let you know via this same page.
Page created 25 February 2007,
Page equipped with GoogleBuster technology