add ntfs.sys standalone driver target, change default usb vhd layout formatting to ntfs, implement Fat32CreateDir for directory creation support in the fat32 file system driver, add a dedicated HAL serial output endpoint for COM1 writes in hal_serial.c and subscribe serial to HAL text streams, introduce waitable kernel timers with KeTimerCreate, KeTimerSet, and KeTimerCancel alongside spinlock-protected global timer list initialization and scheduler tick tracking, implement SyscallWriteFileAsync system call for asynchronous non-blocking file writes, refactor NetSocketConnect and NetSocketSendTo to use generic SYS_SOCKET_ADDRESS_K structures instead of being hardcoded to IPv4, update gethostbyname and DNS name resolution to support IPv6 parsing via ResolveNameFamily, update tcpserve.exe with -4 and -6 command-line flags to accept and display IPv6 addresses, append size and version headers to all kernel telemetry and statistics structures including SYS_PMM_STATS, SYS_CPU_STATS, and SYS_SCHEDULER_STATS, update winmm timeGetTime to look up high-resolution hardware frequencies via SysGetTickFrequency, integrate 14 native smoke test applications.
This commit is contained in:
1 parent
2c4a68a75f
commit
ed3d065abd
156 files changed
+10509
-2643
No files matched your search
@@ -0,0 +1,258 @@
|
||||
// Native file metadata smoke test.
|
||||
// Verifies path stat, handle stat, directory metadata, missing paths, and invalid handles.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <ntlite/syscall.h>
|
||||
|
||||
#define TEST_FILE_SIZE 1537u
|
||||
|
||||
static uint8_t gPattern[TEST_FILE_SIZE];
|
||||
|
||||
// Prints one NUL-terminated string to the kernel console.
|
||||
static void print(const char* s) {
|
||||
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) };
|
||||
SysWriteConsole(&req);
|
||||
}
|
||||
|
||||
// Prints one unsigned integer to the kernel console.
|
||||
static void print_u64(uint64_t v) {
|
||||
char buf[32];
|
||||
int i = 0;
|
||||
if (v == 0) {
|
||||
print("0");
|
||||
return;
|
||||
}
|
||||
while (v && i < (int)sizeof(buf)) {
|
||||
buf[i++] = (char)('0' + (v % 10));
|
||||
v /= 10;
|
||||
}
|
||||
while (i--) {
|
||||
char c = buf[i];
|
||||
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) };
|
||||
SysWriteConsole(&req);
|
||||
}
|
||||
}
|
||||
|
||||
// Terminates the current test process.
|
||||
static void exit_now(int code) {
|
||||
for (;;) SysExitProcess(code);
|
||||
}
|
||||
|
||||
// Fails the test with one plain message.
|
||||
static void fail(const char* msg) {
|
||||
print("file_stat_smoke: ");
|
||||
print(msg);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
|
||||
// Fails the test with one status value.
|
||||
static void fail_status(const char* what, uint32_t status) {
|
||||
print("file_stat_smoke: ");
|
||||
print(what);
|
||||
print(" failed status=");
|
||||
print_u64(status);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
|
||||
// Removes a file path if it already exists.
|
||||
static void delete_file_path(const char* path) {
|
||||
SYS_PATH_REQUEST req = { SysSvFromCstr(path) };
|
||||
(void)SysDeleteFile(&req);
|
||||
}
|
||||
|
||||
// Removes a directory path if it already exists.
|
||||
static void remove_dir_path(const char* path) {
|
||||
SYS_PATH_REQUEST req = { SysSvFromCstr(path) };
|
||||
(void)SysRemoveDir(&req);
|
||||
}
|
||||
|
||||
// Opens a new temporary file on the first writable path that works.
|
||||
static uint32_t create_temp_file(uint32_t* fileOut, const char** pathOut) {
|
||||
static const char* paths[] = {
|
||||
"file_stat_smoke.tmp",
|
||||
"/file_stat_smoke.tmp",
|
||||
"1:/file_stat_smoke.tmp",
|
||||
"0:/file_stat_smoke.tmp",
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); ++i) {
|
||||
uint32_t h = 0;
|
||||
delete_file_path(paths[i]);
|
||||
SYS_OPEN_FILE_REQUEST req = SysMakeOpenFileRequest(SysSvFromCstr(paths[i]),
|
||||
SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_WRITE | SYS_FILE_ACCESS_QUERY,
|
||||
SYS_FILE_CREATE_NEW,
|
||||
SYS_FILE_FLAG_NONE,
|
||||
&h);
|
||||
uint32_t s = SysOpenFile(&req);
|
||||
if (s == STATUS_SUCCESS) {
|
||||
*fileOut = h;
|
||||
*pathOut = paths[i];
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Creates a temporary directory on the first writable path that works.
|
||||
static uint32_t create_temp_dir(const char** pathOut) {
|
||||
static const char* paths[] = {
|
||||
"file_stat_smoke.dir",
|
||||
"/file_stat_smoke.dir",
|
||||
"1:/file_stat_smoke.dir",
|
||||
"0:/file_stat_smoke.dir",
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); ++i) {
|
||||
remove_dir_path(paths[i]);
|
||||
SYS_PATH_REQUEST req = { SysSvFromCstr(paths[i]) };
|
||||
uint32_t s = SysCreateDir(&req);
|
||||
if (s == STATUS_SUCCESS) {
|
||||
*pathOut = paths[i];
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Fills the write pattern used by the test file.
|
||||
static void fill_pattern(void) {
|
||||
for (size_t i = 0; i < sizeof(gPattern); ++i)
|
||||
gPattern[i] = (uint8_t)(0x31u + (uint8_t)(i * 17u + (i >> 3)));
|
||||
}
|
||||
|
||||
// Writes the test file contents and flushes them to the filesystem.
|
||||
static void write_test_file(uint32_t file) {
|
||||
size_t done = 0;
|
||||
SYS_FILE_IO_REQUEST writeReq = SysMakeFileIoRequest(file, gPattern, sizeof(gPattern), &done);
|
||||
uint32_t s = SysWriteFile(&writeReq);
|
||||
if (s != STATUS_SUCCESS) fail_status("write test file", s);
|
||||
if (done != sizeof(gPattern)) fail("short write");
|
||||
|
||||
s = SysFlushFile(file);
|
||||
if (s != STATUS_SUCCESS) fail_status("flush test file", s);
|
||||
}
|
||||
|
||||
// Checks one regular-file metadata result.
|
||||
static void check_regular_stat(const SYS_FILE_STAT* stat, uint64_t expectedSize, const char* what) {
|
||||
if (stat->Size != sizeof(*stat)) fail("stat abi size mismatch");
|
||||
if (stat->Type != SYS_FILE_TYPE_REGULAR) {
|
||||
print("file_stat_smoke: ");
|
||||
print(what);
|
||||
print(" type=");
|
||||
print_u64(stat->Type);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
if ((stat->Attributes & SYS_FILE_ATTR_DIRECTORY) != 0) fail("regular file has directory attribute");
|
||||
if (stat->LinkCount == 0) fail("regular file has zero links");
|
||||
if (stat->FileSize != expectedSize) {
|
||||
print("file_stat_smoke: ");
|
||||
print(what);
|
||||
print(" size=");
|
||||
print_u64(stat->FileSize);
|
||||
print(" expected=");
|
||||
print_u64(expectedSize);
|
||||
print("\n");
|
||||
exit_now(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Checks one directory metadata result.
|
||||
static void check_directory_stat(const SYS_FILE_STAT* stat) {
|
||||
if (stat->Size != sizeof(*stat)) fail("directory stat abi size mismatch");
|
||||
if (stat->Type != SYS_FILE_TYPE_DIRECTORY) fail("directory stat type mismatch");
|
||||
if ((stat->Attributes & SYS_FILE_ATTR_DIRECTORY) == 0) fail("directory attribute missing");
|
||||
if (stat->LinkCount == 0) fail("directory has zero links");
|
||||
}
|
||||
|
||||
// Exercises handle and path stat for one regular file.
|
||||
static void test_file_stat(uint32_t file, const char* path) {
|
||||
SYS_FILE_STAT byHandle;
|
||||
memset(&byHandle, 0xA5, sizeof(byHandle));
|
||||
uint32_t s = SysGetFileStat(file, &byHandle);
|
||||
if (s != STATUS_SUCCESS) fail_status("get file stat", s);
|
||||
check_regular_stat(&byHandle, sizeof(gPattern), "handle stat");
|
||||
|
||||
uint64_t size = 0;
|
||||
s = SysGetFileSize(file, &size);
|
||||
if (s != STATUS_SUCCESS) fail_status("get file size", s);
|
||||
if (size != byHandle.FileSize) fail("file size and file stat disagree");
|
||||
|
||||
SYS_FILE_STAT byPath;
|
||||
memset(&byPath, 0x5A, sizeof(byPath));
|
||||
SYS_STAT_FILE_REQUEST statReq = { SysSvFromCstr(path), &byPath };
|
||||
s = SysStatFile(&statReq);
|
||||
if (s != STATUS_SUCCESS) fail_status("path stat", s);
|
||||
check_regular_stat(&byPath, sizeof(gPattern), "path stat");
|
||||
|
||||
if (byHandle.VolumeId != 0 && byPath.VolumeId != 0 && byHandle.VolumeId != byPath.VolumeId)
|
||||
fail("handle and path volume ids differ");
|
||||
if (byHandle.FileId != 0 && byPath.FileId != 0 && byHandle.FileId != byPath.FileId)
|
||||
fail("handle and path file ids differ");
|
||||
}
|
||||
|
||||
// Exercises path stat for one directory.
|
||||
static void test_directory_stat(const char* path) {
|
||||
SYS_FILE_STAT stat;
|
||||
memset(&stat, 0xCC, sizeof(stat));
|
||||
SYS_STAT_FILE_REQUEST statReq = { SysSvFromCstr(path), &stat };
|
||||
uint32_t s = SysStatFile(&statReq);
|
||||
if (s != STATUS_SUCCESS) fail_status("directory stat", s);
|
||||
check_directory_stat(&stat);
|
||||
}
|
||||
|
||||
// Checks failure status paths that stat callers depend on.
|
||||
static void test_failure_paths(void) {
|
||||
SYS_FILE_STAT stat;
|
||||
SYS_STAT_FILE_REQUEST missingReq = { SysSvFromCstr("file_stat_smoke_missing.nope"), &stat };
|
||||
uint32_t s = SysStatFile(&missingReq);
|
||||
if (s != STATUS_NOT_FOUND) fail_status("missing path status", s);
|
||||
|
||||
s = SysGetFileStat(0xFFFFFFFFu, &stat);
|
||||
if (s != STATUS_INVALID_HANDLE) fail_status("invalid handle status", s);
|
||||
|
||||
SYS_STAT_FILE_REQUEST badReq = { SysSvFromCstr("file_stat_smoke_missing.nope"), 0 };
|
||||
s = SysStatFile(&badReq);
|
||||
if (s != STATUS_INVALID_PARAMETER) fail_status("null stat output status", s);
|
||||
}
|
||||
|
||||
// Runs the native file metadata smoke test.
|
||||
int main(void) {
|
||||
print("file_stat_smoke: start\n");
|
||||
|
||||
fill_pattern();
|
||||
|
||||
uint32_t file = 0;
|
||||
const char* filePath = 0;
|
||||
uint32_t s = create_temp_file(&file, &filePath);
|
||||
if (s != STATUS_SUCCESS) fail_status("create temp file", s);
|
||||
|
||||
write_test_file(file);
|
||||
test_file_stat(file, filePath);
|
||||
SysCloseHandle(file);
|
||||
delete_file_path(filePath);
|
||||
|
||||
const char* dirPath = 0;
|
||||
s = create_temp_dir(&dirPath);
|
||||
if (s != STATUS_SUCCESS) fail_status("create temp dir", s);
|
||||
test_directory_stat(dirPath);
|
||||
remove_dir_path(dirPath);
|
||||
|
||||
SYS_PATH_REQUEST dirReq = { SysSvFromCstr(dirPath) };
|
||||
s = SysCreateDir(&dirReq);
|
||||
if (s != STATUS_SUCCESS) fail_status("recreate temp dir", s);
|
||||
test_directory_stat(dirPath);
|
||||
remove_dir_path(dirPath);
|
||||
|
||||
test_failure_paths();
|
||||
|
||||
print("file_stat_smoke: PASS\n");
|
||||
exit_now(0);
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user