dos.pas 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216
  1. {****************************************************************************
  2. $Id$
  3. Free Pascal Runtime-Library
  4. DOS unit for OS/2
  5. Copyright (c) 1997,1999-2000 by Daniel Mantione,
  6. member of the Free Pascal development team
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. ****************************************************************************}
  13. unit dos;
  14. {$ASMMODE ATT}
  15. {***************************************************************************}
  16. interface
  17. {***************************************************************************}
  18. {$PACKRECORDS 1}
  19. uses strings;
  20. const {Bit masks for CPU flags.}
  21. fcarry = $0001;
  22. fparity = $0004;
  23. fauxiliary = $0010;
  24. fzero = $0040;
  25. fsign = $0080;
  26. foverflow = $0800;
  27. {Bit masks for file attributes.}
  28. readonly = $01;
  29. hidden = $02;
  30. sysfile = $04;
  31. volumeid = $08;
  32. directory = $10;
  33. archive = $20;
  34. anyfile = $3F;
  35. fmclosed = $D7B0;
  36. fminput = $D7B1;
  37. fmoutput = $D7B2;
  38. fminout = $D7B3;
  39. type {Some string types:}
  40. comstr=string; {Filenames can be long in OS/2.}
  41. pathstr=string; {String for pathnames.}
  42. dirstr=string; {String for a directory}
  43. namestr=string; {String for a filename.}
  44. extstr=string[40]; {String for an extension. Can be 253
  45. characters long, in theory, but let's
  46. say fourty will be enough.}
  47. {Search record which is used by findfirst and findnext:}
  48. searchrec=record
  49. case boolean of
  50. false: (handle:longint; {Used in os_OS2 mode}
  51. fill2:array[1..21-SizeOf(longint)] of byte;
  52. attr2:byte;
  53. time2:longint;
  54. size2:longint;
  55. name2:string); {Filenames can be long in OS/2!}
  56. true: (fill:array[1..21] of byte;
  57. attr:byte;
  58. time:longint;
  59. size:longint;
  60. name:string); {Filenames can be long in OS/2!}
  61. end;
  62. {$i filerec.inc}
  63. {$i textrec.inc}
  64. {Data structure for the registers needed by msdos and intr:}
  65. registers=record
  66. case i:integer of
  67. 0:(ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si,f51,di,f6,ds,f7,es,
  68. f8,flags,fs,gs:word);
  69. 1:(al,ah,f9,f10,bl,bh,f11,f12,cl,ch,f13,f14,dl,dh:byte);
  70. 2:(eax,ebx,ecx,edx,ebp,esi,edi:longint);
  71. end;
  72. {Record for date and time:}
  73. datetime=record
  74. year,month,day,hour,min,sec:word;
  75. end;
  76. {Flags for the exec procedure:
  77. Starting the program:
  78. efwait: Wait until program terminates.
  79. efno_wait: Don't wait until the program terminates. Does not work
  80. in dos, as DOS cannot multitask.
  81. efoverlay: Terminate this program, then execute the requested
  82. program. WARNING: Exit-procedures are not called!
  83. efdebug: Debug program. Details are unknown.
  84. efsession: Do not execute as child of this program. Use a seperate
  85. session instead.
  86. efdetach: Detached. Function unknown. Info wanted!
  87. efpm: Run as presentation manager program.
  88. Determining the window state of the program:
  89. efdefault: Run the pm program in it's default situation.
  90. efminimize: Run the pm program minimized.
  91. efmaximize: Run the pm program maximized.
  92. effullscreen: Run the non-pm program fullscreen.
  93. efwindowed: Run the non-pm program in a window.
  94. Other options are not implemented defined because lack of
  95. knowledge about what they do.}
  96. type execrunflags=(efwait,efno_wait,efoverlay,efdebug,efsession,
  97. efdetach,efpm);
  98. execwinflags=(efdefault,efminimize,efmaximize,effullscreen,
  99. efwindowed);
  100. const
  101. (* For compatibility with VP/2, used for runflags in Exec procedure. *)
  102. ExecFlags: cardinal = ord (efwait);
  103. var doserror:integer;
  104. dosexitcode:word;
  105. procedure getdate(var year,month,day,dayofweek:word);
  106. procedure gettime(var hour,minute,second,sec100:word);
  107. function dosversion:word;
  108. procedure setdate(year,month,day:word);
  109. procedure settime(hour,minute,second,sec100:word);
  110. procedure getcbreak(var breakvalue:boolean);
  111. procedure setcbreak(breakvalue:boolean);
  112. procedure getverify(var verify:boolean);
  113. procedure setverify(verify : boolean);
  114. {$IFDEF INT64}
  115. function DiskFree (Drive: byte) : int64;
  116. function DiskSize (Drive: byte) : int64;
  117. {$ELSE}
  118. function DiskFree (Drive: byte) : longint;
  119. function DiskSize (Drive: byte) : longint;
  120. {$ENDIF}
  121. procedure findfirst(const path:pathstr;attr:word;var f:searchRec);
  122. procedure findnext(var f:searchRec);
  123. procedure findclose(var f:searchRec);
  124. {Is a dummy:}
  125. procedure swapvectors;
  126. {Not supported:
  127. procedure getintvec(intno:byte;var vector:pointer);
  128. procedure setintvec(intno:byte;vector:pointer);
  129. procedure keep(exitcode:word);
  130. }
  131. procedure msdos(var regs:registers);
  132. procedure intr(intno : byte;var regs:registers);
  133. procedure getfattr(var f;var attr:word);
  134. procedure setfattr(var f;attr:word);
  135. function fsearch(path:pathstr;dirlist:string):pathstr;
  136. procedure getftime(var f;var time:longint);
  137. procedure setftime(var f;time:longint);
  138. procedure packtime (var d:datetime; var time:longint);
  139. procedure unpacktime (time:longint; var d:datetime);
  140. function fexpand(const path:pathstr):pathstr;
  141. procedure fsplit(path:pathstr;var dir:dirstr;var name:namestr;
  142. var ext:extstr);
  143. procedure exec(const path:pathstr;const comline:comstr);
  144. function exec(path:pathstr;runflags:execrunflags;winflags:execwinflags;
  145. const comline:comstr):longint;
  146. function envcount:longint;
  147. function envstr(index:longint) : string;
  148. function getenv(const envvar:string): string;
  149. implementation
  150. uses DosCalls;
  151. var LastSR: SearchRec;
  152. type TBA = array [1..SizeOf (SearchRec)] of byte;
  153. PBA = ^TBA;
  154. {Import syscall to call it nicely from assembler procedures.}
  155. procedure syscall;external name '___SYSCALL';
  156. function fsearch(path:pathstr;dirlist:string):pathstr;
  157. var i,p1:longint;
  158. newdir:pathstr;
  159. {$ASMMODE INTEL}
  160. function CheckFile (FN: ShortString):boolean; assembler;
  161. asm
  162. mov ax, 4300h
  163. mov edx, FN
  164. inc edx
  165. call syscall
  166. mov ax, 0
  167. jc @LCFstop
  168. test cx, 18h
  169. jnz @LCFstop
  170. inc ax
  171. @LCFstop:
  172. end;
  173. {$ASMMODE ATT}
  174. begin
  175. { check if the file specified exists }
  176. if CheckFile (Path + #0) then
  177. FSearch := Path
  178. else
  179. begin
  180. {No wildcards allowed in these things:}
  181. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  182. fsearch:=''
  183. else
  184. begin
  185. { allow slash as backslash }
  186. for i:=1 to length(dirlist) do
  187. if dirlist[i]='/' then dirlist[i]:='\';
  188. repeat
  189. p1:=pos(';',dirlist);
  190. if p1<>0 then
  191. begin
  192. newdir:=copy(dirlist,1,p1-1);
  193. delete(dirlist,1,p1);
  194. end
  195. else
  196. begin
  197. newdir:=dirlist;
  198. dirlist:='';
  199. end;
  200. if (newdir<>'') and
  201. not (newdir[length(newdir)] in ['\',':']) then
  202. newdir:=newdir+'\';
  203. if CheckFile (NewDir + Path + #0) then
  204. NewDir := NewDir + Path
  205. else
  206. NewDir := '';
  207. until (DirList = '') or (NewDir <> '');
  208. FSearch := NewDir;
  209. end;
  210. end;
  211. end;
  212. procedure getftime(var f;var time:longint);
  213. begin
  214. asm
  215. {Load handle}
  216. movl f,%ebx
  217. movw (%ebx),%bx
  218. {Get date}
  219. movw $0x5700,%ax
  220. call syscall
  221. shll $16,%edx
  222. movw %cx,%dx
  223. movl time,%ebx
  224. movl %edx,(%ebx)
  225. xorb %ah,%ah
  226. movw %ax,doserror
  227. end;
  228. end;
  229. procedure setftime(var f;time : longint);
  230. begin
  231. asm
  232. {Load handle}
  233. movl f,%ebx
  234. movw (%ebx),%bx
  235. movl time,%ecx
  236. shldl $16,%ecx,%edx
  237. {Set date}
  238. movw $0x5701,%ax
  239. call syscall
  240. xorb %ah,%ah
  241. movw %ax,doserror
  242. end;
  243. end;
  244. procedure msdos(var regs:registers);
  245. {Not recommended for EMX. Only works in DOS mode, not in OS/2 mode.}
  246. begin
  247. intr($21,regs);
  248. end;
  249. {$ASMMODE DIRECT}
  250. procedure intr(intno:byte;var regs:registers);
  251. {Not recommended for EMX. Only works in DOS mode, not in OS/2 mode.}
  252. begin
  253. asm
  254. .data
  255. int86:
  256. .byte 0xcd
  257. int86_vec:
  258. .byte 0x03
  259. jmp int86_retjmp
  260. .text
  261. movl 8(%ebp),%eax
  262. movb %al,int86_vec
  263. movl 10(%ebp),%eax
  264. {Do not use first int}
  265. incl %eax
  266. incl %eax
  267. movl 4(%eax),%ebx
  268. movl 8(%eax),%ecx
  269. movl 12(%eax),%edx
  270. movl 16(%eax),%ebp
  271. movl 20(%eax),%esi
  272. movl 24(%eax),%edi
  273. movl (%eax),%eax
  274. jmp int86
  275. int86_retjmp:
  276. pushf
  277. pushl %ebp
  278. pushl %eax
  279. movl %esp,%ebp
  280. {Calc EBP new}
  281. addl $12,%ebp
  282. movl 10(%ebp),%eax
  283. {Do not use first int}
  284. incl %eax
  285. incl %eax
  286. popl (%eax)
  287. movl %ebx,4(%eax)
  288. movl %ecx,8(%eax)
  289. movl %edx,12(%eax)
  290. {Restore EBP}
  291. popl %edx
  292. movl %edx,16(%eax)
  293. movl %esi,20(%eax)
  294. movl %edi,24(%eax)
  295. {Ignore ES and DS}
  296. popl %ebx {Flags.}
  297. movl %ebx,32(%eax)
  298. {FS and GS too}
  299. end;
  300. end;
  301. {$ASMMODE ATT}
  302. procedure exec(const path:pathstr;const comline:comstr);
  303. {Execute a program.}
  304. begin
  305. dosexitcode:=exec(path,execrunflags(ExecFlags),efdefault,comline);
  306. end;
  307. function exec(path:pathstr;runflags:execrunflags;winflags:execwinflags;
  308. const comline:comstr):longint;
  309. {Execute a program. More suitable for OS/2 than the exec above.}
  310. {512 bytes should be enough to contain the command-line.}
  311. type bytearray=array[0..8191] of byte;
  312. Pbytearray=^bytearray;
  313. execstruc=record
  314. argofs,envofs,nameofs:pointer;
  315. argseg,envseg,nameseg:word;
  316. numarg,sizearg,
  317. numenv,sizeenv:word;
  318. mode1,mode2:byte;
  319. end;
  320. var args:Pbytearray;
  321. env:Pbytearray;
  322. i,j:word;
  323. es:execstruc;
  324. esadr:pointer;
  325. d:dirstr;
  326. n:namestr;
  327. e:extstr;
  328. begin
  329. getmem(args,512);
  330. getmem(env,8192);
  331. j:=1;
  332. {Now setup the arguments. The first argument should be the program
  333. name without directory and extension.}
  334. fsplit(path,d,n,e);
  335. es.numarg:=1;
  336. args^[0]:=$80;
  337. for i:=1 to length(n) do
  338. begin
  339. args^[j]:=byte(n[i]);
  340. inc(j);
  341. end;
  342. args^[j]:=0;
  343. inc(j);
  344. {Now do the real arguments.}
  345. i:=1;
  346. while i<=length(comline) do
  347. begin
  348. if comline[i]<>' ' then
  349. begin
  350. {Commandline argument found. Copy it.}
  351. inc(es.numarg);
  352. args^[j]:=$80;
  353. inc(j);
  354. while (i<=length(comline)) and (comline[i]<>' ') do
  355. begin
  356. args^[j]:=byte(comline[i]);
  357. inc(j);
  358. inc(i);
  359. end;
  360. args^[j]:=0;
  361. inc(j);
  362. end;
  363. inc(i);
  364. end;
  365. args^[j]:=0;
  366. inc(j);
  367. {Commandline ready, now build the environment.
  368. Oh boy, I always had the opinion that executing a program under Dos
  369. was a hard job!}
  370. {$ASMMODE DIRECT}
  371. asm
  372. movl env,%edi {Setup destination pointer.}
  373. movl _envc,%ecx {Load number of arguments in edx.}
  374. movl _environ,%esi {Load env. strings.}
  375. xorl %edx,%edx {Count environment size.}
  376. exa1:
  377. lodsl {Load a Pchar.}
  378. xchgl %eax,%ebx
  379. exa2:
  380. movb (%ebx),%al {Load a byte.}
  381. incl %ebx {Point to next byte.}
  382. stosb {Store it.}
  383. incl %edx {Increase counter.}
  384. cmpb $0,%al {Ready ?.}
  385. jne exa2
  386. loop exa1 {Next argument.}
  387. stosb {Store an extra 0 to finish. (AL is now 0).}
  388. incl %edx
  389. movl %edx,(24)es {Store environment size.}
  390. end;
  391. {$ASMMODE ATT}
  392. {Environtment ready, now set-up exec structure.}
  393. es.argofs:=args;
  394. es.envofs:=env;
  395. asm
  396. leal path,%esi
  397. lodsb
  398. movzbl %al,%eax
  399. addl %eax,%esi
  400. movb $0,(%esi)
  401. end;
  402. es.nameofs:=pointer(longint(@path)+1);
  403. asm
  404. movw %ss,es.argseg
  405. movw %ss,es.envseg
  406. movw %ss,es.nameseg
  407. end;
  408. es.sizearg:=j;
  409. es.numenv:=0;
  410. {Typecasting of sets in FPC is a bit hard.}
  411. es.mode1:=byte(runflags);
  412. es.mode2:=byte(winflags);
  413. {Now exec the program.}
  414. asm
  415. leal es,%edx
  416. mov $0x7f06,%ax
  417. call syscall
  418. xorl %edi,%edi
  419. jnc .Lexprg1
  420. xchgl %eax,%edi
  421. xorl %eax,%eax
  422. decl %eax
  423. .Lexprg1:
  424. movw %di,doserror
  425. movl %eax,__RESULT
  426. end;
  427. freemem(args,512);
  428. freemem(env,8192);
  429. {Phew! That's it. This was the most sophisticated procedure to call
  430. a system function I ever wrote!}
  431. end;
  432. function dosversion:word;assembler;
  433. {Returns DOS version in DOS and OS/2 version in OS/2}
  434. asm
  435. movb $0x30,%ah
  436. call syscall
  437. end;
  438. procedure getdate(var year,month,day,dayofweek:word);
  439. begin
  440. asm
  441. movb $0x2a,%ah
  442. call syscall
  443. xorb %ah,%ah
  444. movl 20(%ebp),%edi
  445. stosw
  446. movl 16(%ebp),%edi
  447. movb %dl,%al
  448. stosw
  449. movl 12(%ebp),%edi
  450. movb %dh,%al
  451. stosw
  452. movl 8(%ebp),%edi
  453. xchgw %ecx,%eax
  454. stosw
  455. end;
  456. end;
  457. procedure setdate(year,month,day : word);
  458. begin
  459. {DOS only! You cannot change the system date in OS/2!}
  460. asm
  461. movw 8(%ebp),%cx
  462. movb 10(%ebp),%dh
  463. movb 12(%ebp),%dl
  464. movb $0x2b,%ah
  465. call syscall
  466. (* SetDate isn't supposed to change DosError!!!
  467. xorb %ah,%ah
  468. movw %ax,doserror
  469. *)
  470. end;
  471. end;
  472. procedure gettime(var hour,minute,second,sec100:word);
  473. begin
  474. asm
  475. movb $0x2c,%ah
  476. call syscall
  477. xorb %ah,%ah
  478. movl 20(%ebp),%edi
  479. movb %dl,%al
  480. stosw
  481. movl 16(%ebp),%edi
  482. movb %dh,%al
  483. stosw
  484. movl 12(%ebp),%edi
  485. movb %cl,%al
  486. stosw
  487. movl 8(%ebp),%edi
  488. movb %ch,%al
  489. stosw
  490. end;
  491. end;
  492. procedure settime(hour,minute,second,sec100:word);
  493. (* TODO: Syscall 58h (__settime) should be used instead!!! *)
  494. begin
  495. asm
  496. movb 8(%ebp),%ch
  497. movb 10(%ebp),%cl
  498. movb 12(%ebp),%dh
  499. movb 14(%ebp),%dl
  500. movb $0x2d,%ah
  501. call syscall
  502. (* SetTime isn't supposed to change DosError!!!
  503. xorb %ah,%ah
  504. movw %ax,doserror
  505. *)
  506. end;
  507. end;
  508. procedure getcbreak(var breakvalue:boolean);
  509. begin
  510. {! Do not use in OS/2. Also not recommended in DOS. Use
  511. signal handling instead.}
  512. asm
  513. movw $0x3300,%ax
  514. call syscall
  515. movl 8(%ebp),%eax
  516. movb %dl,(%eax)
  517. end;
  518. end;
  519. procedure setcbreak(breakvalue:boolean);
  520. begin
  521. {! Do not use in OS/2. Also not recommended in DOS. Use
  522. signal handling instead.}
  523. asm
  524. movb 8(%ebp),%dl
  525. movw $0x3301,%ax
  526. call syscall
  527. end;
  528. end;
  529. procedure getverify(var verify:boolean);
  530. begin
  531. {! Do not use in OS/2.}
  532. asm
  533. movb $0x54,%ah
  534. call syscall
  535. movl 8(%ebp),%edi
  536. stosb
  537. end;
  538. end;
  539. procedure setverify(verify:boolean);
  540. begin
  541. {! Do not use in OS/2.}
  542. asm
  543. movb 8(%ebp),%al
  544. movb $0x2e,%ah
  545. call syscall
  546. end;
  547. end;
  548. {$IFDEF INT64}
  549. function DiskFree (Drive: byte): int64;
  550. var FI: TFSinfo;
  551. RC: longint;
  552. begin
  553. if (os_mode = osDOS) or (os_mode = osDPMI) then
  554. {Function 36 is not supported in OS/2.}
  555. asm
  556. movb 8(%ebp),%dl
  557. movb $0x36,%ah
  558. call syscall
  559. cmpw $-1,%ax
  560. je .LDISKFREE1
  561. mulw %cx
  562. mulw %bx
  563. shll $16,%edx
  564. movw %ax,%dx
  565. xchgl %edx,%eax
  566. leave
  567. ret
  568. .LDISKFREE1:
  569. cltd
  570. leave
  571. ret
  572. end
  573. else
  574. {In OS/2, we use the filesystem information.}
  575. begin
  576. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  577. if RC = 0 then
  578. DiskFree := int64 (FI.Free_Clusters) *
  579. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  580. else
  581. DiskFree := -1;
  582. end;
  583. end;
  584. function DiskSize (Drive: byte): int64;
  585. var FI: TFSinfo;
  586. RC: longint;
  587. begin
  588. if (os_mode = osDOS) or (os_mode = osDPMI) then
  589. {Function 36 is not supported in OS/2.}
  590. asm
  591. movb 8(%ebp),%dl
  592. movb $0x36,%ah
  593. call syscall
  594. movw %dx,%bx
  595. cmpw $-1,%ax
  596. je .LDISKSIZE1
  597. mulw %cx
  598. mulw %bx
  599. shll $16,%edx
  600. movw %ax,%dx
  601. xchgl %edx,%eax
  602. leave
  603. ret
  604. .LDISKSIZE1:
  605. cltd
  606. leave
  607. ret
  608. end
  609. else
  610. {In OS/2, we use the filesystem information.}
  611. begin
  612. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  613. if RC = 0 then
  614. DiskSize := int64 (FI.Total_Clusters) *
  615. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  616. else
  617. DiskSize := -1;
  618. end;
  619. end;
  620. {$ELSE}
  621. function DiskFree (Drive: byte): longint;
  622. var FI: TFSinfo;
  623. RC: longint;
  624. begin
  625. if (os_mode = osDOS) or (os_mode = osDPMI) then
  626. {Function 36 is not supported in OS/2.}
  627. asm
  628. movb 8(%ebp),%dl
  629. movb $0x36,%ah
  630. call syscall
  631. cmpw $-1,%ax
  632. je .LDISKFREE1
  633. mulw %cx
  634. mulw %bx
  635. shll $16,%edx
  636. movw %ax,%dx
  637. xchgl %edx,%eax
  638. leave
  639. ret
  640. .LDISKFREE1:
  641. cltd
  642. leave
  643. ret
  644. end
  645. else
  646. {In OS/2, we use the filesystem information.}
  647. begin
  648. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  649. if RC = 0 then
  650. DiskFree := FI.Free_Clusters *
  651. FI.Sectors_Per_Cluster * FI.Bytes_Per_Sector
  652. else
  653. DiskFree := -1;
  654. end;
  655. end;
  656. function DiskSize (Drive: byte): longint;
  657. var FI: TFSinfo;
  658. RC: longint;
  659. begin
  660. if (os_mode = osDOS) or (os_mode = osDPMI) then
  661. {Function 36 is not supported in OS/2.}
  662. asm
  663. movb 8(%ebp),%dl
  664. movb $0x36,%ah
  665. call syscall
  666. movw %dx,%bx
  667. cmpw $-1,%ax
  668. je .LDISKSIZE1
  669. mulw %cx
  670. mulw %bx
  671. shll $16,%edx
  672. movw %ax,%dx
  673. xchgl %edx,%eax
  674. leave
  675. ret
  676. .LDISKSIZE1:
  677. cltd
  678. leave
  679. ret
  680. end
  681. else
  682. {In OS/2, we use the filesystem information.}
  683. begin
  684. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  685. if RC = 0 then
  686. DiskSize := FI.Total_Clusters *
  687. FI.Sectors_Per_Cluster * FI.Bytes_Per_Sector
  688. else
  689. DiskSize := -1;
  690. end;
  691. end;
  692. {$ENDIF}
  693. procedure SearchRec2DosSearchRec (var F: SearchRec);
  694. const NameSize = 255;
  695. var L, I: longint;
  696. begin
  697. if os_mode <> osOS2 then
  698. begin
  699. I := 1;
  700. while (I <= SizeOf (LastSR))
  701. and (PBA (@F)^ [I] = PBA (@LastSR)^ [I]) do Inc (I);
  702. { Raise "Invalid file handle" RTE if nested FindFirst calls were used. }
  703. if I <= SizeOf (LastSR) then RunError (6);
  704. l:=length(f.name);
  705. for i:=1 to namesize do
  706. f.name[i-1]:=f.name[i];
  707. f.name[l]:=#0;
  708. end;
  709. end;
  710. procedure DosSearchRec2SearchRec (var F: SearchRec; FStat: PFileFindBuf3);
  711. const NameSize=255;
  712. var L, I: longint;
  713. type TRec = record
  714. T, D: word;
  715. end;
  716. begin
  717. if os_mode = osOS2 then with F do
  718. begin
  719. Name := FStat^.Name;
  720. Size := FStat^.FileSize;
  721. Attr := FStat^.AttrFile;
  722. TRec (Time).T := FStat^.TimeLastWrite;
  723. TRec (Time).D := FStat^.DateLastWrite;
  724. end else
  725. begin
  726. for i:=0 to namesize do
  727. if f.name[i]=#0 then
  728. begin
  729. l:=i;
  730. break;
  731. end;
  732. for i:=namesize-1 downto 0 do
  733. f.name[i+1]:=f.name[i];
  734. f.name[0]:=char(l);
  735. Move (F, LastSR, SizeOf (LastSR));
  736. end;
  737. end;
  738. procedure FindFirst (const Path: PathStr; Attr: word; var F: SearchRec);
  739. procedure _findfirst(path:pchar;attr:word;var f:searchrec);
  740. begin
  741. asm
  742. movl 12(%esp),%edx
  743. movw 16(%esp),%cx
  744. {No need to set DTA in EMX. Just give a pointer in ESI.}
  745. movl 18(%ebp),%esi
  746. movb $0x4e,%ah
  747. call syscall
  748. jnc .LFF
  749. movw %ax,doserror
  750. .LFF:
  751. end;
  752. end;
  753. const
  754. FStat: PFileFindBuf3 = nil;
  755. var path0: array[0..255] of char;
  756. Count: longint;
  757. begin
  758. {No error.}
  759. DosError := 0;
  760. if os_mode = osOS2 then
  761. begin
  762. New (FStat);
  763. F.Handle := $FFFFFFFF;
  764. Count := 1;
  765. DosError := DosFindFirst (Path, F.Handle, Attr, FStat,
  766. SizeOf (FStat^), Count, ilStandard);
  767. if (DosError = 0) and (Count = 0) then DosError := 18;
  768. end else
  769. begin
  770. strPcopy(path0,path);
  771. _findfirst(path0,attr,f);
  772. end;
  773. DosSearchRec2SearchRec (F, FStat);
  774. if os_mode = osOS2 then Dispose (FStat);
  775. end;
  776. procedure FindNext (var F: SearchRec);
  777. var FStat: PFileFindBuf3;
  778. Count: longint;
  779. procedure _findnext(var f : searchrec);
  780. begin
  781. asm
  782. movl 12(%ebp),%esi
  783. movb $0x4f,%ah
  784. call syscall
  785. jnc .LFN
  786. movw %ax,doserror
  787. .LFN:
  788. end;
  789. end;
  790. begin
  791. {No error}
  792. DosError := 0;
  793. SearchRec2DosSearchRec (F);
  794. if os_mode = osOS2 then
  795. begin
  796. New (FStat);
  797. Count := 1;
  798. DosError := DosFindNext (F.Handle, FStat, SizeOf (FStat), Count);
  799. if (DosError = 0) and (Count = 0) then DosError := 18;
  800. end else _findnext (F);
  801. DosSearchRec2SearchRec (F, FStat);
  802. if os_mode = osOS2 then Dispose (FStat);
  803. end;
  804. procedure FindClose (var F: SearchRec);
  805. begin
  806. if os_mode = osOS2 then
  807. begin
  808. DosError := DosFindClose (F.Handle);
  809. end;
  810. end;
  811. procedure swapvectors;
  812. {For TP compatibility, this exists.}
  813. begin
  814. end;
  815. type PPchar=^Pchar;
  816. {$ASMMODE DIRECT}
  817. function envs:PPchar;assembler;
  818. asm
  819. movl _environ,%eax
  820. end ['EAX'];
  821. function envcount:longint;assembler;
  822. var hp : ppchar;
  823. asm
  824. movl _envc,%eax
  825. end ['EAX'];
  826. {$ASMMODE ATT}
  827. function envstr(index : longint) : string;
  828. var hp:PPchar;
  829. begin
  830. if (index<=0) or (index>envcount) then
  831. begin
  832. envstr:='';
  833. exit;
  834. end;
  835. hp:=PPchar(cardinal(envs)+4*(index-1));
  836. envstr:=strpas(hp^);
  837. end;
  838. function getenv(const envvar : string) : string;
  839. var hs,_envvar : string;
  840. eqpos,i : longint;
  841. begin
  842. _envvar:=upcase(envvar);
  843. getenv:='';
  844. for i:=1 to envcount do
  845. begin
  846. hs:=envstr(i);
  847. eqpos:=pos('=',hs);
  848. if copy(hs,1,eqpos-1)=_envvar then
  849. begin
  850. getenv:=copy(hs,eqpos+1,length(hs)-eqpos);
  851. exit;
  852. end;
  853. end;
  854. end;
  855. procedure fsplit(path:pathstr;var dir:dirstr;var name:namestr;
  856. var ext:extstr);
  857. var p1,i : longint;
  858. begin
  859. {Get drive name}
  860. p1:=pos(':',path);
  861. if p1>0 then
  862. begin
  863. dir:=path[1]+':';
  864. delete(path,1,p1);
  865. end
  866. else
  867. dir:='';
  868. { split the path and the name, there are no more path informtions }
  869. { if path contains no backslashes }
  870. while true do
  871. begin
  872. p1:=pos('\',path);
  873. if p1=0 then
  874. p1:=pos('/',path);
  875. if p1=0 then
  876. break;
  877. dir:=dir+copy(path,1,p1);
  878. delete(path,1,p1);
  879. end;
  880. {Try to find an extension.}
  881. ext:='';
  882. for i:=length(path) downto 1 do
  883. if path[i]='.' then
  884. begin
  885. ext:=copy(path,i,high(extstr));
  886. delete(path,i,length(path)-i+1);
  887. break;
  888. end;
  889. name:=path;
  890. end;
  891. function fexpand(const path:pathstr):pathstr;
  892. function get_current_drive:byte;assembler;
  893. asm
  894. movb $0x19,%ah
  895. call syscall
  896. end;
  897. var s,pa:string;
  898. i,j:longint;
  899. begin
  900. getdir(0,s);
  901. if FileNameCaseSensitive then
  902. pa := path
  903. else
  904. pa:=upcase(path);
  905. {Allow slash as backslash}
  906. for i:=1 to length(pa) do
  907. if pa[i]='/' then
  908. pa[i]:='\';
  909. if (length(pa)>1) and (pa[1] in ['A'..'Z']) and (pa[2]=':') then
  910. begin
  911. {We must get the right directory}
  912. getdir(byte(pa[1])-byte('A')+1,s);
  913. if (byte(pa[0])>2) and (pa[3]<>'\') then
  914. if pa[1]=s[1] then
  915. pa:=s+'\'+copy (pa,3,length(pa))
  916. else
  917. pa:=pa[1]+':\'+copy (pa,3,length(pa))
  918. end
  919. else
  920. if pa[1]='\' then
  921. pa:=s[1]+':'+pa
  922. else if s[0]=#3 then
  923. pa:=s+pa
  924. else
  925. pa:=s+'\'+pa;
  926. {First remove all references to '\.\'}
  927. i:=pos('\.\',pa);
  928. while i<>0 do
  929. begin
  930. delete(pa,i,2);
  931. i:=pos('\.\',pa);
  932. end;
  933. {Now remove also all references to '\..\' + of course previous dirs..}
  934. repeat
  935. i:=pos('\..\',pa);
  936. if i<>0 then
  937. begin
  938. j:=i-1;
  939. while (j>1) and (pa[j]<>'\') do
  940. dec(j);
  941. delete (pa,j,i-j+3);
  942. end;
  943. until i=0;
  944. {Remove End . and \}
  945. if (length(pa)>0) and (pa[length(pa)]='.') then
  946. dec(byte(pa[0]));
  947. if (length(pa)>0) and (pa[length(pa)]='\') then
  948. dec(byte(pa[0]));
  949. fexpand:=pa;
  950. end;
  951. procedure packtime(var d:datetime;var time:longint);
  952. var zs:longint;
  953. begin
  954. time:=-1980;
  955. time:=time+d.year and 127;
  956. time:=time shl 4;
  957. time:=time+d.month;
  958. time:=time shl 5;
  959. time:=time+d.day;
  960. time:=time shl 16;
  961. zs:=d.hour;
  962. zs:=zs shl 6;
  963. zs:=zs+d.min;
  964. zs:=zs shl 5;
  965. zs:=zs+d.sec div 2;
  966. time:=time+(zs and $ffff);
  967. end;
  968. procedure unpacktime (time:longint;var d:datetime);
  969. begin
  970. d.sec:=(time and 31) * 2;
  971. time:=time shr 5;
  972. d.min:=time and 63;
  973. time:=time shr 6;
  974. d.hour:=time and 31;
  975. time:=time shr 5;
  976. d.day:=time and 31;
  977. time:=time shr 5;
  978. d.month:=time and 15;
  979. time:=time shr 4;
  980. d.year:=time+1980;
  981. end;
  982. procedure getfattr(var f;var attr : word);assembler;
  983. asm
  984. movw $0x4300,%ax
  985. movl f,%edx
  986. {addl $filerec.name,%edx Doesn't work!!}
  987. addl $60,%edx
  988. call syscall
  989. movl attr,%ebx
  990. movw %cx,(%ebx)
  991. xorb %ah,%ah
  992. movw %ax,doserror
  993. end;
  994. procedure setfattr(var f;attr : word);assembler;
  995. asm
  996. movw $0x4301,%ax
  997. movl f,%edx
  998. {addl $filerec.name,%edx Doesn't work!!}
  999. addl $60,%edx
  1000. movw attr,%cx
  1001. call syscall
  1002. xorb %ah,%ah
  1003. movw %ax,doserror
  1004. end;
  1005. end.
  1006. {
  1007. $Log$
  1008. Revision 1.25 2000-05-28 18:20:16 hajny
  1009. * DiskFree/DiskSize updated
  1010. Revision 1.24 2000/05/21 16:06:38 hajny
  1011. + FSearch and Find* reworked
  1012. Revision 1.23 2000/04/18 20:30:02 hajny
  1013. * FSearch with given path corrected
  1014. Revision 1.22 2000/03/12 18:32:17 hajny
  1015. * missing parentheses added
  1016. Revision 1.21 2000/03/05 19:00:37 hajny
  1017. * DiskFree, DiskSize - int64 result, fix for osDPMI mode
  1018. Revision 1.20 2000/02/09 16:59:33 peter
  1019. * truncated log
  1020. Revision 1.19 2000/01/09 20:51:03 hajny
  1021. * FPK changed to FPC
  1022. Revision 1.18 2000/01/07 16:41:45 daniel
  1023. * copyright 2000
  1024. Revision 1.17 1999/10/13 12:21:56 daniel
  1025. * OS/2 compiler works again.
  1026. Revision 1.16 1999/09/13 18:21:02 hajny
  1027. * again didn't manage to read docu for DosFindFirst properly :-(
  1028. Revision 1.15 1999/09/13 17:56:26 hajny
  1029. * another correction to FSearch fix - mistyping
  1030. Revision 1.14 1999/09/13 17:35:15 hajny
  1031. * little addition/correction to FSearch fix
  1032. Revision 1.13 1999/09/09 09:20:43 hajny
  1033. * FSearch under OS/2 fixed
  1034. }