Hi, I have updated (5+ hours) FORMAT to version 0.91r:

http://www.coli.uni-sb.de/~eric/stuff/soft/by-others/ format-0.91r.zip

Version 0.91r (18 Jul 2004) 
              Changes by Eric Auer: 
              - unless you use the /D option, we now use boring MS compat 
                errorlevels: 0 ok, 3 user abort, 4 fatal, 5 not confirmed 
                (WITH /D option: see help.txt for new errorlevels...!) 
              - attempt to lock non-existing drives is recognized as such 
                (in FAT16 DOS, attempt to get parameters of non-existing
                drive, *after* format confirmation, is recognized... This
                is a kludge as FreeDOS 2035 int 21.36/21.1c return wrong
                errors for unformatted *existing* drives. Happy fixing!?) 
              - now unlocking drives in case of an abort (not for ^C yet)
              - prompts for label if no /V:... given, unless /Y used
              - Mirror aborts if it would overwrite used data, SafeFormat
                gives a warning if mirror data damaged unformateable data
              - shortended debug messages even more (e.g. in createfs)

So Aitor should now be happy with the features. I also noticed that atoi()
parses /f:1440k and /f:1440 and /f:1440unitscalledkilobytes all the same,
so for full MS syntax only /f:1.44... stuff is missing (so what?).

Summary of the highlights:
- MS compatible errorlevels in normal mode
- more informative errorlevels in /D mode
- unlocks drive if an error happens
- prompts for a volume label (if none given at command line and if not in /y
  noninteractive mode). For sequential floppy mode, FORMAT always asks for
  labels for subsequent disks.
- MIRROR refuses to damage the contents of used clusters. Only SafeFormat is
  allowed to damage data in order to make UnFormat possible in any case.

The binary size is still slightly below 32768 bytes ;-)).

Happy testing!

When trying to make FORMAT properly distinguish between
- SafeFormatable drives
- not yet formatted drives and
- non-existing drives
I found that FreeDOS kernel is really buggy in several aspects here.
The FAT32 version of the kernel is best: LOCK will fail for non-existing
drives. For existing drives, I can distinguish between formatted and not
yet formatted drives by reading the boot sector.
The FAT16 version compatible calls are worse: int 21.440d.0860 is okay
for detecting non-existing drives, BUT I have to wait with this call
until AFTER the "do you really want to..." confirmation and LOCK call.

It would be better if int 21.36 and int 21.1c would work properly. But:
When I call int 21.36 for a not yet formatted drive (it properly detects
non-existing drives, at least), I trigger an INTERACTIVE critical error.
This confuses people, so I cannot use it in FORMAT. All four choices,
abort, ignore, retry, fail, work, but of course RETRY will be infinite
and IGNORE is dangerous here, so the whole interactivity is a BUG in our
kernel. Correct reaction would be to return error 7, unknown media type
(in terms of critical error, that is category "fail"). For non-existing
drives, a special (non-error) return value is already defined and working.

Things got even worse when I tried int 21.1c as an alternative: This is
less recommended because Win9x reportedly has bugs in this function (it
might help to check sector size as extra test). For non-existing drives,
the correct non-error special return value is returned, but for not yet
formatted drives, the whole kernel CRASHES!

DS = 0xcf ES=SS = from caller CS = wrong
SP = 0xc33d AX = 0x3504 BX = 0x574 CX = 0x6FE DX = 4 SI = 0x574 DI = 0x0E BP = 0x70
... but that probably does not help much because CS already went mad.

Even happens in 2035a:
debug
w somenonsense 4 0 1 (zap boot sector of E:, don't try at home)
q
reboot
debug
acs:100
mov ah,1c
mov dl,5
int 21
nop
int 20
gcs:106 (drive is 1-based in int 21.1c, so we again check E:)
--> DOSEmu tells:

AX=3804  BX=1a92  CX=0000  DX=00d2  SI=0586  DI=000c  SP=ffe0  BP=0070
DS=00d2  ES=0889  FS=0000  GS=0000  FL=0246
CS:IP=0000:0002       SS:SP=0889:ffe0
0000:0002 6303             arpl    [bp+di],ax

SP was FFFE and segments were 889 when I did "gcs:106", so:
DS points to kernel, AH is "something", AL pretends that the disk would
actually be formatted, BX pretends that the whole disk would be free,
CX is either not set yet or tells "sector size 0", DX is the kernel segment,
SI is "something", DI is "something" (maybe we are in a messed up critical
error state "general failure" here?), BP is yet another kernel segment. Stack:

0889:ffe0 07 03 FF FF 46 00 00 1C 00 00 00 00 05 00 00 00  ..F...........
0889:fff0 00 00 00 00 89 08 89 08 06 01 89 08 02 02 00 00  ................

And yes, looks INTish:

...
ffff:02f3 FE062003         inc     byte ptr [0320]
ffff:02f7 FE0E2103         dec     byte ptr [0321]
ffff:02fb 268E163000       mov     ss,es:[0030]
ffff:0300 268B262E00       mov     sp,es:[002e]
ffff:0305 CD24             int     0x24
ffff:0307 FC               cld
ffff:0308 FA               cli
ffff:0309 2E8B2E3100       mov     bp,cs:[0031]
...

The call seems to start at ffff:2b8, code is:
push bp / mov bp,sp / push si / push di / ah=[bp+4] / al=[bp+6] / di = [bp+8] /
si = [bp+a] / bp = [bp+c] / cli / es=[330] / push [es:30] / push [es:2e] /
push [33e] / push [586] / push [584] / push [586] / push [584] / mov [588],sp /
inc byte [320] / dec byte [321] / ss=[es:30] / sp=[es:2e] / int 24 / cld /
cli / bp=[cs:31] / ds=bp / ss=bp / sp=[588] / pop [584] / pop [586] / pop [584] /
pop [586] / pop [33e] / es=[330] / pop [es:2e] / pop [es:30] / bp=sp /
ah=[bp+8] / sti / [320] = 0 / inc byte [321] / if AL != 0 352 / if AL & 20 352 /
al=3 / 352: if al != 1 35d / if AH & 10 35d / al=3 / 35d: if al != 3 368 /
if AH & 8 368 / al=2 / 368: if al == 2 372 / ah=0 / pop di / pop si / pop bp /
ret
372: es=ax=[330] / cmp ax,[es:16] / al=3 / jz 36c (that "ah=0 / pop di / ...") /
cli / ss=bp=[586] / sp=bp=[584] / [320]=1 / ax=4c00 / [bp]=ax / sti / jmp 1a3
(1a3 seems to be the main int 21 dispatcher, first checking for those functions
which do not need a stack. It starts by setting ds=dx=[cs:31], so the entry
from "userland" is a bit earlier, probably 18e, where registers are pushed...)

The above is, as said, for an 2035a kernel: 15 Jul 2004 Arkady/Lucho 386 FAT32
Borland kernel. Looks like something messes up the int 24 vector at the wrong
moment - when it is just about to be called. So probably int 21.1c is attempting
to do the same WRONG interactive critical error handling for unformatted disks
as int 21.36 does. Only difference: int 21.36 does not crash for some reason.

Happy debugging :-|.

Eric

PS: Fixing int 21.36 would be useful not only for FORMAT but also for
WHICHFAT and other things. All three cases - FAT, not formatted and no drive
letter - should be distinguishable. I also noticed that the DEFAULT BPB
as reported by DOS seems to be quite exotic if you have a FAT16 filesystem
on a FAT32 partition (people do have such things: MS FDISK even displays the
filesystem FAT type if it differs from partition FAT type, which is kind of
illogical... Free FDISK displays partition FAT type, e.g. in /INFO /TECH mode,
but I must tell that it was hard to guess "FDISK 3 /INFO /TECH" as the right
syntax to check drive 0x83 and get a partition ID dump (decimal, by the way)
...).

[Somebody had reported "kernel does not see my drives" - he had a FAT16
FreeDOS and FAT32 partition types: MS DOS 7, because it can do FAT32, found
all drives but everything including MS FDISK pretended that the drives would
be 100% native FAT16, while in fact partition type was FAT32 and the file-
systems were actually FAT16. You cannot blame FreeDOS FAT16 kernel for not
detecting the drives, but still a suprising MS / FreeDOS difference... 8-)]

(I told him to use a FAT32 kernel or fix the partition types to FAT16 or
convert the filesystems to real FAT32 or ... to solve his problem ;-)).