1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-27 11:07:44 +00:00

Test on FreeBSD using Cirrus CI and link to the Discord in the README

This commit is contained in:
Alex Lyon 2019-04-27 19:14:22 -07:00
parent 52785d6a4b
commit 220e07dc95
13 changed files with 808 additions and 771 deletions

19
.cirrus.yml Normal file
View file

@ -0,0 +1,19 @@
freebsd_instance:
image: freebsd-12-0-release-amd64
task:
name: stable x86_64-unknown-freebsd
setup_script:
- pkg install -y curl gmake py36-sphinx
- curl https://sh.rustup.rs -sSf --output rustup.sh
- sh rustup.sh -y
build_script:
- . $HOME/.cargo/env
- cargo build
test_script:
- . $HOME/.cargo/env
- cargo test
- |
mkdir installdir_test
make install DESTDIR=installdir_test SPHINXBUILD='sphinx-build-3.6'
[ `ls installdir_test/usr/local/bin | wc -l` -gt 0 ]

729
Cargo.lock generated

File diff suppressed because it is too large Load diff

324
GNUmakefile Normal file
View file

@ -0,0 +1,324 @@
# Config options
PROFILE ?= debug
MULTICALL ?= n
INSTALL ?= install
ifneq (,$(filter install, $(MAKECMDGOALS)))
override PROFILE:=release
endif
PROFILE_CMD :=
ifeq ($(PROFILE),release)
PROFILE_CMD = --release
endif
RM := rm -rf
# Binaries
CARGO ?= cargo
CARGOFLAGS ?=
# Install directories
PREFIX ?= /usr/local
DESTDIR ?=
BINDIR ?= /bin
MANDIR ?= /man/man1
INSTALLDIR_BIN=$(DESTDIR)$(PREFIX)$(BINDIR)
INSTALLDIR_MAN=$(DESTDIR)$(PREFIX)/share/$(MANDIR)
$(shell test -d $(INSTALLDIR_MAN))
ifneq ($(.SHELLSTATUS),0)
override INSTALLDIR_MAN=$(DESTDIR)$(PREFIX)$(MANDIR)
endif
#prefix to apply to uutils binary and all tool binaries
PROG_PREFIX ?=
# This won't support any directory with spaces in its name, but you can just
# make a symlink without spaces that points to the directory.
BASEDIR ?= $(shell pwd)
BUILDDIR := $(BASEDIR)/target/${PROFILE}
PKG_BUILDDIR := $(BUILDDIR)/deps
DOCSDIR := $(BASEDIR)/docs
BUSYBOX_ROOT := $(BASEDIR)/tmp
BUSYBOX_VER := 1.24.1
BUSYBOX_SRC := $(BUSYBOX_ROOT)/busybox-$(BUSYBOX_VER)
# Possible programs
PROGS := \
base32 \
base64 \
basename \
cat \
cksum \
comm \
cp \
cut \
dircolors \
dirname \
echo \
env \
expand \
expr \
factor \
false \
fmt \
fold \
hashsum \
head \
join \
link \
ln \
ls \
mkdir \
mktemp \
more \
mv \
nl \
numfmt \
nproc \
od \
paste \
printenv \
printf \
ptx \
pwd \
readlink \
realpath \
relpath \
rm \
rmdir \
seq \
shred \
shuf \
sleep \
sort \
split \
sum \
sync \
tac \
tail \
tee \
test \
tr \
true \
truncate \
tsort \
unexpand \
uniq \
wc \
whoami \
yes
UNIX_PROGS := \
arch \
chgrp \
chmod \
chown \
chroot \
du \
groups \
hostid \
hostname \
id \
install \
kill \
logname \
mkfifo \
mknod \
nice \
nohup \
pathchk \
pinky \
stat \
stdbuf \
timeout \
touch \
tty \
uname \
unlink \
uptime \
users \
who
ifneq ($(OS),Windows_NT)
PROGS := $(PROGS) $(UNIX_PROGS)
endif
UTILS ?= $(PROGS)
# Programs with usable tests
TEST_PROGS := \
base32 \
base64 \
basename \
cat \
chgrp \
chmod \
chown \
cksum \
comm \
cp \
cut \
dircolors \
dirname \
echo \
env \
expr \
factor \
false \
fold \
hashsum \
head \
install \
link \
ln \
ls \
mkdir \
mktemp \
mv \
nl \
numfmt \
od \
paste \
pathchk \
pinky \
printf \
ptx \
pwd \
readlink \
realpath \
rm \
rmdir \
seq \
sort \
split \
stat \
stdbuf \
sum \
tac \
tail \
test \
touch \
tr \
true \
truncate \
tsort \
unexpand \
uniq \
unlink \
wc \
who
TESTS := \
$(sort $(filter $(UTILS),$(filter-out $(SKIP_UTILS),$(TEST_PROGS))))
TEST_NO_FAIL_FAST :=
TEST_SPEC_FEATURE :=
ifneq ($(SPEC),)
TEST_NO_FAIL_FAST :=--no-fail-fast
TEST_SPEC_FEATURE := test_unimplemented
endif
define TEST_BUSYBOX
test_busybox_$(1):
(cd $(BUSYBOX_SRC)/testsuite && bindir=$(BUILDDIR) ./runtest $(RUNTEST_ARGS) $(1) )
endef
# Output names
EXES := \
$(sort $(filter $(UTILS),$(filter-out $(SKIP_UTILS),$(PROGS))))
INSTALLEES := ${EXES}
ifeq (${MULTICALL}, y)
INSTALLEES := ${INSTALLEES} uutils
endif
# Shared library extension
SYSTEM := $(shell uname)
DYLIB_EXT :=
ifeq ($(SYSTEM),Linux)
DYLIB_EXT := so
DYLIB_FLAGS := -shared
endif
ifeq ($(SYSTEM),Darwin)
DYLIB_EXT := dylib
DYLIB_FLAGS := -dynamiclib -undefined dynamic_lookup
endif
all: build
do_install = $(INSTALL) ${1}
use_default := 1
build-pkgs:
ifneq (${MULTICALL}, y)
${CARGO} build ${CARGOFLAGS} ${PROFILE_CMD} $(foreach pkg,$(EXES),-p $(pkg))
endif
build-uutils:
${CARGO} build ${CARGOFLAGS} --features "${EXES}" ${PROFILE_CMD} --no-default-features
build-manpages:
cd $(DOCSDIR) && make man
build: build-uutils build-pkgs build-manpages
$(foreach test,$(filter-out $(SKIP_UTILS),$(PROGS)),$(eval $(call TEST_BUSYBOX,$(test))))
test:
${CARGO} test ${CARGOFLAGS} --features "$(TESTS) $(TEST_SPEC_FEATURE)" --no-default-features $(TEST_NO_FAIL_FAST)
busybox-src:
if [ ! -e $(BUSYBOX_SRC) ]; then \
mkdir -p $(BUSYBOX_ROOT); \
wget https://busybox.net/downloads/busybox-$(BUSYBOX_VER).tar.bz2 -P $(BUSYBOX_ROOT); \
tar -C $(BUSYBOX_ROOT) -xf $(BUSYBOX_ROOT)/busybox-$(BUSYBOX_VER).tar.bz2; \
fi; \
# This is a busybox-specific config file their test suite wants to parse.
$(BUILDDIR)/.config: $(BASEDIR)/.busybox-config
cp $< $@
# Test under the busybox testsuite
$(BUILDDIR)/busybox: busybox-src build-uutils $(BUILDDIR)/.config
cp $(BUILDDIR)/uutils $(BUILDDIR)/busybox; \
chmod +x $@;
ifeq ($(EXES),)
busytest:
else
busytest: $(BUILDDIR)/busybox $(addprefix test_busybox_,$(filter-out $(SKIP_UTILS),$(EXES)))
endif
clean:
$(RM) $(BUILDDIR)
cd $(DOCSDIR) && make clean
distclean: clean
$(CARGO) clean $(CARGOFLAGS) && $(CARGO) update $(CARGOFLAGS)
install: build
mkdir -p $(INSTALLDIR_BIN)
mkdir -p $(INSTALLDIR_MAN)
ifeq (${MULTICALL}, y)
$(INSTALL) $(BUILDDIR)/uutils $(INSTALLDIR_BIN)/$(PROG_PREFIX)uutils
cd $(INSTALLDIR_BIN) && $(foreach prog, $(filter-out uutils, $(INSTALLEES)), \
ln -fs $(PROG_PREFIX)uutils $(PROG_PREFIX)$(prog) &&) :
cat $(DOCSDIR)/_build/man/uutils.1 | gzip > $(INSTALLDIR_MAN)/$(PROG_PREFIX)uutils.1.gz
else
$(foreach prog, $(INSTALLEES), \
$(INSTALL) $(BUILDDIR)/$(prog) $(INSTALLDIR_BIN)/$(PROG_PREFIX)$(prog);)
endif
$(foreach man, $(filter $(INSTALLEES), $(basename $(notdir $(wildcard $(DOCSDIR)/_build/man/*)))), \
cat $(DOCSDIR)/_build/man/$(man).1 | gzip > $(INSTALLDIR_MAN)/$(PROG_PREFIX)$(man).1.gz &&) :
uninstall:
ifeq (${MULTICALL}, y)
rm -f $(addprefix $(INSTALLDIR_BIN)/,$(PROG_PREFIX)uutils)
endif
rm -f $(addprefix $(INSTALLDIR_MAN)/,$(PROG_PREFIX)uutils.1.gz)
rm -f $(addprefix $(INSTALLDIR_BIN)/$(PROG_PREFIX),$(PROGS))
rm -f $(addprefix $(INSTALLDIR_MAN)/$(PROG_PREFIX),$(addsuffix .1.gz,$(PROGS)))
.PHONY: all build build-uutils build-pkgs build-docs test distclean clean busytest install uninstall

329
Makefile
View file

@ -1,324 +1,5 @@
# Config options USEGNU=gmake $*
PROFILE ?= debug all:
MULTICALL ?= n @$(USEGNU)
INSTALL ?= install .DEFAULT:
ifneq (,$(filter install, $(MAKECMDGOALS))) @$(USEGNU)
override PROFILE:=release
endif
PROFILE_CMD :=
ifeq ($(PROFILE),release)
PROFILE_CMD = --release
endif
RM := rm -rf
# Binaries
CARGO ?= cargo
CARGOFLAGS ?=
# Install directories
PREFIX ?= /usr/local
DESTDIR ?=
BINDIR ?= /bin
MANDIR ?= /man/man1
INSTALLDIR_BIN=$(DESTDIR)$(PREFIX)$(BINDIR)
INSTALLDIR_MAN=$(DESTDIR)$(PREFIX)/share/$(MANDIR)
$(shell test -d $(INSTALLDIR_MAN))
ifneq ($(.SHELLSTATUS),0)
override INSTALLDIR_MAN=$(DESTDIR)$(PREFIX)$(MANDIR)
endif
#prefix to apply to uutils binary and all tool binaries
PROG_PREFIX ?=
# This won't support any directory with spaces in its name, but you can just
# make a symlink without spaces that points to the directory.
BASEDIR ?= $(shell pwd)
BUILDDIR := $(BASEDIR)/target/${PROFILE}
PKG_BUILDDIR := $(BUILDDIR)/deps
DOCSDIR := $(BASEDIR)/docs
BUSYBOX_ROOT := $(BASEDIR)/tmp
BUSYBOX_VER := 1.24.1
BUSYBOX_SRC := $(BUSYBOX_ROOT)/busybox-$(BUSYBOX_VER)
# Possible programs
PROGS := \
base32 \
base64 \
basename \
cat \
cksum \
comm \
cp \
cut \
dircolors \
dirname \
echo \
env \
expand \
expr \
factor \
false \
fmt \
fold \
hashsum \
head \
join \
link \
ln \
ls \
mkdir \
mktemp \
more \
mv \
nl \
numfmt \
nproc \
od \
paste \
printenv \
printf \
ptx \
pwd \
readlink \
realpath \
relpath \
rm \
rmdir \
seq \
shred \
shuf \
sleep \
sort \
split \
sum \
sync \
tac \
tail \
tee \
test \
tr \
true \
truncate \
tsort \
unexpand \
uniq \
wc \
whoami \
yes
UNIX_PROGS := \
arch \
chgrp \
chmod \
chown \
chroot \
du \
groups \
hostid \
hostname \
id \
install \
kill \
logname \
mkfifo \
mknod \
nice \
nohup \
pathchk \
pinky \
stat \
stdbuf \
timeout \
touch \
tty \
uname \
unlink \
uptime \
users \
who
ifneq ($(OS),Windows_NT)
PROGS := $(PROGS) $(UNIX_PROGS)
endif
UTILS ?= $(PROGS)
# Programs with usable tests
TEST_PROGS := \
base32 \
base64 \
basename \
cat \
chgrp \
chmod \
chown \
cksum \
comm \
cp \
cut \
dircolors \
dirname \
echo \
env \
expr \
factor \
false \
fold \
hashsum \
head \
install \
link \
ln \
ls \
mkdir \
mktemp \
mv \
nl \
numfmt \
od \
paste \
pathchk \
pinky \
printf \
ptx \
pwd \
readlink \
realpath \
rm \
rmdir \
seq \
sort \
split \
stat \
stdbuf \
sum \
tac \
tail \
test \
touch \
tr \
true \
truncate \
tsort \
unexpand \
uniq \
unlink \
wc \
who
TESTS := \
$(sort $(filter $(UTILS),$(filter-out $(SKIP_UTILS),$(TEST_PROGS))))
TEST_NO_FAIL_FAST :=
TEST_SPEC_FEATURE :=
ifneq ($(SPEC),)
TEST_NO_FAIL_FAST :=--no-fail-fast
TEST_SPEC_FEATURE := test_unimplemented
endif
define TEST_BUSYBOX
test_busybox_$(1):
(cd $(BUSYBOX_SRC)/testsuite && bindir=$(BUILDDIR) ./runtest $(RUNTEST_ARGS) $(1) )
endef
# Output names
EXES := \
$(sort $(filter $(UTILS),$(filter-out $(SKIP_UTILS),$(PROGS))))
INSTALLEES := ${EXES}
ifeq (${MULTICALL}, y)
INSTALLEES := ${INSTALLEES} uutils
endif
# Shared library extension
SYSTEM := $(shell uname)
DYLIB_EXT :=
ifeq ($(SYSTEM),Linux)
DYLIB_EXT := so
DYLIB_FLAGS := -shared
endif
ifeq ($(SYSTEM),Darwin)
DYLIB_EXT := dylib
DYLIB_FLAGS := -dynamiclib -undefined dynamic_lookup
endif
all: build
do_install = $(INSTALL) ${1}
use_default := 1
build-pkgs:
ifneq (${MULTICALL}, y)
${CARGO} build ${CARGOFLAGS} ${PROFILE_CMD} $(foreach pkg,$(EXES),-p $(pkg))
endif
build-uutils:
${CARGO} build ${CARGOFLAGS} --features "${EXES}" ${PROFILE_CMD} --no-default-features
build-manpages:
cd $(DOCSDIR) && make man
build: build-uutils build-pkgs build-manpages
$(foreach test,$(filter-out $(SKIP_UTILS),$(PROGS)),$(eval $(call TEST_BUSYBOX,$(test))))
test:
${CARGO} test ${CARGOFLAGS} --features "$(TESTS) $(TEST_SPEC_FEATURE)" --no-default-features $(TEST_NO_FAIL_FAST)
busybox-src:
if [ ! -e $(BUSYBOX_SRC) ]; then \
mkdir -p $(BUSYBOX_ROOT); \
wget https://busybox.net/downloads/busybox-$(BUSYBOX_VER).tar.bz2 -P $(BUSYBOX_ROOT); \
tar -C $(BUSYBOX_ROOT) -xf $(BUSYBOX_ROOT)/busybox-$(BUSYBOX_VER).tar.bz2; \
fi; \
# This is a busybox-specific config file their test suite wants to parse.
$(BUILDDIR)/.config: $(BASEDIR)/.busybox-config
cp $< $@
# Test under the busybox testsuite
$(BUILDDIR)/busybox: busybox-src build-uutils $(BUILDDIR)/.config
cp $(BUILDDIR)/uutils $(BUILDDIR)/busybox; \
chmod +x $@;
ifeq ($(EXES),)
busytest:
else
busytest: $(BUILDDIR)/busybox $(addprefix test_busybox_,$(filter-out $(SKIP_UTILS),$(EXES)))
endif
clean:
$(RM) $(BUILDDIR)
cd $(DOCSDIR) && make clean
distclean: clean
$(CARGO) clean $(CARGOFLAGS) && $(CARGO) update $(CARGOFLAGS)
install: build
mkdir -p $(INSTALLDIR_BIN)
mkdir -p $(INSTALLDIR_MAN)
ifeq (${MULTICALL}, y)
$(INSTALL) $(BUILDDIR)/uutils $(INSTALLDIR_BIN)/$(PROG_PREFIX)uutils
cd $(INSTALLDIR_BIN) && $(foreach prog, $(filter-out uutils, $(INSTALLEES)), \
ln -fs $(PROG_PREFIX)uutils $(PROG_PREFIX)$(prog) &&) :
cat $(DOCSDIR)/_build/man/uutils.1 | gzip > $(INSTALLDIR_MAN)/$(PROG_PREFIX)uutils.1.gz
else
$(foreach prog, $(INSTALLEES), \
$(INSTALL) $(BUILDDIR)/$(prog) $(INSTALLDIR_BIN)/$(PROG_PREFIX)$(prog);)
endif
$(foreach man, $(filter $(INSTALLEES), $(basename $(notdir $(wildcard $(DOCSDIR)/_build/man/*)))), \
cat $(DOCSDIR)/_build/man/$(man).1 | gzip > $(INSTALLDIR_MAN)/$(PROG_PREFIX)$(man).1.gz &&) :
uninstall:
ifeq (${MULTICALL}, y)
rm -f $(addprefix $(INSTALLDIR_BIN)/,$(PROG_PREFIX)uutils)
endif
rm -f $(addprefix $(INSTALLDIR_MAN)/,$(PROG_PREFIX)uutils.1.gz)
rm -f $(addprefix $(INSTALLDIR_BIN)/$(PROG_PREFIX),$(PROGS))
rm -f $(addprefix $(INSTALLDIR_MAN)/$(PROG_PREFIX),$(addsuffix .1.gz,$(PROGS)))
.PHONY: all build build-uutils build-pkgs build-docs test distclean clean busytest install uninstall

View file

@ -1,12 +1,17 @@
uutils coreutils uutils coreutils
================ ================
[![Discord](https://img.shields.io/badge/discord-join-7289DA.svg?logo=discord&longCache=true&style=flat)](https://discord.gg/wQVJbvJ)
[![License](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/uutils/coreutils/blob/master/LICENSE) [![License](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/uutils/coreutils/blob/master/LICENSE)
[![Build Status](https://api.travis-ci.org/uutils/coreutils.svg?branch=master)](https://travis-ci.org/uutils/coreutils) [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fuutils%2Fcoreutils.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fuutils%2Fcoreutils?ref=badge_shield)
[![Build status](https://ci.appveyor.com/api/projects/status/787ltcxgy86r20le?svg=true)](https://ci.appveyor.com/project/Arcterus/coreutils)
[![LOC](https://tokei.rs/b1/github/uutils/coreutils?category=code)](https://github.com/Aaronepower/tokei) [![LOC](https://tokei.rs/b1/github/uutils/coreutils?category=code)](https://github.com/Aaronepower/tokei)
[![dependency status](https://deps.rs/repo/github/uutils/coreutils/status.svg)](https://deps.rs/repo/github/uutils/coreutils) [![dependency status](https://deps.rs/repo/github/uutils/coreutils/status.svg)](https://deps.rs/repo/github/uutils/coreutils)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fuutils%2Fcoreutils.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fuutils%2Fcoreutils?ref=badge_shield)
[![Build Status](https://api.travis-ci.org/uutils/coreutils.svg?branch=master)](https://travis-ci.org/uutils/coreutils)
[![Build Status (Windows)](https://ci.appveyor.com/api/projects/status/787ltcxgy86r20le?svg=true)](https://ci.appveyor.com/project/Arcterus/coreutils)
[![Build Status (FreeBSD)](https://api.cirrus-ci.com/github/uutils/coreutils.svg)](https://cirrus-ci.com/github/uutils/coreutils/master)
-----------------------------------------------
uutils is an attempt at writing universal (as in cross-platform) CLI uutils is an attempt at writing universal (as in cross-platform) CLI
utils in [Rust](http://www.rust-lang.org). This repo is to aggregate the GNU utils in [Rust](http://www.rust-lang.org). This repo is to aggregate the GNU

20
docs/GNUmakefile Normal file
View file

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXPROJ = uutils
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help GNUmakefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: GNUmakefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

View file

@ -1,20 +1,5 @@
# Minimal makefile for Sphinx documentation USEGNU=gmake $*
# all:
@$(USEGNU)
# You can set these variables from the command line. .DEFAULT:
SPHINXOPTS = @$(USEGNU)
SPHINXBUILD = sphinx-build
SPHINXPROJ = uutils
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

View file

@ -12,7 +12,7 @@ path = "ls.rs"
getopts = "0.2.18" getopts = "0.2.18"
number_prefix = "0.2.8" number_prefix = "0.2.8"
term_grid = "0.1.5" term_grid = "0.1.5"
termsize = "0.1.4" termsize = { git = "https://github.com/Arcterus/termsize" }
time = "0.1.40" time = "0.1.40"
lazy_static = "1.0.1" lazy_static = "1.0.1"
unicode-width = "0.1.5" unicode-width = "0.1.5"

View file

@ -21,28 +21,21 @@ pub trait BirthTime {
use std::fs::Metadata; use std::fs::Metadata;
impl BirthTime for Metadata { impl BirthTime for Metadata {
#[cfg(feature = "nightly")]
fn pretty_birth(&self) -> String { fn pretty_birth(&self) -> String {
self.created() self.created()
.map(|t| t.elapsed().unwrap()) .ok()
.and_then(|t| t.elapsed().ok())
.map(|e| pretty_time(e.as_secs() as i64, e.subsec_nanos() as i64)) .map(|e| pretty_time(e.as_secs() as i64, e.subsec_nanos() as i64))
.unwrap_or("-".to_owned()) .unwrap_or("-".to_owned())
} }
#[cfg(not(feature = "nightly"))]
fn pretty_birth(&self) -> String {
"-".to_owned()
}
#[cfg(feature = "nightly")]
fn birth(&self) -> String { fn birth(&self) -> String {
self.created() self.created()
.map(|t| t.elapsed().unwrap()) .ok()
.and_then(|t| t.elapsed().ok())
.map(|e| format!("{}", e.as_secs())) .map(|e| format!("{}", e.as_secs()))
.unwrap_or("0".to_owned()) .unwrap_or("0".to_owned())
} }
#[cfg(not(feature = "nightly"))]
fn birth(&self) -> String {
"0".to_owned()
}
} }
#[macro_export] #[macro_export]
@ -94,7 +87,6 @@ pub fn pretty_access(mode: mode_t) -> String {
S_IFLNK => 'l', S_IFLNK => 'l',
S_IFSOCK => 's', S_IFSOCK => 's',
// TODO: Other file types // TODO: Other file types
// See coreutils/gnulib/lib/filemode.c
_ => '?', _ => '?',
}); });
@ -151,19 +143,19 @@ use std::convert::{AsRef, From};
use std::error::Error; use std::error::Error;
use std::io::Error as IOError; use std::io::Error as IOError;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "macos", target_os = "android", target_os = "freebsd"))]
use libc::statfs as Sstatfs; use libc::statfs as Sstatfs;
// #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "openbsd", target_os = "bitrig", target_os = "dragonfly"))] #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "openbsd", target_os = "bitrig", target_os = "dragonfly"))]
// use self::libc::statvfs as Sstatfs; use libc::statvfs as Sstatfs;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "macos", target_os = "android", target_os = "freebsd"))]
use libc::statfs as statfs_fn; use libc::statfs as statfs_fn;
// #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "openbsd", target_os = "bitrig", target_os = "dragonfly"))] #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "openbsd", target_os = "bitrig", target_os = "dragonfly"))]
// use self::libc::statvfs as statfs_fn; use libc::statvfs as statfs_fn;
pub trait FsMeta { pub trait FsMeta {
fn fs_type(&self) -> i64; fn fs_type(&self) -> i64;
fn iosize(&self) -> i64; fn iosize(&self) -> u64;
fn blksize(&self) -> i64; fn blksize(&self) -> i64;
fn total_blocks(&self) -> u64; fn total_blocks(&self) -> u64;
fn free_blocks(&self) -> u64; fn free_blocks(&self) -> u64;
@ -171,7 +163,7 @@ pub trait FsMeta {
fn total_fnodes(&self) -> u64; fn total_fnodes(&self) -> u64;
fn free_fnodes(&self) -> u64; fn free_fnodes(&self) -> u64;
fn fsid(&self) -> u64; fn fsid(&self) -> u64;
fn namelen(&self) -> i64; fn namelen(&self) -> u64;
} }
impl FsMeta for Sstatfs { impl FsMeta for Sstatfs {
@ -193,22 +185,28 @@ impl FsMeta for Sstatfs {
fn free_fnodes(&self) -> u64 { fn free_fnodes(&self) -> u64 {
self.f_ffree as u64 self.f_ffree as u64
} }
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))]
fn fs_type(&self) -> i64 { fn fs_type(&self) -> i64 {
self.f_type as i64 self.f_type as i64
} }
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "freebsd")))]
fn fs_type(&self) -> i64 {
// FIXME: statvfs doesn't have an equivalent, so we need to do something else
unimplemented!()
}
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
fn iosize(&self) -> i64 { fn iosize(&self) -> u64 {
self.f_frsize as i64 self.f_frsize as u64
} }
#[cfg(target_os = "macos")] #[cfg(any(target_os = "macos", target_os = "freebsd"))]
fn iosize(&self) -> i64 { fn iosize(&self) -> u64 {
self.f_iosize as i64 self.f_iosize as u64
} }
// FIXME: // XXX: dunno if this is right
#[cfg(not(any(target_os = "macos", target_os = "linux")))] #[cfg(not(any(target_os = "macos", target_os = "freebsd", target_os = "linux")))]
fn iosize(&self) -> i64 { fn iosize(&self) -> u64 {
0 self.f_bsize as u64
} }
// Linux, SunOS, HP-UX, 4.4BSD, FreeBSD have a system call statfs() that returns // Linux, SunOS, HP-UX, 4.4BSD, FreeBSD have a system call statfs() that returns
@ -217,29 +215,32 @@ impl FsMeta for Sstatfs {
// //
// Solaris, Irix and POSIX have a system call statvfs(2) that returns a // Solaris, Irix and POSIX have a system call statvfs(2) that returns a
// struct statvfs, containing an unsigned long f_fsid // struct statvfs, containing an unsigned long f_fsid
#[cfg(any(target_os = "macos", target_os = "linux"))] #[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "linux"))]
fn fsid(&self) -> u64 { fn fsid(&self) -> u64 {
let f_fsid: &[u32; 2] = unsafe { transmute(&self.f_fsid) }; let f_fsid: &[u32; 2] = unsafe { transmute(&self.f_fsid) };
(f_fsid[0] as u64) << 32 | f_fsid[1] as u64 (f_fsid[0] as u64) << 32 | f_fsid[1] as u64
} }
// FIXME: #[cfg(not(any(target_os = "macos", target_os = "freebsd", target_os = "linux")))]
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
fn fsid(&self) -> u64 { fn fsid(&self) -> u64 {
0 self.f_fsid as u64
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
fn namelen(&self) -> i64 { fn namelen(&self) -> u64 {
self.f_namelen as i64 self.f_namelen as u64
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
fn namelen(&self) -> i64 { fn namelen(&self) -> u64 {
1024 1024
} }
// FIXME: #[cfg(target_os = "freebsd")]
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
fn namelen(&self) -> u64 { fn namelen(&self) -> u64 {
0 self.f_namemax as u64
}
// XXX: should everything just use statvfs?
#[cfg(not(any(target_os = "macos", target_os = "freebsd", target_os = "linux")))]
fn namelen(&self) -> u64 {
self.f_namemax as u64
} }
} }

View file

@ -5,16 +5,21 @@ use std::path::Path;
#[path = "../../mkmain.rs"] #[path = "../../mkmain.rs"]
mod mkmain; mod mkmain;
#[cfg(target_os = "linux")] #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
mod platform { mod platform {
pub const DYLIB_EXT: &str = ".so"; pub const DYLIB_EXT: &str = ".so";
} }
#[cfg(target_os = "macos")] #[cfg(any(target_os = "macos", target_os = "ios"))]
mod platform { mod platform {
pub const DYLIB_EXT: &str = ".dylib"; pub const DYLIB_EXT: &str = ".dylib";
} }
#[cfg(target_os = "windows")]
mod platform {
pub const DYLIB_EXT: &str = ".dll";
}
fn main() { fn main() {
mkmain::main(); mkmain::main();

View file

@ -51,7 +51,7 @@ enum OkMsg {
Version, Version,
} }
#[cfg(target_os = "linux")] #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd", target_os = "dragonflybsd"))]
fn preload_strings() -> (&'static str, &'static str) { fn preload_strings() -> (&'static str, &'static str) {
("LD_PRELOAD", "so") ("LD_PRELOAD", "so")
} }
@ -61,7 +61,7 @@ fn preload_strings() -> (&'static str, &'static str) {
("DYLD_LIBRARY_PATH", "dylib") ("DYLD_LIBRARY_PATH", "dylib")
} }
#[cfg(not(any(target_os = "linux", target_os = "macos")))] #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "netbsd", target_os = "dragonflybsd", target_os = "macos")))]
fn preload_strings() -> (&'static str, &'static str) { fn preload_strings() -> (&'static str, &'static str) {
crash!(1, "Command not supported for this operating system!") crash!(1, "Command not supported for this operating system!")
} }

View file

@ -31,7 +31,7 @@ static LONG_HELP: &str = "
-m only hostname and user associated with stdin -m only hostname and user associated with stdin
-p, --process print active processes spawned by init -p, --process print active processes spawned by init
-q, --count all login names and number of users logged on -q, --count all login names and number of users logged on
-r, --runlevel print current runlevel -r, --runlevel print current runlevel (not available on BSDs)
-s, --short print only name, line, and time (default) -s, --short print only name, line, and time (default)
-t, --time print last system clock change -t, --time print last system clock change
-T, -w, --mesg add user's message status as +, - or ? -T, -w, --mesg add user's message status as +, - or ?
@ -60,6 +60,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
"count", "count",
"all login names and number of users logged on", "all login names and number of users logged on",
); );
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "linux", target_os = "android"))]
opts.optflag("r", "runlevel", "print current runlevel"); opts.optflag("r", "runlevel", "print current runlevel");
opts.optflag("s", "short", "print only name, line, and time (default)"); opts.optflag("s", "short", "print only name, line, and time (default)");
opts.optflag("t", "time", "print last system clock change"); opts.optflag("t", "time", "print last system clock change");
@ -291,6 +292,15 @@ fn current_tty() -> String {
impl Who { impl Who {
fn exec(&mut self) { fn exec(&mut self) {
let run_level_chk = |record: i16| {
let mut res = false;
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "linux", target_os = "android"))]
{
res = record == utmpx::RUN_LVL;
}
res
};
let f = if self.args.len() == 1 { let f = if self.args.len() == 1 {
self.args[0].as_ref() self.args[0].as_ref()
} else { } else {
@ -321,7 +331,7 @@ impl Who {
if !self.my_line_only || cur_tty == ut.tty_device() { if !self.my_line_only || cur_tty == ut.tty_device() {
if self.need_users && ut.is_user_process() { if self.need_users && ut.is_user_process() {
self.print_user(&ut); self.print_user(&ut);
} else if self.need_runlevel && ut.record_type() == utmpx::RUN_LVL { } else if self.need_runlevel && run_level_chk(ut.record_type()) {
self.print_runlevel(&ut); self.print_runlevel(&ut);
} else if self.need_boottime && ut.record_type() == utmpx::BOOT_TIME { } else if self.need_boottime && ut.record_type() == utmpx::BOOT_TIME {
self.print_boottime(&ut); self.print_boottime(&ut);

View file

@ -17,10 +17,10 @@ mod test_passgrp {
#[test] #[test]
fn test_grp2gid() { fn test_grp2gid() {
if cfg!(target_os = "macos") { if cfg!(target_os = "linux") || cfg!(target_os = "android") || cfg!(target_os = "windows") {
assert_eq!(0, grp2gid("wheel").unwrap()); assert_eq!(0, grp2gid("root").unwrap())
} else { } else {
assert_eq!(0, grp2gid("root").unwrap()); assert_eq!(0, grp2gid("wheel").unwrap());
} }
assert!(grp2gid("88888888").is_err()); assert!(grp2gid("88888888").is_err());
assert!(grp2gid("agroupthatdoesntexist").is_err()); assert!(grp2gid("agroupthatdoesntexist").is_err());
@ -34,10 +34,10 @@ mod test_passgrp {
#[test] #[test]
fn test_gid2grp() { fn test_gid2grp() {
if cfg!(target_os = "macos") { if cfg!(target_os = "linux") || cfg!(target_os = "android") || cfg!(target_os = "windows") {
assert_eq!("wheel", gid2grp(0).unwrap());
} else {
assert_eq!("root", gid2grp(0).unwrap()); assert_eq!("root", gid2grp(0).unwrap());
} else {
assert_eq!("wheel", gid2grp(0).unwrap());
} }
assert!(gid2grp(88888888).is_err()); assert!(gid2grp(88888888).is_err());
} }