fix(natives): repaired win32 build and bazel feature drift
- Synced pi-builtins bazel crate_features with cargo's resolved default set: bazel features are literal, so the meta-features never expanded and the procs/rg cluster (nohup, pgrep, pidwait, pkill, proc-match, ps, rg, sleep, timeout, top) was silently compiled out, leaving the process builtins unregistered under bazel and failing pi-shell tests. - Repaired windows compilation of pi-builtins: cfg-gated the uucore::mode import in mkdir, imported std::env in sort's non-unix locale probe, mapped ProcInfo::pid through a closure in kill, brought MetadataExt into scope in wc, and replaced stat's unstable windows_by_handle metadata with a stable GetFileInformationByHandle query (volume serial, link count, file index, no-dereference aware). - Imported HashSet for pi-shell's windows-only PATH merge. - Added a clippy-ported bazel config + CI bucket so pi-builtins keeps its manifest-declared clippy allows under the bazel aspect while rustc warnings stay denied, and zeroed the remaining windows-target rustc warnings (unused params/imports in find, mv, rm, proc_match, ps).
This commit is contained in:
@@ -95,12 +95,19 @@ rust_library(
|
||||
"util.mkdir",
|
||||
"util.mktemp",
|
||||
"util.mv",
|
||||
"util.nohup",
|
||||
"util.nproc",
|
||||
"util.paste",
|
||||
"util.pgrep",
|
||||
"util.pidwait",
|
||||
"util.pkill",
|
||||
"util.printenv",
|
||||
"util.proc-match",
|
||||
"util.procs",
|
||||
"util.ps",
|
||||
"util.readlink",
|
||||
"util.realpath",
|
||||
"util.rg",
|
||||
"util.rm",
|
||||
"util.sed",
|
||||
"util.seq",
|
||||
@@ -109,12 +116,15 @@ rust_library(
|
||||
"util.sha256sum",
|
||||
"util.sha384sum",
|
||||
"util.sha512sum",
|
||||
"util.sleep",
|
||||
"util.sort",
|
||||
"util.sponge",
|
||||
"util.stat",
|
||||
"util.tac",
|
||||
"util.tail",
|
||||
"util.tee",
|
||||
"util.timeout",
|
||||
"util.top",
|
||||
"util.touch",
|
||||
"util.tr",
|
||||
"util.truncate",
|
||||
|
||||
@@ -776,7 +776,7 @@ pub mod matchers {
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn matches(&self, _file_info: &WalkEntry, matcher_io: &mut MatcherIO) -> bool {
|
||||
fn matches(&self, _file_info: &WalkEntry, _matcher_io: &mut MatcherIO) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ impl builtins::Command for KillCommand {
|
||||
ProcInfo::all()
|
||||
.into_iter()
|
||||
.filter(|process| process.status() == ProcessStatus::Running)
|
||||
.map(ProcInfo::pid)
|
||||
.map(|process| process.pid())
|
||||
.collect()
|
||||
};
|
||||
#[cfg(unix)]
|
||||
|
||||
@@ -11,7 +11,9 @@ use std::{
|
||||
|
||||
use brush_core::{ShellExtensions, builtins::Registration};
|
||||
use clap::{Arg, ArgAction, ArgMatches, Command, builder::ValueParser, parser::ValuesRef};
|
||||
use uucore::{display::Quotable, fs, mode};
|
||||
use uucore::{display::Quotable, fs};
|
||||
#[cfg(not(windows))]
|
||||
use uucore::mode;
|
||||
#[cfg(all(unix, target_os = "linux"))]
|
||||
use uucore::fsxattr;
|
||||
|
||||
|
||||
@@ -1097,7 +1097,7 @@ fn rename_fifo_fallback(host: &mut Host, from: &Path, to: &Path) -> io::Result<(
|
||||
|
||||
#[cfg(not(unix))]
|
||||
#[expect(clippy::unnecessary_wraps, reason = "fn sig must match on all platforms")]
|
||||
fn rename_fifo_fallback(host: &mut Host, _from: &Path, _to: &Path) -> io::Result<()> {
|
||||
fn rename_fifo_fallback(_host: &mut Host, _from: &Path, _to: &Path) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use brush_core::{
|
||||
ExecutionContext, ExecutionExitCode, ExecutionResult, openfiles::OpenFiles,
|
||||
};
|
||||
use brush_core::{ExecutionContext, ExecutionExitCode, ExecutionResult};
|
||||
#[cfg(unix)]
|
||||
use brush_core::openfiles::OpenFiles;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::{kill::signal_number, proc_snapshot};
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
//! The `ps` process-status builtin, moved from `pi-shell`.
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::collections::HashSet;
|
||||
#[cfg(unix)]
|
||||
use std::fs;
|
||||
#[cfg(unix)]
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
collections::HashMap,
|
||||
fmt::Write as _,
|
||||
fs,
|
||||
io::{self, Write},
|
||||
path::{Path, PathBuf},
|
||||
time::{Duration, SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
|
||||
@@ -1126,7 +1126,7 @@ fn is_readable_metadata(metadata: &Metadata) -> bool {
|
||||
|
||||
/// Whether the given file or directory is readable.
|
||||
#[cfg(any(not(unix), target_os = "redox"))]
|
||||
fn is_readable(host: &mut Host, _path: &Path) -> bool {
|
||||
fn is_readable(_host: &mut Host, _path: &Path) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
@@ -4164,6 +4164,7 @@ fn default_merge_batch_size() -> usize {
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn locale_failed_to_set() -> bool {
|
||||
use std::env;
|
||||
env::var_os("LC_ALL").as_deref() == Some(OsStr::new("missing"))
|
||||
}
|
||||
|
||||
|
||||
@@ -48,8 +48,6 @@ pub(crate) fn stat_builtin<SE: ShellExtensions>() -> Registration<SE> {
|
||||
mod imp {
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::{FileTypeExt, MetadataExt};
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::fs::MetadataExt;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
cell::OnceCell,
|
||||
@@ -1951,10 +1949,9 @@ for details about the options it supports.";
|
||||
}
|
||||
}
|
||||
/// file-status path is Unix-only (`std::os::unix`); this reimplements the
|
||||
/// GNU directives on top of `std::fs::Metadata`, the `windows_by_handle`
|
||||
/// metadata extensions (inode / link count / device via
|
||||
/// `GetFileInformationByHandle`), and the Win32 volume APIs for
|
||||
/// `--file-system` mode.
|
||||
/// GNU directives on top of `std::fs::Metadata`, direct
|
||||
/// `GetFileInformationByHandle` queries (inode / link count / device),
|
||||
/// and the Win32 volume APIs for `--file-system` mode.
|
||||
#[cfg(windows)]
|
||||
mod win {
|
||||
use std::{
|
||||
@@ -2066,6 +2063,52 @@ for details about the options it supports.";
|
||||
(u64::from(high) << 32) | u64::from(low)
|
||||
}
|
||||
|
||||
/// Per-file identity numbers for `%d`/`%D`/`%h`/`%i`: volume serial,
|
||||
/// hard-link count, and NTFS file index.
|
||||
pub struct HandleInfo {
|
||||
pub volume_serial: u64,
|
||||
pub links: u64,
|
||||
pub file_index: u64,
|
||||
}
|
||||
|
||||
/// Query [`HandleInfo`] via `GetFileInformationByHandle`, the stable
|
||||
/// replacement for std's unstable `windows_by_handle` metadata
|
||||
/// extensions. `follow_links` mirrors how the caller's metadata was
|
||||
/// obtained, so a `--no-dereference` stat reports the link itself.
|
||||
/// Returns `None` when the file cannot be opened or queried.
|
||||
pub fn handle_info(path: &Path, follow_links: bool) -> Option<HandleInfo> {
|
||||
use std::os::windows::{fs::OpenOptionsExt, io::AsRawHandle};
|
||||
|
||||
use windows_sys::Win32::Storage::FileSystem::{
|
||||
BY_HANDLE_FILE_INFORMATION, FILE_FLAG_BACKUP_SEMANTICS,
|
||||
FILE_FLAG_OPEN_REPARSE_POINT, GetFileInformationByHandle,
|
||||
};
|
||||
|
||||
// `FILE_FLAG_BACKUP_SEMANTICS` is required to open directories;
|
||||
// `access_mode(0)` asks for metadata access only.
|
||||
let mut flags = FILE_FLAG_BACKUP_SEMANTICS;
|
||||
if !follow_links {
|
||||
flags |= FILE_FLAG_OPEN_REPARSE_POINT;
|
||||
}
|
||||
let file = std::fs::OpenOptions::new()
|
||||
.access_mode(0)
|
||||
.custom_flags(flags)
|
||||
.open(path)
|
||||
.ok()?;
|
||||
// SAFETY: zeroed BY_HANDLE_FILE_INFORMATION is a valid out
|
||||
// buffer, and the handle stays open across the call.
|
||||
let mut info: BY_HANDLE_FILE_INFORMATION = unsafe { std::mem::zeroed() };
|
||||
if unsafe { GetFileInformationByHandle(file.as_raw_handle(), &mut info) } == 0 {
|
||||
return None;
|
||||
}
|
||||
Some(HandleInfo {
|
||||
volume_serial: u64::from(info.dwVolumeSerialNumber),
|
||||
links: u64::from(info.nNumberOfLinks),
|
||||
file_index: (u64::from(info.nFileIndexHigh) << 32)
|
||||
| u64::from(info.nFileIndexLow),
|
||||
})
|
||||
}
|
||||
|
||||
/// File-system status collected for `stat --file-system` on Windows.
|
||||
pub struct StatFs {
|
||||
pub fs_type: String,
|
||||
@@ -2249,6 +2292,11 @@ for details about the options it supports.";
|
||||
},
|
||||
Token::Directive { flag, width, precision, format } => {
|
||||
let mode = win::synth_mode(meta);
|
||||
// `%d`/`%D`/`%h`/`%i` need a fresh handle query; skip it for
|
||||
// every other directive.
|
||||
let ids = matches!(format, 'd' | 'D' | 'h' | 'i')
|
||||
.then(|| win::handle_info(resolved, !meta.file_type().is_symlink()))
|
||||
.flatten();
|
||||
let output = match format {
|
||||
// access rights in octal
|
||||
'a' => OutputType::UnsignedOct(0o7777 & mode),
|
||||
@@ -2264,9 +2312,11 @@ for details about the options it supports.";
|
||||
'C' => OutputType::Str("unsupported for this operating system".to_string()),
|
||||
// device number: Windows volume serial number
|
||||
'd' if flag.major || flag.minor => OutputType::Unsigned(0),
|
||||
'd' => OutputType::Unsigned(meta.volume_serial_number().map_or(0, u64::from)),
|
||||
'd' => OutputType::Unsigned(ids.as_ref().map_or(0, |ids| ids.volume_serial)),
|
||||
// device number in hex
|
||||
'D' => OutputType::UnsignedHex(meta.volume_serial_number().map_or(0, u64::from)),
|
||||
'D' => {
|
||||
OutputType::UnsignedHex(ids.as_ref().map_or(0, |ids| ids.volume_serial))
|
||||
},
|
||||
// raw mode in hex
|
||||
'f' => OutputType::UnsignedHex(u64::from(mode)),
|
||||
// file type
|
||||
@@ -2276,9 +2326,9 @@ for details about the options it supports.";
|
||||
// group name of owner
|
||||
'G' => OutputType::Str("UNKNOWN".to_string()),
|
||||
// number of hard links
|
||||
'h' => OutputType::Unsigned(meta.number_of_links().map_or(1, u64::from)),
|
||||
'h' => OutputType::Unsigned(ids.as_ref().map_or(1, |ids| ids.links)),
|
||||
// inode number (NTFS file index)
|
||||
'i' => OutputType::Unsigned(meta.file_index().unwrap_or(0)),
|
||||
'i' => OutputType::Unsigned(ids.as_ref().map_or(0, |ids| ids.file_index)),
|
||||
// mount point (not resolved on Windows)
|
||||
'm' => OutputType::Str(String::new()),
|
||||
// file name
|
||||
|
||||
@@ -14,6 +14,8 @@ mod count_fast {
|
||||
use super::WordCountable;
|
||||
use super::{wc_simd_allowed, word_count::WordCount};
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::fs::MetadataExt;
|
||||
#[cfg(windows)]
|
||||
const FILE_ATTRIBUTE_ARCHIVE: u32 = 32;
|
||||
#[cfg(windows)]
|
||||
const FILE_ATTRIBUTE_NORMAL: u32 = 128;
|
||||
|
||||
Reference in New Issue
Block a user