dos.pp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Michael Van Canneyt and Peter Vreman,
  4. members of the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. Unit Dos;
  12. Interface
  13. uses baseunix;
  14. Const
  15. FileNameLen = 255;
  16. Type
  17. SearchRec =
  18. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  19. packed
  20. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  21. Record
  22. {Fill : array[1..21] of byte; Fill replaced with below}
  23. SearchPos : TOff; {directory position}
  24. SearchNum : LongInt; {to track which search this is}
  25. DirPtr : Pointer; {directory pointer for reading directory}
  26. SearchType : Byte; {0=normal, 1=open will close, 2=only 1 file}
  27. SearchAttr : Byte; {attribute we are searching for}
  28. Mode : Word;
  29. Fill : Array[1..1] of Byte; {future use}
  30. {End of fill}
  31. Attr : Byte; {attribute of found file}
  32. Time : LongInt; {last modify date of found file}
  33. Size : LongInt; {file size of found file}
  34. Reserved : Word; {future use}
  35. Name : String[FileNameLen]; {name of found file}
  36. SearchSpec : String[FileNameLen]; {search pattern}
  37. NamePos : Word; {end of path, start of name position}
  38. End;
  39. {$DEFINE HAS_FILENAMELEN}
  40. {$i dosh.inc}
  41. {Extra Utils}
  42. function weekday(y,m,d : longint) : longint; platform;
  43. Procedure UnixDateToDt(SecsPast: LongInt; Var Dt: DateTime); platform;
  44. Function DTToUnixDate(DT: DateTime): LongInt; platform;
  45. {Disk}
  46. Function AddDisk(const path:string) : byte; platform;
  47. Implementation
  48. Uses
  49. UnixUtil,
  50. Strings,
  51. Unix,
  52. {$ifdef FPC_USE_LIBC}initc{$ELSE}Syscall{$ENDIF};
  53. {$DEFINE HAS_GETMSCOUNT}
  54. {$DEFINE FPC_FEXPAND_TILDE} { Tilde is expanded to home }
  55. {$DEFINE FPC_FEXPAND_GETENVPCHAR} { GetEnv result is a PChar }
  56. {$I dos.inc}
  57. {******************************************************************************
  58. --- Link C Lib if set ---
  59. ******************************************************************************}
  60. type
  61. RtlInfoType = Record
  62. FMode,
  63. FInode,
  64. FUid,
  65. FGid,
  66. FSize,
  67. FMTime : LongInt;
  68. End;
  69. {******************************************************************************
  70. --- Info / Date / Time ---
  71. ******************************************************************************}
  72. Function DosVersion:Word;
  73. Var
  74. Buffer : Array[0..255] of Char;
  75. Tmp2,
  76. TmpStr : String[40];
  77. TmpPos,
  78. SubRel,
  79. Rel : LongInt;
  80. info : utsname;
  81. Begin
  82. FPUName(info);
  83. Move(info.release,buffer[0],40);
  84. TmpStr:=StrPas(Buffer);
  85. SubRel:=0;
  86. TmpPos:=Pos('.',TmpStr);
  87. if TmpPos>0 then
  88. begin
  89. Tmp2:=Copy(TmpStr,TmpPos+1,40);
  90. Delete(TmpStr,TmpPos,40);
  91. end;
  92. TmpPos:=Pos('.',Tmp2);
  93. if TmpPos>0 then
  94. Delete(Tmp2,TmpPos,40);
  95. Val(TmpStr,Rel);
  96. Val(Tmp2,SubRel);
  97. DosVersion:=Rel+(SubRel shl 8);
  98. End;
  99. function WeekDay (y,m,d:longint):longint;
  100. {
  101. Calculates th day of the week. returns -1 on error
  102. }
  103. var
  104. u,v : longint;
  105. begin
  106. if (m<1) or (m>12) or (y<1600) or (y>4000) or
  107. (d<1) or (d>30+((m+ord(m>7)) and 1)-ord(m=2)) or
  108. ((m*d=58) and (((y mod 4>0) or (y mod 100=0)) and (y mod 400>0))) then
  109. WeekDay:=-1
  110. else
  111. begin
  112. u:=m;
  113. v:=y;
  114. if m<3 then
  115. begin
  116. inc(u,12);
  117. dec(v);
  118. end;
  119. WeekDay:=(d+2*u+((3*(u+1)) div 5)+v+(v div 4)-(v div 100)+(v div 400)+1) mod 7;
  120. end;
  121. end;
  122. Procedure GetDate(Var Year, Month, MDay, WDay: Word);
  123. var
  124. tv:timeval;
  125. tz:timezone;
  126. hour,min,sec : word;
  127. begin
  128. fpgettimeofday(@tv,@tz);
  129. tv.tv_sec:=tv.tv_sec-tz.tz_minuteswest*60;
  130. EpochToUniversal(tv.tv_sec,year,month,mday,hour,min,sec);
  131. Wday:=weekday(Year,Month,MDay);
  132. end;
  133. procedure SetTime(Hour,Minute,Second,sec100:word);
  134. var
  135. dow,Year, Month, Day : Word;
  136. tv : timeval;
  137. begin
  138. GetDate (Year, Month, Day,dow);
  139. tv.tv_sec:= LocalToEpoch ( Year, Month, Day, Hour, Minute, Second ) ;
  140. tv.tv_usec:= Sec100 * 10000;
  141. fpSettimeofday(@tv,nil);
  142. end;
  143. procedure SetDate(Year,Month,Day:Word);
  144. var
  145. Hour, Min, Sec, Sec100 : Word;
  146. tv : timeval;
  147. begin
  148. GetTime ( Hour, Min, Sec, Sec100 );
  149. tv.tv_sec:= LocalToEpoch ( Year, Month, Day, Hour, Min, Sec ) ;
  150. tv.tv_usec:= Sec100 * 10000;
  151. fpSettimeofday(@tv,nil);
  152. end;
  153. Function SetDateTime(Year,Month,Day,hour,minute,second:Word) : Boolean;
  154. var
  155. tv : timeval;
  156. begin
  157. tv.tv_sec:= LocalToEpoch ( Year, Month, Day, Hour, Minute, Second ) ;
  158. tv.tv_usec:= 0;
  159. SetDatetime:=fpSettimeofday(@tv,nil)=0;
  160. end;
  161. Procedure GetTime(Var Hour, Minute, Second, Sec100: Word);
  162. var
  163. tv:timeval;
  164. tz:timezone;
  165. year,month,day : word;
  166. begin
  167. fpgettimeofday(@tv,@tz);
  168. tv.tv_sec:=tv.tv_sec-tz.tz_minuteswest*60;
  169. EpochToUniversal(tv.tv_sec,year,month,day,hour,minute,second);
  170. sec100:=tv.tv_usec div 10000;
  171. end;
  172. Procedure UnixDateToDt(SecsPast: LongInt; Var Dt: DateTime);
  173. Begin
  174. EpochToLocal(SecsPast,dt.Year,dt.Month,dt.Day,dt.Hour,dt.Min,dt.Sec);
  175. End;
  176. Function DTToUnixDate(DT: DateTime): LongInt;
  177. Begin
  178. DTToUnixDate:=LocalToEpoch(dt.Year,dt.Month,dt.Day,dt.Hour,dt.Min,dt.Sec);
  179. End;
  180. function GetMsCount: int64;
  181. var
  182. tv : TimeVal;
  183. { tz : TimeZone;}
  184. begin
  185. FPGetTimeOfDay (@tv, nil {,tz});
  186. GetMsCount := int64(tv.tv_Sec) * 1000 + tv.tv_uSec div 1000;
  187. end;
  188. {******************************************************************************
  189. --- Exec ---
  190. ******************************************************************************}
  191. Procedure Exec (Const Path: PathStr; Const ComLine: ComStr);
  192. var
  193. pid : longint; // pid_t?
  194. cmdline2 : ppchar;
  195. commandline : RawByteString;
  196. realpath : ansistring;
  197. // The Error-Checking in the previous Version failed, since halt($7F) gives an WaitPid-status of $7F00
  198. Begin
  199. LastDosExitCode:=0;
  200. if Path='' then
  201. begin
  202. doserror:=2;
  203. exit;
  204. end;
  205. pid:=fpFork;
  206. if pid=0 then
  207. begin
  208. cmdline2:=nil;
  209. realpath:=path;
  210. if Comline<>'' Then
  211. begin
  212. CommandLine:=ToSingleByteFileSystemEncodedFileName(ComLine); // conversion must live till after fpexec!
  213. cmdline2:=StringtoPPChar(CommandLine,1);
  214. cmdline2^:=pchar(realPath);
  215. end
  216. else
  217. begin
  218. getmem(cmdline2,2*sizeof(pchar));
  219. cmdline2^:=pchar(realPath);
  220. cmdline2[1]:=nil;
  221. end;
  222. {The child does the actual exec, and then exits}
  223. fpExecv(pchar(realPath),cmdline2);
  224. {If the execve fails, we return an exitvalue of 127, to let it be known}
  225. fpExit(127);
  226. end
  227. else
  228. if pid=-1 then {Fork failed}
  229. begin
  230. DosError:=8;
  231. exit
  232. end;
  233. {We're in the parent, let's wait.}
  234. LastDosExitCode:=WaitProcess(pid); // WaitPid and result-convert
  235. if (LastDosExitCode>=0) and (LastDosExitCode<>127) then
  236. DosError:=0
  237. else
  238. DosError:=8; // perhaps one time give an better error
  239. End;
  240. {******************************************************************************
  241. --- Disk ---
  242. ******************************************************************************}
  243. {
  244. The Diskfree and Disksize functions need a file on the specified drive, since this
  245. is required for the fpstatfs system call.
  246. These filenames are set in drivestr[0..26], and have been preset to :
  247. 0 - '.' (default drive - hence current dir is ok.)
  248. 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
  249. 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
  250. 3 - '/' (C: equivalent of dos is the root partition)
  251. 4..26 (can be set by you're own applications)
  252. ! Use AddDisk() to Add new drives !
  253. They both return -1 when a failure occurs.
  254. }
  255. Const
  256. FixDriveStr : array[0..3] of pchar=(
  257. '.',
  258. '/fd0/.',
  259. '/fd1/.',
  260. '/.'
  261. );
  262. const
  263. Drives : byte = 4;
  264. var
  265. DriveStr : array[4..26] of pchar;
  266. Function AddDisk(const path:string) : byte;
  267. begin
  268. if not (DriveStr[Drives]=nil) then
  269. FreeMem(DriveStr[Drives]);
  270. GetMem(DriveStr[Drives],length(Path)+1);
  271. StrPCopy(DriveStr[Drives],path);
  272. AddDisk:=Drives;
  273. inc(Drives);
  274. if Drives>26 then
  275. Drives:=4;
  276. end;
  277. Function DiskFree(Drive: Byte): int64;
  278. var
  279. fs : tstatfs;
  280. Begin
  281. if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (fpStatFS(fixdrivestr[drive],@fs)<>-1)) or
  282. ((not (drivestr[Drive]=nil)) and (fpStatFS(drivestr[drive],@fs)<>-1)) then
  283. Diskfree:=int64(fs.bavail)*int64(fs.bsize)
  284. else
  285. Diskfree:=-1;
  286. End;
  287. Function DiskSize(Drive: Byte): int64;
  288. var
  289. fs : tstatfs;
  290. Begin
  291. if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (fpStatFS(fixdrivestr[drive],@fs)<>-1)) or
  292. ((not (drivestr[Drive]=nil)) and (fpStatFS(drivestr[drive],@fs)<>-1)) then
  293. DiskSize:=int64(fs.blocks)*int64(fs.bsize)
  294. else
  295. DiskSize:=-1;
  296. End;
  297. Procedure FreeDriveStr;
  298. var
  299. i: longint;
  300. begin
  301. for i:=low(drivestr) to high(drivestr) do
  302. if assigned(drivestr[i]) then
  303. begin
  304. freemem(drivestr[i]);
  305. drivestr[i]:=nil;
  306. end;
  307. end;
  308. {******************************************************************************
  309. --- Findfirst FindNext ---
  310. ******************************************************************************}
  311. Function FNMatch(const Pattern,Name:string):Boolean;
  312. Var
  313. LenPat,LenName : longint;
  314. Function DoFNMatch(i,j:longint):Boolean;
  315. Var
  316. Found : boolean;
  317. Begin
  318. Found:=true;
  319. While Found and (i<=LenPat) Do
  320. Begin
  321. Case Pattern[i] of
  322. '?' : Found:=(j<=LenName);
  323. '*' : Begin
  324. {find the next character in pattern, different of ? and *}
  325. while Found do
  326. begin
  327. inc(i);
  328. if i>LenPat then Break;
  329. case Pattern[i] of
  330. '*' : ;
  331. '?' : begin
  332. if j>LenName then begin DoFNMatch:=false; Exit; end;
  333. inc(j);
  334. end;
  335. else
  336. Found:=false;
  337. end;
  338. end;
  339. Assert((i>LenPat) or ( (Pattern[i]<>'*') and (Pattern[i]<>'?') ));
  340. {Now, find in name the character which i points to, if the * or ?
  341. wasn't the last character in the pattern, else, use up all the
  342. chars in name}
  343. Found:=false;
  344. if (i<=LenPat) then
  345. begin
  346. repeat
  347. {find a letter (not only first !) which maches pattern[i]}
  348. while (j<=LenName) and (name[j]<>pattern[i]) do
  349. inc (j);
  350. if (j<LenName) then
  351. begin
  352. if DoFnMatch(i+1,j+1) then
  353. begin
  354. i:=LenPat;
  355. j:=LenName;{we can stop}
  356. Found:=true;
  357. Break;
  358. end else
  359. inc(j);{We didn't find one, need to look further}
  360. end else
  361. if j=LenName then
  362. begin
  363. Found:=true;
  364. Break;
  365. end;
  366. { This 'until' condition must be j>LenName, not j>=LenName.
  367. That's because when we 'need to look further' and
  368. j = LenName then loop must not terminate. }
  369. until (j>LenName);
  370. end else
  371. begin
  372. j:=LenName;{we can stop}
  373. Found:=true;
  374. end;
  375. end;
  376. else {not a wildcard character in pattern}
  377. Found:=(j<=LenName) and (pattern[i]=name[j]);
  378. end;
  379. inc(i);
  380. inc(j);
  381. end;
  382. DoFnMatch:=Found and (j>LenName);
  383. end;
  384. Begin {start FNMatch}
  385. LenPat:=Length(Pattern);
  386. LenName:=Length(Name);
  387. FNMatch:=DoFNMatch(1,1);
  388. End;
  389. Const
  390. RtlFindSize = 15;
  391. Type
  392. RtlFindRecType = Record
  393. DirPtr : Pointer;
  394. SearchNum,
  395. LastUsed : LongInt;
  396. End;
  397. Var
  398. RtlFindRecs : Array[1..RtlFindSize] of RtlFindRecType;
  399. CurrSearchNum : LongInt;
  400. Procedure FindClose(Var f: SearchRec);
  401. {
  402. Closes dirptr if it is open
  403. }
  404. Var
  405. i : longint;
  406. Begin
  407. if f.SearchType=0 then
  408. begin
  409. i:=1;
  410. repeat
  411. if (RtlFindRecs[i].SearchNum=f.SearchNum) then
  412. break;
  413. inc(i);
  414. until (i>RtlFindSize);
  415. If i<=RtlFindSize Then
  416. Begin
  417. RtlFindRecs[i].SearchNum:=0;
  418. if f.dirptr<>nil then
  419. fpclosedir(pdir(f.dirptr)^);
  420. End;
  421. end;
  422. f.dirptr:=nil;
  423. End;
  424. Function FindGetFileInfo(const s:string;var f:SearchRec):boolean;
  425. var
  426. DT : DateTime;
  427. Info : RtlInfoType;
  428. st : baseunix.stat;
  429. begin
  430. FindGetFileInfo:=false;
  431. if not fpstat(s,st)>=0 then
  432. exit;
  433. info.FSize:=st.st_Size;
  434. info.FMTime:=st.st_mtime;
  435. if (st.st_mode and STAT_IFMT)=STAT_IFDIR then
  436. info.fmode:=$10
  437. else
  438. info.fmode:=$0;
  439. if (st.st_mode and STAT_IWUSR)=0 then
  440. info.fmode:=info.fmode or 1;
  441. if s[f.NamePos+1]='.' then
  442. info.fmode:=info.fmode or $2;
  443. If ((Info.FMode and Not(f.searchattr))=0) Then
  444. Begin
  445. f.Name:=Copy(s,f.NamePos+1,255);
  446. f.Attr:=Info.FMode;
  447. f.Size:=Info.FSize;
  448. f.mode:=st.st_mode;
  449. UnixDateToDT(Info.FMTime, DT);
  450. PackTime(DT,f.Time);
  451. FindGetFileInfo:=true;
  452. End;
  453. end;
  454. Function FindLastUsed: Longint;
  455. {
  456. Find unused or least recently used dirpointer slot in findrecs array
  457. }
  458. Var
  459. BestMatch,i : Longint;
  460. Found : Boolean;
  461. Begin
  462. BestMatch:=1;
  463. i:=1;
  464. Found:=False;
  465. While (i <= RtlFindSize) And (Not Found) Do
  466. Begin
  467. If (RtlFindRecs[i].SearchNum = 0) Then
  468. Begin
  469. BestMatch := i;
  470. Found := True;
  471. End
  472. Else
  473. Begin
  474. If RtlFindRecs[i].LastUsed > RtlFindRecs[BestMatch].LastUsed Then
  475. BestMatch := i;
  476. End;
  477. Inc(i);
  478. End;
  479. FindLastUsed := BestMatch;
  480. End;
  481. Procedure FindNext(Var f: SearchRec);
  482. {
  483. re-opens dir if not already in array and calls FindWorkProc
  484. }
  485. Var
  486. DirName : Array[0..256] of Char;
  487. i,
  488. ArrayPos : Longint;
  489. FName,
  490. SName : string;
  491. Found,
  492. Finished : boolean;
  493. p : pdirent;
  494. Begin
  495. If f.SearchType=0 Then
  496. Begin
  497. ArrayPos:=0;
  498. For i:=1 to RtlFindSize Do
  499. Begin
  500. If RtlFindRecs[i].SearchNum = f.SearchNum Then
  501. ArrayPos:=i;
  502. Inc(RtlFindRecs[i].LastUsed);
  503. End;
  504. If ArrayPos=0 Then
  505. Begin
  506. If f.NamePos = 0 Then
  507. Begin
  508. DirName[0] := '.';
  509. DirName[1] := '/';
  510. DirName[2] := #0;
  511. End
  512. Else
  513. Begin
  514. Move(f.SearchSpec[1], DirName[0], f.NamePos);
  515. DirName[f.NamePos] := #0;
  516. End;
  517. f.DirPtr := fpopendir(@DirName[0]);
  518. If f.DirPtr <> nil Then
  519. begin
  520. ArrayPos:=FindLastUsed;
  521. If RtlFindRecs[ArrayPos].SearchNum > 0 Then
  522. FpCloseDir((pdir(rtlfindrecs[arraypos].dirptr)^));
  523. RtlFindRecs[ArrayPos].SearchNum := f.SearchNum;
  524. RtlFindRecs[ArrayPos].DirPtr := f.DirPtr;
  525. if f.searchpos>0 then
  526. seekdir(pdir(f.dirptr), f.searchpos);
  527. end;
  528. End;
  529. if ArrayPos>0 then
  530. RtlFindRecs[ArrayPos].LastUsed:=0;
  531. end;
  532. {Main loop}
  533. SName:=Copy(f.SearchSpec,f.NamePos+1,255);
  534. Found:=False;
  535. Finished:=(f.dirptr=nil);
  536. While Not Finished Do
  537. Begin
  538. p:=fpreaddir(pdir(f.dirptr)^);
  539. if p=nil then
  540. FName:=''
  541. else
  542. FName:=Strpas(@p^.d_name[0]);
  543. If FName='' Then
  544. Finished:=True
  545. Else
  546. Begin
  547. If FNMatch(SName,FName) Then
  548. Begin
  549. Found:=FindGetFileInfo(Copy(f.SearchSpec,1,f.NamePos)+FName,f);
  550. if Found then
  551. Finished:=true;
  552. End;
  553. End;
  554. End;
  555. {Shutdown}
  556. If Found Then
  557. Begin
  558. f.searchpos:=telldir(pdir(f.dirptr));
  559. DosError:=0;
  560. End
  561. Else
  562. Begin
  563. FindClose(f);
  564. DosError:=18;
  565. End;
  566. End;
  567. Procedure FindFirst(Const Path: PathStr; Attr: Word; Var f: SearchRec);
  568. {
  569. opens dir and calls FindWorkProc
  570. }
  571. Begin
  572. fillchar(f,sizeof(f),0);
  573. if Path='' then
  574. begin
  575. DosError:=3;
  576. exit;
  577. end;
  578. {Create Info}
  579. f.SearchSpec := Path;
  580. {We always also search for readonly and archive, regardless of Attr:}
  581. f.SearchAttr := Attr or archive or readonly;
  582. f.SearchPos := 0;
  583. f.NamePos := Length(f.SearchSpec);
  584. while (f.NamePos>0) and (f.SearchSpec[f.NamePos]<>'/') do
  585. dec(f.NamePos);
  586. {Wildcards?}
  587. if (Pos('?',Path)=0) and (Pos('*',Path)=0) then
  588. begin
  589. if FindGetFileInfo(Path,f) then
  590. DosError:=0
  591. else
  592. begin
  593. { According to tdos2 test it should return 18
  594. if ErrNo=Sys_ENOENT then
  595. DosError:=3
  596. else }
  597. DosError:=18;
  598. end;
  599. f.DirPtr:=nil;
  600. f.SearchType:=1;
  601. f.searchnum:=-1;
  602. end
  603. else
  604. {Find Entry}
  605. begin
  606. Inc(CurrSearchNum);
  607. f.SearchNum:=CurrSearchNum;
  608. f.SearchType:=0;
  609. FindNext(f);
  610. end;
  611. End;
  612. {******************************************************************************
  613. --- File ---
  614. ******************************************************************************}
  615. Function FSearch(path : pathstr;dirlist : string) : pathstr;
  616. Var
  617. info : BaseUnix.stat;
  618. Begin
  619. if (length(Path)>0) and (path[1]='/') and (fpStat(path,info)>=0) and (not fpS_ISDIR(Info.st_Mode)) then
  620. FSearch:=path
  621. else
  622. FSearch:=Unix.FSearch(path,dirlist);
  623. End;
  624. Procedure GetFAttr(var f; var attr : word);
  625. Var
  626. info : baseunix.stat;
  627. LinAttr : longint;
  628. p : pchar;
  629. {$ifndef FPC_ANSI_TEXTFILEREC}
  630. r : RawByteString;
  631. {$endif not FPC_ANSI_TEXTFILEREC}
  632. Begin
  633. DosError:=0;
  634. {$ifdef FPC_ANSI_TEXTFILEREC}
  635. { encoding is already correct }
  636. p:=@textrec(f).name;
  637. {$else}
  638. r:=ToSingleByteFileSystemEncodedFileName(textrec(f).name);
  639. p:=pchar(r);
  640. {$endif}
  641. { use the pchar rather than the rawbytestring version so that we don't check
  642. a second time whether the string needs to be converted to the right code
  643. page
  644. }
  645. if FPStat(p,info)<0 then
  646. begin
  647. Attr:=0;
  648. DosError:=3;
  649. exit;
  650. end
  651. else
  652. LinAttr:=Info.st_Mode;
  653. if fpS_ISDIR(LinAttr) then
  654. Attr:=$10
  655. else
  656. Attr:=$0;
  657. if fpAccess(p,W_OK)<0 then
  658. Attr:=Attr or $1;
  659. if filerec(f).name[0]='.' then
  660. Attr:=Attr or $2;
  661. end;
  662. Procedure getftime (var f; var time : longint);
  663. Var
  664. Info: baseunix.stat;
  665. DT: DateTime;
  666. Begin
  667. doserror:=0;
  668. if fpfstat(filerec(f).handle,info)<0 then
  669. begin
  670. Time:=0;
  671. doserror:=6;
  672. exit
  673. end
  674. else
  675. UnixDateToDT(Info.st_mTime,DT);
  676. PackTime(DT,Time);
  677. End;
  678. Procedure setftime(var f; time : longint);
  679. Var
  680. utim: utimbuf;
  681. DT: DateTime;
  682. p : pchar;
  683. {$ifndef FPC_ANSI_TEXTFILEREC}
  684. r : Rawbytestring;
  685. {$endif not FPC_ANSI_TEXTFILEREC}
  686. Begin
  687. doserror:=0;
  688. with utim do
  689. begin
  690. actime:=fptime;
  691. UnPackTime(Time,DT);
  692. modtime:=DTToUnixDate(DT);
  693. end;
  694. {$ifdef FPC_ANSI_TEXTFILEREC}
  695. { encoding is already correct }
  696. p:=@textrec(f).name;
  697. {$else}
  698. r:=ToSingleByteFileSystemEncodedFileName(textrec(f).name);
  699. p:=pchar(r);
  700. {$endif}
  701. { use the pchar rather than the rawbytestring version so that we don't check
  702. a second time whether the string needs to be converted to the right code
  703. page
  704. }
  705. if fputime(p,@utim)<0 then
  706. begin
  707. Time:=0;
  708. doserror:=3;
  709. end;
  710. End;
  711. {******************************************************************************
  712. --- Environment ---
  713. ******************************************************************************}
  714. Function EnvCount: Longint;
  715. var
  716. envcnt : longint;
  717. p : ppchar;
  718. Begin
  719. envcnt:=0;
  720. p:=envp; {defined in syslinux}
  721. while (p^<>nil) do
  722. begin
  723. inc(envcnt);
  724. inc(p);
  725. end;
  726. EnvCount := envcnt
  727. End;
  728. Function EnvStr (Index: longint): String;
  729. Var
  730. i : longint;
  731. p : ppchar;
  732. Begin
  733. if Index <= 0 then
  734. envstr:=''
  735. else
  736. begin
  737. p:=envp; {defined in syslinux}
  738. i:=1;
  739. while (i<Index) and (p^<>nil) do
  740. begin
  741. inc(i);
  742. inc(p);
  743. end;
  744. if p=nil then
  745. envstr:=''
  746. else
  747. envstr:=strpas(p^)
  748. end;
  749. end;
  750. Function GetEnv(EnvVar: String): String;
  751. var
  752. p : pchar;
  753. Begin
  754. p:=BaseUnix.fpGetEnv(EnvVar);
  755. if p=nil then
  756. GetEnv:=''
  757. else
  758. GetEnv:=StrPas(p);
  759. End;
  760. Procedure setfattr (var f;attr : word);
  761. Begin
  762. {! No Unix equivalent !}
  763. { Fail for setting VolumeId }
  764. if (attr and VolumeID)<>0 then
  765. doserror:=5;
  766. End;
  767. {******************************************************************************
  768. --- Initialization ---
  769. ******************************************************************************}
  770. Finalization
  771. FreeDriveStr;
  772. End.