dos.pp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2023 by the Free Pascal development team.
  4. DOS unit for BP7 compatible RTL, Human68k 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 h68kdos.inc}
  32. procedure Error2DosError(errno: longint);
  33. begin
  34. case errno of
  35. DOSE_NOENT: DosError:=2; // File not found
  36. DOSE_NODIR: DosError:=3; // Directory (folder/path) not found
  37. DOSE_ISDIR: DosError:=5; // Access denied
  38. DOSE_BADF: DosError:=6; // Invalid file handle
  39. DOSE_NOMEM: DosError:=8; // Insufficient memory
  40. DOSE_MFILE: 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:=Swap(human68k_vernum);
  48. end;
  49. procedure GetDate(Var Year, Month, MDay, WDay: Word);
  50. var
  51. OSDate: LongInt;
  52. D: DateTime;
  53. begin
  54. OSDate:=h68kdos_getdate;
  55. { the time values will be invalid here,
  56. but it doesn't matter, we want the date }
  57. UnpackTime(OSDate shl 16,D);
  58. Year:=D.Year;
  59. Month:=D.Month;
  60. MDay:=D.Day;
  61. WDay:=OSDate shr 16;
  62. end;
  63. procedure SetDate(Year, Month, Day: Word);
  64. var
  65. D: DateTime;
  66. OSDate: LongInt;
  67. begin
  68. D.Year:=Year;
  69. D.Month:=Month;
  70. D.Day:=Day;
  71. PackTime(D,OSDate);
  72. h68kdos_setdate(hi(OSDate));
  73. end;
  74. procedure GetTime(Var Hour, Minute, Second, Sec100: Word);
  75. var
  76. OSTime: LongInt;
  77. T: DateTime;
  78. begin
  79. OSTime:=h68kdos_gettime;
  80. { the date values will be invalid here,
  81. but it doesn't matter, we want the time }
  82. UnpackTime(OSTime,T);
  83. Hour:=T.Hour;
  84. Minute:=T.Min;
  85. Second:=T.Sec;
  86. Sec100:=0;
  87. end;
  88. procedure SetTime(Hour, Minute, Second, Sec100: Word);
  89. var
  90. T: DateTime;
  91. OSTime: LongInt;
  92. begin
  93. T.Hour:=Hour;
  94. T.Min:=Minute;
  95. T.Sec:=Second;
  96. PackTime(T,OSTime);
  97. h68kdos_settime(lo(OSTime));
  98. end;
  99. function h68kdos_exec0(const fil: pchar; p1: pointer; p2: pointer): longint; external name '_fpc_h68kdos_exec0';
  100. procedure Exec(const Path: PathStr; const ComLine: ComStr);
  101. var
  102. dosResult: LongInt;
  103. tmpPath: String;
  104. begin
  105. tmpPath:=Path+#0;
  106. DoDirSeparators(tmpPath);
  107. { 1) If I understand the Human68k documentation, this will not execute
  108. programs in the PATH, but you need an exec, mode 2 call first.
  109. Not sure how the original DOS unit Exec() call behaves. (KB) }
  110. { 2) the zero offset for cmdline is actually correct here. exec() expects
  111. pascal formatted string for cmdline, so length in first byte }
  112. dosResult:=h68kdos_exec0(PAnsiChar(@tmpPath[1]),@ComLine[0],nil);
  113. if dosResult < 0 then
  114. Error2DosError(dosResult);
  115. end;
  116. function DiskSize(Drive: Byte): Int64;
  117. var
  118. dosResult: longint;
  119. fi: Th68kdos_freeinfo;
  120. begin
  121. DiskSize := -1;
  122. dosResult:=h68kdos_dskfre(drive,@fi);
  123. if dosResult < 0 then
  124. exit;
  125. DiskSize:=fi.max * fi.sectors * fi.bytes;
  126. end;
  127. function DiskFree(Drive: Byte): Int64;
  128. var
  129. dosResult: longint;
  130. fi: Th68kdos_freeinfo;
  131. begin
  132. DiskFree := -1;
  133. dosResult:=h68kdos_dskfre(drive,@fi);
  134. if dosResult < 0 then
  135. exit;
  136. DiskFree:=fi.free * fi.sectors * fi.bytes;
  137. end;
  138. type
  139. PInternalFindData = ^TInternalFindData;
  140. TInternalFindData = record
  141. filebuf: Th68kdos_filbuf;
  142. end;
  143. procedure FindFirst(const Path: PathStr; Attr: Word; Var f: SearchRec);
  144. var
  145. p: PathStr;
  146. r: RawByteString;
  147. dosResult: LongInt;
  148. IFD: PInternalFindData;
  149. begin
  150. p:=Path;
  151. DoDirSeparators(p);
  152. r:=p;
  153. new(IFD);
  154. f.IFD:=IFD;
  155. dosResult:=h68kdos_files(@IFD^.filebuf, PAnsiChar(r), Attr and AnyFile);
  156. if dosResult < 0 then
  157. begin
  158. Error2DosError(dosResult);
  159. FindClose(f);
  160. exit;
  161. end;
  162. DosError:=0;
  163. with IFD^.filebuf do
  164. begin
  165. f.name:=name;
  166. f.time:=(date shl 16) + time;
  167. f.size:=filelen;
  168. f.attr:=atr;
  169. end;
  170. end;
  171. procedure FindNext(Var f: SearchRec);
  172. var
  173. IFD: PInternalFindData;
  174. dosResult: LongInt;
  175. begin
  176. IFD:=f.IFD;
  177. if not assigned(IFD) then
  178. begin
  179. DosError:=6;
  180. exit;
  181. end;
  182. dosResult:=h68kdos_nfiles(@IFD^.filebuf);
  183. if dosResult < 0 then
  184. begin
  185. Error2DosError(dosResult);
  186. exit;
  187. end;
  188. DosError:=0;
  189. with IFD^.filebuf do
  190. begin
  191. f.name:=name;
  192. f.time:=(date shl 16) + time;
  193. f.size:=filelen;
  194. f.attr:=atr;
  195. end;
  196. end;
  197. procedure FindClose(Var f: SearchRec);
  198. var
  199. IFD: PInternalFindData;
  200. begin
  201. IFD:=f.IFD;
  202. if not assigned(IFD) then
  203. exit;
  204. dispose(IFD);
  205. f.IFD:=nil;
  206. end;
  207. function FSearch(path: PathStr; dirlist: String) : PathStr;
  208. var
  209. p1 : longint;
  210. s : searchrec;
  211. newdir : pathstr;
  212. begin
  213. { No wildcards allowed in these things }
  214. if (pos('?',path)<>0) or (pos('*',path)<>0) then
  215. begin
  216. fsearch:='';
  217. exit;
  218. end;
  219. { check if the file specified exists }
  220. findfirst(path,anyfile and not(directory),s);
  221. if doserror=0 then
  222. begin
  223. findclose(s);
  224. fsearch:=path;
  225. exit;
  226. end;
  227. findclose(s);
  228. { allow slash as backslash }
  229. DoDirSeparators(dirlist);
  230. repeat
  231. p1:=pos(';',dirlist);
  232. if p1<>0 then
  233. begin
  234. newdir:=copy(dirlist,1,p1-1);
  235. delete(dirlist,1,p1);
  236. end
  237. else
  238. begin
  239. newdir:=dirlist;
  240. dirlist:='';
  241. end;
  242. if (newdir<>'') and (not (newdir[length(newdir)] in ['\',':'])) then
  243. newdir:=newdir+'\';
  244. findfirst(newdir+path,anyfile and not(directory),s);
  245. if doserror=0 then
  246. newdir:=newdir+path
  247. else
  248. newdir:='';
  249. findclose(s);
  250. until (dirlist='') or (newdir<>'');
  251. fsearch:=newdir;
  252. end;
  253. procedure GetFAttr(var f; var Attr : word);
  254. var
  255. dosResult: LongInt;
  256. path: PAnsiChar;
  257. {$ifndef FPC_ANSI_TEXTFILEREC}
  258. r: rawbytestring;
  259. {$endif not FPC_ANSI_TEXTFILEREC}
  260. begin
  261. {$ifdef FPC_ANSI_TEXTFILEREC}
  262. path:=@filerec(f).Name;
  263. {$else}
  264. r:=ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
  265. path:=PAnsiChar(r);
  266. {$endif}
  267. Attr:=0;
  268. dosResult:=h68kdos_chmod(path,-1);
  269. if dosResult < 0 then
  270. Error2DosError(dosResult)
  271. else
  272. Attr:=word(dosResult);
  273. end;
  274. procedure GetFTime(var f; var Time : longint);
  275. var
  276. dosResult: longint;
  277. begin
  278. Time:=-1;
  279. if hi(human68k_vernum) <= 2 then
  280. dosResult:=h68kdos_filedate_v2(TextRec(f).Handle,0)
  281. else
  282. dosResult:=h68kdos_filedate_v3(TextRec(f).Handle,0);
  283. if hi(dosResult) = $ffff then
  284. begin
  285. Error2DosError(dosResult);
  286. exit;
  287. end;
  288. Time:=dosResult;
  289. end;
  290. procedure SetFAttr(var f; attr : word);
  291. var
  292. dosResult: LongInt;
  293. path: PAnsiChar;
  294. {$ifndef FPC_ANSI_TEXTFILEREC}
  295. r: rawbytestring;
  296. {$endif not FPC_ANSI_TEXTFILEREC}
  297. begin
  298. {$ifdef FPC_ANSI_TEXTFILEREC}
  299. path:=@filerec(f).Name;
  300. {$else}
  301. r:=ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
  302. path:=PAnsiChar(r);
  303. {$endif}
  304. dosResult:=h68kdos_chmod(path,Attr);
  305. if dosResult < 0 then
  306. Error2DosError(dosResult);
  307. end;
  308. procedure SetFTime(var f; time : longint);
  309. var
  310. dosResult: longint;
  311. begin
  312. if hi(human68k_vernum) <= 2 then
  313. dosResult:=h68kdos_filedate_v2(TextRec(f).Handle,time)
  314. else
  315. dosResult:=h68kdos_filedate_v3(TextRec(f).Handle,time);
  316. if hi(dosResult) = $ffff then
  317. begin
  318. Error2DosError(dosResult);
  319. exit;
  320. end;
  321. end;
  322. function EnvCount: Longint;
  323. var
  324. hp : PAnsiChar;
  325. begin
  326. EnvCount:=0;
  327. hp:=''; // FIX ME!
  328. If (Hp<>Nil) then
  329. while hp^<>#0 do
  330. begin
  331. Inc(EnvCount);
  332. hp:=hp+strlen(hp)+1;
  333. end;
  334. end;
  335. function EnvStr(Index: LongInt): String;
  336. var
  337. hp : PAnsiChar;
  338. begin
  339. EnvStr:='';
  340. hp:=nil; // FIX ME!
  341. If (Hp<>Nil) then
  342. begin
  343. while (hp^<>#0) and (Index>1) do
  344. begin
  345. Dec(Index);
  346. hp:=hp+strlen(hp)+1;
  347. end;
  348. If (hp^<>#0) then
  349. begin
  350. EnvStr:=hp;
  351. end;
  352. end;
  353. end;
  354. function GetEnv(envvar : String): String;
  355. begin
  356. GetEnv:='';
  357. end;
  358. end.