This chapter describes the DOS unit for Free pascal, both under DOS, OS/2, WINDOWS and LINUX. The unit was first written for DOS by Florian klämpfl. It was ported to LINUX by Mark May2.1, and enhanced by Michaël Van Canneyt.
Under non-DOS systems, some of the functionality is lost, as it is either impossible or meaningless to implement it. Other than that, the functionality for all operating systems is the same.
This chapter is divided in three sections:
{Bitmasks for CPU Flags} fcarry = $0001; fparity = $0004; fauxiliary = $0010; fzero = $0040; fsign = $0080; foverflow = $0800; {Bitmasks for file attribute} readonly = $01; hidden = $02; sysfile = $04; volumeid = $08; directory = $10; archive = $20; anyfile = $3F; fmclosed = $D7B0; fminput = $D7B1; fmoutput = $D7B2; fminout = $D7B3;
ComStr = String[255]; { For command-lines } PathStr = String[255]; { For full path for file names } DirStr = String[255]; { For Directory and (DOS) drive string } NameStr = String[255]; { For Name of file } ExtStr = String[255]; { For Extension of file }
SearchRec = Packed Record Fill : array[1..21] of byte; { Fill replaced with declarations below, for Linux} Attr : Byte; {attribute of found file} Time : LongInt; {last modify date of found file} Size : LongInt; {file size of found file} Reserved : Word; {future use} Name : String[255]; {name of found file} SearchSpec: String[255]; {search pattern} NamePos: Word; {end of path, start of name position} End;Under LINUX, the Fill array is replaced with the following:
SearchNum: LongInt; {to track which search this is} SearchPos: LongInt; {directory position} DirPtr: LongInt; {directory pointer for reading directory} SearchType: Byte; {0=normal, 1=open will close} SearchAttr: Byte; {attribute we are searching for} Fill: Array[1..07] of Byte; {future use}This is because the searching meachanism on Unix systems is substantially different from DOS's, and the calls have to be mimicked.
const filerecnamelength = 255; type FileRec = Packed Record Handle, Mode, RecSize : longint; _private : array[1..32] of byte; UserData : array[1..16] of byte; name : array[0..filerecnamelength] of char; End;FileRec is used for internal representation of typed and untyped files. Text files are handled by the following types :
const TextRecNameLength = 256; TextRecBufSize = 256; type TextBuf = array[0..TextRecBufSize-1] of char; TextRec = Packed Record Handle, Mode, bufsize, _private, bufpos, bufend : longint; bufptr : ^textbuf; openfunc, inoutfunc, flushfunc, closefunc : pointer; UserData : array[1..16] of byte; name : array[0..textrecnamelength-1] of char; buffer : textbuf; End;Remark that this is not binary compatible with the Turbo Pascal definition of TextRec, since the sizes of the different fields are different.
Registers = record case i : integer of 0 : (ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si, f51,di,f6,ds,f7,es,f8,flags,fs,gs : word); 1 : (al,ah,f9,f10,bl,bh,f11,f12, cl,ch,f13,f14,dl,dh : byte); 2 : (eax, ebx, ecx, edx, ebp, esi, edi : longint); End;The registers type is used in the MSDos call.
DateTime = record Year: Word; Month: Word; Day: Word; Hour: Word; Min: Word; Sec: word; End;The DateTime type is used in PackTime and UnPackTime for setting/reading file times with GetFTime and SetFTime.
DosError : integer;The DosError variable is used by the procedures in the DOS unit to report errors. It can have the following values :
2 | File not found. |
3 | path not found. |
5 | Access denied. |
6 | Invalid handle. |
8 | Not enough memory. |
10 | Invalid environment. |
11 | Invalid format. |
18 | No more files. |
DiskFree returns the number of free bytes on a disk. The parameter
Drive indicates which disk should be checked. This parameter is 1 for
floppy a:, 2 for floppy b:, etc. A value of 0 returns the free
space on the current drive.
Typically, the free space is the size of a disk block, multiplied by the
number of free blocks on the disk.
For LINUX only:
The diskfree and disksize functions need a file on the
specified drive, since this is required for the statfs system call.
These filenames are set in the initialization of the dos unit, and have
been preset to :
Program Example6; uses Dos; { Program to demonstrate the DiskSize and DiskFree function. } begin WriteLn('This partition size has ',DiskSize(0),' bytes'); WriteLn('Currently ',DiskFree(0),' bytes are free'); end.
DiskSize returns the total size (in bytes) of a disk. The parameter
Drive indicates which disk should be checked. This parameter is 1 for
floppy a:, 2 for floppy b:, etc. A value of 0 returns the size
of the current drive.
For LINUX only:
The diskfree and disksize functions need a file on the specified drive, since this
is required for the statfs system call.
These filenames are set in the initialization of the dos unit, and have
been preset to :
DosExitCode contains (in the low byte) the exit-code of a program executed with the Exec call.
Program Example5; uses Dos; { Program to demonstrate the Exec and DosExitCode function. } begin {$IFDEF LINUX} WriteLn('Executing /bin/ls -la'); Exec('/bin/ls','-la'); {$ELSE} WriteLn('Executing Dir'); Exec(GetEnv('COMSPEC'),'/C dir'); {$ENDIF} WriteLn('Program returned with ExitCode ',DosExitCode); end.
Program Example1; uses Dos; { Program to demonstrate the DosVersion function. } var OS : string[32]; Version : word; begin {$IFDEF LINUX} OS:='Linux'; {$ENDIF} {$IFDEF DOS} OS:='Dos'; {$ENDIF} Version:=DosVersion; WriteLn('Current ',OS,' version is ',Lo(Version),'.',Hi(Version)); end.
EnvStr returns the Index-th Name=Value pair from the list of environment variables. The index of the first pair is zero.
Program Example13; uses Dos; { Program to demonstrate the EnvCount and EnvStr function. } var i : Longint; begin WriteLn('Current Environment is:'); for i:=1to EnvCount do WriteLn(EnvStr(i)); end.
Exec executes the program in Path, with the options given by ComLine. After the program has terminated, the procedure returns. The Exit value of the program can be consulted with the DosExitCode function.
FExpand takes its argument and expands it to a complete filename, i.e. a filename starting from the root directory of the current drive, prepended with the drive-letter (under DOS). The resulting name is converted to uppercase on DOS systems. Under LINUX, the name is left as it is. (filenames are case sensitive under Unix)
Under LINUX, WINDOWS and OS/2 the findfirst/findnext calls have to be mimicked. This call is needed to free any internal resources allocated by the FindFirst or FindNext calls.
E.g. on LINUX, an internal table of file descriptors is kept. When using different searchrecs at the same time, the system may run out of file descriptors for directories.
The LINUX implementation of the DOS unit therefore keeps a table of open directories, and when the table is full, closes one of the directories, and reopens another. This system is adequate but slow if you use a lot of searchrecs. So, to speed up the findfirst/findnext system, the FindClose call was implemented. When you don't need a searchrec any more, you can tell this to the DOS unit by issuing a FindClose call. The directory which is kept open for this searchrec is then closed, and the table slot freed.
It is recommended to use the LINUX call Glob when looking for files on LINUX.
FindFirst searches the file specified in Path, checks the atrributes specified in Attr. It returns a SearchRec record for further searching in F. Path can contain the wildcard characters ? (matches any single character) and * (matches 0 ore more arbitrary characters). In this case FindFirst will return the first file which matches the specified criteria. If DosError is different from zero, no file(s) matching the criteria was(were) found.
On OS/2, you cannot issue two different FindFirst calls. That is, you must close any previous search operation with FindClose before starting a new one. Failure to do so will end in a Run-Time Error 6 (Invalid file handle)
Also, on OS/2, the boolean variable FileNameCaseSensitive indicates whether searches are conducted case-sensitive or not. By default, searches are not case sensitive. If the varieble is set to True, searches on OS/2 are case sensistive.
Program Example7; uses Dos; { Program to demonstrate the FindFirst and FindNext function. } var Dir : SearchRec; begin FindFirst('*.*',$20,Dir); WriteLn('FileName'+Space(32),'FileSize':9); while (DosError=0) do begin Writeln(Dir.Name+Space(40-Length(Dir.Name)),Dir.Size:9); FindNext(Dir); end; FindClose(Dir); end.
FindNext takes as an argument a SearchRec from a previous FindNext call, or a FindFirst call, and tries to find another file which matches the criteria, specified in the FindFirst call. If DosError is different from zero, no more files matching the criteria were found.
Program Example10; uses Dos; { Program to demonstrate the FSearch function. } var s : string; begin s:=FSearch(ParamStr(1),GetEnv('PATH')); if s='' then WriteLn(ParamStr(1),' not Found in PATH') else Writeln(ParamStr(1),' Found in PATH at ',s); end.
FSplit splits a full file name into 3 parts : A Path, a Name and an extension (in ext.) The extension is taken to be all letters after the last dot (.). For DOS, however, an exception is made when LFNSupport=False, then the extension is defined as all characters after the first dot.
Program Example12; uses Dos; { Program to demonstrate the FSplit function. } var Path,Name,Ext : string; begin FSplit(ParamStr(1),Path,Name,Ext); WriteLn('Splitted ',ParamStr(1),' in:'); WriteLn('Path : ',Path); WriteLn('Name : ',Name); WriteLn('Extension: ',Ext); end.
GetCBreak gets the status of CTRL-Break checking under DOS. When BreakValue is false, then DOS only checks for the CTRL-Break key-press when I/O is performed. When it is set to True, then a check is done at every system call.
GetDate returns the system's date. Year is a number in the range 1980..2099.mday is the day of the month, wday is the day of the week, starting with Sunday as day 0.
Program Example2; uses Dos; { Program to demonstrate the GetDate function. } const DayStr:array[0..6] of string[3]=('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); MonthStr:array[1..12] of string[3]=('Jan','Feb','Mar','Apr','May','Jun', 'Jul','Aug','Sep','Oct','Nov','Dec'); var Year,Month,Day,WDay : word; begin GetDate(Year,Month,Day,WDay); WriteLn('Current date'); WriteLn(DayStr[WDay],', ',Day,' ',MonthStr[Month],' ',Year,'.'); end.
Getenv returns the value of the environment variable EnvVar. Under LINUX, case is important when looking for EnvVar. When there is no environment variable EnvVar defined, an empty string is returned.
Program Example14; uses Dos; { Program to demonstrate the GetEnv function. } begin WriteLn('Current PATH is ',GetEnv('PATH')); end.
GetFAttr returns the file attributes of the file-variable f. F can be a untyped or typed file, or of type Text. f must have been assigned, but not opened. The attributes can be examined with the following constants :
Program Example8; uses Dos; { Program to demonstrate the GetFAttr function. } var Attr : Word; f : File; begin Assign(f,ParamStr(1)); GetFAttr(f,Attr); WriteLn('File ',ParamStr(1),' has attribute ',Attr); if (Attr and $20)<>0 then WriteLn('- Archive'); if (Attr and $10)<>0 then WriteLn('- Directory'); if (Attr and $4)<>0 then WriteLn('- Read-Only'); if (Attr and $2)<>0 then WriteLn('- System'); if (Attr and $1)<>0 then WriteLn('- Hidden'); end.
GetFTime returns the modification time of a file. This time is encoded and must be decoded with UnPackTime. F must be a file type, which has been assigned, and opened.
Program Example9; uses Dos; { Program to demonstrate the GetFTime function. } Function L0(w:word):string; var s : string; begin Str(w,s); if w<10 then L0:='0'+s else L0:=s; end; var f : File; Time : Longint; DT : DateTime; begin Assign(f,ParamStr(1)); Reset(f); GetFTime(f,Time); Close(f); UnPackTime(Time,DT); Write ('File ',ParamStr(1),' is last modified on '); Writeln (L0(DT.Month),'-',L0(DT.Day),'-',DT.Year, ' at ',L0(DT.Hour),':',L0(DT.Min)); end.
GetIntVec returns the address of interrupt vector IntNo.
GetLongName changes the filename p to a long filename if the DOS call to do this is successful. The resulting string is the long file name corresponding to the short filename p.
The function returns True if the DOS call was successful, False otherwise.
This function should only be necessary when using the DOS extender under Windows 95 and higher.
GetShortName changes the filename p to a short filename if the DOS call to do this is successful. The resulting string is the short file name corresponding to the long filename p.
The function returns True if the DOS call was successful, False otherwise.
This function should only be necessary when using the DOS extender under Windows 95 and higher.
GetTime returns the system's time. Hour is a on a 24-hour time scale. sec100 is in hundredth of a second.
Program Example3; uses Dos; { Program to demonstrate the GetTime function. } Function L0(w:word):string; var s : string; begin Str(w,s); if w<10 then L0:='0'+s else L0:=s; end; var Hour,Min,Sec,HSec : word; begin GetTime(Hour,Min,Sec,HSec); WriteLn('Current time'); WriteLn(L0(Hour),':',L0(Min),':',L0(Sec)); end.
GetVerify returns the status of the verify flag under DOS. When Verify is True, then DOS checks data which are written to disk, by reading them after writing. If Verify is False, then data written to disk are not verified.
Intr executes a software interrupt number IntNo (must be between 0 and 255), with processor registers set to Regs. After the interrupt call returned, the processor registers are saved in Regs.
MSDos executes an MS-DOS call (int 21h). This is the same as doing a Intr call with an interrupt number of 21h.
UnPackTime converts the date and time specified in T to a packed-time format which can be fed to SetFTime.
Program Example4; uses Dos; { Program to demonstrate the PackTime and UnPackTime functions. } var DT : DateTime; Time : longint; begin with DT do begin Year:=1998; Month:=11; Day:=11; Hour:=11; Min:=11; Sec:=11; end; PackTime(DT,Time); WriteLn('Packed Time : ',Time); UnPackTime(Time,DT); WriteLn('Unpacked Again:'); with DT do begin WriteLn('Year ',Year); WriteLn('Month ',Month); WriteLn('Day ',Day); WriteLn('Hour ',Hour); WriteLn('Min ',Min); WriteLn('Sec ',Sec); end; end.
SetCBreak sets the status of CTRL-Break checking under DOS. When BreakValue is false, then DOS only checks for the CTRL-Break key-press when I/O is performed. When it is set to True, then a check is done at every system call.
SetDate sets the system's internal date. Year is a number between 1980 and 2099.
SetFAttr sets the file attributes of the file-variable F. F can be a untyped or typed file, or of type Text. F must have been assigned, but not opened. The attributes can be a sum of the following constants:
SetFTime sets the modification time of a file, this time is encoded and must be encoded with PackTime. F must be a file type, which has been assigned, and opened.
SetVerify sets the status of the verify flag under DOS. When Verify is True, then DOS checks data which are written to disk, by reading them after writing. If Verify is False, then data written to disk are not verified.
SwapVectors swaps the contents of the internal table of interrupt vectors with the current contents of the interrupt vectors. This is called typically in before and after an Exec call.
UnPackTime converts the file-modification time in p to a DateTime record. The file-modification time can be returned by GetFTime, FindFirst or FindNext calls.