snapshot before regression test

This commit is contained in:
t
2026-07-18 19:25:40 +08:00
commit 796222a300
2295 changed files with 206453 additions and 0 deletions

234
includes/os/_win32.py Normal file
View File

@@ -0,0 +1,234 @@
import t, c
from stdint import *
import w32.win32base
import w32.win32file
import memhub
import stdlib
# Windows 路径最大长度
MAX_PATH_LEN: t.CDefine = 260
# INVALID_FILE_ATTRIBUTES
INVALID_FILE_ATTRIBUTES: t.CDefine = 0xFFFFFFFF
# 模块级全局 MBuddy 指针(由用户在 main 中赋值初始化)
_mbuddy: memhub.MemBuddy | t.CPtr
# =============================================================================
# 文件/目录属性查询
# =============================================================================
def _get_attrs(path: str) -> ULONG:
"""获取文件属性。失败返回 INVALID_FILE_ATTRIBUTES。"""
return w32.win32file.GetFileAttributesA(path)
def exists(path: str) -> bool:
"""检查文件/目录是否存在"""
attrs: ULONG = _get_attrs(path)
if attrs == INVALID_FILE_ATTRIBUTES:
return False
return True
def isdir(path: str) -> bool:
"""检查路径是否为目录"""
attrs: ULONG = _get_attrs(path)
if attrs == INVALID_FILE_ATTRIBUTES:
return False
if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0:
return True
return False
def isfile(path: str) -> bool:
"""检查路径是否为普通文件"""
attrs: ULONG = _get_attrs(path)
if attrs == INVALID_FILE_ATTRIBUTES:
return False
if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0:
return False
return True
def getsize(path: str) -> t.CInt64T:
"""返回文件大小(字节)。失败返回 -1。"""
handle: w32.win32base.HANDLE = w32.win32file.CreateFileA(
path, w32.win32file.GENERIC_READ, w32.win32file.FILE_SHARE_READ,
t.CPtr(0), w32.win32file.OPEN_EXISTING, w32.win32file.FILE_ATTRIBUTE_NORMAL, t.CPtr(0)
)
if handle == w32.win32base.INVALID_HANDLE_VALUE:
return -1
li: w32.win32base.LARGE_INTEGER = w32.win32base.LARGE_INTEGER()
result: BOOL = w32.win32file.GetFileSizeEx(handle, t.CPtr(c.Addr(li)))
w32.win32base.CloseHandle(handle)
if result == 0:
return -1
return li.QuadPart
# =============================================================================
# 工作目录
# =============================================================================
def getcwd() -> str:
"""返回当前工作目录(通过 _mbuddy 分配内存)"""
buf: bytes = _mbuddy.alloc(MAX_PATH_LEN + 1)
if buf == None: return None
length: ULONG = w32.win32file.GetCurrentDirectoryA(MAX_PATH_LEN + 1, buf)
if length == 0:
return None
if length > MAX_PATH_LEN:
# 缓冲区不够,重新分配
buf2: bytes = _mbuddy.alloc(length + 1)
if buf2 == None: return None
w32.win32file.GetCurrentDirectoryA(length + 1, buf2)
buf2[length] = 0
return str(buf2)
buf[length] = 0
return str(buf)
def chdir(path: str) -> int:
"""切换当前工作目录。成功返回 0失败返回 -1。"""
result: BOOL = w32.win32file.SetCurrentDirectoryA(path)
if result == 0:
return -1
return 0
# =============================================================================
# 文件/目录操作
# =============================================================================
def mkdir(path: str) -> int:
"""创建目录。成功返回 0失败返回 -1。"""
result: BOOL = w32.win32file.CreateDirectoryA(path, t.CPtr(0))
if result == 0:
return -1
return 0
def remove(path: str) -> int:
"""删除文件。成功返回 0失败返回 -1。"""
result: BOOL = w32.win32file.DeleteFileA(path)
if result == 0:
return -1
return 0
def rmdir(path: str) -> int:
"""删除空目录。成功返回 0失败返回 -1。"""
result: BOOL = w32.win32file.RemoveDirectoryA(path)
if result == 0:
return -1
return 0
def rename(old_path: str, new_path: str) -> int:
"""重命名/移动文件或目录。成功返回 0失败返回 -1。"""
result: BOOL = w32.win32file.MoveFileExA(
old_path, new_path,
w32.win32file.MOVEFILE_REPLACE_EXISTING | w32.win32file.MOVEFILE_COPY_ALLOWED
)
if result == 0:
return -1
return 0
def chmod(path: str, mode: int) -> int:
"""修改文件属性Windows 简化版:只处理只读位)。
mode 的 S_IWUSR 位0o200为 0 时设为只读,为 1 时设为可写。
成功返回 0失败返回 -1。"""
if (mode & 0o200) != 0:
# 可写:清除只读属性
result: BOOL = w32.win32file.SetFileAttributesA(
path, w32.win32file.FILE_ATTRIBUTE_NORMAL
)
else:
# 只读:设置只读属性
result: BOOL = w32.win32file.SetFileAttributesA(
path, w32.win32file.FILE_ATTRIBUTE_READONLY
)
if result == 0:
return -1
return 0
# =============================================================================
# 目录列举FindFirstFile / FindNextFile
# =============================================================================
def listdir(path: str, out_names: str, max_count: ULONG) -> ULONG:
"""列举目录下的文件/子目录名。
out_names 为调用者提供的字符串指针数组char**),每个元素指向一个文件名。
文件名通过 _mbuddy 分配内存。
max_count 为 out_names 数组最大容量。
返回实际列举的条目数。失败返回 0。"""
# 构造搜索模式path\*
path_len: t.CSizeT = len(path)
pattern: bytes = _mbuddy.alloc(path_len + 3)
if pattern == None: return 0
i: t.CSizeT = 0
for ch in path:
pattern[i] = ch
i += 1
# 添加 \* 后缀
if path[path_len - 1] != '\\' and path[path_len - 1] != '/':
pattern[i] = '\\'
i += 1
pattern[i] = '*'
i += 1
pattern[i] = 0
find_data: w32.win32file.WIN32_FIND_DATAA = w32.win32file.WIN32_FIND_DATAA()
handle: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(pattern, t.CPtr(c.Addr(find_data)))
if handle == w32.win32base.INVALID_HANDLE_VALUE:
return 0
count: ULONG = 0
while count < max_count:
# 跳过 . 和 ..
name: str = find_data.cFileName
if name[0] == '.':
if name[1] == 0:
# "."
if w32.win32file.FindNextFileA(handle, t.CPtr(c.Addr(find_data))) == 0:
break
continue
if name[1] == '.' and name[2] == 0:
# ".."
if w32.win32file.FindNextFileA(handle, t.CPtr(c.Addr(find_data))) == 0:
break
continue
# 复制文件名到新分配的内存
name_len: t.CSizeT = len(name)
name_buf: bytes = _mbuddy.alloc(name_len + 1)
if name_buf == None: break
j: t.CSizeT = 0
for ch in name:
name_buf[j] = ch
j += 1
name_buf[name_len] = 0
out_names[count] = str(name_buf)
count += 1
if w32.win32file.FindNextFileA(handle, t.CPtr(c.Addr(find_data))) == 0:
break
w32.win32file.FindClose(handle)
return count
# =============================================================================
# 命令执行
# =============================================================================
def system(cmd: str) -> int:
"""执行命令行命令(通过 C 运行时 system())。
命令输出直接到子进程的终端(继承父进程 stdout/stderr
返回命令的退出码0 表示成功)。"""
return stdlib.system(cmd)