dos.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2004 by the Free Pascal development team.
  5. Dos unit for BP7 compatible RTL (novell netware libc)
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit dos;
  13. interface
  14. uses libc;
  15. Const
  16. FileNameLen = 255;
  17. Type
  18. searchrec = packed record
  19. DirP : POINTER; { used for opendir }
  20. EntryP: POINTER; { and readdir }
  21. Magic : WORD;
  22. fill : array[1..11] of byte;
  23. attr : byte;
  24. time : longint;
  25. size : longint;
  26. name : string[255];
  27. { Internals used by netware port only: }
  28. _mask : string[255];
  29. _dir : string[255];
  30. end;
  31. registers = packed record
  32. case i : integer of
  33. 0 : (ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si,f51,di,f6,ds,f7,es,f8,flags,fs,gs : word);
  34. 1 : (al,ah,f9,f10,bl,bh,f11,f12,cl,ch,f13,f14,dl,dh : byte);
  35. 2 : (eax, ebx, ecx, edx, ebp, esi, edi : longint);
  36. end;
  37. {$i dosh.inc}
  38. implementation
  39. uses
  40. strings;
  41. {$ASMMODE ATT}
  42. {*****************************************************************************
  43. --- Info / Date / Time ---
  44. ******************************************************************************}
  45. {$PACKRECORDS 4}
  46. function dosversion : word;
  47. var i : Tutsname;
  48. begin
  49. if uname (i) >= 0 then
  50. dosversion := WORD (i.netware_major) SHL 8 + i.netware_minor
  51. else dosversion := $0005;
  52. end;
  53. procedure getdate(var year,month,mday,wday : word);
  54. var
  55. t : TTime;
  56. tm : Ttm;
  57. begin
  58. time(t); localtime_r(t,tm);
  59. with tm do
  60. begin
  61. year := tm_year+1900;
  62. month := tm_mon+1;
  63. mday := tm_mday;
  64. wday := tm_wday;
  65. end;
  66. end;
  67. procedure setdate(year,month,day : word);
  68. begin
  69. end;
  70. procedure gettime(var hour,minute,second,sec100 : word);
  71. var
  72. t : TTime;
  73. tm : Ttm;
  74. begin
  75. time(t); localtime_r(t,tm);
  76. with tm do
  77. begin
  78. hour := tm_hour;
  79. minute := tm_min;
  80. second := tm_sec;
  81. sec100 := 0;
  82. end;
  83. end;
  84. procedure settime(hour,minute,second,sec100 : word);
  85. begin
  86. end;
  87. Procedure packtime(var t : datetime;var p : longint);
  88. Begin
  89. p:=(t.sec shr 1)+(t.min shl 5)+(t.hour shl 11)+(t.day shl 16)+(t.month shl 21)+((t.year-1980) shl 25);
  90. End;
  91. Procedure unpacktime(p : longint;var t : datetime);
  92. Begin
  93. with t do
  94. begin
  95. sec:=(p and 31) shl 1;
  96. min:=(p shr 5) and 63;
  97. hour:=(p shr 11) and 31;
  98. day:=(p shr 16) and 31;
  99. month:=(p shr 21) and 15;
  100. year:=(p shr 25)+1980;
  101. end;
  102. End;
  103. {******************************************************************************
  104. --- Exec ---
  105. ******************************************************************************}
  106. {$ifdef HASTHREADVAR}
  107. threadvar
  108. {$else HASTHREADVAR}
  109. var
  110. {$endif HASTHREADVAR}
  111. lastdosexitcode : word;
  112. const maxargs=256;
  113. procedure exec(const path : pathstr;const comline : comstr);
  114. var c : comstr;
  115. i : integer;
  116. args : array[0..maxargs] of pchar;
  117. arg0 : pathstr;
  118. numargs,wstat : integer;
  119. begin
  120. //writeln ('dos.exec (',path,',',comline,')');
  121. arg0 := fexpand (path)+#0;
  122. args[0] := @arg0[1];
  123. numargs := 0;
  124. c:=comline;
  125. i:=1;
  126. while i<=length(c) do
  127. begin
  128. if c[i]<>' ' then
  129. begin
  130. {Commandline argument found. append #0 and set pointer in args }
  131. inc(numargs);
  132. args[numargs]:=@c[i];
  133. while (i<=length(c)) and (c[i]<>' ') do
  134. inc(i);
  135. c[i] := #0;
  136. end;
  137. inc(i);
  138. end;
  139. args[numargs+1] := nil;
  140. // i := spawnvp (P_WAIT,args[0],@args);
  141. i := procve(args[0], PROC_CURRENT_SPACE+PROC_INHERIT_CWD,nil,nil,nil,nil,0,nil,args);
  142. if i <> -1 then
  143. begin
  144. waitpid(i,@wstat,0);
  145. doserror := 0;
  146. lastdosexitcode := wstat;
  147. end else
  148. begin
  149. doserror := 8; // for now, what about errno ?
  150. end;
  151. end;
  152. function dosexitcode : word;
  153. begin
  154. dosexitcode:=lastdosexitcode;
  155. end;
  156. procedure getcbreak(var breakvalue : boolean);
  157. begin
  158. end;
  159. procedure setcbreak(breakvalue : boolean);
  160. begin
  161. end;
  162. procedure getverify(var verify : boolean);
  163. begin
  164. verify := true;
  165. end;
  166. procedure setverify(verify : boolean);
  167. begin
  168. end;
  169. {******************************************************************************
  170. --- Disk ---
  171. ******************************************************************************}
  172. function getvolnum (drive : byte) : longint;
  173. var dir : STRING[255];
  174. P,PS,
  175. V : LONGINT;
  176. begin
  177. {if drive = 0 then
  178. begin // get volume name from current directory (i.e. SERVER-NAME/VOL2:TEST)
  179. getdir (0,dir);
  180. p := pos (':', dir);
  181. if p = 0 then
  182. begin
  183. getvolnum := -1;
  184. exit;
  185. end;
  186. byte (dir[0]) := p-1;
  187. dir[p] := #0;
  188. PS := pos ('/', dir);
  189. INC (PS);
  190. if _GetVolumeNumber (@dir[PS], V) <> 0 then
  191. getvolnum := -1
  192. else
  193. getvolnum := V;
  194. end else
  195. getvolnum := drive-1;}
  196. end;
  197. function diskfree(drive : byte) : int64;
  198. VAR Buf : ARRAY [0..255] OF CHAR;
  199. TotalBlocks : WORD;
  200. SectorsPerBlock : WORD;
  201. availableBlocks : WORD;
  202. totalDirectorySlots : WORD;
  203. availableDirSlots : WORD;
  204. volumeisRemovable : WORD;
  205. volumeNumber : LONGINT;
  206. begin
  207. volumeNumber := getvolnum (drive);
  208. (*
  209. if volumeNumber >= 0 then
  210. begin
  211. {i think thats not the right function but for others i need a connection handle}
  212. if _GetVolumeInfoWithNumber (byte(volumeNumber),@Buf,
  213. TotalBlocks,
  214. SectorsPerBlock,
  215. availableBlocks,
  216. totalDirectorySlots,
  217. availableDirSlots,
  218. volumeisRemovable) = 0 THEN
  219. begin
  220. diskfree := int64 (availableBlocks) * int64 (SectorsPerBlock) * 512;
  221. end else
  222. diskfree := 0;
  223. end else*)
  224. diskfree := 0;
  225. end;
  226. function disksize(drive : byte) : int64;
  227. VAR Buf : ARRAY [0..255] OF CHAR;
  228. TotalBlocks : WORD;
  229. SectorsPerBlock : WORD;
  230. availableBlocks : WORD;
  231. totalDirectorySlots : WORD;
  232. availableDirSlots : WORD;
  233. volumeisRemovable : WORD;
  234. volumeNumber : LONGINT;
  235. begin
  236. volumeNumber := getvolnum (drive);
  237. (*
  238. if volumeNumber >= 0 then
  239. begin
  240. {i think thats not the right function but for others i need a connection handle}
  241. if _GetVolumeInfoWithNumber (byte(volumeNumber),@Buf,
  242. TotalBlocks,
  243. SectorsPerBlock,
  244. availableBlocks,
  245. totalDirectorySlots,
  246. availableDirSlots,
  247. volumeisRemovable) = 0 THEN
  248. begin
  249. disksize := int64 (TotalBlocks) * int64 (SectorsPerBlock) * 512;
  250. end else
  251. disksize := 0;
  252. end else*)
  253. disksize := 0;
  254. end;
  255. {******************************************************************************
  256. --- Utils ---
  257. ******************************************************************************}
  258. procedure timet2dostime (timet:longint; var dostime : longint);
  259. var tm : Ttm;
  260. begin
  261. localtime_r(timet,tm);
  262. dostime:=(tm.tm_sec shr 1)+(tm.tm_min shl 5)+(tm.tm_hour shl 11)+(tm.tm_mday shl 16)+((tm.tm_mon+1) shl 21)+((tm.tm_year+1900-1980) shl 25);
  263. end;
  264. function nwattr2dosattr (nwattr : longint) : word;
  265. begin
  266. nwattr2dosattr := 0;
  267. if nwattr and M_A_RDONLY > 0 then nwattr2dosattr := nwattr2dosattr + readonly;
  268. if nwattr and M_A_HIDDEN > 0 then nwattr2dosattr := nwattr2dosattr + hidden;
  269. if nwattr and M_A_SYSTEM > 0 then nwattr2dosattr := nwattr2dosattr + sysfile;
  270. if nwattr and M_A_SUBDIR > 0 then nwattr2dosattr := nwattr2dosattr + directory;
  271. if nwattr and M_A_ARCH > 0 then nwattr2dosattr := nwattr2dosattr + archive;
  272. end;
  273. {******************************************************************************
  274. --- Findfirst FindNext ---
  275. ******************************************************************************}
  276. procedure find_setfields (var f : searchRec);
  277. var
  278. StatBuf : TStat;
  279. fname : string[255];
  280. begin
  281. with F do
  282. begin
  283. if Magic = $AD01 then
  284. begin
  285. attr := nwattr2dosattr (Pdirent(EntryP)^.d_mode);
  286. size := Pdirent(EntryP)^.d_size;
  287. name := strpas (Pdirent(EntryP)^.d_name);
  288. doserror := 0;
  289. fname := f._dir + f.name;
  290. if length (fname) = 255 then dec (byte(fname[0]));
  291. fname := fname + #0;
  292. if stat (@fname[1],StatBuf) = 0 then
  293. timet2dostime (StatBuf.st_mtim.tv_sec, time)
  294. else
  295. time := 0;
  296. end else
  297. begin
  298. FillChar (f,sizeof(f),0);
  299. doserror := 18;
  300. end;
  301. end;
  302. end;
  303. procedure findfirst(const path : pathstr;attr : word;var f : searchRec);
  304. var
  305. path0 : array[0..256] of char;
  306. p : longint;
  307. begin
  308. IF path = '' then
  309. begin
  310. doserror := 18;
  311. exit;
  312. end;
  313. if (pos ('?',path) > 0) or (pos ('*',path) > 0) then
  314. begin
  315. p := length (path);
  316. while (p > 0) and (not (path[p] in ['\','/'])) do
  317. dec (p);
  318. if p > 0 then
  319. begin
  320. f._mask := copy (path,p+1,255);
  321. f._dir := copy (path,1,p);
  322. strpcopy(path0,f._dir);
  323. end else
  324. begin
  325. f._mask := path;
  326. getdir (0,f._dir);
  327. if (f._dir[length(f._dir)] <> '/') and
  328. (f._dir[length(f._dir)] <> '\') then
  329. f._dir := f._dir + '/';
  330. end;
  331. end;
  332. //writeln (stderr,'mask: "',f._mask,'" dir:"',path0,'"');
  333. f._mask := f._mask + #0;
  334. Pdirent(f.DirP) := opendir (path0);
  335. if f.DirP = nil then
  336. doserror := 18
  337. else begin
  338. F.Magic := $AD01;
  339. findnext (f);
  340. end;
  341. end;
  342. procedure findnext(var f : searchRec);
  343. begin
  344. if F.Magic <> $AD01 then
  345. begin
  346. doserror := 18;
  347. exit;
  348. end;
  349. doserror:=0;
  350. repeat
  351. Pdirent(f.EntryP) := readdir (Pdirent(f.DirP));
  352. if F.EntryP = nil then
  353. doserror := 18
  354. else
  355. if f._mask = #0 then
  356. begin
  357. find_setfields (f);
  358. exit;
  359. end else
  360. if fnmatch(@f._mask[1],Pdirent(f.EntryP)^.d_name,FNM_CASEFOLD) = 0 then
  361. begin
  362. find_setfields (f);
  363. exit;
  364. end;
  365. until doserror <> 0;
  366. end;
  367. Procedure FindClose(Var f: SearchRec);
  368. begin
  369. if F.Magic <> $AD01 then
  370. begin
  371. doserror := 18;
  372. EXIT;
  373. end;
  374. doserror:=0;
  375. closedir (Pdirent(f.DirP));
  376. f.Magic := 0;
  377. f.DirP := NIL;
  378. f.EntryP := NIL;
  379. end;
  380. procedure swapvectors;
  381. begin
  382. end;
  383. {******************************************************************************
  384. --- File ---
  385. ******************************************************************************}
  386. procedure fsplit(path : pathstr;var dir : dirstr;var name : namestr;var ext : extstr);
  387. var
  388. dotpos,p1,i : longint;
  389. begin
  390. { allow backslash as slash }
  391. for i:=1 to length(path) do
  392. if path[i]='\' then path[i]:='/';
  393. { get volume name }
  394. p1:=pos(':',path);
  395. if p1>0 then
  396. begin
  397. dir:=copy(path,1,p1);
  398. delete(path,1,p1);
  399. end
  400. else
  401. dir:='';
  402. { split the path and the name, there are no more path informtions }
  403. { if path contains no backslashes }
  404. while true do
  405. begin
  406. p1:=pos('/',path);
  407. if p1=0 then
  408. break;
  409. dir:=dir+copy(path,1,p1);
  410. delete(path,1,p1);
  411. end;
  412. { try to find out a extension }
  413. //if LFNSupport then
  414. begin
  415. Ext:='';
  416. i:=Length(Path);
  417. DotPos:=256;
  418. While (i>0) Do
  419. Begin
  420. If (Path[i]='.') Then
  421. begin
  422. DotPos:=i;
  423. break;
  424. end;
  425. Dec(i);
  426. end;
  427. Ext:=Copy(Path,DotPos,255);
  428. Name:=Copy(Path,1,DotPos - 1);
  429. end
  430. end;
  431. function GetShortName(var p : String) : boolean;
  432. begin
  433. GetShortName := false;
  434. end;
  435. function GetLongName(var p : String) : boolean;
  436. begin
  437. GetLongName := false;
  438. end;
  439. {$define FPC_FEXPAND_DRIVES}
  440. {$define FPC_FEXPAND_VOLUMES}
  441. {$define FPC_FEXPAND_NO_DEFAULT_PATHS}
  442. {$i fexpand.inc}
  443. Function FSearch(path: pathstr; dirlist: string): pathstr;
  444. var
  445. i,p1 : longint;
  446. s : searchrec;
  447. newdir : pathstr;
  448. begin
  449. system.write ('FSearch ("',path,'","',dirlist,'"');
  450. { check if the file specified exists }
  451. findfirst(path,anyfile,s);
  452. if doserror=0 then
  453. begin
  454. findclose(s);
  455. fsearch:=path;
  456. exit;
  457. end;
  458. { No wildcards allowed in these things }
  459. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  460. fsearch:=''
  461. else
  462. begin
  463. { allow backslash as slash }
  464. for i:=1 to length(dirlist) do
  465. if dirlist[i]='\' then dirlist[i]:='/';
  466. repeat
  467. p1:=pos(';',dirlist);
  468. if p1<>0 then
  469. begin
  470. newdir:=copy(dirlist,1,p1-1);
  471. delete(dirlist,1,p1);
  472. end
  473. else
  474. begin
  475. newdir:=dirlist;
  476. dirlist:='';
  477. end;
  478. if (newdir<>'') and (not (newdir[length(newdir)] in ['/',':'])) then
  479. newdir:=newdir+'/';
  480. findfirst(newdir+path,anyfile,s);
  481. if doserror=0 then
  482. newdir:=newdir+path
  483. else
  484. newdir:='';
  485. until (dirlist='') or (newdir<>'');
  486. fsearch:=newdir;
  487. end;
  488. findclose(s);
  489. end;
  490. {******************************************************************************
  491. --- Get/Set File Time,Attr ---
  492. ******************************************************************************}
  493. procedure getftime(var f;var time : longint);
  494. var
  495. StatBuf : TStat;
  496. begin
  497. doserror := 0;
  498. if fstat (FileRec (f).Handle, StatBuf) = 0 then
  499. timet2dostime (StatBuf.st_mtim.tv_sec,time)
  500. else begin
  501. time := 0;
  502. doserror := ___errno^;
  503. end;
  504. end;
  505. procedure setftime(var f;time : longint);
  506. begin
  507. {is there a netware function to do that ?????}
  508. ConsolePrintf ('warning: fpc dos.setftime not implemented'#13#10);
  509. end;
  510. procedure getfattr(var f;var attr : word);
  511. VAR StatBuf : TStat;
  512. begin
  513. doserror := 0;
  514. if fstat (FileRec (f).Handle, StatBuf) = 0 then
  515. attr := nwattr2dosattr (StatBuf.st_mode)
  516. else
  517. begin
  518. attr := 0;
  519. doserror := ___errno^;
  520. end;
  521. end;
  522. procedure setfattr(var f;attr : word);
  523. var
  524. StatBuf : TStat;
  525. newMode : longint;
  526. begin
  527. if fstat (FileRec(f).Handle,StatBuf) = 0 then
  528. begin
  529. newmode := StatBuf.st_mode and ($FFFFFFFF - M_A_RDONLY-M_A_HIDDEN-M_A_SYSTEM-M_A_ARCH); {only this can be set by dos unit}
  530. newmode := newmode and M_A_BITS_SIGNIFICANT; {set netware attributes}
  531. if attr and readonly > 0 then
  532. newmode := newmode or M_A_RDONLY;
  533. if attr and hidden > 0 then
  534. newmode := newmode or M_A_HIDDEN;
  535. if attr and sysfile > 0 then
  536. newmode := newmode or M_A_SYSTEM;
  537. if attr and archive > 0 then
  538. newmode := newmode or M_A_ARCH;
  539. if fchmod (FileRec(f).Handle,newMode) < 0 then
  540. doserror := ___errno^ else
  541. doserror := 0;
  542. end else
  543. doserror := ___errno^;
  544. end;
  545. {******************************************************************************
  546. --- Environment ---
  547. ******************************************************************************}
  548. Function EnvCount: Longint;
  549. var
  550. envcnt : longint;
  551. p : ppchar;
  552. Begin
  553. envcnt:=0;
  554. p:=envp; {defined in system}
  555. while (p^<>nil) do
  556. begin
  557. inc(envcnt);
  558. inc(p);
  559. end;
  560. EnvCount := envcnt
  561. End;
  562. Function EnvStr (Index: longint): String;
  563. Var
  564. i : longint;
  565. p : ppchar;
  566. Begin
  567. if Index <= 0 then
  568. envstr:=''
  569. else
  570. begin
  571. p:=envp; {defined in system}
  572. i:=1;
  573. while (i<Index) and (p^<>nil) do
  574. begin
  575. inc(i);
  576. inc(p);
  577. end;
  578. if p=nil then
  579. envstr:=''
  580. else
  581. envstr:=strpas(p^)
  582. end;
  583. end;
  584. { works fine (at least with netware 6.5) }
  585. Function GetEnv(envvar: string): string;
  586. var envvar0 : array[0..512] of char;
  587. p : pchar;
  588. i,isDosPath,res : longint;
  589. begin
  590. if upcase(envvar) = 'PATH' then
  591. begin // netware does not have search paths in the environment var PATH
  592. // return it here (needed for the compiler)
  593. GetEnv := '';
  594. i := 1;
  595. res := GetSearchPathElement (i, isdosPath, @envvar0[0]);
  596. while res = 0 do
  597. begin
  598. if GetEnv <> '' then GetEnv := GetEnv + ';';
  599. GetEnv := GetEnv + envvar0;
  600. inc (i);
  601. res := GetSearchPathElement (i, isdosPath, @envvar0[0]);
  602. end;
  603. for i := 1 to length(GetEnv) do
  604. if GetEnv[i] = '\' then
  605. GetEnv[i] := '/';
  606. end else
  607. begin
  608. strpcopy(envvar0,envvar);
  609. p := libc.getenv (envvar0);
  610. if p = NIL then
  611. GetEnv := ''
  612. else
  613. GetEnv := strpas (p);
  614. end;
  615. end;
  616. {******************************************************************************
  617. --- Not Supported ---
  618. ******************************************************************************}
  619. Procedure keep(exitcode : word);
  620. Begin
  621. { simply wait until nlm will be unloaded }
  622. while true do delay (60000);
  623. End;
  624. Procedure getintvec(intno : byte;var vector : pointer);
  625. Begin
  626. { no netware equivalent }
  627. End;
  628. Procedure setintvec(intno : byte;vector : pointer);
  629. Begin
  630. { no netware equivalent }
  631. End;
  632. procedure intr(intno : byte;var regs : registers);
  633. begin
  634. { no netware equivalent }
  635. end;
  636. procedure msdos(var regs : registers);
  637. begin
  638. { no netware equivalent }
  639. end;
  640. end.
  641. {
  642. $Log$
  643. Revision 1.1 2004-09-05 20:58:47 armin
  644. * first rtl version for netwlibc
  645. }