dos.pp 20 KB

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