dos.pas 27 KB

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