dos.pp 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157
  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 carryflag) <> 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 Free then
  417. Do_DiskData:=int64(rec.AvailAllocUnits)*rec.SecPerClus*rec.BytePerSec
  418. else
  419. Do_DiskData:=int64(rec.TotalAllocUnits)*rec.SecPerClus*rec.BytePerSec;
  420. if doserror<>0 THEN {No error clausule in int except cf}
  421. Do_DiskData:=-1;
  422. end
  423. else
  424. begin
  425. dosregs.dl:=drive;
  426. dosregs.ah:=$36;
  427. msdos(dosregs);
  428. if dosregs.ax<>$FFFF then
  429. begin
  430. if Free then
  431. Do_DiskData:=int64(dosregs.ax)*dosregs.bx*dosregs.cx
  432. else
  433. Do_DiskData:=int64(dosregs.ax)*dosregs.cx*dosregs.dx;
  434. end
  435. else
  436. do_diskdata:=-1;
  437. end;
  438. end;
  439. function diskfree(drive : byte) : int64;
  440. begin
  441. diskfree:=Do_DiskData(drive,TRUE);
  442. end;
  443. function disksize(drive : byte) : int64;
  444. begin
  445. disksize:=Do_DiskData(drive,false);
  446. end;
  447. {******************************************************************************
  448. --- LFNFindfirst LFNFindNext ---
  449. ******************************************************************************}
  450. type
  451. LFNSearchRec=packed record
  452. attr,
  453. crtime,
  454. crtimehi,
  455. actime,
  456. actimehi,
  457. lmtime,
  458. lmtimehi,
  459. sizehi,
  460. size : longint;
  461. reserved : array[0..7] of byte;
  462. name : array[0..259] of byte;
  463. shortname : array[0..13] of byte;
  464. end;
  465. procedure LFNSearchRec2Dos(const w:LFNSearchRec;hdl:longint;var d:Searchrec);
  466. var
  467. Len : longint;
  468. begin
  469. With w do
  470. begin
  471. FillChar(d,sizeof(SearchRec),0);
  472. if DosError=0 then
  473. len:=StrLen(@Name)
  474. else
  475. len:=0;
  476. d.Name[0]:=chr(len);
  477. Move(Name[0],d.Name[1],Len);
  478. d.Time:=lmTime;
  479. d.Size:=Size;
  480. d.Attr:=Attr and $FF;
  481. Move(hdl,d.Fill,4);
  482. end;
  483. end;
  484. procedure LFNFindFirst(path:pchar;attr:longint;var s:searchrec);
  485. var
  486. i : longint;
  487. w : LFNSearchRec;
  488. begin
  489. { allow slash as backslash }
  490. for i:=0 to strlen(path) do
  491. if path[i]='/' then path[i]:='\';
  492. dosregs.si:=1; { use ms-dos time }
  493. { don't include the label if not asked for it, needed for network drives }
  494. if attr=$8 then
  495. dosregs.ecx:=8
  496. else
  497. dosregs.ecx:=attr and (not 8);
  498. dosregs.edx:=tb_offset+Sizeof(LFNSearchrec)+1;
  499. dosmemput(tb_segment,tb_offset+Sizeof(LFNSearchrec)+1,path^,strlen(path)+1);
  500. dosregs.ds:=tb_segment;
  501. dosregs.edi:=tb_offset;
  502. dosregs.es:=tb_segment;
  503. dosregs.ax:=$714e;
  504. msdos(dosregs);
  505. LoadDosError;
  506. copyfromdos(w,sizeof(LFNSearchRec));
  507. LFNSearchRec2Dos(w,dosregs.ax,s);
  508. end;
  509. procedure LFNFindNext(var s:searchrec);
  510. var
  511. hdl : longint;
  512. w : LFNSearchRec;
  513. begin
  514. Move(s.Fill,hdl,4);
  515. dosregs.si:=1; { use ms-dos time }
  516. dosregs.edi:=tb_offset;
  517. dosregs.es:=tb_segment;
  518. dosregs.ebx:=hdl;
  519. dosregs.ax:=$714f;
  520. msdos(dosregs);
  521. LoadDosError;
  522. copyfromdos(w,sizeof(LFNSearchRec));
  523. LFNSearchRec2Dos(w,hdl,s);
  524. end;
  525. procedure LFNFindClose(var s:searchrec);
  526. var
  527. hdl : longint;
  528. begin
  529. Move(s.Fill,hdl,4);
  530. dosregs.ebx:=hdl;
  531. dosregs.ax:=$71a1;
  532. msdos(dosregs);
  533. LoadDosError;
  534. end;
  535. {******************************************************************************
  536. --- DosFindfirst DosFindNext ---
  537. ******************************************************************************}
  538. procedure dossearchrec2searchrec(var f : searchrec);
  539. var
  540. len : longint;
  541. begin
  542. { Check is necessary!! OS/2's VDM doesn't clear the name with #0 if the }
  543. { file doesn't exist! (JM) }
  544. if dosError = 0 then
  545. len:=StrLen(@f.Name)
  546. else len := 0;
  547. Move(f.Name[0],f.Name[1],Len);
  548. f.Name[0]:=chr(len);
  549. end;
  550. procedure DosFindfirst(path : pchar;attr : word;var f : searchrec);
  551. var
  552. i : longint;
  553. begin
  554. { allow slash as backslash }
  555. for i:=0 to strlen(path) do
  556. if path[i]='/' then path[i]:='\';
  557. copytodos(f,sizeof(searchrec));
  558. dosregs.edx:=tb_offset;
  559. dosregs.ds:=tb_segment;
  560. dosregs.ah:=$1a;
  561. msdos(dosregs);
  562. dosregs.ecx:=attr;
  563. dosregs.edx:=tb_offset+Sizeof(searchrec)+1;
  564. dosmemput(tb_segment,tb_offset+Sizeof(searchrec)+1,path^,strlen(path)+1);
  565. dosregs.ds:=tb_segment;
  566. dosregs.ah:=$4e;
  567. msdos(dosregs);
  568. copyfromdos(f,sizeof(searchrec));
  569. LoadDosError;
  570. dossearchrec2searchrec(f);
  571. end;
  572. procedure Dosfindnext(var f : searchrec);
  573. begin
  574. copytodos(f,sizeof(searchrec));
  575. dosregs.edx:=tb_offset;
  576. dosregs.ds:=tb_segment;
  577. dosregs.ah:=$1a;
  578. msdos(dosregs);
  579. dosregs.ah:=$4f;
  580. msdos(dosregs);
  581. copyfromdos(f,sizeof(searchrec));
  582. LoadDosError;
  583. dossearchrec2searchrec(f);
  584. end;
  585. {******************************************************************************
  586. --- Findfirst FindNext ---
  587. ******************************************************************************}
  588. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  589. var
  590. path0 : array[0..256] of char;
  591. begin
  592. doserror:=0;
  593. strpcopy(path0,path);
  594. if LFNSupport then
  595. LFNFindFirst(path0,attr,f)
  596. else
  597. Dosfindfirst(path0,attr,f);
  598. end;
  599. procedure findnext(var f : searchRec);
  600. begin
  601. doserror:=0;
  602. if LFNSupport then
  603. LFNFindnext(f)
  604. else
  605. Dosfindnext(f);
  606. end;
  607. Procedure FindClose(Var f: SearchRec);
  608. begin
  609. DosError:=0;
  610. if LFNSupport then
  611. LFNFindClose(f);
  612. end;
  613. type swap_proc = procedure;
  614. var
  615. _swap_in : swap_proc;external name '_swap_in';
  616. _swap_out : swap_proc;external name '_swap_out';
  617. _exception_exit : pointer;external name '_exception_exit';
  618. _v2prt0_exceptions_on : longbool;external name '_v2prt0_exceptions_on';
  619. procedure swapvectors;
  620. begin
  621. if _exception_exit<>nil then
  622. if _v2prt0_exceptions_on then
  623. _swap_in()
  624. else
  625. _swap_out();
  626. end;
  627. {******************************************************************************
  628. --- File ---
  629. ******************************************************************************}
  630. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;var ext : extstr);
  631. var
  632. dotpos,p1,i : longint;
  633. begin
  634. { allow slash as backslash }
  635. for i:=1 to length(path) do
  636. if path[i]='/' then path[i]:='\';
  637. { get drive name }
  638. p1:=pos(':',path);
  639. if p1>0 then
  640. begin
  641. dir:=path[1]+':';
  642. delete(path,1,p1);
  643. end
  644. else
  645. dir:='';
  646. { split the path and the name, there are no more path informtions }
  647. { if path contains no backslashes }
  648. while true do
  649. begin
  650. p1:=pos('\',path);
  651. if p1=0 then
  652. break;
  653. dir:=dir+copy(path,1,p1);
  654. delete(path,1,p1);
  655. end;
  656. { try to find out a extension }
  657. if LFNSupport then
  658. begin
  659. Ext:='';
  660. i:=Length(Path);
  661. DotPos:=256;
  662. While (i>0) Do
  663. Begin
  664. If (Path[i]='.') Then
  665. begin
  666. while (i>1) and (Path[i-1]='.') do
  667. dec(i);
  668. DotPos:=i;
  669. break;
  670. end;
  671. Dec(i);
  672. end;
  673. Ext:=Copy(Path,DotPos,255);
  674. Name:=Copy(Path,1,DotPos - 1);
  675. end
  676. else
  677. begin
  678. p1:=pos('.',path);
  679. if p1>0 then
  680. begin
  681. ext:=copy(path,p1,4);
  682. delete(path,p1,length(path)-p1+1);
  683. end
  684. else
  685. ext:='';
  686. name:=path;
  687. end;
  688. end;
  689. function fexpand(const path : pathstr) : pathstr;
  690. var
  691. s,pa : pathstr;
  692. i,j : longint;
  693. begin
  694. getdir(0,s);
  695. i:=ioresult;
  696. if LFNSupport then
  697. begin
  698. pa:=path;
  699. end
  700. else
  701. if FileNameCaseSensitive then
  702. pa:=path
  703. else
  704. pa:=upcase(path);
  705. { allow slash as backslash }
  706. for i:=1 to length(pa) do
  707. if pa[i]='/' then
  708. pa[i]:='\';
  709. if (length(pa)>1) and (pa[2]=':') and (pa[1] in ['A'..'Z','a'..'z']) then
  710. begin
  711. { Always uppercase driveletter }
  712. if (pa[1] in ['a'..'z']) then
  713. pa[1]:=Chr(Ord(Pa[1])-32);
  714. { we must get the right directory }
  715. getdir(ord(pa[1])-ord('A')+1,s);
  716. i:=ioresult;
  717. if (ord(pa[0])>2) and (pa[3]<>'\') then
  718. if pa[1]=s[1] then
  719. begin
  720. { remove ending slash if it already exists }
  721. if s[length(s)]='\' then
  722. dec(s[0]);
  723. pa:=s+'\'+copy (pa,3,length(pa));
  724. end
  725. else
  726. pa:=pa[1]+':\'+copy (pa,3,length(pa))
  727. end
  728. else
  729. if pa[1]='\' then
  730. begin
  731. { Do not touch Network drive names if LFNSupport is true }
  732. if not ((Length(pa)>1) and (pa[2]='\') and LFNSupport) then
  733. pa:=s[1]+':'+pa;
  734. end
  735. else if s[0]=#3 then
  736. pa:=s+pa
  737. else
  738. pa:=s+'\'+pa;
  739. { Turbo Pascal gives current dir on drive if only drive given as parameter! }
  740. if length(pa) = 2 then
  741. begin
  742. getdir(byte(pa[1])-64,s);
  743. pa := s;
  744. end;
  745. {First remove all references to '\.\'}
  746. while pos ('\.\',pa)<>0 do
  747. delete (pa,pos('\.\',pa),2);
  748. {Now remove also all references to '\..\' + of course previous dirs..}
  749. repeat
  750. i:=pos('\..\',pa);
  751. if i<>0 then
  752. begin
  753. j:=i-1;
  754. while (j>1) and (pa[j]<>'\') do
  755. dec (j);
  756. if pa[j+1] = ':' then j := 3;
  757. delete (pa,j,i-j+3);
  758. end;
  759. until i=0;
  760. { Turbo Pascal gets rid of a \.. at the end of the path }
  761. { Now remove also any reference to '\..' at end of line
  762. + of course previous dir.. }
  763. i:=pos('\..',pa);
  764. if i<>0 then
  765. begin
  766. if i = length(pa) - 2 then
  767. begin
  768. j:=i-1;
  769. while (j>1) and (pa[j]<>'\') do
  770. dec (j);
  771. delete (pa,j,i-j+3);
  772. end;
  773. pa := pa + '\';
  774. end;
  775. { Remove End . and \}
  776. if (length(pa)>0) and (pa[length(pa)]='.') then
  777. dec(byte(pa[0]));
  778. { if only the drive + a '\' is left then the '\' should be left to prevtn the program
  779. accessing the current directory on the drive rather than the root!}
  780. { if the last char of path = '\' then leave it in as this is what TP does! }
  781. if ((length(pa)>3) and (pa[length(pa)]='\')) and (path[length(path)] <> '\') then
  782. dec(byte(pa[0]));
  783. { if only a drive is given in path then there should be a '\' at the
  784. end of the string given back }
  785. if length(pa) = 2 then pa := pa + '\';
  786. fexpand:=pa;
  787. end;
  788. Function FSearch(path: pathstr; dirlist: string): pathstr;
  789. var
  790. i,p1 : longint;
  791. s : searchrec;
  792. newdir : pathstr;
  793. begin
  794. { check if the file specified exists }
  795. findfirst(path,anyfile,s);
  796. if doserror=0 then
  797. begin
  798. findclose(s);
  799. fsearch:=path;
  800. exit;
  801. end;
  802. { No wildcards allowed in these things }
  803. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  804. fsearch:=''
  805. else
  806. begin
  807. { allow slash as backslash }
  808. for i:=1 to length(dirlist) do
  809. if dirlist[i]='/' then dirlist[i]:='\';
  810. repeat
  811. p1:=pos(';',dirlist);
  812. if p1<>0 then
  813. begin
  814. newdir:=copy(dirlist,1,p1-1);
  815. delete(dirlist,1,p1);
  816. end
  817. else
  818. begin
  819. newdir:=dirlist;
  820. dirlist:='';
  821. end;
  822. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  823. newdir:=newdir+'\';
  824. findfirst(newdir+path,anyfile,s);
  825. if doserror=0 then
  826. newdir:=newdir+path
  827. else
  828. newdir:='';
  829. until (dirlist='') or (newdir<>'');
  830. fsearch:=newdir;
  831. end;
  832. findclose(s);
  833. end;
  834. { change to short filename if successful DOS call PM }
  835. function GetShortName(var p : String) : boolean;
  836. var
  837. c : array[0..255] of char;
  838. begin
  839. move(p[1],c[0],length(p));
  840. c[length(p)]:=#0;
  841. copytodos(c,length(p)+1);
  842. dosregs.ax:=$7160;
  843. dosregs.cx:=1;
  844. dosregs.ds:=tb_segment;
  845. dosregs.si:=tb_offset;
  846. dosregs.es:=tb_segment;
  847. dosregs.di:=tb_offset;
  848. msdos(dosregs);
  849. LoadDosError;
  850. if DosError=0 then
  851. begin
  852. copyfromdos(c,255);
  853. move(c[0],p[1],strlen(c));
  854. p[0]:=char(strlen(c));
  855. GetShortName:=true;
  856. end
  857. else
  858. GetShortName:=false;
  859. end;
  860. { change to long filename if successful DOS call PM }
  861. function GetLongName(var p : String) : boolean;
  862. var
  863. c : array[0..255] of char;
  864. begin
  865. move(p[1],c[0],length(p));
  866. c[length(p)]:=#0;
  867. copytodos(c,length(p)+1);
  868. dosregs.ax:=$7160;
  869. dosregs.cx:=2;
  870. dosregs.ds:=tb_segment;
  871. dosregs.si:=tb_offset;
  872. dosregs.es:=tb_segment;
  873. dosregs.di:=tb_offset;
  874. msdos(dosregs);
  875. LoadDosError;
  876. if DosError=0 then
  877. begin
  878. copyfromdos(c,255);
  879. move(c[0],p[1],strlen(c));
  880. p[0]:=char(strlen(c));
  881. GetLongName:=true;
  882. end
  883. else
  884. GetLongName:=false;
  885. end;
  886. {******************************************************************************
  887. --- Get/Set File Time,Attr ---
  888. ******************************************************************************}
  889. procedure getftime(var f;var time : longint);
  890. begin
  891. dosregs.bx:=textrec(f).handle;
  892. dosregs.ax:=$5700;
  893. msdos(dosregs);
  894. loaddoserror;
  895. time:=(dosregs.dx shl 16)+dosregs.cx;
  896. end;
  897. procedure setftime(var f;time : longint);
  898. begin
  899. dosregs.bx:=textrec(f).handle;
  900. dosregs.cx:=time and $ffff;
  901. dosregs.dx:=time shr 16;
  902. dosregs.ax:=$5701;
  903. msdos(dosregs);
  904. loaddoserror;
  905. end;
  906. procedure getfattr(var f;var attr : word);
  907. begin
  908. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  909. dosregs.edx:=tb_offset;
  910. dosregs.ds:=tb_segment;
  911. if LFNSupport then
  912. begin
  913. dosregs.ax:=$7143;
  914. dosregs.bx:=0;
  915. end
  916. else
  917. dosregs.ax:=$4300;
  918. msdos(dosregs);
  919. LoadDosError;
  920. Attr:=dosregs.cx;
  921. end;
  922. procedure setfattr(var f;attr : word);
  923. begin
  924. copytodos(filerec(f).name,strlen(filerec(f).name)+1);
  925. dosregs.edx:=tb_offset;
  926. dosregs.ds:=tb_segment;
  927. if LFNSupport then
  928. begin
  929. dosregs.ax:=$7143;
  930. dosregs.bx:=1;
  931. end
  932. else
  933. dosregs.ax:=$4301;
  934. dosregs.cx:=attr;
  935. msdos(dosregs);
  936. LoadDosError;
  937. end;
  938. {******************************************************************************
  939. --- Environment ---
  940. ******************************************************************************}
  941. function envcount : longint;
  942. var
  943. hp : ppchar;
  944. begin
  945. hp:=envp;
  946. envcount:=0;
  947. while assigned(hp^) do
  948. begin
  949. inc(envcount);
  950. inc(hp);
  951. end;
  952. end;
  953. function envstr(index : integer) : string;
  954. begin
  955. if (index<=0) or (index>envcount) then
  956. begin
  957. envstr:='';
  958. exit;
  959. end;
  960. envstr:=strpas(ppchar(pointer(envp)+4*(index-1))^);
  961. end;
  962. Function GetEnv(envvar: string): string;
  963. var
  964. hp : ppchar;
  965. hs : string;
  966. eqpos : longint;
  967. begin
  968. envvar:=upcase(envvar);
  969. hp:=envp;
  970. getenv:='';
  971. while assigned(hp^) do
  972. begin
  973. hs:=strpas(hp^);
  974. eqpos:=pos('=',hs);
  975. if upcase(copy(hs,1,eqpos-1))=envvar then
  976. begin
  977. getenv:=copy(hs,eqpos+1,255);
  978. exit;
  979. end;
  980. inc(hp);
  981. end;
  982. end;
  983. {******************************************************************************
  984. --- Not Supported ---
  985. ******************************************************************************}
  986. Procedure keep(exitcode : word);
  987. Begin
  988. End;
  989. Procedure getintvec(intno : byte;var vector : pointer);
  990. Begin
  991. End;
  992. Procedure setintvec(intno : byte;vector : pointer);
  993. Begin
  994. End;
  995. end.
  996. {
  997. $Log$
  998. Revision 1.8 2000-09-04 20:17:53 peter
  999. * fixed previous commit (merged)
  1000. Revision 1.7 2000/09/04 19:38:12 peter
  1001. * fsplit with .. fix from Thomas (merged)
  1002. Revision 1.6 2000/08/04 21:45:39 peter
  1003. * getenv case insensitive (merged)
  1004. Revision 1.4 2000/07/22 12:24:55 jonas
  1005. * merged dossearchrec2searchrec() fix from fixes branch
  1006. Revision 1.3 2000/07/14 10:33:09 michael
  1007. + Conditionals fixed
  1008. Revision 1.2 2000/07/13 11:33:39 michael
  1009. + removed logs
  1010. }