mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +00:00
Various Windows fixes
Improve handling of unicode on Windows Disable a few crates on Windows that abuse unix APIs too much Signed-off-by: Peter Atashian <retep998@gmail.com>
This commit is contained in:
parent
1a2be4bf7f
commit
47f82f0de2
14 changed files with 153 additions and 139 deletions
12
Makefile
12
Makefile
|
@ -52,7 +52,6 @@ PROGS := \
|
||||||
dirname \
|
dirname \
|
||||||
echo \
|
echo \
|
||||||
env \
|
env \
|
||||||
du \
|
|
||||||
expand \
|
expand \
|
||||||
factor \
|
factor \
|
||||||
false \
|
false \
|
||||||
|
@ -62,7 +61,6 @@ PROGS := \
|
||||||
hashsum \
|
hashsum \
|
||||||
ln \
|
ln \
|
||||||
mkdir \
|
mkdir \
|
||||||
mv \
|
|
||||||
nl \
|
nl \
|
||||||
nproc \
|
nproc \
|
||||||
od \
|
od \
|
||||||
|
@ -85,13 +83,11 @@ PROGS := \
|
||||||
tac \
|
tac \
|
||||||
tee \
|
tee \
|
||||||
test \
|
test \
|
||||||
touch \
|
|
||||||
tr \
|
tr \
|
||||||
true \
|
true \
|
||||||
truncate \
|
truncate \
|
||||||
tsort \
|
tsort \
|
||||||
unexpand \
|
unexpand \
|
||||||
unlink \
|
|
||||||
uniq \
|
uniq \
|
||||||
wc \
|
wc \
|
||||||
yes \
|
yes \
|
||||||
|
@ -101,6 +97,7 @@ PROGS := \
|
||||||
|
|
||||||
UNIX_PROGS := \
|
UNIX_PROGS := \
|
||||||
chroot \
|
chroot \
|
||||||
|
du \
|
||||||
groups \
|
groups \
|
||||||
hostid \
|
hostid \
|
||||||
hostname \
|
hostname \
|
||||||
|
@ -108,12 +105,15 @@ UNIX_PROGS := \
|
||||||
kill \
|
kill \
|
||||||
logname \
|
logname \
|
||||||
mkfifo \
|
mkfifo \
|
||||||
|
mv \
|
||||||
nice \
|
nice \
|
||||||
nohup \
|
nohup \
|
||||||
stdbuf \
|
stdbuf \
|
||||||
timeout \
|
timeout \
|
||||||
|
touch \
|
||||||
tty \
|
tty \
|
||||||
uname \
|
uname \
|
||||||
|
unlink \
|
||||||
uptime \
|
uptime \
|
||||||
users
|
users
|
||||||
|
|
||||||
|
@ -256,6 +256,10 @@ define DEP_BUILD
|
||||||
DEP_$(1):
|
DEP_$(1):
|
||||||
ifeq ($(1),crypto)
|
ifeq ($(1),crypto)
|
||||||
cd $(BASEDIR)/deps && $(CARGO) build --package rust-crypto --release
|
cd $(BASEDIR)/deps && $(CARGO) build --package rust-crypto --release
|
||||||
|
else ifeq ($(1),kernel32)
|
||||||
|
cd $(BASEDIR)/deps && $(CARGO) build --package kernel32-sys --release
|
||||||
|
else ifeq ($(1),advapi32)
|
||||||
|
cd $(BASEDIR)/deps && $(CARGO) build --package advapi32-sys --release
|
||||||
else
|
else
|
||||||
cd $(BASEDIR)/deps && $(CARGO) build --package $(1) --release
|
cd $(BASEDIR)/deps && $(CARGO) build --package $(1) --release
|
||||||
endif
|
endif
|
||||||
|
|
3
deps/Cargo.toml
vendored
3
deps/Cargo.toml
vendored
|
@ -17,3 +17,6 @@ rust-crypto = "0.2.31"
|
||||||
rustc-serialize = "0.3.15"
|
rustc-serialize = "0.3.15"
|
||||||
time = "0.1.26"
|
time = "0.1.26"
|
||||||
unicode-width = "0.1.1"
|
unicode-width = "0.1.1"
|
||||||
|
winapi = "0.2"
|
||||||
|
advapi32-sys = "0.1"
|
||||||
|
kernel32-sys = "0.1"
|
||||||
|
|
|
@ -124,17 +124,17 @@ fn verify_mode(modes: &str) -> Result<(), String> {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
#[inline]
|
#[inline]
|
||||||
// XXX: THIS IS NOT TESTED!!!
|
// XXX: THIS IS NOT TESTED!!!
|
||||||
fn verify_mode(mode: &str) -> Result<(), String> {
|
fn verify_mode(modes: &str) -> Result<(), String> {
|
||||||
let re: regex::Regex = Regex::new(r"^[ugoa]*(?:[-+=](?:([rwxXst]*)|[ugo]))+|[-+=]?([0-7]+)$").unwrap();
|
let re: regex::Regex = Regex::new(r"^[ugoa]*(?:[-+=](?:([rwxXst]*)|[ugo]))+|[-+=]?([0-7]+)$").unwrap();
|
||||||
for mode in modes.split(',') {
|
for mode in modes.split(',') {
|
||||||
match re.captures(mode) {
|
match re.captures(mode) {
|
||||||
Some(cap) => {
|
Some(cap) => {
|
||||||
let symbols = cap.at(1);
|
let symbols = cap.at(1).unwrap();
|
||||||
let numbers = cap.at(2);
|
let numbers = cap.at(2).unwrap();
|
||||||
if symbols.contains("s") || symbols.contains("t") {
|
if symbols.contains("s") || symbols.contains("t") {
|
||||||
return Err("The 's' and 't' modes are not supported on Windows".to_string());
|
return Err("The 's' and 't' modes are not supported on Windows".into());
|
||||||
} else if numbers.len() >= 4 && numbers.slice_to(num_len - 3).find(|ch| ch != '0').is_some() {
|
} else if numbers.len() >= 4 && numbers[..numbers.len() - 3].find(|ch| ch != '0').is_some() {
|
||||||
return Err("Setuid, setgid, and sticky modes are not supported on Windows".to_string());
|
return Err("Setuid, setgid, and sticky modes are not supported on Windows".into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => return Err(format!("invalid mode '{}'", mode))
|
None => return Err(format!("invalid mode '{}'", mode))
|
||||||
|
@ -191,6 +191,14 @@ fn chmod(files: Vec<String>, changes: bool, quiet: bool, verbose: bool, preserve
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn chmod_file(file: &Path, name: &str, changes: bool, quiet: bool, verbose: bool, fmode: Option<libc::mode_t>, cmode: Option<&String>) -> Result<(), i32> {
|
||||||
|
// chmod is useless on Windows
|
||||||
|
// it doesn't set any permissions at all
|
||||||
|
// instead it just sets the readonly attribute on the file
|
||||||
|
Err(0)
|
||||||
|
}
|
||||||
|
#[cfg(unix)]
|
||||||
fn chmod_file(file: &Path, name: &str, changes: bool, quiet: bool, verbose: bool, fmode: Option<libc::mode_t>, cmode: Option<&String>) -> Result<(), i32> {
|
fn chmod_file(file: &Path, name: &str, changes: bool, quiet: bool, verbose: bool, fmode: Option<libc::mode_t>, cmode: Option<&String>) -> Result<(), i32> {
|
||||||
let path = CString::new(name).unwrap_or_else(|e| panic!("{}", e));
|
let path = CString::new(name).unwrap_or_else(|e| panic!("{}", e));
|
||||||
match fmode {
|
match fmode {
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern crate libc;
|
|
||||||
|
|
||||||
macro_rules! show_error(
|
macro_rules! show_error(
|
||||||
($($args:tt)+) => ({
|
($($args:tt)+) => ({
|
||||||
pipe_write!(&mut ::std::io::stderr(), "{}: error: ", ::NAME);
|
pipe_write!(&mut ::std::io::stderr(), "{}: error: ", ::NAME);
|
||||||
|
@ -46,14 +44,14 @@ macro_rules! eprintln(
|
||||||
macro_rules! crash(
|
macro_rules! crash(
|
||||||
($exitcode:expr, $($args:tt)+) => ({
|
($exitcode:expr, $($args:tt)+) => ({
|
||||||
show_error!($($args)+);
|
show_error!($($args)+);
|
||||||
unsafe { ::util::libc::exit($exitcode as ::util::libc::c_int); }
|
::std::process::exit($exitcode)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! exit(
|
macro_rules! exit(
|
||||||
($exitcode:expr) => ({
|
($exitcode:expr) => ({
|
||||||
unsafe { ::util::libc::exit($exitcode); }
|
::std::process::exit($exitcode)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
35
src/common/wide.rs
Normal file
35
src/common/wide.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the uutils coreutils package.
|
||||||
|
*
|
||||||
|
* (c) Peter Atashian <retep998@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
use std::ffi::{OsStr, OsString};
|
||||||
|
use std::os::windows::ffi::{OsStrExt, OsStringExt};
|
||||||
|
pub trait ToWide {
|
||||||
|
fn to_wide(&self) -> Vec<u16>;
|
||||||
|
fn to_wide_null(&self) -> Vec<u16>;
|
||||||
|
}
|
||||||
|
impl<T> ToWide for T where T: AsRef<OsStr> {
|
||||||
|
fn to_wide(&self) -> Vec<u16> {
|
||||||
|
self.as_ref().encode_wide().collect()
|
||||||
|
}
|
||||||
|
fn to_wide_null(&self) -> Vec<u16> {
|
||||||
|
self.as_ref().encode_wide().chain(Some(0)).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub trait FromWide {
|
||||||
|
fn from_wide(wide: &[u16]) -> Self;
|
||||||
|
fn from_wide_null(wide: &[u16]) -> Self;
|
||||||
|
}
|
||||||
|
impl FromWide for String {
|
||||||
|
fn from_wide(wide: &[u16]) -> String {
|
||||||
|
OsString::from_wide(wide).to_string_lossy().into_owned()
|
||||||
|
}
|
||||||
|
fn from_wide_null(wide: &[u16]) -> String {
|
||||||
|
let len = wide.iter().take_while(|&&c| c != 0).count();
|
||||||
|
OsString::from_wide(&wide[..len]).to_string_lossy().into_owned()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1 @@
|
||||||
DEPLIBS += time
|
DEPLIBS += time kernel32 winapi
|
||||||
|
|
|
@ -25,7 +25,7 @@ macro_rules! silent_unwrap(
|
||||||
($exp:expr) => (
|
($exp:expr) => (
|
||||||
match $exp {
|
match $exp {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(_) => unsafe { ::util::libc::exit(1) }
|
Err(_) => ::std::process::exit(1),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
DEPLIBS += regex regex-syntax crypto rand rustc-serialize time
|
DEPLIBS += regex regex-syntax crypto rand rustc-serialize time winapi kernel32
|
||||||
|
|
|
@ -136,13 +136,21 @@ fn mkdir(path: &Path, mode: u16, verbose: bool) -> i32 {
|
||||||
show_info!("created directory '{}'", path.display());
|
show_info!("created directory '{}'", path.display());
|
||||||
}
|
}
|
||||||
|
|
||||||
let directory = CString::new(path.as_os_str().to_str().unwrap()).unwrap_or_else(|e| crash!(1, "{}", e));
|
#[cfg(unix)]
|
||||||
let mode = mode as libc::mode_t;
|
fn chmod(path: &Path, mode: u16) -> i32 {
|
||||||
|
let directory = CString::new(path.as_os_str().to_str().unwrap()).unwrap_or_else(|e| crash!(1, "{}", e));
|
||||||
|
let mode = mode as libc::mode_t;
|
||||||
|
|
||||||
if unsafe { libc::chmod(directory.as_ptr(), mode) } != 0 {
|
if unsafe { libc::chmod(directory.as_ptr(), mode) } != 0 {
|
||||||
show_info!("{}: errno {}", path.display(), Error::last_os_error().raw_os_error().unwrap());
|
show_info!("{}: errno {}", path.display(), Error::last_os_error().raw_os_error().unwrap());
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
0
|
||||||
}
|
}
|
||||||
|
#[cfg(windows)]
|
||||||
0
|
fn chmod(path: &Path, mode: u16) -> i32 {
|
||||||
|
// chmod on Windows only sets the readonly flag, which isn't even honored on directories
|
||||||
|
0
|
||||||
|
}
|
||||||
|
chmod(path, mode)
|
||||||
}
|
}
|
||||||
|
|
1
src/sync/deps.mk
Normal file
1
src/sync/deps.mk
Normal file
|
@ -0,0 +1 @@
|
||||||
|
DEPLIBS += winapi kernel32
|
119
src/sync/sync.rs
119
src/sync/sync.rs
|
@ -35,103 +35,62 @@ mod platform {
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
mod platform {
|
mod platform {
|
||||||
pub use super::libc;
|
extern crate winapi;
|
||||||
use std::{mem, string};
|
extern crate kernel32;
|
||||||
use std::ptr::null;
|
#[path = "../../common/wide.rs"] mod wide;
|
||||||
|
use std::{mem};
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
use std::io::{Write};
|
||||||
|
use std::os::windows::prelude::*;
|
||||||
|
use self::wide::{FromWide, ToWide};
|
||||||
|
|
||||||
extern "system" {
|
|
||||||
fn CreateFileA(lpFileName: *const libc::c_char,
|
|
||||||
dwDesiredAccess: libc::uint32_t,
|
|
||||||
dwShareMode: libc::uint32_t,
|
|
||||||
lpSecurityAttributes: *const libc::c_void, // *LPSECURITY_ATTRIBUTES
|
|
||||||
dwCreationDisposition: libc::uint32_t,
|
|
||||||
dwFlagsAndAttributes: libc::uint32_t,
|
|
||||||
hTemplateFile: *const libc::c_void) -> *const libc::c_void;
|
|
||||||
fn GetDriveTypeA(lpRootPathName: *const libc::c_char) -> libc::c_uint;
|
|
||||||
fn GetLastError() -> libc::uint32_t;
|
|
||||||
fn FindFirstVolumeA(lpszVolumeName: *mut libc::c_char,
|
|
||||||
cchBufferLength: libc::uint32_t) -> *const libc::c_void;
|
|
||||||
fn FindNextVolumeA(hFindVolume: *const libc::c_void,
|
|
||||||
lpszVolumeName: *mut libc::c_char,
|
|
||||||
cchBufferLength: libc::uint32_t) -> libc::c_int;
|
|
||||||
fn FindVolumeClose(hFindVolume: *const libc::c_void) -> libc::c_int;
|
|
||||||
fn FlushFileBuffers(hFile: *const libc::c_void) -> libc::c_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_unsafe)]
|
|
||||||
unsafe fn flush_volume(name: &str) {
|
unsafe fn flush_volume(name: &str) {
|
||||||
let name_buffer = name.to_c_str().as_ptr();
|
let name_wide = name.to_wide_null();
|
||||||
if 0x00000003 == GetDriveTypeA(name_buffer) { // DRIVE_FIXED
|
if kernel32::GetDriveTypeW(name_wide.as_ptr()) == winapi::DRIVE_FIXED {
|
||||||
let sliced_name = &name[..name.len() - 1]; // eliminate trailing backslash
|
let sliced_name = &name[..name.len() - 1]; // eliminate trailing backslash
|
||||||
let sliced_name_buffer = sliced_name.to_c_str().as_ptr();
|
match OpenOptions::new().write(true).open(sliced_name) {
|
||||||
match CreateFileA(sliced_name_buffer,
|
Ok(file) => if kernel32::FlushFileBuffers(file.as_raw_handle()) == 0 {
|
||||||
0xC0000000, // GENERIC_WRITE
|
crash!(kernel32::GetLastError() as i32, "failed to flush file buffer");
|
||||||
0x00000003, // FILE_SHARE_WRITE,
|
},
|
||||||
null(),
|
Err(e) => crash!(e.raw_os_error().unwrap_or(1), "failed to create volume handle")
|
||||||
0x00000003, // OPEN_EXISTING
|
|
||||||
0,
|
|
||||||
null()) {
|
|
||||||
-1 => { // INVALID_HANDLE_VALUE
|
|
||||||
crash!(GetLastError(), "failed to create volume handle");
|
|
||||||
}
|
|
||||||
handle => {
|
|
||||||
if FlushFileBuffers(handle) == 0 {
|
|
||||||
crash!(GetLastError(), "failed to flush file buffer");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_unsafe)]
|
unsafe fn find_first_volume() -> (String, winapi::HANDLE) {
|
||||||
unsafe fn find_first_volume() -> (String, *const libc::c_void) {
|
let mut name: [winapi::WCHAR; winapi::MAX_PATH] = mem::uninitialized();
|
||||||
let mut name: [libc::c_char; 260] = mem::uninitialized(); // MAX_PATH
|
let handle = kernel32::FindFirstVolumeW(name.as_mut_ptr(), name.len() as winapi::DWORD);
|
||||||
match FindFirstVolumeA(name.as_mut_ptr(),
|
if handle == winapi::INVALID_HANDLE_VALUE {
|
||||||
name.len() as libc::uint32_t) {
|
crash!(kernel32::GetLastError() as i32, "failed to find first volume");
|
||||||
-1 => { // INVALID_HANDLE_VALUE
|
|
||||||
crash!(GetLastError(), "failed to find first volume");
|
|
||||||
}
|
|
||||||
handle => {
|
|
||||||
(string::raw::from_buf(name.as_ptr() as *const u8), handle)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
(String::from_wide_null(&name), handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_unsafe)]
|
|
||||||
unsafe fn find_all_volumes() -> Vec<String> {
|
unsafe fn find_all_volumes() -> Vec<String> {
|
||||||
match find_first_volume() {
|
let (first_volume, next_volume_handle) = find_first_volume();
|
||||||
(first_volume, next_volume_handle) => {
|
let mut volumes = vec![first_volume];
|
||||||
let mut volumes = vec![first_volume];
|
loop {
|
||||||
loop {
|
let mut name: [winapi::WCHAR; winapi::MAX_PATH] = mem::uninitialized();
|
||||||
let mut name: [libc::c_char; 260] = mem::uninitialized(); // MAX_PATH
|
if kernel32::FindNextVolumeW(
|
||||||
match FindNextVolumeA(next_volume_handle,
|
next_volume_handle, name.as_mut_ptr(), name.len() as winapi::DWORD
|
||||||
name.as_mut_ptr(),
|
) == 0 {
|
||||||
name.len() as libc::uint32_t) {
|
match kernel32::GetLastError() {
|
||||||
0 => {
|
winapi::ERROR_NO_MORE_FILES => {
|
||||||
match GetLastError() {
|
kernel32::FindVolumeClose(next_volume_handle);
|
||||||
0x12 => { // ERROR_NO_MORE_FILES
|
return volumes
|
||||||
FindVolumeClose(next_volume_handle); // ignore FindVolumeClose() failures
|
},
|
||||||
break;
|
err => crash!(err as i32, "failed to find next volume"),
|
||||||
}
|
|
||||||
err => {
|
|
||||||
crash!(err, "failed to find next volume");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
volumes.push(string::raw::from_buf(name.as_ptr() as *const u8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
volumes
|
} else {
|
||||||
|
volumes.push(String::from_wide_null(&name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn do_sync() -> int {
|
pub unsafe fn do_sync() -> isize {
|
||||||
let volumes = find_all_volumes();
|
let volumes = find_all_volumes();
|
||||||
for vol in volumes.iter() {
|
for vol in &volumes {
|
||||||
flush_volume(&vol);
|
flush_volume(vol);
|
||||||
}
|
}
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,10 @@ use std::str::{from_utf8};
|
||||||
static NAME: &'static str = "test";
|
static NAME: &'static str = "test";
|
||||||
|
|
||||||
// TODO: decide how to handle non-UTF8 input for all the utils
|
// TODO: decide how to handle non-UTF8 input for all the utils
|
||||||
|
// Definitely don't use [u8], try keeping it as OsStr or OsString instead
|
||||||
pub fn uumain(_: Vec<String>) -> i32 {
|
pub fn uumain(_: Vec<String>) -> i32 {
|
||||||
let args = args_os().collect::<Vec<OsString>>();
|
let args = args_os().collect::<Vec<OsString>>();
|
||||||
|
// This is completely disregarding valid windows paths that aren't valid unicode
|
||||||
let args = args.iter().map(|a| a.to_bytes().unwrap()).collect::<Vec<&[u8]>>();
|
let args = args.iter().map(|a| a.to_bytes().unwrap()).collect::<Vec<&[u8]>>();
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
return 2;
|
return 2;
|
||||||
|
@ -382,32 +384,26 @@ fn path(path: &[u8], cond: PathCondition) -> bool {
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn path(path: &[u8], cond: PathCondition) -> bool {
|
fn path(path: &[u8], cond: PathCondition) -> bool {
|
||||||
use std::old_io::{TypeFile, TypeDirectory, TypeBlockSpecial, TypeNamedPipe};
|
use std::fs::metadata;
|
||||||
use std::old_io::fs::{stat};
|
let path = from_utf8(path).unwrap();
|
||||||
use std::old_path::{Path};
|
let stat = match metadata(path) {
|
||||||
|
|
||||||
let path = match Path::new_opt(path) {
|
|
||||||
Some(p) => p,
|
|
||||||
None => return false,
|
|
||||||
};
|
|
||||||
let stat = match stat(&path) {
|
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
_ => return false,
|
_ => return false,
|
||||||
};
|
};
|
||||||
match cond {
|
match cond {
|
||||||
BlockSpecial => stat.kind == TypeBlockSpecial,
|
PathCondition::BlockSpecial => false,
|
||||||
CharacterSpecial => false,
|
PathCondition::CharacterSpecial => false,
|
||||||
Directory => stat.kind == TypeDirectory,
|
PathCondition::Directory => stat.is_dir(),
|
||||||
Exists => true,
|
PathCondition::Exists => true,
|
||||||
Regular => stat.kind == TypeFile,
|
PathCondition::Regular => stat.is_file(),
|
||||||
GroupIDFlag => false,
|
PathCondition::GroupIDFlag => false,
|
||||||
SymLink => false,
|
PathCondition::SymLink => false,
|
||||||
FIFO => stat.kind == TypeNamedPipe,
|
PathCondition::FIFO => false,
|
||||||
Readable => false, // TODO
|
PathCondition::Readable => false, // TODO
|
||||||
Socket => false, // TODO?
|
PathCondition::Socket => false,
|
||||||
NonEmpty => stat.size > 0,
|
PathCondition::NonEmpty => stat.len() > 0,
|
||||||
UserIDFlag => false,
|
PathCondition::UserIDFlag => false,
|
||||||
Writable => false, // TODO
|
PathCondition::Writable => false, // TODO
|
||||||
Executable => false, // TODO
|
PathCondition::Executable => false, // TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
src/whoami/deps.mk
Normal file
1
src/whoami/deps.mk
Normal file
|
@ -0,0 +1 @@
|
||||||
|
DEPLIBS += winapi advapi32 kernel32
|
|
@ -7,21 +7,22 @@
|
||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use ::libc;
|
extern crate winapi;
|
||||||
|
extern crate advapi32;
|
||||||
|
|
||||||
|
#[path = "../../common/wide.rs"] #[macro_use] mod wide;
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
use std::os::windows::ffi::OsStringExt;
|
||||||
|
use self::wide::FromWide;
|
||||||
|
|
||||||
extern "system" {
|
|
||||||
pub fn GetUserNameA(out: *mut libc::c_char, len: *mut libc::uint32_t) -> libc::uint8_t;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_unsafe)]
|
|
||||||
pub unsafe fn getusername() -> String {
|
pub unsafe fn getusername() -> String {
|
||||||
// usernames can only be up to 104 characters in windows
|
let mut buffer: [winapi::WCHAR; winapi::UNLEN as usize + 1] = mem::uninitialized();
|
||||||
let mut buffer: [libc::c_char; 105] = mem::uninitialized();
|
let mut len = buffer.len() as winapi::DWORD;
|
||||||
|
if advapi32::GetUserNameW(buffer.as_mut_ptr(), &mut len) == 0 {
|
||||||
if !GetUserNameA(buffer.as_mut_ptr(), &mut (buffer.len() as libc::uint32_t)) == 0 {
|
crash!(1, "failed to get username");
|
||||||
crash!(1, "username is too long");
|
|
||||||
}
|
}
|
||||||
String::from_utf8_lossy(::std::ffi::CStr::from_ptr(buffer.as_ptr()).to_bytes()).to_string()
|
String::from_wide(&buffer[..len as usize - 1])
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue