Merge wasi-common into wasmtime

This commit merges [CraneStation/wasi-common] repo as a subdir of
this repo while preserving **all** of git history. There is an
initiative to pull `wasi-common` into [CraneStation/wasmtime], and
[CraneStation/wasmtime] becoming a monorepo. This came about for
several reasons with a common theme of convenience, namely,
having a monorepo:
1. cleans up the problem of dependencies (as we have seen first
   hand with dependabot enabled, it can cause some grief)
2. completely removes the problem of syncing the closely dependent
   repos (e.g., updating `wasi-common` with say a bugfix generally
   implies creating a "sync" commit for pulling in the changes into
   the "parent" repo, in this case, `wasmtime`)
3. mainly for the two reasons above, makes publishing to crates.io
   easier
4. hopefully streamlines the process of getting the community
   involved in contributing to `wasi-common` as now everything
   is one place

[CraneStation/wasi-common]: https://github.com/CraneStation/wasi-common
[CraneStation/wasmtime]: https://github.com/CraneStation/wasmtime
This commit is contained in:
Jakub Konka
2019-11-07 15:16:34 +01:00
120 changed files with 14853 additions and 5 deletions

View File

@@ -0,0 +1,12 @@
[package]
name = "winx"
version = "0.5.0"
authors = ["Jakub Konka <kubkon@jakubkonka.com>"]
edition = "2018"
license = "Apache-2.0 WITH LLVM-exception"
description = "Windows API helper library"
[dependencies]
winapi = { version = "0.3", features = ["std", "errhandlingapi", "handleapi", "processthreadsapi", "securitybaseapi", "winbase", "winerror", "ws2def", "fileapi", "aclapi" ] }
bitflags = "1.0"
cvt = "0.1"

220
wasi-common/winx/LICENSE Normal file
View File

@@ -0,0 +1,220 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--- LLVM Exceptions to the Apache 2.0 License ----
As an exception, if, as a result of your compiling your source code, portions
of this Software are embedded into an Object form of such source code, you
may redistribute such embedded portions in such Object form without complying
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
In addition, if you combine or link compiled forms of this Software with
software that is licensed under the GPLv2 ("Combined Software") and if a
court of competent jurisdiction determines that the patent provision (Section
3), the indemnity provision (Section 9) or other Section of the License
conflicts with the conditions of the GPLv2, you may retroactively and
prospectively choose to deem waived or otherwise exclude such Section(s) of
the License, but only in their entirety and only with respect to the Combined
Software.

View File

@@ -0,0 +1,416 @@
#![allow(non_camel_case_types)]
use crate::{winerror, Result};
use cvt::cvt;
use std::ffi::{c_void, OsString};
use std::fs::File;
use std::io;
use std::os::windows::prelude::{AsRawHandle, OsStringExt, RawHandle};
use winapi::shared::minwindef::{self, DWORD};
use winapi::um::{fileapi, fileapi::GetFileType, minwinbase, winbase, winnt};
/// Maximum total path length for Unicode in Windows.
/// [Maximum path length limitation]: https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
pub const WIDE_MAX_PATH: DWORD = 0x7fff;
#[derive(Debug, Copy, Clone)]
pub struct FileType(minwindef::DWORD);
// possible types are:
// * FILE_TYPE_CHAR
// * FILE_TYPE_DISK
// * FILE_TYPE_PIPE
// * FILE_TYPE_REMOTE
// * FILE_TYPE_UNKNOWN
//
// FILE_TYPE_REMOTE is unused
// https://technet.microsoft.com/en-us/evalcenter/aa364960(v=vs.100)
impl FileType {
/// Returns true if character device such as LPT device or console
pub fn is_char(&self) -> bool {
self.0 == winbase::FILE_TYPE_CHAR
}
/// Returns true if disk device such as file or dir
pub fn is_disk(&self) -> bool {
self.0 == winbase::FILE_TYPE_DISK
}
/// Returns true if pipe device such as socket, named pipe or anonymous pipe
pub fn is_pipe(&self) -> bool {
self.0 == winbase::FILE_TYPE_PIPE
}
/// Returns true if unknown device
pub fn is_unknown(&self) -> bool {
self.0 == winbase::FILE_TYPE_UNKNOWN
}
}
pub unsafe fn get_file_type(handle: RawHandle) -> Result<FileType> {
let file_type = FileType(GetFileType(handle));
let err = winerror::WinError::last();
if file_type.is_unknown() && err != winerror::WinError::ERROR_SUCCESS {
Err(err)
} else {
Ok(file_type)
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[repr(u32)]
pub enum CreationDisposition {
NO_DISPOSITION = 0,
/// Creates a new file, only if it does not already exist.
/// If the specified file exists, the function fails and the last-error code is
/// set to ERROR_FILE_EXISTS (80).
///
/// If the specified file does not exist and is a valid path to a writable location,
/// a new file is created.
CREATE_NEW = fileapi::CREATE_NEW,
/// Creates a new file, always.
/// If the specified file exists and is writable, the function overwrites the file,
/// the function succeeds, and last-error code is set to ERROR_ALREADY_EXISTS (183).
///
/// If the specified file does not exist and is a valid path, a new file is created,
/// the function succeeds, and the last-error code is set to zero.
CREATE_ALWAYS = fileapi::CREATE_ALWAYS,
/// Opens a file or device, only if it exists.
/// If the specified file or device does not exist, the function fails and the
/// last-error code is set to ERROR_FILE_NOT_FOUND (2).
OPEN_EXISTING = fileapi::OPEN_EXISTING,
/// Opens a file, always.
/// If the specified file exists, the function succeeds and the last-error code is
/// set to ERROR_ALREADY_EXISTS (183).
///
/// If the specified file does not exist and is a valid path to a writable location,
/// the function creates a file and the last-error code is set to zero.
OPEN_ALWAYS = fileapi::OPEN_ALWAYS,
/// Opens a file and truncates it so that its size is zero bytes, only if it exists.
/// If the specified file does not exist, the function fails and the last-error code
/// is set to ERROR_FILE_NOT_FOUND (2).
///
/// The calling process must open the file with the GENERIC_WRITE bit set as part
/// of the dwDesiredAccess parameter.
TRUNCATE_EXISTING = fileapi::TRUNCATE_EXISTING,
}
impl CreationDisposition {
pub fn from_u32(disp: u32) -> Self {
use CreationDisposition::*;
match disp {
fileapi::CREATE_NEW => CREATE_NEW,
fileapi::CREATE_ALWAYS => CREATE_ALWAYS,
fileapi::OPEN_EXISTING => OPEN_EXISTING,
fileapi::OPEN_ALWAYS => OPEN_ALWAYS,
fileapi::TRUNCATE_EXISTING => TRUNCATE_EXISTING,
_ => NO_DISPOSITION,
}
}
}
bitflags! {
pub struct Attributes: minwindef::DWORD {
/// A file or directory that is an archive file or directory.
/// Applications typically use this attribute to mark files for backup or removal.
const FILE_ATTRIBUTE_ARCHIVE = winnt::FILE_ATTRIBUTE_ARCHIVE;
/// A file or directory that is compressed. For a file, all of the data in the file is compressed.
/// For a directory, compression is the default for newly created files and subdirectories.
const FILE_ATTRIBUTE_COMPRESSED = winnt::FILE_ATTRIBUTE_COMPRESSED;
/// This value is reserved for system use.
const FILE_ATTRIBUTE_DEVICE = winnt::FILE_ATTRIBUTE_DEVICE;
/// The handle that identifies a directory.
const FILE_ATTRIBUTE_DIRECTORY = winnt::FILE_ATTRIBUTE_DIRECTORY;
/// A file or directory that is encrypted. For a file, all data streams in the file are encrypted.
/// For a directory, encryption is the default for newly created files and subdirectories.
const FILE_ATTRIBUTE_ENCRYPTED = winnt::FILE_ATTRIBUTE_ENCRYPTED;
/// The file or directory is hidden. It is not included in an ordinary directory listing.
const FILE_ATTRIBUTE_HIDDEN = winnt::FILE_ATTRIBUTE_HIDDEN;
/// The directory or user data stream is configured with integrity (only supported on ReFS volumes).
/// It is not included in an ordinary directory listing. The integrity setting persists with the file if it's renamed.
/// If a file is copied the destination file will have integrity set if either the source file or destination directory have integrity set.
const FILE_ATTRIBUTE_INTEGRITY_STREAM = winnt::FILE_ATTRIBUTE_INTEGRITY_STREAM;
/// A file that does not have other attributes set. This attribute is valid only when used alone.
const FILE_ATTRIBUTE_NORMAL = winnt::FILE_ATTRIBUTE_NORMAL;
/// The file or directory is not to be indexed by the content indexing service.
const FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = winnt::FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
/// The user data stream not to be read by the background data integrity scanner (AKA scrubber).
/// When set on a directory it only provides inheritance. This flag is only supported on Storage Spaces and ReFS volumes.
/// It is not included in an ordinary directory listing.
const FILE_ATTRIBUTE_NO_SCRUB_DATA = winnt::FILE_ATTRIBUTE_NO_SCRUB_DATA;
/// The data of a file is not available immediately.
/// This attribute indicates that the file data is physically moved to offline storage.
/// This attribute is used by Remote Storage, which is the hierarchical storage management software.
/// Applications should not arbitrarily change this attribute.
const FILE_ATTRIBUTE_OFFLINE = winnt::FILE_ATTRIBUTE_OFFLINE;
/// A file that is read-only. Applications can read the file, but cannot write to it or delete it.
/// This attribute is not honored on directories.
const FILE_ATTRIBUTE_READONLY = winnt::FILE_ATTRIBUTE_READONLY;
/// When this attribute is set, it means that the file or directory is not fully present locally.
/// For a file that means that not all of its data is on local storage (e.g. it may be sparse with some data still in remote storage).
/// For a directory it means that some of the directory contents are being virtualized from another location.
/// Reading the file / enumerating the directory will be more expensive than normal, e.g. it will cause at least some of the
/// file/directory content to be fetched from a remote store. Only kernel-mode callers can set this bit.
const FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = winnt::FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS;
/// This attribute only appears in directory enumeration classes (FILE_DIRECTORY_INFORMATION, FILE_BOTH_DIR_INFORMATION, etc.).
/// When this attribute is set, it means that the file or directory has no physical representation on the local system; the item is virtual.
/// Opening the item will be more expensive than normal, e.g. it will cause at least some of it to be fetched from a remote store.
const FILE_ATTRIBUTE_RECALL_ON_OPEN = winnt::FILE_ATTRIBUTE_RECALL_ON_OPEN;
/// A file or directory that has an associated reparse point, or a file that is a symbolic link.
const FILE_ATTRIBUTE_REPARSE_POINT = winnt::FILE_ATTRIBUTE_REPARSE_POINT;
/// A file that is a sparse file.
const FILE_ATTRIBUTE_SPARSE_FILE = winnt::FILE_ATTRIBUTE_SPARSE_FILE;
/// A file or directory that the operating system uses a part of, or uses exclusively.
const FILE_ATTRIBUTE_SYSTEM = winnt::FILE_ATTRIBUTE_SYSTEM;
/// A file that is being used for temporary storage.
/// File systems avoid writing data back to mass storage if sufficient cache memory is available, because typically,
/// an application deletes a temporary file after the handle is closed. In that scenario, the system can entirely
/// avoid writing the data. Otherwise, the data is written after the handle is closed.
const FILE_ATTRIBUTE_TEMPORARY = winnt::FILE_ATTRIBUTE_TEMPORARY;
/// This value is reserved for system use.
const FILE_ATTRIBUTE_VIRTUAL = winnt::FILE_ATTRIBUTE_VIRTUAL;
}
}
bitflags! {
pub struct Flags: minwindef::DWORD {
/// The file is being opened or created for a backup or restore operation.
/// The system ensures that the calling process overrides file security checks when the process has SE_BACKUP_NAME and SE_RESTORE_NAME privileges.
/// You must set this flag to obtain a handle to a directory. A directory handle can be passed to some functions instead of a file handle.
const FILE_FLAG_BACKUP_SEMANTICS = winbase::FILE_FLAG_BACKUP_SEMANTICS;
/// The file is to be deleted immediately after all of its handles are closed, which includes the specified handle and any other open or duplicated handles.
/// If there are existing open handles to a file, the call fails unless they were all opened with the FILE_SHARE_DELETE share mode.
/// Subsequent open requests for the file fail, unless the FILE_SHARE_DELETE share mode is specified.
const FILE_FLAG_DELETE_ON_CLOSE = winbase::FILE_FLAG_DELETE_ON_CLOSE;
/// The file or device is being opened with no system caching for data reads and writes.
/// This flag does not affect hard disk caching or memory mapped files.
/// There are strict requirements for successfully working with files opened with
/// CreateFile using the FILE_FLAG_NO_BUFFERING flag.
const FILE_FLAG_NO_BUFFERING = winbase::FILE_FLAG_NO_BUFFERING;
/// The file data is requested, but it should continue to be located in remote storage.
/// It should not be transported back to local storage. This flag is for use by remote storage systems.
const FILE_FLAG_OPEN_NO_RECALL = winbase::FILE_FLAG_OPEN_NO_RECALL;
/// Normal reparse point processing will not occur; CreateFile will attempt to open the reparse point.
/// When a file is opened, a file handle is returned, whether or not the filter that controls the reparse point is operational.
/// This flag cannot be used with the CREATE_ALWAYS flag.
/// If the file is not a reparse point, then this flag is ignored.
const FILE_FLAG_OPEN_REPARSE_POINT = winbase::FILE_FLAG_OPEN_REPARSE_POINT;
/// The file or device is being opened or created for asynchronous I/O.
/// When subsequent I/O operations are completed on this handle, the event specified in the OVERLAPPED structure will be set to the signaled state.
/// If this flag is specified, the file can be used for simultaneous read and write operations.
/// If this flag is not specified, then I/O operations are serialized, even if the calls to the read and write functions specify an OVERLAPPED structure.
const FILE_FLAG_OVERLAPPED = winbase::FILE_FLAG_OVERLAPPED;
/// Access will occur according to POSIX rules. This includes allowing multiple files with names,
/// differing only in case, for file systems that support that naming. Use care when using this option,
/// because files created with this flag may not be accessible by applications that are written for MS-DOS or 16-bit Windows.
const FILE_FLAG_POSIX_SEMANTICS = winbase::FILE_FLAG_POSIX_SEMANTICS;
/// Access is intended to be random. The system can use this as a hint to optimize file caching.
/// This flag has no effect if the file system does not support cached I/O and FILE_FLAG_NO_BUFFERING.
const FILE_FLAG_RANDOM_ACCESS = winbase::FILE_FLAG_RANDOM_ACCESS;
/// The file or device is being opened with session awareness.
/// If this flag is not specified, then per-session devices (such as a device using RemoteFX USB Redirection)
/// cannot be opened by processes running in session 0. This flag has no effect for callers not in session 0.
/// This flag is supported only on server editions of Windows.
const FILE_FLAG_SESSION_AWARE = winbase::FILE_FLAG_SESSION_AWARE;
/// Access is intended to be sequential from beginning to end. The system can use this as a hint to optimize file caching.
/// This flag should not be used if read-behind (that is, reverse scans) will be used.
/// This flag has no effect if the file system does not support cached I/O and FILE_FLAG_NO_BUFFERING.
const FILE_FLAG_SEQUENTIAL_SCAN = winbase::FILE_FLAG_SEQUENTIAL_SCAN;
/// Write operations will not go through any intermediate cache, they will go directly to disk.
const FILE_FLAG_WRITE_THROUGH = winbase::FILE_FLAG_WRITE_THROUGH;
}
}
bitflags! {
/// [Access mask]: https://docs.microsoft.com/en-us/windows/desktop/SecAuthZ/access-mask
pub struct AccessMode: minwindef::DWORD {
/// For a file object, the right to read the corresponding file data.
/// For a directory object, the right to read the corresponding directory data.
const FILE_READ_DATA = winnt::FILE_READ_DATA;
const FILE_LIST_DIRECTORY = winnt::FILE_LIST_DIRECTORY;
/// For a file object, the right to write data to the file.
/// For a directory object, the right to create a file in the directory.
const FILE_WRITE_DATA = winnt::FILE_WRITE_DATA;
const FILE_ADD_FILE = winnt::FILE_ADD_FILE;
/// For a file object, the right to append data to the file.
/// (For local files, write operations will not overwrite existing data
/// if this flag is specified without FILE_WRITE_DATA.)
/// For a directory object, the right to create a subdirectory.
/// For a named pipe, the right to create a pipe.
const FILE_APPEND_DATA = winnt::FILE_APPEND_DATA;
const FILE_ADD_SUBDIRECTORY = winnt::FILE_ADD_SUBDIRECTORY;
const FILE_CREATE_PIPE_INSTANCE = winnt::FILE_CREATE_PIPE_INSTANCE;
/// The right to read extended file attributes.
const FILE_READ_EA = winnt::FILE_READ_EA;
/// The right to write extended file attributes.
const FILE_WRITE_EA = winnt::FILE_WRITE_EA;
/// For a file, the right to execute FILE_EXECUTE.
/// For a directory, the right to traverse the directory.
/// By default, users are assigned the BYPASS_TRAVERSE_CHECKING privilege,
/// which ignores the FILE_TRAVERSE access right.
const FILE_EXECUTE = winnt::FILE_EXECUTE;
const FILE_TRAVERSE = winnt::FILE_TRAVERSE;
/// For a directory, the right to delete a directory and all
/// the files it contains, including read-only files.
const FILE_DELETE_CHILD = winnt::FILE_DELETE_CHILD;
/// The right to read file attributes.
const FILE_READ_ATTRIBUTES = winnt::FILE_READ_ATTRIBUTES;
/// The right to write file attributes.
const FILE_WRITE_ATTRIBUTES = winnt::FILE_WRITE_ATTRIBUTES;
/// The right to delete the object.
const DELETE = winnt::DELETE;
/// The right to read the information in the object's security descriptor,
/// not including the information in the system access control list (SACL).
const READ_CONTROL = winnt::READ_CONTROL;
/// The right to use the object for synchronization. This enables a thread
/// to wait until the object is in the signaled state. Some object types
/// do not support this access right.
const SYNCHRONIZE = winnt::SYNCHRONIZE;
/// The right to modify the discretionary access control list (DACL) in
/// the object's security descriptor.
const WRITE_DAC = winnt::WRITE_DAC;
/// The right to change the owner in the object's security descriptor.
const WRITE_OWNER = winnt::WRITE_OWNER;
/// It is used to indicate access to a system access control list (SACL).
const ACCESS_SYSTEM_SECURITY = winnt::ACCESS_SYSTEM_SECURITY;
/// Maximum allowed.
const MAXIMUM_ALLOWED = winnt::MAXIMUM_ALLOWED;
/// Reserved
const RESERVED1 = 0x4000000;
/// Reserved
const RESERVED2 = 0x8000000;
/// Provides all possible access rights.
/// This is convenience flag which is translated by the OS into actual [`FILE_GENERIC_ALL`] union.
const GENERIC_ALL = winnt::GENERIC_ALL;
/// Provides execute access.
const GENERIC_EXECUTE = winnt::GENERIC_EXECUTE;
/// Provides write access.
/// This is convenience flag which is translated by the OS into actual [`FILE_GENERIC_WRITE`] union.
const GENERIC_WRITE = winnt::GENERIC_WRITE;
/// Provides read access.
/// This is convenience flag which is translated by the OS into actual [`FILE_GENERIC_READ`] union.
const GENERIC_READ = winnt::GENERIC_READ;
/// Provides read access.
/// This flag is a union of: FILE_READ_ATTRIBUTES, FILE_READ_DATA, FILE_READ_EA, READ_CONTROL, SYNCHRONIZE
const FILE_GENERIC_READ = AccessMode::FILE_READ_ATTRIBUTES.bits
| AccessMode::FILE_READ_DATA.bits
| AccessMode::FILE_READ_EA.bits
| AccessMode::READ_CONTROL.bits
| AccessMode::SYNCHRONIZE.bits;
/// Provides write access.
/// This flag is a union of: FILE_WRITE_ATTRIBUTES, FILE_WRITE_DATA, FILE_WRITE_EA, READ_CONTROL, SYNCHRONIZE
const FILE_GENERIC_WRITE = AccessMode::FILE_WRITE_ATTRIBUTES.bits
| AccessMode::FILE_WRITE_DATA.bits
| AccessMode::FILE_WRITE_EA.bits
| AccessMode::READ_CONTROL.bits
| AccessMode::SYNCHRONIZE.bits;
/// Provides execute access.
/// This flag is a union of: FILE_WRITE_ATTRIBUTES, FILE_WRITE_DATA, FILE_WRITE_EA, READ_CONTROL, SYNCHRONIZE
const FILE_GENERIC_EXECUTE = AccessMode::FILE_EXECUTE.bits
| AccessMode::FILE_READ_ATTRIBUTES.bits
| AccessMode::READ_CONTROL.bits
| AccessMode::SYNCHRONIZE.bits;
/// Provides all accesses.
/// This flag is a union of: FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE
const FILE_GENERIC_ALL = AccessMode::FILE_GENERIC_READ.bits | AccessMode::FILE_GENERIC_WRITE.bits | AccessMode::FILE_GENERIC_EXECUTE.bits;
}
}
pub unsafe fn get_file_access_mode(handle: RawHandle) -> Result<AccessMode> {
use winapi::shared::minwindef::FALSE;
use winapi::um::accctrl;
use winapi::um::aclapi::GetSecurityInfo;
use winapi::um::securitybaseapi::{GetAce, IsValidAcl};
let mut dacl = 0 as winnt::PACL;
let mut sec_desc = 0 as winnt::PSECURITY_DESCRIPTOR;
let err = winerror::WinError::from_u32(GetSecurityInfo(
handle,
accctrl::SE_FILE_OBJECT,
winnt::DACL_SECURITY_INFORMATION,
std::ptr::null_mut(),
std::ptr::null_mut(),
&mut dacl,
std::ptr::null_mut(),
&mut sec_desc,
));
if err != winerror::WinError::ERROR_SUCCESS {
return Err(err);
}
if IsValidAcl(dacl) == FALSE {
return Err(winerror::WinError::last());
}
// let count = (*dacl).AceCount;
let mut ace = 0 as winnt::PVOID;
if GetAce(dacl, 0, &mut ace) == FALSE {
return Err(winerror::WinError::last());
}
// TODO: check for PACCESS_ALLOWED_ACE in Ace before accessing
// let header = (*(ace as winnt::PACCESS_ALLOWED_ACE)).Header.AceType;
Ok(AccessMode::from_bits_truncate(
(*(ace as winnt::PACCESS_ALLOWED_ACE)).Mask,
))
}
pub fn get_file_path(file: &File) -> Result<OsString> {
use winapi::um::fileapi::GetFinalPathNameByHandleW;
let mut raw_path: Vec<u16> = vec![0; WIDE_MAX_PATH as usize];
let handle = file.as_raw_handle();
let read_len =
unsafe { GetFinalPathNameByHandleW(handle, raw_path.as_mut_ptr(), WIDE_MAX_PATH, 0) };
if read_len == 0 {
// failed to read
return Err(winerror::WinError::last());
}
// obtain a slice containing the written bytes, and check for it being too long
// (practically probably impossible)
let written_bytes = raw_path
.get(..read_len as usize)
.ok_or(winerror::WinError::ERROR_BUFFER_OVERFLOW)?;
Ok(OsString::from_wide(written_bytes))
}
pub fn get_fileinfo(file: &File) -> io::Result<fileapi::BY_HANDLE_FILE_INFORMATION> {
use fileapi::{GetFileInformationByHandle, BY_HANDLE_FILE_INFORMATION};
use std::mem;
let handle = file.as_raw_handle();
let info = unsafe {
let mut info: BY_HANDLE_FILE_INFORMATION = mem::zeroed();
cvt(GetFileInformationByHandle(handle, &mut info))?;
info
};
Ok(info)
}
pub fn change_time(file: &File) -> io::Result<i64> {
use fileapi::FILE_BASIC_INFO;
use minwinbase::FileBasicInfo;
use std::mem;
use winbase::GetFileInformationByHandleEx;
let handle = file.as_raw_handle();
let tm = unsafe {
let mut info: FILE_BASIC_INFO = mem::zeroed();
let infosize = mem::size_of_val(&info);
cvt(GetFileInformationByHandleEx(
handle,
FileBasicInfo,
&mut info as *mut FILE_BASIC_INFO as *mut c_void,
infosize as u32,
))?;
*info.ChangeTime.QuadPart()
};
Ok(tm)
}

View File

@@ -0,0 +1,33 @@
#![deny(
// missing_docs,
trivial_numeric_casts,
unused_extern_crates,
unstable_features
)]
#![warn(unused_import_braces)]
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../clippy.toml")))]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_without_default))]
#![cfg_attr(
feature = "cargo-clippy",
warn(
clippy::float_arithmetic,
clippy::mut_mut,
clippy::nonminimal_bool,
clippy::option_map_unwrap_or,
clippy::option_map_unwrap_or_else,
clippy::unicode_not_nfc,
clippy::use_self
)
)]
#![cfg(windows)]
#[macro_use]
extern crate bitflags;
pub mod file;
pub mod time;
pub mod winerror;
use winerror::WinError;
pub type Result<T> = std::result::Result<T, WinError>;

View File

@@ -0,0 +1,10 @@
use cvt::cvt;
use winapi::um::{profileapi::QueryPerformanceFrequency, winnt::LARGE_INTEGER};
pub fn perf_counter_frequency() -> std::io::Result<u64> {
unsafe {
let mut frequency: LARGE_INTEGER = std::mem::zeroed();
cvt(QueryPerformanceFrequency(&mut frequency))?;
Ok(*frequency.QuadPart() as u64)
}
}

View File

@@ -0,0 +1,127 @@
#![allow(non_camel_case_types)]
use winapi::shared::winerror;
use winapi::um::errhandlingapi::GetLastError;
macro_rules! win_error_expand {
{
$(
#[doc=$doc:literal]
$error:ident,
)*
} => {
/// Wraps WINAPI error code as enum.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[repr(u32)]
pub enum WinError {
/// Unknown error occurred.
UnknownError = std::u32::MAX,
$(
#[doc=$doc]
$error = winerror::$error,
)*
}
fn desc(err: WinError) -> &'static str {
use WinError::*;
match err {
UnknownError => r" Unknown error occurred.",
$($error => $doc,)*
}
}
fn from_u32(err: u32) -> WinError {
use WinError::*;
match err {
$(winerror::$error => $error,)*
_ => UnknownError,
}
}
}
}
win_error_expand! {
/// The operation completed successfully.
ERROR_SUCCESS,
/// The system cannot find the file specified.
ERROR_FILE_NOT_FOUND,
/// The system cannot find the path specified.
ERROR_PATH_NOT_FOUND,
/// The system cannot open the file.
ERROR_TOO_MANY_OPEN_FILES,
/// Access is denied.
ERROR_ACCESS_DENIED,
/// The handle is invalid.
ERROR_INVALID_HANDLE,
/// Not enough storage is available to process this command.
ERROR_NOT_ENOUGH_MEMORY,
/// The environment is incorrect.
ERROR_BAD_ENVIRONMENT,
/// Not enough storage is available to complete this operation.
ERROR_OUTOFMEMORY,
/// The device is not ready.
ERROR_NOT_READY,
/// The request is not supported.
ERROR_NOT_SUPPORTED,
/// The file exists.
ERROR_FILE_EXISTS,
/// The pipe has been ended.
ERROR_BROKEN_PIPE,
/// The file name is too long.
ERROR_BUFFER_OVERFLOW,
/// The directory is not empty.
ERROR_DIR_NOT_EMPTY,
/// The volume label you entered exceeds the label character limit of the destination file system.
ERROR_LABEL_TOO_LONG,
/// The requested resource is in use.
ERROR_BUSY,
/// The file name, directory name, or volume label syntax is incorrect.
ERROR_INVALID_NAME,
/// The process cannot access the file because it is being used by another process.
ERROR_SHARING_VIOLATION,
/// A required privilege is not held by the client.
ERROR_PRIVILEGE_NOT_HELD,
/// The file or directory is not a reparse point.
ERROR_NOT_A_REPARSE_POINT,
/// An attempt was made to move the file pointer before the beginning of the file.
ERROR_NEGATIVE_SEEK,
/// The directory name is invalid.
ERROR_DIRECTORY,
/// Cannot create a file when that file already exists.
ERROR_ALREADY_EXISTS,
}
impl WinError {
/// Returns the last error as WinError.
pub fn last() -> Self {
Self::from_u32(unsafe { GetLastError() })
}
/// Constructs WinError from error code.
pub fn from_u32(err: u32) -> Self {
from_u32(err)
}
/// Returns error's description string. This description matches
/// the docs for the error.
pub fn desc(self) -> &'static str {
desc(self)
}
}
impl std::error::Error for WinError {
fn description(&self) -> &str {
self.desc()
}
}
impl std::fmt::Display for WinError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}: {}", self, self.desc())
}
}
impl From<WinError> for std::io::Error {
fn from(err: WinError) -> Self {
Self::from_raw_os_error(err as i32)
}
}