dos.pas 30 KB

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