dos.pp 21 KB

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