PageRenderTime 45ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/rpython/translator/cli/src/ll_os.cs

https://bitbucket.org/jonathanslenders/pypy
C# | 580 lines | 472 code | 79 blank | 29 comment | 51 complexity | 8cb7a7397e10700d190a997e3a6deddd MD5 | raw file
  1. using System;
  2. using System.IO;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using pypy.runtime;
  7. namespace pypy.builtin
  8. {
  9. interface IFile
  10. {
  11. FileStream GetStream();
  12. void Write(string buffer);
  13. string Read(int count);
  14. }
  15. // this class is used only for stdin/stdout/stderr
  16. class TextFile: IFile
  17. {
  18. private FileStream stream;
  19. private TextWriter writer;
  20. private TextReader reader;
  21. public TextFile(FileStream stream, TextReader reader, TextWriter writer)
  22. {
  23. this.stream = stream;
  24. this.writer = writer;
  25. this.reader = reader;
  26. }
  27. public FileStream GetStream()
  28. {
  29. return stream;
  30. }
  31. public void Write(string buffer)
  32. {
  33. if (writer == null)
  34. Helpers.raise_OSError(Errno.EBADF);
  35. writer.Write(buffer);
  36. }
  37. public string Read(int count)
  38. {
  39. if (reader == null)
  40. Helpers.raise_OSError(Errno.EBADF);
  41. char[] buf = new char[count];
  42. int n = reader.Read(buf, 0, count);
  43. return new string(buf, 0, n);
  44. }
  45. }
  46. abstract class AbstractFile: IFile
  47. {
  48. protected FileStream stream;
  49. protected abstract string _Read(int count);
  50. protected abstract void _Write(string buffer);
  51. public AbstractFile(FileStream stream)
  52. {
  53. this.stream = stream;
  54. }
  55. public FileStream GetStream()
  56. {
  57. return stream;
  58. }
  59. public void Write(string buffer)
  60. {
  61. if (!stream.CanWrite)
  62. Helpers.raise_OSError(Errno.EBADF);
  63. _Write(buffer);
  64. }
  65. public string Read(int count)
  66. {
  67. if (!stream.CanRead)
  68. Helpers.raise_OSError(Errno.EBADF);
  69. return _Read(count);
  70. }
  71. }
  72. class CRLFTextFile: AbstractFile
  73. {
  74. public CRLFTextFile(FileStream stream): base(stream)
  75. {
  76. }
  77. protected override void _Write(string buffer)
  78. {
  79. foreach(char ch in buffer) {
  80. if (ch == '\n')
  81. stream.WriteByte((byte)'\r');
  82. stream.WriteByte((byte)ch);
  83. }
  84. }
  85. protected override string _Read(int count)
  86. {
  87. System.Text.StringBuilder builder = new System.Text.StringBuilder(count);
  88. bool pending_CR = false;
  89. while (count-- > 0) {
  90. int ch = stream.ReadByte();
  91. if (ch == -1)
  92. break;
  93. else if (ch == '\r')
  94. pending_CR = true;
  95. else {
  96. if (pending_CR && ch != '\n')
  97. builder.Append('\r');
  98. builder.Append((char)ch);
  99. pending_CR = false;
  100. }
  101. }
  102. return builder.ToString();
  103. }
  104. }
  105. class BinaryFile: AbstractFile
  106. {
  107. public BinaryFile(FileStream stream): base(stream)
  108. {
  109. }
  110. protected override void _Write(string buffer)
  111. {
  112. foreach(char ch in buffer)
  113. stream.WriteByte((byte)ch);
  114. }
  115. protected override string _Read(int count)
  116. {
  117. byte[] rawbuf = new byte[count];
  118. int n = stream.Read(rawbuf, 0, count);
  119. char[] buf = new char[count];
  120. for(int i=0; i<count; i++)
  121. buf[i] = (char)rawbuf[i];
  122. return new string(buf, 0, n);
  123. }
  124. }
  125. public class ll_os
  126. {
  127. private static Dictionary<int, IFile> FileDescriptors;
  128. private static int fdcount;
  129. private static Dictionary<int, string> ErrorMessages;
  130. // NB: these values are those used by Windows and they differs
  131. // from the Unix ones; the os module is patched with these
  132. // values before flowgraphing to make sure we get the very
  133. // same values on each platform we do the compilation.
  134. private const int O_RDONLY = 0x0000;
  135. private const int O_WRONLY = 0x0001;
  136. private const int O_RDWR = 0x0002;
  137. private const int O_APPEND = 0x0008;
  138. private const int O_CREAT = 0x0100;
  139. private const int O_TRUNC = 0x0200;
  140. private const int O_TEXT = 0x4000;
  141. private const int O_BINARY = 0x8000;
  142. private const int S_IFMT = 61440;
  143. private const int S_IFDIR = 16384;
  144. private const int S_IFREG = 32768;
  145. static ll_os()
  146. {
  147. ErrorMessages = new Dictionary<int, string>();
  148. FileDescriptors = new Dictionary<int, IFile>();
  149. // XXX: what about CRLF conversion for stdin, stdout and stderr?
  150. // It seems that Posix let you read from stdout and
  151. // stderr, so pass Console.In to them, too.
  152. FileDescriptors[0] = new TextFile(null, Console.In, null);
  153. FileDescriptors[1] = new TextFile(null, Console.In, Console.Out);
  154. FileDescriptors[2] = new TextFile(null, Console.In, Console.Error);
  155. fdcount = 2; // 0, 1 and 2 are already used by stdin, stdout and stderr
  156. }
  157. private static void raise_OSError(int errno, string msg)
  158. {
  159. ErrorMessages[errno] = msg;
  160. Helpers.raise_OSError(errno);
  161. }
  162. public static string ll_os_strerror(int errno)
  163. {
  164. try {
  165. string msg = ErrorMessages[errno];
  166. ErrorMessages.Remove(errno);
  167. return msg;
  168. }
  169. catch(KeyNotFoundException e) {
  170. return "error " + errno;
  171. }
  172. }
  173. public static string ll_os_getcwd()
  174. {
  175. return System.IO.Directory.GetCurrentDirectory();
  176. }
  177. private static IFile getfd(int fd)
  178. {
  179. IFile f = FileDescriptors[fd];
  180. if (f == null)
  181. raise_OSError(Errno.EBADF, string.Format("Invalid file descriptor: {0}", fd));
  182. return f;
  183. }
  184. private static FileAccess get_file_access(int flags)
  185. {
  186. if ((flags & O_RDWR) != 0) return FileAccess.ReadWrite;
  187. if ((flags & O_WRONLY) != 0) return FileAccess.Write;
  188. return FileAccess.Read;
  189. }
  190. private static FileMode get_file_mode(int flags) {
  191. if ((flags & O_APPEND) !=0 ) return FileMode.Append;
  192. if ((flags & O_TRUNC) !=0 ) return FileMode.Create;
  193. if ((flags & O_CREAT) !=0 ) return FileMode.OpenOrCreate;
  194. return FileMode.Open;
  195. }
  196. public static int ll_os_open(string name, int flags, int mode)
  197. {
  198. FileAccess f_access = get_file_access(flags);
  199. FileMode f_mode = get_file_mode(flags);
  200. FileStream stream;
  201. IFile f;
  202. try {
  203. stream = new FileStream(name, f_mode, f_access, FileShare.ReadWrite);
  204. }
  205. catch(UnauthorizedAccessException e) {
  206. raise_OSError(Errno.EACCES, e.Message);
  207. return -1;
  208. }
  209. catch(FileNotFoundException e) {
  210. raise_OSError(Errno.ENOENT, e.Message);
  211. return -1;
  212. }
  213. catch(IOException e) {
  214. raise_OSError(Errno.EIO, e.Message);
  215. return -1;
  216. }
  217. // - on Unix there is no difference between text and binary modes
  218. // - on Windows text mode means that we should convert '\n' from and to '\r\n'
  219. // - on Mac < OS9 text mode means that we should convert '\n' from and to '\r' -- XXX: TODO!
  220. if ((flags & O_BINARY) == 0 && System.Environment.NewLine == "\r\n")
  221. f = new CRLFTextFile(stream);
  222. else
  223. f = new BinaryFile(stream);
  224. fdcount++;
  225. FileDescriptors[fdcount] = f;
  226. return fdcount;
  227. }
  228. public static void ll_os_close(int fd)
  229. {
  230. FileStream stream = getfd(fd).GetStream();
  231. if (stream != null) // stdin/stdout/stderr files don't have a stream
  232. stream.Close();
  233. FileDescriptors.Remove(fd);
  234. }
  235. public static int ll_os_write(int fd, string buffer)
  236. {
  237. getfd(fd).Write(buffer);
  238. return buffer.Length;
  239. }
  240. /*
  241. private static void PrintString(string source, string s)
  242. {
  243. Console.Error.WriteLine(source);
  244. Console.Error.WriteLine(s);
  245. Console.Error.WriteLine("Length: {0}", s.Length);
  246. for (int i=0; i<s.Length; i++)
  247. Console.Error.Write("{0} ", (int)s[i]);
  248. Console.Error.WriteLine();
  249. Console.Error.WriteLine();
  250. }
  251. */
  252. public static string ll_os_read(int fd, long count)
  253. {
  254. return ll_os_read(fd, (int)count);
  255. }
  256. public static string ll_os_read(int fd, int count)
  257. {
  258. return getfd(fd).Read(count);
  259. }
  260. public static Record_Stat_Result ll_os_stat(string path)
  261. {
  262. if (path == "")
  263. raise_OSError(Errno.ENOENT, "No such file or directory: ''");
  264. FileInfo f;
  265. try {
  266. f = new FileInfo(path);
  267. }
  268. catch(System.ArgumentException e) {
  269. raise_OSError(Errno.EINVAL, e.Message);
  270. return null;
  271. }
  272. catch(System.NotSupportedException e) {
  273. raise_OSError(Errno.EINVAL, e.Message);
  274. return null;
  275. }
  276. catch(System.IO.IOException e) {
  277. raise_OSError(Errno.EINVAL, e.Message);
  278. return null;
  279. }
  280. if (f.Exists) {
  281. Record_Stat_Result res = new Record_Stat_Result();
  282. TimeSpan t = File.GetLastWriteTime(path) - new DateTime(1970, 1, 1);
  283. res.item0 ^= S_IFREG;
  284. res.item6 = (int)f.Length;
  285. res.item8 = (int)t.TotalSeconds;
  286. return res;
  287. }
  288. DirectoryInfo d = new DirectoryInfo(path);
  289. if (d.Exists) {
  290. Record_Stat_Result res = new Record_Stat_Result();
  291. res.item0 ^= S_IFDIR;
  292. return res;
  293. }
  294. // path is not a file nor a dir, raise OSError
  295. raise_OSError(Errno.ENOENT, string.Format("No such file or directory: '{0}'", path));
  296. return null; // never reached
  297. }
  298. public static Record_Stat_Result ll_os_fstat(int fd)
  299. {
  300. FileStream stream = getfd(fd).GetStream();
  301. return ll_os_stat(stream.Name); // TODO: approximate only
  302. }
  303. public static Record_Stat_Result ll_os_lstat(string path)
  304. {
  305. return ll_os_stat(path); // TODO
  306. }
  307. public static void ll_os_unlink(string path)
  308. {
  309. File.Delete(path);
  310. }
  311. public static void ll_os_putenv(string key, string value)
  312. {
  313. Environment.SetEnvironmentVariable(key, value);
  314. }
  315. public static string ll_os_getenv(string key)
  316. {
  317. return Environment.GetEnvironmentVariable(key);
  318. }
  319. public static void ll_os_unsetenv(string s)
  320. {
  321. Environment.SetEnvironmentVariable(s, null);
  322. }
  323. public static pypy.runtime.List<Record_String_String> ll_os_envitems()
  324. {
  325. pypy.runtime.List<Record_String_String> env = new pypy.runtime.List<Record_String_String>();
  326. foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
  327. {
  328. Record_String_String var = new Record_String_String();
  329. var.item0 = (string)entry.Key;
  330. var.item1 = (string)entry.Value;
  331. env.Add(var);
  332. }
  333. return env;
  334. }
  335. public static pypy.runtime.List<string> ll_os_envkeys()
  336. {
  337. pypy.runtime.List<string> keys = new pypy.runtime.List<string>();
  338. foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
  339. keys.Add((string)entry.Key);
  340. return keys;
  341. }
  342. public static long ll_os_lseek(int fd, long offset, int whence)
  343. {
  344. SeekOrigin origin = SeekOrigin.Begin;
  345. switch(whence)
  346. {
  347. case 0:
  348. origin = SeekOrigin.Begin;
  349. break;
  350. case 1:
  351. origin = SeekOrigin.Current;
  352. break;
  353. case 2:
  354. origin = SeekOrigin.End;
  355. break;
  356. }
  357. FileStream stream = getfd(fd).GetStream();
  358. return stream.Seek(offset, origin);
  359. }
  360. public static void ll_os__exit(int x)
  361. {
  362. Console.Error.WriteLine("WARNING: ll_os__exit has been called, but it's only a stub");
  363. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  364. }
  365. public static void ll_os_chdir(string s)
  366. {
  367. Console.Error.WriteLine("WARNING: ll_os_chdir has been called, but it's only a stub");
  368. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  369. }
  370. public static void ll_os_chmod(string s, int x)
  371. {
  372. Console.Error.WriteLine("WARNING: ll_os_chmod has been called, but it's only a stub");
  373. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  374. }
  375. public static int ll_os_dup(int x)
  376. {
  377. Console.Error.WriteLine("WARNING: ll_os_dup has been called, but it's only a stub");
  378. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  379. return -1;
  380. }
  381. public static void ll_os_dup2(int x, int y)
  382. {
  383. Console.Error.WriteLine("WARNING: ll_os_dup2 has been called, but it's only a stub");
  384. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  385. }
  386. public static int ll_os_fork()
  387. {
  388. Console.Error.WriteLine("WARNING: ll_os_fork has been called, but it's only a stub");
  389. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  390. return -1;
  391. }
  392. public static void ll_os_ftruncate(int x, int y)
  393. {
  394. Console.Error.WriteLine("WARNING: ll_os_ftruncate has been called, but it's only a stub");
  395. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  396. }
  397. public static int ll_os_getpid()
  398. {
  399. Console.Error.WriteLine("WARNING: ll_os_getpid has been called, but it's only a stub");
  400. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  401. return -1;
  402. }
  403. public static bool ll_os_isatty(int x)
  404. {
  405. // XXX: this is not the right behaviour, but it's needed
  406. // to have the interactive interpreter working
  407. if (x == 0 || x == 1 || x == 2)
  408. return true;
  409. else
  410. return false;
  411. }
  412. public static void ll_os_link(string s1, string s2)
  413. {
  414. Console.Error.WriteLine("WARNING: ll_os_link has been called, but it's only a stub");
  415. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  416. }
  417. public static void ll_os_mkdir(string s, int x)
  418. {
  419. Console.Error.WriteLine("WARNING: ll_os_mkdir has been called, but it's only a stub");
  420. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  421. }
  422. public static pypy.runtime.List<string> ll_os_listdir(string path)
  423. {
  424. if (path == "")
  425. Helpers.raise_OSError(Errno.ENOENT);
  426. DirectoryInfo dir = new DirectoryInfo(path);
  427. if (!dir.Exists)
  428. Helpers.raise_OSError(Errno.ENOENT);
  429. pypy.runtime.List<string> names = new pypy.runtime.List<string>();
  430. foreach(DirectoryInfo d in dir.GetDirectories())
  431. names.Add(d.Name);
  432. foreach(FileInfo f in dir.GetFiles())
  433. names.Add(f.Name);
  434. return names;
  435. }
  436. /* XXX old interface, will be removed at some point */
  437. public static object ll_os_opendir(string path)
  438. {
  439. if (path == "")
  440. Helpers.raise_OSError(Errno.ENOENT);
  441. DirectoryInfo dir = new DirectoryInfo(path);
  442. if (!dir.Exists)
  443. Helpers.raise_OSError(Errno.ENOENT);
  444. System.Collections.Generic.List<string> names = new System.Collections.Generic.List<string>();
  445. foreach(DirectoryInfo d in dir.GetDirectories())
  446. names.Add(d.Name);
  447. foreach(FileInfo f in dir.GetFiles())
  448. names.Add(f.Name);
  449. return names.GetEnumerator();
  450. }
  451. /* XXX old interface, will be removed at some point */
  452. public static string ll_os_readdir(object obj)
  453. {
  454. IEnumerator<string> names = (IEnumerator<string>)obj;
  455. if (names.MoveNext())
  456. return names.Current;
  457. else
  458. return null;
  459. }
  460. /* XXX old interface, will be removed at some point */
  461. public static void ll_os_closedir(object obj)
  462. {
  463. }
  464. public static string posix__getfullpathname(string path)
  465. {
  466. return System.IO.Path.GetFullPath(path);
  467. }
  468. public static Record_Signed_Signed ll_os_pipe()
  469. {
  470. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  471. return null;
  472. }
  473. public static string ll_os_readlink(string s)
  474. {
  475. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  476. return null;
  477. }
  478. public static void ll_os_rename(string s1, string s2)
  479. {
  480. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  481. }
  482. public static void ll_os_rmdir(string s)
  483. {
  484. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  485. }
  486. public static void ll_os_symlink(string s1, string s2)
  487. {
  488. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  489. }
  490. public static int ll_os_system(string s)
  491. {
  492. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  493. return -1;
  494. }
  495. public static Record_Signed_Signed ll_os_waitpid(int x, int y)
  496. {
  497. Helpers.raise_OSError(Errno.EPERM); // this is only a stub
  498. return null;
  499. }
  500. }
  501. }