dos.pp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team.
  4. Dos unit for BP7 compatible RTL
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$inline on}
  12. unit dos;
  13. interface
  14. Uses
  15. Go32;
  16. Type
  17. searchrec = packed record
  18. fill : array[1..21] of byte;
  19. attr : byte;
  20. time : longint;
  21. { reserved : word; not in DJGPP V2 }
  22. size : longint;
  23. name : string[255]; { LFN Name, DJGPP uses only [12] but more can't hurt (PFV) }
  24. end;
  25. {$DEFINE HAS_REGISTERS}
  26. Registers = Go32.Registers;
  27. {$i dosh.inc}
  28. implementation
  29. uses
  30. strings;
  31. {$DEFINE HAS_GETMSCOUNT}
  32. {$DEFINE HAS_INTR}
  33. {$DEFINE HAS_SETCBREAK}
  34. {$DEFINE HAS_GETCBREAK}
  35. {$DEFINE HAS_SETVERIFY}
  36. {$DEFINE HAS_GETVERIFY}
  37. {$DEFINE HAS_SWAPVECTORS}
  38. {$DEFINE HAS_GETSHORTNAME}
  39. {$DEFINE HAS_GETLONGNAME}
  40. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  41. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  42. {$I dos.inc}
  43. {******************************************************************************
  44. --- Dos Interrupt ---
  45. ******************************************************************************}
  46. var
  47. dosregs : registers;
  48. procedure LoadDosError;
  49. var
  50. r : registers;
  51. SimpleDosError : word;
  52. begin
  53. if (dosregs.flags and fcarry) <> 0 then
  54. begin
  55. { I got a extended error = 0
  56. while CarryFlag was set from Exec function }
  57. SimpleDosError:=dosregs.ax;
  58. r.eax:=$5900;
  59. r.ebx:=$0;
  60. realintr($21,r);
  61. { conversion from word to integer !!
  62. gave a Bound check error if ax is $FFFF !! PM }
  63. doserror:=integer(r.ax);
  64. case doserror of
  65. 0 : DosError:=integer(SimpleDosError);
  66. 19 : DosError:=150;
  67. 21 : DosError:=152;
  68. end;
  69. end
  70. else
  71. doserror:=0;
  72. end;
  73. procedure intr(intno : byte;var regs : registers);
  74. begin
  75. realintr(intno,regs);
  76. end;
  77. {******************************************************************************
  78. --- Info / Date / Time ---
  79. ******************************************************************************}
  80. function dosversion : word;
  81. begin
  82. dosregs.ax:=$3000;
  83. msdos(dosregs);
  84. dosversion:=dosregs.ax;
  85. end;
  86. procedure getdate(var year,month,mday,wday : word);
  87. begin
  88. dosregs.ax:=$2a00;
  89. msdos(dosregs);
  90. wday:=dosregs.al;
  91. year:=dosregs.cx;
  92. month:=dosregs.dh;
  93. mday:=dosregs.dl;
  94. end;
  95. procedure setdate(year,month,day : word);
  96. begin
  97. dosregs.cx:=year;
  98. dosregs.dh:=month;
  99. dosregs.dl:=day;
  100. dosregs.ah:=$2b;
  101. msdos(dosregs);
  102. end;
  103. procedure gettime(var hour,minute,second,sec100 : word);
  104. begin
  105. dosregs.ah:=$2c;
  106. msdos(dosregs);
  107. hour:=dosregs.ch;
  108. minute:=dosregs.cl;
  109. second:=dosregs.dh;
  110. sec100:=dosregs.dl;
  111. end;
  112. procedure settime(hour,minute,second,sec100 : word);
  113. begin
  114. dosregs.ch:=hour;
  115. dosregs.cl:=minute;
  116. dosregs.dh:=second;
  117. dosregs.dl:=sec100;
  118. dosregs.ah:=$2d;
  119. msdos(dosregs);
  120. end;
  121. function GetMsCount: int64;
  122. begin
  123. GetMsCount := int64 (MemL [$40:$6c]) * 55;
  124. end;
  125. {******************************************************************************
  126. --- Exec ---
  127. ******************************************************************************}
  128. procedure exec(const path : pathstr;const comline : comstr);
  129. type
  130. realptr = packed record
  131. ofs,seg : word;
  132. end;
  133. texecblock = packed record
  134. envseg : word;
  135. comtail : realptr;
  136. firstFCB : realptr;
  137. secondFCB : realptr;
  138. { iniStack : realptr;
  139. iniCSIP : realptr;}
  140. end;
  141. var
  142. current_dos_buffer_pos,
  143. arg_ofs,
  144. i,la_env,
  145. la_p,la_c,la_e,
  146. fcb1_la,fcb2_la : longint;
  147. execblock : texecblock;
  148. c,p : string;
  149. function paste_to_dos(src : string;cr : boolean; n : longint) : boolean;
  150. {Changed by Laaca - added parameter N}
  151. var
  152. c : pchar;
  153. CLen : cardinal;
  154. ls : longint;
  155. begin
  156. paste_to_dos:=false;
  157. ls:=Length(src)-n;
  158. if current_dos_buffer_pos+ls+3>transfer_buffer+tb_size then
  159. RunError(217);
  160. getmem(c,ls+3);
  161. move(src[n],c^,ls+1);
  162. if cr then
  163. begin
  164. c[ls+1]:=#13;
  165. c[ls+2]:=#0;
  166. end
  167. else
  168. c[ls+1]:=#0;
  169. CLen := StrLen (C) + 1;
  170. seg_move(get_ds,longint(c),dosmemselector,current_dos_buffer_pos,CLen);
  171. current_dos_buffer_pos:=current_dos_buffer_pos+CLen;
  172. freemem(c,ls+3);
  173. paste_to_dos:=true;
  174. end;
  175. begin
  176. { create command line }
  177. c:=comline;
  178. { create path }
  179. p:=path;
  180. { allow slash as backslash }
  181. DoDirSeparators(p);
  182. if LFNSupport then
  183. GetShortName(p);
  184. { create buffer }
  185. la_env:=transfer_buffer;
  186. while (la_env and 15)<>0 do
  187. inc(la_env);
  188. current_dos_buffer_pos:=la_env;
  189. { copy environment }
  190. for i:=1 to envcount do
  191. paste_to_dos(envstr(i),false,1);
  192. {the behaviour is still suboptimal because variable COMMAND is stripped out}
  193. paste_to_dos(chr(0),false,1); { adds a double zero at the end }
  194. la_p:=current_dos_buffer_pos;
  195. paste_to_dos(p,false,0);
  196. la_c:=current_dos_buffer_pos;
  197. paste_to_dos(c,true,0);
  198. la_e:=current_dos_buffer_pos;
  199. fcb1_la:=la_e;
  200. la_e:=la_e+16;
  201. fcb2_la:=la_e;
  202. la_e:=la_e+16;
  203. { allocate FCB see dosexec code }
  204. arg_ofs:=1;
  205. while (c[arg_ofs] in [' ',#9]) and
  206. (arg_ofs<length(c)) do
  207. inc(arg_ofs);
  208. dosregs.ax:=$2901;
  209. dosregs.ds:=(la_c+arg_ofs) shr 4;
  210. dosregs.esi:=(la_c+arg_ofs) and 15;
  211. dosregs.es:=fcb1_la shr 4;
  212. dosregs.edi:=fcb1_la and 15;
  213. msdos(dosregs);
  214. { allocate second FCB see dosexec code }
  215. dosregs.ax:=$2901;
  216. dosregs.ds:=(la_c+arg_ofs) shr 4;
  217. dosregs.esi:=(la_c+arg_ofs) and 15;
  218. dosregs.es:=fcb2_la shr 4;
  219. dosregs.edi:=fcb2_la and 15;
  220. msdos(dosregs);
  221. with execblock do
  222. begin
  223. envseg:=la_env shr 4;
  224. comtail.seg:=la_c shr 4;
  225. comtail.ofs:=la_c and 15;
  226. firstFCB.seg:=fcb1_la shr 4;
  227. firstFCB.ofs:=fcb1_la and 15;
  228. secondFCB.seg:=fcb2_la shr 4;
  229. secondFCB.ofs:=fcb2_la and 15;
  230. end;
  231. seg_move(get_ds,longint(@execblock),dosmemselector,la_e,sizeof(texecblock));
  232. dosregs.edx:=la_p and 15+1;
  233. dosregs.ds:=la_p shr 4;
  234. dosregs.ebx:=la_p and 15+la_e-la_p;
  235. dosregs.es:=la_p shr 4;
  236. dosregs.ax:=$4b00;
  237. msdos(dosregs);
  238. LoadDosError;
  239. if DosError<>0 then
  240. begin
  241. dosregs.ax:=$4d00;
  242. msdos(dosregs);
  243. LastDosExitCode:=DosRegs.al
  244. end
  245. else
  246. LastDosExitCode:=0;
  247. end;
  248. procedure getcbreak(var breakvalue : boolean);
  249. begin
  250. dosregs.ax:=$3300;
  251. msdos(dosregs);
  252. breakvalue:=dosregs.dl<>0;
  253. end;
  254. procedure setcbreak(breakvalue : boolean);
  255. begin
  256. dosregs.ax:=$3301;
  257. dosregs.dl:=ord(breakvalue);
  258. msdos(dosregs);
  259. end;
  260. procedure getverify(var verify : boolean);
  261. begin
  262. dosregs.ah:=$54;
  263. msdos(dosregs);
  264. verify:=dosregs.al<>0;
  265. end;
  266. procedure setverify(verify : boolean);
  267. begin
  268. dosregs.ah:=$2e;
  269. dosregs.al:=ord(verify);
  270. msdos(dosregs);
  271. end;
  272. {******************************************************************************
  273. --- Disk ---
  274. ******************************************************************************}
  275. TYPE ExtendedFat32FreeSpaceRec=packed Record
  276. RetSize : WORD; { (ret) size of returned structure}
  277. Strucversion : WORD; {(call) structure version (0000h)
  278. (ret) actual structure version (0000h)}
  279. SecPerClus, {number of sectors per cluster}
  280. BytePerSec, {number of bytes per sector}
  281. AvailClusters, {number of available clusters}
  282. TotalClusters, {total number of clusters on the drive}
  283. AvailPhysSect, {physical sectors available on the drive}
  284. TotalPhysSect, {total physical sectors on the drive}
  285. AvailAllocUnits, {Available allocation units}
  286. TotalAllocUnits : DWORD; {Total allocation units}
  287. Dummy,Dummy2 : DWORD; {8 bytes reserved}
  288. END;
  289. function do_diskdata(drive : byte; Free : BOOLEAN) : Int64;
  290. VAR
  291. S : String;
  292. Rec : ExtendedFat32FreeSpaceRec;
  293. procedure OldDosDiskData; inline;
  294. begin
  295. dosregs.dl:=drive;
  296. dosregs.ah:=$36;
  297. msdos(dosregs);
  298. if dosregs.ax<>$FFFF then
  299. begin
  300. if Free then
  301. Do_DiskData:=int64(dosregs.ax)*dosregs.bx*dosregs.cx
  302. else
  303. Do_DiskData:=int64(dosregs.ax)*dosregs.cx*dosregs.dx;
  304. end
  305. else
  306. do_diskdata:=-1;
  307. end;
  308. BEGIN
  309. if LFNSupport then
  310. begin
  311. S:='C:\'#0;
  312. if Drive=0 then
  313. begin
  314. GetDir(Drive,S);
  315. Setlength(S,4);
  316. S[4]:=#0;
  317. end
  318. else
  319. S[1]:=chr(Drive+64);
  320. Rec.Strucversion:=0;
  321. Rec.RetSize := 0;
  322. dosmemput(tb_segment,tb_offset,Rec,SIZEOF(ExtendedFat32FreeSpaceRec));
  323. dosmemput(tb_segment,tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1,S[1],4);
  324. dosregs.dx:=tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1;
  325. dosregs.ds:=tb_segment;
  326. dosregs.di:=tb_offset;
  327. dosregs.es:=tb_segment;
  328. dosregs.cx:=Sizeof(ExtendedFat32FreeSpaceRec);
  329. dosregs.ax:=$7303;
  330. msdos(dosregs);
  331. if (dosregs.flags and fcarry) = 0 then {No error clausule in int except cf}
  332. begin
  333. copyfromdos(rec,Sizeof(ExtendedFat32FreeSpaceRec));
  334. if Rec.RetSize = 0 then (* Error - "FAT32" function not supported! *)
  335. OldDosDiskData
  336. else
  337. if Free then
  338. Do_DiskData:=int64(rec.AvailAllocUnits)*rec.SecPerClus*rec.BytePerSec
  339. else
  340. Do_DiskData:=int64(rec.TotalAllocUnits)*rec.SecPerClus*rec.BytePerSec;
  341. end
  342. else
  343. Do_DiskData:=-1;
  344. end
  345. else
  346. OldDosDiskData;
  347. end;
  348. function diskfree(drive : byte) : int64;
  349. begin
  350. diskfree:=Do_DiskData(drive,TRUE);
  351. end;
  352. function disksize(drive : byte) : int64;
  353. begin
  354. disksize:=Do_DiskData(drive,false);
  355. end;
  356. {******************************************************************************
  357. --- LFNFindfirst LFNFindNext ---
  358. ******************************************************************************}
  359. type
  360. LFNSearchRec=packed record
  361. attr,
  362. crtime,
  363. crtimehi,
  364. actime,
  365. actimehi,
  366. lmtime,
  367. lmtimehi,
  368. sizehi,
  369. size : longint;
  370. reserved : array[0..7] of byte;
  371. name : array[0..259] of byte;
  372. shortname : array[0..13] of byte;
  373. end;
  374. procedure LFNSearchRec2Dos(const w:LFNSearchRec;hdl:longint;var d:Searchrec;from_findfirst : boolean);
  375. var
  376. Len : longint;
  377. begin
  378. With w do
  379. begin
  380. FillChar(d,sizeof(SearchRec),0);
  381. if DosError=0 then
  382. len:=StrLen(@Name)
  383. else
  384. len:=0;
  385. d.Name[0]:=chr(len);
  386. Move(Name[0],d.Name[1],Len);
  387. d.Time:=lmTime;
  388. d.Size:=Size;
  389. d.Attr:=Attr and $FF;
  390. if (DosError<>0) and from_findfirst then
  391. hdl:=-1;
  392. Move(hdl,d.Fill,4);
  393. end;
  394. end;
  395. {$ifdef DEBUG_LFN}
  396. const
  397. LFNFileName : string = 'LFN.log';
  398. LFNOpenNb : longint = 0;
  399. LogLFN : boolean = false;
  400. var
  401. lfnfile : text;
  402. {$endif DEBUG_LFN}
  403. procedure LFNFindFirst(path:pchar;attr:longint;var s:searchrec);
  404. var
  405. i : longint;
  406. w : LFNSearchRec;
  407. begin
  408. { allow slash as backslash }
  409. DoDirSeparators(path);
  410. dosregs.si:=1; { use ms-dos time }
  411. { don't include the label if not asked for it, needed for network drives }
  412. if attr=$8 then
  413. dosregs.ecx:=8
  414. else
  415. dosregs.ecx:=attr and (not 8);
  416. dosregs.edx:=tb_offset+Sizeof(LFNSearchrec)+1;
  417. dosmemput(tb_segment,tb_offset+Sizeof(LFNSearchrec)+1,path^,strlen(path)+1);
  418. dosregs.ds:=tb_segment;
  419. dosregs.edi:=tb_offset;
  420. dosregs.es:=tb_segment;
  421. dosregs.ax:=$714e;
  422. msdos(dosregs);
  423. LoadDosError;
  424. {$ifdef DEBUG_LFN}
  425. if (DosError=0) and LogLFN then
  426. begin
  427. Append(lfnfile);
  428. inc(LFNOpenNb);
  429. Writeln(lfnfile,LFNOpenNb,' LFNFindFirst called ',path);
  430. close(lfnfile);
  431. end;
  432. {$endif DEBUG_LFN}
  433. copyfromdos(w,sizeof(LFNSearchRec));
  434. LFNSearchRec2Dos(w,dosregs.ax,s,true);
  435. end;
  436. procedure LFNFindNext(var s:searchrec);
  437. var
  438. hdl : longint;
  439. w : LFNSearchRec;
  440. begin
  441. Move(s.Fill,hdl,4);
  442. dosregs.si:=1; { use ms-dos time }
  443. dosregs.edi:=tb_offset;
  444. dosregs.es:=tb_segment;
  445. dosregs.ebx:=hdl;
  446. dosregs.ax:=$714f;
  447. msdos(dosregs);
  448. LoadDosError;
  449. copyfromdos(w,sizeof(LFNSearchRec));
  450. LFNSearchRec2Dos(w,hdl,s,false);
  451. end;
  452. procedure LFNFindClose(var s:searchrec);
  453. var
  454. hdl : longint;
  455. begin
  456. Move(s.Fill,hdl,4);
  457. { Do not call MsDos if FindFirst returned with an error }
  458. if hdl=-1 then
  459. begin
  460. DosError:=0;
  461. exit;
  462. end;
  463. dosregs.ebx:=hdl;
  464. dosregs.ax:=$71a1;
  465. msdos(dosregs);
  466. LoadDosError;
  467. {$ifdef DEBUG_LFN}
  468. if (DosError=0) and LogLFN then
  469. begin
  470. Append(lfnfile);
  471. Writeln(lfnfile,LFNOpenNb,' LFNFindClose called ');
  472. close(lfnfile);
  473. if LFNOpenNb>0 then
  474. dec(LFNOpenNb);
  475. end;
  476. {$endif DEBUG_LFN}
  477. end;
  478. {******************************************************************************
  479. --- DosFindfirst DosFindNext ---
  480. ******************************************************************************}
  481. procedure dossearchrec2searchrec(var f : searchrec);
  482. var
  483. len : longint;
  484. begin
  485. { Check is necessary!! OS/2's VDM doesn't clear the name with #0 if the }
  486. { file doesn't exist! (JM) }
  487. if dosError = 0 then
  488. len:=StrLen(@f.Name)
  489. else len := 0;
  490. Move(f.Name[0],f.Name[1],Len);
  491. f.Name[0]:=chr(len);
  492. end;
  493. procedure DosFindfirst(path : pchar;attr : word;var f : searchrec);
  494. var
  495. i : longint;
  496. begin
  497. { allow slash as backslash }
  498. DoDirSeparators(path);
  499. copytodos(f,sizeof(searchrec));
  500. dosregs.edx:=tb_offset;
  501. dosregs.ds:=tb_segment;
  502. dosregs.ah:=$1a;
  503. msdos(dosregs);
  504. dosregs.ecx:=attr;
  505. dosregs.edx:=tb_offset+Sizeof(searchrec)+1;
  506. dosmemput(tb_segment,tb_offset+Sizeof(searchrec)+1,path^,strlen(path)+1);
  507. dosregs.ds:=tb_segment;
  508. dosregs.ah:=$4e;
  509. msdos(dosregs);
  510. copyfromdos(f,sizeof(searchrec));
  511. LoadDosError;
  512. dossearchrec2searchrec(f);
  513. end;
  514. procedure Dosfindnext(var f : searchrec);
  515. begin
  516. copytodos(f,sizeof(searchrec));
  517. dosregs.edx:=tb_offset;
  518. dosregs.ds:=tb_segment;
  519. dosregs.ah:=$1a;
  520. msdos(dosregs);
  521. dosregs.ah:=$4f;
  522. msdos(dosregs);
  523. copyfromdos(f,sizeof(searchrec));
  524. LoadDosError;
  525. dossearchrec2searchrec(f);
  526. end;
  527. {******************************************************************************
  528. --- Findfirst FindNext ---
  529. ******************************************************************************}
  530. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  531. var
  532. path0 : array[0..255] of char;
  533. begin
  534. doserror:=0;
  535. strpcopy(path0,path);
  536. if LFNSupport then
  537. LFNFindFirst(path0,attr,f)
  538. else
  539. Dosfindfirst(path0,attr,f);
  540. end;
  541. procedure findnext(var f : searchRec);
  542. begin
  543. doserror:=0;
  544. if LFNSupport then
  545. LFNFindnext(f)
  546. else
  547. Dosfindnext(f);
  548. end;
  549. Procedure FindClose(Var f: SearchRec);
  550. begin
  551. DosError:=0;
  552. if LFNSupport then
  553. LFNFindClose(f);
  554. end;
  555. type swap_proc = procedure;
  556. var
  557. _swap_in : swap_proc;external name '_swap_in';
  558. _swap_out : swap_proc;external name '_swap_out';
  559. _exception_exit : pointer;external name '_exception_exit';
  560. _v2prt0_exceptions_on : longbool;external name '_v2prt0_exceptions_on';
  561. procedure swapvectors;
  562. begin
  563. if _exception_exit<>nil then
  564. if _v2prt0_exceptions_on then
  565. _swap_out()
  566. else
  567. _swap_in();
  568. end;
  569. {******************************************************************************
  570. --- File ---
  571. ******************************************************************************}
  572. Function FSearch(path: pathstr; dirlist: string): pathstr;
  573. var
  574. i,p1 : longint;
  575. s : searchrec;
  576. newdir : pathstr;
  577. begin
  578. { check if the file specified exists }
  579. findfirst(path,anyfile and not(directory),s);
  580. if doserror=0 then
  581. begin
  582. findclose(s);
  583. fsearch:=path;
  584. exit;
  585. end;
  586. { No wildcards allowed in these things }
  587. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  588. fsearch:=''
  589. else
  590. begin
  591. { allow slash as backslash }
  592. DoDirSeparators(dirlist);
  593. repeat
  594. p1:=pos(';',dirlist);
  595. if p1<>0 then
  596. begin
  597. newdir:=copy(dirlist,1,p1-1);
  598. delete(dirlist,1,p1);
  599. end
  600. else
  601. begin
  602. newdir:=dirlist;
  603. dirlist:='';
  604. end;
  605. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  606. newdir:=newdir+'\';
  607. findfirst(newdir+path,anyfile and not(directory),s);
  608. if doserror=0 then
  609. newdir:=newdir+path
  610. else
  611. newdir:='';
  612. until (dirlist='') or (newdir<>'');
  613. fsearch:=newdir;
  614. end;
  615. findclose(s);
  616. end;
  617. { change to short filename if successful DOS call PM }
  618. function GetShortName(var p : String) : boolean;
  619. var
  620. c : array[0..255] of char;
  621. begin
  622. move(p[1],c[0],length(p));
  623. c[length(p)]:=#0;
  624. copytodos(c,length(p)+1);
  625. dosregs.ax:=$7160;
  626. dosregs.cx:=1;
  627. dosregs.ds:=tb_segment;
  628. dosregs.si:=tb_offset;
  629. dosregs.es:=tb_segment;
  630. dosregs.di:=tb_offset;
  631. msdos(dosregs);
  632. LoadDosError;
  633. if DosError=0 then
  634. begin
  635. copyfromdos(c,256);
  636. move(c[0],p[1],strlen(c));
  637. p[0]:=char(strlen(c));
  638. GetShortName:=true;
  639. end
  640. else
  641. GetShortName:=false;
  642. end;
  643. { change to long filename if successful DOS call PM }
  644. function GetLongName(var p : String) : boolean;
  645. var
  646. c : array[0..255] of char;
  647. begin
  648. move(p[1],c[0],length(p));
  649. c[length(p)]:=#0;
  650. copytodos(c,length(p)+1);
  651. dosregs.ax:=$7160;
  652. dosregs.cx:=2;
  653. dosregs.ds:=tb_segment;
  654. dosregs.si:=tb_offset;
  655. dosregs.es:=tb_segment;
  656. dosregs.di:=tb_offset;
  657. msdos(dosregs);
  658. LoadDosError;
  659. if DosError=0 then
  660. begin
  661. copyfromdos(c,256);
  662. move(c[0],p[1],strlen(c));
  663. p[0]:=char(strlen(c));
  664. GetLongName:=true;
  665. end
  666. else
  667. GetLongName:=false;
  668. end;
  669. {******************************************************************************
  670. --- Get/Set File Time,Attr ---
  671. ******************************************************************************}
  672. procedure getftime(var f;var time : longint);
  673. begin
  674. dosregs.bx:=textrec(f).handle;
  675. dosregs.ax:=$5700;
  676. msdos(dosregs);
  677. loaddoserror;
  678. time:=(dosregs.dx shl 16)+dosregs.cx;
  679. end;
  680. procedure setftime(var f;time : longint);
  681. begin
  682. dosregs.bx:=textrec(f).handle;
  683. dosregs.cx:=time and $ffff;
  684. dosregs.dx:=time shr 16;
  685. dosregs.ax:=$5701;
  686. msdos(dosregs);
  687. loaddoserror;
  688. end;
  689. procedure getfattr(var f;var attr : word);
  690. begin
  691. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  692. dosregs.edx:=tb_offset;
  693. dosregs.ds:=tb_segment;
  694. if LFNSupport then
  695. begin
  696. dosregs.ax:=$7143;
  697. dosregs.bx:=0;
  698. end
  699. else
  700. dosregs.ax:=$4300;
  701. msdos(dosregs);
  702. LoadDosError;
  703. Attr:=dosregs.cx;
  704. end;
  705. procedure setfattr(var f;attr : word);
  706. begin
  707. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  708. dosregs.edx:=tb_offset;
  709. dosregs.ds:=tb_segment;
  710. if LFNSupport then
  711. begin
  712. dosregs.ax:=$7143;
  713. dosregs.bx:=1;
  714. end
  715. else
  716. dosregs.ax:=$4301;
  717. dosregs.cx:=attr;
  718. msdos(dosregs);
  719. LoadDosError;
  720. end;
  721. {******************************************************************************
  722. --- Environment ---
  723. ******************************************************************************}
  724. function envcount : longint;
  725. var
  726. hp : ppchar;
  727. begin
  728. hp:=envp;
  729. envcount:=0;
  730. while assigned(hp^) do
  731. begin
  732. inc(envcount);
  733. inc(hp);
  734. end;
  735. end;
  736. function envstr (Index: longint): string;
  737. begin
  738. if (index<=0) or (index>envcount) then
  739. envstr:=''
  740. else
  741. envstr:=strpas(ppchar(pointer(envp)+SizeOf(PChar)*(index-1))^);
  742. end;
  743. Function GetEnv(envvar: string): string;
  744. var
  745. hp : ppchar;
  746. hs : string;
  747. eqpos : longint;
  748. begin
  749. envvar:=upcase(envvar);
  750. hp:=envp;
  751. getenv:='';
  752. while assigned(hp^) do
  753. begin
  754. hs:=strpas(hp^);
  755. eqpos:=pos('=',hs);
  756. if upcase(copy(hs,1,eqpos-1))=envvar then
  757. begin
  758. getenv:=copy(hs,eqpos+1,length(hs)-eqpos);
  759. break;
  760. end;
  761. inc(hp);
  762. end;
  763. end;
  764. {$ifdef DEBUG_LFN}
  765. begin
  766. LogLFN:=(GetEnv('LOGLFN')<>'');
  767. assign(lfnfile,LFNFileName);
  768. {$I-}
  769. Reset(lfnfile);
  770. if IOResult<>0 then
  771. begin
  772. Rewrite(lfnfile);
  773. Writeln(lfnfile,'New lfn.log');
  774. end;
  775. close(lfnfile);
  776. {$endif DEBUG_LFN}
  777. end.