dos.pp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2017 by the Free Pascal development team.
  4. DOS unit for BP7 compatible RTL, Atari implementation
  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. type
  14. SearchRec = record
  15. { Replacement for Fill }
  16. IFD: Pointer;
  17. Fill: Array[1..17] of Byte; {future use}
  18. {End of replacement for fill}
  19. Attr : BYTE; {attribute of found file}
  20. Time : LongInt; {last modify date of found file}
  21. Size : LongInt; {file size of found file}
  22. Name : String[255]; {name of found file}
  23. end;
  24. {$i dosh.inc}
  25. implementation
  26. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  27. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  28. {$i dos.inc}
  29. {$i gemdos.inc}
  30. var
  31. basepage: PPD; external name '__base';
  32. procedure Error2DosError(errno: longint);
  33. begin
  34. case errno of
  35. EFILNF: DosError:=2; // File not found
  36. EPTHNF: DosError:=3; // Directory (folder/path) not found
  37. EACCDN: DosError:=5; // Access denied
  38. EIHNDL: DosError:=6; // Invalid file handle
  39. ENSMEM: DosError:=8; // Insufficient memory
  40. ENMFIL: DosError:=18; // No more files can be opened
  41. else
  42. DosError:=errno;
  43. end;
  44. end;
  45. function DosVersion: Word;
  46. begin
  47. DosVersion:=0;
  48. end;
  49. function WeekDay (y,m,d:longint):longint;
  50. {
  51. Calculates th day of the week. returns -1 on error
  52. }
  53. var
  54. u,v : longint;
  55. begin
  56. if (m<1) or (m>12) or (y<1600) or (y>4000) or
  57. (d<1) or (d>30+((m+ord(m>7)) and 1)-ord(m=2)) or
  58. ((m*d=58) and (((y mod 4>0) or (y mod 100=0)) and (y mod 400>0))) then
  59. WeekDay:=-1
  60. else
  61. begin
  62. u:=m;
  63. v:=y;
  64. if m<3 then
  65. begin
  66. inc(u,12);
  67. dec(v);
  68. end;
  69. WeekDay:=(d+2*u+((3*(u+1)) div 5)+v+(v div 4)-(v div 100)+(v div 400)+1) mod 7;
  70. end;
  71. end;
  72. procedure GetDate(Var Year, Month, MDay, WDay: Word);
  73. var
  74. TOSDate: LongInt;
  75. D: DateTime;
  76. begin
  77. TOSDate:=gemdos_tgetdate shl 16;
  78. { the time values will be invalid here,
  79. but it doesn't matter, we want the date }
  80. UnpackTime(TOSDate,D);
  81. Year:=D.Year;
  82. Month:=D.Month;
  83. MDay:=D.Day;
  84. WDay:=WeekDay(Year,Month,MDay);
  85. end;
  86. procedure SetDate(Year, Month, Day: Word);
  87. var
  88. D: DateTime;
  89. TOSDate: LongInt;
  90. begin
  91. D.Year:=Year;
  92. D.Month:=Month;
  93. D.Day:=Day;
  94. PackTime(D,TOSDate);
  95. gemdos_tsetdate(hi(TOSDate));
  96. end;
  97. procedure GetTime(Var Hour, Minute, Second, Sec100: Word);
  98. var
  99. TOSTime: LongInt;
  100. T: DateTime;
  101. begin
  102. TOSTime:=gemdos_tgettime;
  103. { the date values will be invalid here,
  104. but it doesn't matter, we want the time }
  105. UnpackTime(TOSTime,T);
  106. Hour:=T.Hour;
  107. Minute:=T.Min;
  108. Second:=T.Sec;
  109. Sec100:=0;
  110. end;
  111. procedure SetTime(Hour, Minute, Second, Sec100: Word);
  112. var
  113. T: DateTime;
  114. TOSTime: LongInt;
  115. begin
  116. T.Hour:=Hour;
  117. T.Min:=Minute;
  118. T.Sec:=Second;
  119. PackTime(T,TOSTime);
  120. gemdos_tsettime(lo(TOSTime));
  121. end;
  122. procedure Exec(const Path: PathStr; const ComLine: ComStr);
  123. var
  124. dosResult: LongInt;
  125. tmpPath: String;
  126. begin
  127. tmpPath:=Path+#0;
  128. DoDirSeparators(tmpPath);
  129. { the zero offset for cmdline is actually correct here. pexec() expects
  130. pascal formatted string for cmdline, so length in first byte }
  131. dosResult:=gemdos_pexec(0,PChar(@tmpPath[1]),@ComLine[0],nil);
  132. if dosResult < 0 then
  133. Error2DosError(dosResult);
  134. end;
  135. function DiskSize(Drive: Byte): Int64;
  136. var
  137. dosResult: longint;
  138. di: TDISKINFO;
  139. begin
  140. DiskSize := -1;
  141. dosResult:=gemdos_dfree(@di,drive);
  142. if dosResult < 0 then
  143. exit;
  144. DiskSize:=di.b_total * di.b_secsiz * di.b_clsiz;
  145. end;
  146. function DiskFree(Drive: Byte): Int64;
  147. var
  148. dosResult: longint;
  149. di: TDISKINFO;
  150. begin
  151. DiskFree := -1;
  152. dosResult:=gemdos_dfree(@di,drive);
  153. if dosResult < 0 then
  154. exit;
  155. DiskFree:=di.b_free * di.b_secsiz * di.b_clsiz;
  156. end;
  157. type
  158. PInternalFindData = ^TInternalFindData;
  159. TInternalFindData = record
  160. dta_original: pointer;
  161. dta_search: TDTA;
  162. end;
  163. procedure FindFirst(const Path: PathStr; Attr: Word; Var f: SearchRec);
  164. var
  165. p: PathStr;
  166. r: RawByteString;
  167. dosResult: LongInt;
  168. IFD: PInternalFindData;
  169. begin
  170. p:=Path;
  171. DoDirSeparators(p);
  172. r:=p;
  173. new(IFD);
  174. IFD^.dta_original:=gemdos_getdta;
  175. gemdos_setdta(@IFD^.dta_search);
  176. f.IFD:=IFD;
  177. dosResult:=gemdos_fsfirst(pchar(r), Attr and AnyFile);
  178. if dosResult < 0 then
  179. begin
  180. Error2DosError(dosResult);
  181. FindClose(f);
  182. exit;
  183. end;
  184. DosError:=0;
  185. with IFD^.dta_search do
  186. begin
  187. f.name:=d_fname;
  188. f.time:=(d_date shl 16) + d_time;
  189. f.size:=d_length;
  190. f.attr:=d_attrib;
  191. end;
  192. end;
  193. procedure FindNext(Var f: SearchRec);
  194. var
  195. IFD: PInternalFindData;
  196. dosResult: LongInt;
  197. begin
  198. IFD:=f.IFD;
  199. if not assigned(IFD) then
  200. begin
  201. DosError:=6;
  202. exit;
  203. end;
  204. dosResult:=gemdos_fsnext;
  205. if dosResult < 0 then
  206. begin
  207. Error2DosError(dosResult);
  208. exit;
  209. end;
  210. DosError:=0;
  211. with IFD^.dta_search do
  212. begin
  213. f.name:=d_fname;
  214. f.time:=(d_date shl 16) + d_time;
  215. f.size:=d_length;
  216. f.attr:=d_attrib;
  217. end;
  218. end;
  219. procedure FindClose(Var f: SearchRec);
  220. var
  221. IFD: PInternalFindData;
  222. begin
  223. IFD:=f.IFD;
  224. if not assigned(IFD) then
  225. exit;
  226. gemdos_setdta(IFD^.dta_original);
  227. dispose(IFD);
  228. f.IFD:=nil;
  229. end;
  230. function FSearch(path: PathStr; dirlist: String) : PathStr;
  231. var
  232. p1 : longint;
  233. s : searchrec;
  234. newdir : pathstr;
  235. begin
  236. { No wildcards allowed in these things }
  237. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  238. begin
  239. fsearch:='';
  240. exit;
  241. end;
  242. { check if the file specified exists }
  243. findfirst(path,anyfile and not(directory),s);
  244. if doserror=0 then
  245. begin
  246. findclose(s);
  247. fsearch:=path;
  248. exit;
  249. end;
  250. findclose(s);
  251. { allow slash as backslash }
  252. DoDirSeparators(dirlist);
  253. repeat
  254. p1:=pos(';',dirlist);
  255. if p1<>0 then
  256. begin
  257. newdir:=copy(dirlist,1,p1-1);
  258. delete(dirlist,1,p1);
  259. end
  260. else
  261. begin
  262. newdir:=dirlist;
  263. dirlist:='';
  264. end;
  265. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  266. newdir:=newdir+'\';
  267. findfirst(newdir+path,anyfile and not(directory),s);
  268. if doserror=0 then
  269. newdir:=newdir+path
  270. else
  271. newdir:='';
  272. findclose(s);
  273. until (dirlist='') or (newdir<>'');
  274. fsearch:=newdir;
  275. end;
  276. procedure GetFAttr(var f; var Attr : word);
  277. var
  278. dosResult: LongInt;
  279. path: PChar;
  280. {$ifndef FPC_ANSI_TEXTFILEREC}
  281. r: rawbytestring;
  282. {$endif not FPC_ANSI_TEXTFILEREC}
  283. begin
  284. {$ifdef FPC_ANSI_TEXTFILEREC}
  285. path:=@filerec(f).Name;
  286. {$else}
  287. r:=ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
  288. path:=pchar(r);
  289. {$endif}
  290. Attr:=0;
  291. dosResult:=gemdos_fattrib(path,0,0);
  292. if dosResult < 0 then
  293. Error2DosError(dosResult)
  294. else
  295. Attr:=word(dosResult);
  296. end;
  297. procedure GetFTime(var f; var Time : longint);
  298. var
  299. td: TDOSTIME;
  300. begin
  301. gemdos_fdatime(@td,TextRec(f).Handle,0);
  302. Time:=(td.date shl 16) + td.time;
  303. end;
  304. procedure SetFAttr(var f; attr : word);
  305. var
  306. dosResult: LongInt;
  307. path: PChar;
  308. {$ifndef FPC_ANSI_TEXTFILEREC}
  309. r: rawbytestring;
  310. {$endif not FPC_ANSI_TEXTFILEREC}
  311. begin
  312. {$ifdef FPC_ANSI_TEXTFILEREC}
  313. path:=@filerec(f).Name;
  314. {$else}
  315. r:=ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
  316. path:=pchar(r);
  317. {$endif}
  318. dosResult:=gemdos_fattrib(pchar(@FileRec(f).name),1,Attr);
  319. if dosResult < 0 then
  320. Error2DosError(dosResult)
  321. end;
  322. procedure SetFTime(var f; time : longint);
  323. var
  324. td: TDOSTIME;
  325. begin
  326. td.date:=Hi(Time);
  327. td.time:=Lo(Time);
  328. gemdos_fdatime(@td,TextRec(f).Handle,1);
  329. end;
  330. function EnvCount: Longint;
  331. var
  332. hp : pchar;
  333. begin
  334. EnvCount:=0;
  335. hp:=basepage^.p_env;
  336. If (Hp<>Nil) then
  337. while hp^<>#0 do
  338. begin
  339. Inc(EnvCount);
  340. hp:=hp+strlen(hp)+1;
  341. end;
  342. end;
  343. function EnvStr(Index: LongInt): String;
  344. var
  345. hp : pchar;
  346. begin
  347. EnvStr:='';
  348. hp:=basepage^.p_env;
  349. If (Hp<>Nil) then
  350. begin
  351. while (hp^<>#0) and (Index>1) do
  352. begin
  353. Dec(Index);
  354. hp:=hp+strlen(hp)+1;
  355. end;
  356. If (hp^<>#0) then
  357. begin
  358. EnvStr:=hp;
  359. end;
  360. end;
  361. end;
  362. function GetEnv(envvar : String): String;
  363. var
  364. hp : pchar;
  365. i : longint;
  366. upperenv, str : RawByteString;
  367. begin
  368. GetEnv:='';
  369. hp:=basepage^.p_env;
  370. if (hp=nil) then
  371. exit;
  372. upperenv:=upcase(envvar);
  373. while hp^<>#0 do
  374. begin
  375. str:=hp;
  376. i:=pos('=',str);
  377. if upcase(copy(str,1,i-1))=upperenv then
  378. begin
  379. GetEnv:=copy(str,i+1,length(str)-i);
  380. break;
  381. end;
  382. { next string entry}
  383. hp:=hp+strlen(hp)+1;
  384. end;
  385. end;
  386. end.