PageRenderTime 55ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/DICK.B1/IronPython.Modules/nt.cs

https://bitbucket.org/williamybs/uidipythontool
C# | 1616 lines | 1237 code | 269 blank | 110 comment | 226 complexity | 05172044dcb891d55e37f4083fef332a MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Microsoft Public License, please send an email to
  8. * ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. using System;
  16. using System.Collections;
  17. using System.Collections.Generic;
  18. using System.ComponentModel;
  19. using System.Diagnostics;
  20. using System.Globalization;
  21. using System.IO;
  22. using System.Runtime.InteropServices;
  23. using System.Security.Cryptography;
  24. using Microsoft.Scripting;
  25. using Microsoft.Scripting.Runtime;
  26. using Microsoft.Scripting.Utils;
  27. using IronPython.Runtime;
  28. using IronPython.Runtime.Exceptions;
  29. using IronPython.Runtime.Operations;
  30. using IronPython.Runtime.Types;
  31. #if CLR2
  32. using Microsoft.Scripting.Math;
  33. #else
  34. using System.Numerics;
  35. #endif
  36. [assembly: PythonModule("nt", typeof(IronPython.Modules.PythonNT))]
  37. namespace IronPython.Modules {
  38. public static class PythonNT {
  39. public const string __doc__ = "Provides low-level operationg system access for files, the environment, etc...";
  40. #if !SILVERLIGHT
  41. private static Dictionary<int, Process> _processToIdMapping = new Dictionary<int, Process>();
  42. private static List<int> _freeProcessIds = new List<int>();
  43. private static int _processCount;
  44. #endif
  45. #region Public API Surface
  46. #if !SILVERLIGHT // FailFast
  47. public static void abort() {
  48. System.Environment.FailFast("IronPython os.abort");
  49. }
  50. #endif
  51. /// <summary>
  52. /// Checks for the specific permissions, provided by the mode parameter, are available for the provided path. Permissions can be:
  53. ///
  54. /// F_OK: Check to see if the file exists
  55. /// R_OK | W_OK | X_OK: Check for the specific permissions. Only W_OK is respected.
  56. /// </summary>
  57. public static bool access(CodeContext/*!*/ context, string path, int mode) {
  58. if (path == null) throw PythonOps.TypeError("expected string, got None");
  59. if (mode == F_OK) {
  60. return context.LanguageContext.DomainManager.Platform.FileExists(path);
  61. }
  62. #if !SILVERLIGHT
  63. // match the behavior of the VC C Runtime
  64. FileAttributes fa = File.GetAttributes(path);
  65. if ((fa & FileAttributes.Directory) != 0) {
  66. // directories have read & write access
  67. return true;
  68. }
  69. if ((fa & FileAttributes.ReadOnly) != 0 && (mode & W_OK) != 0) {
  70. // want to write but file is read-only
  71. return false;
  72. }
  73. return true;
  74. #else
  75. return false;
  76. #endif
  77. }
  78. #if !SILVERLIGHT // SetCurrentDirectory, FileInfo
  79. public static void chdir([NotNull]string path) {
  80. if (String.IsNullOrEmpty(path)) {
  81. throw PythonExceptions.CreateThrowable(WindowsError, PythonExceptions._WindowsError.ERROR_INVALID_NAME, "Path cannot be an empty string");
  82. }
  83. try {
  84. Directory.SetCurrentDirectory(path);
  85. } catch (Exception e) {
  86. throw ToPythonException(e, path);
  87. }
  88. }
  89. public static void chmod(string path, int mode) {
  90. FileInfo fi = new FileInfo(path);
  91. if ((mode & S_IWRITE) != 0) {
  92. fi.Attributes &= ~(FileAttributes.ReadOnly);
  93. } else {
  94. fi.Attributes |= FileAttributes.ReadOnly;
  95. }
  96. }
  97. #endif
  98. public static void close(CodeContext/*!*/ context, int fd) {
  99. PythonContext pythonContext = PythonContext.GetContext(context);
  100. PythonFile pf = pythonContext.FileManager.GetFileFromId(pythonContext, fd);
  101. pf.close();
  102. }
  103. #if !SILVERLIGHT
  104. /// <summary>
  105. /// single instance of environment dictionary is shared between multiple runtimes because the environment
  106. /// is shared by multiple runtimes.
  107. /// </summary>
  108. public static readonly object environ = new PythonDictionary(new EnvironmentDictionaryStorage());
  109. #endif
  110. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
  111. public static readonly PythonType error = Builtin.OSError;
  112. public static void _exit(CodeContext/*!*/ context, int code) {
  113. PythonContext.GetContext(context).DomainManager.Platform.TerminateScriptExecution(code);
  114. }
  115. public static object fdopen(CodeContext/*!*/ context, int fd) {
  116. return fdopen(context, fd, "r");
  117. }
  118. public static object fdopen(CodeContext/*!*/ context, int fd, string mode) {
  119. return fdopen(context, fd, mode, 0);
  120. }
  121. public static object fdopen(CodeContext/*!*/ context, int fd, string mode, int bufsize) {
  122. // check for a valid file mode...
  123. PythonFile.ValidateMode(mode);
  124. PythonContext pythonContext = PythonContext.GetContext(context);
  125. PythonFile pf = pythonContext.FileManager.GetFileFromId(pythonContext, fd);
  126. return pf;
  127. }
  128. public static object fstat(CodeContext/*!*/ context, int fd) {
  129. PythonContext pythonContext = PythonContext.GetContext(context);
  130. PythonFile pf = pythonContext.FileManager.GetFileFromId(pythonContext, fd);
  131. if (pf.IsConsole) {
  132. return new stat_result(8192);
  133. }
  134. return lstat(pf.name);
  135. }
  136. public static string getcwd(CodeContext/*!*/ context) {
  137. return context.LanguageContext.DomainManager.Platform.CurrentDirectory;
  138. }
  139. public static string getcwdu(CodeContext/*!*/ context) {
  140. return context.LanguageContext.DomainManager.Platform.CurrentDirectory;
  141. }
  142. public static string _getfullpathname(CodeContext/*!*/ context, [NotNull]string/*!*/ dir) {
  143. PlatformAdaptationLayer pal = context.LanguageContext.DomainManager.Platform;
  144. try {
  145. return context.LanguageContext.DomainManager.Platform.GetFullPath(dir);
  146. } catch (ArgumentException) {
  147. // .NET validates the path, CPython doesn't... so we replace invalid chars with
  148. // Char.Maxvalue, get the full path, and then replace the Char.Maxvalue's back w/
  149. // their original value.
  150. string newdir = dir;
  151. if (IsWindows()) {
  152. if (newdir.Length >= 2 && newdir[1] == ':' &&
  153. (newdir[0] < 'a' || newdir[0] > 'z') && (newdir[0] < 'A' || newdir[0] > 'Z')) {
  154. // invalid drive, .NET will reject this
  155. if (newdir.Length == 2) {
  156. return newdir + Path.DirectorySeparatorChar;
  157. } else if (newdir[2] == Path.DirectorySeparatorChar) {
  158. return newdir;
  159. } else {
  160. return newdir.Substring(0, 2) + Path.DirectorySeparatorChar + newdir.Substring(2);
  161. }
  162. }
  163. if (newdir.Length > 2 && newdir.IndexOf(':', 2) != -1) {
  164. // : is an invalid char if it's not in the 2nd position
  165. newdir = newdir.Substring(0, 2) + newdir.Substring(2).Replace(':', Char.MaxValue);
  166. }
  167. if (newdir.Length > 0 && newdir[0] == ':') {
  168. newdir = Char.MaxValue + newdir.Substring(1);
  169. }
  170. }
  171. foreach (char c in Path.GetInvalidPathChars()) {
  172. newdir = newdir.Replace(c, Char.MaxValue);
  173. }
  174. // walk backwards through the path replacing the same characters. We should have
  175. // only updated the directory leaving the filename which we're fixing.
  176. string res = context.LanguageContext.DomainManager.Platform.GetFullPath(newdir);
  177. int curDir = dir.Length;
  178. for (int curRes = res.Length - 1; curRes >= 0; curRes--) {
  179. if (res[curRes] == Char.MaxValue) {
  180. for (curDir--; curDir >= 0; curDir--) {
  181. if (newdir[curDir] == Char.MaxValue) {
  182. res = res.Substring(0, curRes) + dir[curDir] + res.Substring(curRes + 1);
  183. break;
  184. }
  185. }
  186. }
  187. }
  188. return res;
  189. }
  190. }
  191. private static bool IsWindows() {
  192. return Environment.OSVersion.Platform == PlatformID.Win32NT ||
  193. Environment.OSVersion.Platform == PlatformID.Win32S ||
  194. Environment.OSVersion.Platform == PlatformID.Win32Windows;
  195. }
  196. #if !SILVERLIGHT
  197. public static int getpid() {
  198. return System.Diagnostics.Process.GetCurrentProcess().Id;
  199. }
  200. #endif
  201. public static List listdir(CodeContext/*!*/ context, [NotNull]string path) {
  202. if (path == String.Empty) {
  203. path = ".";
  204. }
  205. List ret = PythonOps.MakeList();
  206. try {
  207. addBase(context.LanguageContext.DomainManager.Platform.GetFileSystemEntries(path, "*"), ret);
  208. return ret;
  209. } catch (Exception e) {
  210. throw ToPythonException(e, path);
  211. }
  212. }
  213. //
  214. // lstat(path) -> stat result
  215. // Like stat(path), but do not follow symbolic links.
  216. //
  217. public static object lstat(string path) {
  218. return stat(path);
  219. }
  220. #if !SILVERLIGHT
  221. public static void mkdir(string path) {
  222. if (Directory.Exists(path))
  223. throw DirectoryExists();
  224. try {
  225. Directory.CreateDirectory(path);
  226. } catch (Exception e) {
  227. throw ToPythonException(e, path);
  228. }
  229. }
  230. public static void mkdir(string path, int mode) {
  231. if (Directory.Exists(path)) throw DirectoryExists();
  232. // we ignore mode
  233. try {
  234. Directory.CreateDirectory(path);
  235. } catch (Exception e) {
  236. throw ToPythonException(e, path);
  237. }
  238. }
  239. public static object open(CodeContext/*!*/ context, string filename, int flag) {
  240. return open(context, filename, flag, 0777);
  241. }
  242. private const int DefaultBufferSize = 4096;
  243. public static object open(CodeContext/*!*/ context, string filename, int flag, int mode) {
  244. try {
  245. FileMode fileMode = FileModeFromFlags(flag);
  246. FileAccess access = FileAccessFromFlags(flag);
  247. FileOptions options = FileOptionsFromFlags(flag);
  248. FileStream fs;
  249. if (access == FileAccess.Read && (fileMode == FileMode.CreateNew || fileMode == FileMode.Create || fileMode == FileMode.Append)) {
  250. // .NET doesn't allow Create/CreateNew w/ access == Read, so create the file, then close it, then
  251. // open it again w/ just read access.
  252. fs = new FileStream(filename, fileMode, FileAccess.Write, FileShare.None);
  253. fs.Close();
  254. fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, DefaultBufferSize, options);
  255. } else if(access == FileAccess.ReadWrite && fileMode == FileMode.Append) {
  256. fs = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.ReadWrite, DefaultBufferSize, options);
  257. } else {
  258. fs = new FileStream(filename, fileMode, access, FileShare.ReadWrite, DefaultBufferSize, options);
  259. }
  260. string mode2;
  261. if (fs.CanRead && fs.CanWrite) mode2 = "w+";
  262. else if (fs.CanWrite) mode2 = "w";
  263. else mode2 = "r";
  264. if ((flag & O_BINARY) != 0) {
  265. mode2 += "b";
  266. }
  267. return PythonContext.GetContext(context).FileManager.AddToStrongMapping(PythonFile.Create(context, fs, filename, mode2));
  268. } catch (Exception e) {
  269. throw ToPythonException(e, filename);
  270. }
  271. }
  272. private static FileOptions FileOptionsFromFlags(int flag) {
  273. FileOptions res = FileOptions.None;
  274. if ((flag & O_TEMPORARY) != 0) {
  275. res |= FileOptions.DeleteOnClose;
  276. }
  277. if ((flag & O_RANDOM) != 0) {
  278. res |= FileOptions.RandomAccess;
  279. }
  280. if ((flag & O_SEQUENTIAL) != 0) {
  281. res |= FileOptions.SequentialScan;
  282. }
  283. return res;
  284. }
  285. public static PythonFile popen(CodeContext/*!*/ context, string command) {
  286. return popen(context, command, "r");
  287. }
  288. public static PythonFile popen(CodeContext/*!*/ context, string command, string mode) {
  289. return popen(context, command, mode, 4096);
  290. }
  291. public static PythonFile popen(CodeContext/*!*/ context, string command, string mode, int bufsize) {
  292. if (String.IsNullOrEmpty(mode)) mode = "r";
  293. ProcessStartInfo psi = GetProcessInfo(command);
  294. psi.CreateNoWindow = true; // ipyw shouldn't create a new console window
  295. Process p;
  296. PythonFile res;
  297. try {
  298. switch (mode) {
  299. case "r":
  300. psi.RedirectStandardOutput = true;
  301. p = Process.Start(psi);
  302. res = new POpenFile(context, command, p, p.StandardOutput.BaseStream, "r");
  303. break;
  304. case "w":
  305. psi.RedirectStandardInput = true;
  306. p = Process.Start(psi);
  307. res = new POpenFile(context, command, p, p.StandardInput.BaseStream, "w");
  308. break;
  309. default:
  310. throw PythonOps.ValueError("expected 'r' or 'w' for mode, got {0}", mode);
  311. }
  312. } catch (Exception e) {
  313. throw ToPythonException(e);
  314. }
  315. return res;
  316. }
  317. public static PythonTuple popen2(CodeContext/*!*/ context, string command) {
  318. return popen2(context, command, "t");
  319. }
  320. public static PythonTuple popen2(CodeContext/*!*/ context, string command, string mode) {
  321. return popen2(context, command, "t", 4096);
  322. }
  323. public static PythonTuple popen2(CodeContext/*!*/ context, string command, string mode, int bufsize) {
  324. if (String.IsNullOrEmpty(mode)) mode = "t";
  325. if (mode != "t" && mode != "b") throw PythonOps.ValueError("mode must be 't' or 'b' (default is t)");
  326. if (mode == "t") mode = String.Empty;
  327. try {
  328. ProcessStartInfo psi = GetProcessInfo(command);
  329. psi.RedirectStandardInput = true;
  330. psi.RedirectStandardOutput = true;
  331. psi.CreateNoWindow = true; // ipyw shouldn't create a new console window
  332. Process p = Process.Start(psi);
  333. return PythonTuple.MakeTuple(new POpenFile(context, command, p, p.StandardInput.BaseStream, "w" + mode),
  334. new POpenFile(context, command, p, p.StandardOutput.BaseStream, "r" + mode));
  335. } catch (Exception e) {
  336. throw ToPythonException(e);
  337. }
  338. }
  339. public static PythonTuple popen3(CodeContext/*!*/ context, string command) {
  340. return popen3(context, command, "t");
  341. }
  342. public static PythonTuple popen3(CodeContext/*!*/ context, string command, string mode) {
  343. return popen3(context, command, "t", 4096);
  344. }
  345. public static PythonTuple popen3(CodeContext/*!*/ context, string command, string mode, int bufsize) {
  346. if (String.IsNullOrEmpty(mode)) mode = "t";
  347. if (mode != "t" && mode != "b") throw PythonOps.ValueError("mode must be 't' or 'b' (default is t)");
  348. if (mode == "t") mode = String.Empty;
  349. try {
  350. ProcessStartInfo psi = GetProcessInfo(command);
  351. psi.RedirectStandardInput = true;
  352. psi.RedirectStandardOutput = true;
  353. psi.RedirectStandardError = true;
  354. psi.CreateNoWindow = true; // ipyw shouldn't create a new console window
  355. Process p = Process.Start(psi);
  356. return PythonTuple.MakeTuple(new POpenFile(context, command, p, p.StandardInput.BaseStream, "w" + mode),
  357. new POpenFile(context, command, p, p.StandardOutput.BaseStream, "r" + mode),
  358. new POpenFile(context, command, p, p.StandardError.BaseStream, "r+" + mode));
  359. } catch (Exception e) {
  360. throw ToPythonException(e);
  361. }
  362. }
  363. public static void putenv(string varname, string value) {
  364. try {
  365. System.Environment.SetEnvironmentVariable(varname, value);
  366. } catch (Exception e) {
  367. throw ToPythonException(e);
  368. }
  369. }
  370. #endif
  371. public static string read(CodeContext/*!*/ context, int fd, int buffersize) {
  372. if (buffersize < 0) {
  373. throw PythonExceptions.CreateThrowable(PythonExceptions.OSError, PythonErrorNumber.EINVAL, "Invalid argument");
  374. }
  375. try {
  376. PythonContext pythonContext = PythonContext.GetContext(context);
  377. PythonFile pf = pythonContext.FileManager.GetFileFromId(pythonContext, fd);
  378. return pf.read();
  379. } catch (Exception e) {
  380. throw ToPythonException(e);
  381. }
  382. }
  383. #if !SILVERLIGHT
  384. public static void remove(string path) {
  385. UnlinkWorker(path);
  386. }
  387. #endif
  388. public static void rename(string src, string dst) {
  389. try {
  390. Directory.Move(src, dst);
  391. } catch (Exception e) {
  392. throw ToPythonException(e);
  393. }
  394. }
  395. public static void rmdir(string path) {
  396. try {
  397. Directory.Delete(path);
  398. } catch (Exception e) {
  399. throw ToPythonException(e, path);
  400. }
  401. }
  402. #if !SILVERLIGHT
  403. /// <summary>
  404. /// spawns a new process.
  405. ///
  406. /// If mode is nt.P_WAIT then then the call blocks until the process exits and the return value
  407. /// is the exit code.
  408. ///
  409. /// Otherwise the call returns a handle to the process. The caller must then call nt.waitpid(pid, options)
  410. /// to free the handle and get the exit code of the process. Failure to call nt.waitpid will result
  411. /// in a handle leak.
  412. /// </summary>
  413. public static object spawnl(CodeContext/*!*/ context, int mode, string path, params object[] args) {
  414. return SpawnProcessImpl(context, MakeProcess(), mode, path, args);
  415. }
  416. /// <summary>
  417. /// spawns a new process.
  418. ///
  419. /// If mode is nt.P_WAIT then then the call blocks until the process exits and the return value
  420. /// is the exit code.
  421. ///
  422. /// Otherwise the call returns a handle to the process. The caller must then call nt.waitpid(pid, options)
  423. /// to free the handle and get the exit code of the process. Failure to call nt.waitpid will result
  424. /// in a handle leak.
  425. /// </summary>
  426. public static object spawnle(CodeContext/*!*/ context, int mode, string path, params object[] args) {
  427. if (args.Length < 1) {
  428. throw PythonOps.TypeError("spawnle() takes at least three arguments ({0} given)", 2 + args.Length);
  429. }
  430. object env = args[args.Length - 1];
  431. object[] slicedArgs = ArrayUtils.RemoveFirst(args);
  432. Process process = MakeProcess();
  433. SetEnvironment(process.StartInfo.EnvironmentVariables, env);
  434. return SpawnProcessImpl(context, process, mode, path, slicedArgs);
  435. }
  436. /// <summary>
  437. /// spawns a new process.
  438. ///
  439. /// If mode is nt.P_WAIT then then the call blocks until the process exits and the return value
  440. /// is the exit code.
  441. ///
  442. /// Otherwise the call returns a handle to the process. The caller must then call nt.waitpid(pid, options)
  443. /// to free the handle and get the exit code of the process. Failure to call nt.waitpid will result
  444. /// in a handle leak.
  445. /// </summary>
  446. public static object spawnv(CodeContext/*!*/ context, int mode, string path, object args) {
  447. return SpawnProcessImpl(context, MakeProcess(), mode, path, args);
  448. }
  449. /// <summary>
  450. /// spawns a new process.
  451. ///
  452. /// If mode is nt.P_WAIT then then the call blocks until the process exits and the return value
  453. /// is the exit code.
  454. ///
  455. /// Otherwise the call returns a handle to the process. The caller must then call nt.waitpid(pid, options)
  456. /// to free the handle and get the exit code of the process. Failure to call nt.waitpid will result
  457. /// in a handle leak.
  458. /// </summary>
  459. public static object spawnve(CodeContext/*!*/ context, int mode, string path, object args, object env) {
  460. Process process = MakeProcess();
  461. SetEnvironment(process.StartInfo.EnvironmentVariables, env);
  462. return SpawnProcessImpl(context, process, mode, path, args);
  463. }
  464. private static Process MakeProcess() {
  465. try {
  466. return new Process();
  467. } catch (Exception e) {
  468. throw ToPythonException(e);
  469. }
  470. }
  471. private static object SpawnProcessImpl(CodeContext/*!*/ context, Process process, int mode, string path, object args) {
  472. try {
  473. process.StartInfo.Arguments = ArgumentsToString(context, args);
  474. process.StartInfo.FileName = path;
  475. process.StartInfo.UseShellExecute = false;
  476. } catch (Exception e) {
  477. throw ToPythonException(e, path);
  478. }
  479. if (!process.Start()) {
  480. throw PythonOps.OSError("Cannot start process: {0}", path);
  481. }
  482. if (mode == P_WAIT) {
  483. process.WaitForExit();
  484. int exitCode = process.ExitCode;
  485. process.Close();
  486. return exitCode;
  487. }
  488. lock (_processToIdMapping) {
  489. int id;
  490. if (_freeProcessIds.Count > 0) {
  491. id = _freeProcessIds[_freeProcessIds.Count - 1];
  492. _freeProcessIds.RemoveAt(_freeProcessIds.Count - 1);
  493. } else {
  494. // process IDs are handles on CPython/Win32 so we match
  495. // that behavior and return something that is handle like. Handles
  496. // on NT are guaranteed to have the low 2 bits not set and users
  497. // could use these for their own purposes. We therefore match that
  498. // behavior here.
  499. _processCount += 4;
  500. id = _processCount;
  501. }
  502. _processToIdMapping[id] = process;
  503. return ScriptingRuntimeHelpers.Int32ToObject(id);
  504. }
  505. }
  506. /// <summary>
  507. /// Copy elements from a Python mapping of dict environment variables to a StringDictionary.
  508. /// </summary>
  509. private static void SetEnvironment(System.Collections.Specialized.StringDictionary currentEnvironment, object newEnvironment) {
  510. PythonDictionary env = newEnvironment as PythonDictionary;
  511. if (env == null) {
  512. throw PythonOps.TypeError("env argument must be a dict");
  513. }
  514. currentEnvironment.Clear();
  515. string strKey, strValue;
  516. foreach (object key in env.keys()) {
  517. if (!Converter.TryConvertToString(key, out strKey)) {
  518. throw PythonOps.TypeError("env dict contains a non-string key");
  519. }
  520. if (!Converter.TryConvertToString(env[key], out strValue)) {
  521. throw PythonOps.TypeError("env dict contains a non-string value");
  522. }
  523. currentEnvironment[strKey] = strValue;
  524. }
  525. }
  526. #endif
  527. /// <summary>
  528. /// Convert a sequence of args to a string suitable for using to spawn a process.
  529. /// </summary>
  530. private static string ArgumentsToString(CodeContext/*!*/ context, object args) {
  531. IEnumerator argsEnumerator;
  532. System.Text.StringBuilder sb = null;
  533. if (!PythonOps.TryGetEnumerator(context, args, out argsEnumerator)) {
  534. throw PythonOps.TypeError("args parameter must be sequence, not {0}", DynamicHelpers.GetPythonType(args));
  535. }
  536. bool space = false;
  537. try {
  538. // skip the first element, which is the name of the command being run
  539. argsEnumerator.MoveNext();
  540. while (argsEnumerator.MoveNext()) {
  541. if (sb == null) sb = new System.Text.StringBuilder(); // lazy creation
  542. string strarg = PythonOps.ToString(argsEnumerator.Current);
  543. if (space) {
  544. sb.Append(' ');
  545. }
  546. if (strarg.IndexOf(' ') != -1) {
  547. sb.Append('"');
  548. // double quote any existing quotes
  549. sb.Append(strarg.Replace("\"", "\"\""));
  550. sb.Append('"');
  551. } else {
  552. sb.Append(strarg);
  553. }
  554. space = true;
  555. }
  556. } finally {
  557. IDisposable disposable = argsEnumerator as IDisposable;
  558. if (disposable != null) disposable.Dispose();
  559. }
  560. if (sb == null) return "";
  561. return sb.ToString();
  562. }
  563. #if !SILVERLIGHT
  564. public static void startfile(string filename, [DefaultParameterValue("open")]string operation) {
  565. System.Diagnostics.Process process = new System.Diagnostics.Process();
  566. process.StartInfo.FileName = filename;
  567. process.StartInfo.UseShellExecute = true;
  568. process.StartInfo.Verb = operation;
  569. try {
  570. process.Start();
  571. } catch (Exception e) {
  572. throw ToPythonException(e, filename);
  573. }
  574. }
  575. #endif
  576. [PythonType, DontMapIEnumerableToIter]
  577. public class stat_result : IList, IList<object> {
  578. private readonly object _mode, _size, _atime, _mtime, _ctime, _st_atime, _st_mtime, _st_ctime, _ino, _dev, _nlink, _uid, _gid;
  579. public const int n_fields = 13;
  580. public const int n_sequence_fields = 10;
  581. public const int n_unnamed_fields = 3;
  582. internal stat_result(int mode) : this(mode, BigInteger.Zero, BigInteger.Zero, BigInteger.Zero, BigInteger.Zero) {
  583. _mode = mode;
  584. }
  585. internal stat_result(int mode, BigInteger size, BigInteger st_atime, BigInteger st_mtime, BigInteger st_ctime) {
  586. _mode = mode;
  587. _size = size;
  588. _st_atime = _atime = TryShrinkToInt(st_atime);
  589. _st_mtime = _mtime = TryShrinkToInt(st_mtime);
  590. _st_ctime = _ctime = TryShrinkToInt(st_ctime);
  591. _ino = _dev = _nlink = _uid = _gid = ScriptingRuntimeHelpers.Int32ToObject(0);
  592. }
  593. public stat_result(CodeContext/*!*/ context, IList statResult, [DefaultParameterValue(null)]PythonDictionary dict) {
  594. // dict is allowed by CPython's stat_result, but doesn't seem to do anything, so we ignore it here.
  595. if (statResult.Count < 10) {
  596. throw PythonOps.TypeError("stat_result() takes an at least 10-sequence ({0}-sequence given)", statResult.Count);
  597. }
  598. _mode = statResult[0];
  599. _ino = statResult[1];
  600. _dev = statResult[2];
  601. _nlink = statResult[3];
  602. _uid = statResult[4];
  603. _gid = statResult[5];
  604. _size = statResult[6];
  605. _atime = statResult[7];
  606. _mtime = statResult[8];
  607. _ctime = statResult[9];
  608. object dictTime;
  609. if (statResult.Count >= 11) {
  610. _st_atime = TryShrinkToInt(statResult[10]);
  611. } else if (TryGetDictValue(dict, "st_atime", out dictTime)) {
  612. _st_atime = dictTime;
  613. } else {
  614. _st_atime = TryShrinkToInt(_atime);
  615. }
  616. if (statResult.Count >= 12) {
  617. _st_mtime = TryShrinkToInt(statResult[11]);
  618. } else if (TryGetDictValue(dict, "st_mtime", out dictTime)) {
  619. _st_mtime = dictTime;
  620. } else {
  621. _st_mtime = TryShrinkToInt(_mtime);
  622. }
  623. if (statResult.Count >= 13) {
  624. _st_ctime = TryShrinkToInt(statResult[12]);
  625. } else if (TryGetDictValue(dict, "st_ctime", out dictTime)) {
  626. _st_ctime = dictTime;
  627. } else {
  628. _st_ctime = TryShrinkToInt(_ctime);
  629. }
  630. }
  631. private static bool TryGetDictValue(PythonDictionary dict, string name, out object dictTime) {
  632. if (dict != null && dict.TryGetValue(name, out dictTime)) {
  633. dictTime = TryShrinkToInt(dictTime);
  634. return true;
  635. }
  636. dictTime = null;
  637. return false;
  638. }
  639. private static object TryShrinkToInt(object value) {
  640. if (!(value is BigInteger)) {
  641. return value;
  642. }
  643. return BigIntegerOps.__int__((BigInteger)value);
  644. }
  645. public object st_atime {
  646. get {
  647. return _st_atime;
  648. }
  649. }
  650. public object st_ctime {
  651. get {
  652. return _st_ctime;
  653. }
  654. }
  655. public object st_mtime {
  656. get {
  657. return _st_mtime;
  658. }
  659. }
  660. public object st_dev {
  661. get {
  662. return TryShrinkToInt(_dev);
  663. }
  664. }
  665. public object st_gid {
  666. get {
  667. return _gid;
  668. }
  669. }
  670. public object st_ino {
  671. get {
  672. return _ino;
  673. }
  674. }
  675. public object st_mode {
  676. get {
  677. return TryShrinkToInt(_mode);
  678. }
  679. }
  680. public object st_nlink {
  681. get {
  682. return TryShrinkToInt(_nlink);
  683. }
  684. }
  685. public object st_size {
  686. get {
  687. return _size;
  688. }
  689. }
  690. public object st_uid {
  691. get {
  692. return _uid;
  693. }
  694. }
  695. public static PythonTuple operator +(stat_result stat, object tuple) {
  696. PythonTuple tupleObj = tuple as PythonTuple;
  697. if (tupleObj == null) {
  698. throw PythonOps.TypeError("can only concatenate tuple (not \"{0}\") to tuple", PythonTypeOps.GetName(tuple));
  699. }
  700. return stat.MakeTuple() + tupleObj;
  701. }
  702. public static bool operator >(stat_result stat, [NotNull]stat_result o) {
  703. return stat.MakeTuple() > PythonTuple.Make(o);
  704. }
  705. public static bool operator <(stat_result stat, [NotNull]stat_result o) {
  706. return stat.MakeTuple() < PythonTuple.Make(o);
  707. }
  708. public static bool operator >=(stat_result stat, [NotNull]stat_result o) {
  709. return stat.MakeTuple() >= PythonTuple.Make(o);
  710. }
  711. public static bool operator <=(stat_result stat, [NotNull]stat_result o) {
  712. return stat.MakeTuple() <= PythonTuple.Make(o);
  713. }
  714. public static bool operator >(stat_result stat, object o) {
  715. return true;
  716. }
  717. public static bool operator <(stat_result stat, object o) {
  718. return false;
  719. }
  720. public static bool operator >=(stat_result stat, object o) {
  721. return true;
  722. }
  723. public static bool operator <=(stat_result stat, object o) {
  724. return false;
  725. }
  726. public static PythonTuple operator *(stat_result stat, int size) {
  727. return stat.MakeTuple() * size;
  728. }
  729. public static PythonTuple operator *(int size, stat_result stat) {
  730. return stat.MakeTuple() * size;
  731. }
  732. public override string ToString() {
  733. return MakeTuple().ToString();
  734. }
  735. public string/*!*/ __repr__() {
  736. return ToString();
  737. }
  738. public PythonTuple __reduce__() {
  739. PythonDictionary timeDict = new PythonDictionary(3);
  740. timeDict["st_atime"] = st_atime;
  741. timeDict["st_ctime"] = st_ctime;
  742. timeDict["st_mtime"] = st_mtime;
  743. return PythonTuple.MakeTuple(
  744. DynamicHelpers.GetPythonTypeFromType(typeof(stat_result)),
  745. PythonTuple.MakeTuple(MakeTuple(), timeDict)
  746. );
  747. }
  748. #region ISequence Members
  749. //public object AddSequence(object other) {
  750. // return MakeTuple().AddSequence(other);
  751. //}
  752. //public object MultiplySequence(object count) {
  753. // return MakeTuple().MultiplySequence(count);
  754. //}
  755. public object this[int index] {
  756. get {
  757. return MakeTuple()[index];
  758. }
  759. }
  760. public object this[Slice slice] {
  761. get {
  762. return MakeTuple()[slice];
  763. }
  764. }
  765. public object __getslice__(int start, int stop) {
  766. return MakeTuple().__getslice__(start, stop);
  767. }
  768. public int __len__() {
  769. return MakeTuple().__len__();
  770. }
  771. public bool __contains__(object item) {
  772. return ((ICollection<object>)MakeTuple()).Contains(item);
  773. }
  774. #endregion
  775. private PythonTuple MakeTuple() {
  776. return PythonTuple.MakeTuple(
  777. st_mode,
  778. st_ino,
  779. st_dev,
  780. st_nlink,
  781. st_uid,
  782. st_gid,
  783. st_size,
  784. _atime,
  785. _mtime,
  786. _ctime
  787. );
  788. }
  789. #region Object overrides
  790. public override bool Equals(object obj) {
  791. if (obj is stat_result) {
  792. return MakeTuple().Equals(((stat_result)obj).MakeTuple());
  793. } else {
  794. return MakeTuple().Equals(obj);
  795. }
  796. }
  797. public override int GetHashCode() {
  798. return MakeTuple().GetHashCode();
  799. }
  800. #endregion
  801. #region IList<object> Members
  802. int IList<object>.IndexOf(object item) {
  803. return MakeTuple().IndexOf(item);
  804. }
  805. void IList<object>.Insert(int index, object item) {
  806. throw new InvalidOperationException();
  807. }
  808. void IList<object>.RemoveAt(int index) {
  809. throw new InvalidOperationException();
  810. }
  811. object IList<object>.this[int index] {
  812. get {
  813. return MakeTuple()[index];
  814. }
  815. set {
  816. throw new InvalidOperationException();
  817. }
  818. }
  819. #endregion
  820. #region ICollection<object> Members
  821. void ICollection<object>.Add(object item) {
  822. throw new InvalidOperationException();
  823. }
  824. void ICollection<object>.Clear() {
  825. throw new InvalidOperationException();
  826. }
  827. bool ICollection<object>.Contains(object item) {
  828. return __contains__(item);
  829. }
  830. void ICollection<object>.CopyTo(object[] array, int arrayIndex) {
  831. throw new NotImplementedException();
  832. }
  833. int ICollection<object>.Count {
  834. get { return __len__(); }
  835. }
  836. bool ICollection<object>.IsReadOnly {
  837. get { return true; }
  838. }
  839. bool ICollection<object>.Remove(object item) {
  840. throw new InvalidOperationException();
  841. }
  842. #endregion
  843. #region IEnumerable<object> Members
  844. IEnumerator<object> IEnumerable<object>.GetEnumerator() {
  845. foreach (object o in MakeTuple()) {
  846. yield return o;
  847. }
  848. }
  849. #endregion
  850. #region IEnumerable Members
  851. IEnumerator IEnumerable.GetEnumerator() {
  852. foreach (object o in MakeTuple()) {
  853. yield return o;
  854. }
  855. }
  856. #endregion
  857. #region IList Members
  858. int IList.Add(object value) {
  859. throw new InvalidOperationException();
  860. }
  861. void IList.Clear() {
  862. throw new InvalidOperationException();
  863. }
  864. bool IList.Contains(object value) {
  865. return __contains__(value);
  866. }
  867. int IList.IndexOf(object value) {
  868. return MakeTuple().IndexOf(value);
  869. }
  870. void IList.Insert(int index, object value) {
  871. throw new InvalidOperationException();
  872. }
  873. bool IList.IsFixedSize {
  874. get { return true; }
  875. }
  876. bool IList.IsReadOnly {
  877. get { return true; }
  878. }
  879. void IList.Remove(object value) {
  880. throw new InvalidOperationException();
  881. }
  882. void IList.RemoveAt(int index) {
  883. throw new InvalidOperationException();
  884. }
  885. object IList.this[int index] {
  886. get {
  887. return MakeTuple()[index];
  888. }
  889. set {
  890. throw new InvalidOperationException();
  891. }
  892. }
  893. #endregion
  894. #region ICollection Members
  895. void ICollection.CopyTo(Array array, int index) {
  896. throw new NotImplementedException();
  897. }
  898. int ICollection.Count {
  899. get { return __len__(); }
  900. }
  901. bool ICollection.IsSynchronized {
  902. get { return false; }
  903. }
  904. object ICollection.SyncRoot {
  905. get { return this; }
  906. }
  907. #endregion
  908. }
  909. private static bool HasExecutableExtension(string path) {
  910. string extension = Path.GetExtension(path).ToLower(CultureInfo.InvariantCulture);
  911. return (extension == ".exe" || extension == ".dll" || extension == ".com" || extension == ".bat");
  912. }
  913. [Documentation("stat(path) -> stat result\nGathers statistics about the specified file or directory")]
  914. public static object stat(string path) {
  915. if (path == null) throw PythonOps.TypeError("expected string, got NoneType");
  916. stat_result sr;
  917. try {
  918. FileInfo fi = new FileInfo(path);
  919. int mode = 0;
  920. long size;
  921. if (Directory.Exists(path)) {
  922. size = 0;
  923. mode = 0x4000 | S_IEXEC;
  924. } else if (File.Exists(path)) {
  925. size = fi.Length;
  926. mode = 0x8000;
  927. if (HasExecutableExtension(path)) {
  928. mode |= S_IEXEC;
  929. }
  930. } else {
  931. throw PythonExceptions.CreateThrowable(WindowsError, PythonExceptions._WindowsError.ERROR_PATH_NOT_FOUND, "file does not exist: " + path);
  932. }
  933. long st_atime = (long)PythonTime.TicksToTimestamp(fi.LastAccessTime.ToUniversalTime().Ticks);
  934. long st_ctime = (long)PythonTime.TicksToTimestamp(fi.CreationTime.ToUniversalTime().Ticks);
  935. long st_mtime = (long)PythonTime.TicksToTimestamp(fi.LastWriteTime.ToUniversalTime().Ticks);
  936. mode |= S_IREAD;
  937. if ((fi.Attributes & FileAttributes.ReadOnly) == 0) {
  938. mode |= S_IWRITE;
  939. }
  940. sr = new stat_result(mode, size, st_atime, st_mtime, st_ctime);
  941. } catch (ArgumentException) {
  942. throw PythonExceptions.CreateThrowable(WindowsError, PythonExceptions._WindowsError.ERROR_INVALID_NAME, "The path is invalid: " + path);
  943. } catch (Exception e) {
  944. throw ToPythonException(e, path);
  945. }
  946. return sr;
  947. }
  948. public static string strerror(int code) {
  949. switch(code) {
  950. case 0: return "No error";
  951. case PythonErrorNumber.E2BIG: return "Arg list too long";
  952. case PythonErrorNumber.EACCES: return "Permission denied";
  953. case PythonErrorNumber.EAGAIN: return "Resource temporarily unavailable";
  954. case PythonErrorNumber.EBADF: return "Bad file descriptor";
  955. case PythonErrorNumber.EBUSY: return "Resource device";
  956. case PythonErrorNumber.ECHILD: return "No child processes";
  957. case PythonErrorNumber.EDEADLK: return "Resource deadlock avoided";
  958. case PythonErrorNumber.EDOM: return "Domain error";
  959. case PythonErrorNumber.EDQUOT: return "Unknown error";
  960. case PythonErrorNumber.EEXIST: return "File exists";
  961. case PythonErrorNumber.EFAULT: return "Bad address";
  962. case PythonErrorNumber.EFBIG: return "File too large";
  963. case PythonErrorNumber.EILSEQ: return "Illegal byte sequence";
  964. case PythonErrorNumber.EINTR: return "Interrupted function call";
  965. case PythonErrorNumber.EINVAL: return "Invalid argument";
  966. case PythonErrorNumber.EIO: return "Input/output error";
  967. case PythonErrorNumber.EISCONN: return "Unknown error";
  968. case PythonErrorNumber.EISDIR: return "Is a directory";
  969. case PythonErrorNumber.EMFILE: return "Too many open files";
  970. case PythonErrorNumber.EMLINK: return "Too many links";
  971. case PythonErrorNumber.ENAMETOOLONG: return "Filename too long";
  972. case PythonErrorNumber.ENFILE: return "Too many open files in system";
  973. case PythonErrorNumber.ENODEV: return "No such device";
  974. case PythonErrorNumber.ENOENT: return "No such file or directory";
  975. case PythonErrorNumber.ENOEXEC: return "Exec format error";
  976. case PythonErrorNumber.ENOLCK: return "No locks available";
  977. case PythonErrorNumber.ENOMEM: return "Not enough space";
  978. case PythonErrorNumber.ENOSPC: return "No space left on device";
  979. case PythonErrorNumber.ENOSYS: return "Function not implemented";
  980. case PythonErrorNumber.ENOTDIR: return "Not a directory";
  981. case PythonErrorNumber.ENOTEMPTY: return "Directory not empty";
  982. case PythonErrorNumber.ENOTSOCK: return "Unknown error";
  983. case PythonErrorNumber.ENOTTY: return "Inappropriate I/O control operation";
  984. case PythonErrorNumber.ENXIO: return "No such device or address";
  985. case PythonErrorNumber.EPERM: return "Operation not permitted";
  986. case PythonErrorNumber.EPIPE: return "Broken pipe";
  987. case PythonErrorNumber.ERANGE: return "Result too large";
  988. case PythonErrorNumber.EROFS: return "Read-only file system";
  989. case PythonErrorNumber.ESPIPE: return "Invalid seek";
  990. case PythonErrorNumber.ESRCH: return "No such process";
  991. case PythonErrorNumber.EXDEV: return "Improper link";
  992. default:
  993. return "Unknown error " + code;
  994. }
  995. }
  996. private static PythonType WindowsError {
  997. get {
  998. #if !SILVERLIGHT
  999. return PythonExceptions.WindowsError;
  1000. #else
  1001. return PythonExceptions.OSError;
  1002. #endif
  1003. }
  1004. }
  1005. #if !SILVERLIGHT
  1006. [Documentation("system(command) -> int\nExecute the command (a string) in a subshell.")]
  1007. public static int system(string command) {
  1008. ProcessStartInfo psi = GetProcessInfo(command);
  1009. psi.CreateNoWindow = false;
  1010. try {
  1011. Process process = Process.Start(psi);
  1012. if (process == null) {
  1013. return -1;
  1014. }
  1015. process.WaitForExit();
  1016. return process.ExitCode;
  1017. } catch (Win32Exception) {
  1018. return 1;
  1019. }
  1020. }
  1021. public static string tempnam(CodeContext/*!*/ context) {
  1022. return tempnam(context, null);
  1023. }
  1024. public static string tempnam(CodeContext/*!*/ context, string dir) {
  1025. return tempnam(context, null, null);
  1026. }
  1027. public static string tempnam(CodeContext/*!*/ context, string dir, string prefix) {
  1028. PythonOps.Warn(context, PythonExceptions.RuntimeWarning, "tempnam is a potential security risk to your program");
  1029. try {
  1030. dir = Path.GetTempPath(); // Reasonably consistent with CPython behavior under Windows
  1031. return Path.GetFullPath(Path.Combine(dir, prefix ?? String.Empty) + Path.GetRandomFileName());
  1032. } catch (Exception e) {
  1033. throw ToPythonException(e, dir);
  1034. }
  1035. }
  1036. public static object times() {
  1037. System.Diagnostics.Process p = System.Diagnostics.Process.GetCurrentProcess();
  1038. return PythonTuple.MakeTuple(p.UserProcessorTime.TotalSeconds,
  1039. p.PrivilegedProcessorTime.TotalSeconds,
  1040. 0, // child process system time
  1041. 0, // child process os time
  1042. DateTime.Now.Subtract(p.StartTime).TotalSeconds);
  1043. }
  1044. #endif
  1045. #if !SILVERLIGHT
  1046. public static PythonFile/*!*/ tmpfile(CodeContext/*!*/ context) {
  1047. try {
  1048. FileStream sw = new FileStream(Path.GetTempFileName(), FileMode.Open, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
  1049. PythonFile res = PythonFile.Create(context, sw, sw.Name, "w+b");
  1050. return res;
  1051. } catch (Exception e) {
  1052. throw ToPythonException(e);
  1053. }

Large files files are truncated, but you can click here to view the full file