dos.pp 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 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. Uses
  15. Go32;
  16. Const
  17. {Bitmasks for CPU Flags}
  18. fcarry = $0001;
  19. fparity = $0004;
  20. fauxiliary = $0010;
  21. fzero = $0040;
  22. fsign = $0080;
  23. foverflow = $0800;
  24. {Bitmasks for file attribute}
  25. readonly = $01;
  26. hidden = $02;
  27. sysfile = $04;
  28. volumeid = $08;
  29. directory = $10;
  30. archive = $20;
  31. anyfile = $3F;
  32. {File Status}
  33. fmclosed = $D7B0;
  34. fminput = $D7B1;
  35. fmoutput = $D7B2;
  36. fminout = $D7B3;
  37. Type
  38. { Needed for LFN Support }
  39. ComStr = String[255];
  40. PathStr = String[255];
  41. DirStr = String[255];
  42. NameStr = String[255];
  43. ExtStr = String[255];
  44. {
  45. filerec.inc contains the definition of the filerec.
  46. textrec.inc contains the definition of the textrec.
  47. It is in a separate file to make it available in other units without
  48. having to use the DOS unit for it.
  49. }
  50. {$i filerec.inc}
  51. {$i textrec.inc}
  52. DateTime = packed record
  53. Year,
  54. Month,
  55. Day,
  56. Hour,
  57. Min,
  58. Sec : word;
  59. End;
  60. searchrec = packed record
  61. fill : array[1..21] of byte;
  62. attr : byte;
  63. time : longint;
  64. { reserved : word; not in DJGPP V2 }
  65. size : longint;
  66. name : string[255]; { LFN Name, DJGPP uses only [12] but more can't hurt (PFV) }
  67. end;
  68. Registers = Go32.Registers;
  69. Var
  70. DosError : integer;
  71. {Interrupt}
  72. Procedure Intr(intno: byte; var regs: registers);
  73. Procedure MSDos(var regs: registers);
  74. {Info/Date/Time}
  75. Function DosVersion: Word;
  76. Procedure GetDate(var year, month, mday, wday: word);
  77. Procedure GetTime(var hour, minute, second, sec100: word);
  78. procedure SetDate(year,month,day: word);
  79. Procedure SetTime(hour,minute,second,sec100: word);
  80. Procedure UnpackTime(p: longint; var t: datetime);
  81. Procedure PackTime(var t: datetime; var p: longint);
  82. {Exec}
  83. Procedure Exec(const path: pathstr; const comline: comstr);
  84. Function DosExitCode: word;
  85. {Disk}
  86. Function DiskFree(drive: byte) : int64;
  87. Function DiskSize(drive: byte) : int64;
  88. Procedure FindFirst(const path: pathstr; attr: word; var f: searchRec);
  89. Procedure FindNext(var f: searchRec);
  90. Procedure FindClose(Var f: SearchRec);
  91. {File}
  92. Procedure GetFAttr(var f; var attr: word);
  93. Procedure GetFTime(var f; var time: longint);
  94. Function FSearch(path: pathstr; dirlist: string): pathstr;
  95. Function FExpand(const path: pathstr): pathstr;
  96. Procedure FSplit(path: pathstr; var dir: dirstr; var name: namestr; var ext: extstr);
  97. function GetShortName(var p : String) : boolean;
  98. function GetLongName(var p : String) : boolean;
  99. {Environment}
  100. Function EnvCount: longint;
  101. Function EnvStr(index: integer): string;
  102. Function GetEnv(envvar: string): string;
  103. {Misc}
  104. Procedure SetFAttr(var f; attr: word);
  105. Procedure SetFTime(var f; time: longint);
  106. Procedure GetCBreak(var breakvalue: boolean);
  107. Procedure SetCBreak(breakvalue: boolean);
  108. Procedure GetVerify(var verify: boolean);
  109. Procedure SetVerify(verify: boolean);
  110. {Do Nothing Functions}
  111. Procedure SwapVectors;
  112. Procedure GetIntVec(intno: byte; var vector: pointer);
  113. Procedure SetIntVec(intno: byte; vector: pointer);
  114. Procedure Keep(exitcode: word);
  115. implementation
  116. uses
  117. strings;
  118. {$ASMMODE ATT}
  119. {******************************************************************************
  120. --- Dos Interrupt ---
  121. ******************************************************************************}
  122. var
  123. dosregs : registers;
  124. procedure LoadDosError;
  125. var
  126. r : registers;
  127. SimpleDosError : word;
  128. begin
  129. if (dosregs.flags and fcarry) <> 0 then
  130. begin
  131. { I got a extended error = 0
  132. while CarryFlag was set from Exec function }
  133. SimpleDosError:=dosregs.ax;
  134. r.eax:=$5900;
  135. r.ebx:=$0;
  136. realintr($21,r);
  137. { conversion from word to integer !!
  138. gave a Bound check error if ax is $FFFF !! PM }
  139. doserror:=integer(r.ax);
  140. case doserror of
  141. 0 : DosError:=integer(SimpleDosError);
  142. 19 : DosError:=150;
  143. 21 : DosError:=152;
  144. end;
  145. end
  146. else
  147. doserror:=0;
  148. end;
  149. procedure intr(intno : byte;var regs : registers);
  150. begin
  151. realintr(intno,regs);
  152. end;
  153. procedure msdos(var regs : registers);
  154. begin
  155. intr($21,regs);
  156. end;
  157. {******************************************************************************
  158. --- Info / Date / Time ---
  159. ******************************************************************************}
  160. function dosversion : word;
  161. begin
  162. dosregs.ax:=$3000;
  163. msdos(dosregs);
  164. dosversion:=dosregs.ax;
  165. end;
  166. procedure getdate(var year,month,mday,wday : word);
  167. begin
  168. dosregs.ax:=$2a00;
  169. msdos(dosregs);
  170. wday:=dosregs.al;
  171. year:=dosregs.cx;
  172. month:=dosregs.dh;
  173. mday:=dosregs.dl;
  174. end;
  175. procedure setdate(year,month,day : word);
  176. begin
  177. dosregs.cx:=year;
  178. dosregs.dh:=month;
  179. dosregs.dl:=day;
  180. dosregs.ah:=$2b;
  181. msdos(dosregs);
  182. end;
  183. procedure gettime(var hour,minute,second,sec100 : word);
  184. begin
  185. dosregs.ah:=$2c;
  186. msdos(dosregs);
  187. hour:=dosregs.ch;
  188. minute:=dosregs.cl;
  189. second:=dosregs.dh;
  190. sec100:=dosregs.dl;
  191. end;
  192. procedure settime(hour,minute,second,sec100 : word);
  193. begin
  194. dosregs.ch:=hour;
  195. dosregs.cl:=minute;
  196. dosregs.dh:=second;
  197. dosregs.dl:=sec100;
  198. dosregs.ah:=$2d;
  199. msdos(dosregs);
  200. end;
  201. Procedure packtime(var t : datetime;var p : longint);
  202. Begin
  203. 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);
  204. End;
  205. Procedure unpacktime(p : longint;var t : datetime);
  206. Begin
  207. with t do
  208. begin
  209. sec:=(p and 31) shl 1;
  210. min:=(p shr 5) and 63;
  211. hour:=(p shr 11) and 31;
  212. day:=(p shr 16) and 31;
  213. month:=(p shr 21) and 15;
  214. year:=(p shr 25)+1980;
  215. end;
  216. End;
  217. {******************************************************************************
  218. --- Exec ---
  219. ******************************************************************************}
  220. var
  221. lastdosexitcode : word;
  222. procedure exec(const path : pathstr;const comline : comstr);
  223. type
  224. realptr = packed record
  225. ofs,seg : word;
  226. end;
  227. texecblock = packed record
  228. envseg : word;
  229. comtail : realptr;
  230. firstFCB : realptr;
  231. secondFCB : realptr;
  232. iniStack : realptr;
  233. iniCSIP : realptr;
  234. end;
  235. var
  236. current_dos_buffer_pos,
  237. arg_ofs,
  238. i,la_env,
  239. la_p,la_c,la_e,
  240. fcb1_la,fcb2_la : longint;
  241. execblock : texecblock;
  242. c,p : string;
  243. function paste_to_dos(src : string) : boolean;
  244. var
  245. c : array[0..255] of char;
  246. begin
  247. paste_to_dos:=false;
  248. if current_dos_buffer_pos+length(src)+1>transfer_buffer+tb_size then
  249. RunError(217);
  250. move(src[1],c[0],length(src));
  251. c[length(src)]:=#0;
  252. seg_move(get_ds,longint(@c),dosmemselector,current_dos_buffer_pos,length(src)+1);
  253. current_dos_buffer_pos:=current_dos_buffer_pos+length(src)+1;
  254. paste_to_dos:=true;
  255. end;
  256. begin
  257. { create command line }
  258. move(comline[0],c[1],length(comline)+1);
  259. c[length(comline)+2]:=#13;
  260. c[0]:=char(length(comline)+2);
  261. { create path }
  262. p:=path;
  263. for i:=1 to length(p) do
  264. if p[i]='/' then
  265. p[i]:='\';
  266. if LFNSupport then
  267. GetShortName(p);
  268. { create buffer }
  269. la_env:=transfer_buffer;
  270. while (la_env and 15)<>0 do
  271. inc(la_env);
  272. current_dos_buffer_pos:=la_env;
  273. { copy environment }
  274. for i:=1 to envcount do
  275. paste_to_dos(envstr(i));
  276. paste_to_dos(''); { adds a double zero at the end }
  277. { allow slash as backslash }
  278. la_p:=current_dos_buffer_pos;
  279. paste_to_dos(p);
  280. la_c:=current_dos_buffer_pos;
  281. paste_to_dos(c);
  282. la_e:=current_dos_buffer_pos;
  283. fcb1_la:=la_e;
  284. la_e:=la_e+16;
  285. fcb2_la:=la_e;
  286. la_e:=la_e+16;
  287. { allocate FCB see dosexec code }
  288. arg_ofs:=1;
  289. while (c[arg_ofs] in [' ',#9]) do
  290. inc(arg_ofs);
  291. dosregs.ax:=$2901;
  292. dosregs.ds:=(la_c+arg_ofs) shr 4;
  293. dosregs.esi:=(la_c+arg_ofs) and 15;
  294. dosregs.es:=fcb1_la shr 4;
  295. dosregs.edi:=fcb1_la and 15;
  296. msdos(dosregs);
  297. { allocate second FCB see dosexec code }
  298. repeat
  299. inc(arg_ofs);
  300. until (c[arg_ofs] in [' ',#9,#13]);
  301. if c[arg_ofs]<>#13 then
  302. begin
  303. repeat
  304. inc(arg_ofs);
  305. until not (c[arg_ofs] in [' ',#9]);
  306. end;
  307. dosregs.ax:=$2901;
  308. dosregs.ds:=(la_c+arg_ofs) shr 4;
  309. dosregs.si:=(la_c+arg_ofs) and 15;
  310. dosregs.es:=fcb2_la shr 4;
  311. dosregs.di:=fcb2_la and 15;
  312. msdos(dosregs);
  313. with execblock do
  314. begin
  315. envseg:=la_env shr 4;
  316. comtail.seg:=la_c shr 4;
  317. comtail.ofs:=la_c and 15;
  318. firstFCB.seg:=fcb1_la shr 4;
  319. firstFCB.ofs:=fcb1_la and 15;
  320. secondFCB.seg:=fcb2_la shr 4;
  321. secondFCB.ofs:=fcb2_la and 15;
  322. end;
  323. seg_move(get_ds,longint(@execblock),dosmemselector,la_e,sizeof(texecblock));
  324. dosregs.edx:=la_p and 15;
  325. dosregs.ds:=la_p shr 4;
  326. dosregs.ebx:=la_e and 15;
  327. dosregs.es:=la_e shr 4;
  328. dosregs.ax:=$4b00;
  329. msdos(dosregs);
  330. LoadDosError;
  331. if DosError=0 then
  332. begin
  333. dosregs.ax:=$4d00;
  334. msdos(dosregs);
  335. LastDosExitCode:=DosRegs.al
  336. end
  337. else
  338. LastDosExitCode:=0;
  339. end;
  340. function dosexitcode : word;
  341. begin
  342. dosexitcode:=lastdosexitcode;
  343. end;
  344. procedure getcbreak(var breakvalue : boolean);
  345. begin
  346. dosregs.ax:=$3300;
  347. msdos(dosregs);
  348. breakvalue:=dosregs.dl<>0;
  349. end;
  350. procedure setcbreak(breakvalue : boolean);
  351. begin
  352. dosregs.ax:=$3301;
  353. dosregs.dl:=ord(breakvalue);
  354. msdos(dosregs);
  355. end;
  356. procedure getverify(var verify : boolean);
  357. begin
  358. dosregs.ah:=$54;
  359. msdos(dosregs);
  360. verify:=dosregs.al<>0;
  361. end;
  362. procedure setverify(verify : boolean);
  363. begin
  364. dosregs.ah:=$2e;
  365. dosregs.al:=ord(verify);
  366. msdos(dosregs);
  367. end;
  368. {******************************************************************************
  369. --- Disk ---
  370. ******************************************************************************}
  371. TYPE ExtendedFat32FreeSpaceRec=packed Record
  372. RetSize : WORD; { (ret) size of returned structure}
  373. Strucversion : WORD; {(call) structure version (0000h)
  374. (ret) actual structure version (0000h)}
  375. SecPerClus, {number of sectors per cluster}
  376. BytePerSec, {number of bytes per sector}
  377. AvailClusters, {number of available clusters}
  378. TotalClusters, {total number of clusters on the drive}
  379. AvailPhysSect, {physical sectors available on the drive}
  380. TotalPhysSect, {total physical sectors on the drive}
  381. AvailAllocUnits, {Available allocation units}
  382. TotalAllocUnits : DWORD; {Total allocation units}
  383. Dummy,Dummy2 : DWORD; {8 bytes reserved}
  384. END;
  385. function do_diskdata(drive : byte; Free : BOOLEAN) : Int64;
  386. VAR
  387. S : String;
  388. Rec : ExtendedFat32FreeSpaceRec;
  389. BEGIN
  390. if (swap(dosversion)>=$070A) AND LFNSupport then
  391. begin
  392. S:='C:\'#0;
  393. if Drive=0 then
  394. begin
  395. GetDir(Drive,S);
  396. Setlength(S,4);
  397. S[4]:=#0;
  398. end
  399. else
  400. S[1]:=chr(Drive+64);
  401. Rec.Strucversion:=0;
  402. dosmemput(tb_segment,tb_offset,Rec,SIZEOF(ExtendedFat32FreeSpaceRec));
  403. dosmemput(tb_segment,tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1,S[1],4);
  404. dosregs.dx:=tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1;
  405. dosregs.ds:=tb_segment;
  406. dosregs.di:=tb_offset;
  407. dosregs.es:=tb_segment;
  408. dosregs.cx:=Sizeof(ExtendedFat32FreeSpaceRec);
  409. dosregs.ax:=$7303;
  410. msdos(dosregs);
  411. if (dosregs.flags and fcarry) = 0 then {No error clausule in int except cf}
  412. begin
  413. copyfromdos(rec,Sizeof(ExtendedFat32FreeSpaceRec));
  414. if Free then
  415. Do_DiskData:=int64(rec.AvailAllocUnits)*rec.SecPerClus*rec.BytePerSec
  416. else
  417. Do_DiskData:=int64(rec.TotalAllocUnits)*rec.SecPerClus*rec.BytePerSec;
  418. end
  419. else
  420. Do_DiskData:=-1;
  421. end
  422. else
  423. begin
  424. dosregs.dl:=drive;
  425. dosregs.ah:=$36;
  426. msdos(dosregs);
  427. if dosregs.ax<>$FFFF then
  428. begin
  429. if Free then
  430. Do_DiskData:=int64(dosregs.ax)*dosregs.bx*dosregs.cx
  431. else
  432. Do_DiskData:=int64(dosregs.ax)*dosregs.cx*dosregs.dx;
  433. end
  434. else
  435. do_diskdata:=-1;
  436. end;
  437. end;
  438. function diskfree(drive : byte) : int64;
  439. begin
  440. diskfree:=Do_DiskData(drive,TRUE);
  441. end;
  442. function disksize(drive : byte) : int64;
  443. begin
  444. disksize:=Do_DiskData(drive,false);
  445. end;
  446. {******************************************************************************
  447. --- LFNFindfirst LFNFindNext ---
  448. ******************************************************************************}
  449. type
  450. LFNSearchRec=packed record
  451. attr,
  452. crtime,
  453. crtimehi,
  454. actime,
  455. actimehi,
  456. lmtime,
  457. lmtimehi,
  458. sizehi,
  459. size : longint;
  460. reserved : array[0..7] of byte;
  461. name : array[0..259] of byte;
  462. shortname : array[0..13] of byte;
  463. end;
  464. procedure LFNSearchRec2Dos(const w:LFNSearchRec;hdl:longint;var d:Searchrec;from_findfirst : boolean);
  465. var
  466. Len : longint;
  467. begin
  468. With w do
  469. begin
  470. FillChar(d,sizeof(SearchRec),0);
  471. if DosError=0 then
  472. len:=StrLen(@Name)
  473. else
  474. len:=0;
  475. d.Name[0]:=chr(len);
  476. Move(Name[0],d.Name[1],Len);
  477. d.Time:=lmTime;
  478. d.Size:=Size;
  479. d.Attr:=Attr and $FF;
  480. if (DosError<>0) and from_findfirst then
  481. hdl:=-1;
  482. Move(hdl,d.Fill,4);
  483. end;
  484. end;
  485. procedure LFNFindFirst(path:pchar;attr:longint;var s:searchrec);
  486. var
  487. i : longint;
  488. w : LFNSearchRec;
  489. begin
  490. { allow slash as backslash }
  491. for i:=0 to strlen(path) do
  492. if path[i]='/' then path[i]:='\';
  493. dosregs.si:=1; { use ms-dos time }
  494. { don't include the label if not asked for it, needed for network drives }
  495. if attr=$8 then
  496. dosregs.ecx:=8
  497. else
  498. dosregs.ecx:=attr and (not 8);
  499. dosregs.edx:=tb_offset+Sizeof(LFNSearchrec)+1;
  500. dosmemput(tb_segment,tb_offset+Sizeof(LFNSearchrec)+1,path^,strlen(path)+1);
  501. dosregs.ds:=tb_segment;
  502. dosregs.edi:=tb_offset;
  503. dosregs.es:=tb_segment;
  504. dosregs.ax:=$714e;
  505. msdos(dosregs);
  506. LoadDosError;
  507. copyfromdos(w,sizeof(LFNSearchRec));
  508. LFNSearchRec2Dos(w,dosregs.ax,s,true);
  509. end;
  510. procedure LFNFindNext(var s:searchrec);
  511. var
  512. hdl : longint;
  513. w : LFNSearchRec;
  514. begin
  515. Move(s.Fill,hdl,4);
  516. dosregs.si:=1; { use ms-dos time }
  517. dosregs.edi:=tb_offset;
  518. dosregs.es:=tb_segment;
  519. dosregs.ebx:=hdl;
  520. dosregs.ax:=$714f;
  521. msdos(dosregs);
  522. LoadDosError;
  523. copyfromdos(w,sizeof(LFNSearchRec));
  524. LFNSearchRec2Dos(w,hdl,s,false);
  525. end;
  526. procedure LFNFindClose(var s:searchrec);
  527. var
  528. hdl : longint;
  529. begin
  530. Move(s.Fill,hdl,4);
  531. { Do not call MsDos if FindFirst returned with an error }
  532. if hdl=-1 then
  533. begin
  534. DosError:=0;
  535. exit;
  536. end;
  537. dosregs.ebx:=hdl;
  538. dosregs.ax:=$71a1;
  539. msdos(dosregs);
  540. LoadDosError;
  541. end;
  542. {******************************************************************************
  543. --- DosFindfirst DosFindNext ---
  544. ******************************************************************************}
  545. procedure dossearchrec2searchrec(var f : searchrec);
  546. var
  547. len : longint;
  548. begin
  549. { Check is necessary!! OS/2's VDM doesn't clear the name with #0 if the }
  550. { file doesn't exist! (JM) }
  551. if dosError = 0 then
  552. len:=StrLen(@f.Name)
  553. else len := 0;
  554. Move(f.Name[0],f.Name[1],Len);
  555. f.Name[0]:=chr(len);
  556. end;
  557. procedure DosFindfirst(path : pchar;attr : word;var f : searchrec);
  558. var
  559. i : longint;
  560. begin
  561. { allow slash as backslash }
  562. for i:=0 to strlen(path) do
  563. if path[i]='/' then path[i]:='\';
  564. copytodos(f,sizeof(searchrec));
  565. dosregs.edx:=tb_offset;
  566. dosregs.ds:=tb_segment;
  567. dosregs.ah:=$1a;
  568. msdos(dosregs);
  569. dosregs.ecx:=attr;
  570. dosregs.edx:=tb_offset+Sizeof(searchrec)+1;
  571. dosmemput(tb_segment,tb_offset+Sizeof(searchrec)+1,path^,strlen(path)+1);
  572. dosregs.ds:=tb_segment;
  573. dosregs.ah:=$4e;
  574. msdos(dosregs);
  575. copyfromdos(f,sizeof(searchrec));
  576. LoadDosError;
  577. dossearchrec2searchrec(f);
  578. end;
  579. procedure Dosfindnext(var f : searchrec);
  580. begin
  581. copytodos(f,sizeof(searchrec));
  582. dosregs.edx:=tb_offset;
  583. dosregs.ds:=tb_segment;
  584. dosregs.ah:=$1a;
  585. msdos(dosregs);
  586. dosregs.ah:=$4f;
  587. msdos(dosregs);
  588. copyfromdos(f,sizeof(searchrec));
  589. LoadDosError;
  590. dossearchrec2searchrec(f);
  591. end;
  592. {******************************************************************************
  593. --- Findfirst FindNext ---
  594. ******************************************************************************}
  595. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  596. var
  597. path0 : array[0..256] of char;
  598. begin
  599. doserror:=0;
  600. strpcopy(path0,path);
  601. if LFNSupport then
  602. LFNFindFirst(path0,attr,f)
  603. else
  604. Dosfindfirst(path0,attr,f);
  605. end;
  606. procedure findnext(var f : searchRec);
  607. begin
  608. doserror:=0;
  609. if LFNSupport then
  610. LFNFindnext(f)
  611. else
  612. Dosfindnext(f);
  613. end;
  614. Procedure FindClose(Var f: SearchRec);
  615. begin
  616. DosError:=0;
  617. if LFNSupport then
  618. LFNFindClose(f);
  619. end;
  620. type swap_proc = procedure;
  621. var
  622. _swap_in : swap_proc;external name '_swap_in';
  623. _swap_out : swap_proc;external name '_swap_out';
  624. _exception_exit : pointer;external name '_exception_exit';
  625. _v2prt0_exceptions_on : longbool;external name '_v2prt0_exceptions_on';
  626. procedure swapvectors;
  627. begin
  628. if _exception_exit<>nil then
  629. if _v2prt0_exceptions_on then
  630. _swap_out()
  631. else
  632. _swap_in();
  633. end;
  634. {******************************************************************************
  635. --- File ---
  636. ******************************************************************************}
  637. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;var ext : extstr);
  638. var
  639. dotpos,p1,i : longint;
  640. begin
  641. { allow slash as backslash }
  642. for i:=1 to length(path) do
  643. if path[i]='/' then path[i]:='\';
  644. { get drive name }
  645. p1:=pos(':',path);
  646. if p1>0 then
  647. begin
  648. dir:=path[1]+':';
  649. delete(path,1,p1);
  650. end
  651. else
  652. dir:='';
  653. { split the path and the name, there are no more path informtions }
  654. { if path contains no backslashes }
  655. while true do
  656. begin
  657. p1:=pos('\',path);
  658. if p1=0 then
  659. break;
  660. dir:=dir+copy(path,1,p1);
  661. delete(path,1,p1);
  662. end;
  663. { try to find out a extension }
  664. if LFNSupport then
  665. begin
  666. Ext:='';
  667. i:=Length(Path);
  668. DotPos:=256;
  669. While (i>0) Do
  670. Begin
  671. If (Path[i]='.') Then
  672. begin
  673. DotPos:=i;
  674. break;
  675. end;
  676. Dec(i);
  677. end;
  678. Ext:=Copy(Path,DotPos,255);
  679. Name:=Copy(Path,1,DotPos - 1);
  680. end
  681. else
  682. begin
  683. p1:=pos('.',path);
  684. if p1>0 then
  685. begin
  686. ext:=copy(path,p1,4);
  687. delete(path,p1,length(path)-p1+1);
  688. end
  689. else
  690. ext:='';
  691. name:=path;
  692. end;
  693. end;
  694. (*
  695. function FExpand (const Path: PathStr): PathStr;
  696. - declared in fexpand.inc
  697. *)
  698. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  699. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  700. {$I fexpand.inc}
  701. {$UNDEF FPC_FEXPAND_DRIVES}
  702. {$UNDEF FPC_FEXPAND_UNC}
  703. Function FSearch(path: pathstr; dirlist: string): pathstr;
  704. var
  705. i,p1 : longint;
  706. s : searchrec;
  707. newdir : pathstr;
  708. begin
  709. { check if the file specified exists }
  710. findfirst(path,anyfile,s);
  711. if doserror=0 then
  712. begin
  713. findclose(s);
  714. fsearch:=path;
  715. exit;
  716. end;
  717. { No wildcards allowed in these things }
  718. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  719. fsearch:=''
  720. else
  721. begin
  722. { allow slash as backslash }
  723. for i:=1 to length(dirlist) do
  724. if dirlist[i]='/' then dirlist[i]:='\';
  725. repeat
  726. p1:=pos(';',dirlist);
  727. if p1<>0 then
  728. begin
  729. newdir:=copy(dirlist,1,p1-1);
  730. delete(dirlist,1,p1);
  731. end
  732. else
  733. begin
  734. newdir:=dirlist;
  735. dirlist:='';
  736. end;
  737. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  738. newdir:=newdir+'\';
  739. findfirst(newdir+path,anyfile,s);
  740. if doserror=0 then
  741. newdir:=newdir+path
  742. else
  743. newdir:='';
  744. until (dirlist='') or (newdir<>'');
  745. fsearch:=newdir;
  746. end;
  747. findclose(s);
  748. end;
  749. { change to short filename if successful DOS call PM }
  750. function GetShortName(var p : String) : boolean;
  751. var
  752. c : array[0..255] of char;
  753. begin
  754. move(p[1],c[0],length(p));
  755. c[length(p)]:=#0;
  756. copytodos(c,length(p)+1);
  757. dosregs.ax:=$7160;
  758. dosregs.cx:=1;
  759. dosregs.ds:=tb_segment;
  760. dosregs.si:=tb_offset;
  761. dosregs.es:=tb_segment;
  762. dosregs.di:=tb_offset;
  763. msdos(dosregs);
  764. LoadDosError;
  765. if DosError=0 then
  766. begin
  767. copyfromdos(c,255);
  768. move(c[0],p[1],strlen(c));
  769. p[0]:=char(strlen(c));
  770. GetShortName:=true;
  771. end
  772. else
  773. GetShortName:=false;
  774. end;
  775. { change to long filename if successful DOS call PM }
  776. function GetLongName(var p : String) : boolean;
  777. var
  778. c : array[0..255] of char;
  779. begin
  780. move(p[1],c[0],length(p));
  781. c[length(p)]:=#0;
  782. copytodos(c,length(p)+1);
  783. dosregs.ax:=$7160;
  784. dosregs.cx:=2;
  785. dosregs.ds:=tb_segment;
  786. dosregs.si:=tb_offset;
  787. dosregs.es:=tb_segment;
  788. dosregs.di:=tb_offset;
  789. msdos(dosregs);
  790. LoadDosError;
  791. if DosError=0 then
  792. begin
  793. copyfromdos(c,255);
  794. move(c[0],p[1],strlen(c));
  795. p[0]:=char(strlen(c));
  796. GetLongName:=true;
  797. end
  798. else
  799. GetLongName:=false;
  800. end;
  801. {******************************************************************************
  802. --- Get/Set File Time,Attr ---
  803. ******************************************************************************}
  804. procedure getftime(var f;var time : longint);
  805. begin
  806. dosregs.bx:=textrec(f).handle;
  807. dosregs.ax:=$5700;
  808. msdos(dosregs);
  809. loaddoserror;
  810. time:=(dosregs.dx shl 16)+dosregs.cx;
  811. end;
  812. procedure setftime(var f;time : longint);
  813. begin
  814. dosregs.bx:=textrec(f).handle;
  815. dosregs.cx:=time and $ffff;
  816. dosregs.dx:=time shr 16;
  817. dosregs.ax:=$5701;
  818. msdos(dosregs);
  819. loaddoserror;
  820. end;
  821. procedure getfattr(var f;var attr : word);
  822. begin
  823. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  824. dosregs.edx:=tb_offset;
  825. dosregs.ds:=tb_segment;
  826. if LFNSupport then
  827. begin
  828. dosregs.ax:=$7143;
  829. dosregs.bx:=0;
  830. end
  831. else
  832. dosregs.ax:=$4300;
  833. msdos(dosregs);
  834. LoadDosError;
  835. Attr:=dosregs.cx;
  836. end;
  837. procedure setfattr(var f;attr : word);
  838. begin
  839. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  840. dosregs.edx:=tb_offset;
  841. dosregs.ds:=tb_segment;
  842. if LFNSupport then
  843. begin
  844. dosregs.ax:=$7143;
  845. dosregs.bx:=1;
  846. end
  847. else
  848. dosregs.ax:=$4301;
  849. dosregs.cx:=attr;
  850. msdos(dosregs);
  851. LoadDosError;
  852. end;
  853. {******************************************************************************
  854. --- Environment ---
  855. ******************************************************************************}
  856. function envcount : longint;
  857. var
  858. hp : ppchar;
  859. begin
  860. hp:=envp;
  861. envcount:=0;
  862. while assigned(hp^) do
  863. begin
  864. inc(envcount);
  865. inc(hp);
  866. end;
  867. end;
  868. function envstr(index : integer) : string;
  869. begin
  870. if (index<=0) or (index>envcount) then
  871. begin
  872. envstr:='';
  873. exit;
  874. end;
  875. envstr:=strpas(ppchar(pointer(envp)+4*(index-1))^);
  876. end;
  877. Function GetEnv(envvar: string): string;
  878. var
  879. hp : ppchar;
  880. hs : string;
  881. eqpos : longint;
  882. begin
  883. envvar:=upcase(envvar);
  884. hp:=envp;
  885. getenv:='';
  886. while assigned(hp^) do
  887. begin
  888. hs:=strpas(hp^);
  889. eqpos:=pos('=',hs);
  890. if upcase(copy(hs,1,eqpos-1))=envvar then
  891. begin
  892. getenv:=copy(hs,eqpos+1,255);
  893. exit;
  894. end;
  895. inc(hp);
  896. end;
  897. end;
  898. {******************************************************************************
  899. --- Not Supported ---
  900. ******************************************************************************}
  901. Procedure keep(exitcode : word);
  902. Begin
  903. End;
  904. Procedure getintvec(intno : byte;var vector : pointer);
  905. Begin
  906. End;
  907. Procedure setintvec(intno : byte;vector : pointer);
  908. Begin
  909. End;
  910. end.
  911. {
  912. $Log$
  913. Revision 1.14 2001-11-23 00:18:54 carl
  914. * completely merged from fixes branch
  915. Revision 1.1.2.15 2001/10/04 11:23:22 pierre
  916. * fix failure check for do_diskdata with LFN support
  917. Revision 1.1.2.14 2001/06/13 22:13:15 hajny
  918. * universal FExpand merged
  919. Revision 1.1.2.13 2001/06/06 11:05:27 pierre
  920. * correct SwapVectors behavior
  921. Revision 1.1.2.12 2000/12/16 15:34:28 peter
  922. * fixed disksize return -1 for error
  923. Revision 1.1.2.11 2000/10/11 15:38:17 peter
  924. * diskfree doserror fix
  925. Revision 1.1.2.10 2000/09/22 10:09:42 pierre
  926. * fix LFN handle problem if FindFirst fails
  927. Revision 1.1.2.9 2000/09/22 08:42:51 pierre
  928. * fix wrong DiskSize report
  929. Revision 1.1.2.8 2000/09/06 20:46:18 peter
  930. * removed previous fsplit() patch as it's not the correct behaviour for
  931. LFNs. The code showing the bug could easily be adapted
  932. Revision 1.1.2.7 2000/09/04 20:15:22 peter
  933. * fixed previous commit
  934. Revision 1.1.2.6 2000/09/04 19:36:24 peter
  935. * fsplit with .. fix from Thomas
  936. Revision 1.1.2.5 2000/08/04 21:40:25 peter
  937. * getenv is case insentive, needed for windir and winbootdir envs
  938. Revision 1.1.2.4 2000/08/02 19:34:14 peter
  939. * more doserror fixes
  940. Revision 1.1.2.3 2000/07/30 17:06:23 peter
  941. * removed dos lf
  942. Revision 1.1.2.2 2000/07/30 16:35:44 peter
  943. * don't set doserror in gettime/settime/getdate/setdate, tp compatible
  944. Revision 1.1.2.1 2000/07/22 12:21:30 jonas
  945. * fixed buffer overrun error in dossearchrec2searchrec when a file
  946. is not found (at least it happened in OS/2's VDM)
  947. Revision 1.1 2000/07/13 06:30:35 michael
  948. + Initial import
  949. Revision 1.24 2000/05/30 04:41:05 jonas
  950. * fixed compiling problem with formal expression passed as var
  951. parameter
  952. Revision 1.23 2000/03/22 08:00:42 pierre
  953. + allow double backslash for network drives
  954. Revision 1.22 2000/02/09 16:59:28 peter
  955. * truncated log
  956. Revision 1.21 2000/02/09 13:00:32 peter
  957. + getlongname
  958. Revision 1.20 2000/02/02 17:34:49 pierre
  959. * use int64 typecast to avoid overflows in diskfree and disksize
  960. Revision 1.19 2000/01/23 16:31:23 peter
  961. * hasint64diskspace define changed to int64 so it's default now
  962. Revision 1.18 2000/01/23 12:28:38 marco
  963. * Added diskfree and disksize with AH=71 dos functions (LFN/Fat32)
  964. Revision 1.17 2000/01/07 16:41:30 daniel
  965. * copyright 2000
  966. Revision 1.16 2000/01/07 16:32:23 daniel
  967. * copyright 2000 added
  968. Revision 1.15 1999/12/06 18:26:49 peter
  969. * fpcmake updated for win32 commandline
  970. Revision 1.14 1999/11/09 11:07:50 pierre
  971. * SwapVectors does not reset DosError anymore
  972. + DosError is set to ax regsiter value if extended doserror function
  973. retruns zero.
  974. + Support for LFN in EXEC function using
  975. function 7160 to get short filename counterpart
  976. Revision 1.13 1999/11/06 14:38:23 peter
  977. * truncated log
  978. Revision 1.12 1999/09/10 17:14:09 peter
  979. * better errorcode returning using int21h,5900
  980. Revision 1.11 1999/09/08 18:55:49 peter
  981. * pointer fixes
  982. Revision 1.10 1999/08/13 21:23:15 peter
  983. * fsearch checks first if the specified file exists and returns that
  984. if it was found
  985. }