dos.pp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128
  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. {Max FileName Length for files}
  16. FileNameLen=255;
  17. Type
  18. SearchRec =
  19. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  20. packed
  21. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  22. Record
  23. {Fill : array[1..21] of byte; Fill replaced with below}
  24. SearchNum : LongInt; {to track which search this is}
  25. SearchPos : LongInt; {directory position}
  26. DirPtr : Pointer; {directory pointer for reading directory}
  27. SearchType : Byte; {0=normal, 1=open will close, 2=only 1 file}
  28. SearchAttr : Byte; {attribute we are searching for}
  29. Fill : Array[1..07] 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. {$ifdef cpui386}
  40. Registers = packed record
  41. case i : integer of
  42. 0 : (ax,f1,bx,f2,cx,f3,dx,f4,bp,f5,si,f51,di,f6,ds,f7,es,f8,flags,fs,gs : word);
  43. 1 : (al,ah,f9,f10,bl,bh,f11,f12,cl,ch,f13,f14,dl,dh : byte);
  44. 2 : (eax, ebx, ecx, edx, ebp, esi, edi : longint);
  45. End;
  46. {$endif cpui386}
  47. {$i dosh.inc}
  48. {Extra Utils}
  49. function weekday(y,m,d : longint) : longint;
  50. Procedure UnixDateToDt(SecsPast: LongInt; Var Dt: DateTime);
  51. Function DTToUnixDate(DT: DateTime): LongInt;
  52. {Disk}
  53. Procedure AddDisk(const path:string);
  54. Implementation
  55. Uses
  56. Strings,Unix,BaseUnix,{$ifdef FPC_USE_LIBC}initc{$ELSE}Syscall{$ENDIF};
  57. {$ifndef FPC_USE_LIBC}
  58. {$i sysnr.inc}
  59. {$endif}
  60. {$i settimeo.inc}
  61. {******************************************************************************
  62. --- Link C Lib if set ---
  63. ******************************************************************************}
  64. type
  65. RtlInfoType = Record
  66. FMode,
  67. FInode,
  68. FUid,
  69. FGid,
  70. FSize,
  71. FMTime : LongInt;
  72. End;
  73. {******************************************************************************
  74. --- Info / Date / Time ---
  75. ******************************************************************************}
  76. Const
  77. {Date Calculation}
  78. C1970 = 2440588;
  79. D0 = 1461;
  80. D1 = 146097;
  81. D2 = 1721119;
  82. type
  83. GTRec = packed Record
  84. Year,
  85. Month,
  86. MDay,
  87. WDay,
  88. Hour,
  89. Minute,
  90. Second : Word;
  91. End;
  92. Function GregorianToJulian(Year,Month,Day:Longint):LongInt;
  93. Var
  94. Century,XYear: LongInt;
  95. Begin
  96. If Month<=2 Then
  97. Begin
  98. Dec(Year);
  99. Inc(Month,12);
  100. End;
  101. Dec(Month,3);
  102. Century:=(longint(Year Div 100)*D1) shr 2;
  103. XYear:=(longint(Year Mod 100)*D0) shr 2;
  104. GregorianToJulian:=((((Month*153)+2) div 5)+Day)+D2+XYear+Century;
  105. End;
  106. Function LocalToEpoch(year,month,day,hour,minute,second:Word):Longint;
  107. {
  108. Transforms local time (year,month,day,hour,minutes,second) to Epoch time
  109. (seconds since 00:00, january 1 1970, corrected for local time zone)
  110. }
  111. Begin
  112. LocalToEpoch:=((GregorianToJulian(Year,Month,Day)-c1970)*86400)+
  113. (LongInt(Hour)*3600)+(Longint(Minute)*60)+Second-TZSeconds;
  114. End;
  115. Procedure JulianToGregorian(JulianDN:LongInt;Var Year,Month,Day:Word);
  116. Var
  117. YYear,XYear,Temp,TempMonth : LongInt;
  118. Begin
  119. Temp:=((JulianDN-D2) shl 2)-1;
  120. JulianDN:=Temp Div D1;
  121. XYear:=(Temp Mod D1) or 3;
  122. YYear:=(XYear Div D0);
  123. Temp:=((((XYear mod D0)+4) shr 2)*5)-3;
  124. Day:=((Temp Mod 153)+5) Div 5;
  125. TempMonth:=Temp Div 153;
  126. If TempMonth>=10 Then
  127. Begin
  128. inc(YYear);
  129. dec(TempMonth,12);
  130. End;
  131. inc(TempMonth,3);
  132. Month := TempMonth;
  133. Year:=YYear+(JulianDN*100);
  134. end;
  135. Procedure EpochToLocal(epoch:longint;var year,month,day,hour,minute,second:Word);
  136. {
  137. Transforms Epoch time into local time (hour, minute,seconds)
  138. }
  139. Var
  140. DateNum: LongInt;
  141. Begin
  142. inc(Epoch,TZSeconds);
  143. Datenum:=(Epoch Div 86400) + c1970;
  144. JulianToGregorian(DateNum,Year,Month,day);
  145. Epoch:=Abs(Epoch Mod 86400);
  146. Hour:=Epoch Div 3600;
  147. Epoch:=Epoch Mod 3600;
  148. Minute:=Epoch Div 60;
  149. Second:=Epoch Mod 60;
  150. End;
  151. Function DosVersion:Word;
  152. Var
  153. Buffer : Array[0..255] of Char;
  154. Tmp2,
  155. TmpStr : String[40];
  156. TmpPos,
  157. SubRel,
  158. Rel : LongInt;
  159. info : utsname;
  160. Begin
  161. FPUName(info);
  162. Move(info.release,buffer[0],40);
  163. TmpStr:=StrPas(Buffer);
  164. SubRel:=0;
  165. TmpPos:=Pos('.',TmpStr);
  166. if TmpPos>0 then
  167. begin
  168. Tmp2:=Copy(TmpStr,TmpPos+1,40);
  169. Delete(TmpStr,TmpPos,40);
  170. end;
  171. TmpPos:=Pos('.',Tmp2);
  172. if TmpPos>0 then
  173. Delete(Tmp2,TmpPos,40);
  174. Val(TmpStr,Rel);
  175. Val(Tmp2,SubRel);
  176. DosVersion:=Rel+(SubRel shl 8);
  177. End;
  178. function WeekDay (y,m,d:longint):longint;
  179. {
  180. Calculates th day of the week. returns -1 on error
  181. }
  182. var
  183. u,v : longint;
  184. begin
  185. if (m<1) or (m>12) or (y<1600) or (y>4000) or
  186. (d<1) or (d>30+((m+ord(m>7)) and 1)-ord(m=2)) or
  187. ((m*d=58) and (((y mod 4>0) or (y mod 100=0)) and (y mod 400>0))) then
  188. WeekDay:=-1
  189. else
  190. begin
  191. u:=m;
  192. v:=y;
  193. if m<3 then
  194. begin
  195. inc(u,12);
  196. dec(v);
  197. end;
  198. WeekDay:=(d+2*u+((3*(u+1)) div 5)+v+(v div 4)-(v div 100)+(v div 400)+1) mod 7;
  199. end;
  200. end;
  201. Procedure GetDate(Var Year, Month, MDay, WDay: Word);
  202. var
  203. tz:timeval;
  204. hour,min,sec : word;
  205. begin
  206. fpgettimeofday(@tz,nil);
  207. EpochToLocal(tz.tv_sec,year,month,mday,hour,min,sec);
  208. Wday:=weekday(Year,Month,MDay);
  209. end;
  210. procedure SetTime(Hour,Minute,Second,sec100:word);
  211. var
  212. dow,Year, Month, Day : Word;
  213. tv : timeval;
  214. begin
  215. GetDate (Year, Month, Day,dow);
  216. tv.tv_sec:= LocalToEpoch ( Year, Month, Day, Hour, Minute, Second ) ;
  217. Settimeofday(@tv,nil);
  218. end;
  219. procedure SetDate(Year,Month,Day:Word);
  220. var
  221. Hour, Min, Sec, Sec100 : Word;
  222. tv : timeval;
  223. begin
  224. GetTime ( Hour, Min, Sec, Sec100 );
  225. tv.tv_sec:= LocalToEpoch ( Year, Month, Day, Hour, Min, Sec ) ;
  226. Settimeofday(@tv,nil);
  227. end;
  228. Function SetDateTime(Year,Month,Day,hour,minute,second:Word) : Boolean;
  229. var
  230. tv : timeval;
  231. begin
  232. tv.tv_sec:= LocalToEpoch ( Year, Month, Day, Hour, Minute, Second ) ;
  233. SetDatetime:=Settimeofday(@tv,nil)=0;
  234. end;
  235. Procedure GetTime(Var Hour, Minute, Second, Sec100: Word);
  236. var
  237. tz:timeval;
  238. year,month,day : word;
  239. begin
  240. fpgettimeofday(@tz,nil);
  241. EpochToLocal(tz.tv_sec,year,month,day,hour,minute,second);
  242. sec100:=tz.tv_usec div 10000;
  243. end;
  244. Procedure packtime(var t : datetime;var p : longint);
  245. Begin
  246. 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);
  247. End;
  248. Procedure unpacktime(p : longint;var t : datetime);
  249. Begin
  250. t.sec:=(p and 31) shl 1;
  251. t.min:=(p shr 5) and 63;
  252. t.hour:=(p shr 11) and 31;
  253. t.day:=(p shr 16) and 31;
  254. t.month:=(p shr 21) and 15;
  255. t.year:=(p shr 25)+1980;
  256. End;
  257. Procedure UnixDateToDt(SecsPast: LongInt; Var Dt: DateTime);
  258. Begin
  259. EpochToLocal(SecsPast,dt.Year,dt.Month,dt.Day,dt.Hour,dt.Min,dt.Sec);
  260. End;
  261. Function DTToUnixDate(DT: DateTime): LongInt;
  262. Begin
  263. DTToUnixDate:=LocalToEpoch(dt.Year,dt.Month,dt.Day,dt.Hour,dt.Min,dt.Sec);
  264. End;
  265. {******************************************************************************
  266. --- Exec ---
  267. ******************************************************************************}
  268. Procedure FSplit( Path:PathStr;Var Dir:DirStr;Var Name:NameStr;Var Ext:ExtStr);
  269. Var
  270. DotPos,SlashPos,i : longint;
  271. Begin
  272. SlashPos:=0;
  273. DotPos:=256;
  274. i:=Length(Path);
  275. While (i>0) and (SlashPos=0) Do
  276. Begin
  277. If (DotPos=256) and (Path[i]='.') Then
  278. begin
  279. DotPos:=i;
  280. end;
  281. If (Path[i]='/') Then
  282. SlashPos:=i;
  283. Dec(i);
  284. End;
  285. Ext:=Copy(Path,DotPos,255);
  286. Dir:=Copy(Path,1,SlashPos);
  287. Name:=Copy(Path,SlashPos + 1,DotPos - SlashPos - 1);
  288. End;
  289. {$ifdef HASTHREADVAR}
  290. {$ifdef VER1_9_2}
  291. var
  292. {$else VER1_9_2}
  293. threadvar
  294. {$endif VER1_9_2}
  295. {$else HASTHREADVAR}
  296. var
  297. {$endif HASTHREADVAR}
  298. LastDosExitCode: word;
  299. Procedure Exec (Const Path: PathStr; Const ComLine: ComStr);
  300. var
  301. pid : longint; // pid_t?
  302. cmdline2 : ppchar;
  303. commandline : ansistring;
  304. realpath : ansistring;
  305. // The Error-Checking in the previous Version failed, since halt($7F) gives an WaitPid-status of $7F00
  306. Begin
  307. LastDosExitCode:=0;
  308. pid:=fpFork;
  309. if pid=0 then
  310. begin
  311. cmdline2:=nil;
  312. realpath:=path;
  313. if Comline<>'' Then
  314. begin
  315. CommandLine:=ComLine; // conversion must live till after fpexec!
  316. cmdline2:=StringtoPPChar(CommandLine,1);
  317. cmdline2^:=pchar(realPath);
  318. end
  319. else
  320. begin
  321. getmem(cmdline2,2*sizeof(pchar));
  322. cmdline2^:=pchar(realPath);
  323. cmdline2[1]:=nil;
  324. end;
  325. {The child does the actual exec, and then exits}
  326. fpExecv(pchar(realPath),cmdline2);
  327. {If the execve fails, we return an exitvalue of 127, to let it be known}
  328. fpExit(127);
  329. end
  330. else
  331. if pid=-1 then {Fork failed}
  332. begin
  333. DosError:=8;
  334. exit
  335. end;
  336. {We're in the parent, let's wait.}
  337. LastDosExitCode:=WaitProcess(pid); // WaitPid and result-convert
  338. if (LastDosExitCode>=0) and (LastDosExitCode<>127) then
  339. DosError:=0
  340. else
  341. DosError:=8; // perhaps one time give an better error
  342. End;
  343. Function DosExitCode: Word;
  344. Begin
  345. DosExitCode:=LastDosExitCode;
  346. End;
  347. {******************************************************************************
  348. --- Disk ---
  349. ******************************************************************************}
  350. {
  351. The Diskfree and Disksize functions need a file on the specified drive, since this
  352. is required for the statfs system call.
  353. These filenames are set in drivestr[0..26], and have been preset to :
  354. 0 - '.' (default drive - hence current dir is ok.)
  355. 1 - '/fd0/.' (floppy drive 1 - should be adapted to local system )
  356. 2 - '/fd1/.' (floppy drive 2 - should be adapted to local system )
  357. 3 - '/' (C: equivalent of dos is the root partition)
  358. 4..26 (can be set by you're own applications)
  359. ! Use AddDisk() to Add new drives !
  360. They both return -1 when a failure occurs.
  361. }
  362. Const
  363. FixDriveStr : array[0..3] of pchar=(
  364. '.',
  365. '/fd0/.',
  366. '/fd1/.',
  367. '/.'
  368. );
  369. const
  370. Drives : byte = 4;
  371. var
  372. DriveStr : array[4..26] of pchar;
  373. Procedure AddDisk(const path:string);
  374. begin
  375. if not (DriveStr[Drives]=nil) then
  376. FreeMem(DriveStr[Drives],StrLen(DriveStr[Drives])+1);
  377. GetMem(DriveStr[Drives],length(Path)+1);
  378. StrPCopy(DriveStr[Drives],path);
  379. inc(Drives);
  380. if Drives>26 then
  381. Drives:=4;
  382. end;
  383. Function DiskFree(Drive: Byte): int64;
  384. var
  385. fs : tstatfs;
  386. Begin
  387. if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (StatFS(fixdrivestr[drive],fs)<>-1)) or
  388. ((not (drivestr[Drive]=nil)) and (StatFS(drivestr[drive],fs)<>-1)) then
  389. Diskfree:=int64(fs.bavail)*int64(fs.bsize)
  390. else
  391. Diskfree:=-1;
  392. End;
  393. Function DiskSize(Drive: Byte): int64;
  394. var
  395. fs : tstatfs;
  396. Begin
  397. if ((Drive<4) and (not (fixdrivestr[Drive]=nil)) and (StatFS(fixdrivestr[drive],fs)<>-1)) or
  398. ((not (drivestr[Drive]=nil)) and (StatFS(drivestr[drive],fs)<>-1)) then
  399. DiskSize:=int64(fs.blocks)*int64(fs.bsize)
  400. else
  401. DiskSize:=-1;
  402. End;
  403. {******************************************************************************
  404. --- Findfirst FindNext ---
  405. ******************************************************************************}
  406. Function FNMatch(const Pattern,Name:string):Boolean;
  407. Var
  408. LenPat,LenName : longint;
  409. Function DoFNMatch(i,j:longint):Boolean;
  410. Var
  411. Found : boolean;
  412. Begin
  413. Found:=true;
  414. While Found and (i<=LenPat) Do
  415. Begin
  416. Case Pattern[i] of
  417. '?' : Found:=(j<=LenName);
  418. '*' : Begin
  419. {find the next character in pattern, different of ? and *}
  420. while Found do
  421. begin
  422. inc(i);
  423. if i>LenPat then Break;
  424. case Pattern[i] of
  425. '*' : ;
  426. '?' : begin
  427. if j>LenName then begin DoFNMatch:=false; Exit; end;
  428. inc(j);
  429. end;
  430. else
  431. Found:=false;
  432. end;
  433. end;
  434. Assert((i>LenPat) or ( (Pattern[i]<>'*') and (Pattern[i]<>'?') ));
  435. {Now, find in name the character which i points to, if the * or ?
  436. wasn't the last character in the pattern, else, use up all the
  437. chars in name}
  438. Found:=false;
  439. if (i<=LenPat) then
  440. begin
  441. repeat
  442. {find a letter (not only first !) which maches pattern[i]}
  443. while (j<=LenName) and (name[j]<>pattern[i]) do
  444. inc (j);
  445. if (j<LenName) then
  446. begin
  447. if DoFnMatch(i+1,j+1) then
  448. begin
  449. i:=LenPat;
  450. j:=LenName;{we can stop}
  451. Found:=true;
  452. Break;
  453. end else
  454. inc(j);{We didn't find one, need to look further}
  455. end else
  456. if j=LenName then
  457. begin
  458. Found:=true;
  459. Break;
  460. end;
  461. { This 'until' condition must be j>LenName, not j>=LenName.
  462. That's because when we 'need to look further' and
  463. j = LenName then loop must not terminate. }
  464. until (j>LenName);
  465. end else
  466. begin
  467. j:=LenName;{we can stop}
  468. Found:=true;
  469. end;
  470. end;
  471. else {not a wildcard character in pattern}
  472. Found:=(j<=LenName) and (pattern[i]=name[j]);
  473. end;
  474. inc(i);
  475. inc(j);
  476. end;
  477. DoFnMatch:=Found and (j>LenName);
  478. end;
  479. Begin {start FNMatch}
  480. LenPat:=Length(Pattern);
  481. LenName:=Length(Name);
  482. FNMatch:=DoFNMatch(1,1);
  483. End;
  484. Const
  485. RtlFindSize = 15;
  486. Type
  487. RtlFindRecType = Record
  488. DirPtr : Pointer;
  489. SearchNum,
  490. LastUsed : LongInt;
  491. End;
  492. Var
  493. RtlFindRecs : Array[1..RtlFindSize] of RtlFindRecType;
  494. CurrSearchNum : LongInt;
  495. Procedure FindClose(Var f: SearchRec);
  496. {
  497. Closes dirptr if it is open
  498. }
  499. Var
  500. i : longint;
  501. Begin
  502. if f.SearchType=0 then
  503. begin
  504. i:=1;
  505. repeat
  506. if (RtlFindRecs[i].SearchNum=f.SearchNum) then
  507. break;
  508. inc(i);
  509. until (i>RtlFindSize);
  510. If i<=RtlFindSize Then
  511. Begin
  512. RtlFindRecs[i].SearchNum:=0;
  513. if f.dirptr<>nil then
  514. fpclosedir(pdir(f.dirptr)^);
  515. End;
  516. end;
  517. f.dirptr:=nil;
  518. End;
  519. Function FindGetFileInfo(const s:string;var f:SearchRec):boolean;
  520. var
  521. DT : DateTime;
  522. Info : RtlInfoType;
  523. st : baseunix.stat;
  524. begin
  525. FindGetFileInfo:=false;
  526. if not fpstat(s,st)>=0 then
  527. exit;
  528. info.FSize:=st.st_Size;
  529. info.FMTime:=st.st_mtime;
  530. if (st.st_mode and STAT_IFMT)=STAT_IFDIR then
  531. info.fmode:=$10
  532. else
  533. info.fmode:=$0;
  534. if (st.st_mode and STAT_IWUSR)=0 then
  535. info.fmode:=info.fmode or 1;
  536. if s[f.NamePos+1]='.' then
  537. info.fmode:=info.fmode or $2;
  538. If ((Info.FMode and Not(f.searchattr))=0) Then
  539. Begin
  540. f.Name:=Copy(s,f.NamePos+1,255);
  541. f.Attr:=Info.FMode;
  542. f.Size:=Info.FSize;
  543. UnixDateToDT(Info.FMTime, DT);
  544. PackTime(DT,f.Time);
  545. FindGetFileInfo:=true;
  546. End;
  547. end;
  548. Function FindLastUsed: Longint;
  549. {
  550. Find unused or least recently used dirpointer slot in findrecs array
  551. }
  552. Var
  553. BestMatch,i : Longint;
  554. Found : Boolean;
  555. Begin
  556. BestMatch:=1;
  557. i:=1;
  558. Found:=False;
  559. While (i <= RtlFindSize) And (Not Found) Do
  560. Begin
  561. If (RtlFindRecs[i].SearchNum = 0) Then
  562. Begin
  563. BestMatch := i;
  564. Found := True;
  565. End
  566. Else
  567. Begin
  568. If RtlFindRecs[i].LastUsed > RtlFindRecs[BestMatch].LastUsed Then
  569. BestMatch := i;
  570. End;
  571. Inc(i);
  572. End;
  573. FindLastUsed := BestMatch;
  574. End;
  575. Procedure FindNext(Var f: SearchRec);
  576. {
  577. re-opens dir if not already in array and calls FindWorkProc
  578. }
  579. Var
  580. DirName : Array[0..256] of Char;
  581. i,
  582. ArrayPos : Longint;
  583. FName,
  584. SName : string;
  585. Found,
  586. Finished : boolean;
  587. p : pdirent;
  588. Begin
  589. If f.SearchType=0 Then
  590. Begin
  591. ArrayPos:=0;
  592. For i:=1 to RtlFindSize Do
  593. Begin
  594. If RtlFindRecs[i].SearchNum = f.SearchNum Then
  595. ArrayPos:=i;
  596. Inc(RtlFindRecs[i].LastUsed);
  597. End;
  598. If ArrayPos=0 Then
  599. Begin
  600. If f.NamePos = 0 Then
  601. Begin
  602. DirName[0] := '.';
  603. DirName[1] := '/';
  604. DirName[2] := #0;
  605. End
  606. Else
  607. Begin
  608. Move(f.SearchSpec[1], DirName[0], f.NamePos);
  609. DirName[f.NamePos] := #0;
  610. End;
  611. f.DirPtr := fpopendir(@(DirName));
  612. If f.DirPtr <> nil Then
  613. begin
  614. ArrayPos:=FindLastUsed;
  615. If RtlFindRecs[ArrayPos].SearchNum > 0 Then
  616. FpCloseDir((pdir(rtlfindrecs[arraypos].dirptr)^));
  617. RtlFindRecs[ArrayPos].SearchNum := f.SearchNum;
  618. RtlFindRecs[ArrayPos].DirPtr := f.DirPtr;
  619. if f.searchpos>0 then
  620. seekdir(pdir(f.dirptr), f.searchpos);
  621. end;
  622. End;
  623. if ArrayPos>0 then
  624. RtlFindRecs[ArrayPos].LastUsed:=0;
  625. end;
  626. {Main loop}
  627. SName:=Copy(f.SearchSpec,f.NamePos+1,255);
  628. Found:=False;
  629. Finished:=(f.dirptr=nil);
  630. While Not Finished Do
  631. Begin
  632. p:=fpreaddir(pdir(f.dirptr)^);
  633. if p=nil then
  634. FName:=''
  635. else
  636. FName:=Strpas(@p^.d_name);
  637. If FName='' Then
  638. Finished:=True
  639. Else
  640. Begin
  641. If FNMatch(SName,FName) Then
  642. Begin
  643. Found:=FindGetFileInfo(Copy(f.SearchSpec,1,f.NamePos)+FName,f);
  644. if Found then
  645. Finished:=true;
  646. End;
  647. End;
  648. End;
  649. {Shutdown}
  650. If Found Then
  651. Begin
  652. f.searchpos:=telldir(pdir(f.dirptr));
  653. DosError:=0;
  654. End
  655. Else
  656. Begin
  657. FindClose(f);
  658. DosError:=18;
  659. End;
  660. End;
  661. Procedure FindFirst(Const Path: PathStr; Attr: Word; Var f: SearchRec);
  662. {
  663. opens dir and calls FindWorkProc
  664. }
  665. Begin
  666. fillchar(f,sizeof(f),0);
  667. if Path='' then
  668. begin
  669. DosError:=3;
  670. exit;
  671. end;
  672. {Create Info}
  673. f.SearchSpec := Path;
  674. {We always also search for readonly and archive, regardless of Attr:}
  675. f.SearchAttr := Attr or archive or readonly;
  676. f.SearchPos := 0;
  677. f.NamePos := Length(f.SearchSpec);
  678. while (f.NamePos>0) and (f.SearchSpec[f.NamePos]<>'/') do
  679. dec(f.NamePos);
  680. {Wildcards?}
  681. if (Pos('?',Path)=0) and (Pos('*',Path)=0) then
  682. begin
  683. if FindGetFileInfo(Path,f) then
  684. DosError:=0
  685. else
  686. begin
  687. { According to tdos2 test it should return 18
  688. if ErrNo=Sys_ENOENT then
  689. DosError:=3
  690. else }
  691. DosError:=18;
  692. end;
  693. f.DirPtr:=nil;
  694. f.SearchType:=1;
  695. f.searchnum:=-1;
  696. end
  697. else
  698. {Find Entry}
  699. begin
  700. Inc(CurrSearchNum);
  701. f.SearchNum:=CurrSearchNum;
  702. f.SearchType:=0;
  703. FindNext(f);
  704. end;
  705. End;
  706. {******************************************************************************
  707. --- File ---
  708. ******************************************************************************}
  709. {$DEFINE FPC_FEXPAND_TILDE} { Tilde is expanded to home }
  710. {$DEFINE FPC_FEXPAND_GETENVPCHAR} { GetEnv result is a PChar }
  711. {$I fexpand.inc}
  712. {$UNDEF FPC_FEXPAND_GETENVPCHAR}
  713. {$UNDEF FPC_FEXPAND_TILDE}
  714. Function FSearch(path : pathstr;dirlist : string) : pathstr;
  715. Var
  716. info : BaseUnix.stat;
  717. Begin
  718. if (length(Path)>0) and (path[1]='/') and (fpStat(path,info)>=0) then
  719. FSearch:=path
  720. else
  721. FSearch:=Unix.FSearch(path,dirlist);
  722. End;
  723. Procedure GetFAttr(var f; var attr : word);
  724. Var
  725. info : baseunix.stat;
  726. LinAttr : longint;
  727. Begin
  728. DosError:=0;
  729. if FPStat(@textrec(f).name,info)<0 then
  730. begin
  731. Attr:=0;
  732. DosError:=3;
  733. exit;
  734. end
  735. else
  736. LinAttr:=Info.st_Mode;
  737. if fpS_ISDIR(LinAttr) then
  738. Attr:=$10
  739. else
  740. Attr:=$0;
  741. if fpAccess(@textrec(f).name,W_OK)<0 then
  742. Attr:=Attr or $1;
  743. if filerec(f).name[0]='.' then
  744. Attr:=Attr or $2;
  745. end;
  746. Procedure getftime (var f; var time : longint);
  747. Var
  748. Info: baseunix.stat;
  749. DT: DateTime;
  750. Begin
  751. doserror:=0;
  752. if fpfstat(filerec(f).handle,info)<0 then
  753. begin
  754. Time:=0;
  755. doserror:=6;
  756. exit
  757. end
  758. else
  759. UnixDateToDT(Info.st_mTime,DT);
  760. PackTime(DT,Time);
  761. End;
  762. Procedure setftime(var f; time : longint);
  763. Var
  764. utim: utimbuf;
  765. DT: DateTime;
  766. Begin
  767. doserror:=0;
  768. with utim do
  769. begin
  770. actime:=fptime;
  771. UnPackTime(Time,DT);
  772. modtime:=DTToUnixDate(DT);
  773. end;
  774. if fputime(@filerec(f).name,@utim)<0 then
  775. begin
  776. Time:=0;
  777. doserror:=3;
  778. end;
  779. End;
  780. {******************************************************************************
  781. --- Environment ---
  782. ******************************************************************************}
  783. Function EnvCount: Longint;
  784. var
  785. envcnt : longint;
  786. p : ppchar;
  787. Begin
  788. envcnt:=0;
  789. p:=envp; {defined in syslinux}
  790. while (p^<>nil) do
  791. begin
  792. inc(envcnt);
  793. inc(p);
  794. end;
  795. EnvCount := envcnt
  796. End;
  797. Function EnvStr (Index: longint): String;
  798. Var
  799. i : longint;
  800. p : ppchar;
  801. Begin
  802. if Index <= 0 then
  803. envstr:=''
  804. else
  805. begin
  806. p:=envp; {defined in syslinux}
  807. i:=1;
  808. while (i<Index) and (p^<>nil) do
  809. begin
  810. inc(i);
  811. inc(p);
  812. end;
  813. if p=nil then
  814. envstr:=''
  815. else
  816. envstr:=strpas(p^)
  817. end;
  818. end;
  819. Function GetEnv(EnvVar: String): String;
  820. var
  821. p : pchar;
  822. Begin
  823. p:=BaseUnix.fpGetEnv(EnvVar);
  824. if p=nil then
  825. GetEnv:=''
  826. else
  827. GetEnv:=StrPas(p);
  828. End;
  829. {******************************************************************************
  830. --- Do Nothing Procedures/Functions ---
  831. ******************************************************************************}
  832. {$ifdef cpui386}
  833. Procedure Intr (intno: byte; var regs: registers);
  834. Begin
  835. {! No Unix equivalent !}
  836. End;
  837. Procedure msdos(var regs : registers);
  838. Begin
  839. {! No Unix equivalent !}
  840. End;
  841. {$endif cpui386}
  842. Procedure getintvec(intno : byte;var vector : pointer);
  843. Begin
  844. {! No Unix equivalent !}
  845. End;
  846. Procedure setintvec(intno : byte;vector : pointer);
  847. Begin
  848. {! No Unix equivalent !}
  849. End;
  850. Procedure SwapVectors;
  851. Begin
  852. {! No Unix equivalent !}
  853. End;
  854. Procedure keep(exitcode : word);
  855. Begin
  856. {! No Unix equivalent !}
  857. End;
  858. Procedure setfattr (var f;attr : word);
  859. Begin
  860. {! No Unix equivalent !}
  861. { Fail for setting VolumeId }
  862. if (attr and VolumeID)<>0 then
  863. doserror:=5;
  864. End;
  865. Procedure GetCBreak(Var BreakValue: Boolean);
  866. Begin
  867. {! No Unix equivalent !}
  868. breakvalue:=true
  869. End;
  870. Procedure SetCBreak(BreakValue: Boolean);
  871. Begin
  872. {! No Unix equivalent !}
  873. End;
  874. Procedure GetVerify(Var Verify: Boolean);
  875. Begin
  876. {! No Unix equivalent !}
  877. Verify:=true;
  878. End;
  879. Procedure SetVerify(Verify: Boolean);
  880. Begin
  881. {! No Unix equivalent !}
  882. End;
  883. function GetShortName(var p : String) : boolean;
  884. begin
  885. { short=long under *nix}
  886. GetShortName:=True;
  887. end;
  888. function GetLongName(var p : String) : boolean;
  889. begin
  890. { short=long under *nix}
  891. GetLongName:=True;
  892. end;
  893. {******************************************************************************
  894. --- Initialization ---
  895. ******************************************************************************}
  896. End.
  897. {
  898. $Log$
  899. Revision 1.38 2004-10-31 17:11:52 marco
  900. * FPC_USE_LIBC fixes
  901. Revision 1.37 2004/10/31 16:20:58 peter
  902. * remove sysutils
  903. Revision 1.36 2004/10/30 20:55:54 marco
  904. * unix interface cleanup
  905. Revision 1.35 2004/09/25 15:09:57 peter
  906. * remove strpas() before syscalls so it chooses the pchar overload
  907. Revision 1.34 2004/08/14 14:22:17 florian
  908. * alignment for sparc fixed
  909. Revision 1.33 2004/07/25 22:46:34 olle
  910. * envstr now returns empty string when index out of bounds
  911. Revision 1.32 2004/03/14 18:42:39 peter
  912. * reset searchrec info in findfirst
  913. Revision 1.31 2004/03/04 22:15:16 marco
  914. * UnixType changes. Please report problems to me.
  915. Revision 1.30 2004/02/18 22:00:45 peter
  916. * dirptr changed to pointer
  917. Revision 1.29 2004/02/18 19:08:27 florian
  918. * fixed bootstrapping with 1.9.2
  919. Revision 1.28 2004/02/17 17:37:26 daniel
  920. * Enable threadvars again
  921. Revision 1.27 2004/02/16 22:18:44 hajny
  922. * LastDosExitCode changed back from threadvar temporarily
  923. Revision 1.26 2004/02/15 21:36:10 hajny
  924. * overloaded ExecuteProcess added, EnvStr param changed to longint
  925. Revision 1.25 2004/02/09 17:01:28 marco
  926. * fixes to get it working under FreeBSD, and probably Linux too
  927. Revision 1.24 2004/02/09 12:03:16 michael
  928. + Switched to single interface in dosh.inc
  929. Revision 1.23 2004/01/31 16:15:14 florian
  930. * packing of searchrec for arm fixed
  931. Revision 1.22 2003/12/29 21:15:04 jonas
  932. * fixed setftime (sorry Marco :)
  933. Revision 1.21 2003/12/03 20:17:03 olle
  934. * files are not pretended to have attr ARCHIVED anymore
  935. + FindFirst etc now also filters on attr HIDDEN
  936. * files with attr READONLY and ARCHIVE are always returned by FindFirst etc
  937. Revision 1.19 2003/10/17 22:13:30 olle
  938. * changed i386 to cpui386
  939. Revision 1.18 2003/09/27 12:51:33 peter
  940. * fpISxxx macros renamed to C compliant fpS_ISxxx
  941. Revision 1.17 2003/09/17 17:30:46 marco
  942. * Introduction of unixutil
  943. Revision 1.16 2003/09/14 20:15:01 marco
  944. * Unix reform stage two. Remove all calls from Unix that exist in Baseunix.
  945. Revision 1.15 2003/05/16 20:56:06 florian
  946. no message
  947. Revision 1.14 2003/05/14 13:51:03 florian
  948. * ifdef'd code which i386 specific
  949. Revision 1.13 2002/12/08 16:05:34 peter
  950. * small error code fixes so tdos2 passes
  951. Revision 1.12 2002/09/07 16:01:27 peter
  952. * old logs removed and tabs fixed
  953. }