dos.pp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083
  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. DosError:=0;
  347. dosregs.ax:=$3300;
  348. msdos(dosregs);
  349. breakvalue:=dosregs.dl<>0;
  350. end;
  351. procedure setcbreak(breakvalue : boolean);
  352. begin
  353. DosError:=0;
  354. dosregs.ax:=$3301;
  355. dosregs.dl:=ord(breakvalue);
  356. msdos(dosregs);
  357. end;
  358. procedure getverify(var verify : boolean);
  359. begin
  360. DosError:=0;
  361. dosregs.ah:=$54;
  362. msdos(dosregs);
  363. verify:=dosregs.al<>0;
  364. end;
  365. procedure setverify(verify : boolean);
  366. begin
  367. DosError:=0;
  368. dosregs.ah:=$2e;
  369. dosregs.al:=ord(verify);
  370. msdos(dosregs);
  371. end;
  372. {******************************************************************************
  373. --- Disk ---
  374. ******************************************************************************}
  375. TYPE ExtendedFat32FreeSpaceRec=packed Record
  376. RetSize : WORD; { (ret) size of returned structure}
  377. Strucversion : WORD; {(call) structure version (0000h)
  378. (ret) actual structure version (0000h)}
  379. SecPerClus, {number of sectors per cluster}
  380. BytePerSec, {number of bytes per sector}
  381. AvailClusters, {number of available clusters}
  382. TotalClusters, {total number of clusters on the drive}
  383. AvailPhysSect, {physical sectors available on the drive}
  384. TotalPhysSect, {total physical sectors on the drive}
  385. AvailAllocUnits, {Available allocation units}
  386. TotalAllocUnits : DWORD; {Total allocation units}
  387. Dummy,Dummy2 : DWORD; {8 bytes reserved}
  388. END;
  389. function do_diskdata(drive : byte; Free : BOOLEAN) : Int64;
  390. VAR
  391. S : String;
  392. Rec : ExtendedFat32FreeSpaceRec;
  393. BEGIN
  394. if (swap(dosversion)>=$070A) AND LFNSupport then
  395. begin
  396. S:='C:\'#0;
  397. if Drive=0 then
  398. begin
  399. GetDir(Drive,S);
  400. Setlength(S,4);
  401. S[4]:=#0;
  402. end
  403. else
  404. S[1]:=chr(Drive+64);
  405. Rec.Strucversion:=0;
  406. dosmemput(tb_segment,tb_offset,Rec,SIZEOF(ExtendedFat32FreeSpaceRec));
  407. dosmemput(tb_segment,tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1,S[1],4);
  408. dosregs.dx:=tb_offset+Sizeof(ExtendedFat32FreeSpaceRec)+1;
  409. dosregs.ds:=tb_segment;
  410. dosregs.di:=tb_offset;
  411. dosregs.es:=tb_segment;
  412. dosregs.cx:=Sizeof(ExtendedFat32FreeSpaceRec);
  413. dosregs.ax:=$7303;
  414. msdos(dosregs);
  415. copyfromdos(rec,Sizeof(ExtendedFat32FreeSpaceRec));
  416. if (dosregs.flags and fcarry) = 0 then {No error clausule in int except cf}
  417. begin
  418. copyfromdos(rec,Sizeof(ExtendedFat32FreeSpaceRec));
  419. if Free then
  420. Do_DiskData:=int64(rec.AvailAllocUnits)*rec.SecPerClus*rec.BytePerSec
  421. else
  422. Do_DiskData:=int64(rec.TotalAllocUnits)*rec.SecPerClus*rec.BytePerSec;
  423. end
  424. else
  425. Do_DiskData:=-1;
  426. end
  427. else
  428. begin
  429. dosregs.dl:=drive;
  430. dosregs.ah:=$36;
  431. msdos(dosregs);
  432. if dosregs.ax<>$FFFF then
  433. begin
  434. if Free then
  435. Do_DiskData:=int64(dosregs.ax)*dosregs.bx*dosregs.cx
  436. else
  437. Do_DiskData:=int64(dosregs.ax)*dosregs.cx*dosregs.dx;
  438. end
  439. else
  440. do_diskdata:=-1;
  441. end;
  442. end;
  443. function diskfree(drive : byte) : int64;
  444. begin
  445. diskfree:=Do_DiskData(drive,TRUE);
  446. end;
  447. function disksize(drive : byte) : int64;
  448. begin
  449. disksize:=Do_DiskData(drive,false);
  450. end;
  451. {******************************************************************************
  452. --- LFNFindfirst LFNFindNext ---
  453. ******************************************************************************}
  454. type
  455. LFNSearchRec=packed record
  456. attr,
  457. crtime,
  458. crtimehi,
  459. actime,
  460. actimehi,
  461. lmtime,
  462. lmtimehi,
  463. sizehi,
  464. size : longint;
  465. reserved : array[0..7] of byte;
  466. name : array[0..259] of byte;
  467. shortname : array[0..13] of byte;
  468. end;
  469. procedure LFNSearchRec2Dos(const w:LFNSearchRec;hdl:longint;var d:Searchrec);
  470. var
  471. Len : longint;
  472. begin
  473. With w do
  474. begin
  475. FillChar(d,sizeof(SearchRec),0);
  476. if DosError=0 then
  477. len:=StrLen(@Name)
  478. else
  479. len:=0;
  480. d.Name[0]:=chr(len);
  481. Move(Name[0],d.Name[1],Len);
  482. d.Time:=lmTime;
  483. d.Size:=Size;
  484. d.Attr:=Attr and $FF;
  485. Move(hdl,d.Fill,4);
  486. end;
  487. end;
  488. procedure LFNFindFirst(path:pchar;attr:longint;var s:searchrec);
  489. var
  490. i : longint;
  491. w : LFNSearchRec;
  492. begin
  493. { allow slash as backslash }
  494. for i:=0 to strlen(path) do
  495. if path[i]='/' then path[i]:='\';
  496. dosregs.si:=1; { use ms-dos time }
  497. { don't include the label if not asked for it, needed for network drives }
  498. if attr=$8 then
  499. dosregs.ecx:=8
  500. else
  501. dosregs.ecx:=attr and (not 8);
  502. dosregs.edx:=tb_offset+Sizeof(LFNSearchrec)+1;
  503. dosmemput(tb_segment,tb_offset+Sizeof(LFNSearchrec)+1,path^,strlen(path)+1);
  504. dosregs.ds:=tb_segment;
  505. dosregs.edi:=tb_offset;
  506. dosregs.es:=tb_segment;
  507. dosregs.ax:=$714e;
  508. msdos(dosregs);
  509. LoadDosError;
  510. copyfromdos(w,sizeof(LFNSearchRec));
  511. LFNSearchRec2Dos(w,dosregs.ax,s);
  512. end;
  513. procedure LFNFindNext(var s:searchrec);
  514. var
  515. hdl : longint;
  516. w : LFNSearchRec;
  517. begin
  518. Move(s.Fill,hdl,4);
  519. dosregs.si:=1; { use ms-dos time }
  520. dosregs.edi:=tb_offset;
  521. dosregs.es:=tb_segment;
  522. dosregs.ebx:=hdl;
  523. dosregs.ax:=$714f;
  524. msdos(dosregs);
  525. LoadDosError;
  526. copyfromdos(w,sizeof(LFNSearchRec));
  527. LFNSearchRec2Dos(w,hdl,s);
  528. end;
  529. procedure LFNFindClose(var s:searchrec);
  530. var
  531. hdl : longint;
  532. begin
  533. Move(s.Fill,hdl,4);
  534. dosregs.ebx:=hdl;
  535. dosregs.ax:=$71a1;
  536. msdos(dosregs);
  537. LoadDosError;
  538. end;
  539. {******************************************************************************
  540. --- DosFindfirst DosFindNext ---
  541. ******************************************************************************}
  542. procedure dossearchrec2searchrec(var f : searchrec);
  543. var
  544. len : longint;
  545. begin
  546. { Check is necessary!! OS/2's VDM doesn't clear the name with #0 if the }
  547. { file doesn't exist! (JM) }
  548. if dosError = 0 then
  549. len:=StrLen(@f.Name)
  550. else len := 0;
  551. Move(f.Name[0],f.Name[1],Len);
  552. f.Name[0]:=chr(len);
  553. end;
  554. procedure DosFindfirst(path : pchar;attr : word;var f : searchrec);
  555. var
  556. i : longint;
  557. begin
  558. { allow slash as backslash }
  559. for i:=0 to strlen(path) do
  560. if path[i]='/' then path[i]:='\';
  561. copytodos(f,sizeof(searchrec));
  562. dosregs.edx:=tb_offset;
  563. dosregs.ds:=tb_segment;
  564. dosregs.ah:=$1a;
  565. msdos(dosregs);
  566. dosregs.ecx:=attr;
  567. dosregs.edx:=tb_offset+Sizeof(searchrec)+1;
  568. dosmemput(tb_segment,tb_offset+Sizeof(searchrec)+1,path^,strlen(path)+1);
  569. dosregs.ds:=tb_segment;
  570. dosregs.ah:=$4e;
  571. msdos(dosregs);
  572. copyfromdos(f,sizeof(searchrec));
  573. LoadDosError;
  574. dossearchrec2searchrec(f);
  575. end;
  576. procedure Dosfindnext(var f : searchrec);
  577. begin
  578. copytodos(f,sizeof(searchrec));
  579. dosregs.edx:=tb_offset;
  580. dosregs.ds:=tb_segment;
  581. dosregs.ah:=$1a;
  582. msdos(dosregs);
  583. dosregs.ah:=$4f;
  584. msdos(dosregs);
  585. copyfromdos(f,sizeof(searchrec));
  586. LoadDosError;
  587. dossearchrec2searchrec(f);
  588. end;
  589. {******************************************************************************
  590. --- Findfirst FindNext ---
  591. ******************************************************************************}
  592. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  593. var
  594. path0 : array[0..256] of char;
  595. begin
  596. doserror:=0;
  597. strpcopy(path0,path);
  598. if LFNSupport then
  599. LFNFindFirst(path0,attr,f)
  600. else
  601. Dosfindfirst(path0,attr,f);
  602. end;
  603. procedure findnext(var f : searchRec);
  604. begin
  605. doserror:=0;
  606. if LFNSupport then
  607. LFNFindnext(f)
  608. else
  609. Dosfindnext(f);
  610. end;
  611. Procedure FindClose(Var f: SearchRec);
  612. begin
  613. DosError:=0;
  614. if LFNSupport then
  615. LFNFindClose(f);
  616. end;
  617. type swap_proc = procedure;
  618. var
  619. _swap_in : swap_proc;external name '_swap_in';
  620. _swap_out : swap_proc;external name '_swap_out';
  621. _exception_exit : pointer;external name '_exception_exit';
  622. _v2prt0_exceptions_on : longbool;external name '_v2prt0_exceptions_on';
  623. procedure swapvectors;
  624. begin
  625. if _exception_exit<>nil then
  626. if _v2prt0_exceptions_on then
  627. _swap_in()
  628. else
  629. _swap_out();
  630. end;
  631. {******************************************************************************
  632. --- File ---
  633. ******************************************************************************}
  634. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;var ext : extstr);
  635. var
  636. dotpos,p1,i : longint;
  637. begin
  638. { allow slash as backslash }
  639. for i:=1 to length(path) do
  640. if path[i]='/' then path[i]:='\';
  641. { get drive name }
  642. p1:=pos(':',path);
  643. if p1>0 then
  644. begin
  645. dir:=path[1]+':';
  646. delete(path,1,p1);
  647. end
  648. else
  649. dir:='';
  650. { split the path and the name, there are no more path informtions }
  651. { if path contains no backslashes }
  652. while true do
  653. begin
  654. p1:=pos('\',path);
  655. if p1=0 then
  656. break;
  657. dir:=dir+copy(path,1,p1);
  658. delete(path,1,p1);
  659. end;
  660. { try to find out a extension }
  661. if LFNSupport then
  662. begin
  663. Ext:='';
  664. i:=Length(Path);
  665. DotPos:=256;
  666. While (i>0) Do
  667. Begin
  668. If (Path[i]='.') Then
  669. begin
  670. DotPos:=i;
  671. break;
  672. end;
  673. Dec(i);
  674. end;
  675. Ext:=Copy(Path,DotPos,255);
  676. Name:=Copy(Path,1,DotPos - 1);
  677. end
  678. else
  679. begin
  680. p1:=pos('.',path);
  681. if p1>0 then
  682. begin
  683. ext:=copy(path,p1,4);
  684. delete(path,p1,length(path)-p1+1);
  685. end
  686. else
  687. ext:='';
  688. name:=path;
  689. end;
  690. end;
  691. (*
  692. function FExpand (const Path: PathStr): PathStr;
  693. - declared in fexpand.inc
  694. *)
  695. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  696. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  697. {$I fexpand.inc}
  698. {$UNDEF FPC_FEXPAND_DRIVES}
  699. {$UNDEF FPC_FEXPAND_UNC}
  700. Function FSearch(path: pathstr; dirlist: string): pathstr;
  701. var
  702. i,p1 : longint;
  703. s : searchrec;
  704. newdir : pathstr;
  705. begin
  706. { check if the file specified exists }
  707. findfirst(path,anyfile,s);
  708. if doserror=0 then
  709. begin
  710. findclose(s);
  711. fsearch:=path;
  712. exit;
  713. end;
  714. { No wildcards allowed in these things }
  715. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  716. fsearch:=''
  717. else
  718. begin
  719. { allow slash as backslash }
  720. for i:=1 to length(dirlist) do
  721. if dirlist[i]='/' then dirlist[i]:='\';
  722. repeat
  723. p1:=pos(';',dirlist);
  724. if p1<>0 then
  725. begin
  726. newdir:=copy(dirlist,1,p1-1);
  727. delete(dirlist,1,p1);
  728. end
  729. else
  730. begin
  731. newdir:=dirlist;
  732. dirlist:='';
  733. end;
  734. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  735. newdir:=newdir+'\';
  736. findfirst(newdir+path,anyfile,s);
  737. if doserror=0 then
  738. newdir:=newdir+path
  739. else
  740. newdir:='';
  741. until (dirlist='') or (newdir<>'');
  742. fsearch:=newdir;
  743. end;
  744. findclose(s);
  745. end;
  746. { change to short filename if successful DOS call PM }
  747. function GetShortName(var p : String) : boolean;
  748. var
  749. c : array[0..255] of char;
  750. begin
  751. move(p[1],c[0],length(p));
  752. c[length(p)]:=#0;
  753. copytodos(c,length(p)+1);
  754. dosregs.ax:=$7160;
  755. dosregs.cx:=1;
  756. dosregs.ds:=tb_segment;
  757. dosregs.si:=tb_offset;
  758. dosregs.es:=tb_segment;
  759. dosregs.di:=tb_offset;
  760. msdos(dosregs);
  761. LoadDosError;
  762. if DosError=0 then
  763. begin
  764. copyfromdos(c,255);
  765. move(c[0],p[1],strlen(c));
  766. p[0]:=char(strlen(c));
  767. GetShortName:=true;
  768. end
  769. else
  770. GetShortName:=false;
  771. end;
  772. { change to long filename if successful DOS call PM }
  773. function GetLongName(var p : String) : boolean;
  774. var
  775. c : array[0..255] of char;
  776. begin
  777. move(p[1],c[0],length(p));
  778. c[length(p)]:=#0;
  779. copytodos(c,length(p)+1);
  780. dosregs.ax:=$7160;
  781. dosregs.cx:=2;
  782. dosregs.ds:=tb_segment;
  783. dosregs.si:=tb_offset;
  784. dosregs.es:=tb_segment;
  785. dosregs.di:=tb_offset;
  786. msdos(dosregs);
  787. LoadDosError;
  788. if DosError=0 then
  789. begin
  790. copyfromdos(c,255);
  791. move(c[0],p[1],strlen(c));
  792. p[0]:=char(strlen(c));
  793. GetLongName:=true;
  794. end
  795. else
  796. GetLongName:=false;
  797. end;
  798. {******************************************************************************
  799. --- Get/Set File Time,Attr ---
  800. ******************************************************************************}
  801. procedure getftime(var f;var time : longint);
  802. begin
  803. dosregs.bx:=textrec(f).handle;
  804. dosregs.ax:=$5700;
  805. msdos(dosregs);
  806. loaddoserror;
  807. time:=(dosregs.dx shl 16)+dosregs.cx;
  808. end;
  809. procedure setftime(var f;time : longint);
  810. begin
  811. dosregs.bx:=textrec(f).handle;
  812. dosregs.cx:=time and $ffff;
  813. dosregs.dx:=time shr 16;
  814. dosregs.ax:=$5701;
  815. msdos(dosregs);
  816. loaddoserror;
  817. end;
  818. procedure getfattr(var f;var attr : word);
  819. begin
  820. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  821. dosregs.edx:=tb_offset;
  822. dosregs.ds:=tb_segment;
  823. if LFNSupport then
  824. begin
  825. dosregs.ax:=$7143;
  826. dosregs.bx:=0;
  827. end
  828. else
  829. dosregs.ax:=$4300;
  830. msdos(dosregs);
  831. LoadDosError;
  832. Attr:=dosregs.cx;
  833. end;
  834. procedure setfattr(var f;attr : word);
  835. begin
  836. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  837. dosregs.edx:=tb_offset;
  838. dosregs.ds:=tb_segment;
  839. if LFNSupport then
  840. begin
  841. dosregs.ax:=$7143;
  842. dosregs.bx:=1;
  843. end
  844. else
  845. dosregs.ax:=$4301;
  846. dosregs.cx:=attr;
  847. msdos(dosregs);
  848. LoadDosError;
  849. end;
  850. {******************************************************************************
  851. --- Environment ---
  852. ******************************************************************************}
  853. function envcount : longint;
  854. var
  855. hp : ppchar;
  856. begin
  857. hp:=envp;
  858. envcount:=0;
  859. while assigned(hp^) do
  860. begin
  861. inc(envcount);
  862. inc(hp);
  863. end;
  864. end;
  865. function envstr(index : integer) : string;
  866. begin
  867. if (index<=0) or (index>envcount) then
  868. begin
  869. envstr:='';
  870. exit;
  871. end;
  872. envstr:=strpas(ppchar(pointer(envp)+4*(index-1))^);
  873. end;
  874. Function GetEnv(envvar: string): string;
  875. var
  876. hp : ppchar;
  877. hs : string;
  878. eqpos : longint;
  879. begin
  880. envvar:=upcase(envvar);
  881. hp:=envp;
  882. getenv:='';
  883. while assigned(hp^) do
  884. begin
  885. hs:=strpas(hp^);
  886. eqpos:=pos('=',hs);
  887. if upcase(copy(hs,1,eqpos-1))=envvar then
  888. begin
  889. getenv:=copy(hs,eqpos+1,255);
  890. exit;
  891. end;
  892. inc(hp);
  893. end;
  894. end;
  895. {******************************************************************************
  896. --- Not Supported ---
  897. ******************************************************************************}
  898. Procedure keep(exitcode : word);
  899. Begin
  900. End;
  901. Procedure getintvec(intno : byte;var vector : pointer);
  902. Begin
  903. End;
  904. Procedure setintvec(intno : byte;vector : pointer);
  905. Begin
  906. End;
  907. end.
  908. {
  909. $Log$
  910. Revision 1.13 2001-10-12 16:04:15 peter
  911. * fix error return in disksize (merged)
  912. Revision 1.12 2001/03/16 20:09:58 hajny
  913. * universal FExpand
  914. Revision 1.11 2000/12/16 15:27:15 peter
  915. * fixed disksize to return -1 on error
  916. Revision 1.10 2000/10/11 15:38:03 peter
  917. * diskfree doserror fix (merged)
  918. Revision 1.9 2000/09/06 20:47:34 peter
  919. * removed previous fsplit() patch as it's not the correct behaviour for
  920. LFNs. The code showing the bug could easily be adapted (merged)
  921. Revision 1.8 2000/09/04 20:17:53 peter
  922. * fixed previous commit (merged)
  923. Revision 1.7 2000/09/04 19:38:12 peter
  924. * fsplit with .. fix from Thomas (merged)
  925. Revision 1.6 2000/08/04 21:45:39 peter
  926. * getenv case insensitive (merged)
  927. Revision 1.4 2000/07/22 12:24:55 jonas
  928. * merged dossearchrec2searchrec() fix from fixes branch
  929. Revision 1.3 2000/07/14 10:33:09 michael
  930. + Conditionals fixed
  931. Revision 1.2 2000/07/13 11:33:39 michael
  932. + removed logs
  933. }