2
0

dos.pp 8.5 KB

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