1115
CopyFileWithMetadata(source.c_str(), dest.c_str(), (LX_S_IFREG | 0755), DistroVersion);
1116
}
1117
1118
-void wsl::windows::common::filesystem::CreateCpioInitrd(_In_ const std::filesystem::path& SourcePath, _In_ const std::filesystem::path& DestPath)
1119
-{
1120
- // Open the source init binary
1121
- wil::unique_hfile sourceFile{
1122
- CreateFileW(SourcePath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr)};
1123
- THROW_LAST_ERROR_IF(!sourceFile);
1124
-
1125
- // Get file size
1126
- LARGE_INTEGER fileSize{};
1127
- THROW_IF_WIN32_BOOL_FALSE(GetFileSizeEx(sourceFile.get(), &fileSize));
1128
- THROW_HR_IF(E_INVALIDARG, fileSize.HighPart != 0); // File too large
1129
-
1130
- const DWORD initSize = fileSize.LowPart;
1131
- const auto initDataPadding = (4 - (initSize % 4)) % 4;
1132
- wil::unique_hfile destFile{CreateFileW(DestPath.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr)};
1133
- THROW_LAST_ERROR_IF(!destFile);
1134
-
1135
- // Clean up the destination file on failure.
1136
- auto deleteFile = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] {
1137
- destFile.reset();
1138
- LOG_IF_WIN32_BOOL_FALSE(DeleteFileW(DestPath.c_str()));
1139
- });
1140
-
1141
- auto writeCpioHeader = [&destFile](DWORD fileSize, PCSTR name) {
1142
- // CPIO newc header: magic(6) + 13 fields of 8 hex chars each = 110 bytes
1143
- constexpr size_t headerSize = 110;
1144
- const auto nameLen = strlen(name) + 1;
1145
- const auto headerPadding = (4 - ((headerSize + nameLen) % 4)) % 4;
1146
- const bool isTrailer = strcmp(name, "TRAILER!!!") == 0;
1147
-
1148
- // Get current time for mtime. CPIO newc format only supports 32-bit fields.
1149
- const auto mtime = static_cast<DWORD>(time(nullptr));
1150
-
1151
- char header[headerSize + 1];
1152
- sprintf_s(
1153
- header,
1154
- "070701" // magic
1155
- "%08X" // inode
1156
- "%08X" // mode
1157
- "%08X" // uid
1158
- "%08X" // gid
1159
- "%08X" // nlink
1160
- "%08X" // mtime
1161
- "%08X" // filesize
1162
- "%08X" // devmajor
1163
- "%08X" // devminor
1164
- "%08X" // rdevmajor
1165
- "%08X" // rdevminor
1166
- "%08X" // namesize
1167
- "%08X", // check
1168
- 0,
1169
- isTrailer ? 0 : 0100755,
1170
- 0,
1171
- 0,
1172
- isTrailer ? 0 : 1,
1173
- mtime,
1174
- fileSize,
1175
- 0,
1176
- 0,
1177
- 0,
1178
- 0,
1179
- static_cast<DWORD>(nameLen),
1180
- 0);
1181
-
1182
- DWORD bytesWritten;
1183
- THROW_IF_WIN32_BOOL_FALSE(WriteFile(destFile.get(), header, headerSize, &bytesWritten, nullptr));
1184
-
1185
- // Write name with null terminator
1186
- THROW_IF_WIN32_BOOL_FALSE(WriteFile(destFile.get(), name, static_cast<DWORD>(nameLen), &bytesWritten, nullptr));
1187
-
1188
- // Write padding to align to 4 bytes
1189
- if (headerPadding > 0)
1190
- {
1191
- char padding[4] = {0};
1192
- THROW_IF_WIN32_BOOL_FALSE(WriteFile(destFile.get(), padding, static_cast<DWORD>(headerPadding), &bytesWritten, nullptr));
1193
- }
1194
- };
1195
-
1196
- // Write init file header
1197
- writeCpioHeader(initSize, SourcePath.filename().string().c_str());
1198
-
1199
- // Copy file contents
1200
- wsl::windows::common::relay::InterruptableRelay(sourceFile.get(), destFile.get(), nullptr, 64 * 1024);
1201
-
1202
- // Write data padding
1203
- if (initDataPadding > 0)
1204
- {
1205
- char padding[4] = {0};
1206
- DWORD bytesWritten;
1207
- THROW_IF_WIN32_BOOL_FALSE(WriteFile(destFile.get(), padding, static_cast<DWORD>(initDataPadding), &bytesWritten, nullptr));
1208
- }
1209
-
1210
- // Write trailer entry (empty file with name "TRAILER!!!")
1211
- writeCpioHeader(0, "TRAILER!!!");
1212
-
1213
- // Pad the archive to 512-byte boundary
1214
- constexpr DWORD archiveBlockSize = 512;
1215
- LARGE_INTEGER currentPos{};
1216
- THROW_IF_WIN32_BOOL_FALSE(SetFilePointerEx(destFile.get(), {}, ¤tPos, FILE_CURRENT));
1217
-
1218
- const auto currentSize = static_cast<ULONGLONG>(currentPos.QuadPart);
1219
- const auto archivePadding = static_cast<DWORD>((archiveBlockSize - (currentSize % archiveBlockSize)) % archiveBlockSize);
1220
- if (archivePadding > 0)
1221
- {
1222
- char paddingBuffer[archiveBlockSize] = {0};
1223
- DWORD bytesWritten;
1224
- THROW_IF_WIN32_BOOL_FALSE(WriteFile(destFile.get(), paddingBuffer, archivePadding, &bytesWritten, nullptr));
1225
- }
1226
-
1227
- deleteFile.release();
1228
-}
1229
-
1118
wil::unique_hfile wsl::windows::common::filesystem::WipeAndOpenDirectory(_In_ LPCWSTR pPath)
1119
{
1120
const auto result = wil::RemoveDirectoryRecursiveNoThrow(pPath);