dos.pas 26 KB

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