PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Cli/Microsoft.DotNet.Cli.Utils/RuntimeEnvironment.cs

https://gitlab.com/dotnetfoundation/sdk
C# | 263 lines | 200 code | 26 blank | 37 comment | 24 complexity | 6b487fa3ffd78d9caf06d9a2e7539555 MD5 | raw file
  1. // Copyright (c) .NET Foundation and contributors. All rights reserved.
  2. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
  3. using System;
  4. using System.IO;
  5. using System.Runtime.InteropServices;
  6. namespace Microsoft.DotNet.Cli.Utils
  7. {
  8. internal enum Platform
  9. {
  10. Unknown = 0,
  11. Windows = 1,
  12. Linux = 2,
  13. Darwin = 3,
  14. FreeBSD = 4,
  15. illumos = 5,
  16. Solaris = 6
  17. }
  18. internal static class RuntimeEnvironment
  19. {
  20. private static readonly Lazy<Platform> _platform = new Lazy<Platform>(DetermineOSPlatform);
  21. private static readonly Lazy<DistroInfo> _distroInfo = new Lazy<DistroInfo>(LoadDistroInfo);
  22. public static Platform OperatingSystemPlatform { get; } = GetOSPlatform();
  23. public static string OperatingSystemVersion { get; } = GetOSVersion();
  24. public static string OperatingSystem { get; } = GetOSName();
  25. private class DistroInfo
  26. {
  27. public string Id;
  28. public string VersionId;
  29. }
  30. private static string GetOSName()
  31. {
  32. switch (GetOSPlatform())
  33. {
  34. case Platform.Windows:
  35. return nameof(Platform.Windows);
  36. case Platform.Linux:
  37. return GetDistroId() ?? nameof(Platform.Linux);
  38. case Platform.Darwin:
  39. return "Mac OS X";
  40. case Platform.FreeBSD:
  41. return nameof(Platform.FreeBSD);
  42. case Platform.illumos:
  43. return GetDistroId() ?? nameof(Platform.illumos);
  44. case Platform.Solaris:
  45. return nameof(Platform.Solaris);
  46. default:
  47. return nameof(Platform.Unknown);
  48. }
  49. }
  50. private static string GetOSVersion()
  51. {
  52. switch (GetOSPlatform())
  53. {
  54. case Platform.Windows:
  55. return Environment.OSVersion.Version.ToString(3);
  56. case Platform.Linux:
  57. case Platform.illumos:
  58. return GetDistroVersionId() ?? string.Empty;
  59. case Platform.Darwin:
  60. return Environment.OSVersion.Version.ToString(2);
  61. case Platform.FreeBSD:
  62. return GetFreeBSDVersion() ?? string.Empty;
  63. case Platform.Solaris:
  64. // RuntimeInformation.OSDescription example on Solaris 11.3: SunOS 5.11 11.3
  65. // we only need the major version; 11
  66. return RuntimeInformation.OSDescription.Split(' ')[2].Split('.')[0];
  67. default:
  68. return string.Empty;
  69. }
  70. }
  71. private static string GetFreeBSDVersion()
  72. {
  73. // This is same as sysctl kern.version
  74. // FreeBSD 11.0-RELEASE-p1 FreeBSD 11.0-RELEASE-p1 #0 r306420: Thu Sep 29 01:43:23 UTC 2016 root@releng2.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC
  75. // What we want is major release as minor releases should be compatible.
  76. String version = RuntimeInformation.OSDescription;
  77. try
  78. {
  79. // second token up to first dot
  80. return RuntimeInformation.OSDescription.Split()[1].Split('.')[0];
  81. }
  82. catch
  83. {
  84. }
  85. return string.Empty;
  86. }
  87. private static Platform GetOSPlatform()
  88. {
  89. return _platform.Value;
  90. }
  91. private static string GetDistroId()
  92. {
  93. return _distroInfo.Value?.Id;
  94. }
  95. private static string GetDistroVersionId()
  96. {
  97. return _distroInfo.Value?.VersionId;
  98. }
  99. private static DistroInfo LoadDistroInfo()
  100. {
  101. switch (GetOSPlatform())
  102. {
  103. case Platform.Linux:
  104. return LoadDistroInfoFromLinux();
  105. case Platform.illumos:
  106. return LoadDistroInfoFromIllumos();
  107. }
  108. return null;
  109. }
  110. private static DistroInfo LoadDistroInfoFromLinux()
  111. {
  112. DistroInfo result = null;
  113. // Sample os-release file:
  114. // NAME="Ubuntu"
  115. // VERSION = "14.04.3 LTS, Trusty Tahr"
  116. // ID = ubuntu
  117. // ID_LIKE = debian
  118. // PRETTY_NAME = "Ubuntu 14.04.3 LTS"
  119. // VERSION_ID = "14.04"
  120. // HOME_URL = "http://www.ubuntu.com/"
  121. // SUPPORT_URL = "http://help.ubuntu.com/"
  122. // BUG_REPORT_URL = "http://bugs.launchpad.net/ubuntu/"
  123. // We use ID and VERSION_ID
  124. if (File.Exists("/etc/os-release"))
  125. {
  126. var lines = File.ReadAllLines("/etc/os-release");
  127. result = new DistroInfo();
  128. foreach (var line in lines)
  129. {
  130. if (line.StartsWith("ID=", StringComparison.Ordinal))
  131. {
  132. result.Id = line.Substring(3).Trim('"', '\'');
  133. }
  134. else if (line.StartsWith("VERSION_ID=", StringComparison.Ordinal))
  135. {
  136. result.VersionId = line.Substring(11).Trim('"', '\'');
  137. }
  138. }
  139. }
  140. if (result != null)
  141. {
  142. result = NormalizeDistroInfo(result);
  143. }
  144. return result;
  145. }
  146. private static DistroInfo LoadDistroInfoFromIllumos()
  147. {
  148. DistroInfo result = null;
  149. // examples:
  150. // on OmniOS
  151. // SunOS 5.11 omnios-r151018-95eaa7e
  152. // on OpenIndiana Hipster:
  153. // SunOS 5.11 illumos-63878f749f
  154. // on SmartOS:
  155. // SunOS 5.11 joyent_20200408T231825Z
  156. var versionDescription = RuntimeInformation.OSDescription.Split(' ')[2];
  157. switch (versionDescription)
  158. {
  159. case string version when version.StartsWith("omnios"):
  160. result = new DistroInfo
  161. {
  162. Id = "OmniOS",
  163. VersionId = version.Substring("omnios-r".Length, 2) // e.g. 15
  164. };
  165. break;
  166. case string version when version.StartsWith("joyent"):
  167. result = new DistroInfo
  168. {
  169. Id = "SmartOS",
  170. VersionId = version.Substring("joyent_".Length, 4) // e.g. 2020
  171. };
  172. break;
  173. case string version when version.StartsWith("illumos"):
  174. result = new DistroInfo
  175. {
  176. Id = "OpenIndiana"
  177. // version-less
  178. };
  179. break;
  180. }
  181. return result;
  182. }
  183. // For some distros, we don't want to use the full version from VERSION_ID. One example is
  184. // Red Hat Enterprise Linux, which includes a minor version in their VERSION_ID but minor
  185. // versions are backwards compatable.
  186. //
  187. // In this case, we'll normalized RIDs like 'rhel.7.2' and 'rhel.7.3' to a generic
  188. // 'rhel.7'. This brings RHEL in line with other distros like CentOS or Debian which
  189. // don't put minor version numbers in their VERSION_ID fields because all minor versions
  190. // are backwards compatible.
  191. private static DistroInfo NormalizeDistroInfo(DistroInfo distroInfo)
  192. {
  193. // Handle if VersionId is null by just setting the index to -1.
  194. int lastVersionNumberSeparatorIndex = distroInfo.VersionId?.IndexOf('.') ?? -1;
  195. if (lastVersionNumberSeparatorIndex != -1 && distroInfo.Id == "alpine")
  196. {
  197. // For Alpine, the version reported has three components, so we need to find the second version separator
  198. lastVersionNumberSeparatorIndex = distroInfo.VersionId.IndexOf('.', lastVersionNumberSeparatorIndex + 1);
  199. }
  200. if (lastVersionNumberSeparatorIndex != -1 && (distroInfo.Id == "rhel" || distroInfo.Id == "alpine"))
  201. {
  202. distroInfo.VersionId = distroInfo.VersionId.Substring(0, lastVersionNumberSeparatorIndex);
  203. }
  204. return distroInfo;
  205. }
  206. private static Platform DetermineOSPlatform()
  207. {
  208. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
  209. {
  210. return Platform.Windows;
  211. }
  212. if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
  213. {
  214. return Platform.Linux;
  215. }
  216. if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
  217. {
  218. return Platform.Darwin;
  219. }
  220. #if NETCOREAPP
  221. if (RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD))
  222. {
  223. return Platform.FreeBSD;
  224. }
  225. if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("ILLUMOS")))
  226. {
  227. return Platform.illumos;
  228. }
  229. if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("SOLARIS")))
  230. {
  231. return Platform.Solaris;
  232. }
  233. #endif
  234. return Platform.Unknown;
  235. }
  236. }
  237. }