diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-07-15 20:46:12 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-07-15 20:46:12 -0400 |
| commit | 3f4abe97bdbe666dbb3532c14a97e414aae4caca (patch) | |
| tree | ba08f2f14e79a8c8f7e83cea0344826fefffd9a2 /std/os | |
| parent | 33eaaadd01b20d1327b67758664ce1265216e471 (diff) | |
| parent | aff90c22520bbbadd56fbfd1378f161ee8a3cdb2 (diff) | |
| download | zig-3f4abe97bdbe666dbb3532c14a97e414aae4caca.tar.gz zig-3f4abe97bdbe666dbb3532c14a97e414aae4caca.zip | |
Merge pull request #2892 from ziglang/install-with-zig-build
move some of the installation from cmake to zig build
Diffstat (limited to 'std/os')
| -rw-r--r-- | std/os/bits/darwin.zig | 42 | ||||
| -rw-r--r-- | std/os/bits/freebsd.zig | 18 | ||||
| -rw-r--r-- | std/os/bits/linux/arm64.zig | 17 | ||||
| -rw-r--r-- | std/os/bits/linux/x86_64.zig | 17 | ||||
| -rw-r--r-- | std/os/bits/netbsd.zig | 18 | ||||
| -rw-r--r-- | std/os/linux.zig | 9 | ||||
| -rw-r--r-- | std/os/windows.zig | 74 | ||||
| -rw-r--r-- | std/os/windows/bits.zig | 171 | ||||
| -rw-r--r-- | std/os/windows/kernel32.zig | 12 | ||||
| -rw-r--r-- | std/os/windows/ntdll.zig | 15 | ||||
| -rw-r--r-- | std/os/windows/status.zig | 5 |
11 files changed, 388 insertions, 10 deletions
diff --git a/std/os/bits/darwin.zig b/std/os/bits/darwin.zig index 39dae6e7a1..b8d229dbe9 100644 --- a/std/os/bits/darwin.zig +++ b/std/os/bits/darwin.zig @@ -44,6 +44,11 @@ pub const mach_timebase_info_data = extern struct { }; /// Renamed to Stat to not conflict with the stat function. +/// atime, mtime, and ctime have functions to return `timespec`, +/// because although this is a POSIX API, the layout and names of +/// the structs are inconsistent across operating systems, and +/// in C, macros are used to hide the differences. Here we use +/// methods to accomplish this. pub const Stat = extern struct { dev: i32, mode: u16, @@ -52,14 +57,14 @@ pub const Stat = extern struct { uid: u32, gid: u32, rdev: i32, - atime: usize, - atimensec: usize, - mtime: usize, - mtimensec: usize, - ctime: usize, - ctimensec: usize, - birthtime: usize, - birthtimensec: usize, + atimesec: isize, + atimensec: isize, + mtimesec: isize, + mtimensec: isize, + ctimesec: isize, + ctimensec: isize, + birthtimesec: isize, + birthtimensec: isize, size: i64, blocks: i64, blksize: i32, @@ -67,6 +72,27 @@ pub const Stat = extern struct { gen: u32, lspare: i32, qspare: [2]i64, + + pub fn atime(self: Stat) timespec { + return timespec{ + .tv_sec = self.atimesec, + .tv_nsec = self.atimensec, + }; + } + + pub fn mtime(self: Stat) timespec { + return timespec{ + .tv_sec = self.mtimesec, + .tv_nsec = self.mtimensec, + }; + } + + pub fn ctime(self: Stat) timespec { + return timespec{ + .tv_sec = self.ctimesec, + .tv_nsec = self.ctimensec, + }; + } }; pub const timespec = extern struct { diff --git a/std/os/bits/freebsd.zig b/std/os/bits/freebsd.zig index c73887d648..198857983e 100644 --- a/std/os/bits/freebsd.zig +++ b/std/os/bits/freebsd.zig @@ -73,6 +73,12 @@ pub const msghdr_const = extern struct { msg_flags: i32, }; +/// Renamed to Stat to not conflict with the stat function. +/// atime, mtime, and ctime have functions to return `timespec`, +/// because although this is a POSIX API, the layout and names of +/// the structs are inconsistent across operating systems, and +/// in C, macros are used to hide the differences. Here we use +/// methods to accomplish this. pub const Stat = extern struct { dev: u64, ino: u64, @@ -96,6 +102,18 @@ pub const Stat = extern struct { flags: u32, gen: u64, __spare: [10]u64, + + pub fn atime(self: Stat) timespec { + return self.atim; + } + + pub fn mtime(self: Stat) timespec { + return self.mtim; + } + + pub fn ctime(self: Stat) timespec { + return self.ctim; + } }; pub const timespec = extern struct { diff --git a/std/os/bits/linux/arm64.zig b/std/os/bits/linux/arm64.zig index bd381c16e7..e19b631292 100644 --- a/std/os/bits/linux/arm64.zig +++ b/std/os/bits/linux/arm64.zig @@ -396,6 +396,11 @@ pub const msghdr_const = extern struct { }; /// Renamed to Stat to not conflict with the stat function. +/// atime, mtime, and ctime have functions to return `timespec`, +/// because although this is a POSIX API, the layout and names of +/// the structs are inconsistent across operating systems, and +/// in C, macros are used to hide the differences. Here we use +/// methods to accomplish this. pub const Stat = extern struct { dev: u64, ino: u64, @@ -414,6 +419,18 @@ pub const Stat = extern struct { mtim: timespec, ctim: timespec, __unused: [3]isize, + + pub fn atime(self: Stat) timespec { + return self.atim; + } + + pub fn mtime(self: Stat) timespec { + return self.mtim; + } + + pub fn ctime(self: Stat) timespec { + return self.ctim; + } }; pub const timespec = extern struct { diff --git a/std/os/bits/linux/x86_64.zig b/std/os/bits/linux/x86_64.zig index d85cac564c..499f925280 100644 --- a/std/os/bits/linux/x86_64.zig +++ b/std/os/bits/linux/x86_64.zig @@ -493,6 +493,11 @@ pub const msghdr_const = extern struct { }; /// Renamed to Stat to not conflict with the stat function. +/// atime, mtime, and ctime have functions to return `timespec`, +/// because although this is a POSIX API, the layout and names of +/// the structs are inconsistent across operating systems, and +/// in C, macros are used to hide the differences. Here we use +/// methods to accomplish this. pub const Stat = extern struct { dev: u64, ino: u64, @@ -511,6 +516,18 @@ pub const Stat = extern struct { mtim: timespec, ctim: timespec, __unused: [3]isize, + + pub fn atime(self: Stat) timespec { + return self.atim; + } + + pub fn mtime(self: Stat) timespec { + return self.mtim; + } + + pub fn ctime(self: Stat) timespec { + return self.ctim; + } }; pub const timespec = extern struct { diff --git a/std/os/bits/netbsd.zig b/std/os/bits/netbsd.zig index d83ea82b06..ef58bd1356 100644 --- a/std/os/bits/netbsd.zig +++ b/std/os/bits/netbsd.zig @@ -73,6 +73,12 @@ pub const msghdr_const = extern struct { msg_flags: i32, }; +/// Renamed to Stat to not conflict with the stat function. +/// atime, mtime, and ctime have functions to return `timespec`, +/// because although this is a POSIX API, the layout and names of +/// the structs are inconsistent across operating systems, and +/// in C, macros are used to hide the differences. Here we use +/// methods to accomplish this. pub const Stat = extern struct { dev: u64, mode: u32, @@ -94,6 +100,18 @@ pub const Stat = extern struct { flags: u32, gen: u32, __spare: [2]u32, + + pub fn atime(self: Stat) timespec { + return self.atim; + } + + pub fn mtime(self: Stat) timespec { + return self.mtim; + } + + pub fn ctime(self: Stat) timespec { + return self.ctim; + } }; pub const timespec = extern struct { diff --git a/std/os/linux.zig b/std/os/linux.zig index 9d3746418f..053f30d265 100644 --- a/std/os/linux.zig +++ b/std/os/linux.zig @@ -94,6 +94,15 @@ pub inline fn vfork() usize { return @inlineCall(syscall0, SYS_vfork); } +pub fn futimens(fd: i32, times: *const [2]timespec) usize { + return utimensat(fd, null, times, 0); +} + +// TODO https://github.com/ziglang/zig/issues/265 +pub fn utimensat(dirfd: i32, path: ?[*]const u8, times: *const [2]timespec, flags: u32) usize { + return syscall4(SYS_utimensat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(times), flags); +} + pub fn futex_wait(uaddr: *const i32, futex_op: u32, val: i32, timeout: ?*timespec) usize { return syscall4(SYS_futex, @ptrToInt(uaddr), futex_op, @bitCast(u32, val), @ptrToInt(timeout)); } diff --git a/std/os/windows.zig b/std/os/windows.zig index 2377fc00e7..ac76e8f58f 100644 --- a/std/os/windows.zig +++ b/std/os/windows.zig @@ -752,6 +752,66 @@ pub fn HeapDestroy(hHeap: HANDLE) void { assert(kernel32.HeapDestroy(hHeap) != 0); } +pub const GetFileInformationByHandleError = error{Unexpected}; + +pub fn GetFileInformationByHandle( + hFile: HANDLE, +) GetFileInformationByHandleError!BY_HANDLE_FILE_INFORMATION { + var info: BY_HANDLE_FILE_INFORMATION = undefined; + const rc = ntdll.GetFileInformationByHandle(hFile, &info); + if (rc == 0) { + switch (kernel32.GetLastError()) { + else => |err| return unexpectedError(err), + } + } + return info; +} + +pub const SetFileTimeError = error{Unexpected}; + +pub fn SetFileTime( + hFile: HANDLE, + lpCreationTime: ?*const FILETIME, + lpLastAccessTime: ?*const FILETIME, + lpLastWriteTime: ?*const FILETIME, +) SetFileTimeError!void { + const rc = kernel32.SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime); + if (rc == 0) { + switch (kernel32.GetLastError()) { + else => |err| return unexpectedError(err), + } + } +} + +/// A file time is a 64-bit value that represents the number of 100-nanosecond +/// intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated +/// Universal Time (UTC). +/// This function returns the number of nanoseconds since the canonical epoch, +/// which is the POSIX one (Jan 01, 1970 AD). +pub fn fromSysTime(hns: i64) i64 { + const adjusted_epoch = hns + std.time.epoch.windows * (std.time.ns_per_s / 100); + return adjusted_epoch * 100; +} + +pub fn toSysTime(ns: i64) i64 { + const hns = @divFloor(ns, 100); + return hns - std.time.epoch.windows * (std.time.ns_per_s / 100); +} + +pub fn fileTimeToNanoSeconds(ft: FILETIME) i64 { + const hns = @bitCast(i64, (u64(ft.dwHighDateTime) << 32) | ft.dwLowDateTime); + return fromSysTime(hns); +} + +/// Converts a number of nanoseconds since the POSIX epoch to a Windows FILETIME. +pub fn nanoSecondsToFileTime(ns: i64) FILETIME { + const adjusted = @bitCast(u64, toSysTime(ns)); + return FILETIME{ + .dwHighDateTime = @truncate(u32, adjusted >> 32), + .dwLowDateTime = @truncate(u32, adjusted), + }; +} + pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 { return sliceToPrefixedFileW(mem.toSliceConst(u8, s)); } @@ -761,9 +821,8 @@ pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE + 1]u16 { } pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len]u16 { - // TODO well defined copy elision + // TODO https://github.com/ziglang/zig/issues/2765 var result: [PATH_MAX_WIDE + suffix.len]u16 = undefined; - // > File I/O functions in the Windows API convert "/" to "\" as part of // > converting the name to an NT-style name, except when using the "\\?\" // > prefix as detailed in the following sections. @@ -806,3 +865,14 @@ pub fn unexpectedError(err: DWORD) std.os.UnexpectedError { } return error.Unexpected; } + + +/// Call this when you made a windows NtDll call +/// and you get an unexpected status. +pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError { + if (std.os.unexpected_error_tracing) { + std.debug.warn("error.Unexpected NTSTATUS={}\n", status); + std.debug.dumpCurrentStackTrace(null); + } + return error.Unexpected; +} diff --git a/std/os/windows/bits.zig b/std/os/windows/bits.zig index fe72a710eb..79697995f4 100644 --- a/std/os/windows/bits.zig +++ b/std/os/windows/bits.zig @@ -6,6 +6,7 @@ const assert = std.debug.assert; const maxInt = std.math.maxInt; pub const ERROR = @import("error.zig"); +pub const STATUS = @import("status.zig"); pub const LANG = @import("lang.zig"); pub const SUBLANG = @import("sublang.zig"); @@ -59,6 +60,7 @@ pub const ULONGLONG = u64; pub const LONGLONG = i64; pub const HLOCAL = HANDLE; pub const LANGID = c_ushort; +pub const NTSTATUS = ULONG; pub const va_list = *@OpaqueType(); @@ -69,6 +71,147 @@ pub const INVALID_HANDLE_VALUE = @intToPtr(HANDLE, maxInt(usize)); pub const INVALID_FILE_ATTRIBUTES = DWORD(maxInt(DWORD)); +pub const FILE_ALL_INFORMATION = extern struct { + BasicInformation: FILE_BASIC_INFORMATION, + StandardInformation: FILE_STANDARD_INFORMATION, + InternalInformation: FILE_INTERNAL_INFORMATION, + EaInformation: FILE_EA_INFORMATION, + AccessInformation: FILE_ACCESS_INFORMATION, + PositionInformation: FILE_POSITION_INFORMATION, + ModeInformation: FILE_MODE_INFORMATION, + AlignmentInformation: FILE_ALIGNMENT_INFORMATION, + NameInformation: FILE_NAME_INFORMATION, +}; + +pub const FILE_BASIC_INFORMATION = extern struct { + CreationTime: LARGE_INTEGER, + LastAccessTime: LARGE_INTEGER, + LastWriteTime: LARGE_INTEGER, + ChangeTime: LARGE_INTEGER, + FileAttributes: ULONG, +}; + +pub const FILE_STANDARD_INFORMATION = extern struct { + AllocationSize: LARGE_INTEGER, + EndOfFile: LARGE_INTEGER, + NumberOfLinks: ULONG, + DeletePending: BOOLEAN, + Directory: BOOLEAN, +}; + +pub const FILE_INTERNAL_INFORMATION = extern struct { + IndexNumber: LARGE_INTEGER, +}; + +pub const FILE_EA_INFORMATION = extern struct { + EaSize: ULONG, +}; + +pub const FILE_ACCESS_INFORMATION = extern struct { + AccessFlags: ACCESS_MASK, +}; + +pub const FILE_POSITION_INFORMATION = extern struct { + CurrentByteOffset: LARGE_INTEGER, +}; + +pub const FILE_MODE_INFORMATION = extern struct { + Mode: ULONG, +}; + +pub const FILE_ALIGNMENT_INFORMATION = extern struct { + AlignmentRequirement: ULONG, +}; + +pub const FILE_NAME_INFORMATION = extern struct { + FileNameLength: ULONG, + FileName: [1]WCHAR, +}; + +pub const IO_STATUS_BLOCK = extern struct { + Status: usize, + Information: ULONG_PTR, +}; + +pub const FILE_INFORMATION_CLASS = extern enum { + FileDirectoryInformation = 1, + FileFullDirectoryInformation, + FileBothDirectoryInformation, + FileBasicInformation, + FileStandardInformation, + FileInternalInformation, + FileEaInformation, + FileAccessInformation, + FileNameInformation, + FileRenameInformation, + FileLinkInformation, + FileNamesInformation, + FileDispositionInformation, + FilePositionInformation, + FileFullEaInformation, + FileModeInformation, + FileAlignmentInformation, + FileAllInformation, + FileAllocationInformation, + FileEndOfFileInformation, + FileAlternateNameInformation, + FileStreamInformation, + FilePipeInformation, + FilePipeLocalInformation, + FilePipeRemoteInformation, + FileMailslotQueryInformation, + FileMailslotSetInformation, + FileCompressionInformation, + FileObjectIdInformation, + FileCompletionInformation, + FileMoveClusterInformation, + FileQuotaInformation, + FileReparsePointInformation, + FileNetworkOpenInformation, + FileAttributeTagInformation, + FileTrackingInformation, + FileIdBothDirectoryInformation, + FileIdFullDirectoryInformation, + FileValidDataLengthInformation, + FileShortNameInformation, + FileIoCompletionNotificationInformation, + FileIoStatusBlockRangeInformation, + FileIoPriorityHintInformation, + FileSfioReserveInformation, + FileSfioVolumeInformation, + FileHardLinkInformation, + FileProcessIdsUsingFileInformation, + FileNormalizedNameInformation, + FileNetworkPhysicalNameInformation, + FileIdGlobalTxDirectoryInformation, + FileIsRemoteDeviceInformation, + FileUnusedInformation, + FileNumaNodeInformation, + FileStandardLinkInformation, + FileRemoteProtocolInformation, + FileRenameInformationBypassAccessCheck, + FileLinkInformationBypassAccessCheck, + FileVolumeNameInformation, + FileIdInformation, + FileIdExtdDirectoryInformation, + FileReplaceCompletionInformation, + FileHardLinkFullIdInformation, + FileIdExtdBothDirectoryInformation, + FileDispositionInformationEx, + FileRenameInformationEx, + FileRenameInformationExBypassAccessCheck, + FileDesiredStorageClassInformation, + FileStatInformation, + FileMemoryPartitionInformation, + FileStatLxInformation, + FileCaseSensitiveInformation, + FileLinkInformationEx, + FileLinkInformationExBypassAccessCheck, + FileStorageReserveIdInformation, + FileCaseSensitiveInformationForceAccessCheck, + FileMaximumInformation +}; + pub const OVERLAPPED = extern struct { Internal: ULONG_PTR, InternalHigh: ULONG_PTR, @@ -104,6 +247,19 @@ pub const FileIdInfo = 18; pub const FileIdExtdDirectoryInfo = 19; pub const FileIdExtdDirectoryRestartInfo = 20; +pub const BY_HANDLE_FILE_INFORMATION = extern struct { + dwFileAttributes: DWORD, + ftCreationTime: FILETIME, + ftLastAccessTime: FILETIME, + ftLastWriteTime: FILETIME, + dwVolumeSerialNumber: DWORD, + nFileSizeHigh: DWORD, + nFileSizeLow: DWORD, + nNumberOfLinks: DWORD, + nFileIndexHigh: DWORD, + nFileIndexLow: DWORD, +}; + pub const FILE_NAME_INFO = extern struct { FileNameLength: DWORD, FileName: [1]WCHAR, @@ -561,3 +717,18 @@ pub const EXCEPTION_POINTERS = extern struct { }; pub const VECTORED_EXCEPTION_HANDLER = stdcallcc fn (ExceptionInfo: *EXCEPTION_POINTERS) c_long; + +pub const OBJECT_ATTRIBUTES = extern struct { + Length: ULONG, + RootDirectory: HANDLE, + ObjectName: *UNICODE_STRING, + Attributes: ULONG, + SecurityDescriptor: ?*c_void, + SecurityQualityOfService: ?*c_void, +}; + +pub const UNICODE_STRING = extern struct { + Length: USHORT, + MaximumLength: USHORT, + Buffer: [*]WCHAR, +};
\ No newline at end of file diff --git a/std/os/windows/kernel32.zig b/std/os/windows/kernel32.zig index 494da90d72..e4edc349ab 100644 --- a/std/os/windows/kernel32.zig +++ b/std/os/windows/kernel32.zig @@ -83,6 +83,11 @@ pub extern "kernel32" stdcallcc fn GetModuleHandleW(lpModuleName: ?[*]const WCHA pub extern "kernel32" stdcallcc fn GetLastError() DWORD; +pub extern "kernel32" stdcallcc fn GetFileInformationByHandle( + hFile: HANDLE, + lpFileInformation: *BY_HANDLE_FILE_INFORMATION, +) BOOL; + pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx( in_hFile: HANDLE, in_FileInformationClass: FILE_INFO_BY_HANDLE_CLASS, @@ -165,6 +170,13 @@ pub extern "kernel32" stdcallcc fn SetFilePointerEx( in_dwMoveMethod: DWORD, ) BOOL; +pub extern "kernel32" stdcallcc fn SetFileTime( + hFile: HANDLE, + lpCreationTime: ?*const FILETIME, + lpLastAccessTime: ?*const FILETIME, + lpLastWriteTime: ?*const FILETIME, +) BOOL; + pub extern "kernel32" stdcallcc fn SetHandleInformation(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD) BOOL; pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD) void; diff --git a/std/os/windows/ntdll.zig b/std/os/windows/ntdll.zig index e5469cdcf9..746403fa6d 100644 --- a/std/os/windows/ntdll.zig +++ b/std/os/windows/ntdll.zig @@ -1,3 +1,18 @@ usingnamespace @import("bits.zig"); pub extern "NtDll" stdcallcc fn RtlCaptureStackBackTrace(FramesToSkip: DWORD, FramesToCapture: DWORD, BackTrace: **c_void, BackTraceHash: ?*DWORD) WORD; +pub extern "NtDll" stdcallcc fn NtQueryInformationFile(FileHandle: HANDLE, IoStatusBlock: *IO_STATUS_BLOCK, FileInformation: *c_void, Length: ULONG, FileInformationClass: FILE_INFORMATION_CLASS,) NTSTATUS; +pub extern "NtDll" stdcallcc fn NtCreateFile( + FileHandle: *HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: *OBJECT_ATTRIBUTES, + IoStatusBlock: *IO_STATUS_BLOCK, + AllocationSize: *LARGE_INTEGER, + FileAttributes: ULONG, + ShareAccess: ULONG, + CreateDisposition: ULONG, + CreateOptions: ULONG, + EaBuffer: *c_void, + EaLength: ULONG, +) NTSTATUS; +pub extern "NtDll" stdcallcc fn NtClose(Handle: HANDLE) NTSTATUS;
\ No newline at end of file diff --git a/std/os/windows/status.zig b/std/os/windows/status.zig new file mode 100644 index 0000000000..668a736e90 --- /dev/null +++ b/std/os/windows/status.zig @@ -0,0 +1,5 @@ +/// The operation completed successfully. +pub const SUCCESS = 0x00000000; + +/// The data was too large to fit into the specified buffer. +pub const BUFFER_OVERFLOW = 0x80000005;
\ No newline at end of file |
