@@ -12,7 +12,9 @@ namespace Microsoft.NET.Build.Containers;
12
12
13
13
internal class Layer
14
14
{
15
- // NOTE: The SID string below was created using the following snippet. As the code is Windows only we keep the constant
15
+ // NOTE: The SID string below was created using the following snippet. As the code is Windows only we keep the constant,
16
+ // so that we can author Windows layers successfully on non-Windows hosts.
17
+ //
16
18
// private static string CreateUserOwnerAndGroupSID()
17
19
// {
18
20
// var descriptor = new RawSecurityDescriptor(
@@ -50,7 +52,7 @@ public static Layer FromDescriptor(Descriptor descriptor)
50
52
return new ( ContentStore . PathForDescriptor ( descriptor ) , descriptor ) ;
51
53
}
52
54
53
- public static Layer FromDirectory ( string directory , string containerPath , bool isWindowsLayer , string manifestMediaType )
55
+ public static Layer FromDirectory ( string directory , string containerPath , bool isWindowsLayer , string manifestMediaType , int ? userId = null )
54
56
{
55
57
long fileSize ;
56
58
Span < byte > hash = stackalloc byte [ SHA256 . HashSizeInBytes ] ;
@@ -101,7 +103,7 @@ public static Layer FromDirectory(string directory, string containerPath, bool i
101
103
}
102
104
103
105
// Write an entry for the application directory.
104
- WriteTarEntryForFile ( writer , new DirectoryInfo ( directory ) , containerPath , entryAttributes ) ;
106
+ WriteTarEntryForFile ( writer , new DirectoryInfo ( directory ) , containerPath , entryAttributes , isWindowsLayer ? null : userId ) ;
105
107
106
108
// Write entries for the application directory contents.
107
109
var fileList = new FileSystemEnumerable < ( FileSystemInfo file , string containerPath ) > (
@@ -124,7 +126,7 @@ public static Layer FromDirectory(string directory, string containerPath, bool i
124
126
} ) ;
125
127
foreach ( var item in fileList )
126
128
{
127
- WriteTarEntryForFile ( writer , item . file , item . containerPath , entryAttributes ) ;
129
+ WriteTarEntryForFile ( writer , item . file , item . containerPath , entryAttributes , isWindowsLayer ? null : userId ) ;
128
130
}
129
131
130
132
// Windows layers need a Hives folder, we do not need to create any Registry Hive deltas inside
@@ -148,27 +150,36 @@ public static Layer FromDirectory(string directory, string containerPath, bool i
148
150
Debug . Assert ( bW == hash . Length ) ;
149
151
150
152
// Writes a tar entry corresponding to the file system item.
151
- static void WriteTarEntryForFile ( TarWriter writer , FileSystemInfo file , string containerPath , IEnumerable < KeyValuePair < string , string > > entryAttributes )
153
+ static void WriteTarEntryForFile ( TarWriter writer , FileSystemInfo file , string containerPath , IEnumerable < KeyValuePair < string , string > > entryAttributes , int ? userId )
152
154
{
153
155
UnixFileMode mode = DetermineFileMode ( file ) ;
156
+ PaxTarEntry entry ;
154
157
155
158
if ( file is FileInfo )
156
159
{
157
- using var fileStream = File . OpenRead ( file . FullName ) ;
158
- PaxTarEntry entry = new ( TarEntryType . RegularFile , containerPath , entryAttributes )
160
+ var fileStream = File . OpenRead ( file . FullName ) ;
161
+ entry = new ( TarEntryType . RegularFile , containerPath , entryAttributes )
159
162
{
160
- Mode = mode ,
161
- DataStream = fileStream
163
+ DataStream = fileStream ,
162
164
} ;
163
- writer . WriteEntry ( entry ) ;
164
165
}
165
166
else
166
167
{
167
- PaxTarEntry entry = new ( TarEntryType . Directory , containerPath , entryAttributes )
168
- {
169
- Mode = mode
170
- } ;
171
- writer . WriteEntry ( entry ) ;
168
+ entry = new ( TarEntryType . Directory , containerPath , entryAttributes ) ;
169
+ }
170
+
171
+ entry . Mode = mode ;
172
+ if ( userId is int uid )
173
+ {
174
+ entry . Uid = uid ;
175
+ }
176
+
177
+ writer . WriteEntry ( entry ) ;
178
+
179
+ if ( entry . DataStream is not null )
180
+ {
181
+ // no longer relying on the `using` of the FileStream, so need to do it manually
182
+ entry . DataStream . Dispose ( ) ;
172
183
}
173
184
174
185
static UnixFileMode DetermineFileMode ( FileSystemInfo file )
0 commit comments