-
Notifications
You must be signed in to change notification settings - Fork 4.9k
[WIP] Move Console usage of stat wrapper to new IO shim #2303
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,11 @@ We have the following goals related to interop code being used in CoreFX: | |
| - This is both for good hygiene and to help keep platform-specific code | ||
| separated from platform-neutral code, which is important for maximizing | ||
| reusable code above PAL layers. | ||
| - Ensure maximal managed code reuse across different OS flavors which have | ||
| the same API but not the same ABI. | ||
| - This is the case for UNIX and addressing it is a work-in-progress (see issue | ||
| #2137 and section on "shims" below.) | ||
|
|
||
|
|
||
| ## Approach | ||
|
|
||
|
|
@@ -244,3 +249,42 @@ rather than the underlying integral type. | |
| should be named with the most discoverable name possible; if that name | ||
| is a concept (e.g. Errors), it can be named using managed naming | ||
| guidelines. | ||
|
|
||
|
|
||
| ## UNIX shims | ||
|
|
||
| Often, various UNIX flavors offer the same API from the point-of-view of compatibility | ||
| with C/C++ source code, but they do not have the same ABI. e.g. Fields can be laid out | ||
| differently, constants can have different numeric values, etc. | ||
|
|
||
| This leaves us with a situation where we can't write portable P/Invoke declarations | ||
| that will work on all flavors, and writing separate declarations per flavor won't scale. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And is quite fragile. |
||
|
|
||
| To address this, we're moving to a model where all UNIX interop from corefx starts with | ||
| a P/Invoke to a C++ lib written specifically for corefx. These libs -- libcorefx_*.so | ||
| (aka "shims") -- are intended to be very thin layer over underlying platform libraries. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: "thin layer" => "thin layers" |
||
| Generally, they are not there to add any significant abstraction, but to create a | ||
| stable ABI such that the same IL assembly can work across UNIX flavors. | ||
|
|
||
| At this time, these shims are compiled in the dotnet/coreclr repository under the corefx | ||
| folder. This is temporary (issue #2301) until we add necessary infrastructure to build them | ||
| in this repository. | ||
|
|
||
| Guidelines for shim C++ API: | ||
|
|
||
| - Keep them as "thin"/1:1 as possible. | ||
| - We want to write the majority of code in C#. | ||
| - Never skip the shim and P/Invoke directly to the underlying platform API. It's | ||
| easy to assume something is safe/guaranteed when it isn't. | ||
| - Don't cheat and take advantage of coincidental agreement between | ||
| one flavor's ABI and the shim's ABI. | ||
| - Use PascalCase and spell things out in a style closer to Win32 than libc. | ||
| - At first, it seemed that we'd want to use 1:1 names for the shims, but it | ||
| turns out there are many cases where being strictly 1:1 isn't practical. As such, | ||
| the libraries will end up looking more self-consistent if we give them their | ||
| own style with which to express themselves. | ||
| - Stick to data types which are guaranteed not to vary in size across flavors. (Pointers | ||
| and size_t variance across bitness is OK.) | ||
| - e.g. use int32_t, int64_t from stdint.h and not int, long. | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
| // Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
|
||
| using System; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| internal static partial class Interop | ||
| { | ||
| internal static partial class libcorefx_io | ||
| { | ||
| internal struct FileStats | ||
| { | ||
| private FileStatsFlags Flags; | ||
| internal int Mode; | ||
| internal int Uid; | ||
| internal int Gid; | ||
| internal int Size; | ||
| internal int AccessTime; | ||
| internal int ModificationTime; | ||
| internal int StatusChangeTime; | ||
| internal int CreationTime; | ||
| } | ||
|
|
||
| internal static class FileTypes | ||
| { | ||
| internal const int S_IFMT = 0xF000; | ||
| internal const int S_IFIFO = 0x1000; | ||
| internal const int S_IFCHR = 0x2000; | ||
| internal const int S_IFDIR = 0x4000; | ||
| internal const int S_IFREG = 0x8000; | ||
| internal const int S_IFLNK = 0xA000; | ||
| } | ||
|
|
||
| [Flags] | ||
| internal enum FileStatsFlags | ||
| { | ||
| None = 0, | ||
| HasCreationTime = 1, | ||
| } | ||
|
|
||
|
|
||
| [DllImport(Libraries.LibCoreFxIO, SetLastError = true)] | ||
| internal static extern int GetFileStatsFromDescriptor(int fileDescriptor, out FileStats output); | ||
|
|
||
| [DllImport(Libraries.LibCoreFxIO, SetLastError = true)] | ||
| internal static extern int GetFileStatsFromPath(string path, out FileStats output); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we have both of these Interop.libcorefx_io.cs and Interop.GetFileStat.cs files?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. :) |
||
| // Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
|
||
| using System; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| internal static partial class Interop | ||
| { | ||
| internal static partial class libcorefx_io | ||
| { | ||
| internal struct FileStats | ||
| { | ||
| private Flags Flags; | ||
| internal int Mode; | ||
| internal int Uid; | ||
| internal int Gid; | ||
| internal int Size; | ||
| internal int AccessTime; | ||
| internal int ModificationTime; | ||
| internal int StatusChangeTime; | ||
| internal int CreationTime; | ||
|
|
||
| internal bool HasCreationTime | ||
| { | ||
| get { return (this.Flags & Flags.HasCreationTime) != 0; } | ||
| } | ||
|
|
||
| [Flags] | ||
| private enum Flags | ||
| { | ||
| None = 0, | ||
| HasCreationTime = 1, | ||
| } | ||
| } | ||
|
|
||
| [DllImport(Libraries.LibCoreFxIO, SetLastError = true)] | ||
| internal static extern int GetFileStatsFromDescriptor(int fileDescriptor, out FileStats stats); | ||
|
|
||
| [DllImport(Libraries.LibCoreFxIO, CharSet = CharSet.Ansi, SetLastError = true)] | ||
| internal static extern int GetFileStatsFromPath(string path, out FileStats stats); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another big one is that exports can be named differently, making the DllImport mechanism itself quite challenging.