dos.pp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 by the Free Pascal development team.
  5. Dos unit for BP7 compatible RTL
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit dos;
  13. interface
  14. { Include Win32 Consts,Types }
  15. {$I win32.inc}
  16. Const
  17. Max_Path = 260;
  18. {Bitmasks for CPU Flags}
  19. fcarry = $0001;
  20. fparity = $0004;
  21. fauxiliary = $0010;
  22. fzero = $0040;
  23. fsign = $0080;
  24. foverflow = $0800;
  25. {Bitmasks for file attribute}
  26. readonly = $01;
  27. hidden = $02;
  28. sysfile = $04;
  29. volumeid = $08;
  30. directory = $10;
  31. archive = $20;
  32. anyfile = $3F;
  33. {File Status}
  34. fmclosed = $D7B0;
  35. fminput = $D7B1;
  36. fmoutput = $D7B2;
  37. fminout = $D7B3;
  38. Type
  39. { Needed for Win95 LFN Support }
  40. ComStr = String[255];
  41. PathStr = String[255];
  42. DirStr = String[255];
  43. NameStr = String[255];
  44. ExtStr = String[255];
  45. {
  46. filerec.inc contains the definition of the filerec.
  47. textrec.inc contains the definition of the textrec.
  48. It is in a separate file to make it available in other units without
  49. having to use the DOS unit for it.
  50. }
  51. {$i filerec.inc}
  52. {$i textrec.inc}
  53. DateTime = packed record
  54. Year,
  55. Month,
  56. Day,
  57. Hour,
  58. Min,
  59. Sec : word;
  60. End;
  61. PWin32FindData = ^TWin32FindData;
  62. TWin32FindData = record
  63. dwFileAttributes: Cardinal;
  64. ftCreationTime: TFileTime;
  65. ftLastAccessTime: TFileTime;
  66. ftLastWriteTime: TFileTime;
  67. nFileSizeHigh: Cardinal;
  68. nFileSizeLow: Cardinal;
  69. dwReserved0: Cardinal;
  70. dwReserved1: Cardinal;
  71. cFileName: array[0..MAX_PATH - 1] of Char;
  72. cAlternateFileName: array[0..13] of Char;
  73. // The structure should be 320 bytes long...
  74. pad : system.integer;
  75. end;
  76. Searchrec = Packed Record
  77. FindHandle : THandle;
  78. W32FindData : TWin32FindData;
  79. ExcludeAttr : longint;
  80. time : longint;
  81. size : longint;
  82. attr : longint;
  83. name : string;
  84. end;
  85. registers = packed record
  86. case i : integer of
  87. 0 : (ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si,f51,di,f6,ds,f7,es,f8,flags,fs,gs : word);
  88. 1 : (al,ah,f9,f10,bl,bh,f11,f12,cl,ch,f13,f14,dl,dh : byte);
  89. 2 : (eax, ebx, ecx, edx, ebp, esi, edi : longint);
  90. end;
  91. Var
  92. DosError : integer;
  93. {Interrupt}
  94. Procedure Intr(intno: byte; var regs: registers);
  95. Procedure MSDos(var regs: registers);
  96. {Info/Date/Time}
  97. Function DosVersion: Word;
  98. Procedure GetDate(var year, month, mday, wday: word);
  99. Procedure GetTime(var hour, minute, second, sec100: word);
  100. procedure SetDate(year,month,day: word);
  101. Procedure SetTime(hour,minute,second,sec100: word);
  102. Procedure UnpackTime(p: longint; var t: datetime);
  103. Procedure PackTime(var t: datetime; var p: longint);
  104. {Exec}
  105. Procedure Exec(const path: pathstr; const comline: comstr);
  106. Function DosExitCode: word;
  107. {Disk}
  108. Function DiskFree(drive: byte) : longint;
  109. Function DiskSize(drive: byte) : longint;
  110. Procedure FindFirst(const path: pathstr; attr: word; var f: searchRec);
  111. Procedure FindNext(var f: searchRec);
  112. Procedure FindClose(Var f: SearchRec);
  113. {File}
  114. Procedure GetFAttr(var f; var attr: word);
  115. Procedure GetFTime(var f; var time: longint);
  116. Function FSearch(path: pathstr; dirlist: string): pathstr;
  117. Function FExpand(const path: pathstr): pathstr;
  118. Procedure FSplit(path: pathstr; var dir: dirstr; var name: namestr; var ext: extstr);
  119. {Environment}
  120. Function EnvCount: longint;
  121. Function EnvStr(index: integer): string;
  122. Function GetEnv(envvar: string): string;
  123. {Misc}
  124. Procedure SetFAttr(var f; attr: word);
  125. Procedure SetFTime(var f; time: longint);
  126. Procedure GetCBreak(var breakvalue: boolean);
  127. Procedure SetCBreak(breakvalue: boolean);
  128. Procedure GetVerify(var verify: boolean);
  129. Procedure SetVerify(verify: boolean);
  130. {Do Nothing Functions}
  131. Procedure SwapVectors;
  132. Procedure GetIntVec(intno: byte; var vector: pointer);
  133. Procedure SetIntVec(intno: byte; vector: pointer);
  134. Procedure Keep(exitcode: word);
  135. Const
  136. { allow EXEC to inherited handles from calling process,
  137. needed for FPREDIR in ide/text
  138. now set to true by default because
  139. other OS also pass open handles to childs PM }
  140. ExecInheritsHandles : BOOL = true;
  141. implementation
  142. uses strings;
  143. {******************************************************************************
  144. --- Conversion ---
  145. ******************************************************************************}
  146. function GetLastError : DWORD;
  147. external 'kernel32' name 'GetLastError';
  148. function FileTimeToDosDateTime(const ft :TFileTime;var data,time : word) : longbool;
  149. external 'kernel32' name 'FileTimeToDosDateTime';
  150. function DosDateTimeToFileTime(date,time : word;var ft :TFileTime) : longbool;
  151. external 'kernel32' name 'DosDateTimeToFileTime';
  152. function FileTimeToLocalFileTime(const ft : TFileTime;var lft : TFileTime) : longbool;
  153. external 'kernel32' name 'FileTimeToLocalFileTime';
  154. function LocalFileTimeToFileTime(const lft : TFileTime;var ft : TFileTime) : longbool;
  155. external 'kernel32' name 'LocalFileTimeToFileTime';
  156. type
  157. Longrec=packed record
  158. lo,hi : word;
  159. end;
  160. function Last2DosError(d:dword):integer;
  161. begin
  162. Last2DosError:=d;
  163. end;
  164. Function DosToWinAttr (Const Attr : Longint) : longint;
  165. begin
  166. DosToWinAttr:=Attr;
  167. end;
  168. Function WinToDosAttr (Const Attr : Longint) : longint;
  169. begin
  170. WinToDosAttr:=Attr;
  171. end;
  172. Function DosToWinTime (DTime:longint;Var Wtime : TFileTime):longbool;
  173. var
  174. lft : TFileTime;
  175. begin
  176. DosToWinTime:=DosDateTimeToFileTime(longrec(dtime).hi,longrec(dtime).lo,lft) and
  177. LocalFileTimeToFileTime(lft,Wtime);
  178. end;
  179. Function WinToDosTime (Const Wtime : TFileTime;var DTime:longint):longbool;
  180. var
  181. lft : TFileTime;
  182. begin
  183. WinToDosTime:=FileTimeToLocalFileTime(WTime,lft) and
  184. FileTimeToDosDateTime(lft,longrec(dtime).hi,longrec(dtime).lo);
  185. end;
  186. {******************************************************************************
  187. --- Dos Interrupt ---
  188. ******************************************************************************}
  189. procedure intr(intno : byte;var regs : registers);
  190. begin
  191. { !!!!!!!! }
  192. end;
  193. procedure msdos(var regs : registers);
  194. begin
  195. { !!!!!!!! }
  196. end;
  197. {******************************************************************************
  198. --- Info / Date / Time ---
  199. ******************************************************************************}
  200. function GetVersion : longint;
  201. external 'kernel32' name 'GetVersion';
  202. procedure GetLocalTime(var t : TSystemTime);
  203. external 'kernel32' name 'GetLocalTime';
  204. function SetLocalTime(const t : TSystemTime) : longbool;
  205. external 'kernel32' name 'SetLocalTime';
  206. function dosversion : word;
  207. begin
  208. dosversion:=GetVersion;
  209. end;
  210. procedure getdate(var year,month,mday,wday : word);
  211. var
  212. t : TSystemTime;
  213. begin
  214. GetLocalTime(t);
  215. year:=t.wYear;
  216. month:=t.wMonth;
  217. mday:=t.wDay;
  218. wday:=t.wDayOfWeek;
  219. end;
  220. procedure setdate(year,month,day : word);
  221. var
  222. t : TSystemTime;
  223. begin
  224. { we need the time set privilege }
  225. { so this function crash currently }
  226. {!!!!!}
  227. GetLocalTime(t);
  228. t.wYear:=year;
  229. t.wMonth:=month;
  230. t.wDay:=day;
  231. { only a quite good solution, we can loose some ms }
  232. SetLocalTime(t);
  233. end;
  234. procedure gettime(var hour,minute,second,sec100 : word);
  235. var
  236. t : TSystemTime;
  237. begin
  238. GetLocalTime(t);
  239. hour:=t.wHour;
  240. minute:=t.wMinute;
  241. second:=t.wSecond;
  242. sec100:=t.wMilliSeconds div 10;
  243. end;
  244. procedure settime(hour,minute,second,sec100 : word);
  245. var
  246. t : TSystemTime;
  247. begin
  248. { we need the time set privilege }
  249. { so this function crash currently }
  250. {!!!!!}
  251. GetLocalTime(t);
  252. t.wHour:=hour;
  253. t.wMinute:=minute;
  254. t.wSecond:=second;
  255. t.wMilliSeconds:=sec100*10;
  256. SetLocalTime(t);
  257. end;
  258. Procedure packtime(var t : datetime;var p : longint);
  259. Begin
  260. p:=(t.sec shr 1)+(t.min shl 5)+(t.hour shl 11)+(t.day shl 16)+(t.month shl 21)+((t.year-1980) shl 25);
  261. End;
  262. Procedure unpacktime(p : longint;var t : datetime);
  263. Begin
  264. with t do
  265. begin
  266. sec:=(p and 31) shl 1;
  267. min:=(p shr 5) and 63;
  268. hour:=(p shr 11) and 31;
  269. day:=(p shr 16) and 31;
  270. month:=(p shr 21) and 15;
  271. year:=(p shr 25)+1980;
  272. end;
  273. End;
  274. {******************************************************************************
  275. --- Exec ---
  276. ******************************************************************************}
  277. function CreateProcess(lpApplicationName: PChar; lpCommandLine: PChar;
  278. lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
  279. bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
  280. lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo;
  281. var lpProcessInformation: TProcessInformation): longbool;
  282. external 'kernel32' name 'CreateProcessA';
  283. function getExitCodeProcess(h:THandle;var code:longint):longbool;
  284. external 'kernel32' name 'GetExitCodeProcess';
  285. function WaitForSingleObject(hHandle: THandle; dwMilliseconds: DWORD): DWORD;
  286. external 'kernel32' name 'WaitForSingleObject';
  287. function CloseHandle(h : THandle) : longint;
  288. external 'kernel32' name 'CloseHandle';
  289. var
  290. lastdosexitcode : word;
  291. procedure exec(const path : pathstr;const comline : comstr);
  292. var
  293. SI: TStartupInfo;
  294. PI: TProcessInformation;
  295. Proc : THandle;
  296. l : Longint;
  297. AppPath,
  298. AppParam : array[0..255] of char;
  299. begin
  300. FillChar(SI, SizeOf(SI), 0);
  301. SI.cb:=SizeOf(SI);
  302. SI.wShowWindow:=1;
  303. Move(Path[1],AppPath,length(Path));
  304. AppPath[Length(Path)]:=#0;
  305. AppParam[0]:='-';
  306. AppParam[1]:=' ';
  307. Move(ComLine[1],AppParam[2],length(Comline));
  308. AppParam[Length(ComLine)+2]:=#0;
  309. if not CreateProcess(PChar(@AppPath), PChar(@AppParam),
  310. Nil, Nil, ExecInheritedHandles,$20, Nil, Nil, SI, PI) then
  311. begin
  312. DosError:=Last2DosError(GetLastError);
  313. exit;
  314. end;
  315. Proc:=PI.hProcess;
  316. CloseHandle(PI.hThread);
  317. if WaitForSingleObject(Proc, Infinite) <> $ffffffff then
  318. GetExitCodeProcess(Proc,l)
  319. else
  320. l:=-1;
  321. CloseHandle(Proc);
  322. LastDosExitCode:=l;
  323. end;
  324. function dosexitcode : word;
  325. begin
  326. dosexitcode:=lastdosexitcode;
  327. end;
  328. procedure getcbreak(var breakvalue : boolean);
  329. begin
  330. { !! No Win32 Function !! }
  331. end;
  332. procedure setcbreak(breakvalue : boolean);
  333. begin
  334. { !! No Win32 Function !! }
  335. end;
  336. procedure getverify(var verify : boolean);
  337. begin
  338. { !! No Win32 Function !! }
  339. end;
  340. procedure setverify(verify : boolean);
  341. begin
  342. { !! No Win32 Function !! }
  343. end;
  344. {******************************************************************************
  345. --- Disk ---
  346. ******************************************************************************}
  347. function GetDiskFreeSpace(drive:pchar;var sector_cluster,bytes_sector,
  348. freeclusters,totalclusters:longint):longbool;
  349. external 'kernel32' name 'GetDiskFreeSpaceA';
  350. function diskfree(drive : byte) : longint;
  351. var
  352. disk : array[1..4] of char;
  353. secs,bytes,
  354. free,total : longint;
  355. begin
  356. if drive=0 then
  357. begin
  358. disk[1]:='\';
  359. disk[2]:=#0;
  360. end
  361. else
  362. begin
  363. disk[1]:=chr(drive+64);
  364. disk[2]:=':';
  365. disk[3]:='\';
  366. disk[4]:=#0;
  367. end;
  368. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  369. diskfree:=free*secs*bytes
  370. else
  371. diskfree:=-1;
  372. end;
  373. function disksize(drive : byte) : longint;
  374. var
  375. disk : array[1..4] of char;
  376. secs,bytes,
  377. free,total : longint;
  378. begin
  379. if drive=0 then
  380. begin
  381. disk[1]:='\';
  382. disk[2]:=#0;
  383. end
  384. else
  385. begin
  386. disk[1]:=chr(drive+64);
  387. disk[2]:=':';
  388. disk[3]:='\';
  389. disk[4]:=#0;
  390. end;
  391. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  392. disksize:=total*secs*bytes
  393. else
  394. disksize:=-1;
  395. end;
  396. {******************************************************************************
  397. --- Findfirst FindNext ---
  398. ******************************************************************************}
  399. { Needed kernel calls }
  400. function FindFirstFile (lpFileName: PChar; var lpFindFileData: TWIN32FindData): THandle;
  401. external 'kernel32' name 'FindFirstFileA';
  402. function FindNextFile (hFindFile: THandle; var lpFindFileData: TWIN32FindData): LongBool;
  403. external 'kernel32' name 'FindNextFileA';
  404. function FindCloseFile (hFindFile: THandle): LongBool;
  405. external 'kernel32' name 'FindClose';
  406. Procedure StringToPchar (Var S : String);
  407. Var L : Longint;
  408. begin
  409. L:=ord(S[0]);
  410. Move (S[1],S[0],L);
  411. S[L]:=#0;
  412. end;
  413. procedure FindMatch(var f:searchrec);
  414. begin
  415. { Find file with correct attribute }
  416. While (F.W32FindData.dwFileAttributes and F.ExcludeAttr)<>0 do
  417. begin
  418. if not FindNextFile (F.FindHandle,F.W32FindData) then
  419. begin
  420. DosError:=Last2DosError(GetLastError);
  421. exit;
  422. end;
  423. end;
  424. { Convert some attributes back }
  425. f.size:=F.W32FindData.NFileSizeLow;
  426. f.attr:=WinToDosAttr(F.W32FindData.dwFileAttributes);
  427. WinToDosTime(F.W32FindData.ftLastWriteTime,f.Time);
  428. f.Name:=StrPas(@F.W32FindData.cFileName);
  429. end;
  430. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  431. begin
  432. { no error }
  433. doserror:=0;
  434. F.Name:=Path;
  435. F.Attr:=attr;
  436. F.ExcludeAttr:=(not Attr) and ($1e); {hidden,sys,dir,volume}
  437. StringToPchar(f.name);
  438. { FindFirstFile is a Win32 Call }
  439. F.FindHandle:=FindFirstFile (pchar(@f.Name),F.W32FindData);
  440. If longint(F.FindHandle)=Invalid_Handle_value then
  441. begin
  442. DosError:=Last2DosError(GetLastError);
  443. exit;
  444. end;
  445. { Find file with correct attribute }
  446. FindMatch(f);
  447. end;
  448. procedure findnext(var f : searchRec);
  449. begin
  450. { no error }
  451. doserror:=0;
  452. if not FindNextFile (F.FindHandle,F.W32FindData) then
  453. begin
  454. DosError:=Last2DosError(GetLastError);
  455. exit;
  456. end;
  457. { Find file with correct attribute }
  458. FindMatch(f);
  459. end;
  460. procedure swapvectors;
  461. begin
  462. end;
  463. Procedure FindClose(Var f: SearchRec);
  464. begin
  465. If longint(F.FindHandle)<>Invalid_Handle_value then
  466. FindCloseFile(F.FindHandle);
  467. end;
  468. {******************************************************************************
  469. --- File ---
  470. ******************************************************************************}
  471. function GetFileTime(h : longint;creation,lastaccess,lastwrite : PFileTime) : longbool;
  472. external 'kernel32' name 'GetFileTime';
  473. function SetFileTime(h : longint;creation,lastaccess,lastwrite : PFileTime) : longbool;
  474. external 'kernel32' name 'SetFileTime';
  475. function SetFileAttributes(lpFileName : pchar;dwFileAttributes : longint) : longbool;
  476. external 'kernel32' name 'SetFileAttributesA';
  477. function GetFileAttributes(lpFileName : pchar) : longint;
  478. external 'kernel32' name 'GetFileAttributesA';
  479. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;var ext : extstr);
  480. var
  481. dotpos,p1,i : longint;
  482. begin
  483. { allow slash as backslash }
  484. for i:=1 to length(path) do
  485. if path[i]='/' then path[i]:='\';
  486. { get drive name }
  487. p1:=pos(':',path);
  488. if p1>0 then
  489. begin
  490. dir:=path[1]+':';
  491. delete(path,1,p1);
  492. end
  493. else
  494. dir:='';
  495. { split the path and the name, there are no more path informtions }
  496. { if path contains no backslashes }
  497. while true do
  498. begin
  499. p1:=pos('\',path);
  500. if p1=0 then
  501. break;
  502. dir:=dir+copy(path,1,p1);
  503. delete(path,1,p1);
  504. end;
  505. { try to find out a extension }
  506. Ext:='';
  507. i:=Length(Path);
  508. DotPos:=256;
  509. While (i>0) Do
  510. Begin
  511. If (Path[i]='.') Then
  512. begin
  513. DotPos:=i;
  514. break;
  515. end;
  516. Dec(i);
  517. end;
  518. Ext:=Copy(Path,DotPos,255);
  519. Name:=Copy(Path,1,DotPos - 1);
  520. end;
  521. function fexpand(const path : pathstr) : pathstr;
  522. var
  523. s,pa : string[79];
  524. i,j : longint;
  525. begin
  526. getdir(0,s);
  527. i:=ioresult;
  528. if FileNameCaseSensitive then
  529. pa:=path
  530. else
  531. pa:=upcase(path);
  532. { allow slash as backslash }
  533. for i:=1 to length(pa) do
  534. if pa[i]='/' then
  535. pa[i]:='\';
  536. if (length(pa)>1) and (pa[2]=':') and (pa[1] in ['A'..'Z','a'..'z']) then
  537. begin
  538. { Always uppercase driveletter }
  539. if (pa[1] in ['a'..'z']) then
  540. pa[1]:=Chr(Ord(Pa[1])-32);
  541. { we must get the right directory }
  542. getdir(ord(pa[1])-ord('A')+1,s);
  543. if (ord(pa[0])>2) and (pa[3]<>'\') then
  544. if pa[1]=s[1] then
  545. pa:=s+'\'+copy (pa,3,length(pa))
  546. else
  547. pa:=pa[1]+':\'+copy (pa,3,length(pa))
  548. end
  549. else
  550. if pa[1]='\' then
  551. pa:=s[1]+':'+pa
  552. else if s[0]=#3 then
  553. pa:=s+pa
  554. else
  555. pa:=s+'\'+pa;
  556. { Turbo Pascal gives current dir on drive if only drive given as parameter! }
  557. if length(pa) = 2 then
  558. begin
  559. getdir(byte(pa[1])-64,s);
  560. i:=ioresult;
  561. pa := s;
  562. end;
  563. {First remove all references to '\.\'}
  564. while pos ('\.\',pa)<>0 do
  565. delete (pa,pos('\.\',pa),2);
  566. {Now remove also all references to '\..\' + of course previous dirs..}
  567. repeat
  568. i:=pos('\..\',pa);
  569. if i<>0 then
  570. begin
  571. j:=i-1;
  572. while (j>1) and (pa[j]<>'\') do
  573. dec (j);
  574. if pa[j+1] = ':' then j := 3;
  575. delete (pa,j,i-j+3);
  576. end;
  577. until i=0;
  578. { Turbo Pascal gets rid of a \.. at the end of the path }
  579. { Now remove also any reference to '\..' at end of line
  580. + of course previous dir.. }
  581. i:=pos('\..',pa);
  582. if i<>0 then
  583. begin
  584. if i = length(pa) - 2 then
  585. begin
  586. j:=i-1;
  587. while (j>1) and (pa[j]<>'\') do
  588. dec (j);
  589. delete (pa,j,i-j+3);
  590. end;
  591. pa := pa + '\';
  592. end;
  593. { Remove End . and \}
  594. if (length(pa)>0) and (pa[length(pa)]='.') then
  595. dec(byte(pa[0]));
  596. { if only the drive + a '\' is left then the '\' should be left to prevtn the program
  597. accessing the current directory on the drive rather than the root!}
  598. { if the last char of path = '\' then leave it in as this is what TP does! }
  599. if ((length(pa)>3) and (pa[length(pa)]='\')) and (path[length(path)] <> '\') then
  600. dec(byte(pa[0]));
  601. { if only a drive is given in path then there should be a '\' at the
  602. end of the string given back }
  603. if length(path) = 2 then pa := pa + '\';
  604. fexpand:=pa;
  605. end;
  606. Function FSearch(path: pathstr; dirlist: string): pathstr;
  607. var
  608. i,p1 : longint;
  609. s : searchrec;
  610. newdir : pathstr;
  611. begin
  612. { No wildcards allowed in these things }
  613. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  614. fsearch:=''
  615. else
  616. begin
  617. { allow slash as backslash }
  618. for i:=1 to length(dirlist) do
  619. if dirlist[i]='/' then dirlist[i]:='\';
  620. repeat
  621. p1:=pos(';',dirlist);
  622. if p1<>0 then
  623. begin
  624. newdir:=copy(dirlist,1,p1-1);
  625. delete(dirlist,1,p1);
  626. end
  627. else
  628. begin
  629. newdir:=dirlist;
  630. dirlist:='';
  631. end;
  632. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  633. newdir:=newdir+'\';
  634. findfirst(newdir+path,anyfile,s);
  635. if doserror=0 then
  636. newdir:=newdir+path
  637. else
  638. newdir:='';
  639. until (dirlist='') or (newdir<>'');
  640. fsearch:=newdir;
  641. end;
  642. end;
  643. procedure getftime(var f;var time : longint);
  644. var
  645. ft : TFileTime;
  646. begin
  647. if GetFileTime(filerec(f).Handle,nil,nil,@ft) and
  648. WinToDosTime(ft,time) then
  649. exit
  650. else
  651. time:=0;
  652. end;
  653. procedure setftime(var f;time : longint);
  654. var
  655. ft : TFileTime;
  656. begin
  657. if DosToWinTime(time,ft) then
  658. SetFileTime(filerec(f).Handle,nil,nil,@ft);
  659. end;
  660. procedure getfattr(var f;var attr : word);
  661. var
  662. l : longint;
  663. begin
  664. l:=GetFileAttributes(filerec(f).name);
  665. if l=$ffffffff then
  666. doserror:=getlasterror;
  667. attr:=l;
  668. end;
  669. procedure setfattr(var f;attr : word);
  670. begin
  671. doserror:=0;
  672. if not(SetFileAttributes(filerec(f).name,attr)) then
  673. doserror:=getlasterror;
  674. end;
  675. {******************************************************************************
  676. --- Environment ---
  677. ******************************************************************************}
  678. {
  679. The environment is a block of zero terminated strings
  680. terminated by a #0
  681. }
  682. function GetEnvironmentStrings : pchar;
  683. external 'kernel32' name 'GetEnvironmentStringsA';
  684. function FreeEnvironmentStrings(p : pchar) : longbool;
  685. external 'kernel32' name 'FreeEnvironmentStringsA';
  686. function envcount : longint;
  687. var
  688. hp,p : pchar;
  689. count : longint;
  690. begin
  691. p:=GetEnvironmentStrings;
  692. hp:=p;
  693. count:=0;
  694. while hp^<>#0 do
  695. begin
  696. { next string entry}
  697. hp:=hp+strlen(hp)+1;
  698. inc(count);
  699. end;
  700. FreeEnvironmentStrings(p);
  701. envcount:=count;
  702. end;
  703. Function EnvStr(index: integer): string;
  704. var
  705. hp,p : pchar;
  706. count,i : longint;
  707. begin
  708. { envcount takes some time in win32 }
  709. count:=envcount;
  710. { range checking }
  711. if (index<=0) or (index>count) then
  712. begin
  713. envstr:='';
  714. exit;
  715. end;
  716. p:=GetEnvironmentStrings;
  717. hp:=p;
  718. { retrive the string with the given index }
  719. for i:=2 to index do
  720. hp:=hp+strlen(hp)+1;
  721. envstr:=strpas(hp);
  722. FreeEnvironmentStrings(p);
  723. end;
  724. Function GetEnv(envvar: string): string;
  725. var
  726. s : string;
  727. i : longint;
  728. hp,p : pchar;
  729. begin
  730. getenv:='';
  731. p:=GetEnvironmentStrings;
  732. hp:=p;
  733. while hp^<>#0 do
  734. begin
  735. s:=strpas(hp);
  736. i:=pos('=',s);
  737. if upcase(copy(s,1,i-1))=upcase(envvar) then
  738. begin
  739. getenv:=copy(s,i+1,length(s)-i);
  740. break;
  741. end;
  742. { next string entry}
  743. hp:=hp+strlen(hp)+1;
  744. end;
  745. FreeEnvironmentStrings(p);
  746. end;
  747. {******************************************************************************
  748. --- Not Supported ---
  749. ******************************************************************************}
  750. Procedure keep(exitcode : word);
  751. Begin
  752. End;
  753. Procedure getintvec(intno : byte;var vector : pointer);
  754. Begin
  755. End;
  756. Procedure setintvec(intno : byte;vector : pointer);
  757. Begin
  758. End;
  759. end.
  760. {
  761. $Log$
  762. Revision 1.21 1999-09-21 12:37:09 pierre
  763. * Child inherits now file handles from parent in Exec by default
  764. Revision 1.20 1999/09/21 11:34:40 pierre
  765. + ExecInheritedHandles boolean
  766. Revision 1.19 1999/08/25 13:57:55 michael
  767. + Patched FSearch from Frank McCormick
  768. Revision 1.18 1999/08/12 09:24:14 michael
  769. Fixed win32finddata size; searchrec.excludeattr was overwritten.
  770. Revision 1.17 1999/05/16 17:08:59 peter
  771. * fixed driveletter checking
  772. Revision 1.16 1999/05/08 19:47:27 peter
  773. * check ioresult after getdir calls
  774. Revision 1.15 1999/04/28 11:42:52 peter
  775. + FileNameCaseSensetive boolean
  776. Revision 1.14 1999/04/08 12:23:07 peter
  777. * removed os.inc
  778. Revision 1.13 1998/11/16 15:48:53 peter
  779. * fixed longbool returns for api calls
  780. Revision 1.12 1998/10/27 10:55:55 michael
  781. * environment vars are case insensitive under WinNT/DOS
  782. Revision 1.11 1998/10/22 15:32:38 pierre
  783. * fsplit adapted to long filenames
  784. Revision 1.10 1998/10/16 14:20:06 peter
  785. * removed writelns
  786. Revision 1.9 1998/10/16 08:55:26 peter
  787. * findfirst is now more delphi alike
  788. Revision 1.8 1998/08/16 09:12:11 michael
  789. Corrected fexpand behaviour.
  790. Revision 1.7 1998/06/10 10:39:13 peter
  791. * working w32 rtl
  792. Revision 1.6 1998/06/08 23:07:45 peter
  793. * dos interface is now 100% compatible
  794. * fixed call PASCALMAIN which must be direct asm
  795. Revision 1.5 1998/05/06 12:36:50 michael
  796. + Removed log from before restored version.
  797. Revision 1.4 1998/04/27 14:01:38 florian
  798. * was uncompilable
  799. Revision 1.3 1998/04/26 22:37:02 florian
  800. + getftime, unpacktime, packtime
  801. Revision 1.2 1998/04/26 21:49:09 florian
  802. + first compiling and working version
  803. }