This chapter describes the DOS unit for Free pascal. The DOS unit gives access to some operating system calls related to files, the file system, date and time. Except for the target, this unit is available to all supported platforms.
The unit was first written for DOS by Florian Klämpfl. It was ported to
LINUX by Mark May,
and enhanced by Michaël Van Canneyt. The AMIGA version was ported by
Nils Sjoholm.
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:
The File Attribute constants are used in FindFirst, FindNext to determine what type of special file to search for in addition to normal files. These flags are also used in the SetFAttr and GetFAttr routines to set and retrieve attributes of files. For their definitions consult table (fileattributes) .
These constants are used in the Mode field of the TextRec record. Gives information on the filemode of the text I/O. For their definitions consult table (fmxxxconstants) .
The following constants are not portable, and should not be used. They are present for compatibility only.
{Bitmasks for CPU Flags} fcarry = $0001; fparity = $0004; fauxiliary = $0010; fzero = $0040; fsign = $0080; foverflow = $0800;
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.
For UNIX 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 UNIX 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 Unix} WriteLn('Executing /bin/ls -la'); Exec('/bin/ls','-la'); {$ELSE} WriteLn('Executing Dir'); Exec(GetEnv('COMSPEC'),'/C dir'); {$ENDIF} WriteLn('Program returned with ExitCode ',Lo(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 FreeBSD} OS:='FreeBSD'; {$endif} {$ifdef NetBSD} OS:='NetBSD'; {$endif} {$ifdef Solaris} OS:='Solaris'; {$endif} {$ifdef QNX} OS:='QNX'; {$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 or volume name (when supported). On case sensitive file systems (such as UNIX and LINUX), the resulting name is left as it is, otherwise it is converted to uppercase.
Program Example5; uses Dos; { Program to demonstrate the Exec and DosExitCode function. } begin {$IFDEF Unix} WriteLn('Executing /bin/ls -la'); Exec('/bin/ls','-la'); {$ELSE} WriteLn('Executing Dir'); Exec(GetEnv('COMSPEC'),'/C dir'); {$ENDIF} WriteLn('Program returned with ExitCode ',Lo(DosExitCode)); end.
This call is needed to free any internal resources allocated by the FindFirst or FindNext calls.
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. Normal files, as well as all special files which have the attributes specified in Attr will be returned.
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)
Program Example7; uses Dos; { Program to demonstrate the FindFirst and FindNext function. } var Dir : SearchRec; begin FindFirst('*.*',archive,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 and AMIGA. 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. Under non-DOS and non-AMIGA operating systems, BreakValue always returns True.
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. When there is no environment variable EnvVar defined, an empty string is returned. Under some operating systems (such as UNIX), case is important when looking for EnvVar.
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 archive)<>0 then WriteLn('- Archive'); if (Attr and directory)<>0 then WriteLn('- Directory'); if (Attr and readonly)<>0 then WriteLn('- Read-Only'); if (Attr and sysfile)<>0 then WriteLn('- System'); if (Attr and hidden)<>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. This call does nothing, it is present for compatibility only.
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. Certain operating systems (such as AMIGA), always set the sec100 field to zero.
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. Under non-DOS systems (excluding OS/2 applications running under vanilla DOS), Verify is always True.
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. Under non-DOS operating systems, this call does nothing.
MSDos executes an operating system. This is the same as doing a Intr call with the interrupt number for an os call. Under non-DOS operating systems, this call does nothing. On DOS systems, this calls interrupt $21.
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. 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. Under non-DOS and non-AMIGA operating systems, this call does nothing.
SetDate sets the system's internal date. Year is a number between 1980 and 2099. On a LINUX machine, there must be root privileges, otherwise this routine will do nothing. On other UNIX systems, this call currently does nothing.
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:
Under UNIX like systems (such as LINUX and ) the call exists, but is not implemented, i.e. it does nothing.
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. Under UNIX like systems (such as LINUX and ) the call exists, but is not implemented, i.e. it does nothing.
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. Under non-DOS operating systems (excluding OS/2 applications running under vanilla dos), Verify is always True.
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.
Under certain operating systems, this routine may be implemented as an empty stub.
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.