Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 25 additions & 12 deletions common/pwd/pwd_nix.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,21 @@ struct C.passwd {
pw_shell &char
}

// getgrgid returns a `struct group`, not a `struct passwd`. Reading it through
// a passwd only worked because gr_name happens to sit at the same offset.
struct C.group {
gr_name &char
gr_passwd &char
gr_gid u32
gr_mem voidptr // char **
}

fn C.getpwuid(int) &C.passwd
fn C.getgrgid(int) &C.passwd
fn C.getgrgid(int) &C.group
fn C.getpwnam(&char) &C.passwd
fn C.getgroups(int, &int) int
fn C.getgrouplist(&char, int, &int, &int) int
// gid_t is a 32 bit type, so both of these fill a u32 array.
fn C.getgroups(int, &u32) int
fn C.getgrouplist(&char, u32, &u32, &int) int

pub fn get_uid_for_name(username string) !int {
r := C.getpwnam(username.str)
Expand Down Expand Up @@ -60,7 +70,7 @@ pub fn get_name_for_gid(gid int) !string {
}
return os.error_posix()
}
return cstring_to_vstring(r.pw_name)
return cstring_to_vstring(r.gr_name)
}
}

Expand All @@ -82,26 +92,29 @@ pub fn get_groups(username string) ![]int {
user := get_userinfo_for_name(username)!
unsafe {
mut count := init_group_buf_size
mut groups := []int{len: count}
mut res := C.getgrouplist(username.str, user.gid, &groups[0], &count)
// getgrouplist stores gid_t values, which are 32 bits wide. Handing it
// a []int would leave the upper half of every slot holding whatever was
// there before, so the ids come back as things like 103079215108.
mut gids := []u32{len: count}
mut res := C.getgrouplist(username.str, u32(user.gid), &gids[0], &count)
// If the buffer was not big enough, count will be updated with the
// number we need.
if res == -1 {
groups = []int{len: count}
res = C.getgrouplist(username.str, user.gid, &groups[0], &count)
gids = []u32{len: count}
res = C.getgrouplist(username.str, u32(user.gid), &gids[0], &count)
}
return groups[0..count]
return gids[0..count].map(int(it))
}
}

fn get_effective_groups_up_to(limit int) !(int, []int) {
mut groups := []int{len: init_group_buf_size}
unsafe {
num_groups := C.getgroups(limit, &groups[0])
gids := []u32{len: init_group_buf_size}
num_groups := C.getgroups(limit, &gids[0])
if num_groups < 0 {
return os.error_posix()
}
return num_groups, groups
return num_groups, gids[0..num_groups].map(int(it))
}
}

Expand Down
42 changes: 21 additions & 21 deletions common/readutmp_nix.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,30 @@ module common
#include <utmpx.h>
#include <errno.h>

// TODO: conflicts with `timeval` in <time.h>
// <bits/types/struct_timeval.h>
/*
pub struct C.timeval {
tv_sec i64 // Seconds.
tv_usec i64 // Microseconds.
}*/

// <time.h>
pub struct C.timeval {
pub:
tv_sec u64 // Seconds.
tv_usec u64 // Microseconds.
// `struct utmpx` was previously declared twice, once here and once in
// src/users/users.c.v with a different (shorter) field list, which V rejects as
// a redeclaration. Declare it once, here, with the glibc layout.
//
// The fixed size fields are UT_LINESIZE/UT_NAMESIZE/UT_HOSTSIZE (32/32/256) and
// the element size has to match what getutxent() writes, because read_utmp()
// copies entries into a []C.utmpx.
pub struct C.exit_status {
et_code u16
et_term u16
}

pub struct C.utmpx {
ut_type i16 // Type of login.
ut_pid int // Process ID of login process.
ut_line [32]char // Devicename.
ut_id [4]char // Inittab ID.
ut_user [32]char // Username.
ut_host [256]char // Hostname for remote login.
ut_tv C.timeval // TODO: Declare sub struct correctly
ut_addr_v6 [4]int // Internet address of remote host.
ut_type i16 // Type of login.
ut_pid int // Process ID of login process.
ut_line [32]u8 // Devicename.
ut_id [4]u8 // Inittab ID.
ut_user [32]u8 // Username.
ut_host [256]u8 // Hostname for remote login.
ut_exit C.exit_status // Exit status of the process.
ut_session_id i32 // Session ID.
ut_tv C.timeval // Time entry.
ut_addr_v6 [4]i32 // Internet address of remote host.
__unused [20]u8 // Reserved.
}

// sets the name of the utmp-format file for the other utmp functions to access.
Expand Down
3 changes: 1 addition & 2 deletions common/testing/testrig.v
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,7 @@ pub fn (rig TestRig) assert_platform_util() {
} else {
// uptime was moved to procps-ng and may not be available in coreutils

assert
ver == 'uptime (GNU coreut' || ver == 'uptime (coreutils)' || ver == 'uptime from procps'
assert ver == 'uptime (GNU coreut' || ver == 'uptime (coreutils)' || ver == 'uptime from procps'
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/base64/base64.v
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ fn main() {
exit(1)
}
if wraping_opt < 0 {
eprintln('${application_name}: invalid wrap size: \'${wraping_opt}\'')
eprintln("${application_name}: invalid wrap size: '${wraping_opt}'")
exit(1)
}

Expand Down
4 changes: 2 additions & 2 deletions src/basenc/basenc.v
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os
import v.mathutil
import math
import encoding.base64
import encoding.base32

Expand Down Expand Up @@ -51,7 +51,7 @@ fn print_encoded(encoded string, options Options) {
return
}
for start := 0; start < encoded.len; start += options.wrap {
end := mathutil.min(start + options.wrap, encoded.len)
end := math.min(start + options.wrap, encoded.len)
// safe to use string slicing because all chars
// are in printable ascii
println(encoded[start..end])
Expand Down
3 changes: 2 additions & 1 deletion src/cksum/cksum.v
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ fn calc_sums(args Args) {
}

mut len_counter := total_length
for ; len_counter; len_counter >>= 8 {
for len_counter > 0 {
crc = (crc << 8) ^ crctab[0][((crc >> 24) ^ len_counter) & 0xFF]
len_counter >>= 8
}
crc = ~crc & 0xffff_ffff

Expand Down
6 changes: 2 additions & 4 deletions src/cp/helper.v
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ fn success_exit(messages ...string) {
exit(0)
}

fn setup_cp_command(args []string) ?(CpCommand, []string, string) {
fn setup_cp_command(args []string) (CpCommand, []string, string) {
mut fp := common.flag_parser(args)
fp.application('cp')
fp.limit_free_args_to_at_least(1) or { common.exit_with_error_message(name, err.msg()) }
Expand Down Expand Up @@ -143,9 +143,7 @@ fn setup_cp_command(args []string) ?(CpCommand, []string, string) {
}

pub fn run_cp(args []string) {
cp, sources, dest := setup_cp_command(args) or {
common.exit_with_error_message(name, err.msg())
}
cp, sources, dest := setup_cp_command(args)
if sources.len > 1 && !os.is_dir(dest) {
common.exit_with_error_message(name, target_not_dir(dest))
}
Expand Down
16 changes: 8 additions & 8 deletions src/cut/cut.v
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import arrays
import common
import flag
import io
import math
import os
import v.mathutil

const app_name = 'cut'
const space_comma = ' ,'
Expand Down Expand Up @@ -124,13 +124,13 @@ fn combine_ranges_and_zero_index(ranges []Range, max int, complement bool) []Ran

outer: for range in ranges.sorted(a.start < b.start) {
start := range.start - 1
end := if range.end == -1 { max } else { mathutil.min(max, range.end) }
end := if range.end == -1 { max } else { math.min(max, range.end) }

for mut combined_range in combined_ranges {
if range_overlaps_range(start, end, combined_range.start, combined_range.end) {
combined_range = Range{
start: mathutil.min(start, combined_range.start)
end: mathutil.max(end, combined_range.end)
start: math.min(start, combined_range.start)
end: math.max(end, combined_range.end)
}
continue outer
}
Expand Down Expand Up @@ -189,7 +189,7 @@ fn get_args(args []string) Args {
delimiter := fp.string('delimter', `d`, '', 'use <string> instead of TAB for field delimter')
fields := fp.string('fields', `f`, '',
'select only <string> fields; also print any line${wrap}' +
'that contains no delimiter character, unless the${wrap}-s option is specified')
'that contains no delimiter character, unless the${wrap}-s option is specified')
fp.bool('', `n`, false, '(ignored)')
complement := fp.bool('complement', ` `, false,
'complement the set of selected bytes, characters${wrap}or fields')
Expand All @@ -207,9 +207,9 @@ fn get_args(args []string) Args {
'range, or many ranges separated by commas. Selected input is written${eol}' +
'in the same order that it is read, and is written exactly once.${eol}${eol}' +
'Each range is one of:${eol}${eol}' +
' N N\'th byte, character or field, counted from 1${eol}' +
' N- from N\'th byte, character or field, to end of line${eol}' +
' N-M from N\'th to M\'th (included) byte, character or field${eol}' + " -M from first to M'th (included) byte, character or field")
" N N'th byte, character or field, counted from 1${eol}" +
" N- from N'th byte, character or field, to end of line${eol}" +
" N-M from N'th to M'th (included) byte, character or field${eol}" + " -M from first to M'th (included) byte, character or field")
fp.footer(common.coreutils_footer())

file_args := fp.finalize() or { exit_error(err.msg()) }
Expand Down
2 changes: 1 addition & 1 deletion src/expand/expand.v
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const nl = '\n'
fn process_line(line string, initial bool, tabs int) {
mut sp := ''

for i := tabs; i; i-- {
for _ in 0 .. tabs {
sp += ' '
}

Expand Down
2 changes: 1 addition & 1 deletion src/expr/expr_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ const mb_tests = [
// fail: multi; broken UTF-8 is treated in different way
// "substr \u03B1bc\xB4ef 3 3",
'match abcdef ab',
'match abcdef "\\(ab\\)"'
'match abcdef "\\(ab\\)"',
// fail: single; this is a good news, regex in vlib supports UTF-8
// "match \u03B1bc\u03B4ef .bc",
// fail: both; broken regex of vlib, see #10885
Expand Down
6 changes: 3 additions & 3 deletions src/fmt/fmt.v
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,11 @@ fn process_args(args []string) App {

crown_marg := fp.bool('crown-margin', `c`, false,
'preserve the indentation of the first two lines within' +
'${pad}a paragraph, and align the left margin of each' +
'${pad}subsequent line with that of the second line')
'${pad}a paragraph, and align the left margin of each' +
'${pad}subsequent line with that of the second line')
prefix_str := fp.string('prefix', `p`, '',
'reformat only lines beginning with STRING, reattaching ' +
'${pad}the prefix to reformatted lines')
'${pad}the prefix to reformatted lines')
split_only := fp.bool('split-only', `s`, false, 'split long lines, but do not refill')
tagged_par := fp.bool('tagged-paragraph', `t`, false,
'indentation of first line different from second')
Expand Down
14 changes: 8 additions & 6 deletions src/fmt/fmt_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ fn to_tmp_file(data []string) string {
}

fn setup() (fn (s string), fn () []string) {
mut result := []string{}
mut result_ref := &result
out_fn := fn [mut result_ref] (s string) {
result_ref << s
// The array header has to be heap allocated: a pointer to a local would
// dangle as soon as setup() returned, and the closures would then append to
// freed stack memory.
mut result := &[]string{}
out_fn := fn [mut result] (s string) {
(*result) << s
}
result_fn := fn [mut result_ref] () []string {
return *result_ref
result_fn := fn [result] () []string {
return *result
}
return out_fn, result_fn
}
Expand Down
4 changes: 2 additions & 2 deletions src/head/head.v
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ fn wrap_long_command_description(description string, max_cols int) string {
return buf.str()
}

fn setup_command(args []string) ?(HeadCommand, []InputFile) {
fn setup_command(args []string) (HeadCommand, []InputFile) {
mut fp := common.flag_parser(args)
fp.application(name)
fp.usage_example('[OPTION]... [FILE]...')
Expand Down Expand Up @@ -330,7 +330,7 @@ fn setup_command(args []string) ?(HeadCommand, []InputFile) {
}

fn run_head(args []string) {
head, mut files := setup_command(args) or { common.exit_with_error_message(name, err.msg()) }
head, mut files := setup_command(args)

head.run(mut files)
}
Expand Down
6 changes: 2 additions & 4 deletions src/mv/helper.v
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ fn int_yes(prompt string) bool {
}

pub fn run_mv(args []string) {
mv, sources, dest := setup_mv_command(args) or {
common.exit_with_error_message(name, err.msg())
}
mv, sources, dest := setup_mv_command(args)
if sources.len > 1 && !os.is_dir(dest) {
common.exit_with_error_message(name, target_not_dir(dest))
}
Expand All @@ -59,7 +57,7 @@ pub fn run_mv(args []string) {
}
}

fn setup_mv_command(args []string) ?(MvCommand, []string, string) {
fn setup_mv_command(args []string) (MvCommand, []string, string) {
mut fp := common.flag_parser(args)
fp.application('mv')
fp.limit_free_args_to_at_least(1) or { common.exit_with_error_message(name, err.msg()) }
Expand Down
2 changes: 1 addition & 1 deletion src/nproc/nproc.v
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fn main() {

// Check if ignored CPUs is > 0
if ignored_cpus < 0 {
println('nproc: invalid number: \'${ignored_cpus}\'')
println("nproc: invalid number: '${ignored_cpus}'")
exit(1)
}

Expand Down
16 changes: 14 additions & 2 deletions src/numfmt/numfmt.v
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fn numfmt(number string, mut app App, options Options) !string {
mut result := match true {
options.pformat.len != 0 { unsafe { strconv.v_sprintf(options.pformat, n) } }
options.grouping { commaize(n) }
options.to == 'none' { n.str() }
options.to == 'none' { number_str(n) }
else { num_to_str(n, options) or { handle_error(err.msg(), mut app, options) } }
}

Expand Down Expand Up @@ -170,7 +170,19 @@ fn readable_size(size f64, unit Unit, rounding string) !string {
}
sz /= kb
}
return size.str()
return number_str(size)
}

// number_str renders n the way GNU numfmt does: plain decimal digits, never
// exponent notation, and no trailing ".0" on an integral value. f64.str()
// switches to scientific notation above a million and always keeps the
// fractional part, which would turn 2000000 into "2e+06" and 2000 into "2000.0".
fn number_str(n f64) string {
s := n.strlong()
if s.ends_with('.0') {
return s[..s.len - 2]
}
return s
}

fn scale_number(num f64, pow int, options Options) i64 {
Expand Down
14 changes: 7 additions & 7 deletions src/numfmt/options.v
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,21 @@ fn get_options() Options {
'use locale-defined grouping of digits, e.g. 1,000,000')
header := fp.int('header', 0, 1,
'print (without converting) the first N header lines; <int>\n${flag.space}' +
'defaults to 1 if not specified')
'defaults to 1 if not specified')
invalid := fp.string('invalid', 0, 'abort',
'failure mode for invalid numbers: MODE can be:\n${flag.space}' +
'abort (default), fail, warn, ignore')
'abort (default), fail, warn, ignore')
padding := fp.int('padding', 0, 0,
'pad the output to N characters; positive N will\n${flag.space}' +
'right-align; negative N will left-align; padding is\n${flag.space}' +
'ignored if the output is wider than N; the default is to\n${flag.space}' +
'automatically pad if a whitespace is found')
'right-align; negative N will left-align; padding is\n${flag.space}' +
'ignored if the output is wider than N; the default is to\n${flag.space}' +
'automatically pad if a whitespace is found')
round := fp.string('round', 0, 'from-zero',
'use METHOD for rounding when scaling; METHOD can be:\n${flag.space}' +
'up, down, from-zero (default), towards-zero, nearest')
'up, down, from-zero (default), towards-zero, nearest')
suffix := fp.string('suffix', 0, '',
'add SUFFIX to output numbers, and accept optional SUFFIX\n${flag.space}' +
'in input numbers')
'in input numbers')
to := fp.string('to', 0, 'none', 'auto-scale output numbers to UNIT\n${flag.space}' +
'none, si, iec, iec-i')
to_unit := fp.int('to-unit', 0, 1, 'the output unit size (instead of the default 1)')
Expand Down
Loading
Loading