dos.pp 26 KB

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