Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4f8493ffe | ||
|
|
687eaa0eb5 | ||
|
|
011d93c524 | ||
|
|
97f0f5726c | ||
|
|
9c546dfd05 | ||
|
|
8941548ddc | ||
|
|
179d480020 | ||
|
|
4092a164d8 | ||
|
|
ca7c29ab8d | ||
|
|
e4a9a3621f | ||
|
|
f1b7d5ddbe | ||
|
|
78fae360f7 | ||
|
|
cb29deed54 | ||
|
|
390cf01ce1 | ||
|
|
7387b80843 | ||
|
|
c6b71ecfe1 | ||
|
|
1422edeb6a | ||
|
|
7c57fb08ad | ||
|
|
88a304dc16 | ||
|
|
411808c680 | ||
|
|
1fbd9b56a3 | ||
|
|
bbfc794852 | ||
|
|
65edd8ff3a | ||
|
|
5e8d201571 | ||
|
|
7523111d67 | ||
|
|
d4a0d4ffdd | ||
|
|
aeecd914cf | ||
|
|
1190e70085 | ||
|
|
34ee909c59 | ||
|
|
ed14b56a7c | ||
|
|
ca7829b996 | ||
|
|
1c99a3820b | ||
|
|
9258cee615 | ||
|
|
c427c367c1 | ||
|
|
f58ad83c95 | ||
|
|
05f9adade5 | ||
|
|
b29da37462 | ||
|
|
827614dd66 | ||
|
|
d075ddf1ed | ||
|
|
5971d622bd | ||
|
|
14ee298bc3 | ||
|
|
07c1798b5e | ||
|
|
4765b677e7 | ||
|
|
9dbec3cf50 | ||
|
|
246d7701e4 | ||
|
|
8f4bed3274 | ||
|
|
7e993ba14e | ||
|
|
ae0fe82d8a | ||
|
|
76a8da7dc1 | ||
|
|
6130d65249 | ||
|
|
85918358a5 | ||
|
|
0331673e02 | ||
|
|
542c91cdbc | ||
|
|
868a054366 | ||
|
|
549db120db | ||
|
|
0a1e53c2db | ||
|
|
ecfe1f72e3 | ||
|
|
703cf06b7e | ||
|
|
3628ed5072 | ||
|
|
067c9aa7a3 | ||
|
|
9b3f37c233 | ||
|
|
b20598ff72 | ||
|
|
8bd5e89f92 | ||
|
|
905894f294 | ||
|
|
453bcec11a | ||
|
|
a984ab5dd3 | ||
|
|
624097639f | ||
|
|
47ca0d8cf8 | ||
|
|
5944115d94 | ||
|
|
b99026d7d7 | ||
|
|
f72486d4e8 | ||
|
|
e74cab6985 | ||
|
|
a0a097decb | ||
|
|
d0b230bceb | ||
|
|
63f4a0bc39 | ||
|
|
983f75c7df | ||
|
|
e043efd259 | ||
|
|
7e99aa5b13 | ||
|
|
2d08b3208a | ||
|
|
944ae9aca1 | ||
|
|
e82d5e48f4 | ||
|
|
98c92e0239 | ||
|
|
6c5d86c66f | ||
|
|
9d96c7d6eb | ||
|
|
1f27ba3b35 | ||
|
|
4aa73d5fc6 | ||
|
|
50150d0d66 | ||
|
|
192566a9fd | ||
|
|
6dcb41f2fa | ||
|
|
54b0c8bc23 | ||
|
|
6609500d90 | ||
|
|
905e27ad47 | ||
|
|
df77b78e23 | ||
|
|
87f2326012 | ||
|
|
a0cd6a5d18 | ||
|
|
e11d1dec19 | ||
|
|
b51afc07e2 | ||
|
|
813f6aaeab | ||
|
|
49adee62c4 | ||
|
|
35d1e59f74 | ||
|
|
1a00a7fdf5 | ||
|
|
d546e90a94 | ||
|
|
82de6be6fd | ||
|
|
958cacf4bb | ||
|
|
8198058bb2 | ||
|
|
60203aabf5 | ||
|
|
d65dbd2f37 | ||
|
|
65741d9b2e | ||
|
|
4fbcfebc6c | ||
|
|
270bcb066e | ||
|
|
229aadf194 | ||
|
|
6b0f8477d0 | ||
|
|
61b412b0f1 | ||
|
|
6772d7e5a1 | ||
|
|
f6b2196369 | ||
|
|
d2c183d234 | ||
|
|
e09976042d | ||
|
|
7ddbc72525 | ||
|
|
7c19f58e75 | ||
|
|
723d96b54b | ||
|
|
6b5d217e22 | ||
|
|
d9eb83e1f5 | ||
|
|
411f9529a2 | ||
|
|
adf2767763 | ||
|
|
4fc5d10671 | ||
|
|
19d1835d37 | ||
|
|
6f9e73f058 | ||
|
|
5897576ca1 | ||
|
|
9b28da72eb | ||
|
|
d49234eefe | ||
|
|
4bfe83a445 | ||
|
|
228ff740bf | ||
|
|
c69343856a | ||
|
|
d381a1c714 | ||
|
|
0a98062586 | ||
|
|
e7087b101d | ||
|
|
eae06cf3c0 | ||
|
|
0e7a77b42a | ||
|
|
a78a432f50 | ||
|
|
4867b641a7 | ||
|
|
355d030ce0 | ||
|
|
547efed258 | ||
|
|
a4b90879a0 | ||
|
|
3b1bad2334 | ||
|
|
cfe7b4e97a | ||
|
|
10895792d2 | ||
|
|
6b19d8e31c | ||
|
|
f3ce23e7c7 | ||
|
|
663a54bda0 | ||
|
|
ae60fc0688 | ||
|
|
11d727a88d | ||
|
|
b75ecd79d5 | ||
|
|
5fb7e49848 | ||
|
|
21c8237a73 | ||
|
|
b300046eb1 | ||
|
|
17cbab3045 | ||
|
|
d421024fb8 | ||
|
|
7a6ce0f0b6 | ||
|
|
b1bf99c09b | ||
|
|
096b655bb8 | ||
|
|
7a276040ad | ||
|
|
89d2a7840f | ||
|
|
fb2b325e94 | ||
|
|
e7d188ac65 | ||
|
|
79a6420fea | ||
|
|
c54c3258a6 | ||
|
|
0c28d017de | ||
|
|
0a69501594 | ||
|
|
a3f0caeab4 | ||
|
|
478039f539 | ||
|
|
2a25221eaf | ||
|
|
c763f1fcaa | ||
|
|
8b4fa8ade7 | ||
|
|
57f0b91d16 | ||
|
|
a66a1cc10c | ||
|
|
2a31b73a32 | ||
|
|
ee96f3f43b | ||
|
|
2b1d359281 | ||
|
|
4854d71aa9 | ||
|
|
18b1926d61 | ||
|
|
43a54bd541 | ||
|
|
bf371e9a8c | ||
|
|
239a20d13f | ||
|
|
a220e993af | ||
|
|
a955038360 | ||
|
|
c0e530eefd | ||
|
|
1d28da18ce | ||
|
|
571c3bee06 | ||
|
|
618f1c1578 | ||
|
|
496b1e431e | ||
|
|
ef9240a7a5 | ||
|
|
b2f44b6724 | ||
|
|
c19d16b3c8 | ||
|
|
0440ba26da | ||
|
|
070bcb5acc | ||
|
|
f3353cb4bd | ||
|
|
9f63212a7c | ||
|
|
a59c91f03d | ||
|
|
f724ebe158 | ||
|
|
3bc102c334 | ||
|
|
d638cd50f4 | ||
|
|
ebbcdf4b4d | ||
|
|
b3410cf8c0 | ||
|
|
dc51002ba4 | ||
|
|
9bc5903337 | ||
|
|
26c4ad45bd | ||
|
|
cb8cac81aa | ||
|
|
7dc02a475e | ||
|
|
25f43e129f | ||
|
|
b12681d667 | ||
|
|
0af9cb2314 | ||
|
|
fc364d381f | ||
|
|
0481e99c2f | ||
|
|
7eedf884ea | ||
|
|
ebefc02f4e | ||
|
|
17d9ee59e7 | ||
|
|
fec4253f07 | ||
|
|
505a6d9d2b | ||
|
|
3a90959f9c | ||
|
|
73d1237f1b | ||
|
|
1b5a936ebf | ||
|
|
7de5e2ca33 | ||
|
|
854186c942 | ||
|
|
39c7d4f586 | ||
|
|
2e08bbb20a | ||
|
|
bea21335c0 | ||
|
|
ba80d546bc | ||
|
|
d120d654c6 | ||
|
|
b68560a5b6 | ||
|
|
d66343d6f6 | ||
|
|
7e1aa366b6 | ||
|
|
4749cdbb27 | ||
|
|
70fd445307 | ||
|
|
99d27893eb | ||
|
|
ef730dda06 | ||
|
|
e82aa71f26 | ||
|
|
e0f091384f | ||
|
|
bca6fc9542 | ||
|
|
937298eec2 | ||
|
|
2ff99ab1cd | ||
|
|
593723ba92 | ||
|
|
989a34b7c7 | ||
|
|
49b6c71f42 | ||
|
|
b3eacc71d0 | ||
|
|
0eab393715 | ||
|
|
52585447f0 | ||
|
|
3eff81f1a6 | ||
|
|
72376e2d29 | ||
|
|
7532f33c7d | ||
|
|
cf68a17f33 | ||
|
|
f4a3d61a17 | ||
|
|
e01e456825 | ||
|
|
ba0738496e | ||
|
|
bec0b6924e | ||
|
|
1f96f368bd | ||
|
|
3aac6a7b64 | ||
|
|
fc23d71226 | ||
|
|
c2474f5c33 | ||
|
|
9427d210d8 | ||
|
|
bd5b709dda | ||
|
|
b79273bb91 | ||
|
|
f5fd94ef77 | ||
|
|
7c0573c847 | ||
|
|
02b3f215fc | ||
|
|
00b03fbfea | ||
|
|
74de4e9a01 | ||
|
|
d8cc637b56 | ||
|
|
8f19633dd7 | ||
|
|
6c3a08af2b | ||
|
|
7892e54d7e | ||
|
|
d7327aaf95 | ||
|
|
80358e84f3 | ||
|
|
002780fbaf | ||
|
|
1003bbb121 | ||
|
|
f36ff9b378 | ||
|
|
ad834055db | ||
|
|
7ce6d275ba | ||
|
|
8ef4ff2e84 | ||
|
|
00f06f2b2c | ||
|
|
2a54d4edcc | ||
|
|
8281b918ef | ||
|
|
3c8393f8be | ||
|
|
b1178b2ee2 | ||
|
|
d670d47542 | ||
|
|
00cd3cfcc5 | ||
|
|
7edbd3e951 | ||
|
|
d98237134b | ||
|
|
53d9f81eee | ||
|
|
7e504b2f47 | ||
|
|
0e2e30a74c | ||
|
|
7373ccfaad | ||
|
|
1442c148d8 | ||
|
|
59873f1d41 | ||
|
|
805f66badf | ||
|
|
a063b95005 | ||
|
|
5c84305817 | ||
|
|
c8e13d226b | ||
|
|
6a20139f5c | ||
|
|
7be959ece1 | ||
|
|
b3896f93b2 | ||
|
|
09a55ef62a | ||
|
|
149be3f9ab | ||
|
|
f647b12a2d | ||
|
|
ff8e396500 | ||
|
|
04f99c4951 | ||
|
|
29c65ad9e1 | ||
|
|
f84a668098 | ||
|
|
06721c7be1 | ||
|
|
bd70b0c6cb | ||
|
|
220625f370 | ||
|
|
4606638567 | ||
|
|
882428883a | ||
|
|
c2bbb8eef1 | ||
|
|
111b687449 | ||
|
|
547b52a313 | ||
|
|
5f1893f094 | ||
|
|
a33ee8ef26 | ||
|
|
6d8fbbf848 | ||
|
|
d28d2f3155 | ||
|
|
9566e7d7ea | ||
|
|
c39601bbb2 | ||
|
|
e3fcc6ae71 | ||
|
|
9c18fecb98 | ||
|
|
521391a495 | ||
|
|
f65caacfca | ||
|
|
0a27a85b4a | ||
|
|
d186d618e3 | ||
|
|
ae97565e13 | ||
|
|
d028d5165c | ||
|
|
e17f64fce7 |
+7
-1
@@ -8,7 +8,7 @@ bin_PROGRAMS = pv
|
||||
dist_doc_DATA = README.md docs/INSTALL docs/COPYING docs/NEWS.md docs/ACKNOWLEDGEMENTS.md docs/DEVELOPERS.md
|
||||
dist_man1_MANS = docs/pv.1
|
||||
|
||||
EXTRA_DIST = docs/pv.1.md docs/benchmark-rw-syscalls-vs-data.sh docs/release.cf
|
||||
EXTRA_DIST = docs/pv.1.md docs/benchmark-rw-syscalls-vs-data.sh docs/benchmark-pv-transfers.sh docs/release.cf
|
||||
|
||||
pv_SOURCES = \
|
||||
src/main/debug.c \
|
||||
@@ -25,6 +25,7 @@ src/pv/format/averagerate.c \
|
||||
src/pv/format/barstyle.c \
|
||||
src/pv/format/bufferpercent.c \
|
||||
src/pv/format/bytes.c \
|
||||
src/pv/format/conemu.c \
|
||||
src/pv/format/eta.c \
|
||||
src/pv/format/fineta.c \
|
||||
src/pv/format/lastwritten.c \
|
||||
@@ -32,6 +33,7 @@ src/pv/format/name.c \
|
||||
src/pv/format/previousline.c \
|
||||
src/pv/format/progressbar.c \
|
||||
src/pv/format/rate.c \
|
||||
src/pv/format/ratio.c \
|
||||
src/pv/format/sgr.c \
|
||||
src/pv/format/timer.c \
|
||||
src/pv/loop.c \
|
||||
@@ -81,6 +83,8 @@ tests/Integrity_-_Basic.test \
|
||||
tests/Integrity_-_Binary_data.test \
|
||||
tests/Integrity_-_From_bursty_source.test \
|
||||
tests/Integrity_-_Large_file_support.test \
|
||||
tests/Integrity_-_On_closed_output_pipe_at_EOF.test \
|
||||
tests/Integrity_-_On_failed_input_pipe_at_EOF.test \
|
||||
tests/Integrity_-_On_output_pipe_close.test \
|
||||
tests/Integrity_-_When_adjusted_remotely.test \
|
||||
tests/Memory_safety_-_Basic.test \
|
||||
@@ -93,8 +97,10 @@ tests/Modifiers_-_--force.test \
|
||||
tests/Modifiers_-_--interval.test \
|
||||
tests/Modifiers_-_--line-mode.test \
|
||||
tests/Modifiers_-_--size_from_file_size.test \
|
||||
tests/Modifiers_-_--size_from_dir_size.test \
|
||||
tests/Modifiers_-_--size.test \
|
||||
tests/Modifiers_-_--sync.test \
|
||||
tests/Monitor_-_Basic.test \
|
||||
tests/Sparse_-_Basic.test \
|
||||
tests/Terminal_-_Detect_width.test \
|
||||
tests/Transfer_-_--rate-limit.test \
|
||||
|
||||
@@ -3,15 +3,20 @@
|
||||
**pv** ("Pipe Viewer") is a terminal-based tool for monitoring the progress
|
||||
of data through a pipeline and modifying its flow.
|
||||
|
||||
It can be inserted into any normal pipeline between two processes to give a
|
||||
visual indication of how quickly data is passing through, how long it has
|
||||
taken, how near to completion it is, and an estimate of how long it will be
|
||||
until completion. Data flow rate, error handling strategy, buffer size, and
|
||||
cache interaction can all be adjusted.
|
||||
When used just like "**cat**", **pv** displays how quickly data is being
|
||||
transferred, how long it has taken, how near to completion it is, and an
|
||||
estimate of how long it will be until completion. Data flow rate, error
|
||||
handling strategy, buffer size, and cache interaction can all be adjusted.
|
||||
|
||||
With the "**\--cursor**" option, several **pv** instances can work together,
|
||||
showing transfer progress at different points in the same pipeline.
|
||||
|
||||
In "**\--watchfd**" mode, **pv** will inspect another process and show its
|
||||
progress through the files it has open.
|
||||
|
||||
In "**\--monitor**" mode, **pv** will run a command and display the progress
|
||||
of data through both its standard input and its standard output.
|
||||
|
||||
|
||||
# Documentation
|
||||
|
||||
@@ -57,7 +62,7 @@ run it as described above.
|
||||
See "[docs/ACKNOWLEDGEMENTS.md](./docs/ACKNOWLEDGEMENTS.md)" for a list of
|
||||
contributors.
|
||||
|
||||
Copyright (C) 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood.
|
||||
Copyright (C) 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood.
|
||||
|
||||
License GPLv3+: GNU GPL version 3 or later <https://www.gnu.org/licenses/gpl-3.0.html>.
|
||||
|
||||
|
||||
+26
-4
@@ -1,10 +1,10 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
dnl
|
||||
dnl Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
dnl Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
dnl
|
||||
dnl License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
|
||||
AC_INIT([pv], [1.10.3], [https://codeberg.org/ivarch/pv/issues], [pv], [https://ivarch.com/p/pv])
|
||||
AC_INIT([pv], [1.11.0], [https://codeberg.org/ivarch/pv/issues], [pv], [https://ivarch.com/p/pv])
|
||||
AC_CONFIG_SRCDIR([src/include/config.h.in])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([src/include/config.h])
|
||||
@@ -17,6 +17,7 @@ AC_C_CONST
|
||||
AC_HEADER_STDBOOL
|
||||
AC_SYS_LARGEFILE
|
||||
AM_GNU_GETTEXT_VERSION([0.21])
|
||||
AM_GNU_GETTEXT_REQUIRE_VERSION([0.21])
|
||||
AM_GNU_GETTEXT([external])
|
||||
if test "$USE_NLS" = "yes"; then
|
||||
CPPFLAGS="$CPPFLAGS -DLOCALEDIR=\\\"\$(localedir)\\\""
|
||||
@@ -25,12 +26,15 @@ fi
|
||||
|
||||
dnl Items we can use if present, but can do without if not present.
|
||||
AC_CHECK_FUNCS([getopt_long])
|
||||
AC_CHECK_FUNCS([vsnprintf strlcat strtoul memrchr])
|
||||
AC_CHECK_FUNCS([vsnprintf vasprintf strlcat strtoul memrchr])
|
||||
AC_CHECK_FUNCS([fdatasync])
|
||||
AC_CHECK_FUNCS([fpathconf sysconf posix_memalign posix_fadvise])
|
||||
AC_CHECK_FUNCS([getcwd])
|
||||
AC_CHECK_FUNCS([nanosleep])
|
||||
AC_CHECK_FUNCS([setitimer])
|
||||
AC_CHECK_FUNCS([setproctitle])
|
||||
AC_CHECK_FUNCS([nftw])
|
||||
AC_CHECK_FUNCS([strsignal])
|
||||
AC_CHECK_HEADERS([getopt.h])
|
||||
AC_CHECK_HEADERS([limits.h])
|
||||
AC_CHECK_HEADERS([langinfo.h])
|
||||
@@ -40,20 +44,25 @@ AC_CHECK_HEADERS([libgen.h])
|
||||
AC_CHECK_HEADERS([sys/ioctl.h])
|
||||
AC_CHECK_HEADERS([libintl.h locale.h])
|
||||
AC_CHECK_HEADERS([sys/sysmacros.h])
|
||||
AC_CHECK_HEADERS([ftw.h])
|
||||
AC_CHECK_HEADERS([poll.h sys/poll.h])
|
||||
AC_CHECK_FUNCS([poll])
|
||||
AC_CHECK_MEMBERS([struct stat.st_blksize])
|
||||
AC_CHECK_DECLS([SA_SIGINFO], [], [], [[#include <signal.h>]])
|
||||
|
||||
AC_SEARCH_LIBS([sqrtl],[m])
|
||||
AC_SEARCH_LIBS([fmod],[m])
|
||||
AC_SEARCH_LIBS([lroundl],[m])
|
||||
AC_CHECK_HEADERS([math.h])
|
||||
AC_CHECK_FUNCS([sqrtl])
|
||||
AC_CHECK_FUNCS([fmod])
|
||||
AC_CHECK_FUNCS([lroundl])
|
||||
|
||||
dnl Libraries that may contain key functions.
|
||||
AC_SEARCH_LIBS([clock_gettime],[rt])
|
||||
|
||||
dnl Items we can't do without.
|
||||
AC_CHECK_FUNCS([alarm basename clock_gettime dup2 getcwd memcpy memmove memset mkdir select setlocale strchr strerror strrchr strstr], [], [AC_MSG_ERROR([required function is missing])])
|
||||
AC_CHECK_FUNCS([alarm basename clock_gettime dup2 memcpy memmove memset mkdir select setlocale strchr strerror strrchr strstr], [], [AC_MSG_ERROR([required function is missing])])
|
||||
AC_CHECK_HEADERS([fcntl.h sys/file.h sys/time.h unistd.h], [], [AC_MSG_ERROR([required header file is missing])])
|
||||
|
||||
dnl Make sure all the types we use are defined.
|
||||
@@ -134,6 +143,15 @@ AC_ARG_ENABLE([splice],
|
||||
SPLICE_SUPPORT="yes"
|
||||
)
|
||||
|
||||
COPY_FILE_RANGE_SUPPORT="no"
|
||||
AC_ARG_ENABLE([copy-file-range],
|
||||
[AS_HELP_STRING([--disable-copy-file-range], [do not use copy_file_range system call])],
|
||||
if test "$enable_copy_file_range" = "yes"; then
|
||||
COPY_FILE_RANGE_SUPPORT="yes"
|
||||
fi,
|
||||
COPY_FILE_RANGE_SUPPORT="yes"
|
||||
)
|
||||
|
||||
IPC_SUPPORT="no"
|
||||
AC_ARG_ENABLE([ipc],
|
||||
[AS_HELP_STRING([--disable-ipc], [turn off IPC messaging])],
|
||||
@@ -188,6 +206,10 @@ if test "$SPLICE_SUPPORT" = "yes"; then
|
||||
AC_CHECK_FUNCS([splice])
|
||||
fi
|
||||
|
||||
if test "$COPY_FILE_RANGE_SUPPORT" = "yes"; then
|
||||
AC_CHECK_FUNCS([copy_file_range])
|
||||
fi
|
||||
|
||||
CPPFLAGS="$CPPFLAGS -I\$(top_srcdir)/src/include"
|
||||
|
||||
dnl This must go after all the compiler based tests above.
|
||||
|
||||
@@ -110,6 +110,16 @@ is acknowledged and greatly appreciated:
|
||||
* [ipaqmaster](https://codeberg.org/ipaqmaster) - investigated 100%-CPU utilisation bug when piping to a command that has exited ([#164](https://codeberg.org/ivarch/pv/issues/164))
|
||||
* Andriy Galetski, and also [thinrope](https://codeberg.org/thinrope) - suggested the "**--sparse**" option ([#45](https://codeberg.org/ivarch/pv/issues/45))
|
||||
* [KimHansen](https://codeberg.org/KimHansen) - suggested that "**--watchfd**" should keep its display when the process ends ([#81](https://codeberg.org/ivarch/pv/issues/81))
|
||||
* [njt](https://codeberg.org/njt) - suggested that "**--size** @*PATH*" should accept directories ([#179](https://codeberg.org/ivarch/pv/issues/179))
|
||||
* [mojohakase](https://codeberg.org/mojohakase) - provided fix for multiplication bug when combining "**--bits**" with "**--gauge**" ([#182](https://codeberg.org/ivarch/pv/issues/182))
|
||||
* [traq6046](https://codeberg.org/traq6046) - highlighted autoreconf issues with the repository ([#185](https://codeberg.org/ivarch/pv/issues/185))
|
||||
* [heitbaum](https://codeberg.org/heitbaum) - fixed GCC warning when using glibc 2.43 ([#180](https://codeberg.org/ivarch/pv/pulls/180))
|
||||
* [haarp](https://codeberg.org/haarp) - reported that control-C writes "^C" over the progress, and suggested a fix ([#187](https://codeberg.org/ivarch/pv/issues/187))
|
||||
* [Wolfgang Hoschek](https://codeberg.org/whoschek) - provided a fix for the endless wait if the output receiver exits before emptying the pipe ([#189](https://codeberg.org/ivarch/pv/issues/189))
|
||||
* [oech3](https://codeberg.org/oech3) - suggested and tested performance improvements using `splice()` in more situations on Linux ([#188](https://codeberg.org/ivarch/pv/issues/188), [#191](https://codeberg.org/ivarch/pv/issues/191), [#192](https://codeberg.org/ivarch/pv/issues/192))
|
||||
* [Barak A. Pearlmutter](https://codeberg.org/barak) - suggested that "**--rate-limit**" should accept non-integer values ([#193](https://codeberg.org/ivarch/pv/issues/193))
|
||||
* [dirkmueller](https://codeberg.org/dirkmueller) - fixed the potential for stdout closure under a combination of error conditions in **--monitor** mode ([#201](https://codeberg.org/ivarch/pv/pulls/201))
|
||||
* [InkstainTheBat](https://codeberg.org/InkstainTheBat) - suggested ConEmu OSC 9;4 support ([#202](https://codeberg.org/ivarch/pv/issues/202))
|
||||
|
||||
Translations provided through [Codeberg Weblate](https://translate.codeberg.org/projects/pv/):
|
||||
|
||||
@@ -117,6 +127,7 @@ Translations provided through [Codeberg Weblate](https://translate.codeberg.org/
|
||||
* [mmatous](https://translate.codeberg.org/user/mmatous/) (135)
|
||||
* **Finnish**
|
||||
* [artnay](https://translate.codeberg.org/user/artnay/) (65)
|
||||
* [Ricky-Tigg](https://translate.codeberg.org/user/Ricky-Tigg/) (66)
|
||||
* **French**
|
||||
* anonymous suggestions (7)
|
||||
* [milimarg](https://codeberg.org/milimarg) (13)
|
||||
@@ -127,10 +138,13 @@ Translations provided through [Codeberg Weblate](https://translate.codeberg.org/
|
||||
* [Benny](https://translate.codeberg.org/user/Benny/) (7)
|
||||
* [kre](https://translate.codeberg.org/user/kre/) (2)
|
||||
* [fnetX](https://translate.codeberg.org/user/fnetX/) (1)
|
||||
* **Italian**
|
||||
* [ldm](https://translate.codeberg.org/user/ldm/) (27)
|
||||
* **Polish**
|
||||
* [coralpink](https://translate.codeberg.org/user/coralpink/) (106)
|
||||
* [coralpink](https://translate.codeberg.org/user/coralpink/) (122)
|
||||
* **Russian**
|
||||
* [0ko](https://translate.codeberg.org/user/0ko/) (157)
|
||||
* [some_user](https://translate.codeberg.org/user/some_user/) (7)
|
||||
* **Turkish**
|
||||
* [omerdduran](https://translate.codeberg.org/user/omerdduran/) (129)
|
||||
* [Oğuz Ersen](https://codeberg.org/ersen) (8)
|
||||
|
||||
@@ -133,6 +133,51 @@ translations (empty _"msgstr"_ lines) or translations marked as "fuzzy", as
|
||||
these will need to be corrected by translators.
|
||||
|
||||
|
||||
## Benchmarking
|
||||
|
||||
The "`docs/benchmark-pv-transfers.sh`" script, introduced in
|
||||
[#198](https://codeberg.org/ivarch/pv/issues/198), is used to check that new
|
||||
changes to **pv** aren't making it less efficient at transferring data. Run
|
||||
it with the **--help** option for a summary of its options.
|
||||
|
||||
In _benchmark_ mode, it takes multiple rounds of measurements of the
|
||||
transfer rate using various different transfer options. The mean (μ) and
|
||||
standard deviation (σ) of each measurement is produced at the end of the
|
||||
run. All data is written to the standard output - pipe to "`tee OUTPUT`" to
|
||||
write to a file _OUTPUT_ while still displaying it on the terminal.
|
||||
|
||||
Either a specific **pv** binary can be benchmarked (with the **-p** option),
|
||||
or multiple **pv** versions can be benchmarked in a single call, each one
|
||||
counting as an individual run (with the **-d** option, pointing to a
|
||||
directory containing _tar.gz_ source archives).
|
||||
|
||||
Transfer rate measurements use up to two test files, the size of which can
|
||||
be overridden by the **-s** option, and some measurements will transfer and
|
||||
discard zeros from _/dev/zero_, the amount of which can be overridden with
|
||||
the **-z** option.
|
||||
|
||||
The measured rates may vary significantly due to external factors such as
|
||||
system load, so multiple measurement rounds (the **-r** option) are
|
||||
recommended per run.
|
||||
|
||||
In _analyse_ mode, the results of multiple runs are read from standard
|
||||
input, and a report is produced that shows how each measurement differs
|
||||
between runs.
|
||||
|
||||
If the input data is from multiple versions of **pv**, the differences
|
||||
between versions will be compared; otherwise, the differences between
|
||||
individual runs will be compared. The **-c** option overrides this.
|
||||
|
||||
When re-using data from multiple runs, the **-f** option causes the report
|
||||
to only show the differences between the last two runs (or versions).
|
||||
|
||||
The **-t** option produces a terse report that is more machine-readable.
|
||||
|
||||
In _measurements_ mode, a list of all of the measurement types is produced.
|
||||
Each type of measurement has an associated ID - these IDs can be passed to
|
||||
the benchmark mode to only run a subset of the measurements in that run.
|
||||
|
||||
|
||||
## Release checklist
|
||||
|
||||
The package maintainer should run through these steps for a new release:
|
||||
@@ -145,6 +190,7 @@ The package maintainer should run through these steps for a new release:
|
||||
* <https://packages.gentoo.org/packages/sys-apps/pv>
|
||||
* <https://cvsweb.openbsd.org/ports/sysutils/pv/>
|
||||
* <https://packages.fedoraproject.org/pkgs/pv/pv/>
|
||||
* Check for translation updates <https://translate.codeberg.org/projects/pv>
|
||||
* Run "`make indent; make indent indentclean check`"
|
||||
* Check that _po/POTFILES.in_ is up to date
|
||||
* Run "`make -C po update-po`"
|
||||
|
||||
+55
-10
@@ -1,3 +1,48 @@
|
||||
### UNRELEASED
|
||||
|
||||
* *feature:* new **--format** string **%{progress-conemu}**, and option **--conemu**, to show progress in the terminal title tab on terminals with ConEmu OSC 9;4 support ([#202](https://codeberg.org/ivarch/pv/issues/202))
|
||||
* *cleanup:* eliminate potential for closure of standard output under a combination of error conditions when using **--monitor** mode ([#201](https://codeberg.org/ivarch/pv/pulls/201))
|
||||
* *i18n:* Italian translations added
|
||||
* *i18n:* Russian translations updated
|
||||
* *i18n:* empty Romanian message catalogue added, awaiting translations
|
||||
|
||||
### 1.11.0 - 11 June 2026
|
||||
|
||||
* *feature:* new **--monitor** option to run a command and watch its input, output, or both ([#67](https://codeberg.org/ivarch/pv/issues/67))
|
||||
* *feature:* allow decimal values for **--rate-limit** ([#193](https://codeberg.org/ivarch/pv/issues/193))
|
||||
* *feature:* extend the **--format** string **%T**/**%{buffer-percent}** to indicate the transfer method when the buffer isn't being used
|
||||
* *performance:* insert an intermediate input pipe where it would allow `splice()` to be used in more circumstances ([#188](https://codeberg.org/ivarch/pv/issues/188))
|
||||
* *performance:* use `copy_file_range`(2) when the input and output are both regular files ([#196](https://codeberg.org/ivarch/pv/issues/196))
|
||||
* *performance:* improve **--discard** performance by splicing to /dev/null internally ([#191](https://codeberg.org/ivarch/pv/issues/191))
|
||||
* *fix:* report signal interrupts on a new line, so that control-C doesn't write "^C" over the progress ([#187](https://codeberg.org/ivarch/pv/issues/187))
|
||||
* *fix:* prevent an endless wait if there is unread data in the output pipe when its reader terminates ([#189](https://codeberg.org/ivarch/pv/issues/189))
|
||||
* *fix:* prevent `splice()` from falling back to `read()` when using **--rate-limit**
|
||||
* *fix:* stop spliced transfers requiring two EOFs when the input is a terminal
|
||||
* *fix:* add timer interrupt to spliced transfers to avoid progress display lockup when the receiver stalls
|
||||
* *fix:* exit with an error if the PID file given to **--pidfile** cannot be replaced
|
||||
* *fix:* correct the **--help** word wrapping on very small terminals
|
||||
* *i18n:* Polish translations updated
|
||||
* *i18n:* Finnish translations updated
|
||||
* *i18n:* German translations updated
|
||||
* *i18n:* French translations updated
|
||||
* *i18n:* partial draft of Georgian translations added
|
||||
* *i18n:* removed empty unmaintained translation catalogue for Spanish
|
||||
* *cleanup:* fix GCC warning when using glibc 2.43 ([#180](https://codeberg.org/ivarch/pv/pulls/180))
|
||||
* *cleanup:* fix warning in pv_remote_check() stub on OpenBSD
|
||||
* *cleanup:* use dynamic line buffers for **--watchfd** process lookups
|
||||
* *cleanup:* replace the blanket 100,000-hour clamp on displayed times with a million days for timer and ETA, and 7,000 years for estimated finish time, on 64-bit systems
|
||||
* *cleanup:* use rounding when calculating ETA, and avoid integer overflows, particularly on 32-bit systems
|
||||
* *cleanup:* standardise the error reporting mechanism
|
||||
* *cleanup:* improve code comments
|
||||
|
||||
### 1.10.5 - 22 March 2026
|
||||
|
||||
* *fix:* when using **--bits** with **--gauge**, don't incorrectly multiply the rate twice ([#182](https://codeberg.org/ivarch/pv/issues/182))
|
||||
|
||||
### 1.10.4 - 8 March 2026
|
||||
|
||||
* *fix:* when using **--size @PATH**, *PATH* can be a directory, and the total size of all files within it will be used ([#179](https://codeberg.org/ivarch/pv/issues/179))
|
||||
|
||||
### 1.10.3 - 15 December 2025
|
||||
|
||||
* *fix:* stop truncating the process title set by **--extra-display**
|
||||
@@ -154,7 +199,7 @@
|
||||
* *feature:* new **--discard** option to discard input as if writing to */dev/null* ([#42](https://codeberg.org/ivarch/pv/issues/42))
|
||||
* *feature:* new **--error-skip-block** option to make **--skip-errors** skip whole blocks ([#37](https://codeberg.org/ivarch/pv/issues/37))
|
||||
* *feature:* use `posix_fadvise()` like `cat`(1) does, to improve efficiency ([#39](https://codeberg.org/ivarch/pv/issues/39))
|
||||
* *feature:* new **--enable-static** option to "`configure`" for static builds ([#75](https://codeberg.org/ivarch/pv/pull/75))
|
||||
* *feature:* new **--enable-static** option to "`configure`" for static builds ([#75](https://codeberg.org/ivarch/pv/pulls/75))
|
||||
|
||||
#### Security
|
||||
|
||||
@@ -229,15 +274,15 @@
|
||||
### 1.7.0 - 17 July 2023
|
||||
|
||||
* *dropped:* support for Red Hat Enterprise Linux and its derivatives has been dropped; removed the RPM spec file, and will no longer build binaries
|
||||
* *feature:* the **--size** option now accepts "`@filename`" to use the size of another file (pull request [#57](https://codeberg.org/ivarch/pv/pull/57) supplied by [Dave Beckett](https://github.com/dajobe))
|
||||
* *feature:* the **--watchfd** option is now available on OS X (pull request [#60](https://codeberg.org/ivarch/pv/pull/60) supplied by [christoph-zededa](https://github.com/christoph-zededa))
|
||||
* *feature:* new **--bits** option to show bit count instead of byte count (adapted from pull request [#63](https://codeberg.org/ivarch/pv/pull/63) supplied by [Nick Black](https://nick-black.com))
|
||||
* *feature:* new **--average-rate-window** option, to set the window over which the average rate is calculated, also used for ETA (modified from pull request [#65](https://codeberg.org/ivarch/pv/pull/65) supplied by [lemonsqueeze](https://github.com/lemonsqueeze))
|
||||
* *feature:* the **--watchfd** option will now show relative filenames, if they are under the current directory (pull request [#66](https://codeberg.org/ivarch/pv/pull/66) supplied by [ikasty](https://github.com/ikasty))
|
||||
* *fix:* correction to `pv_in_foreground()` to behave as its comment block says it should, when not on a terminal - corrects [#19 "No output in Arch Linux initcpio after 1.6.6"](https://codeberg.org/ivarch/pv/issues/19), [#31 "No output written from inside zsh <() construct"](https://codeberg.org/ivarch/pv/issues/31), [#55 "pv Stopped Working in the Background"](https://codeberg.org/ivarch/pv/issues/55) (pull request [#64](https://codeberg.org/ivarch/pv/pull/64) supplied by [Michael Weiß](https://github.com/quitschbo))
|
||||
* *fix:* workaround for OS X 11 behaviour in configure script regarding stat64 at compile time (pull request [#57](https://codeberg.org/ivarch/pv/pull/57) supplied by [Dave Beckett](https://github.com/dajobe))
|
||||
* *feature:* the **--size** option now accepts "`@filename`" to use the size of another file (pull request [#57](https://codeberg.org/ivarch/pv/pulls/57) supplied by [Dave Beckett](https://github.com/dajobe))
|
||||
* *feature:* the **--watchfd** option is now available on OS X (pull request [#60](https://codeberg.org/ivarch/pv/pulls/60) supplied by [christoph-zededa](https://github.com/christoph-zededa))
|
||||
* *feature:* new **--bits** option to show bit count instead of byte count (adapted from pull request [#63](https://codeberg.org/ivarch/pv/pulls/63) supplied by [Nick Black](https://nick-black.com))
|
||||
* *feature:* new **--average-rate-window** option, to set the window over which the average rate is calculated, also used for ETA (modified from pull request [#65](https://codeberg.org/ivarch/pv/pulls/65) supplied by [lemonsqueeze](https://github.com/lemonsqueeze))
|
||||
* *feature:* the **--watchfd** option will now show relative filenames, if they are under the current directory (pull request [#66](https://codeberg.org/ivarch/pv/pulls/66) supplied by [ikasty](https://github.com/ikasty))
|
||||
* *fix:* correction to `pv_in_foreground()` to behave as its comment block says it should, when not on a terminal - corrects [#19 "No output in Arch Linux initcpio after 1.6.6"](https://codeberg.org/ivarch/pv/issues/19), [#31 "No output written from inside zsh <() construct"](https://codeberg.org/ivarch/pv/issues/31), [#55 "pv Stopped Working in the Background"](https://codeberg.org/ivarch/pv/issues/55) (pull request [#64](https://codeberg.org/ivarch/pv/pulls/64) supplied by [Michael Weiß](https://github.com/quitschbo))
|
||||
* *fix:* workaround for OS X 11 behaviour in configure script regarding stat64 at compile time (pull request [#57](https://codeberg.org/ivarch/pv/pulls/57) supplied by [Dave Beckett](https://github.com/dajobe))
|
||||
* *fix:* workaround for macOS equivalence of stat to stat64 - patches from [Filippo Valsorda](https://github.com/FiloSottile) and [Demitri Muna](https://github.com/demitri), correcting [#33 "Fix compilation problems due to `stat64()` on Apple Silicon"](https://codeberg.org/ivarch/pv/issues/33)
|
||||
* *fix:* add burst rate limit to transfer, so rate limits are not broken by bursty traffic (pull request [#62](https://codeberg.org/ivarch/pv/pull/62) supplied by [Volodymyr Bychkovyak](https://github.com/vbychkoviak))
|
||||
* *fix:* add burst rate limit to transfer, so rate limits are not broken by bursty traffic (pull request [#62](https://codeberg.org/ivarch/pv/pulls/62) supplied by [Volodymyr Bychkovyak](https://github.com/vbychkoviak))
|
||||
* *fix:* corrected **--force** option so it will still output progress when not in the same process group as the owner of the terminal - corrects [#23 "No output with "-f" when run in background after 1.6.6"](https://codeberg.org/ivarch/pv/issues/23) and helps to correct [#31 "No output written from inside zsh <() construct"](https://codeberg.org/ivarch/pv/issues/31)
|
||||
* *fix:* corrected elapsed time display to show as D:HH:MM:SS after 1 day, like the ETA does - corrects [#16 "Show days in same format in ETA as in elapsed time"](https://codeberg.org/ivarch/pv/issues/16)
|
||||
* *fix:* corrected bug where percentages went down after 100% when in **--numeric** mode with a **--size** that was too small - corrects [#26 "Correct "-n" behaviour when going past 100% of "-s" size"](https://codeberg.org/ivarch/pv/issues/26)
|
||||
@@ -318,7 +363,7 @@ Full changelog is below:
|
||||
|
||||
* allow **--watchfd** to look at block devices
|
||||
* let **--watchfd PID:FD** work with **--size N**
|
||||
* moved contributors out of the manual as the list was too long (NB everyone is still listed in the README and always will be)
|
||||
* moved contributors out of the manual as the list was too long (NB everyone is still listed in the package documentation and always will be)
|
||||
|
||||
### 1.5.1 - 23 January 2014
|
||||
|
||||
|
||||
Executable
+701
@@ -0,0 +1,701 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Benchmark transfer rates, and analyse benchmark results.
|
||||
#
|
||||
# Measures transfer rates and CPU usage with various different options,
|
||||
# multiple times, then calculates the mean and standard deviation for each
|
||||
# set of measurements.
|
||||
#
|
||||
# The results are written to stdout as tab-separated values, each line
|
||||
# prefixed with an opaque system ID (based on "uname -a"), the PV version
|
||||
# expressed as an integer, and a run ID based on the start date and time.
|
||||
#
|
||||
# In analysis mode, reads results from multiple benchmark runs on standard
|
||||
# input, and for each type of measurement, show the differences between
|
||||
# either the different PV versions or the different runs.
|
||||
|
||||
# Defaults.
|
||||
pv='pv' # PV executable to run the measurements with
|
||||
rounds='10' # how many rounds of measurements to take
|
||||
testFileMB='256' # max size of each of the test files, in MiB
|
||||
testZeroesMB='1024' # amount of /dev/zero data to use, in MiB
|
||||
sourcesDir='' # directory containing sources to benchmark
|
||||
compareWhat='auto' # what to compare in the analysis
|
||||
finalLineOnly='false' # whether to only show the last measurement's analysis
|
||||
terseFormat='false' # whether to use a terse report format
|
||||
|
||||
# Script information for --help and --version.
|
||||
programName='benchmark-pv-transfers'
|
||||
programVersion='1.0.0'
|
||||
bugReportsTo='https://codeberg.org/ivarch/pv/issues'
|
||||
copyrightYear='2026'
|
||||
copyrightHolder='Andrew Wood'
|
||||
|
||||
# Constants.
|
||||
fieldsPerRecord='4' # measurements taken: rate, time - real, user, sys.
|
||||
|
||||
# Hash function - write hex on stdout based on a hash of stdin.
|
||||
runHash () {
|
||||
command -v md5sum >/dev/null 2>&1 && exec md5sum
|
||||
# OpenBSD has no "md5sum" but does have "cksum -a md5".
|
||||
cksum -r -a md5 2>/dev/null || cksum
|
||||
}
|
||||
|
||||
# Define the measurements. Each measurement definition contains:
|
||||
# - The ID of the measurement
|
||||
# - The name of the measurement
|
||||
# - A space-separated list of single-letter options that PV must support
|
||||
# - How many testFileMB multiples are transferred, or Z for testZeroesMB
|
||||
# - The command to run
|
||||
# In the command to run, {PV} is replaced with the path to PV, {FILE1} and
|
||||
# {FILE2} are replaced by the random data filenames, {ZSIZE} is replaced by
|
||||
# testZeroesMB, and {OUTPUT} is replaced by a temporary output filename.
|
||||
# Each definition is stored as single line, with the above parts separated
|
||||
# by "!".
|
||||
measurementDefinitions=''
|
||||
# Add a definition (name, options list, data size, command) to the
|
||||
# definitions array.
|
||||
addDefinition () {
|
||||
measurementDefinitions="$(
|
||||
printf '%s\n%s!%s!%s!%s!%s\n' \
|
||||
"${measurementDefinitions}" \
|
||||
"$(printf '%s\n' "$1" | runHash | cut -b1-7)" \
|
||||
"$1" "$2" "$3" "$4" \
|
||||
| grep .
|
||||
)"
|
||||
}
|
||||
# Add a set of standard definitions for measurements, naming them with a
|
||||
# prefix "$1: ", each with extra options "$2".
|
||||
addStandardMeasurements () {
|
||||
# From file via stdin to file via stdout.
|
||||
addDefinition "$1: stdin file to file" "$2" 1 "{PV} $2 < {FILE1} > {OUTPUT}"
|
||||
# From file to file via stdout.
|
||||
addDefinition "$1: file to file" "$2" 1 "{PV} $2 {FILE1} > {OUTPUT}"
|
||||
# From two files to file via stdout.
|
||||
addDefinition "$1: two files to file" "$2" 2 "{PV} $2 {FILE1} {FILE2} > {OUTPUT}"
|
||||
# From pipe to file via stdout.
|
||||
addDefinition "$1: pipe to file" "$2" 1 "cat {FILE1} | {PV} $2 > {OUTPUT}"
|
||||
# From file via stdin to pipe.
|
||||
addDefinition "$1: stdin file to pipe" "$2" 1 "{PV} $2 < {FILE1} | cat > {OUTPUT}"
|
||||
# From file to pipe.
|
||||
addDefinition "$1: file to pipe" "$2" 1 "{PV} $2 {FILE1} | cat > {OUTPUT}"
|
||||
# From two files to pipe.
|
||||
addDefinition "$1: two files to pipe" "$2" 2 "{PV} $2 {FILE1} {FILE2} | cat > {OUTPUT}"
|
||||
# From pipe to pipe.
|
||||
addDefinition "$1: pipe to pipe" "$2" 1 "cat {FILE1} | {PV} $2 | cat > {OUTPUT}"
|
||||
}
|
||||
# Generate the measurement definitions, most of which are based on repeated
|
||||
# blocks of the above standard measurements, with various different options.
|
||||
defineMeasurements () {
|
||||
addStandardMeasurements 'Default' ''
|
||||
addStandardMeasurements 'No-splice' '-C'
|
||||
addStandardMeasurements 'Pipe buffer 1M' '-J 1M'
|
||||
addStandardMeasurements 'Transfer buffer 1M' '-B 1M'
|
||||
|
||||
addStandardMeasurements 'Discard' '-X'
|
||||
addStandardMeasurements 'Discard with no-splice' '-X -C'
|
||||
addStandardMeasurements 'Discard with pipe buffer 1M' '-X -J 1M'
|
||||
addStandardMeasurements 'Discard with transfer buffer 1M' '-X -B 1M'
|
||||
|
||||
addDefinition "Zeroes: stdout to /dev/null" '-S -s' Z "{PV} -S -s {ZSIZE}M /dev/zero > /dev/null"
|
||||
addDefinition "Zeroes: stdout to pipe" '-S -s' Z "{PV} -S -s {ZSIZE}M /dev/zero | cat > /dev/null"
|
||||
addDefinition "Zeroes: discarded" '-X -S -s' Z "{PV} -X -S -s {ZSIZE}M /dev/zero"
|
||||
addDefinition "Zeroes: stdout to /dev/null with no-splice" '-C -S -s' Z "{PV} -C -S -s {ZSIZE}M /dev/zero > /dev/null"
|
||||
addDefinition "Zeroes: stdout to pipe with no-splice" '-C -S -s' Z "{PV} -C -S -s {ZSIZE}M /dev/zero | cat > /dev/null"
|
||||
addDefinition "Zeroes: discarded with no-splice" '-C -X -S -s' Z "{PV} -C -X -S -s {ZSIZE}M /dev/zero"
|
||||
}
|
||||
|
||||
# Write an error message $1 to standard error, prefixed with the program
|
||||
# name.
|
||||
error () {
|
||||
printf '%s: %s\n' "${programName}" "$1" >&2
|
||||
}
|
||||
|
||||
# Output an error message $1, and exit with a failure status.
|
||||
die () {
|
||||
error "$1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Show all measurement definitions.
|
||||
showMeasurementDefinitions () {
|
||||
printf '%s\n%s\n' 'ID!Name!Opts!Size!Command' "${measurementDefinitions}" \
|
||||
| awk -F '!' '{printf "%s\t%-60s\t%s\n", $1, $2, $5}'
|
||||
}
|
||||
|
||||
# Sort a list of version numbers on stdin, in version order.
|
||||
versionSort () {
|
||||
# If sort has no -V, like on CentOS 5, fall back to a simplistic
|
||||
# substitute.
|
||||
sort -V 2>/dev/null \
|
||||
|| perl -pe '$x=$_;$x=~s/(0*[0-9]+)/sprintf("%09d",$1)/ge;chomp $x;$_=$x." ".$_' | sort | awk '{print $2}'
|
||||
}
|
||||
|
||||
# Write a line of results for the measurement with ID $1 and name $2, round
|
||||
# ${thisRound}, reading the times from ${workDir}/times and deriving the
|
||||
# rate from the elapsed time (the real time in the times file) and the size
|
||||
# written in ${workDir}/size. Removes those two files in the process.
|
||||
#
|
||||
# The results are also spooled to ${workDir}/results for later analysis,
|
||||
# prefixed with only the ID $1.
|
||||
resultsLine () {
|
||||
testTimeReal="$(awk '$1=="real" {print $2}' "${workDir}/times")"
|
||||
testTimeUser="$(awk '$1=="user" {print $2}' "${workDir}/times")"
|
||||
testTimeSystem="$(awk '$1=="sys" {print $2}' "${workDir}/times")"
|
||||
testRate="$(awk -v t="${testTimeReal}" '{if (t>0) { printf "%.3f\n", $1/t } else { print "-" }}' < "${workDir}/size")"
|
||||
test -n "${testRate}" || testRate='-'
|
||||
rm -f "${workDir}/times" "${workDir}/size"
|
||||
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' "${outputPrefix}" "${thisRound}" "$1" "${testRate}" "${testTimeReal}" "${testTimeUser}" "${testTimeSystem}" "$2"
|
||||
printf '%s\t%s\t%s\t%s\t%s\n' "$1" "${testRate}" "${testTimeReal}" "${testTimeUser}" "${testTimeSystem}" >> "${workDir}/results"
|
||||
}
|
||||
|
||||
# Run $2 in a shell under "time", writing $1 to ${workDir}/size and the
|
||||
# times to ${workDir}/times.
|
||||
captureTimes () {
|
||||
printf '%s\n' "$1" > "${workDir}/size"
|
||||
(
|
||||
TIMEFORMAT="real %3R
|
||||
user %3U
|
||||
sys %3S"
|
||||
time sh -c "{ $2; } 2>&3"
|
||||
) 3>&2 2>"${workDir}/times"
|
||||
}
|
||||
|
||||
# Run all defined measurements for which the required options are available.
|
||||
#
|
||||
# If "${workDir}/permitted-measurements" is not empty, only measurements
|
||||
# with IDs listed in that file will be taken.
|
||||
gatherMeasurements () {
|
||||
printf '%s\n' "${measurementDefinitions}" \
|
||||
| {
|
||||
while read -r definitionLine; do
|
||||
measurementId="${definitionLine%%!*}"
|
||||
measurementName="${definitionLine#*!}"
|
||||
measurementName="${measurementName%%!*}"
|
||||
requiredOptions="${definitionLine#*!}"
|
||||
requiredOptions="${requiredOptions#*!}"
|
||||
requiredOptions="${requiredOptions%%!*}"
|
||||
dataSize="${definitionLine#*!}"
|
||||
dataSize="${dataSize#*!}"
|
||||
dataSize="${dataSize#*!}"
|
||||
dataSize="${dataSize%%!*}"
|
||||
templateCommand="${definitionLine##*!}"
|
||||
|
||||
test -n "${templateCommand}" || continue
|
||||
|
||||
if test -s "${workDir}/permitted-measurements"; then
|
||||
grep -Fqx "${measurementId}" "${workDir}/permitted-measurements" || continue
|
||||
fi
|
||||
|
||||
if test -n "${requiredOptions}"; then
|
||||
optionLetters="$(printf 'x%s\n' "${requiredOptions}" | tr -d '!' | sed 's/-/!-/g' | tr '!' '\n' | grep '^-' | cut -b 2)"
|
||||
optionsPresent='true'
|
||||
for pvOption in ${optionLetters}; do
|
||||
grep -Fq " -${pvOption}" "${workDir}/help" || optionsPresent='false'
|
||||
done
|
||||
${optionsPresent} || continue
|
||||
fi
|
||||
|
||||
# Add some display options to make more information visible
|
||||
# on versions that support them.
|
||||
pvExtraOptions=''
|
||||
pvFormatString='%b %t %r %p %e %T'
|
||||
if grep -Fq " -N" "${workDir}/help"; then
|
||||
pvExtraOptions="${pvExtraOptions} -N '${measurementId}'"
|
||||
pvFormatString="%N ${pvFormatString}"
|
||||
fi
|
||||
grep -Fq " -F" "${workDir}/help" && pvExtraOptions="${pvExtraOptions} -F '${pvFormatString}'"
|
||||
|
||||
activeCommand="$(
|
||||
printf '%s\n' "${templateCommand}" | sed \
|
||||
-e "s!{PV}!${pv}${pvExtraOptions}!g" \
|
||||
-e "s!{FILE1}!${workDir}/file1!g" \
|
||||
-e "s!{FILE2}!${workDir}/file2!g" \
|
||||
-e "s!{ZSIZE}!${testZeroesMB}!g" \
|
||||
-e "s!{OUTPUT}!${workDir}/output!g"
|
||||
)"
|
||||
|
||||
if test "${dataSize}" = "Z"; then
|
||||
dataSize="${testZeroesMB}"
|
||||
else
|
||||
dataSize=$((dataSize*testFileMB))
|
||||
fi
|
||||
|
||||
rm -f "${workDir}/output1" "${workDir}/output2"
|
||||
captureTimes "${dataSize}" "${activeCommand}"
|
||||
resultsLine "${measurementId}" "${measurementName}"
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
# Run several rounds of benchmark measurements using $1 as the pv
|
||||
# executable, producing tab-separated data, including a final section
|
||||
# containing the means and standard deviations for each measurement type.
|
||||
#
|
||||
# If $2 is not blank, only run the measurements whose IDs are listed in it.
|
||||
runBenchmarks () {
|
||||
pv="$1"
|
||||
restrictTo="$2"
|
||||
|
||||
# Check there's enough room for the test files, meaning that 2 test
|
||||
# files + 1 output file + 2MB doesn't add up to more than 75% of the
|
||||
# space on the filesystem holding TMPDIR - make the test files
|
||||
# smaller, if not.
|
||||
tmpSpaceMB="$(df -kP "${TMPDIR:-/tmp}" | awk 'FNR==2 {print int($4*3/4096)}')"
|
||||
while test "${testFileMB}" -gt 4; do
|
||||
test "${tmpSpaceMB}" -gt $((2+3*testFileMB)) && break
|
||||
testFileMB=$((testFileMB/2))
|
||||
done
|
||||
|
||||
# Capture the help text so that capabilities can be checked.
|
||||
${pv} -h > "${workDir}/help"
|
||||
|
||||
# Write a list of permitted measurement IDs, one per line. An empty
|
||||
# file means no restriction.
|
||||
# shellcheck disable=SC2020 # silence the warning about "tr" here.
|
||||
printf '%s\n' "${restrictTo}" \
|
||||
| tr ',; \t' '\n\n\n\n' \
|
||||
| sort -u \
|
||||
| grep . \
|
||||
> "${workDir}/permitted-measurements"
|
||||
|
||||
# Define identifiers for the system this is running on, the pv
|
||||
# version being benchmarked, and this specific benchmark run.
|
||||
sysId="$(uname -a | runHash | cut -b1-7)"
|
||||
pvId="$(${pv} --version | awk 'FNR==1{print $2}' | awk -F . '{print 1000000*$1+1000*$2+$3}')"
|
||||
runId="$(date '+%Y%m%d%H%M%S')"
|
||||
outputPrefix="$(printf '%s\t%s\t%s\n' "${sysId}" "${pvId}" "${runId}")"
|
||||
|
||||
# Basic system information, and a header line for the test results.
|
||||
printf '%s\t%s\t%s\n' "${outputPrefix}" 'System hostname' "$(uname -n)"
|
||||
printf '%s\t%s\t%s\n' "${outputPrefix}" 'System load' "$(uptime | awk '{printf "%.2f\n",$(NF-2)}')"
|
||||
printf '%s\t%s\t%s\n' "${outputPrefix}" 'System kernel type' "$(uname -s)"
|
||||
printf '%s\t%s\t%s\n' "${outputPrefix}" 'System kernel release' "$(uname -r)"
|
||||
printf '%s\t%s\t%s\n' "${outputPrefix}" 'System OS' "$(uname -o)"
|
||||
printf '%s\t%s\t%s\n' "${outputPrefix}" 'PV path' "${pv}"
|
||||
printf '%s\t%s\t%s\n' "${outputPrefix}" 'PV version' "$(${pv} -V | awk 'FNR==1 {print $2}')"
|
||||
printf '%s\t%s\t%s\n' "${outputPrefix}" 'Test file size (MB)' "${testFileMB}"
|
||||
|
||||
# Generate two files of random data.
|
||||
dd if='/dev/urandom' of="${workDir}/file1" bs=1048576 count="${testFileMB}" 2>/dev/null
|
||||
dd if='/dev/urandom' of="${workDir}/file2" bs=1048576 count="${testFileMB}" 2>/dev/null
|
||||
|
||||
# Run several rounds of measurements.
|
||||
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' "${outputPrefix}" '#' 'ID' 'MiB/sec' 'Real time' 'User CPU time' 'System CPU time' 'Raw measurement'
|
||||
thisRound=0
|
||||
while test ${thisRound} -lt "${rounds}"; do
|
||||
thisRound=$((1+thisRound))
|
||||
gatherMeasurements
|
||||
done
|
||||
|
||||
# For each of the types of measurement, report the mean and standard
|
||||
# deviation of each field.
|
||||
awk -F "\t" '{print $1}' < "${workDir}/results" > "${workDir}/measurement-ids"
|
||||
true > "${workDir}/measurement-ids-used"
|
||||
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' "${outputPrefix}" 'μ/σ' 'ID' 'MiB/sec' 'Real time' 'User CPU time' 'System CPU time' 'Aggregated measurement'
|
||||
{
|
||||
while read -r measurementId; do
|
||||
# Skip this type of measurement if already processed.
|
||||
grep -Fqx "${measurementId}" "${workDir}/measurement-ids-used" && continue
|
||||
printf '%s\n' "${measurementId}" >> "${workDir}/measurement-ids-used"
|
||||
# Get the associated measurement name.
|
||||
measurementName="$(printf '%s\n' "${measurementDefinitions}" | awk -F '!' -v "x=${measurementId}" '$1==x{print $2}')"
|
||||
# Separate out this measurement type's results.
|
||||
awk -F "\t" -v "mId=${measurementId}" '$1==mId {print}' < "${workDir}/results" \
|
||||
> "${workDir}/measurements"
|
||||
# Calculate the mean of each field.
|
||||
awk -F "\t" -v "mId=${measurementId}" -v "mName=${measurementName}" -v "fieldcount=${fieldsPerRecord}" \
|
||||
'BEGIN { samples=0 }
|
||||
{ samples++; for (field=1; field<=fieldcount; field++) { total[field] += $(1+field) } }
|
||||
END { printf "%s\t%s", "μ", mId; for (field=1; field<=fieldcount; field++) { printf "\t%.3f", total[field]/samples }; printf "\t%s\n", mName }' \
|
||||
< "${workDir}/measurements" > "${workDir}/mean"
|
||||
# Calculate the standard deviation of each field.
|
||||
cat "${workDir}/mean" "${workDir}/measurements" \
|
||||
| awk -F "\t" -v "mId=${measurementId}" -v "mName=${measurementName}" -v "fieldcount=${fieldsPerRecord}" \
|
||||
'BEGIN { samples=0 }
|
||||
FNR==1 { for (field=1; field<=fieldcount; field++) { mean[field] += $(2+field) } }
|
||||
FNR>1 { samples++; for (field=1; field<=fieldcount; field++) { variance=$(1+field)-mean[field]; sum_variance_squared[field] += (variance*variance) } }
|
||||
END { printf "%s\t%s", "σ", mId; for (field=1; field<=fieldcount; field++) { printf "\t%.3f", sqrt(sum_variance_squared[field]/samples) }; printf "\t%s\n", mName }' \
|
||||
> "${workDir}/stddev"
|
||||
sed "s,^,${outputPrefix}!," "${workDir}/mean" "${workDir}/stddev" | tr '!' '\t'
|
||||
done
|
||||
} < "${workDir}/measurement-ids"
|
||||
rm -f "${workDir}/file1" "${workDir}/file2" "${workDir}/output1" "${workDir}/output2"
|
||||
}
|
||||
|
||||
# Reformat data on stdin so that each (whitespace-separated) column is
|
||||
# space-padded and right-aligned to a consistent width for all rows.
|
||||
#
|
||||
# Note that this can only handle ASCII, not UTF-8.
|
||||
lineUpColumns () {
|
||||
tee "${workDir}/lineup-temp" \
|
||||
| awk 'BEGIN {cols=0}
|
||||
/./ {
|
||||
if (NF > cols)
|
||||
cols=NF
|
||||
for (col=1; col<=NF; col++) {
|
||||
if (length($col) >= max[col])
|
||||
max[col]=length($col)
|
||||
}
|
||||
}
|
||||
END {
|
||||
for (col=1; col<=cols; col++) {
|
||||
printf "%d ", max[col]
|
||||
}
|
||||
printf "\n"
|
||||
}
|
||||
' > "${workDir}/lineup-colwidths"
|
||||
cat "${workDir}/lineup-colwidths" "${workDir}/lineup-temp" \
|
||||
| awk '
|
||||
FNR==1 { cols=NF; for (col=1; col<=NF; col++) { max[col]=$col } }
|
||||
FNR>1 {
|
||||
for (col=1; col<=cols; col++) {
|
||||
if (col>1)
|
||||
printf " "
|
||||
val=(col<=NF ? $col : "")
|
||||
printf "%" max[col] "s", val
|
||||
}
|
||||
printf "\n"
|
||||
}'
|
||||
}
|
||||
|
||||
# Read a stream of benchmark data on stdin containing runs from a single
|
||||
# system, and report how the measurements changed across $1 - either "runs"
|
||||
# for benchmark runs, or "versions" for PV versions.
|
||||
compareResults () {
|
||||
comparisonSelector="$1"
|
||||
cat > "${workDir}/raw-system-data"
|
||||
# List the measurement IDs in the order they appear in the data.
|
||||
awk -F "\t" '$4=="σ"{print $5}' < "${workDir}/raw-system-data" > "${workDir}/measurement-ids"
|
||||
case "${comparisonSelector}" in
|
||||
'versions')
|
||||
# List all PV versions for which any data is available.
|
||||
awk -F "\t" '$4=="PV version"{print $2,$5}' "${workDir}/raw-system-data" | sort -nu > "${workDir}/comparison-items"
|
||||
itemHeading='Version'
|
||||
itemField=2
|
||||
;;
|
||||
'runs')
|
||||
# List all runs.
|
||||
awk -F "\t" '$4=="σ"{print $3,$3}' "${workDir}/raw-system-data" | sort -nu > "${workDir}/comparison-items"
|
||||
itemHeading='Run'
|
||||
itemField=3
|
||||
;;
|
||||
esac
|
||||
# Report on each measurement type in turn.
|
||||
true > "${workDir}/measurement-ids-seen"
|
||||
{
|
||||
measurementsCounter=0
|
||||
while read -r measurementId; do
|
||||
# Skip if this measurement was already processed.
|
||||
grep -Fqx "${measurementId}" "${workDir}/measurement-ids-seen" && continue
|
||||
printf '%s\n' "${measurementId}" >> "${workDir}/measurement-ids-seen"
|
||||
# Collect this measurement's mean and standard deviation
|
||||
# records for each distinct item (version or run). If
|
||||
# there's more than one for a single item, average them.
|
||||
{
|
||||
while read -r itemId itemName; do
|
||||
awk -F "\t" \
|
||||
-v "itemField=${itemField}" -v "itemId=${itemId}" -v "itemName=${itemName}" \
|
||||
-v "mId=${measurementId}" \
|
||||
-v "fieldcount=${fieldsPerRecord}" \
|
||||
'BEGIN {samples=0}
|
||||
$itemField==itemId && $5==mId && $4=="μ" { samples++; for (field=1; field<=fieldcount; field++) { mean[field] += $(5+field) } }
|
||||
$itemField==itemId && $5==mId && $4=="σ" { for (field=1; field<=fieldcount; field++) { stddev[field] += $(5+field) } }
|
||||
END {
|
||||
if (samples > 0) {
|
||||
printf "%s", itemName
|
||||
for (field=1; field<=fieldcount; field++) {
|
||||
printf "\t%.3f\t%.3f", mean[field]/samples, stddev[field]/samples
|
||||
}
|
||||
printf "\n"
|
||||
}
|
||||
}' \
|
||||
< "${workDir}/raw-system-data"
|
||||
done
|
||||
} < "${workDir}/comparison-items" > "${workDir}/measurements-per-item"
|
||||
# If there are not at least 2 items for which this
|
||||
# measurement was available, report nothing as no comparison
|
||||
# can be made.
|
||||
test "$(grep -c . "${workDir}/measurements-per-item")" -lt 2 && continue
|
||||
# Show the measurement name and associated command.
|
||||
# Take the measurement name from the input data.
|
||||
measurementName="$(awk -F "\t" -v "mId=${measurementId}" '$4=="σ" && $5==mId {print $NF;exit}' "${workDir}/raw-system-data")"
|
||||
if ! ${terseFormat}; then
|
||||
# Take the command from the definitions.
|
||||
templateCommand="$(printf '%s\n' "${measurementDefinitions}" | awk -F '!' -v "mId=${measurementId}" '$1==mId {print $5}')"
|
||||
printf '\n%s\n' "${measurementName}"
|
||||
test -n "${templateCommand}" && printf ' (%s)\n' "${templateCommand}"
|
||||
fi
|
||||
# Report each item's measurements and how they compare to
|
||||
# the previous item.
|
||||
awk -F "\t" -v "fieldcount=${fieldsPerRecord}" \
|
||||
'{
|
||||
printf "%s", $1
|
||||
for (field=0; field<fieldcount; field++) {
|
||||
if (field > 0) {
|
||||
printf "\t%s", "-";
|
||||
}
|
||||
mean=$(2+2*field)
|
||||
stddev=$(3+2*field)
|
||||
changescore=0
|
||||
printf "\t%.3f\t%.3f", mean, stddev;
|
||||
if (FNR>1) {
|
||||
low=mean-stddev;
|
||||
high=mean+stddev;
|
||||
range=high-low;
|
||||
prevlow=pmean[field]-pstddev[field];
|
||||
prevhigh=pmean[field]+pstddev[field];
|
||||
prevrange=prevhigh-prevlow;
|
||||
if (prevrange < 1)
|
||||
prevrange = 1;
|
||||
if (high > prevhigh) {
|
||||
changescore = (high - prevhigh) / prevrange;
|
||||
} else if (low < prevlow) {
|
||||
changescore = 0 - ((prevlow - low) / prevrange);
|
||||
}
|
||||
}
|
||||
if (changescore < 0.01 && changescore > -0.01) {
|
||||
printf "\t%d", 0
|
||||
} else {
|
||||
printf "\t%s%.2f", (changescore > 0.00 ? "+" : ""), changescore
|
||||
}
|
||||
pmean[field]=mean;
|
||||
pstddev[field]=stddev;
|
||||
}
|
||||
printf "\n"
|
||||
}' \
|
||||
< "${workDir}/measurements-per-item" \
|
||||
> "${workDir}/item-report"
|
||||
# Leave only the last line if finalLineOnly is set.
|
||||
${finalLineOnly} && sed -i -n '$p' "${workDir}/item-report"
|
||||
# In terse mode, prefix each line with the measurement name,
|
||||
# having replaced spaces in it with underscores.
|
||||
if ${terseFormat}; then
|
||||
showName="$(printf '%s\n' "${measurementName}" | tr ' ' '_')"
|
||||
sed "s,^,${showName}!," < "${workDir}/item-report" | tr '!' '\t' > "${workDir}/item-report.prefixed"
|
||||
mv -f "${workDir}/item-report.prefixed" "${workDir}/item-report"
|
||||
fi
|
||||
# Format the report.
|
||||
# Since the column widths are set by an awk script which
|
||||
# doesn't support UTF-8, ASCII headings are used initially,
|
||||
# and adjusted after formatting.
|
||||
measurementsCounter=$((1+measurementsCounter))
|
||||
{
|
||||
# In terse mode, only print one header per system.
|
||||
if test ${measurementsCounter} -eq 1 || ! ${terseFormat}; then
|
||||
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
|
||||
"${itemHeading}" \
|
||||
'M:Rate' 'S:Rate' 'C:Rate' \
|
||||
'-' \
|
||||
'M:tReal' 'S:tReal' 'C:tReal' \
|
||||
'-' \
|
||||
'M:tUser' 'S:tUser' 'C:tUser' \
|
||||
'-' \
|
||||
'M:tSys' 'S:tSys' 'C:tSys' \
|
||||
| {
|
||||
if ${terseFormat}; then
|
||||
sed 's,^,Measurement!,' | tr '!' '\t'
|
||||
else
|
||||
cat
|
||||
fi
|
||||
}
|
||||
fi
|
||||
cat "${workDir}/item-report"
|
||||
} \
|
||||
> "${workDir}/item-report-with-heading"
|
||||
if ${terseFormat}; then
|
||||
cat "${workDir}/item-report-with-heading"
|
||||
else
|
||||
lineUpColumns < "${workDir}/item-report-with-heading" \
|
||||
| sed '1{s,M:,μ:,g;s,S:,σ:,g;s,C:,±:,g;}'
|
||||
fi
|
||||
done
|
||||
} < "${workDir}/measurement-ids" \
|
||||
> "${workDir}/measurements-report"
|
||||
if "${terseFormat}"; then
|
||||
lineUpColumns < "${workDir}/measurements-report" \
|
||||
| sed '1{s,M:,μ:,g;s,S:,σ:,g;s,C:,±:,g;}'
|
||||
else
|
||||
cat "${workDir}/measurements-report"
|
||||
fi
|
||||
}
|
||||
|
||||
# Read a stream of benchmark data from stdin containing one or more runs
|
||||
# from one or more systems, and for each individual system, report how the
|
||||
# measurements changed across either the different PV versions or between
|
||||
# runs, depending on whether $1 is "versions" or "runs".
|
||||
#
|
||||
# If $1 is "auto", then it will be "versions" if data for more than one PV
|
||||
# version is present, otherwise it will be "runs".
|
||||
runAnalysis () {
|
||||
analysisSelector="$1"
|
||||
cat > "${workDir}/raw-data"
|
||||
# Auto-detect what to analyse.
|
||||
if test "${analysisSelector}" = 'auto'; then
|
||||
if test "$(awk -F "\t" '$4=="σ"{print $2}' < "${workDir}/raw-data" | sort -u | grep -c .)" -gt 1; then
|
||||
analysisSelector='versions'
|
||||
else
|
||||
analysisSelector='runs'
|
||||
fi
|
||||
fi
|
||||
# List the system IDs in the order they appear in the data.
|
||||
awk -F "\t" '{print $1}' < "${workDir}/raw-data" | uniq > "${workDir}/sysids"
|
||||
# Report on each system in turn.
|
||||
true > "${workDir}/sysids-seen"
|
||||
{
|
||||
while read -r sysId; do
|
||||
# Skip if this system was already processed.
|
||||
grep -Fqx "${sysId}" "${workDir}/sysids-seen" && continue
|
||||
printf '%s\n' "${sysId}" >> "${workDir}/sysids-seen"
|
||||
# Extract the data for just this system.
|
||||
awk -F "\t" -v "s=${sysId}" '$1==s {print}' < "${workDir}/raw-data" > "${workDir}/system-data"
|
||||
# Report preamble.
|
||||
printf '%79s\n' '' | tr ' ' '-'
|
||||
printf '%s: %s - %s - %s %s\n' \
|
||||
'System' \
|
||||
"$(awk -F "\t" '$4=="System hostname"{print $5;exit}' "${workDir}/system-data")" \
|
||||
"$(awk -F "\t" '$4=="System OS"{print $5;exit}' "${workDir}/system-data")" \
|
||||
"$(awk -F "\t" '$4=="System kernel type"{print $5;exit}' "${workDir}/system-data")" \
|
||||
"$(awk -F "\t" '$4=="System kernel release"{print $5;exit}' "${workDir}/system-data")"
|
||||
${terseFormat} || cat <<EOF
|
||||
|
||||
For each measurement type, each of its aggregate benchmark results are
|
||||
shown. Each field's mean and standard deviation are displayed along with a
|
||||
change indicator showing how different this line's value is from the
|
||||
previous line.
|
||||
EOF
|
||||
compareResults "${analysisSelector}" < "${workDir}/system-data"
|
||||
done
|
||||
} < "${workDir}/sysids"
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
# Main entry point.
|
||||
|
||||
# Process any command-line options.
|
||||
action='benchmark'
|
||||
restrictMeasurementIdList=''
|
||||
while test -n "$1"; do
|
||||
arg="$1"
|
||||
shift
|
||||
case "${arg}" in
|
||||
'measurements'|'benchmark'|'analyse') action="${arg}" ;;
|
||||
'-h'|'--help')
|
||||
cat - <<EOF
|
||||
Usage: ${programName} [OPTIONS] [ACTION]
|
||||
Benchmark pv transfers - take measurements of transfer rate and CPU usage
|
||||
when calling pv in various different ways, and analyse results from multiple
|
||||
benchmark runs to show how each measurement changes between runs or versions.
|
||||
|
||||
Actions:
|
||||
benchmark - take several rounds of measurements (default action)
|
||||
analyse - analyse benchmark data on stdin from multiple runs
|
||||
measurements - list all benchmark measurement definitions
|
||||
|
||||
Benchmark options:
|
||||
-p, --program FILE benchmark using FILE as the pv executable (${pv})
|
||||
-r, --rounds ROUNDS run ROUNDS sets of measurements (${rounds})
|
||||
-m, --measurement ID only run this specific measurement
|
||||
-s, --size SIZE attempt to use a test file of SIZE MiB (${testFileMB})
|
||||
-z, --zeroes SIZE stop at SIZE MiB for /dev/zero measurements (${testZeroesMB})
|
||||
-d, --dir DIR compile and benchmark each of the tar.gz files in DIR
|
||||
|
||||
Analysis options:
|
||||
-c, --compare WHAT analyse differences in runs, versions, or auto (${compareWhat})
|
||||
-f, --final show only the final item's line in each measurement analysis
|
||||
-t, --terse produce a terser report
|
||||
|
||||
Other options:
|
||||
-h, --help show this help
|
||||
-V, --version show script version
|
||||
|
||||
Default values are shown in brackets.
|
||||
|
||||
Please report any bugs to: ${bugReportsTo}
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
'-V'|'--version')
|
||||
cat - <<EOF
|
||||
${programName} (pv) ${programVersion}
|
||||
Copyright ${copyrightYear} ${copyrightHolder}
|
||||
License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>
|
||||
This is free software: you are free to change and redistribute it.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
'-p'|'--program'|'--pv') pv="$1"; test $# -gt 0 && shift ;;
|
||||
'--program='*|'--pv='*) pv="${arg#*=}" ;;
|
||||
'-r'|'--rounds') rounds="$1"; test $# -gt 0 && shift ;;
|
||||
'--rounds='*) rounds="${arg#*=}" ;;
|
||||
'-m'|'--measurement') restrictMeasurementIdList="${restrictMeasurementIdList} $1"; test $# -gt 0 && shift ;;
|
||||
'--measurement='*) restrictMeasurementIdList="${restrictMeasurementIdList} ${arg#*=}" ;;
|
||||
'-s'|'--size') testFileMB="$1"; test $# -gt 0 && shift ;;
|
||||
'--size='*) testFileMB="${arg#*=}" ;;
|
||||
'-z'|'--zeroes') testZeroesMB="$1"; test $# -gt 0 && shift ;;
|
||||
'--zeroes='*) testZeroesMB="${arg#*=}" ;;
|
||||
'-d'|'--dir') sourcesDir="$1"; test $# -gt 0 && shift ;;
|
||||
'--dir='*) sourcesDir="${arg#*=}" ;;
|
||||
'-c'|'--compare') compareWhat="$1"; test $# -gt 0 && shift ;;
|
||||
'--compare='*) compareWhat="${arg#*=}" ;;
|
||||
'-f'|'--final') finalLineOnly='true' ;;
|
||||
'-t'|'--terse') terseFormat='true' ;;
|
||||
'-'*) die "${arg}: unknown option - try \`--help'" ;;
|
||||
*) die "${arg}: unexpected argument - try \`--help'" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check validity of compareWhat, and normalise it.
|
||||
case "${compareWhat}" in
|
||||
'runs'|'run') compareWhat='runs' ;;
|
||||
'versions'|'version') compareWhat='versions' ;;
|
||||
'auto') ;;
|
||||
*) die "--compare: ${compareWhat}: invalid value" ;;
|
||||
esac
|
||||
|
||||
# Use /dev/shm for workspace if possible, to eliminate disk I/O as a factor.
|
||||
if test -z "${TMPDIR}" && test -d '/dev/shm' && mountpoint -q '/dev/shm'; then
|
||||
TMPDIR='/dev/shm'
|
||||
export TMPDIR
|
||||
fi
|
||||
|
||||
# Temporary working area, cleaned up on exit.
|
||||
workDir="$(mktemp -d)" || exit 1
|
||||
trap 'rm -rf "${workDir}"' EXIT
|
||||
|
||||
# Set everything to the "C" locale.
|
||||
LANG=C
|
||||
LC_ALL=C
|
||||
export LANG LC_ALL
|
||||
|
||||
# Define the measurements.
|
||||
defineMeasurements
|
||||
|
||||
# Run the selected action.
|
||||
case "${action}" in
|
||||
'measurements') showMeasurementDefinitions ;;
|
||||
'benchmark')
|
||||
if test -z "${sourcesDir}"; then
|
||||
runBenchmarks "${pv}" "${restrictMeasurementIdList}"
|
||||
else
|
||||
find "${sourcesDir}" -type f -name "*.tar.gz" \
|
||||
| versionSort \
|
||||
| while read -r sourcesFile; do
|
||||
buildDir="$(mktemp -d "${sourcesFile}.build.XXXXXX")" || continue
|
||||
trap 'rm -rf "${workDir}" "${buildDir}"' EXIT
|
||||
tar xzf "${sourcesFile}" -C "${buildDir}" \
|
||||
&& (
|
||||
cd "${buildDir}"/* \
|
||||
&& sh ./configure 1>&2 \
|
||||
&& make 1>&2 \
|
||||
&& mv pv ..
|
||||
) \
|
||||
&& runBenchmarks "${buildDir}/pv" "${restrictMeasurementIdList}"
|
||||
rm -rf "${buildDir}"
|
||||
trap 'rm -rf "${workDir}"' EXIT
|
||||
done
|
||||
fi
|
||||
;;
|
||||
'analyse') runAnalysis "${compareWhat}" ;;
|
||||
esac
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH PV 1 2025-12-15 pv-1.10.3 "User Commands"
|
||||
.TH PV 1 2026-08-01 pv-1.11.0 "User Commands"
|
||||
.\"
|
||||
.SH NAME
|
||||
pv \- monitor and manage the progress of data through a pipe
|
||||
@@ -13,6 +13,8 @@ pv \- monitor and manage the progress of data through a pipe
|
||||
\fBpv\fR \fB\-R\fR|\fB\-\-remote\fR \fIPID\fR [\fIOPTION\fR]...
|
||||
.PP
|
||||
\fBpv\fR \fB\-Q\fR|\fB\-\-query\fR \fIPID\fR [\fIOPTION\fR]...
|
||||
.PP
|
||||
\fBpv\fR [\fIOPTION\fR]... \fB\-M\fR|\fB\-\-monitor\fR \fISIDE\fR \-\- \fICOMMAND\fR [\fIARGS\fR]...
|
||||
.\"
|
||||
.SH DESCRIPTION
|
||||
Show the progress of data through a pipeline by giving information such as
|
||||
@@ -27,6 +29,9 @@ read.
|
||||
.PP
|
||||
In \*(lq\fB\-\-watchfd\fR\*(rq mode, inspect another process and show its
|
||||
progress through the files it has open.
|
||||
.PP
|
||||
In \*(lq\fB\-\-monitor\fR\*(rq mode, run a command and display the progress
|
||||
of data through both its standard input and its standard output.
|
||||
.\"
|
||||
.SH OPTIONS
|
||||
.\"
|
||||
@@ -121,7 +126,7 @@ for custom output. The default format string components for
|
||||
\*(lq\fB\-\-numeric\fR\*(rq are
|
||||
\*(lq\fB%t\~%b\~%r\~%{progress\-amount\-only}\fR\*(rq in that order, each
|
||||
item being active or inactive according to the rules above (so the default
|
||||
with no other options is \*(lq\fB%{progress\-amount\-only}\fR\*(rq.
|
||||
with no other options is \*(lq\fB%{progress\-amount\-only}\fR\*(rq).
|
||||
.TP
|
||||
.B \-q, \-\-quiet
|
||||
No output.
|
||||
@@ -143,14 +148,13 @@ consistency, specify this option first.
|
||||
.B \-W, \-\-wait
|
||||
Wait until the first byte has been transferred before showing any progress
|
||||
information or calculating any ETAs.
|
||||
Useful if the program you are piping to or from requires extra information
|
||||
before it starts, such as when piping data into \fBgpg\fR(1) or
|
||||
\fBmcrypt\fR(1) which require a passphrase before data can be processed.
|
||||
For example, use this option when piping data into tools such as
|
||||
\fBgpg\fR(1) or \*(lq\fBmysql\~\-p\fR\*(rq so the count only starts after
|
||||
the password prompt has been answered.
|
||||
.TP
|
||||
.BI \-D\ SEC \fR,\ \fB\-\-delay\-start\ SEC
|
||||
Wait until \fISEC\fR seconds have passed before showing any progress
|
||||
information, for example in a script where you only want to show a progress
|
||||
bar if it starts taking a long time.
|
||||
information, so that a transfer that is over quickly won't display anything.
|
||||
The value of \fISEC\fR can be a decimal such as \*(lq0.5\*(rq.
|
||||
.TP
|
||||
.BI \-s\ SIZE \fR,\ \fB\-\-size\ SIZE
|
||||
@@ -162,7 +166,8 @@ If \*(lq\fB\-\-si\fR\*(rq appears before this option, suffixes will denote
|
||||
kilobytes (*1000), megabytes, and so on instead.
|
||||
.IP
|
||||
If \fISIZE\fR starts with \*(lq\fB@\fR\*(rq, the size of file whose name
|
||||
follows the @ will be used.
|
||||
follows the @ will be used; if that is a directory, the size of all files
|
||||
under it will be used, like \*(lq\fBdu\~\-\-apparent\-size\~\-b\fR\*(rq.
|
||||
.TP
|
||||
.B \-g, \-\-gauge
|
||||
If the progress bar is shown but the size is not known, then instead of
|
||||
@@ -196,22 +201,21 @@ The default is 30 seconds.
|
||||
The value must be an integer.
|
||||
.TP
|
||||
.BI \-w\ WIDTH \fR,\ \fB\-\-width\ WIDTH
|
||||
Assume the terminal is \fIWIDTH\fR columns wide, instead of trying to work
|
||||
it out (or assuming 80 if it cannot be guessed).
|
||||
Assume the terminal is \fIWIDTH\fR columns wide, instead of autodetecting
|
||||
the width (or assuming 80 if detection fails).
|
||||
If this option is used, the output width will not be adjusted if the width
|
||||
of the terminal changes while the transfer is running.
|
||||
.TP
|
||||
.BI \-H\ HEIGHT \fR,\ \fB\-\-height\ HEIGHT
|
||||
Assume the terminal is \fIHEIGHT\fR rows high, instead of trying to work it
|
||||
out (or assuming 25 if it cannot be guessed).
|
||||
Assume the terminal is \fIHEIGHT\fR rows high, instead of autodetecting
|
||||
the height (or assuming 25 if detection fails).
|
||||
If this option is used, the output height will not be adjusted if the height
|
||||
of the terminal changes while the transfer is running.
|
||||
.TP
|
||||
.BI \-N\ NAME \fR,\ \fB\-\-name\ NAME
|
||||
Prefix the output information with \fINAME\fR.
|
||||
Useful in conjunction with \*(lq\fB\-\-cursor\fR\*(rq if you have a
|
||||
complicated pipeline and you want to be able to tell different parts of it
|
||||
apart.
|
||||
Often used with \*(lq\fB\-\-cursor\fR\*(rq to identify each progress bar in
|
||||
a pipeline containing more than one \fBpv\fR.
|
||||
.TP
|
||||
.BI \-u\ STYLE \fR,\ \fB\-\-bar\-style\ STYLE
|
||||
Change the default progress bar style shown by \*(lq\fB\-\-progress\fR\*(rq,
|
||||
@@ -234,9 +238,16 @@ For example, \*(lq\fB\-x\~'window,process:%t\~%b\~%r'\fR\*(rq will show the
|
||||
elapsed time, bytes transferred, and rate, in both the window title and the
|
||||
process title.
|
||||
.TP
|
||||
.B \-9, \-\-conemu
|
||||
As well as displaying progress to the terminal, also emit the ConEmu
|
||||
"progress bar" sequences (OSC 9;4) to show the progress percentage in the
|
||||
terminal's title tab, on terminals which support it.
|
||||
This is equivalent to adding \*(lq%{progress\-conemu}\*(rq to the
|
||||
\fB\-\-format\fR string.
|
||||
.TP
|
||||
.B \-v, \-\-stats
|
||||
At the end of the transfer, write an additional line showing the transfer
|
||||
rate minimum, maximum, mean, and standard deviation.
|
||||
rate minimum, mean, maximum, and standard deviation.
|
||||
The values are always in bytes per second (or bits, with
|
||||
\*(lq\fB\-\-bits\fR\*(rq).
|
||||
.TP
|
||||
@@ -247,10 +258,20 @@ not a terminal.
|
||||
This option forces it to do so.
|
||||
.TP
|
||||
.B \-c, \-\-cursor
|
||||
Use cursor positioning escape sequences instead of just using carriage
|
||||
returns.
|
||||
This is useful in conjunction with \*(lq\fB\-\-name\fR\*(rq if you are using
|
||||
multiple \fBpv\fR invocations in a single pipeline.
|
||||
Use cursor positioning escape sequences to move to the initial terminal row
|
||||
when updating the display, instead of only using carriage returns.
|
||||
This allows multiple \fBpv\fR instances to show progress on the same
|
||||
terminal together.
|
||||
.IP
|
||||
For example:
|
||||
.IP
|
||||
.in +4
|
||||
.EX
|
||||
pv --cursor --name input file.gz | gzip -d | pv --cursor --name output > file
|
||||
.EE
|
||||
.in
|
||||
.IP
|
||||
As the example shows, this is often used with \*(lq\fB\-\-name\fR\*(rq.
|
||||
.\"
|
||||
.SS "Data transfer modifiers"
|
||||
.TP
|
||||
@@ -261,6 +282,9 @@ If the file already exists, it will be truncated.
|
||||
.BI \-L\ RATE \fR,\ \fB\-\-rate-limit\ RATE
|
||||
Limit the transfer to a maximum of \fIRATE\fR bytes per second.
|
||||
The same suffixes as \*(lq\fB\-\-size\fR\*(rq can be used.
|
||||
Decimal values are allowed.
|
||||
Specifying 0 will turn off rate limiting, which is useful with
|
||||
\*(lq\fB\-\-remote\fR\*(rq.
|
||||
.TP
|
||||
.BI \-B\ BYTES \fR,\ \fB\-\-buffer-size\ BYTES
|
||||
Use a transfer buffer size of \fIBYTES\fR bytes.
|
||||
@@ -273,17 +297,34 @@ better with specific buffer sizes such as 1024.
|
||||
Implies \*(lq\fB\-\-no\-splice\fR\*(rq.
|
||||
.TP
|
||||
.B \-C, \-\-no-splice
|
||||
Never use \fBsplice\fR(2), even if it would normally be possible.
|
||||
The \fBsplice\fR(2) system call is a more efficient way of transferring data
|
||||
from or to a pipe than regular \fBread\fR(2) and \fBwrite\fR(2), but means
|
||||
that the transfer buffer may not be used.
|
||||
This prevents \*(lq\fB\-\-buffer\-percent\fR\*(rq and
|
||||
\*(lq\fB\-\-last\-written\fR\*(rq from working, cannot work with
|
||||
\*(lq\fB\-\-sparse\fR\*(rq or \*(lq\fB\-\-discard\fR\*(rq, and makes
|
||||
Prevent the use of \fBsplice\fR(2) and \fBcopy_file_range\fR(2), which are
|
||||
normally used on systems that support it to improve efficiency by
|
||||
eliminating the need for a transfer buffer.
|
||||
.IP
|
||||
In the default case that \fBsplice\fR(2) or \fBcopy_file_range\fR(2) are
|
||||
used, the lack of a transfer buffer prevents
|
||||
\*(lq\fB\-\-buffer\-percent\fR\*(rq and
|
||||
\*(lq\fB\-\-last\-written\fR\*(rq from working and makes
|
||||
\*(lq\fB\-\-buffer\-size\fR\*(rq redundant, so using any of those options
|
||||
automatically switches on \*(lq\fB\-\-no\-splice\fR\*(rq.
|
||||
Switching on this option results in a small loss of transfer efficiency.
|
||||
It has no effect on systems where \fBsplice\fR(2) is unavailable.
|
||||
.IP
|
||||
Sparse files cannot be written with \fBsplice\fR(2) or
|
||||
\fBcopy_file_range\fR(2), so using
|
||||
\*(lq\fB\-\-sparse\fR\*(rq automatically switches on
|
||||
\*(lq\fB\-\-no\-splice\fR\*(rq.
|
||||
.IP
|
||||
Switching on \*(lq\fB\-\-no\-splice\fR\*(rq results in a small loss of
|
||||
transfer efficiency.
|
||||
It has no effect on systems where \fBsplice\fR(2) and
|
||||
\fBcopy_file_range\fR(2) are unavailable.
|
||||
.TP
|
||||
.BI \-J\ BYTES \fR,\ \fB\-\-pipe\-buffer\-size\ BYTES
|
||||
Attempt to set the size of the output pipe buffer, and the intermediate
|
||||
input pipe buffer if one is needed, to \fIBYTES\fR bytes.
|
||||
This will silently do nothing if the requested size cannot be achieved.
|
||||
If this option is not specified, and both the output and the first input are
|
||||
pipes, then the output pipe buffer size will automatically be increased to
|
||||
match the input pipe buffer, if it was smaller.
|
||||
.TP
|
||||
.B \-E, \-\-skip-errors
|
||||
Ignore read errors by attempting to skip past the offending sections.
|
||||
@@ -318,7 +359,7 @@ end of input.
|
||||
.TP
|
||||
.B \-Y, \-\-sync
|
||||
After every write operation, synchronise the buffer caches to disk with
|
||||
\fBfdatasync\fR(2).
|
||||
\fBsync\fR(2), or \fBfdatasync\fR(2) if possible.
|
||||
This has no effect when the output is a pipe.
|
||||
Using \*(lq\fB\-\-sync\fR\*(rq may improve the accuracy of the progress bar
|
||||
when writing to a slow disk.
|
||||
@@ -342,7 +383,6 @@ seekable, this option will have no effect other than to turn on
|
||||
Instead of transferring input data to standard output, discard it.
|
||||
This is equivalent to redirecting standard output to \fI/dev/null\fR,
|
||||
except that \fBwrite\fR(2) is never called.
|
||||
Implies \*(lq\fB\-\-no\-splice\fR\*(rq.
|
||||
.TP
|
||||
.BI \-U\ FILE \fR,\ \fB\-\-store\-and\-forward\ FILE
|
||||
Instead of passing data through immediately, do it in two stages - first
|
||||
@@ -352,13 +392,11 @@ exhausted, read all of \fIFILE\fR and write it to the output.
|
||||
\*(lq\fB-\fR\*(rq, in which case \fBpv\fR creates a temporary file for this
|
||||
purpose, and automatically removes it afterwards.
|
||||
.IP
|
||||
This can be useful if you have a pipeline which generates data (your
|
||||
input) quickly but you don't know the size, and you wish to pass it to some
|
||||
slower process, once all of the input has been generated and you know its
|
||||
size, so you can see its progress.
|
||||
Note that when doing this with relatively small amounts of data,
|
||||
\*(lq\fB\-\-no-splice\fR\*(rq may be preferable so that pipe buffering
|
||||
doesn't affect the progress display.
|
||||
A common use for this is this where one part of a pipeline generates data
|
||||
quickly but of unknown size, and the next part processes it slowly.
|
||||
With \*(lq\fIquick\fR\~\fB|\~pv\~\-U\~\-\~|\fR\~\fIslow\fR\*(rq, a progress
|
||||
bar is displayed with unknown size for the \fIquick\fR part, then a second
|
||||
is shown with a known size and ETA for the \fIslow\fR part.
|
||||
.\"
|
||||
.\"
|
||||
.SS "Alternative operating modes"
|
||||
@@ -408,6 +446,37 @@ they match those of that process - such as
|
||||
\*(lq\fB\-\-null\fR\*(rq, and
|
||||
\*(lq\fB\-\-average\-rate\-window\fR\*(rq.
|
||||
Data transfer modifiers will have no effect.
|
||||
.TP
|
||||
.BR \-M " \fISIDE\fR, " \-\-monitor " \fISIDE\fR"
|
||||
Run the command specified by the remaining arguments, and monitor its
|
||||
standard input, its standard output, or both, depending on whether
|
||||
\fISIDE\fR is \*(lq\fBin\fR\*(rq, \*(lq\fBout\fR\*(rq, or
|
||||
\*(lq\fBboth\fR\*(rq.
|
||||
Use \*(lq\fB\-\-\fR\*(rq after all of the \fBpv\fR options to keep the
|
||||
monitored command's options separate.
|
||||
.IP
|
||||
With a \fISIDE\fR of \*(lq\fBboth\fR\*(rq, two progress bars will be shown.
|
||||
All of \fBpv\fR's display switches, output modifiers, and data transfer
|
||||
modifiers will apply to both sides.
|
||||
.IP
|
||||
For example,
|
||||
\*(lq\fBpv\~\-\-cursor\~\-\-monitor\~both\~\-\-\~gzip\~\-9\fR\*(rq is
|
||||
equivalent to
|
||||
\*(lq\fBpv\~\-\-cursor\~|\~gzip\~\-9\~|\~pv\~\-\-cursor\fR\*(rq, except that
|
||||
the latter can't show the input:output ratio.
|
||||
.IP
|
||||
The \*(lq\fB\-\-format\fR\*(rq and \*(lq\fB\-\-name\fR\*(rq options may be
|
||||
specified twice, in which case the first one applies to the input side and
|
||||
the second applies to the output side.
|
||||
If no \*(lq\fB\-\-format\fR\*(rq options are specified, the default format
|
||||
based on the other display switches is used as normal, except that the
|
||||
ratio is added to the output side when \fISIDE\fR is \*(lq\fBboth\fR\*(rq.
|
||||
.IP
|
||||
The values \*(lq\fB0\fR\*(rq, \*(lq\fB1\fR\*(rq, and \*(lq\fB2\fR\*(rq may
|
||||
be used as synonyms for \*(lq\fBin\fR\*(rq, \*(lq\fBout\fR\*(rq, and
|
||||
\*(lq\fBboth\fR\*(rq.
|
||||
.IP
|
||||
This option cannot be used with \*(lq\fB\-\-store\-and\-forward\*(rq.
|
||||
.\"
|
||||
.SS "Other options"
|
||||
.TP
|
||||
@@ -443,6 +512,10 @@ Expands to fill the remaining space unless prefixed by a number.
|
||||
The percentage completion (or maximum rate, with \*(lq\fB\-\-gauge\fR\*(rq
|
||||
when the size is unknown).
|
||||
.TP
|
||||
.B %{progress-conemu}
|
||||
Emit the ConEmu "progress bar" sequences (OSC 9;4) to show the progress
|
||||
percentage in the terminal's title tab, on terminals which support it.
|
||||
.TP
|
||||
.B %{bar\-plain}
|
||||
Progress bar in the standard plain format, without any sides, and without
|
||||
any percentage displayed afterwards.
|
||||
@@ -497,23 +570,32 @@ Equivalent to \*(lq\fB\-\-bytes\fR\*(rq.
|
||||
If \*(lq\fB\-\-bits\fR\*(rq was specified, \*(lq\fB%b\fR\*(rq shows the bits
|
||||
transferred so far, not bytes.
|
||||
.TP
|
||||
.B %{ratio}
|
||||
Show the ratio of bytes transferred by the other side to the bytes
|
||||
transferred by this side, in \*(lq\fB\-\-monitor\~both\fR\*(rq mode.
|
||||
.TP
|
||||
.BR %T ", " %{buffer\-percent}
|
||||
Percentage of the transfer buffer in use.
|
||||
Equivalent to \*(lq\fB\-\-buffer\-percent\fR\*(rq.
|
||||
Displays \*(lq{\-\-\-\-}\*(rq if the transfer is being done with
|
||||
\fBsplice\fR(2), since splicing to or from pipes does not use the buffer.
|
||||
Equivalent to \*(lq\fB\-\-buffer\-percent\fR\*(rq, but using it does not
|
||||
turn on \*(lq\fB\-\-no\-splice\fR\*(rq.
|
||||
.IP
|
||||
If the transfer is using \fBsplice\fR(2), displays \*(lq{\-\-\-\-}\*(rq; if
|
||||
the transfer is using \fBsplice\fR(2) via an intermediate input pipe,
|
||||
displays \*(lq{\-||\-}\*(rq; and if the transfer is using
|
||||
\fBcopy_file_range\fR(2), displays \*(lq{\-\-\->}\*(rq.
|
||||
.TP
|
||||
.BR %nA ", " %n{last\-written}
|
||||
Show the last \fIn\fR bytes written (for example, \*(lq\fB%16A\fR\*(rq shows
|
||||
the last 16 bytes).
|
||||
Shows only dots if the transfer is being done with \fBsplice\fR(2), since
|
||||
splicing to or from pipes does not use the buffer.
|
||||
Shows only dots if the transfer is using \fBsplice\fR(2) or
|
||||
\fBcopy_file_range\fR(2), since these transfer modes do not use the buffer.
|
||||
.TP
|
||||
.BR %nL ", " %n{previous\-line}
|
||||
Show the first \fIn\fR bytes of the most recently written line (for example,
|
||||
\*(lq\fB%40L\fR\*(rq shows the first 40 bytes).
|
||||
If no \fIn\fR is given, then this expands to fill the available space.
|
||||
Shows only spaces if the transfer is being done with \fBsplice\fR(2).
|
||||
Shows only spaces if the transfer is using \fBsplice\fR(2) or
|
||||
\fBcopy_file_range\fR(2).
|
||||
.TP
|
||||
.BR %N ", " %{name}
|
||||
Show the name prefix given by \*(lq\fB\-\-name\fR\*(rq.
|
||||
@@ -604,6 +686,11 @@ Show only the elapsed time - useful as a simple timer, such as
|
||||
.B pv \-pterb
|
||||
The default behaviour: progress bar, elapsed time, estimated completion
|
||||
time, current rate, and byte counter.
|
||||
.TP
|
||||
.B pv \-\-format='%{progress-conemu}%{bytes} %{timer} %{rate} %{progress} %{eta}'
|
||||
Show the byte counter, elapsed time, current rate, progress bar, and ETA,
|
||||
and show the percentage progress in the terminal's tab bar, on terminals
|
||||
that support ConEmu OSC 9;4 sequences.
|
||||
.PP
|
||||
On macOS, it may be useful to specify \*(lq\fB\-\-buffer\-size\~1024\fR\*(rq
|
||||
in a pipeline, as this may improve performance.
|
||||
@@ -636,6 +723,17 @@ tar cf \- directory/ \e
|
||||
.EE
|
||||
.in
|
||||
.PP
|
||||
An alternative way of doing the same thing:
|
||||
.PP
|
||||
.in +4
|
||||
.EX
|
||||
tar cf \- directory/ \e
|
||||
| pv \-\-size @directory/ \e
|
||||
| gzip \-9 \e
|
||||
> out.tar.gz
|
||||
.EE
|
||||
.in
|
||||
.PP
|
||||
Taking an image of a disk, skipping errors:
|
||||
.PP
|
||||
.in +4
|
||||
@@ -695,7 +793,7 @@ the progress display:
|
||||
.PP
|
||||
.in +4
|
||||
.EX
|
||||
pv \-\-format '%a %p : %L' big.log | processing-script
|
||||
pv \-\-no\-splice \-\-format '%a %p : %L' big.log | processing-script
|
||||
.EE
|
||||
.in
|
||||
.PP
|
||||
@@ -709,7 +807,8 @@ pv \-\-numeric \-\-format '{"elapsed":%t,"bytes":%b,"rate":%r,"percentage":%{pro
|
||||
.\"
|
||||
.SH EXIT STATUS
|
||||
An exit status of 1 indicates a problem with the \*(lq\fB\-\-remote\fR\*(rq,
|
||||
\*(lq\fB\-\-query\fR\*(rq, or \*(lq\fB\-\-pidfile\fR\*(rq options.
|
||||
\*(lq\fB\-\-query\fR\*(rq, \*(lq\fB\-\-pidfile\fR\*(rq, or
|
||||
\*(lq\fB\-\-monitor\fR\*(rq options.
|
||||
.PP
|
||||
Any other exit status is a bitmask of the following:
|
||||
.TP 5
|
||||
@@ -803,11 +902,14 @@ The \*(lq\fB%nA\fR\*(rq and \*(lq\fB%nL\fR\*(rq format sequences may not be
|
||||
effective with small input files, and \*(lq\fB%nL\fR\*(rq may be a few lines
|
||||
out due to buffering within the pipeline itself.
|
||||
.PP
|
||||
Numbers passed to \*(lq\fB\-\-size\fR\*(rq, \*(lq\fB\-\-rate\-limit\fR\*(rq,
|
||||
\*(lq\fB\-\-buffer\-size\fR\*(rq, and \*(lq\fB\-\-error\-skip\-block\fR\*(rq
|
||||
may all be expressed as decimals if followed by a suffix, so for example
|
||||
\*(lq\fI\-\-size\~1.5G\fR\*(rq is equivalent to
|
||||
\*(lq\fI\-\-size\~1536M\fR\*(rq.
|
||||
Numbers passed to \*(lq\fB\-\-size\fR\*(rq,
|
||||
\*(lq\fB\-\-buffer\-size\fR\*(rq, \*(lq\fB\-\-pipe\-buffer\-size\fR\*(rq,
|
||||
and \*(lq\fB\-\-error\-skip\-block\fR\*(rq may all be expressed as decimals
|
||||
if followed by a suffix, so for example \*(lq\fI\-\-size\~1.5G\fR\*(rq is
|
||||
equivalent to \*(lq\fI\-\-size\~1536M\fR\*(rq.
|
||||
.PP
|
||||
Numbers passed to \*(lq\fB\-\-rate\-limit\fR\*(rq may be expressed as
|
||||
decimals with or without a suffix.
|
||||
.PP
|
||||
Numbers passed to \*(lq\fB\-\-interval\fR\*(rq and
|
||||
\*(lq\fB\-\-delay\-start\fR\*(rq may be integers or decimals, but may not
|
||||
@@ -834,13 +936,15 @@ Please report bugs or feature requests via the issue tracker linked from the
|
||||
.SH "SEE ALSO"
|
||||
.BR cat (1),
|
||||
.BR splice (2),
|
||||
.BR copy_file_range (2),
|
||||
.BR fsync (2),
|
||||
.BR fdatasync (2),
|
||||
.BR open (2)
|
||||
(for \fBO_DIRECT\fR),
|
||||
.BR console_codes (4)
|
||||
.\"
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood.
|
||||
Copyright \(co 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood.
|
||||
.PP
|
||||
License GPLv3+:
|
||||
.UR https://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
+156
-60
@@ -13,6 +13,9 @@ pv - monitor and manage the progress of data through a pipe
|
||||
|
||||
**pv** **-Q**\|**\--query** *PID* \[*OPTION*\]\...
|
||||
|
||||
**pv** \[*OPTION*\]\... **-M**\|**\--monitor** *SIDE* \-- *COMMAND*
|
||||
[*ARGS*\]\...
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
Show the progress of data through a pipeline by giving information such
|
||||
@@ -27,6 +30,9 @@ is "-", standard input is read.
|
||||
In "**\--watchfd**" mode, inspect another process and show its progress
|
||||
through the files it has open.
|
||||
|
||||
In "**\--monitor**" mode, run a command and display the progress of data
|
||||
through both its standard input and its standard output.
|
||||
|
||||
# OPTIONS
|
||||
|
||||
## Display switches
|
||||
@@ -120,7 +126,7 @@ are explicitly switched on will be shown.
|
||||
output. The default format string components for "**\--numeric**"
|
||||
are "**%t %b %r %{progress-amount-only}**" in that order, each item
|
||||
being active or inactive according to the rules above (so the
|
||||
default with no other options is "**%{progress-amount-only}**".
|
||||
default with no other options is "**%{progress-amount-only}**").
|
||||
|
||||
**-q, \--quiet**
|
||||
|
||||
@@ -143,17 +149,16 @@ are explicitly switched on will be shown.
|
||||
**-W, \--wait**
|
||||
|
||||
: Wait until the first byte has been transferred before showing any
|
||||
progress information or calculating any ETAs. Useful if the program
|
||||
you are piping to or from requires extra information before it
|
||||
starts, such as when piping data into **gpg**(1) or **mcrypt**(1)
|
||||
which require a passphrase before data can be processed.
|
||||
progress information or calculating any ETAs. For example, use this
|
||||
option when piping data into tools such as **gpg**(1) or
|
||||
"**mysql -p**" so the count only starts after the password prompt
|
||||
has been answered.
|
||||
|
||||
**-D SEC, \--delay-start SEC**
|
||||
|
||||
: Wait until *SEC* seconds have passed before showing any progress
|
||||
information, for example in a script where you only want to show a
|
||||
progress bar if it starts taking a long time. The value of *SEC* can
|
||||
be a decimal such as "0.5".
|
||||
information, so that a transfer that is over quickly won\'t display
|
||||
anything. The value of *SEC* can be a decimal such as "0.5".
|
||||
|
||||
**-s SIZE, \--size SIZE**
|
||||
|
||||
@@ -164,7 +169,8 @@ are explicitly switched on will be shown.
|
||||
denote kilobytes (\*1000), megabytes, and so on instead.
|
||||
|
||||
If *SIZE* starts with "**@**", the size of file whose name follows
|
||||
the @ will be used.
|
||||
the @ will be used; if that is a directory, the size of all files
|
||||
under it will be used, like "**du \--apparent-size -b**".
|
||||
|
||||
**-g, \--gauge**
|
||||
|
||||
@@ -202,23 +208,23 @@ are explicitly switched on will be shown.
|
||||
|
||||
**-w WIDTH, \--width WIDTH**
|
||||
|
||||
: Assume the terminal is *WIDTH* columns wide, instead of trying to
|
||||
work it out (or assuming 80 if it cannot be guessed). If this option
|
||||
is used, the output width will not be adjusted if the width of the
|
||||
terminal changes while the transfer is running.
|
||||
: Assume the terminal is *WIDTH* columns wide, instead of
|
||||
autodetecting the width (or assuming 80 if detection fails). If this
|
||||
option is used, the output width will not be adjusted if the width
|
||||
of the terminal changes while the transfer is running.
|
||||
|
||||
**-H HEIGHT, \--height HEIGHT**
|
||||
|
||||
: Assume the terminal is *HEIGHT* rows high, instead of trying to work
|
||||
it out (or assuming 25 if it cannot be guessed). If this option is
|
||||
: Assume the terminal is *HEIGHT* rows high, instead of autodetecting
|
||||
the height (or assuming 25 if detection fails). If this option is
|
||||
used, the output height will not be adjusted if the height of the
|
||||
terminal changes while the transfer is running.
|
||||
|
||||
**-N NAME, \--name NAME**
|
||||
|
||||
: Prefix the output information with *NAME*. Useful in conjunction
|
||||
with "**\--cursor**" if you have a complicated pipeline and you want
|
||||
to be able to tell different parts of it apart.
|
||||
: Prefix the output information with *NAME*. Often used with
|
||||
"**\--cursor**" to identify each progress bar in a pipeline
|
||||
containing more than one **pv**.
|
||||
|
||||
**-u STYLE, \--bar-style STYLE**
|
||||
|
||||
@@ -242,10 +248,18 @@ are explicitly switched on will be shown.
|
||||
bytes transferred, and rate, in both the window title and the
|
||||
process title.
|
||||
|
||||
**-9, \--conemu**
|
||||
|
||||
: As well as displaying progress to the terminal, also emit the ConEmu
|
||||
\"progress bar\" sequences (OSC 9;4) to show the progress percentage
|
||||
in the terminal\'s title tab, on terminals which support it. This is
|
||||
equivalent to adding "%{progress-conemu}" to the **\--format**
|
||||
string.
|
||||
|
||||
**-v, \--stats**
|
||||
|
||||
: At the end of the transfer, write an additional line showing the
|
||||
transfer rate minimum, maximum, mean, and standard deviation. The
|
||||
transfer rate minimum, mean, maximum, and standard deviation. The
|
||||
values are always in bytes per second (or bits, with "**\--bits**").
|
||||
|
||||
**-f, \--force**
|
||||
@@ -255,9 +269,16 @@ are explicitly switched on will be shown.
|
||||
|
||||
**-c, \--cursor**
|
||||
|
||||
: Use cursor positioning escape sequences instead of just using
|
||||
carriage returns. This is useful in conjunction with "**\--name**"
|
||||
if you are using multiple **pv** invocations in a single pipeline.
|
||||
: Use cursor positioning escape sequences to move to the initial
|
||||
terminal row when updating the display, instead of only using
|
||||
carriage returns. This allows multiple **pv** instances to show
|
||||
progress on the same terminal together.
|
||||
|
||||
For example:
|
||||
|
||||
pv --cursor --name input file.gz | gzip -d | pv --cursor --name output > file
|
||||
|
||||
As the example shows, this is often used with "**\--name**".
|
||||
|
||||
## Data transfer modifiers
|
||||
|
||||
@@ -269,7 +290,9 @@ are explicitly switched on will be shown.
|
||||
**-L RATE, \--rate-limit RATE**
|
||||
|
||||
: Limit the transfer to a maximum of *RATE* bytes per second. The same
|
||||
suffixes as "**\--size**" can be used.
|
||||
suffixes as "**\--size**" can be used. Decimal values are allowed.
|
||||
Specifying 0 will turn off rate limiting, which is useful with
|
||||
"**\--remote**".
|
||||
|
||||
**-B BYTES, \--buffer-size BYTES**
|
||||
|
||||
@@ -282,16 +305,33 @@ are explicitly switched on will be shown.
|
||||
|
||||
**-C, \--no-splice**
|
||||
|
||||
: Never use **splice**(2), even if it would normally be possible. The
|
||||
**splice**(2) system call is a more efficient way of transferring
|
||||
data from or to a pipe than regular **read**(2) and **write**(2),
|
||||
but means that the transfer buffer may not be used. This prevents
|
||||
"**\--buffer-percent**" and "**\--last-written**" from working,
|
||||
cannot work with "**\--sparse**" or "**\--discard**", and makes
|
||||
: Prevent the use of **splice**(2) and **copy_file_range**(2), which
|
||||
are normally used on systems that support it to improve efficiency
|
||||
by eliminating the need for a transfer buffer.
|
||||
|
||||
In the default case that **splice**(2) or **copy_file_range**(2) are
|
||||
used, the lack of a transfer buffer prevents "**\--buffer-percent**"
|
||||
and "**\--last-written**" from working and makes
|
||||
"**\--buffer-size**" redundant, so using any of those options
|
||||
automatically switches on "**\--no-splice**". Switching on this
|
||||
option results in a small loss of transfer efficiency. It has no
|
||||
effect on systems where **splice**(2) is unavailable.
|
||||
automatically switches on "**\--no-splice**".
|
||||
|
||||
Sparse files cannot be written with **splice**(2) or
|
||||
**copy_file_range**(2), so using "**\--sparse**" automatically
|
||||
switches on "**\--no-splice**".
|
||||
|
||||
Switching on "**\--no-splice**" results in a small loss of transfer
|
||||
efficiency. It has no effect on systems where **splice**(2) and
|
||||
**copy_file_range**(2) are unavailable.
|
||||
|
||||
**-J BYTES, \--pipe-buffer-size BYTES**
|
||||
|
||||
: Attempt to set the size of the output pipe buffer, and the
|
||||
intermediate input pipe buffer if one is needed, to *BYTES* bytes.
|
||||
This will silently do nothing if the requested size cannot be
|
||||
achieved. If this option is not specified, and both the output and
|
||||
the first input are pipes, then the output pipe buffer size will
|
||||
automatically be increased to match the input pipe buffer, if it was
|
||||
smaller.
|
||||
|
||||
**-E, \--skip-errors**
|
||||
|
||||
@@ -329,9 +369,9 @@ are explicitly switched on will be shown.
|
||||
**-Y, \--sync**
|
||||
|
||||
: After every write operation, synchronise the buffer caches to disk
|
||||
with **fdatasync**(2). This has no effect when the output is a pipe.
|
||||
Using "**\--sync**" may improve the accuracy of the progress bar
|
||||
when writing to a slow disk.
|
||||
with **sync**(2), or **fdatasync**(2) if possible. This has no
|
||||
effect when the output is a pipe. Using "**\--sync**" may improve
|
||||
the accuracy of the progress bar when writing to a slow disk.
|
||||
|
||||
**-K, \--direct-io**
|
||||
|
||||
@@ -353,8 +393,7 @@ are explicitly switched on will be shown.
|
||||
|
||||
: Instead of transferring input data to standard output, discard it.
|
||||
This is equivalent to redirecting standard output to */dev/null*,
|
||||
except that **write**(2) is never called. Implies
|
||||
"**\--no-splice**".
|
||||
except that **write**(2) is never called.
|
||||
|
||||
**-U FILE, \--store-and-forward FILE**
|
||||
|
||||
@@ -365,13 +404,11 @@ are explicitly switched on will be shown.
|
||||
**pv** creates a temporary file for this purpose, and automatically
|
||||
removes it afterwards.
|
||||
|
||||
This can be useful if you have a pipeline which generates data (your
|
||||
input) quickly but you don\'t know the size, and you wish to pass it
|
||||
to some slower process, once all of the input has been generated and
|
||||
you know its size, so you can see its progress. Note that when doing
|
||||
this with relatively small amounts of data, "**\--no-splice**" may
|
||||
be preferable so that pipe buffering doesn\'t affect the progress
|
||||
display.
|
||||
A common use for this is this where one part of a pipeline generates
|
||||
data quickly but of unknown size, and the next part processes it
|
||||
slowly. With "*quick* **\| pv -U - \|** *slow*", a progress bar is
|
||||
displayed with unknown size for the *quick* part, then a second is
|
||||
shown with a known size and ETA for the *slow* part.
|
||||
|
||||
## Alternative operating modes
|
||||
|
||||
@@ -422,6 +459,34 @@ are explicitly switched on will be shown.
|
||||
"**\--line-mode**", "**\--null**", and "**\--average-rate-window**".
|
||||
Data transfer modifiers will have no effect.
|
||||
|
||||
**-M** *SIDE*, **\--monitor** *SIDE*
|
||||
|
||||
: Run the command specified by the remaining arguments, and monitor
|
||||
its standard input, its standard output, or both, depending on
|
||||
whether *SIDE* is "**in**", "**out**", or "**both**". Use "**\--**"
|
||||
after all of the **pv** options to keep the monitored command\'s
|
||||
options separate.
|
||||
|
||||
With a *SIDE* of "**both**", two progress bars will be shown. All of
|
||||
**pv**\'s display switches, output modifiers, and data transfer
|
||||
modifiers will apply to both sides.
|
||||
|
||||
For example, "**pv \--cursor \--monitor both \-- gzip -9**" is
|
||||
equivalent to "**pv \--cursor \| gzip -9 \| pv \--cursor**", except
|
||||
that the latter can\'t show the input:output ratio.
|
||||
|
||||
The "**\--format**" and "**\--name**" options may be specified
|
||||
twice, in which case the first one applies to the input side and the
|
||||
second applies to the output side. If no "**\--format**" options are
|
||||
specified, the default format based on the other display switches is
|
||||
used as normal, except that the ratio is added to the output side
|
||||
when *SIDE* is "**both**".
|
||||
|
||||
The values "**0**", "**1**", and "**2**" may be used as synonyms for
|
||||
"**in**", "**out**", and "**both**".
|
||||
|
||||
This option cannot be used with "**\--store-and-forward".**
|
||||
|
||||
## Other options
|
||||
|
||||
**-P FILE, \--pidfile FILE**
|
||||
@@ -462,6 +527,12 @@ contain the following sequences:
|
||||
: The percentage completion (or maximum rate, with "**\--gauge**" when
|
||||
the size is unknown).
|
||||
|
||||
**%{progress-conemu}**
|
||||
|
||||
: Emit the ConEmu \"progress bar\" sequences (OSC 9;4) to show the
|
||||
progress percentage in the terminal\'s title tab, on terminals which
|
||||
support it.
|
||||
|
||||
**%{bar-plain}**
|
||||
|
||||
: Progress bar in the standard plain format, without any sides, and
|
||||
@@ -521,26 +592,35 @@ contain the following sequences:
|
||||
specified). Equivalent to "**\--bytes**". If "**\--bits**" was
|
||||
specified, "**%b**" shows the bits transferred so far, not bytes.
|
||||
|
||||
**%{ratio}**
|
||||
|
||||
: Show the ratio of bytes transferred by the other side to the bytes
|
||||
transferred by this side, in "**\--monitor both**" mode.
|
||||
|
||||
**%T**, **%{buffer-percent}**
|
||||
|
||||
: Percentage of the transfer buffer in use. Equivalent to
|
||||
"**\--buffer-percent**". Displays "{\-\-\--}" if the transfer is
|
||||
being done with **splice**(2), since splicing to or from pipes does
|
||||
not use the buffer.
|
||||
"**\--buffer-percent**", but using it does not turn on
|
||||
"**\--no-splice**".
|
||||
|
||||
If the transfer is using **splice**(2), displays "{\-\-\--}"; if the
|
||||
transfer is using **splice**(2) via an intermediate input pipe,
|
||||
displays "{-\|\|-}"; and if the transfer is using
|
||||
**copy_file_range**(2), displays "{\-\--\>}".
|
||||
|
||||
**%nA**, **%n{last-written}**
|
||||
|
||||
: Show the last *n* bytes written (for example, "**%16A**" shows the
|
||||
last 16 bytes). Shows only dots if the transfer is being done with
|
||||
**splice**(2), since splicing to or from pipes does not use the
|
||||
buffer.
|
||||
last 16 bytes). Shows only dots if the transfer is using
|
||||
**splice**(2) or **copy_file_range**(2), since these transfer modes
|
||||
do not use the buffer.
|
||||
|
||||
**%nL**, **%n{previous-line}**
|
||||
|
||||
: Show the first *n* bytes of the most recently written line (for
|
||||
example, "**%40L**" shows the first 40 bytes). If no *n* is given,
|
||||
then this expands to fill the available space. Shows only spaces if
|
||||
the transfer is being done with **splice**(2).
|
||||
the transfer is using **splice**(2) or **copy_file_range**(2).
|
||||
|
||||
**%N**, **%{name}**
|
||||
|
||||
@@ -613,6 +693,12 @@ Some suggested common switch combinations:
|
||||
: The default behaviour: progress bar, elapsed time, estimated
|
||||
completion time, current rate, and byte counter.
|
||||
|
||||
**pv \--format=\'%{progress-conemu}%{bytes} %{timer} %{rate} %{progress} %{eta}\'**
|
||||
|
||||
: Show the byte counter, elapsed time, current rate, progress bar, and
|
||||
ETA, and show the percentage progress in the terminal\'s tab bar, on
|
||||
terminals that support ConEmu OSC 9;4 sequences.
|
||||
|
||||
On macOS, it may be useful to specify "**\--buffer-size 1024**" in a
|
||||
pipeline, as this may improve performance.
|
||||
|
||||
@@ -632,6 +718,13 @@ To watch the progress of creating a tar.gz archive:
|
||||
| gzip -9 \
|
||||
> out.tar.gz
|
||||
|
||||
An alternative way of doing the same thing:
|
||||
|
||||
tar cf - directory/ \
|
||||
| pv --size @directory/ \
|
||||
| gzip -9 \
|
||||
> out.tar.gz
|
||||
|
||||
Taking an image of a disk, skipping errors:
|
||||
|
||||
pv -EE /dev/your/disk/device > disk-image.img
|
||||
@@ -667,7 +760,7 @@ display:
|
||||
Sending logs to a processing script, showing the most recent line as
|
||||
part of the progress display:
|
||||
|
||||
pv --format '%a %p : %L' big.log | processing-script
|
||||
pv --no-splice --format '%a %p : %L' big.log | processing-script
|
||||
|
||||
Showing progress as lines of JSON data:
|
||||
|
||||
@@ -676,7 +769,7 @@ Showing progress as lines of JSON data:
|
||||
# EXIT STATUS
|
||||
|
||||
An exit status of 1 indicates a problem with the "**\--remote**",
|
||||
"**\--query**", or "**\--pidfile**" options.
|
||||
"**\--query**", "**\--pidfile**", or "**\--monitor**" options.
|
||||
|
||||
Any other exit status is a bitmask of the following:
|
||||
|
||||
@@ -766,10 +859,13 @@ The "**%nA**" and "**%nL**" format sequences may not be effective with
|
||||
small input files, and "**%nL**" may be a few lines out due to buffering
|
||||
within the pipeline itself.
|
||||
|
||||
Numbers passed to "**\--size**", "**\--rate-limit**",
|
||||
"**\--buffer-size**", and "**\--error-skip-block**" may all be expressed
|
||||
as decimals if followed by a suffix, so for example "*\--size 1.5G*" is
|
||||
equivalent to "*\--size 1536M*".
|
||||
Numbers passed to "**\--size**", "**\--buffer-size**",
|
||||
"**\--pipe-buffer-size**", and "**\--error-skip-block**" may all be
|
||||
expressed as decimals if followed by a suffix, so for example
|
||||
"*\--size 1.5G*" is equivalent to "*\--size 1536M*".
|
||||
|
||||
Numbers passed to "**\--rate-limit**" may be expressed as decimals with
|
||||
or without a suffix.
|
||||
|
||||
Numbers passed to "**\--interval**" and "**\--delay-start**" may be
|
||||
integers or decimals, but may not have a suffix.
|
||||
@@ -791,12 +887,12 @@ the [**pv** home page](https://ivarch.com/p/pv).
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
**cat**(1), **splice**(2), **fdatasync**(2), **open**(2) (for
|
||||
**O_DIRECT**), **console_codes**(4)
|
||||
**cat**(1), **splice**(2), **copy_file_range**(2), **fsync**(2),
|
||||
**fdatasync**(2), **open**(2) (for **O_DIRECT**), **console_codes**(4)
|
||||
|
||||
# COPYRIGHT
|
||||
|
||||
Copyright © 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew
|
||||
Copyright © 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew
|
||||
Wood.
|
||||
|
||||
License GPLv3+: [GNU GPL version 3 or
|
||||
|
||||
@@ -7,3 +7,4 @@ Makevars.template
|
||||
Rules-quot
|
||||
stamp-po
|
||||
*~
|
||||
Makefile.in.in
|
||||
|
||||
+2
-1
@@ -1,10 +1,11 @@
|
||||
cs
|
||||
de
|
||||
es
|
||||
fi
|
||||
fr
|
||||
it
|
||||
ka
|
||||
pl
|
||||
pt
|
||||
ro
|
||||
ru
|
||||
tr
|
||||
|
||||
@@ -1,510 +0,0 @@
|
||||
# Makefile for PO directory in any package using GNU gettext.
|
||||
# Copyright (C) 1995-2000 Ulrich Drepper <drepper@gnu.ai.mit.edu>
|
||||
# Copyright (C) 2000-2020 Free Software Foundation, Inc.
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification,
|
||||
# are permitted in any medium without royalty provided the copyright
|
||||
# notice and this notice are preserved. This file is offered as-is,
|
||||
# without any warranty.
|
||||
#
|
||||
# Origin: gettext-0.21
|
||||
GETTEXT_MACRO_VERSION = 0.20
|
||||
|
||||
PACKAGE = @PACKAGE@
|
||||
VERSION = @VERSION@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
|
||||
SED = @SED@
|
||||
SHELL = /bin/sh
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
datarootdir = @datarootdir@
|
||||
datadir = @datadir@
|
||||
localedir = @localedir@
|
||||
gettextsrcdir = $(datadir)/gettext/po
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
# We use $(mkdir_p).
|
||||
# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as
|
||||
# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions,
|
||||
# @install_sh@ does not start with $(SHELL), so we add it.
|
||||
# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined
|
||||
# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake
|
||||
# versions, $(mkinstalldirs) and $(install_sh) are unused.
|
||||
mkinstalldirs = $(SHELL) @install_sh@ -d
|
||||
install_sh = $(SHELL) @install_sh@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
mkdir_p = @mkdir_p@
|
||||
|
||||
# When building gettext-tools, we prefer to use the built programs
|
||||
# rather than installed programs. However, we can't do that when we
|
||||
# are cross compiling.
|
||||
CROSS_COMPILING = @CROSS_COMPILING@
|
||||
|
||||
GMSGFMT_ = @GMSGFMT@
|
||||
GMSGFMT_no = @GMSGFMT@
|
||||
GMSGFMT_yes = @GMSGFMT_015@
|
||||
GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT))
|
||||
XGETTEXT_ = @XGETTEXT@
|
||||
XGETTEXT_no = @XGETTEXT@
|
||||
XGETTEXT_yes = @XGETTEXT_015@
|
||||
XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT))
|
||||
MSGMERGE = @MSGMERGE@
|
||||
MSGMERGE_UPDATE = @MSGMERGE@ --update
|
||||
MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
|
||||
MSGINIT = msginit
|
||||
MSGCONV = msgconv
|
||||
MSGFILTER = msgfilter
|
||||
|
||||
POFILES = @POFILES@
|
||||
GMOFILES = @GMOFILES@
|
||||
UPDATEPOFILES = @UPDATEPOFILES@
|
||||
DUMMYPOFILES = @DUMMYPOFILES@
|
||||
DISTFILES.common = Makefile.in.in remove-potcdate.sin \
|
||||
$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3)
|
||||
DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \
|
||||
$(POFILES) $(GMOFILES) \
|
||||
$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3)
|
||||
|
||||
POTFILES = \
|
||||
|
||||
CATALOGS = @CATALOGS@
|
||||
|
||||
POFILESDEPS_ = $(srcdir)/$(DOMAIN).pot
|
||||
POFILESDEPS_yes = $(POFILESDEPS_)
|
||||
POFILESDEPS_no =
|
||||
POFILESDEPS = $(POFILESDEPS_$(PO_DEPENDS_ON_POT))
|
||||
|
||||
DISTFILESDEPS_ = update-po
|
||||
DISTFILESDEPS_yes = $(DISTFILESDEPS_)
|
||||
DISTFILESDEPS_no =
|
||||
DISTFILESDEPS = $(DISTFILESDEPS_$(DIST_DEPENDS_ON_UPDATE_PO))
|
||||
|
||||
# Makevars gets inserted here. (Don't remove this line!)
|
||||
|
||||
all: all-@USE_NLS@
|
||||
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .po .gmo .sed .sin .nop .po-create .po-update
|
||||
|
||||
# The .pot file, stamp-po, .po files, and .gmo files appear in release tarballs.
|
||||
# The GNU Coding Standards say in
|
||||
# <https://www.gnu.org/prep/standards/html_node/Makefile-Basics.html>:
|
||||
# "GNU distributions usually contain some files which are not source files
|
||||
# ... . Since these files normally appear in the source directory, they
|
||||
# should always appear in the source directory, not in the build directory.
|
||||
# So Makefile rules to update them should put the updated files in the
|
||||
# source directory."
|
||||
# Therefore we put these files in the source directory, not the build directory.
|
||||
|
||||
# During .po -> .gmo conversion, take into account the most recent changes to
|
||||
# the .pot file. This eliminates the need to update the .po files when the
|
||||
# .pot file has changed, which would be troublesome if the .po files are put
|
||||
# under version control.
|
||||
$(GMOFILES): $(srcdir)/$(DOMAIN).pot
|
||||
.po.gmo:
|
||||
@lang=`echo $* | sed -e 's,.*/,,'`; \
|
||||
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
|
||||
echo "$${cdcmd}rm -f $${lang}.gmo && $(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) -o $${lang}.1po $${lang}.po $(DOMAIN).pot && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.1po && rm -f $${lang}.1po"; \
|
||||
cd $(srcdir) && \
|
||||
rm -f $${lang}.gmo && \
|
||||
$(MSGMERGE) $(MSGMERGE_FOR_MSGFMT_OPTION) -o $${lang}.1po $${lang}.po $(DOMAIN).pot && \
|
||||
$(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.1po && \
|
||||
mv t-$${lang}.gmo $${lang}.gmo && \
|
||||
rm -f $${lang}.1po
|
||||
|
||||
.sin.sed:
|
||||
sed -e '/^#/d' $< > t-$@
|
||||
mv t-$@ $@
|
||||
|
||||
|
||||
all-yes: $(srcdir)/stamp-po
|
||||
all-no:
|
||||
|
||||
# Ensure that the gettext macros and this Makefile.in.in are in sync.
|
||||
CHECK_MACRO_VERSION = \
|
||||
test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \
|
||||
|| { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \
|
||||
exit 1; \
|
||||
}
|
||||
|
||||
# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no
|
||||
# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because
|
||||
# we don't want to bother translators with empty POT files). We assume that
|
||||
# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty.
|
||||
# In this case, $(srcdir)/stamp-po is a nop (i.e. a phony target).
|
||||
|
||||
# $(srcdir)/stamp-po is a timestamp denoting the last time at which the CATALOGS
|
||||
# have been loosely updated. Its purpose is that when a developer or translator
|
||||
# checks out the package from a version control system, and the $(DOMAIN).pot
|
||||
# file is not under version control, "make" will update the $(DOMAIN).pot and
|
||||
# the $(CATALOGS), but subsequent invocations of "make" will do nothing. This
|
||||
# timestamp would not be necessary if updating the $(CATALOGS) would always
|
||||
# touch them; however, the rule for $(POFILES) has been designed to not touch
|
||||
# files that don't need to be changed.
|
||||
$(srcdir)/stamp-po: $(srcdir)/$(DOMAIN).pot
|
||||
@$(CHECK_MACRO_VERSION)
|
||||
test ! -f $(srcdir)/$(DOMAIN).pot || \
|
||||
test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
|
||||
@test ! -f $(srcdir)/$(DOMAIN).pot || { \
|
||||
echo "touch $(srcdir)/stamp-po" && \
|
||||
echo timestamp > $(srcdir)/stamp-poT && \
|
||||
mv $(srcdir)/stamp-poT $(srcdir)/stamp-po; \
|
||||
}
|
||||
|
||||
# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update',
|
||||
# otherwise packages like GCC can not be built if only parts of the source
|
||||
# have been downloaded.
|
||||
|
||||
# This target rebuilds $(DOMAIN).pot; it is an expensive operation.
|
||||
# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed.
|
||||
# The determination of whether the package xyz is a GNU one is based on the
|
||||
# heuristic whether some file in the top level directory mentions "GNU xyz".
|
||||
# If GNU 'find' is available, we avoid grepping through monster files.
|
||||
$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed
|
||||
package_gnu="$(PACKAGE_GNU)"; \
|
||||
test -n "$$package_gnu" || { \
|
||||
if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \
|
||||
LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f -size -10000000c -exec grep -i 'GNU @PACKAGE@' /dev/null '{}' ';' 2>/dev/null; \
|
||||
else \
|
||||
LC_ALL=C grep -i 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null; \
|
||||
fi; \
|
||||
} | grep -v 'libtool:' >/dev/null; then \
|
||||
package_gnu=yes; \
|
||||
else \
|
||||
package_gnu=no; \
|
||||
fi; \
|
||||
}; \
|
||||
if test "$$package_gnu" = "yes"; then \
|
||||
package_prefix='GNU '; \
|
||||
else \
|
||||
package_prefix=''; \
|
||||
fi; \
|
||||
if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \
|
||||
msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \
|
||||
else \
|
||||
msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \
|
||||
fi; \
|
||||
case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
|
||||
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \
|
||||
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
|
||||
--add-comments=TRANSLATORS: \
|
||||
--files-from=$(srcdir)/POTFILES.in \
|
||||
--copyright-holder='$(COPYRIGHT_HOLDER)' \
|
||||
--msgid-bugs-address="$$msgid_bugs_address" \
|
||||
$(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
|
||||
;; \
|
||||
*) \
|
||||
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
|
||||
--add-comments=TRANSLATORS: \
|
||||
--files-from=$(srcdir)/POTFILES.in \
|
||||
--copyright-holder='$(COPYRIGHT_HOLDER)' \
|
||||
--package-name="$${package_prefix}@PACKAGE@" \
|
||||
--package-version='@VERSION@' \
|
||||
--msgid-bugs-address="$$msgid_bugs_address" \
|
||||
$(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
|
||||
;; \
|
||||
esac
|
||||
test ! -f $(DOMAIN).po || { \
|
||||
if test -f $(srcdir)/$(DOMAIN).pot-header; then \
|
||||
sed -e '1,/^#$$/d' < $(DOMAIN).po > $(DOMAIN).1po && \
|
||||
cat $(srcdir)/$(DOMAIN).pot-header $(DOMAIN).1po > $(DOMAIN).po && \
|
||||
rm -f $(DOMAIN).1po \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
if test -f $(srcdir)/$(DOMAIN).pot; then \
|
||||
sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \
|
||||
sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \
|
||||
if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \
|
||||
rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \
|
||||
else \
|
||||
rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \
|
||||
mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \
|
||||
fi; \
|
||||
else \
|
||||
mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \
|
||||
fi; \
|
||||
}
|
||||
|
||||
# This rule has no dependencies: we don't need to update $(DOMAIN).pot at
|
||||
# every "make" invocation, only create it when it is missing.
|
||||
# Only "make $(DOMAIN).pot-update" or "make dist" will force an update.
|
||||
$(srcdir)/$(DOMAIN).pot:
|
||||
$(MAKE) $(DOMAIN).pot-update
|
||||
|
||||
# This target rebuilds a PO file if $(DOMAIN).pot has changed.
|
||||
# Note that a PO file is not touched if it doesn't need to be changed.
|
||||
$(POFILES): $(POFILESDEPS)
|
||||
@test -f $(srcdir)/$(DOMAIN).pot || $(MAKE) $(srcdir)/$(DOMAIN).pot
|
||||
@lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
|
||||
if test -f "$(srcdir)/$${lang}.po"; then \
|
||||
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
|
||||
echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot"; \
|
||||
cd $(srcdir) \
|
||||
&& { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
|
||||
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].*) \
|
||||
$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
|
||||
0.1[6-7] | 0.1[6-7].*) \
|
||||
$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --previous $${lang}.po $(DOMAIN).pot;; \
|
||||
*) \
|
||||
$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} --previous $${lang}.po $(DOMAIN).pot;; \
|
||||
esac; \
|
||||
}; \
|
||||
else \
|
||||
$(MAKE) $${lang}.po-create; \
|
||||
fi
|
||||
|
||||
|
||||
install: install-exec install-data
|
||||
install-exec:
|
||||
install-data: install-data-@USE_NLS@
|
||||
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||
$(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
|
||||
for file in $(DISTFILES.common) Makevars.template; do \
|
||||
$(INSTALL_DATA) $(srcdir)/$$file \
|
||||
$(DESTDIR)$(gettextsrcdir)/$$file; \
|
||||
done; \
|
||||
for file in Makevars; do \
|
||||
rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
|
||||
done; \
|
||||
else \
|
||||
: ; \
|
||||
fi
|
||||
install-data-no: all
|
||||
install-data-yes: all
|
||||
@catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
cat=`basename $$cat`; \
|
||||
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
|
||||
dir=$(localedir)/$$lang/LC_MESSAGES; \
|
||||
$(mkdir_p) $(DESTDIR)$$dir; \
|
||||
if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \
|
||||
$(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \
|
||||
echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \
|
||||
for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
|
||||
if test -n "$$lc"; then \
|
||||
if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
|
||||
link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
|
||||
mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||
(cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
|
||||
for file in *; do \
|
||||
if test -f $$file; then \
|
||||
ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
|
||||
fi; \
|
||||
done); \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||
else \
|
||||
if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
|
||||
:; \
|
||||
else \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||
fi; \
|
||||
fi; \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
|
||||
ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
|
||||
ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
|
||||
cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
|
||||
echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \
|
||||
fi; \
|
||||
done; \
|
||||
done
|
||||
|
||||
install-strip: install
|
||||
|
||||
installdirs: installdirs-exec installdirs-data
|
||||
installdirs-exec:
|
||||
installdirs-data: installdirs-data-@USE_NLS@
|
||||
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||
$(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
|
||||
else \
|
||||
: ; \
|
||||
fi
|
||||
installdirs-data-no:
|
||||
installdirs-data-yes:
|
||||
@catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
cat=`basename $$cat`; \
|
||||
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
|
||||
dir=$(localedir)/$$lang/LC_MESSAGES; \
|
||||
$(mkdir_p) $(DESTDIR)$$dir; \
|
||||
for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
|
||||
if test -n "$$lc"; then \
|
||||
if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
|
||||
link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
|
||||
mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||
(cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
|
||||
for file in *; do \
|
||||
if test -f $$file; then \
|
||||
ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
|
||||
fi; \
|
||||
done); \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
|
||||
else \
|
||||
if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
|
||||
:; \
|
||||
else \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
|
||||
fi; \
|
||||
fi; \
|
||||
fi; \
|
||||
done; \
|
||||
done
|
||||
|
||||
# Define this as empty until I found a useful application.
|
||||
installcheck:
|
||||
|
||||
uninstall: uninstall-exec uninstall-data
|
||||
uninstall-exec:
|
||||
uninstall-data: uninstall-data-@USE_NLS@
|
||||
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||
for file in $(DISTFILES.common) Makevars.template; do \
|
||||
rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
|
||||
done; \
|
||||
else \
|
||||
: ; \
|
||||
fi
|
||||
uninstall-data-no:
|
||||
uninstall-data-yes:
|
||||
catalogs='$(CATALOGS)'; \
|
||||
for cat in $$catalogs; do \
|
||||
cat=`basename $$cat`; \
|
||||
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
|
||||
for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \
|
||||
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
|
||||
done; \
|
||||
done
|
||||
|
||||
check: all
|
||||
|
||||
info dvi ps pdf html tags TAGS ctags CTAGS ID:
|
||||
|
||||
install-dvi install-ps install-pdf install-html:
|
||||
|
||||
mostlyclean:
|
||||
rm -f remove-potcdate.sed
|
||||
rm -f $(srcdir)/stamp-poT
|
||||
rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
|
||||
rm -fr *.o
|
||||
|
||||
clean: mostlyclean
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile Makefile.in POTFILES
|
||||
|
||||
maintainer-clean: distclean
|
||||
@echo "This command is intended for maintainers to use;"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
rm -f $(srcdir)/$(DOMAIN).pot $(srcdir)/stamp-po $(GMOFILES)
|
||||
|
||||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
|
||||
dist distdir:
|
||||
test -z "$(DISTFILESDEPS)" || $(MAKE) $(DISTFILESDEPS)
|
||||
@$(MAKE) dist2
|
||||
# This is a separate target because 'update-po' must be executed before.
|
||||
dist2: $(srcdir)/stamp-po $(DISTFILES)
|
||||
@dists="$(DISTFILES)"; \
|
||||
if test "$(PACKAGE)" = "gettext-tools"; then \
|
||||
dists="$$dists Makevars.template"; \
|
||||
fi; \
|
||||
if test -f $(srcdir)/$(DOMAIN).pot; then \
|
||||
dists="$$dists $(DOMAIN).pot stamp-po"; \
|
||||
else \
|
||||
case $(XGETTEXT) in \
|
||||
:) echo "Warning: Creating a tarball without '$(DOMAIN).pot', because a suitable 'xgettext' program was not found in PATH." 1>&2;; \
|
||||
*) echo "Warning: Creating a tarball without '$(DOMAIN).pot', because 'xgettext' found no strings to extract. Check the contents of the POTFILES.in file and the XGETTEXT_OPTIONS in the Makevars file." 1>&2;; \
|
||||
esac; \
|
||||
fi; \
|
||||
if test -f $(srcdir)/ChangeLog; then \
|
||||
dists="$$dists ChangeLog"; \
|
||||
fi; \
|
||||
for i in 0 1 2 3 4 5 6 7 8 9; do \
|
||||
if test -f $(srcdir)/ChangeLog.$$i; then \
|
||||
dists="$$dists ChangeLog.$$i"; \
|
||||
fi; \
|
||||
done; \
|
||||
if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \
|
||||
for file in $$dists; do \
|
||||
if test -f $$file; then \
|
||||
cp -p $$file $(distdir) || exit 1; \
|
||||
else \
|
||||
cp -p $(srcdir)/$$file $(distdir) || exit 1; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
update-po: Makefile
|
||||
$(MAKE) $(DOMAIN).pot-update
|
||||
test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
|
||||
$(MAKE) update-gmo
|
||||
|
||||
# General rule for creating PO files.
|
||||
|
||||
.nop.po-create:
|
||||
@lang=`echo $@ | sed -e 's/\.po-create$$//'`; \
|
||||
echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
|
||||
exit 1
|
||||
|
||||
# General rule for updating PO files.
|
||||
|
||||
.nop.po-update:
|
||||
@lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
|
||||
if test "$(PACKAGE)" = "gettext-tools" && test "$(CROSS_COMPILING)" != "yes"; then PATH=`pwd`/../src:$$PATH; fi; \
|
||||
tmpdir=`pwd`; \
|
||||
echo "$$lang:"; \
|
||||
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
|
||||
echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang --previous $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
|
||||
cd $(srcdir); \
|
||||
if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
|
||||
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].*) \
|
||||
$(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
|
||||
0.1[6-7] | 0.1[6-7].*) \
|
||||
$(MSGMERGE) $(MSGMERGE_OPTIONS) --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
|
||||
*) \
|
||||
$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang --previous -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
|
||||
esac; \
|
||||
}; then \
|
||||
if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
|
||||
rm -f $$tmpdir/$$lang.new.po; \
|
||||
else \
|
||||
if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
|
||||
:; \
|
||||
else \
|
||||
echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
fi; \
|
||||
else \
|
||||
echo "msgmerge for $$lang.po failed!" 1>&2; \
|
||||
rm -f $$tmpdir/$$lang.new.po; \
|
||||
fi
|
||||
|
||||
$(DUMMYPOFILES):
|
||||
|
||||
update-gmo: Makefile $(GMOFILES)
|
||||
@:
|
||||
|
||||
# Recreate Makefile by invoking config.status. Explicitly invoke the shell,
|
||||
# because execution permission bits may not work on the current file system.
|
||||
# Use @SHELL@, which is the shell determined by autoconf for the use by its
|
||||
# scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient.
|
||||
Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@
|
||||
cd $(top_builddir) \
|
||||
&& @SHELL@ ./config.status $(subdir)/$@.in po-directories
|
||||
|
||||
force:
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make not to export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
||||
@@ -19,6 +19,7 @@ src/pv/format/name.c
|
||||
src/pv/format/previousline.c
|
||||
src/pv/format/progressbar.c
|
||||
src/pv/format/rate.c
|
||||
src/pv/format/ratio.c
|
||||
src/pv/format/sgr.c
|
||||
src/pv/format/timer.c
|
||||
src/pv/loop.c
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-12-15 20:10+0000\n"
|
||||
"POT-Creation-Date: 2026-08-01 14:53+0100\n"
|
||||
"PO-Revision-Date: 2024-10-13 20:43+0000\n"
|
||||
"Last-Translator: mmatous <mmatous@users.noreply.translate.codeberg.org>\n"
|
||||
"Language-Team: Czech <https://translate.codeberg.org/projects/pv/pv/cs/>\n"
|
||||
@@ -12,362 +12,353 @@ msgstr ""
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.7.2\n"
|
||||
|
||||
#: src/main/help.c:236
|
||||
#: src/main/help.c:300
|
||||
msgid "show progress bar"
|
||||
msgstr "ukaž indikátor průběhu"
|
||||
|
||||
#: src/main/help.c:239
|
||||
#: src/main/help.c:303
|
||||
msgid "show elapsed time"
|
||||
msgstr "ukaž uběhlý čas"
|
||||
|
||||
#: src/main/help.c:242
|
||||
#: src/main/help.c:306
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "ukaž přibližný zbývající čas"
|
||||
|
||||
#: src/main/help.c:245
|
||||
#: src/main/help.c:309
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "ukaž přibližný čas dokončení"
|
||||
|
||||
#: src/main/help.c:248
|
||||
#: src/main/help.c:312
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "ukaž okamžitou rychlost přenosu dat"
|
||||
|
||||
#: src/main/help.c:251
|
||||
#: src/main/help.c:315
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "ukaž průměrnou rychlost přenosu dat"
|
||||
|
||||
#: src/main/help.c:254
|
||||
#: src/main/help.c:318
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "ukaž počet přenesených bajtů"
|
||||
|
||||
#: src/main/help.c:257
|
||||
#: src/main/help.c:321
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "ukaž procento využité vyrovnávací paměti"
|
||||
|
||||
#: src/main/help.c:259
|
||||
#: src/main/help.c:323
|
||||
msgid "NUM"
|
||||
msgstr "ČÍS"
|
||||
|
||||
#: src/main/help.c:260
|
||||
#: src/main/help.c:324
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "zobraz ČÍS posledních zapsaných bajtů"
|
||||
|
||||
#: src/main/help.c:262
|
||||
#: src/main/help.c:326
|
||||
msgid "FORMAT"
|
||||
msgstr "FORMÁT"
|
||||
|
||||
#: src/main/help.c:263
|
||||
#: src/main/help.c:327
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "nastav formát výstupu na FORMÁT"
|
||||
|
||||
#: src/main/help.c:266
|
||||
#: src/main/help.c:330
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "vypisuj procenta, ne vizuální informace"
|
||||
|
||||
#: src/main/help.c:269
|
||||
#: src/main/help.c:333
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "nevypisuj žádné informace o přenosu"
|
||||
|
||||
#: src/main/help.c:273
|
||||
#: src/main/help.c:337
|
||||
msgid "show number of bits transferred"
|
||||
msgstr "ukaž počet přenesených bitů"
|
||||
|
||||
#: src/main/help.c:276
|
||||
#: src/main/help.c:340
|
||||
msgid "treat suffixes as multiples of 1000 rather than 1024"
|
||||
msgstr "zacházej se suffixy jako s násobky 1000 namísto 1024"
|
||||
|
||||
#: src/main/help.c:279
|
||||
#: src/main/help.c:343
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "nic nevypisuj, dokud není přenesen první byte"
|
||||
|
||||
#: src/main/help.c:281 src/main/help.c:296 src/main/help.c:299
|
||||
#: src/main/help.c:345 src/main/help.c:360 src/main/help.c:363
|
||||
msgid "SEC"
|
||||
msgstr "SEK"
|
||||
|
||||
#: src/main/help.c:282
|
||||
#: src/main/help.c:346
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "nic nevypisuj, dokud neuplyne SEK sekund"
|
||||
|
||||
#: src/main/help.c:284
|
||||
#: src/main/help.c:348
|
||||
msgid "SIZE"
|
||||
msgstr "VEL"
|
||||
|
||||
#: src/main/help.c:285
|
||||
#: src/main/help.c:349
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "nastav očekávanou velikost dat na VEL bajtů"
|
||||
|
||||
#: src/main/help.c:288
|
||||
#: src/main/help.c:352
|
||||
msgid "if size unknown, show rate vs max rate"
|
||||
msgstr "pokud je velikost neznámá, ukaž rychlost vs maximální rychlost"
|
||||
|
||||
#: src/main/help.c:291
|
||||
#: src/main/help.c:355
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "počítej řádky místo bajtů"
|
||||
|
||||
#: src/main/help.c:294
|
||||
#: src/main/help.c:358
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "řádky jsou zakončené nulovým znakem"
|
||||
|
||||
#: src/main/help.c:297
|
||||
#: src/main/help.c:361
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "aktualizuj každých SEK sekund"
|
||||
|
||||
#: src/main/help.c:300
|
||||
#: src/main/help.c:364
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr "počítej průměrnou rychlost za posledních SEK sekund (výchozí: 30)"
|
||||
|
||||
#: src/main/help.c:302
|
||||
#: src/main/help.c:366
|
||||
msgid "WIDTH"
|
||||
msgstr "ŠÍŘ"
|
||||
|
||||
#: src/main/help.c:303
|
||||
#: src/main/help.c:367
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "předpokládej šířku terminálu ŠÍŘ znaků"
|
||||
|
||||
#: src/main/help.c:305
|
||||
#: src/main/help.c:369
|
||||
msgid "HEIGHT"
|
||||
msgstr "VÝŠ"
|
||||
|
||||
#: src/main/help.c:306
|
||||
#: src/main/help.c:370
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "předpokládej výšku terminálu VÝŠ znaků"
|
||||
|
||||
#: src/main/help.c:308
|
||||
#: src/main/help.c:372
|
||||
msgid "NAME"
|
||||
msgstr "JMÉNO"
|
||||
|
||||
#: src/main/help.c:309
|
||||
#: src/main/help.c:373
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "přidej JMÉNO před vizuální informace"
|
||||
|
||||
#: src/main/help.c:311
|
||||
#: src/main/help.c:375
|
||||
msgid "STYLE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "set default bar style to NAME"
|
||||
#: src/main/help.c:376
|
||||
msgid "set default bar style to STYLE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:314
|
||||
#: src/main/help.c:378
|
||||
msgid "SPEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:315
|
||||
#: src/main/help.c:379
|
||||
msgid "also send progress to SPEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:318
|
||||
#: src/main/help.c:382
|
||||
msgid "set terminal progress state with OSC 9;4 (ConEmu)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:385
|
||||
msgid "output transfer statistics at the end"
|
||||
msgstr "po dokončení vypiš údaje o přenosu"
|
||||
|
||||
#: src/main/help.c:321
|
||||
#: src/main/help.c:388
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "vypisuj výstup i pokud standardní chybový výstup není terminál"
|
||||
|
||||
#: src/main/help.c:324
|
||||
#: src/main/help.c:391
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "pozicuj kurzor pomocí řídících znaků"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
#: src/main/help.c:394 src/main/help.c:430 src/main/help.c:449
|
||||
#: src/main/help.c:459
|
||||
msgid "FILE"
|
||||
msgstr "SOUBOR"
|
||||
|
||||
#: src/main/help.c:328
|
||||
#: src/main/help.c:395
|
||||
msgid "write output to FILE instead of stdout"
|
||||
msgstr "zapiš výstup do SOUBORu namísto standardního výstupu"
|
||||
|
||||
#: src/main/help.c:330
|
||||
#: src/main/help.c:397
|
||||
msgid "RATE"
|
||||
msgstr "RYCH"
|
||||
|
||||
#: src/main/help.c:331
|
||||
#: src/main/help.c:398
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "omez přenosovou rychlost na RYCH bajtů za sekundu"
|
||||
|
||||
#: src/main/help.c:333 src/main/help.c:342
|
||||
#: src/main/help.c:400 src/main/help.c:406 src/main/help.c:412
|
||||
msgid "BYTES"
|
||||
msgstr "BAJT"
|
||||
|
||||
#: src/main/help.c:334
|
||||
#: src/main/help.c:401
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "použij vyrovnávací pamět BAJT bajtů"
|
||||
|
||||
#: src/main/help.c:337
|
||||
#: src/main/help.c:404
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "nepoužívej splice(), vždy použij read/write"
|
||||
|
||||
#: src/main/help.c:340
|
||||
#: src/main/help.c:407
|
||||
msgid "set the pipe buffer size to BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:410
|
||||
msgid "skip read errors in input"
|
||||
msgstr "ignoruj chyby při čtení vstupu"
|
||||
|
||||
#: src/main/help.c:343
|
||||
#: src/main/help.c:413
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr "přeskakuj chyby v blocích BAJTů naráz"
|
||||
|
||||
#: src/main/help.c:346
|
||||
#: src/main/help.c:416
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "zastav po přenosu --size bajtů"
|
||||
|
||||
#: src/main/help.c:349
|
||||
#: src/main/help.c:419
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr "po každém zápisu vyprázdni cache na disk"
|
||||
|
||||
#: src/main/help.c:352
|
||||
#: src/main/help.c:422
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr "použij přímý V/V k obejítí cache"
|
||||
|
||||
#: src/main/help.c:355
|
||||
#: src/main/help.c:425
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
#: src/main/help.c:428
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr "zahoď vstup namísto zápisu na výstup"
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:431
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr "zapiš veškerý vstup do SOUBORu před výpisem na výstup"
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:434
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:435
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "sleduj soubor DS otevřený procesem PID"
|
||||
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
#: src/main/help.c:438 src/main/help.c:441
|
||||
msgid "PID"
|
||||
msgstr "PID"
|
||||
|
||||
#: src/main/help.c:369
|
||||
#: src/main/help.c:439
|
||||
msgid "update settings of process PID"
|
||||
msgstr "aktualizuj nastavení procesu PID"
|
||||
|
||||
#: src/main/help.c:372
|
||||
#: src/main/help.c:442
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
#: src/main/help.c:446
|
||||
msgid "run a command and monitor its standard input, output, or both"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:450
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "ulož id procesu do SOUBORu"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:453
|
||||
msgid "show this help and exit"
|
||||
msgstr "ukaž pomoc a skonči"
|
||||
|
||||
#: src/main/help.c:383
|
||||
#: src/main/help.c:456
|
||||
msgid "show version information and exit"
|
||||
msgstr "ukaž informace o verzi a skonči"
|
||||
|
||||
#: src/main/help.c:387
|
||||
#: src/main/help.c:460
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "zapiš ladící záznamy do SOUBORu"
|
||||
|
||||
#: src/main/help.c:413
|
||||
#: src/main/help.c:486
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Použití: %s [VOLBY] [SOUBOR]..."
|
||||
|
||||
#: src/main/help.c:424
|
||||
#: src/main/help.c:497
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
"Spoj SOUBOR(y) nebo standardní vstup na standardního výstup, s monitoringem."
|
||||
|
||||
#: src/main/help.c:562
|
||||
#: src/main/help.c:639
|
||||
msgid "Supported format sequences:"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:576
|
||||
#: src/main/help.c:653
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Prosím, hlašte veškeré chyby na: %s"
|
||||
|
||||
#: src/main/main.c:228
|
||||
#: src/main/main.c:225
|
||||
msgid "(input)"
|
||||
msgstr "(vstup)"
|
||||
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr "selhala alokace stavu"
|
||||
#: src/main/main.c:381 src/main/options.c:1359
|
||||
msgid "a command to run must be specified"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:370
|
||||
#: src/main/main.c:704 src/main/options.c:757 src/main/options.c:777
|
||||
#: src/pv/display.c:1086 src/pv/state.c:45 src/pv/state.c:902
|
||||
#: src/pv/state.c:914 src/pv/state.c:950 src/pv/transfer.c:1335
|
||||
#: src/pv/transfer.c:1451 src/pv/transfer.c:1778
|
||||
msgid "memory allocation failure"
|
||||
msgstr "chyba přidělování paměti"
|
||||
|
||||
#: src/main/options.c:418
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
#: src/main/options.c:438 src/main/options.c:440 src/main/options.c:901
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr "očekáváno ID procesu nebo dvojice PID:DS"
|
||||
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
#: src/main/options.c:449 src/main/options.c:451 src/main/options.c:908
|
||||
msgid "invalid process ID"
|
||||
msgstr "neplatné ID procesu"
|
||||
|
||||
#: src/main/options.c:448 src/pv/file.c:342
|
||||
msgid "failed to stat file"
|
||||
msgstr "nebylo možné zjistit informace o souboru"
|
||||
|
||||
#: src/main/options.c:462
|
||||
msgid "is a directory"
|
||||
msgstr "je adresář"
|
||||
|
||||
#: src/main/options.c:491
|
||||
msgid "failed to generate sysfs filename"
|
||||
msgstr "selhalo vytváření jména pro soubor v sysfs"
|
||||
|
||||
#: src/main/options.c:513
|
||||
msgid "failed to read sysfs size file"
|
||||
msgstr "selhalo čtení velikosti souboru v sysfs"
|
||||
|
||||
#: src/main/options.c:533
|
||||
msgid "failed to open block device"
|
||||
msgstr "selhalo otevření blokového zařízení"
|
||||
|
||||
#: src/main/options.c:543
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr "selhalo zjištění velikosti blokového zařízení"
|
||||
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "selhala alokace struktury pro volby"
|
||||
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "selhala alokace struktury pro argv"
|
||||
|
||||
#: src/main/options.c:723
|
||||
#: src/main/options.c:829
|
||||
msgid "numeric value not understood"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:743
|
||||
#: src/main/options.c:843
|
||||
msgid "integer argument expected"
|
||||
msgstr "očekáván celočíselný argument"
|
||||
|
||||
#: src/main/options.c:755
|
||||
#: src/main/options.c:853
|
||||
msgid "numeric argument expected"
|
||||
msgstr "očekáván číselný argument"
|
||||
|
||||
#: src/main/options.c:767
|
||||
#: src/main/options.c:864
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:795
|
||||
#: src/main/options.c:890
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1056
|
||||
#: src/main/options.c:1182
|
||||
msgid "invalid side specification"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1197
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Zkuste `%s --help' pro více informací."
|
||||
|
||||
#: src/main/options.c:1058
|
||||
#: src/main/options.c:1199
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Zkuste `%s --h' pro více informací."
|
||||
|
||||
#: src/main/options.c:1089
|
||||
#: src/main/options.c:1231
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -375,31 +366,39 @@ msgstr ""
|
||||
"při sledování deskriptorů souborů nelze použít řádkový mód nebo volby pro "
|
||||
"modifikaci přenosu"
|
||||
|
||||
#: src/main/options.c:1098
|
||||
#: src/main/options.c:1239
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr "při sledování deskriptorů souborů nelze pozicování kurzoru použít"
|
||||
|
||||
#: src/main/options.c:1107
|
||||
#: src/main/options.c:1247
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr "při sledování deskriptorů souborů nelze použít vzdálené ovládání"
|
||||
|
||||
#: src/main/options.c:1116
|
||||
#: src/main/options.c:1255
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
#: src/main/options.c:1263
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr "při sledování deskriptorů souborů nelze použít přenos souborů"
|
||||
|
||||
#: src/main/options.c:1150
|
||||
#: src/main/options.c:1287
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "není dostupné na systémech bez /proc/self/fdinfo"
|
||||
|
||||
#: src/main/options.c:1162
|
||||
#: src/main/options.c:1298
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1189
|
||||
#: src/main/options.c:1325
|
||||
msgid "monitor mode cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1337
|
||||
msgid "monitor mode cannot be used with store-and-forward"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1348
|
||||
msgid "files cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
@@ -419,64 +418,44 @@ msgstr "Na program se nevztahuje ŽÁDNÁ ZÁRUKA, v míře povolené zákonem."
|
||||
msgid "Project web site"
|
||||
msgstr "Stránka projektu"
|
||||
|
||||
#: src/pv/cursor.c:61
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "selhalo zjištění názvu terminálu"
|
||||
|
||||
#: src/pv/cursor.c:106
|
||||
#: src/pv/cursor.c:108 src/pv/cursor.c:135
|
||||
msgid "failed to open lock file"
|
||||
msgstr "selhalo otevření zámkového souboru"
|
||||
|
||||
#: src/pv/cursor.c:139
|
||||
msgid "lock attempt failed"
|
||||
msgstr "selhal pokus o uzamčení"
|
||||
#: src/pv/cursor.c:790 src/pv/cursor.c:792
|
||||
msgid "interrupted by a signal"
|
||||
msgstr "přerušeno signálem"
|
||||
|
||||
#: src/pv/cursor.c:400
|
||||
msgid "failed to open terminal"
|
||||
msgstr "selhalo otevření terminálu"
|
||||
|
||||
#: src/pv/display.c:285
|
||||
#: src/pv/display.c:311
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr "yzafpnum kMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:303
|
||||
#: src/pv/display.c:329
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr "yzafpnum KMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "selhala alokace vyrovnávací paměti"
|
||||
#: src/pv/file.c:81
|
||||
msgid "/dev/null is not usable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:153
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr "selhalo posunutí za začátek výstupu"
|
||||
#: src/pv/file.c:371
|
||||
msgid "error closing file"
|
||||
msgstr "chyba při zavírání souboru"
|
||||
|
||||
#: src/pv/file.c:303
|
||||
msgid "failed to close file"
|
||||
msgstr "selhalo zavření souboru"
|
||||
#: src/pv/file.c:438
|
||||
msgid "input file is also the output"
|
||||
msgstr "vstupní soubor je rovněž výstupem"
|
||||
|
||||
#: src/pv/file.c:335
|
||||
msgid "failed to read file"
|
||||
msgstr "selhalo čtení ze souboru"
|
||||
|
||||
#: src/pv/file.c:350
|
||||
msgid "failed to stat output file"
|
||||
msgstr "selhalo zjištění informací o výstupním souboru"
|
||||
|
||||
#: src/pv/file.c:372
|
||||
msgid "input file is output file"
|
||||
msgstr "vstupní soubor je výstupní soubor"
|
||||
|
||||
#: src/pv/file.c:429
|
||||
#: src/pv/file.c:596
|
||||
msgid "(none)"
|
||||
msgstr "(žádný)"
|
||||
|
||||
#: src/pv/file.c:431
|
||||
#: src/pv/file.c:598
|
||||
msgid "(stdin)"
|
||||
msgstr "(stdin)"
|
||||
|
||||
#: src/pv/format/averagerate.c:34 src/pv/format/progressbar.c:92
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:181
|
||||
msgid "b/s"
|
||||
msgstr "b/s"
|
||||
|
||||
@@ -486,7 +465,7 @@ msgid "/s"
|
||||
msgstr "/s"
|
||||
|
||||
#: src/pv/format/averagerate.c:38 src/pv/format/progressbar.c:96
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:181
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
@@ -494,103 +473,141 @@ msgstr "B/s"
|
||||
msgid "b"
|
||||
msgstr "b"
|
||||
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:620
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:1284
|
||||
msgid "B"
|
||||
msgstr "B"
|
||||
|
||||
#: src/pv/format/eta.c:52 src/pv/format/eta.c:56
|
||||
#: src/pv/format/eta.c:63 src/pv/format/eta.c:67
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/format/fineta.c:80
|
||||
#: src/pv/format/fineta.c:93
|
||||
msgid "FIN"
|
||||
msgstr "FIN"
|
||||
|
||||
#: src/pv/loop.c:120
|
||||
#: src/pv/loop.c:180
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr "rychlost min/avg/max/std"
|
||||
|
||||
#: src/pv/loop.c:132
|
||||
#: src/pv/loop.c:192
|
||||
msgid "rate not measured"
|
||||
msgstr "rychlost neměřena"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/loop.c:818 src/pv/loop.c:836 src/pv/watchpid.c:101
|
||||
#: src/pv/watchpid.c:110 src/pv/watchpid.c:121 src/pv/watchpid.c:129
|
||||
#: src/pv/watchpid.c:166 src/pv/watchpid.c:185 src/pv/watchpid.c:193
|
||||
#: src/pv/watchpid.c:203 src/pv/watchpid.c:307 src/pv/watchpid.c:315
|
||||
#: src/pv/watchpid.c:447 src/pv/watchpid.c:470
|
||||
#: src/pv/loop.c:1098 src/pv/loop.c:1114 src/pv/loop.c:1132 src/pv/remote.c:93
|
||||
#: src/pv/remote.c:188 src/pv/remote.c:536 src/pv/remote.c:582
|
||||
#: src/pv/watchpid.c:123 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:158 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:206 src/pv/watchpid.c:218 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:286 src/pv/watchpid.c:401
|
||||
#: src/pv/watchpid.c:409 src/pv/watchpid.c:556 src/pv/watchpid.c:565
|
||||
#: src/pv/watchpid.c:586
|
||||
msgid "pid"
|
||||
msgstr "pid"
|
||||
|
||||
#: src/pv/loop.c:836 src/pv/watchpid.c:110 src/pv/watchpid.c:122
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:185 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:205
|
||||
#: src/pv/loop.c:1132 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:160 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:288
|
||||
msgid "fd"
|
||||
msgstr "ds"
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
#: src/pv/remote.c:242 src/pv/remote.c:636
|
||||
msgid "message not received"
|
||||
msgstr "zpráva nepřijata"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
#: src/pv/remote.c:659 src/pv/remote.c:677
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO není na tomto systému podporováno"
|
||||
|
||||
#: src/pv/state.c:42
|
||||
msgid "history structure allocation failed"
|
||||
msgstr "selhala alokace struktury historie"
|
||||
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr "selhala alokace seznamu souborů"
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr "čtení selhalo"
|
||||
|
||||
#: src/pv/transfer.c:506
|
||||
#: src/pv/transfer.c:1173
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "varování: detekovány chyby při čtení"
|
||||
|
||||
#: src/pv/transfer.c:522
|
||||
msgid "file is not seekable"
|
||||
msgstr "souborem nelze procházet"
|
||||
|
||||
#: src/pv/transfer.c:599
|
||||
msgid "failed to seek past error"
|
||||
msgstr "selhal skok za chybu"
|
||||
|
||||
#: src/pv/transfer.c:619
|
||||
#: src/pv/transfer.c:1283
|
||||
msgid "skipped past read error"
|
||||
msgstr "chyba přeskočena"
|
||||
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr "vyrovnávací paměť není alokována"
|
||||
#: src/pv/transfer.c:1642
|
||||
msgid "write error"
|
||||
msgstr "chyba při zápisu"
|
||||
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr "selhalo nastavení intervalového časovače"
|
||||
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr "selhalo vynulování intervalového časovače"
|
||||
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr "selhala alokace vyrovnávací paměti pro pozici v řádcích"
|
||||
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "zápis selhal"
|
||||
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "selhalo volání select"
|
||||
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
#: src/pv/watchpid.c:160 src/pv/watchpid.c:288
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "není obyčejný soubor nebo blokové zařízení"
|
||||
|
||||
#~ msgid "state allocation failed"
|
||||
#~ msgstr "selhala alokace stavu"
|
||||
|
||||
#~ msgid "failed to stat file"
|
||||
#~ msgstr "nebylo možné zjistit informace o souboru"
|
||||
|
||||
#~ msgid "is a directory"
|
||||
#~ msgstr "je adresář"
|
||||
|
||||
#~ msgid "failed to generate sysfs filename"
|
||||
#~ msgstr "selhalo vytváření jména pro soubor v sysfs"
|
||||
|
||||
#~ msgid "failed to read sysfs size file"
|
||||
#~ msgstr "selhalo čtení velikosti souboru v sysfs"
|
||||
|
||||
#~ msgid "failed to open block device"
|
||||
#~ msgstr "selhalo otevření blokového zařízení"
|
||||
|
||||
#~ msgid "failed to determine size of block device"
|
||||
#~ msgstr "selhalo zjištění velikosti blokového zařízení"
|
||||
|
||||
#~ msgid "option structure allocation failed"
|
||||
#~ msgstr "selhala alokace struktury pro volby"
|
||||
|
||||
#~ msgid "option structure argv allocation failed"
|
||||
#~ msgstr "selhala alokace struktury pro argv"
|
||||
|
||||
#~ msgid "failed to get terminal name"
|
||||
#~ msgstr "selhalo zjištění názvu terminálu"
|
||||
|
||||
#~ msgid "lock attempt failed"
|
||||
#~ msgstr "selhal pokus o uzamčení"
|
||||
|
||||
#~ msgid "failed to open terminal"
|
||||
#~ msgstr "selhalo otevření terminálu"
|
||||
|
||||
#~ msgid "failed to seek to start of output"
|
||||
#~ msgstr "selhalo posunutí za začátek výstupu"
|
||||
|
||||
#~ msgid "failed to read file"
|
||||
#~ msgstr "selhalo čtení ze souboru"
|
||||
|
||||
#~ msgid "failed to stat output file"
|
||||
#~ msgstr "selhalo zjištění informací o výstupním souboru"
|
||||
|
||||
#~ msgid "history structure allocation failed"
|
||||
#~ msgstr "selhala alokace struktury historie"
|
||||
|
||||
#~ msgid "file list allocation failed"
|
||||
#~ msgstr "selhala alokace seznamu souborů"
|
||||
|
||||
#~ msgid "read failed"
|
||||
#~ msgstr "čtení selhalo"
|
||||
|
||||
#~ msgid "file is not seekable"
|
||||
#~ msgstr "souborem nelze procházet"
|
||||
|
||||
#~ msgid "failed to seek past error"
|
||||
#~ msgstr "selhal skok za chybu"
|
||||
|
||||
#~ msgid "no transfer buffer allocated"
|
||||
#~ msgstr "vyrovnávací paměť není alokována"
|
||||
|
||||
#~ msgid "failed to set interval timer"
|
||||
#~ msgstr "selhalo nastavení intervalového časovače"
|
||||
|
||||
#~ msgid "failed to clear interval timer"
|
||||
#~ msgstr "selhalo vynulování intervalového časovače"
|
||||
|
||||
#~ msgid "line position buffer allocation failed"
|
||||
#~ msgstr "selhala alokace vyrovnávací paměti pro pozici v řádcích"
|
||||
|
||||
#~ msgid "select call failed"
|
||||
#~ msgstr "selhalo volání select"
|
||||
|
||||
#~ msgid "PID[:FD]"
|
||||
#~ msgstr "PID[:DS]"
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-12-15 20:10+0000\n"
|
||||
"PO-Revision-Date: 2025-01-14 20:39+0000\n"
|
||||
"Last-Translator: Benny <benny@users.noreply.translate.codeberg.org>\n"
|
||||
"POT-Creation-Date: 2026-08-01 14:53+0100\n"
|
||||
"PO-Revision-Date: 2026-08-01 18:32+0000\n"
|
||||
"Last-Translator: a-j-wood <a-j-wood@noreply.codeberg.org>\n"
|
||||
"Language-Team: German <https://translate.codeberg.org/projects/pv/pv/de/>\n"
|
||||
"Language: de\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.9.2\n"
|
||||
"X-Generator: Weblate 2026.7.1\n"
|
||||
"Date: 1999-06-01 15:18:29+0100\n"
|
||||
"From: Andrew Wood <ivarch@ubik>\n"
|
||||
"Xgettext-Options: --default-domain=pkgbuild --directory=./.pkgdir --add-"
|
||||
"comments --keyword=_ --keyword=N_\n"
|
||||
"Files: src/getopt/getopt.c src/getopt/getopt1.c src/version.c src/main/init."
|
||||
"c src/main/help.c src/main/xpmptr.c src/guts/load.c src/guts/stop.c src/guts/"
|
||||
"configure.c src/guts/make.c src/guts/install.c src/guts/prefs.c src/ui/"
|
||||
"Files: src/getopt/getopt.c src/getopt/getopt1.c src/version.c src/main/"
|
||||
"init.c src/main/help.c src/main/xpmptr.c src/guts/load.c src/guts/stop.c src/"
|
||||
"guts/configure.c src/guts/make.c src/guts/install.c src/guts/prefs.c src/ui/"
|
||||
"generate.c src/ui/main.c src/ui/xpm.c src/ui/status.c src/ui/activate.c src/"
|
||||
"ui/handlers/main.c src/ui/handlers/package.c src/ui/handlers/prefs.c src/ui/"
|
||||
"handlers/dirsel.c src/ui/handlers/popup.c src/ui/handlers/help.c src/ui/"
|
||||
@@ -26,366 +26,359 @@ msgstr ""
|
||||
"nls/intl/textdomain.c src/nls/intl-cat/cat-compat.c src/nls/intl-gett/intl-"
|
||||
"compat.c\n"
|
||||
|
||||
#: src/main/help.c:236
|
||||
#: src/main/help.c:300
|
||||
msgid "show progress bar"
|
||||
msgstr "Fortschritts-Anzeige"
|
||||
|
||||
#: src/main/help.c:239
|
||||
#: src/main/help.c:303
|
||||
msgid "show elapsed time"
|
||||
msgstr "zeige die verstrichene Zeit an"
|
||||
|
||||
#: src/main/help.c:242
|
||||
#: src/main/help.c:306
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "zeige die erwartete Zeit bis zum Ende an"
|
||||
|
||||
#: src/main/help.c:245
|
||||
#: src/main/help.c:309
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "zeige die absolute geschätzte Zeit bis zur Fertigstellung"
|
||||
|
||||
#: src/main/help.c:248
|
||||
#: src/main/help.c:312
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "zeige die Datentransferrate an"
|
||||
|
||||
#: src/main/help.c:251
|
||||
#: src/main/help.c:315
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "zeige die durchschnittliche Übertragungsrate"
|
||||
|
||||
#: src/main/help.c:254
|
||||
#: src/main/help.c:318
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "zeige die Anzahl der übertragenen Bytes"
|
||||
|
||||
#: src/main/help.c:257
|
||||
#: src/main/help.c:321
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "zeige, wie viel Prozent des Übertragungsbuffers in Benutzung sind"
|
||||
|
||||
#: src/main/help.c:259
|
||||
#: src/main/help.c:323
|
||||
msgid "NUM"
|
||||
msgstr "NUM"
|
||||
|
||||
#: src/main/help.c:260
|
||||
#: src/main/help.c:324
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "NUM zeige die zuletzt geschriebenen NUM Bytes"
|
||||
|
||||
#: src/main/help.c:262
|
||||
#: src/main/help.c:326
|
||||
msgid "FORMAT"
|
||||
msgstr "FORMAT"
|
||||
|
||||
#: src/main/help.c:263
|
||||
#: src/main/help.c:327
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "setze das Ausgabeformat auf FORMAT"
|
||||
|
||||
#: src/main/help.c:266
|
||||
#: src/main/help.c:330
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "Ausgabe von Prozent-Angaben statt visueller Darstellung"
|
||||
|
||||
#: src/main/help.c:269
|
||||
#: src/main/help.c:333
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "sämtliche Transferinformationen unterdrücken"
|
||||
|
||||
#: src/main/help.c:273
|
||||
#: src/main/help.c:337
|
||||
msgid "show number of bits transferred"
|
||||
msgstr "zeige die Anzahl der übertragenen Bits"
|
||||
|
||||
#: src/main/help.c:276
|
||||
#: src/main/help.c:340
|
||||
msgid "treat suffixes as multiples of 1000 rather than 1024"
|
||||
msgstr "behandle Endungen als Vielfache von 1000 statt von 1024"
|
||||
|
||||
#: src/main/help.c:279
|
||||
#: src/main/help.c:343
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "keine Ausgabe bevor das erste Byte übertragen wurde"
|
||||
|
||||
#: src/main/help.c:281 src/main/help.c:296 src/main/help.c:299
|
||||
#: src/main/help.c:345 src/main/help.c:360 src/main/help.c:363
|
||||
msgid "SEC"
|
||||
msgstr "SEK"
|
||||
|
||||
#: src/main/help.c:282
|
||||
#: src/main/help.c:346
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "nichts anzeigen ehe SEK Sekunden vergangen sind"
|
||||
|
||||
#: src/main/help.c:284
|
||||
#: src/main/help.c:348
|
||||
msgid "SIZE"
|
||||
msgstr "GRÖẞE"
|
||||
|
||||
#: src/main/help.c:285
|
||||
#: src/main/help.c:349
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "setze erwartete Datenlänge auf SIZE Byte"
|
||||
|
||||
#: src/main/help.c:288
|
||||
#: src/main/help.c:352
|
||||
msgid "if size unknown, show rate vs max rate"
|
||||
msgstr "zeige Rate vs maximale Rate, falls die größe unbekannt ist"
|
||||
|
||||
#: src/main/help.c:291
|
||||
#: src/main/help.c:355
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "zähle Zeilen anstelle von Bytes"
|
||||
|
||||
#: src/main/help.c:294
|
||||
#: src/main/help.c:358
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "Zeilen sind nullterminiert"
|
||||
|
||||
#: src/main/help.c:297
|
||||
#: src/main/help.c:361
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "aktualisiere Ausgabe nach SEK Sekunden Intervall"
|
||||
|
||||
#: src/main/help.c:300
|
||||
#: src/main/help.c:364
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
"berechne die durchschnittliche Übertragungsrate über die letzten SEK "
|
||||
"Sekunden (Standard 30s)"
|
||||
|
||||
#: src/main/help.c:302
|
||||
#: src/main/help.c:366
|
||||
msgid "WIDTH"
|
||||
msgstr "BREITE"
|
||||
|
||||
#: src/main/help.c:303
|
||||
#: src/main/help.c:367
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "setze Terminal-Breite auf BREITE Zeichen"
|
||||
|
||||
#: src/main/help.c:305
|
||||
#: src/main/help.c:369
|
||||
msgid "HEIGHT"
|
||||
msgstr "HÖHE"
|
||||
|
||||
#: src/main/help.c:306
|
||||
#: src/main/help.c:370
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "setze Terminal-Höhe auf HÖHE Zeichen"
|
||||
|
||||
#: src/main/help.c:308
|
||||
#: src/main/help.c:372
|
||||
msgid "NAME"
|
||||
msgstr "NAME"
|
||||
|
||||
#: src/main/help.c:309
|
||||
#: src/main/help.c:373
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "setze den NAMEn für visuelle Darstellung"
|
||||
|
||||
#: src/main/help.c:311
|
||||
#: src/main/help.c:375
|
||||
msgid "STYLE"
|
||||
msgstr "Stil"
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "set default bar style to NAME"
|
||||
msgstr "setze die voreingestellte Darstellung auf NAME"
|
||||
|
||||
#: src/main/help.c:314
|
||||
msgid "SPEC"
|
||||
msgstr "STIL"
|
||||
|
||||
#: src/main/help.c:315
|
||||
#: src/main/help.c:376
|
||||
msgid "set default bar style to STYLE"
|
||||
msgstr "setze die voreingestellte Darstellung auf STIL"
|
||||
|
||||
#: src/main/help.c:378
|
||||
msgid "SPEC"
|
||||
msgstr "SPEC"
|
||||
|
||||
#: src/main/help.c:379
|
||||
msgid "also send progress to SPEC"
|
||||
msgstr "Fortschritt auch an SPEC senden"
|
||||
|
||||
#: src/main/help.c:318
|
||||
#: src/main/help.c:382
|
||||
msgid "set terminal progress state with OSC 9;4 (ConEmu)"
|
||||
msgstr "aktualisieren Sie den Terminal-Fortschrittszustand mit OSC 9;4 (ConEmu)"
|
||||
|
||||
#: src/main/help.c:385
|
||||
msgid "output transfer statistics at the end"
|
||||
msgstr "Übertragungsstatistiken am Ende ausgeben"
|
||||
|
||||
#: src/main/help.c:321
|
||||
#: src/main/help.c:388
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr ""
|
||||
"Ausgabe auch dann erzwingen, wenn der Fehlerausgabe-Kanal kein Terminal ist"
|
||||
|
||||
#: src/main/help.c:324
|
||||
#: src/main/help.c:391
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "benutze Escape-Sequenzen zur Cursor-Positionierung"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
#: src/main/help.c:394 src/main/help.c:430 src/main/help.c:449
|
||||
#: src/main/help.c:459
|
||||
msgid "FILE"
|
||||
msgstr "DATEI"
|
||||
|
||||
#: src/main/help.c:328
|
||||
#: src/main/help.c:395
|
||||
msgid "write output to FILE instead of stdout"
|
||||
msgstr "schreibe die Ausgabe in DATEI statt in die Standardausgabe"
|
||||
|
||||
#: src/main/help.c:330
|
||||
#: src/main/help.c:397
|
||||
msgid "RATE"
|
||||
msgstr "RATE"
|
||||
|
||||
#: src/main/help.c:331
|
||||
#: src/main/help.c:398
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "beschränke die Transferrate auf RATE Byte pro Sekunde"
|
||||
|
||||
#: src/main/help.c:333 src/main/help.c:342
|
||||
#: src/main/help.c:400 src/main/help.c:406 src/main/help.c:412
|
||||
msgid "BYTES"
|
||||
msgstr "BYTES"
|
||||
|
||||
#: src/main/help.c:334
|
||||
#: src/main/help.c:401
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "benutze einen Puffer in der Größe von BYTES"
|
||||
|
||||
#: src/main/help.c:337
|
||||
#: src/main/help.c:404
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "anstelle von splice() immer read/write benutzen"
|
||||
|
||||
#: src/main/help.c:340
|
||||
#: src/main/help.c:407
|
||||
msgid "set the pipe buffer size to BYTES"
|
||||
msgstr "benutze einen Pipe-Puffer in der Größe von BYTES"
|
||||
|
||||
#: src/main/help.c:410
|
||||
msgid "skip read errors in input"
|
||||
msgstr "Lesefehler in der Eingabe nicht beachten"
|
||||
|
||||
#: src/main/help.c:343
|
||||
#: src/main/help.c:413
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr "bei Fehlern BYTES am Stück überspringen"
|
||||
|
||||
#: src/main/help.c:346
|
||||
#: src/main/help.c:416
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "anhalten, nachdem --size Bytes übertragen wurden"
|
||||
|
||||
#: src/main/help.c:349
|
||||
#: src/main/help.c:419
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr "schreibe den Cache nach jedem Schreibvorgang auf die Festplatte"
|
||||
|
||||
#: src/main/help.c:352
|
||||
#: src/main/help.c:422
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr "verwende direkte E/A, um den Cache zu umgehen"
|
||||
|
||||
#: src/main/help.c:355
|
||||
#: src/main/help.c:425
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
msgstr "ausgabelöcher anstelle von Nullbytes"
|
||||
|
||||
#: src/main/help.c:358
|
||||
#: src/main/help.c:428
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr "verwirf die Eingabe anstatt in die Ausgabe zu schreiben"
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:431
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr "Ausgabe nach FILE schrieben bevor sie ausgegeben wird"
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:434
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
msgstr "PID[:FD]|=NAME|@LISTENDATEI"
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:435
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "die vom Prozess PID geöffnete Datei FD beobachten"
|
||||
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
#: src/main/help.c:438 src/main/help.c:441
|
||||
msgid "PID"
|
||||
msgstr "PID"
|
||||
|
||||
#: src/main/help.c:369
|
||||
#: src/main/help.c:439
|
||||
msgid "update settings of process PID"
|
||||
msgstr "Einstellungen der Prozess-PID updaten"
|
||||
|
||||
#: src/main/help.c:372
|
||||
#: src/main/help.c:442
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
msgstr "den Fortschritt des PID-Prozesses darstellen"
|
||||
|
||||
#: src/main/help.c:377
|
||||
#: src/main/help.c:446
|
||||
msgid "run a command and monitor its standard input, output, or both"
|
||||
msgstr ""
|
||||
"Ein Programm ausführen und dessen Standardeingabe, -ausgabe oder beides "
|
||||
"überwachen"
|
||||
|
||||
#: src/main/help.c:450
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "Prozess-ID in DATEI speichern"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:453
|
||||
msgid "show this help and exit"
|
||||
msgstr "zeige diese Hilfe und beende"
|
||||
|
||||
#: src/main/help.c:383
|
||||
#: src/main/help.c:456
|
||||
msgid "show version information and exit"
|
||||
msgstr "zeige Versionsinformationen und beende"
|
||||
|
||||
#: src/main/help.c:387
|
||||
#: src/main/help.c:460
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "schreibe Debug-Protokolle in DATEI"
|
||||
|
||||
#: src/main/help.c:413
|
||||
#: src/main/help.c:486
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Aufruf: %s [OPTION] [DATEI]..."
|
||||
|
||||
#: src/main/help.c:424
|
||||
#: src/main/help.c:497
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
"Verbindet DATEI(en) oder den Standard-Eingabe-Kanal mit dem Standard-Ausgabe-"
|
||||
"Kanal und misst den Datenstrom."
|
||||
|
||||
#: src/main/help.c:562
|
||||
#: src/main/help.c:639
|
||||
msgid "Supported format sequences:"
|
||||
msgstr "unterstützte Formate:"
|
||||
|
||||
#: src/main/help.c:576
|
||||
#: src/main/help.c:653
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Bitte senden Sie Fehlerberichte an %s"
|
||||
|
||||
#: src/main/main.c:228
|
||||
#: src/main/main.c:225
|
||||
msgid "(input)"
|
||||
msgstr "(eingabe)"
|
||||
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr "Speicherzuweisung für `state' fehlgeschlagen"
|
||||
#: src/main/main.c:381 src/main/options.c:1359
|
||||
msgid "a command to run must be specified"
|
||||
msgstr "es muss ein auszuführendes Programm angegeben werden"
|
||||
|
||||
#: src/main/options.c:370
|
||||
#: src/main/main.c:704 src/main/options.c:757 src/main/options.c:777
|
||||
#: src/pv/display.c:1086 src/pv/state.c:45 src/pv/state.c:902
|
||||
#: src/pv/state.c:914 src/pv/state.c:950 src/pv/transfer.c:1335
|
||||
#: src/pv/transfer.c:1451 src/pv/transfer.c:1778
|
||||
msgid "memory allocation failure"
|
||||
msgstr "Fehler bei der Speicheranforderung"
|
||||
|
||||
#: src/main/options.c:418
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
msgstr "Listendateien dürfen keine „@“-Zeilen enthalten"
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
#: src/main/options.c:438 src/main/options.c:440 src/main/options.c:901
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr "Prozess-ID oder PID:FD-Paar erwartet"
|
||||
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
#: src/main/options.c:449 src/main/options.c:451 src/main/options.c:908
|
||||
msgid "invalid process ID"
|
||||
msgstr "ungültige Prozess-ID"
|
||||
|
||||
#: src/main/options.c:448 src/pv/file.c:342
|
||||
msgid "failed to stat file"
|
||||
msgstr "konnte Dateiinformationen nicht lesen"
|
||||
|
||||
#: src/main/options.c:462
|
||||
msgid "is a directory"
|
||||
msgstr "ist ein Verzeichnis"
|
||||
|
||||
#: src/main/options.c:491
|
||||
msgid "failed to generate sysfs filename"
|
||||
msgstr "konnte Sysfs-Dateinamen nicht erzeugen"
|
||||
|
||||
#: src/main/options.c:513
|
||||
msgid "failed to read sysfs size file"
|
||||
msgstr "konnte Größe der Sysfs-Datei nicht lesen"
|
||||
|
||||
#: src/main/options.c:533
|
||||
msgid "failed to open block device"
|
||||
msgstr "konnte Blockgerät nicht öffnen"
|
||||
|
||||
#: src/main/options.c:543
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr "konnte Größe des Blockgeräts nicht ermitteln"
|
||||
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "Speicherzuweisung für `option' fehlgeschlagen"
|
||||
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "Speicherzuweisung für `argv' der Option fehlgeschlagen"
|
||||
|
||||
#: src/main/options.c:723
|
||||
#: src/main/options.c:829
|
||||
msgid "numeric value not understood"
|
||||
msgstr "numerischen Wert nicht verstanden"
|
||||
|
||||
#: src/main/options.c:743
|
||||
#: src/main/options.c:843
|
||||
msgid "integer argument expected"
|
||||
msgstr "Ganzzahliges Argument erwartet"
|
||||
|
||||
#: src/main/options.c:755
|
||||
#: src/main/options.c:853
|
||||
msgid "numeric argument expected"
|
||||
msgstr "numerisches Argument erwartet"
|
||||
|
||||
#: src/main/options.c:767
|
||||
#: src/main/options.c:864
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
msgstr "fehlender Dateiname"
|
||||
|
||||
#: src/main/options.c:795
|
||||
#: src/main/options.c:890
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
msgstr "fehlender Prozessname"
|
||||
|
||||
#: src/main/options.c:1056
|
||||
#: src/main/options.c:1182
|
||||
msgid "invalid side specification"
|
||||
msgstr "ungültige Seitenspezifikation"
|
||||
|
||||
#: src/main/options.c:1197
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "`%s --help' zeigt weitere Informationen an."
|
||||
msgstr "„%s --help“ zeigt weitere Informationen an."
|
||||
|
||||
#: src/main/options.c:1058
|
||||
#: src/main/options.c:1199
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "`%s -h' zeigt weitere Informationen an."
|
||||
msgstr "„%s -h“ zeigt weitere Informationen an."
|
||||
|
||||
#: src/main/options.c:1089
|
||||
#: src/main/options.c:1231
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -393,38 +386,50 @@ msgstr ""
|
||||
"Beim Beobachten von Dateideskriptoren können keine Optionen für den "
|
||||
"Zeilenmodus oder den Übertragungsmodifikator verwendet werden"
|
||||
|
||||
#: src/main/options.c:1098
|
||||
#: src/main/options.c:1239
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
"Beim Beobachten von Dateideskriptoren kann Cursor-Positionierung nicht "
|
||||
"verwendet werden"
|
||||
|
||||
#: src/main/options.c:1107
|
||||
#: src/main/options.c:1247
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
"Beim Beobachten von Dateideskriptoren kann die Fernbedienung nicht verwenden "
|
||||
"werden"
|
||||
|
||||
#: src/main/options.c:1116
|
||||
#: src/main/options.c:1255
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
"Remote-Abfragen können beim Überwachen von Dateideskriptoren nicht verwendet "
|
||||
"werden"
|
||||
|
||||
#: src/main/options.c:1125
|
||||
#: src/main/options.c:1263
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
"Beim Beobachten von Dateideskriptoren können Dateien nicht übertragen werden"
|
||||
|
||||
#: src/main/options.c:1150
|
||||
#: src/main/options.c:1287
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "Nicht verfügbar auf Systemen ohne /proc/self/fdinfo"
|
||||
|
||||
#: src/main/options.c:1162
|
||||
#: src/main/options.c:1298
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
"Fernsteuerung und Fernabfrage können nicht gleichzeitig verwendet werden"
|
||||
|
||||
#: src/main/options.c:1189
|
||||
msgid "files cannot be specified with this option"
|
||||
#: src/main/options.c:1325
|
||||
msgid "monitor mode cannot be specified with this option"
|
||||
msgstr "Der Monitormodus kann mit dieser Option nicht angegeben werden"
|
||||
|
||||
#: src/main/options.c:1337
|
||||
msgid "monitor mode cannot be used with store-and-forward"
|
||||
msgstr ""
|
||||
"Der Monitormodus kann nicht mit Speichern-und-Weiterleiten verwendet werden"
|
||||
|
||||
#: src/main/options.c:1348
|
||||
msgid "files cannot be specified with this option"
|
||||
msgstr "mit dieser Option können keine Dateien angegeben werden"
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid "License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
@@ -442,64 +447,44 @@ msgstr "Es besteht KEINE GARANTIE, soweit dies gesetzlich zulässig ist."
|
||||
msgid "Project web site"
|
||||
msgstr "Projekt-Website"
|
||||
|
||||
#: src/pv/cursor.c:61
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "konnte Terminalname nicht lesen"
|
||||
|
||||
#: src/pv/cursor.c:106
|
||||
#: src/pv/cursor.c:108 src/pv/cursor.c:135
|
||||
msgid "failed to open lock file"
|
||||
msgstr "konnte Sperrdatei nicht öffnen"
|
||||
|
||||
#: src/pv/cursor.c:139
|
||||
msgid "lock attempt failed"
|
||||
msgstr "Sperrversuch fehlgeschlagen"
|
||||
#: src/pv/cursor.c:790 src/pv/cursor.c:792
|
||||
msgid "interrupted by a signal"
|
||||
msgstr "von einem Signal unterbrochen"
|
||||
|
||||
#: src/pv/cursor.c:400
|
||||
msgid "failed to open terminal"
|
||||
msgstr "konnte Terminal nicht öffnen"
|
||||
|
||||
#: src/pv/display.c:285
|
||||
#: src/pv/display.c:311
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr "yzafpnµm kMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:303
|
||||
#: src/pv/display.c:329
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr "yzafpnµm KMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "Speicherzuweisung für den Puffer fehlgeschlagen"
|
||||
#: src/pv/file.c:81
|
||||
msgid "/dev/null is not usable"
|
||||
msgstr "/dev/null ist nicht verwendbar"
|
||||
|
||||
#: src/pv/file.c:153
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr "Konnte nicht zum Anfang der Ausgabe springen"
|
||||
#: src/pv/file.c:371
|
||||
msgid "error closing file"
|
||||
msgstr "Fehler beim Schließen der Datei"
|
||||
|
||||
#: src/pv/file.c:303
|
||||
msgid "failed to close file"
|
||||
msgstr "konnte Datei nicht schließen"
|
||||
#: src/pv/file.c:438
|
||||
msgid "input file is also the output"
|
||||
msgstr "die Eingabedatei ist auch die Ausgabedatei"
|
||||
|
||||
#: src/pv/file.c:335
|
||||
msgid "failed to read file"
|
||||
msgstr "konnte Datei nicht lesen"
|
||||
|
||||
#: src/pv/file.c:350
|
||||
msgid "failed to stat output file"
|
||||
msgstr "konnte Dateiinformationen für Ausgabe-Datei nicht lesen"
|
||||
|
||||
#: src/pv/file.c:372
|
||||
msgid "input file is output file"
|
||||
msgstr "Eingabe-Datei ist Ausgabe-Datei"
|
||||
|
||||
#: src/pv/file.c:429
|
||||
#: src/pv/file.c:596
|
||||
msgid "(none)"
|
||||
msgstr "(keine)"
|
||||
|
||||
#: src/pv/file.c:431
|
||||
#: src/pv/file.c:598
|
||||
msgid "(stdin)"
|
||||
msgstr "(stdin)"
|
||||
|
||||
#: src/pv/format/averagerate.c:34 src/pv/format/progressbar.c:92
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:181
|
||||
msgid "b/s"
|
||||
msgstr "b/s"
|
||||
|
||||
@@ -509,7 +494,7 @@ msgid "/s"
|
||||
msgstr "/s"
|
||||
|
||||
#: src/pv/format/averagerate.c:38 src/pv/format/progressbar.c:96
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:181
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
@@ -517,103 +502,141 @@ msgstr "B/s"
|
||||
msgid "b"
|
||||
msgstr "b"
|
||||
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:620
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:1284
|
||||
msgid "B"
|
||||
msgstr "B"
|
||||
|
||||
#: src/pv/format/eta.c:52 src/pv/format/eta.c:56
|
||||
#: src/pv/format/eta.c:63 src/pv/format/eta.c:67
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/format/fineta.c:80
|
||||
#: src/pv/format/fineta.c:93
|
||||
msgid "FIN"
|
||||
msgstr "Endzeit"
|
||||
|
||||
#: src/pv/loop.c:120
|
||||
#: src/pv/loop.c:180
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr "Rate min/mittel/max/abweichung"
|
||||
|
||||
#: src/pv/loop.c:132
|
||||
#: src/pv/loop.c:192
|
||||
msgid "rate not measured"
|
||||
msgstr "Übertragungsrate nicht gemessen"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/loop.c:818 src/pv/loop.c:836 src/pv/watchpid.c:101
|
||||
#: src/pv/watchpid.c:110 src/pv/watchpid.c:121 src/pv/watchpid.c:129
|
||||
#: src/pv/watchpid.c:166 src/pv/watchpid.c:185 src/pv/watchpid.c:193
|
||||
#: src/pv/watchpid.c:203 src/pv/watchpid.c:307 src/pv/watchpid.c:315
|
||||
#: src/pv/watchpid.c:447 src/pv/watchpid.c:470
|
||||
#: src/pv/loop.c:1098 src/pv/loop.c:1114 src/pv/loop.c:1132 src/pv/remote.c:93
|
||||
#: src/pv/remote.c:188 src/pv/remote.c:536 src/pv/remote.c:582
|
||||
#: src/pv/watchpid.c:123 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:158 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:206 src/pv/watchpid.c:218 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:286 src/pv/watchpid.c:401
|
||||
#: src/pv/watchpid.c:409 src/pv/watchpid.c:556 src/pv/watchpid.c:565
|
||||
#: src/pv/watchpid.c:586
|
||||
msgid "pid"
|
||||
msgstr "pid"
|
||||
|
||||
#: src/pv/loop.c:836 src/pv/watchpid.c:110 src/pv/watchpid.c:122
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:185 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:205
|
||||
#: src/pv/loop.c:1132 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:160 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:288
|
||||
msgid "fd"
|
||||
msgstr "fd"
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
#: src/pv/remote.c:242 src/pv/remote.c:636
|
||||
msgid "message not received"
|
||||
msgstr "Nachricht nicht empfangen"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
#: src/pv/remote.c:659 src/pv/remote.c:677
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO wird auf diesem System nicht unterstützt"
|
||||
|
||||
#: src/pv/state.c:42
|
||||
msgid "history structure allocation failed"
|
||||
msgstr "Speicherzuweisung für `history' fehlgeschlagen"
|
||||
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr "Speicherzuweisung für die Dateiliste fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr "read-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:506
|
||||
#: src/pv/transfer.c:1173
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "warnung: lesefehler erkannt"
|
||||
|
||||
#: src/pv/transfer.c:522
|
||||
msgid "file is not seekable"
|
||||
msgstr "Datei ist nicht durchsuchbar"
|
||||
|
||||
#: src/pv/transfer.c:599
|
||||
msgid "failed to seek past error"
|
||||
msgstr "konnte den Fehler nicht überwinden"
|
||||
|
||||
#: src/pv/transfer.c:619
|
||||
#: src/pv/transfer.c:1283
|
||||
msgid "skipped past read error"
|
||||
msgstr "über den Lesefehler hinaus verschoben"
|
||||
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr "Speicherzuweisung für den Transferpuffer fehlgeschlagen"
|
||||
#: src/pv/transfer.c:1642
|
||||
msgid "write error"
|
||||
msgstr "Schreibfehler"
|
||||
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr "konnte Intervall-Timer nicht setzen"
|
||||
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr "konnte Intervall-Timer nicht löschen"
|
||||
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr "Zuweisung des Zeilenpuffers fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "write-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "select-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
#: src/pv/watchpid.c:160 src/pv/watchpid.c:288
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "ist weder eine normale Datei noch ein Blockgerät"
|
||||
|
||||
#~ msgid "state allocation failed"
|
||||
#~ msgstr "Speicherzuweisung für `state' fehlgeschlagen"
|
||||
|
||||
#~ msgid "failed to stat file"
|
||||
#~ msgstr "konnte Dateiinformationen nicht lesen"
|
||||
|
||||
#~ msgid "is a directory"
|
||||
#~ msgstr "ist ein Verzeichnis"
|
||||
|
||||
#~ msgid "failed to generate sysfs filename"
|
||||
#~ msgstr "konnte Sysfs-Dateinamen nicht erzeugen"
|
||||
|
||||
#~ msgid "failed to read sysfs size file"
|
||||
#~ msgstr "konnte Größe der Sysfs-Datei nicht lesen"
|
||||
|
||||
#~ msgid "failed to open block device"
|
||||
#~ msgstr "konnte Blockgerät nicht öffnen"
|
||||
|
||||
#~ msgid "failed to determine size of block device"
|
||||
#~ msgstr "konnte Größe des Blockgeräts nicht ermitteln"
|
||||
|
||||
#~ msgid "option structure allocation failed"
|
||||
#~ msgstr "Speicherzuweisung für `option' fehlgeschlagen"
|
||||
|
||||
#~ msgid "option structure argv allocation failed"
|
||||
#~ msgstr "Speicherzuweisung für `argv' der Option fehlgeschlagen"
|
||||
|
||||
#~ msgid "failed to get terminal name"
|
||||
#~ msgstr "konnte Terminalname nicht lesen"
|
||||
|
||||
#~ msgid "lock attempt failed"
|
||||
#~ msgstr "Sperrversuch fehlgeschlagen"
|
||||
|
||||
#~ msgid "failed to open terminal"
|
||||
#~ msgstr "konnte Terminal nicht öffnen"
|
||||
|
||||
#~ msgid "failed to seek to start of output"
|
||||
#~ msgstr "Konnte nicht zum Anfang der Ausgabe springen"
|
||||
|
||||
#~ msgid "failed to read file"
|
||||
#~ msgstr "konnte Datei nicht lesen"
|
||||
|
||||
#~ msgid "failed to stat output file"
|
||||
#~ msgstr "konnte Dateiinformationen für Ausgabe-Datei nicht lesen"
|
||||
|
||||
#~ msgid "history structure allocation failed"
|
||||
#~ msgstr "Speicherzuweisung für `history' fehlgeschlagen"
|
||||
|
||||
#~ msgid "file list allocation failed"
|
||||
#~ msgstr "Speicherzuweisung für die Dateiliste fehlgeschlagen"
|
||||
|
||||
#~ msgid "read failed"
|
||||
#~ msgstr "read-Aufruf fehlgeschlagen"
|
||||
|
||||
#~ msgid "file is not seekable"
|
||||
#~ msgstr "Datei ist nicht durchsuchbar"
|
||||
|
||||
#~ msgid "failed to seek past error"
|
||||
#~ msgstr "konnte den Fehler nicht überwinden"
|
||||
|
||||
#~ msgid "no transfer buffer allocated"
|
||||
#~ msgstr "Speicherzuweisung für den Transferpuffer fehlgeschlagen"
|
||||
|
||||
#~ msgid "failed to set interval timer"
|
||||
#~ msgstr "konnte Intervall-Timer nicht setzen"
|
||||
|
||||
#~ msgid "failed to clear interval timer"
|
||||
#~ msgstr "konnte Intervall-Timer nicht löschen"
|
||||
|
||||
#~ msgid "line position buffer allocation failed"
|
||||
#~ msgstr "Zuweisung des Zeilenpuffers fehlgeschlagen"
|
||||
|
||||
#~ msgid "select call failed"
|
||||
#~ msgstr "select-Aufruf fehlgeschlagen"
|
||||
|
||||
#~ msgid "PID[:FD]"
|
||||
#~ msgstr "PID[:FD]"
|
||||
|
||||
@@ -2,407 +2,409 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pv 1.9.34\n"
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-12-15 20:10+0000\n"
|
||||
"PO-Revision-Date: 2025-11-22 15:06+0000\n"
|
||||
"Last-Translator: artnay <artnay@noreply.codeberg.org>\n"
|
||||
"POT-Creation-Date: 2026-08-01 14:53+0100\n"
|
||||
"PO-Revision-Date: 2026-03-24 23:25+0000\n"
|
||||
"Last-Translator: Ricky-Tigg <ricky-tigg@noreply.codeberg.org>\n"
|
||||
"Language-Team: Finnish <https://translate.codeberg.org/projects/pv/pv/fi/>\n"
|
||||
"Language: fi\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.14\n"
|
||||
"X-Generator: Weblate 5.16.2\n"
|
||||
|
||||
#: src/main/help.c:236
|
||||
#: src/main/help.c:300
|
||||
msgid "show progress bar"
|
||||
msgstr "näytä edistymispalkki"
|
||||
|
||||
#: src/main/help.c:239
|
||||
#: src/main/help.c:303
|
||||
msgid "show elapsed time"
|
||||
msgstr "näytä kulunut aika"
|
||||
|
||||
#: src/main/help.c:242
|
||||
#: src/main/help.c:306
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "näytä arvioitu valmistumisaika"
|
||||
|
||||
#: src/main/help.c:245
|
||||
#: src/main/help.c:309
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "näytä absoluuttinen arvioitu valmistumisaika"
|
||||
|
||||
#: src/main/help.c:248
|
||||
#: src/main/help.c:312
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "näytä datan siirtonopeuden laskuri"
|
||||
|
||||
#: src/main/help.c:251
|
||||
#: src/main/help.c:315
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "näytä datan keskimääräisen siirtonopeuden laskuri"
|
||||
|
||||
#: src/main/help.c:254
|
||||
#: src/main/help.c:318
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "näytä siirrettyjen tavujen määrä"
|
||||
|
||||
#: src/main/help.c:257
|
||||
#: src/main/help.c:321
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr ""
|
||||
msgstr "näytä käytössä olevan siirtopuskurin prosenttiosuus"
|
||||
|
||||
#: src/main/help.c:259
|
||||
#: src/main/help.c:323
|
||||
msgid "NUM"
|
||||
msgstr "NUM"
|
||||
|
||||
#: src/main/help.c:260
|
||||
#: src/main/help.c:324
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "näytä NUM viimeksi kirjoitettua tavua"
|
||||
|
||||
#: src/main/help.c:262
|
||||
#: src/main/help.c:326
|
||||
msgid "FORMAT"
|
||||
msgstr "MUOTO"
|
||||
|
||||
#: src/main/help.c:263
|
||||
#: src/main/help.c:327
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "aseta tulostemuodoksi MUOTO"
|
||||
|
||||
#: src/main/help.c:266
|
||||
#: src/main/help.c:330
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "tulosta prosentit, ei visuaalista tietoa"
|
||||
|
||||
#: src/main/help.c:269
|
||||
#: src/main/help.c:333
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "älä tulosta minkäänlaista siirtotietoa"
|
||||
|
||||
#: src/main/help.c:273
|
||||
#: src/main/help.c:337
|
||||
msgid "show number of bits transferred"
|
||||
msgstr "näytä siirrettyjen bittien määrä"
|
||||
|
||||
#: src/main/help.c:276
|
||||
#: src/main/help.c:340
|
||||
msgid "treat suffixes as multiples of 1000 rather than 1024"
|
||||
msgstr "käsittele päätteitä 1000:n kertoimina 1024:n sijaan"
|
||||
|
||||
#: src/main/help.c:279
|
||||
#: src/main/help.c:343
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "älä näytä mitään, ennen kuin ensimmäinen tavu on siirretty"
|
||||
|
||||
#: src/main/help.c:281 src/main/help.c:296 src/main/help.c:299
|
||||
#: src/main/help.c:345 src/main/help.c:360 src/main/help.c:363
|
||||
msgid "SEC"
|
||||
msgstr ""
|
||||
msgstr "SEK"
|
||||
|
||||
#: src/main/help.c:282
|
||||
#: src/main/help.c:346
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "älä näytä mitään, ennen kuin SEC sekuntia on kulunut"
|
||||
|
||||
#: src/main/help.c:284
|
||||
#: src/main/help.c:348
|
||||
msgid "SIZE"
|
||||
msgstr "KOKO"
|
||||
|
||||
#: src/main/help.c:285
|
||||
#: src/main/help.c:349
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "aseta arvioiduksi datan kooksi KOKO tavua"
|
||||
|
||||
#: src/main/help.c:288
|
||||
#: src/main/help.c:352
|
||||
msgid "if size unknown, show rate vs max rate"
|
||||
msgstr ""
|
||||
msgstr "Jos kokoa ei tiedetä, näytä nopeus vs. maksiminopeus"
|
||||
|
||||
#: src/main/help.c:291
|
||||
#: src/main/help.c:355
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "laske rivit tavujen sijaan"
|
||||
|
||||
#: src/main/help.c:294
|
||||
#: src/main/help.c:358
|
||||
msgid "lines are null-terminated"
|
||||
msgstr ""
|
||||
msgstr "rivit päättyvät nullilla"
|
||||
|
||||
#: src/main/help.c:297
|
||||
#: src/main/help.c:361
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "päivitä SEC sekunnin välein"
|
||||
|
||||
#: src/main/help.c:300
|
||||
#: src/main/help.c:364
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr "laske keskimääräinen siirtonopeus SEC sekunnin ajalta (oletus 30 s)"
|
||||
|
||||
#: src/main/help.c:302
|
||||
#: src/main/help.c:366
|
||||
msgid "WIDTH"
|
||||
msgstr "LEVEYS"
|
||||
|
||||
#: src/main/help.c:303
|
||||
#: src/main/help.c:367
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "oleta, että päätteen LEVEYS on merkkiä leveä"
|
||||
|
||||
#: src/main/help.c:305
|
||||
#: src/main/help.c:369
|
||||
msgid "HEIGHT"
|
||||
msgstr "KORKEUS"
|
||||
|
||||
#: src/main/help.c:306
|
||||
#: src/main/help.c:370
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "oleta, että päätteen KORKEUS on merkkiä korkea"
|
||||
|
||||
#: src/main/help.c:308
|
||||
#: src/main/help.c:372
|
||||
msgid "NAME"
|
||||
msgstr "NIMI"
|
||||
|
||||
#: src/main/help.c:309
|
||||
#: src/main/help.c:373
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr ""
|
||||
msgstr "lisää visuaalisiin tietoihin NIMI-etuliite"
|
||||
|
||||
#: src/main/help.c:311
|
||||
#: src/main/help.c:375
|
||||
msgid "STYLE"
|
||||
msgstr "TYYLI"
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "set default bar style to NAME"
|
||||
msgstr ""
|
||||
#: src/main/help.c:376
|
||||
msgid "set default bar style to STYLE"
|
||||
msgstr "aseta oletuspalkkityyli TYYLI:lle"
|
||||
|
||||
#: src/main/help.c:314
|
||||
#: src/main/help.c:378
|
||||
msgid "SPEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:315
|
||||
#: src/main/help.c:379
|
||||
msgid "also send progress to SPEC"
|
||||
msgstr "lähetä edistyminen myös SPECille"
|
||||
|
||||
#: src/main/help.c:382
|
||||
msgid "set terminal progress state with OSC 9;4 (ConEmu)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:318
|
||||
#: src/main/help.c:385
|
||||
msgid "output transfer statistics at the end"
|
||||
msgstr "tulosta siirtotilastot lopussa"
|
||||
|
||||
#: src/main/help.c:321
|
||||
#: src/main/help.c:388
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr ""
|
||||
msgstr "tuloste, vaikka vakiovirhe ei olisikaan päätelaite"
|
||||
|
||||
#: src/main/help.c:324
|
||||
#: src/main/help.c:391
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr ""
|
||||
msgstr "käytä kohdistimen sijoittelun esc-sekvenssiä"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
#: src/main/help.c:394 src/main/help.c:430 src/main/help.c:449
|
||||
#: src/main/help.c:459
|
||||
msgid "FILE"
|
||||
msgstr "TIEDOSTO"
|
||||
|
||||
#: src/main/help.c:328
|
||||
#: src/main/help.c:395
|
||||
msgid "write output to FILE instead of stdout"
|
||||
msgstr "kirjoita tuloste tiedostoon TIEDOSTO oletustulosteen (stdout) sijaan"
|
||||
|
||||
#: src/main/help.c:330
|
||||
#: src/main/help.c:397
|
||||
msgid "RATE"
|
||||
msgstr "NOPEUS"
|
||||
|
||||
#: src/main/help.c:331
|
||||
#: src/main/help.c:398
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "rajoita siirron nopeudeksi NOPEUS tavua per sekunti"
|
||||
|
||||
#: src/main/help.c:333 src/main/help.c:342
|
||||
#: src/main/help.c:400 src/main/help.c:406 src/main/help.c:412
|
||||
msgid "BYTES"
|
||||
msgstr ""
|
||||
msgstr "TAVUT"
|
||||
|
||||
#: src/main/help.c:334
|
||||
#: src/main/help.c:401
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr ""
|
||||
msgstr "käytä puskuria, jonka koko on TAVUT"
|
||||
|
||||
#: src/main/help.c:337
|
||||
#: src/main/help.c:404
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "Älä koskaan käytä splice():tta, käytä aina luku-/kirjoitustoimintoa"
|
||||
|
||||
#: src/main/help.c:407
|
||||
msgid "set the pipe buffer size to BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:340
|
||||
#: src/main/help.c:410
|
||||
msgid "skip read errors in input"
|
||||
msgstr "ohita lukuvirheet syötteessä"
|
||||
|
||||
#: src/main/help.c:343
|
||||
#: src/main/help.c:413
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr ""
|
||||
msgstr "ohita virheet TAVUT:ssa lohkoissa kerrallaan"
|
||||
|
||||
#: src/main/help.c:346
|
||||
#: src/main/help.c:416
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "lopeta kun --size tavua on siirretty"
|
||||
|
||||
#: src/main/help.c:349
|
||||
#: src/main/help.c:419
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr ""
|
||||
msgstr "tyhjennä välimuisti levylle jokaisen kirjoituksen jälkeen"
|
||||
|
||||
#: src/main/help.c:352
|
||||
#: src/main/help.c:422
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
msgstr "käytä suoraa syötettä/lähtöä välimuistin ohittamiseen"
|
||||
|
||||
#: src/main/help.c:355
|
||||
#: src/main/help.c:425
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
msgstr "yritä etsiä tyhjätavujen kirjoittamisen sijaan"
|
||||
|
||||
#: src/main/help.c:358
|
||||
#: src/main/help.c:428
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
msgstr "hylkää syöte tulosteeseen kirjoittamisen sijaan"
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:431
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr ""
|
||||
"kirjoita kaikki syöte tiedostoon TIEDOSTO ennen tulosteeseen kirjoittamista"
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:434
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
msgstr "PID[:FD]|=NIMI|@LISTATIEDOSTO"
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:435
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr ""
|
||||
msgstr "tarkkaile tiedostoa FD, jonka prosessi PID avasi"
|
||||
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
#: src/main/help.c:438 src/main/help.c:441
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:369
|
||||
#: src/main/help.c:439
|
||||
msgid "update settings of process PID"
|
||||
msgstr ""
|
||||
msgstr "päivitä prosessin PID-asetukset"
|
||||
|
||||
#: src/main/help.c:372
|
||||
#: src/main/help.c:442
|
||||
msgid "show progress of process PID"
|
||||
msgstr "näytä prosessin PID:n edistyminen"
|
||||
|
||||
#: src/main/help.c:446
|
||||
msgid "run a command and monitor its standard input, output, or both"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
#: src/main/help.c:450
|
||||
msgid "save process ID in FILE"
|
||||
msgstr ""
|
||||
msgstr "tallenna prosessitunnus TIEDOSTO:on"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:453
|
||||
msgid "show this help and exit"
|
||||
msgstr "näytä tämä ohje ja lopeta"
|
||||
|
||||
#: src/main/help.c:383
|
||||
#: src/main/help.c:456
|
||||
msgid "show version information and exit"
|
||||
msgstr "näytä versiotiedot ja lopeta"
|
||||
|
||||
#: src/main/help.c:387
|
||||
#: src/main/help.c:460
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "kirjoita vianjäljityslokit tiedostoon TIEDOSTO"
|
||||
|
||||
#: src/main/help.c:413
|
||||
#: src/main/help.c:486
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Käyttö: %s [VALINTA] [TIEDOSTO]..."
|
||||
|
||||
#: src/main/help.c:424
|
||||
#: src/main/help.c:497
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
"Putkita TIEDOSTO(t), tai vakiosyöte, vakiotulosteeseen, monitoroinnin kanssa."
|
||||
|
||||
#: src/main/help.c:562
|
||||
#: src/main/help.c:639
|
||||
msgid "Supported format sequences:"
|
||||
msgstr "Tuetut muotosekvenssit:"
|
||||
|
||||
#: src/main/help.c:576
|
||||
#: src/main/help.c:653
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Ilmoita ongelmista: %s"
|
||||
|
||||
#: src/main/main.c:228
|
||||
#: src/main/main.c:225
|
||||
msgid "(input)"
|
||||
msgstr "(syöte)"
|
||||
|
||||
#: src/main/main.c:381 src/main/options.c:1359
|
||||
msgid "a command to run must be specified"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr ""
|
||||
#: src/main/main.c:704 src/main/options.c:757 src/main/options.c:777
|
||||
#: src/pv/display.c:1086 src/pv/state.c:45 src/pv/state.c:902
|
||||
#: src/pv/state.c:914 src/pv/state.c:950 src/pv/transfer.c:1335
|
||||
#: src/pv/transfer.c:1451 src/pv/transfer.c:1778
|
||||
msgid "memory allocation failure"
|
||||
msgstr "muistinvarausvirhe"
|
||||
|
||||
#: src/main/options.c:370
|
||||
#: src/main/options.c:418
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
msgstr "Listatiedostot eivät saa sisältää @-rivejä"
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
#: src/main/options.c:438 src/main/options.c:440 src/main/options.c:901
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr ""
|
||||
msgstr "prosessitunnusta tai pid:fd-paria odotetaan"
|
||||
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
#: src/main/options.c:449 src/main/options.c:451 src/main/options.c:908
|
||||
msgid "invalid process ID"
|
||||
msgstr "virheellinen prosessin ID"
|
||||
|
||||
#: src/main/options.c:448 src/pv/file.c:342
|
||||
msgid "failed to stat file"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:462
|
||||
msgid "is a directory"
|
||||
msgstr "on hakemisto"
|
||||
|
||||
#: src/main/options.c:491
|
||||
msgid "failed to generate sysfs filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:513
|
||||
msgid "failed to read sysfs size file"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:533
|
||||
msgid "failed to open block device"
|
||||
msgstr "lohkolaitteen avaaminen epäonnistui"
|
||||
|
||||
#: src/main/options.c:543
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr "lohkolaitteen koon päättely epäonnistui"
|
||||
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:723
|
||||
#: src/main/options.c:829
|
||||
msgid "numeric value not understood"
|
||||
msgstr "numeerista arvoa ei ymmärretty"
|
||||
|
||||
#: src/main/options.c:743
|
||||
#: src/main/options.c:843
|
||||
msgid "integer argument expected"
|
||||
msgstr ""
|
||||
msgstr "kokonaislukuargumenttia odotetaan"
|
||||
|
||||
#: src/main/options.c:755
|
||||
#: src/main/options.c:853
|
||||
msgid "numeric argument expected"
|
||||
msgstr ""
|
||||
msgstr "numeerista argumenttia odotetaan"
|
||||
|
||||
#: src/main/options.c:767
|
||||
#: src/main/options.c:864
|
||||
msgid "missing filename"
|
||||
msgstr "puuttuva tiedostonimi"
|
||||
|
||||
#: src/main/options.c:795
|
||||
#: src/main/options.c:890
|
||||
msgid "missing process name"
|
||||
msgstr "puuttuva prosessinimi"
|
||||
|
||||
#: src/main/options.c:1056
|
||||
#: src/main/options.c:1182
|
||||
msgid "invalid side specification"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1197
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Suorita `%s --help' saadaksesi lisätietoja."
|
||||
|
||||
#: src/main/options.c:1058
|
||||
#: src/main/options.c:1199
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Suorita `%s -h' saadaksesi lisätietoja."
|
||||
|
||||
#: src/main/options.c:1089
|
||||
#: src/main/options.c:1231
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
msgstr ""
|
||||
"rivitilaa tai siirtomuokkausvaihtoehtoja ei voi käyttää tiedostokuvauksia "
|
||||
"tarkasteltaessa"
|
||||
|
||||
#: src/main/options.c:1098
|
||||
#: src/main/options.c:1239
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
"kohdistimen sijoittelua ei voi käyttää tiedostokuvauksia tarkasteltaessa"
|
||||
|
||||
#: src/main/options.c:1107
|
||||
#: src/main/options.c:1247
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
msgstr "etäohjausta ei voi käyttää tiedostokuvauksia tarkasteltaessa"
|
||||
|
||||
#: src/main/options.c:1116
|
||||
#: src/main/options.c:1255
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
msgstr "etäkyselyä ei voi käyttää tiedostokuvauksia tarkasteltaessa"
|
||||
|
||||
#: src/main/options.c:1125
|
||||
#: src/main/options.c:1263
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
msgstr "tiedostoja ei voi siirtää tiedostokuvauksia tarkasteltaessa"
|
||||
|
||||
#: src/main/options.c:1150
|
||||
#: src/main/options.c:1287
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr ""
|
||||
msgstr "ei saatavilla järjestelmissä, joissa ei ole /proc/self/fdinfo"
|
||||
|
||||
#: src/main/options.c:1162
|
||||
#: src/main/options.c:1298
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr "etäohjausta ja etäkyselyä ei voi käyttää yhdessä"
|
||||
|
||||
#: src/main/options.c:1325
|
||||
msgid "monitor mode cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1189
|
||||
msgid "files cannot be specified with this option"
|
||||
#: src/main/options.c:1337
|
||||
msgid "monitor mode cannot be used with store-and-forward"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1348
|
||||
msgid "files cannot be specified with this option"
|
||||
msgstr "tiedostoja ei voi määrittää tämän vaihtoehdon kanssa"
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid "License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
msgstr "Lisenssi: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
@@ -410,73 +412,55 @@ msgstr "Lisenssi: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
#: src/main/version.c:29
|
||||
msgid "This is free software: you are free to change and redistribute it."
|
||||
msgstr ""
|
||||
"Tämä on ilmaista ohjelmistoa: voit vapaasti muokata sitä ja levittää sitä "
|
||||
"uudelleen."
|
||||
|
||||
#: src/main/version.c:30
|
||||
msgid "There is NO WARRANTY, to the extent permitted by law."
|
||||
msgstr ""
|
||||
msgstr "TAKUUTA EI OLE, lain sallimissa rajoissa."
|
||||
|
||||
#: src/main/version.c:32
|
||||
msgid "Project web site"
|
||||
msgstr "Projektin verkkosivu"
|
||||
|
||||
#: src/pv/cursor.c:61
|
||||
msgid "failed to get terminal name"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:106
|
||||
#: src/pv/cursor.c:108 src/pv/cursor.c:135
|
||||
msgid "failed to open lock file"
|
||||
msgstr ""
|
||||
msgstr "lukitustiedoston avaaminen epäonnistui"
|
||||
|
||||
#: src/pv/cursor.c:139
|
||||
msgid "lock attempt failed"
|
||||
msgstr ""
|
||||
#: src/pv/cursor.c:790 src/pv/cursor.c:792
|
||||
msgid "interrupted by a signal"
|
||||
msgstr "signaalin keskeyttämä"
|
||||
|
||||
#: src/pv/cursor.c:400
|
||||
msgid "failed to open terminal"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:285
|
||||
#: src/pv/display.c:311
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:303
|
||||
#: src/pv/display.c:329
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
#: src/pv/file.c:81
|
||||
msgid "/dev/null is not usable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:153
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr ""
|
||||
#: src/pv/file.c:371
|
||||
msgid "error closing file"
|
||||
msgstr "virhe tiedoston sulkemisessa"
|
||||
|
||||
#: src/pv/file.c:303
|
||||
msgid "failed to close file"
|
||||
msgstr "tiedoston sulkeminen epäonnistui"
|
||||
#: src/pv/file.c:438
|
||||
msgid "input file is also the output"
|
||||
msgstr "syötetiedosto on myös tuotostiedosto"
|
||||
|
||||
#: src/pv/file.c:335
|
||||
msgid "failed to read file"
|
||||
msgstr "tiedoston lukeminen epäonnistui"
|
||||
|
||||
#: src/pv/file.c:350
|
||||
msgid "failed to stat output file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:372
|
||||
msgid "input file is output file"
|
||||
msgstr "syötetiedosto on tulostetiedosto"
|
||||
|
||||
#: src/pv/file.c:429
|
||||
#: src/pv/file.c:596
|
||||
msgid "(none)"
|
||||
msgstr ""
|
||||
msgstr "(ei mitään)"
|
||||
|
||||
#: src/pv/file.c:431
|
||||
#: src/pv/file.c:598
|
||||
msgid "(stdin)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/averagerate.c:34 src/pv/format/progressbar.c:92
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:181
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
@@ -486,108 +470,146 @@ msgid "/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/averagerate.c:38 src/pv/format/progressbar.c:96
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:181
|
||||
msgid "B/s"
|
||||
msgstr ""
|
||||
msgstr "T/s"
|
||||
|
||||
#: src/pv/format/bytes.c:35
|
||||
msgid "b"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:620
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:1284
|
||||
msgid "B"
|
||||
msgstr ""
|
||||
msgstr "T"
|
||||
|
||||
#: src/pv/format/eta.c:52 src/pv/format/eta.c:56
|
||||
#: src/pv/format/eta.c:63 src/pv/format/eta.c:67
|
||||
msgid "ETA"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/fineta.c:80
|
||||
#: src/pv/format/fineta.c:93
|
||||
msgid "FIN"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:120
|
||||
#: src/pv/loop.c:180
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:132
|
||||
#: src/pv/loop.c:192
|
||||
msgid "rate not measured"
|
||||
msgstr ""
|
||||
msgstr "nopeutta ei mitattu"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/loop.c:818 src/pv/loop.c:836 src/pv/watchpid.c:101
|
||||
#: src/pv/watchpid.c:110 src/pv/watchpid.c:121 src/pv/watchpid.c:129
|
||||
#: src/pv/watchpid.c:166 src/pv/watchpid.c:185 src/pv/watchpid.c:193
|
||||
#: src/pv/watchpid.c:203 src/pv/watchpid.c:307 src/pv/watchpid.c:315
|
||||
#: src/pv/watchpid.c:447 src/pv/watchpid.c:470
|
||||
#: src/pv/loop.c:1098 src/pv/loop.c:1114 src/pv/loop.c:1132 src/pv/remote.c:93
|
||||
#: src/pv/remote.c:188 src/pv/remote.c:536 src/pv/remote.c:582
|
||||
#: src/pv/watchpid.c:123 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:158 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:206 src/pv/watchpid.c:218 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:286 src/pv/watchpid.c:401
|
||||
#: src/pv/watchpid.c:409 src/pv/watchpid.c:556 src/pv/watchpid.c:565
|
||||
#: src/pv/watchpid.c:586
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:836 src/pv/watchpid.c:110 src/pv/watchpid.c:122
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:185 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:205
|
||||
#: src/pv/loop.c:1132 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:160 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:288
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
#: src/pv/remote.c:242 src/pv/remote.c:636
|
||||
msgid "message not received"
|
||||
msgstr ""
|
||||
msgstr "viestiä ei vastaanotettu"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
#: src/pv/remote.c:659 src/pv/remote.c:677
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO ei ole tuettu tässä järjestelmässä"
|
||||
|
||||
#: src/pv/state.c:42
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:506
|
||||
#: src/pv/transfer.c:1173
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "varoitus: lukuvirheitä havaittu"
|
||||
|
||||
#: src/pv/transfer.c:522
|
||||
msgid "file is not seekable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:599
|
||||
msgid "failed to seek past error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:619
|
||||
#: src/pv/transfer.c:1283
|
||||
msgid "skipped past read error"
|
||||
msgstr ""
|
||||
msgstr "aiempi lukuvirhe ohitettu"
|
||||
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
#: src/pv/transfer.c:1642
|
||||
msgid "write error"
|
||||
msgstr "kirjoitusvirhe"
|
||||
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "kirjoittaminen epäonnistui"
|
||||
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
#: src/pv/watchpid.c:160 src/pv/watchpid.c:288
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "ei tavallinen tiedosto tai lohkolaite"
|
||||
|
||||
#~ msgid "state allocation failed"
|
||||
#~ msgstr "tilan allokointi epäonnistui"
|
||||
|
||||
#~ msgid "failed to stat file"
|
||||
#~ msgstr "tiedoston tilastointi epäonnistui"
|
||||
|
||||
#~ msgid "is a directory"
|
||||
#~ msgstr "on hakemisto"
|
||||
|
||||
#~ msgid "failed to generate sysfs filename"
|
||||
#~ msgstr "sysfs-tiedostonimen luominen epäonnistui"
|
||||
|
||||
#~ msgid "failed to read sysfs size file"
|
||||
#~ msgstr "sysfs-kokotiedoston lukeminen epäonnistui"
|
||||
|
||||
#~ msgid "failed to open block device"
|
||||
#~ msgstr "lohkolaitteen avaaminen epäonnistui"
|
||||
|
||||
#~ msgid "failed to determine size of block device"
|
||||
#~ msgstr "lohkolaitteen koon päättely epäonnistui"
|
||||
|
||||
#~ msgid "option structure allocation failed"
|
||||
#~ msgstr "vaihtoehtorakenteen allokointi epäonnistui"
|
||||
|
||||
#~ msgid "option structure argv allocation failed"
|
||||
#~ msgstr "vaihtoehtorakenteen argv:n allokointi epäonnistui"
|
||||
|
||||
#~ msgid "failed to get terminal name"
|
||||
#~ msgstr "päätelaitteen nimen hakeminen epäonnistui"
|
||||
|
||||
#~ msgid "lock attempt failed"
|
||||
#~ msgstr "lukitusyritys epäonnistui"
|
||||
|
||||
#~ msgid "failed to open terminal"
|
||||
#~ msgstr "päätelaitteen avaaminen epäonnistui"
|
||||
|
||||
#~ msgid "failed to seek to start of output"
|
||||
#~ msgstr "tulosteen käynnistyksen hakeminen epäonnistui"
|
||||
|
||||
#~ msgid "failed to read file"
|
||||
#~ msgstr "tiedoston lukeminen epäonnistui"
|
||||
|
||||
#~ msgid "failed to stat output file"
|
||||
#~ msgstr "tulostiedoston tilastointi epäonnistui"
|
||||
|
||||
#~ msgid "history structure allocation failed"
|
||||
#~ msgstr "historiarakenteen allokointi epäonnistui"
|
||||
|
||||
#~ msgid "file list allocation failed"
|
||||
#~ msgstr "tiedostolistan allokointi epäonnistui"
|
||||
|
||||
#~ msgid "read failed"
|
||||
#~ msgstr "luku epäonnistui"
|
||||
|
||||
#~ msgid "file is not seekable"
|
||||
#~ msgstr "tiedosto ei ole haettavissa"
|
||||
|
||||
#~ msgid "failed to seek past error"
|
||||
#~ msgstr "menneen virheen hakeminen epäonnistui"
|
||||
|
||||
#~ msgid "no transfer buffer allocated"
|
||||
#~ msgstr "siirtopuskuria ei ole allokoitu"
|
||||
|
||||
#~ msgid "failed to set interval timer"
|
||||
#~ msgstr "aikaväliajastimen asettaminen epäonnistui"
|
||||
|
||||
#~ msgid "failed to clear interval timer"
|
||||
#~ msgstr "aikaväliajastimen tyhjennys epäonnistui"
|
||||
|
||||
#~ msgid "line position buffer allocation failed"
|
||||
#~ msgstr "rivin sijaintipuskurin allokointi epäonnistui"
|
||||
|
||||
#~ msgid "select call failed"
|
||||
#~ msgstr "valintakutsu epäonnistui"
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-12-15 20:10+0000\n"
|
||||
"PO-Revision-Date: 2025-05-31 08:58+0000\n"
|
||||
"Last-Translator: milimarg <milimarg@noreply.codeberg.org>\n"
|
||||
"POT-Creation-Date: 2026-08-01 14:53+0100\n"
|
||||
"PO-Revision-Date: 2026-08-01 18:32+0000\n"
|
||||
"Last-Translator: a-j-wood <a-j-wood@noreply.codeberg.org>\n"
|
||||
"Language-Team: French <https://translate.codeberg.org/projects/pv/pv/fr/>\n"
|
||||
"Language: fr\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 5.11.4\n"
|
||||
"X-Generator: Weblate 2026.7.1\n"
|
||||
"Date: 1999-06-01 15:18:29+0100\n"
|
||||
"From: Andrew Wood <ivarch@ubik>\n"
|
||||
"Xgettext-Options: --default-domain=pkgbuild --directory=./.pkgdir --add-"
|
||||
"comments --keyword=_ --keyword=N_\n"
|
||||
"Files: src/getopt/getopt.c src/getopt/getopt1.c src/version.c src/main/init."
|
||||
"c src/main/help.c src/main/xpmptr.c src/guts/load.c src/guts/stop.c src/guts/"
|
||||
"configure.c src/guts/make.c src/guts/install.c src/guts/prefs.c src/ui/"
|
||||
"Files: src/getopt/getopt.c src/getopt/getopt1.c src/version.c src/main/"
|
||||
"init.c src/main/help.c src/main/xpmptr.c src/guts/load.c src/guts/stop.c src/"
|
||||
"guts/configure.c src/guts/make.c src/guts/install.c src/guts/prefs.c src/ui/"
|
||||
"generate.c src/ui/main.c src/ui/xpm.c src/ui/status.c src/ui/activate.c src/"
|
||||
"ui/handlers/main.c src/ui/handlers/package.c src/ui/handlers/prefs.c src/ui/"
|
||||
"handlers/dirsel.c src/ui/handlers/popup.c src/ui/handlers/help.c src/ui/"
|
||||
@@ -26,367 +26,360 @@ msgstr ""
|
||||
"nls/intl/textdomain.c src/nls/intl-cat/cat-compat.c src/nls/intl-gett/intl-"
|
||||
"compat.c\n"
|
||||
|
||||
#: src/main/help.c:236
|
||||
#: src/main/help.c:300
|
||||
msgid "show progress bar"
|
||||
msgstr "afficher la barre de progression"
|
||||
|
||||
#: src/main/help.c:239
|
||||
#: src/main/help.c:303
|
||||
msgid "show elapsed time"
|
||||
msgstr "afficher le temps écoulé"
|
||||
|
||||
#: src/main/help.c:242
|
||||
#: src/main/help.c:306
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "afficher l'heure approximative de l'achèvement de la tâche"
|
||||
|
||||
#: src/main/help.c:245
|
||||
#: src/main/help.c:309
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "afficher l'heure absolute de l'achèvement de la tâche"
|
||||
|
||||
#: src/main/help.c:248
|
||||
#: src/main/help.c:312
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "afficher le taux de tranfert des données"
|
||||
|
||||
#: src/main/help.c:251
|
||||
#: src/main/help.c:315
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "afficher le compteur de taux moyen de transfert de données"
|
||||
|
||||
#: src/main/help.c:254
|
||||
#: src/main/help.c:318
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "afficher le nombre d'octets transférés"
|
||||
|
||||
#: src/main/help.c:257
|
||||
#: src/main/help.c:321
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "afficher le pourcentage de tampon de transfert utilisé"
|
||||
|
||||
#: src/main/help.c:259
|
||||
#: src/main/help.c:323
|
||||
msgid "NUM"
|
||||
msgstr "NUM"
|
||||
|
||||
#: src/main/help.c:260
|
||||
#: src/main/help.c:324
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "afficher les derniers NUM octets écrits"
|
||||
|
||||
#: src/main/help.c:262
|
||||
#: src/main/help.c:326
|
||||
msgid "FORMAT"
|
||||
msgstr "FORMAT"
|
||||
|
||||
#: src/main/help.c:263
|
||||
#: src/main/help.c:327
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "définir le format de sortie sur FORMAT"
|
||||
|
||||
#: src/main/help.c:266
|
||||
#: src/main/help.c:330
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "imprimer en pourcentage plutôt que des informations visuelles"
|
||||
|
||||
#: src/main/help.c:269
|
||||
#: src/main/help.c:333
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "n'afficher aucune information de transfert"
|
||||
|
||||
#: src/main/help.c:273
|
||||
#: src/main/help.c:337
|
||||
msgid "show number of bits transferred"
|
||||
msgstr "afficher le nombre de bits transférés"
|
||||
|
||||
#: src/main/help.c:276
|
||||
#: src/main/help.c:340
|
||||
msgid "treat suffixes as multiples of 1000 rather than 1024"
|
||||
msgstr "traiter les suffixes comme des multiples de 1000 au lieu de 1024"
|
||||
|
||||
#: src/main/help.c:279
|
||||
#: src/main/help.c:343
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "ne rien afficher avant qu'au moins un octet soit tranféré"
|
||||
|
||||
#: src/main/help.c:281 src/main/help.c:296 src/main/help.c:299
|
||||
#: src/main/help.c:345 src/main/help.c:360 src/main/help.c:363
|
||||
msgid "SEC"
|
||||
msgstr "SEC"
|
||||
|
||||
#: src/main/help.c:282
|
||||
#: src/main/help.c:346
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "ne rien afficher jusqu'à ce que SEC secondes se soient écoulées"
|
||||
|
||||
#: src/main/help.c:284
|
||||
#: src/main/help.c:348
|
||||
msgid "SIZE"
|
||||
msgstr "TAILLE"
|
||||
|
||||
#: src/main/help.c:285
|
||||
#: src/main/help.c:349
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "ajuster la taille estimée des données à TAILLE octets"
|
||||
|
||||
#: src/main/help.c:288
|
||||
#: src/main/help.c:352
|
||||
msgid "if size unknown, show rate vs max rate"
|
||||
msgstr ""
|
||||
"si la taille est inconnue, afficher le taux de transfert par rapport au taux "
|
||||
"de transfert max"
|
||||
|
||||
#: src/main/help.c:291
|
||||
#: src/main/help.c:355
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "compter les lignes au lieu des octets"
|
||||
|
||||
#: src/main/help.c:294
|
||||
#: src/main/help.c:358
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "les lignes sont terminées par un caractère nul"
|
||||
|
||||
#: src/main/help.c:297
|
||||
#: src/main/help.c:361
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "mettre à jour toutes les SEC secondes"
|
||||
|
||||
#: src/main/help.c:300
|
||||
#: src/main/help.c:364
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
"calculer le taux moyen d'après les SEC dernières secondes (30s par défaut)"
|
||||
|
||||
#: src/main/help.c:302
|
||||
#: src/main/help.c:366
|
||||
msgid "WIDTH"
|
||||
msgstr "LARGEUR"
|
||||
|
||||
#: src/main/help.c:303
|
||||
#: src/main/help.c:367
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "présumer la largeur du terminal à LARGEUR caractères"
|
||||
|
||||
#: src/main/help.c:305
|
||||
#: src/main/help.c:369
|
||||
msgid "HEIGHT"
|
||||
msgstr "HAUTEUR"
|
||||
|
||||
#: src/main/help.c:306
|
||||
#: src/main/help.c:370
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "présumer la hauteur du terminal à HAUTEUR lignes"
|
||||
|
||||
#: src/main/help.c:308
|
||||
#: src/main/help.c:372
|
||||
msgid "NAME"
|
||||
msgstr "NOM"
|
||||
|
||||
#: src/main/help.c:309
|
||||
#: src/main/help.c:373
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "préfixer les informations visuelles avec NOM"
|
||||
|
||||
#: src/main/help.c:311
|
||||
#: src/main/help.c:375
|
||||
msgid "STYLE"
|
||||
msgstr "STYLE"
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "set default bar style to NAME"
|
||||
msgstr "définir le style de barre par défaut à NOM"
|
||||
#: src/main/help.c:376
|
||||
msgid "set default bar style to STYLE"
|
||||
msgstr "définir le style de barre par défaut à STYLE"
|
||||
|
||||
#: src/main/help.c:314
|
||||
#: src/main/help.c:378
|
||||
msgid "SPEC"
|
||||
msgstr "SPÉCIFICATION"
|
||||
|
||||
#: src/main/help.c:315
|
||||
#: src/main/help.c:379
|
||||
msgid "also send progress to SPEC"
|
||||
msgstr "aussi envoyer la progression à SPÉCIFICATION"
|
||||
|
||||
#: src/main/help.c:318
|
||||
#: src/main/help.c:382
|
||||
msgid "set terminal progress state with OSC 9;4 (ConEmu)"
|
||||
msgstr "mettre à jour l'état de progression du terminal avec OSC 9;4 (ConEmu)"
|
||||
|
||||
#: src/main/help.c:385
|
||||
msgid "output transfer statistics at the end"
|
||||
msgstr "afficher les statistiques de transfert à la fin"
|
||||
|
||||
#: src/main/help.c:321
|
||||
#: src/main/help.c:388
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr ""
|
||||
"imprimer vers la sortie d'erreur standard même si ce n'est pas un terminal"
|
||||
|
||||
#: src/main/help.c:324
|
||||
#: src/main/help.c:391
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "utiliser les séquences d'échappements de positionnement de curseur"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
#: src/main/help.c:394 src/main/help.c:430 src/main/help.c:449
|
||||
#: src/main/help.c:459
|
||||
msgid "FILE"
|
||||
msgstr "FICHIER"
|
||||
|
||||
#: src/main/help.c:328
|
||||
#: src/main/help.c:395
|
||||
msgid "write output to FILE instead of stdout"
|
||||
msgstr "écrire la sortie dans FICHIER au lieu de la sortie standard"
|
||||
|
||||
#: src/main/help.c:330
|
||||
#: src/main/help.c:397
|
||||
msgid "RATE"
|
||||
msgstr "TAUX"
|
||||
|
||||
#: src/main/help.c:331
|
||||
#: src/main/help.c:398
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "limite le taux de transfert à TAUX octets par seconde"
|
||||
|
||||
#: src/main/help.c:333 src/main/help.c:342
|
||||
#: src/main/help.c:400 src/main/help.c:406 src/main/help.c:412
|
||||
msgid "BYTES"
|
||||
msgstr "OCTETS"
|
||||
|
||||
#: src/main/help.c:334
|
||||
#: src/main/help.c:401
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "Utiliser une mémoire tampon de OCTETS octets"
|
||||
msgstr "utiliser une mémoire tampon de OCTETS octets"
|
||||
|
||||
#: src/main/help.c:337
|
||||
#: src/main/help.c:404
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "ne jamais utiliser splice(), toujours utiliser read/write"
|
||||
|
||||
#: src/main/help.c:340
|
||||
#: src/main/help.c:407
|
||||
msgid "set the pipe buffer size to BYTES"
|
||||
msgstr "définir la taille du tampon de mémoire du tube à OCTETS octets"
|
||||
|
||||
#: src/main/help.c:410
|
||||
msgid "skip read errors in input"
|
||||
msgstr "ignorer les erreurs de lecture dans l'entrée"
|
||||
|
||||
#: src/main/help.c:343
|
||||
#: src/main/help.c:413
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr "ignorer les erreurs dans OCTETS blocs à la fois"
|
||||
|
||||
#: src/main/help.c:346
|
||||
#: src/main/help.c:416
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "arrêter après le transfert de --size octets"
|
||||
|
||||
#: src/main/help.c:349
|
||||
#: src/main/help.c:419
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr "vider le cache sur le disque après chaque écriture"
|
||||
|
||||
#: src/main/help.c:352
|
||||
#: src/main/help.c:422
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr "utiliser les E/S directes pour contourner le cache"
|
||||
|
||||
#: src/main/help.c:355
|
||||
#: src/main/help.c:425
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
msgstr "écrire des trous dans le fichier au lieu d'octets nuls"
|
||||
|
||||
#: src/main/help.c:358
|
||||
#: src/main/help.c:428
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr "rejeter l'entrée au lieu de l'écrire vers la sortie"
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:431
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr "écrire toute l'entrée vers FICHIER avant de l'écrire vers la sortie"
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:434
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
msgstr "PID[:FD]|=NOM|@FICHIER"
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:435
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "surveiller le fichier FD ouvert par le processus PID"
|
||||
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
#: src/main/help.c:438 src/main/help.c:441
|
||||
msgid "PID"
|
||||
msgstr "PID"
|
||||
|
||||
#: src/main/help.c:369
|
||||
#: src/main/help.c:439
|
||||
msgid "update settings of process PID"
|
||||
msgstr "mettre à jour la configuration du processus PID"
|
||||
|
||||
#: src/main/help.c:372
|
||||
#: src/main/help.c:442
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
msgstr "afficher la progression du processus PID"
|
||||
|
||||
#: src/main/help.c:377
|
||||
#: src/main/help.c:446
|
||||
msgid "run a command and monitor its standard input, output, or both"
|
||||
msgstr ""
|
||||
"exécuter une commande et surveiller son entrée standard, sa sortie ou les "
|
||||
"deux"
|
||||
|
||||
#: src/main/help.c:450
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "enregistrer l'ID de processus dans FICHIER"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:453
|
||||
msgid "show this help and exit"
|
||||
msgstr "afficher cette aide puis quitter"
|
||||
|
||||
#: src/main/help.c:383
|
||||
#: src/main/help.c:456
|
||||
msgid "show version information and exit"
|
||||
msgstr "afficher la version puis quitter"
|
||||
|
||||
#: src/main/help.c:387
|
||||
#: src/main/help.c:460
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "écrire les journaux de déboggage vers FICHIER"
|
||||
|
||||
#: src/main/help.c:413
|
||||
#: src/main/help.c:486
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Utilisation : %s [OPTIONS] [FICHIER]..."
|
||||
|
||||
#: src/main/help.c:424
|
||||
#: src/main/help.c:497
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
"Concaténer FICHIER(s), ou l'entrée standard, sur la sortie standard avec "
|
||||
"monitorage."
|
||||
|
||||
#: src/main/help.c:562
|
||||
#: src/main/help.c:639
|
||||
msgid "Supported format sequences:"
|
||||
msgstr "Séquences de formatage supportées :"
|
||||
|
||||
#: src/main/help.c:576
|
||||
#: src/main/help.c:653
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "SVP rapporter tous bogues à %s"
|
||||
|
||||
#: src/main/main.c:228
|
||||
#: src/main/main.c:225
|
||||
msgid "(input)"
|
||||
msgstr "(entrée)"
|
||||
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr "échec de l'allocation de mémoire de condition"
|
||||
#: src/main/main.c:381 src/main/options.c:1359
|
||||
msgid "a command to run must be specified"
|
||||
msgstr "une commande à exécuter doit être spécifiée"
|
||||
|
||||
#: src/main/options.c:370
|
||||
#: src/main/main.c:704 src/main/options.c:757 src/main/options.c:777
|
||||
#: src/pv/display.c:1086 src/pv/state.c:45 src/pv/state.c:902
|
||||
#: src/pv/state.c:914 src/pv/state.c:950 src/pv/transfer.c:1335
|
||||
#: src/pv/transfer.c:1451 src/pv/transfer.c:1778
|
||||
msgid "memory allocation failure"
|
||||
msgstr "échec d'allocation mémoire"
|
||||
|
||||
#: src/main/options.c:418
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
msgstr "les fichiers de liste ne peuvent pas contenir de lignes « @ »"
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
#: src/main/options.c:438 src/main/options.c:440 src/main/options.c:901
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr "ID de processus ou paire pid:fd attendue"
|
||||
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
#: src/main/options.c:449 src/main/options.c:451 src/main/options.c:908
|
||||
msgid "invalid process ID"
|
||||
msgstr "ID de processus non valide"
|
||||
|
||||
#: src/main/options.c:448 src/pv/file.c:342
|
||||
msgid "failed to stat file"
|
||||
msgstr "échec à statuer sur le fichier"
|
||||
|
||||
#: src/main/options.c:462
|
||||
msgid "is a directory"
|
||||
msgstr "est un répertoire"
|
||||
|
||||
#: src/main/options.c:491
|
||||
msgid "failed to generate sysfs filename"
|
||||
msgstr "échec de génération du nom de fichier sysfs"
|
||||
|
||||
#: src/main/options.c:513
|
||||
msgid "failed to read sysfs size file"
|
||||
msgstr "échec de la lecture de la taille du fichier sysfs"
|
||||
|
||||
#: src/main/options.c:533
|
||||
msgid "failed to open block device"
|
||||
msgstr "échec de l'ouverture du périphérique de bloc"
|
||||
|
||||
#: src/main/options.c:543
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr "échec de l'évaluation de la taille du périphérique de bloc"
|
||||
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "l'allocation pour la structure d'une option a échoué"
|
||||
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "l'allocation pour la structure de l'option argv a échoué"
|
||||
|
||||
#: src/main/options.c:723
|
||||
#: src/main/options.c:829
|
||||
msgid "numeric value not understood"
|
||||
msgstr "valeur numérique non comprise"
|
||||
|
||||
#: src/main/options.c:743
|
||||
#: src/main/options.c:843
|
||||
msgid "integer argument expected"
|
||||
msgstr "Valeur entière attendue"
|
||||
msgstr "valeur entière attendue"
|
||||
|
||||
#: src/main/options.c:755
|
||||
#: src/main/options.c:853
|
||||
msgid "numeric argument expected"
|
||||
msgstr "Valeur numérique attendue"
|
||||
msgstr "valeur numérique attendue"
|
||||
|
||||
#: src/main/options.c:767
|
||||
#: src/main/options.c:864
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
msgstr "nom de fichier manquant"
|
||||
|
||||
#: src/main/options.c:795
|
||||
#: src/main/options.c:890
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
msgstr "nom de processus manquant"
|
||||
|
||||
#: src/main/options.c:1056
|
||||
#: src/main/options.c:1182
|
||||
msgid "invalid side specification"
|
||||
msgstr "côté inacceptable"
|
||||
|
||||
#: src/main/options.c:1197
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Essayez `%s --help' pour plus d'informations."
|
||||
|
||||
#: src/main/options.c:1058
|
||||
#: src/main/options.c:1199
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Essayez `%s -h' pour plus d'informations."
|
||||
|
||||
#: src/main/options.c:1089
|
||||
#: src/main/options.c:1231
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -394,43 +387,56 @@ msgstr ""
|
||||
"impossible d'utiliser le mode ligne ou les options de modificateur de "
|
||||
"transfert lors de la visualisation des descripteurs de fichiers"
|
||||
|
||||
#: src/main/options.c:1098
|
||||
#: src/main/options.c:1239
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
"impossible d'utiliser le positionnement du curseur lors de la visualisation "
|
||||
"des descripteurs de fichier"
|
||||
|
||||
#: src/main/options.c:1107
|
||||
#: src/main/options.c:1247
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
"impossible d'utiliser la télécommande lors de la visualisation des "
|
||||
"descripteurs de fichiers"
|
||||
|
||||
#: src/main/options.c:1116
|
||||
#: src/main/options.c:1255
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
"impossible d'utiliser une requête distante lorsque vous regardez des "
|
||||
"descripteurs de fichiers"
|
||||
|
||||
#: src/main/options.c:1125
|
||||
#: src/main/options.c:1263
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
"impossible de transférer des fichiers lorsque vous regardez des descripteurs "
|
||||
"de fichiers"
|
||||
|
||||
#: src/main/options.c:1150
|
||||
#: src/main/options.c:1287
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "non disponible sur les systèmes sans /proc/self/fdinfo"
|
||||
|
||||
#: src/main/options.c:1162
|
||||
#: src/main/options.c:1298
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
"impossible d'utiliser simultanément le contrôle à distance et "
|
||||
"l'interrogation à distance"
|
||||
|
||||
#: src/main/options.c:1189
|
||||
msgid "files cannot be specified with this option"
|
||||
#: src/main/options.c:1325
|
||||
msgid "monitor mode cannot be specified with this option"
|
||||
msgstr "impossible d'utiliser mode moniteur avec cette option"
|
||||
|
||||
#: src/main/options.c:1337
|
||||
msgid "monitor mode cannot be used with store-and-forward"
|
||||
msgstr ""
|
||||
"impossible d'utiliser mode moniteur avec le stockage et la retransmission"
|
||||
|
||||
#: src/main/options.c:1348
|
||||
msgid "files cannot be specified with this option"
|
||||
msgstr "les fichiers ne peuvent pas être spécifiés avec cette option"
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid "License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
msgstr "License : GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
msgstr "License : GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
|
||||
#: src/main/version.c:29
|
||||
msgid "This is free software: you are free to change and redistribute it."
|
||||
@@ -446,64 +452,44 @@ msgstr "Il n'y a AUCUNE GARANTIE, dans la mesure permise par la loi."
|
||||
msgid "Project web site"
|
||||
msgstr "Site web du projet"
|
||||
|
||||
#: src/pv/cursor.c:61
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "échec de lecture du nom du terminal"
|
||||
|
||||
#: src/pv/cursor.c:106
|
||||
#: src/pv/cursor.c:108 src/pv/cursor.c:135
|
||||
msgid "failed to open lock file"
|
||||
msgstr "échec de l'ouverture du fichier de verrouillage"
|
||||
|
||||
#: src/pv/cursor.c:139
|
||||
msgid "lock attempt failed"
|
||||
msgstr "échec de la tentative de verrouillage"
|
||||
#: src/pv/cursor.c:790 src/pv/cursor.c:792
|
||||
msgid "interrupted by a signal"
|
||||
msgstr "interrompu par un signal"
|
||||
|
||||
#: src/pv/cursor.c:400
|
||||
msgid "failed to open terminal"
|
||||
msgstr "échec de l'ouverture du terminal"
|
||||
|
||||
#: src/pv/display.c:285
|
||||
#: src/pv/display.c:311
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr "yzafpnum kMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:303
|
||||
#: src/pv/display.c:329
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr "yzafpnum KMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "échec de l'allocation de mémoire tampon"
|
||||
#: src/pv/file.c:81
|
||||
msgid "/dev/null is not usable"
|
||||
msgstr "/dev/null n'est pas utilisable"
|
||||
|
||||
#: src/pv/file.c:153
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr "ne peut pas passer au début de la sortie"
|
||||
#: src/pv/file.c:371
|
||||
msgid "error closing file"
|
||||
msgstr "erreur à la fermeture du fichier"
|
||||
|
||||
#: src/pv/file.c:303
|
||||
msgid "failed to close file"
|
||||
msgstr "la fermeture du fichier a échoué"
|
||||
#: src/pv/file.c:438
|
||||
msgid "input file is also the output"
|
||||
msgstr "le fichier d'entrée est aussi le fichier de sortie"
|
||||
|
||||
#: src/pv/file.c:335
|
||||
msgid "failed to read file"
|
||||
msgstr "la lecture du fichier a échoué"
|
||||
|
||||
#: src/pv/file.c:350
|
||||
msgid "failed to stat output file"
|
||||
msgstr "échec à statuer sur le fichier de sortie"
|
||||
|
||||
#: src/pv/file.c:372
|
||||
msgid "input file is output file"
|
||||
msgstr "fichiers d'entré et de sortie sont les mêmes"
|
||||
|
||||
#: src/pv/file.c:429
|
||||
#: src/pv/file.c:596
|
||||
msgid "(none)"
|
||||
msgstr "(aucun)"
|
||||
|
||||
#: src/pv/file.c:431
|
||||
#: src/pv/file.c:598
|
||||
msgid "(stdin)"
|
||||
msgstr "(stdin)"
|
||||
|
||||
#: src/pv/format/averagerate.c:34 src/pv/format/progressbar.c:92
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:181
|
||||
msgid "b/s"
|
||||
msgstr "b/s"
|
||||
|
||||
@@ -513,7 +499,7 @@ msgid "/s"
|
||||
msgstr "/s"
|
||||
|
||||
#: src/pv/format/averagerate.c:38 src/pv/format/progressbar.c:96
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:181
|
||||
msgid "B/s"
|
||||
msgstr "O/s"
|
||||
|
||||
@@ -521,104 +507,143 @@ msgstr "O/s"
|
||||
msgid "b"
|
||||
msgstr "b"
|
||||
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:620
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:1284
|
||||
msgid "B"
|
||||
msgstr "O"
|
||||
|
||||
#: src/pv/format/eta.c:52 src/pv/format/eta.c:56
|
||||
#: src/pv/format/eta.c:63 src/pv/format/eta.c:67
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/format/fineta.c:80
|
||||
#: src/pv/format/fineta.c:93
|
||||
msgid "FIN"
|
||||
msgstr "FIN"
|
||||
|
||||
#: src/pv/loop.c:120
|
||||
#: src/pv/loop.c:180
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr "taux min/moy/max/écart-type"
|
||||
|
||||
#: src/pv/loop.c:132
|
||||
#: src/pv/loop.c:192
|
||||
msgid "rate not measured"
|
||||
msgstr "taux non mesuré"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/loop.c:818 src/pv/loop.c:836 src/pv/watchpid.c:101
|
||||
#: src/pv/watchpid.c:110 src/pv/watchpid.c:121 src/pv/watchpid.c:129
|
||||
#: src/pv/watchpid.c:166 src/pv/watchpid.c:185 src/pv/watchpid.c:193
|
||||
#: src/pv/watchpid.c:203 src/pv/watchpid.c:307 src/pv/watchpid.c:315
|
||||
#: src/pv/watchpid.c:447 src/pv/watchpid.c:470
|
||||
#: src/pv/loop.c:1098 src/pv/loop.c:1114 src/pv/loop.c:1132 src/pv/remote.c:93
|
||||
#: src/pv/remote.c:188 src/pv/remote.c:536 src/pv/remote.c:582
|
||||
#: src/pv/watchpid.c:123 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:158 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:206 src/pv/watchpid.c:218 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:286 src/pv/watchpid.c:401
|
||||
#: src/pv/watchpid.c:409 src/pv/watchpid.c:556 src/pv/watchpid.c:565
|
||||
#: src/pv/watchpid.c:586
|
||||
msgid "pid"
|
||||
msgstr "pid"
|
||||
|
||||
#: src/pv/loop.c:836 src/pv/watchpid.c:110 src/pv/watchpid.c:122
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:185 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:205
|
||||
#: src/pv/loop.c:1132 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:160 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:288
|
||||
msgid "fd"
|
||||
msgstr "fd"
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
#: src/pv/remote.c:242 src/pv/remote.c:636
|
||||
msgid "message not received"
|
||||
msgstr "message non reçu"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
#: src/pv/remote.c:659 src/pv/remote.c:677
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO non pris en charge sur ce système"
|
||||
|
||||
#: src/pv/state.c:42
|
||||
msgid "history structure allocation failed"
|
||||
msgstr "l'allocation de la structure de l'historique a échoué"
|
||||
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr "échec de l'allocation de la liste de fichiers"
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr "la lecture a échoué"
|
||||
|
||||
#: src/pv/transfer.c:506
|
||||
#: src/pv/transfer.c:1173
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "avertissement : erreurs de lecture détectées"
|
||||
|
||||
#: src/pv/transfer.c:522
|
||||
msgid "file is not seekable"
|
||||
msgstr "ne peut pas se déplacer dans le fichier"
|
||||
|
||||
#: src/pv/transfer.c:599
|
||||
msgid "failed to seek past error"
|
||||
msgstr "n'a pas réussi à dépasser l'erreur"
|
||||
|
||||
#: src/pv/transfer.c:619
|
||||
#: src/pv/transfer.c:1283
|
||||
msgid "skipped past read error"
|
||||
msgstr "erreur de lecture dépassée"
|
||||
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr "aucun tampon de transfert alloué"
|
||||
#: src/pv/transfer.c:1642
|
||||
msgid "write error"
|
||||
msgstr "erreur d'écriture"
|
||||
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr "La définition de l'intervalle du minuteur a échoué"
|
||||
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr "La réinitialisation des intervalles du minuteur a échoué"
|
||||
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr "L'allocation de la position de la ligne de la mémoire tampon a échoué"
|
||||
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "l'écriture a échoué"
|
||||
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "l'appel de sélection a échoué"
|
||||
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
#: src/pv/watchpid.c:160 src/pv/watchpid.c:288
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "pas un fichier ordinaire ou un périphérique de bloc"
|
||||
|
||||
#~ msgid "state allocation failed"
|
||||
#~ msgstr "échec de l'allocation de mémoire de condition"
|
||||
|
||||
#~ msgid "failed to stat file"
|
||||
#~ msgstr "échec à statuer sur le fichier"
|
||||
|
||||
#~ msgid "is a directory"
|
||||
#~ msgstr "est un répertoire"
|
||||
|
||||
#~ msgid "failed to generate sysfs filename"
|
||||
#~ msgstr "échec de génération du nom de fichier sysfs"
|
||||
|
||||
#~ msgid "failed to read sysfs size file"
|
||||
#~ msgstr "échec de la lecture de la taille du fichier sysfs"
|
||||
|
||||
#~ msgid "failed to open block device"
|
||||
#~ msgstr "échec de l'ouverture du périphérique de bloc"
|
||||
|
||||
#~ msgid "failed to determine size of block device"
|
||||
#~ msgstr "échec de l'évaluation de la taille du périphérique de bloc"
|
||||
|
||||
#~ msgid "option structure allocation failed"
|
||||
#~ msgstr "l'allocation pour la structure d'une option a échoué"
|
||||
|
||||
#~ msgid "option structure argv allocation failed"
|
||||
#~ msgstr "l'allocation pour la structure de l'option argv a échoué"
|
||||
|
||||
#~ msgid "failed to get terminal name"
|
||||
#~ msgstr "échec de lecture du nom du terminal"
|
||||
|
||||
#~ msgid "lock attempt failed"
|
||||
#~ msgstr "échec de la tentative de verrouillage"
|
||||
|
||||
#~ msgid "failed to open terminal"
|
||||
#~ msgstr "échec de l'ouverture du terminal"
|
||||
|
||||
#~ msgid "failed to seek to start of output"
|
||||
#~ msgstr "ne peut pas passer au début de la sortie"
|
||||
|
||||
#~ msgid "failed to read file"
|
||||
#~ msgstr "la lecture du fichier a échoué"
|
||||
|
||||
#~ msgid "failed to stat output file"
|
||||
#~ msgstr "échec à statuer sur le fichier de sortie"
|
||||
|
||||
#~ msgid "history structure allocation failed"
|
||||
#~ msgstr "l'allocation de la structure de l'historique a échoué"
|
||||
|
||||
#~ msgid "file list allocation failed"
|
||||
#~ msgstr "échec de l'allocation de la liste de fichiers"
|
||||
|
||||
#~ msgid "read failed"
|
||||
#~ msgstr "la lecture a échoué"
|
||||
|
||||
#~ msgid "file is not seekable"
|
||||
#~ msgstr "ne peut pas se déplacer dans le fichier"
|
||||
|
||||
#~ msgid "failed to seek past error"
|
||||
#~ msgstr "n'a pas réussi à dépasser l'erreur"
|
||||
|
||||
#~ msgid "no transfer buffer allocated"
|
||||
#~ msgstr "aucun tampon de transfert alloué"
|
||||
|
||||
#~ msgid "failed to set interval timer"
|
||||
#~ msgstr "La définition de l'intervalle du minuteur a échoué"
|
||||
|
||||
#~ msgid "failed to clear interval timer"
|
||||
#~ msgstr "La réinitialisation des intervalles du minuteur a échoué"
|
||||
|
||||
#~ msgid "line position buffer allocation failed"
|
||||
#~ msgstr ""
|
||||
#~ "L'allocation de la position de la ligne de la mémoire tampon a échoué"
|
||||
|
||||
#~ msgid "select call failed"
|
||||
#~ msgstr "l'appel de sélection a échoué"
|
||||
|
||||
#~ msgid "PID[:FD]"
|
||||
#~ msgstr "PID[:FD]"
|
||||
|
||||
|
||||
@@ -0,0 +1,541 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pv 1.11.0\n"
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2026-08-01 14:53+0100\n"
|
||||
"PO-Revision-Date: 2026-08-07 19:25+0000\n"
|
||||
"Last-Translator: ldm <ldm@noreply.codeberg.org>\n"
|
||||
"Language-Team: Italian <https://translate.codeberg.org/projects/pv/pv/it/>\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 2026.7.1\n"
|
||||
|
||||
#: src/main/help.c:300
|
||||
msgid "show progress bar"
|
||||
msgstr "mostra la barra dei progressi"
|
||||
|
||||
#: src/main/help.c:303
|
||||
msgid "show elapsed time"
|
||||
msgstr "mostra tempo trascorso"
|
||||
|
||||
#: src/main/help.c:306
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "mostra tempo stimato di completamento"
|
||||
|
||||
#: src/main/help.c:309
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "mostra l'orario di tempo stimato di completamento"
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "mostrare il contatore della velocità di trasferimento dati"
|
||||
|
||||
#: src/main/help.c:315
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "mostrare la velocità media di trasferimento dati"
|
||||
|
||||
#: src/main/help.c:318
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "mostra numero di byte trasferiti"
|
||||
|
||||
#: src/main/help.c:321
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "mostra la percentuale del buffer di trasferimento in uso"
|
||||
|
||||
#: src/main/help.c:323
|
||||
msgid "NUM"
|
||||
msgstr "NUM"
|
||||
|
||||
#: src/main/help.c:324
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "mostra NUM bytes ultimo scritto"
|
||||
|
||||
#: src/main/help.c:326
|
||||
msgid "FORMAT"
|
||||
msgstr "FORMAT"
|
||||
|
||||
#: src/main/help.c:327
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "impostare il formato output in FORMAT"
|
||||
|
||||
#: src/main/help.c:330
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "percentuali di output, non informazioni visive"
|
||||
|
||||
#: src/main/help.c:333
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "non mostrare alcuna informazione di trasferimento"
|
||||
|
||||
#: src/main/help.c:337
|
||||
msgid "show number of bits transferred"
|
||||
msgstr "mostra numero di bit trasferiti"
|
||||
|
||||
#: src/main/help.c:340
|
||||
msgid "treat suffixes as multiples of 1000 rather than 1024"
|
||||
msgstr "trattare i suffissi come multipli di 1000 piuttosto che 1024"
|
||||
|
||||
#: src/main/help.c:343
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "non mostrare nulla fino al primo byte trasferito"
|
||||
|
||||
#: src/main/help.c:345 src/main/help.c:360 src/main/help.c:363
|
||||
msgid "SEC"
|
||||
msgstr "SEC"
|
||||
|
||||
#: src/main/help.c:346
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "non mostrare nulla fino a quando non sono passati SEC secondi"
|
||||
|
||||
#: src/main/help.c:348
|
||||
msgid "SIZE"
|
||||
msgstr "DIM"
|
||||
|
||||
#: src/main/help.c:349
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "imposta la dimensione stimata dei dati per DIM bytes"
|
||||
|
||||
#: src/main/help.c:352
|
||||
msgid "if size unknown, show rate vs max rate"
|
||||
msgstr "se dimensioni sconosciute, mostrare tasso di trasferimento vs tasso massimo"
|
||||
|
||||
#: src/main/help.c:355
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "contare le linee invece dei bytes"
|
||||
|
||||
#: src/main/help.c:358
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "le righe terminano con un carattere nullo"
|
||||
|
||||
#: src/main/help.c:361
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "aggiornamento ogni SEC secondi"
|
||||
|
||||
#: src/main/help.c:364
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr "calcolare il tasso medio negli ultimi SEC secondi (predefinito 30s)"
|
||||
|
||||
#: src/main/help.c:366
|
||||
msgid "WIDTH"
|
||||
msgstr "LARGHEZZA"
|
||||
|
||||
#: src/main/help.c:367
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "assumere il terminale largo LARGHEZZA caratteri"
|
||||
|
||||
#: src/main/help.c:369
|
||||
msgid "HEIGHT"
|
||||
msgstr "ALTEZZA"
|
||||
|
||||
#: src/main/help.c:370
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "assumere terminale alto ALTEZZA righe"
|
||||
|
||||
#: src/main/help.c:372
|
||||
msgid "NAME"
|
||||
msgstr "NOME"
|
||||
|
||||
#: src/main/help.c:373
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "anteponi NOME alle informazioni visive"
|
||||
|
||||
#: src/main/help.c:375
|
||||
msgid "STYLE"
|
||||
msgstr "STILE"
|
||||
|
||||
#: src/main/help.c:376
|
||||
msgid "set default bar style to STYLE"
|
||||
msgstr "impostare lo stile predefinito della barra a STILE"
|
||||
|
||||
#: src/main/help.c:378
|
||||
msgid "SPEC"
|
||||
msgstr "SPEC"
|
||||
|
||||
#: src/main/help.c:379
|
||||
msgid "also send progress to SPEC"
|
||||
msgstr "inviare i progressi anche a SPEC"
|
||||
|
||||
#: src/main/help.c:382
|
||||
msgid "set terminal progress state with OSC 9;4 (ConEmu)"
|
||||
msgstr "impostare lo stato di avanzamento del terminale con OSC 9;4 (ConEmu)"
|
||||
|
||||
#: src/main/help.c:385
|
||||
msgid "output transfer statistics at the end"
|
||||
msgstr "mostra statistiche di trasferimento alla fine"
|
||||
|
||||
#: src/main/help.c:388
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "output anche se standard error non è un terminale"
|
||||
|
||||
#: src/main/help.c:391
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "utilizzare le sequenze escape di posizionamento del cursore"
|
||||
|
||||
#: src/main/help.c:394 src/main/help.c:430 src/main/help.c:449
|
||||
#: src/main/help.c:459
|
||||
msgid "FILE"
|
||||
msgstr "FILE"
|
||||
|
||||
#: src/main/help.c:395
|
||||
msgid "write output to FILE instead of stdout"
|
||||
msgstr "scrivere output su FILE invece che stdout"
|
||||
|
||||
#: src/main/help.c:397
|
||||
msgid "RATE"
|
||||
msgstr "TASSO"
|
||||
|
||||
#: src/main/help.c:398
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "limite di trasferimento a TASSO byte al secondo"
|
||||
|
||||
#: src/main/help.c:400 src/main/help.c:406 src/main/help.c:412
|
||||
msgid "BYTES"
|
||||
msgstr "BYTE"
|
||||
|
||||
#: src/main/help.c:401
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "utilizzare un buffer di dimensione BYTE"
|
||||
|
||||
#: src/main/help.c:404
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "mai usare splice(), usare sempre lettura/scrittura"
|
||||
|
||||
#: src/main/help.c:407
|
||||
msgid "set the pipe buffer size to BYTES"
|
||||
msgstr "impostare la dimensione del pipe buffer a BYTE"
|
||||
|
||||
#: src/main/help.c:410
|
||||
msgid "skip read errors in input"
|
||||
msgstr "saltare gli errori di lettura in input"
|
||||
|
||||
#: src/main/help.c:413
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr "passare errori passati in blocchi BYTE"
|
||||
|
||||
#: src/main/help.c:416
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "stop dopo aver trasferito --size byte"
|
||||
|
||||
#: src/main/help.c:419
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr "svuotare la cache sul disco dopo ogni scrittura"
|
||||
|
||||
#: src/main/help.c:422
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr "utilizzare direct I/O per bypassare la cache"
|
||||
|
||||
#: src/main/help.c:425
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr "prova a cercare invece di scrivere byte nulli"
|
||||
|
||||
#: src/main/help.c:428
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr "scartare l'input invece di scrivere sull'output"
|
||||
|
||||
#: src/main/help.c:431
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr "scrivere tutti gli input su FILE prima di scrivere su output"
|
||||
|
||||
#: src/main/help.c:434
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr "PID[:FD]|=NOME|@FILE"
|
||||
|
||||
#: src/main/help.c:435
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "visualizza il file FD aperto dal processo PID"
|
||||
|
||||
#: src/main/help.c:438 src/main/help.c:441
|
||||
msgid "PID"
|
||||
msgstr "PID"
|
||||
|
||||
#: src/main/help.c:439
|
||||
msgid "update settings of process PID"
|
||||
msgstr "impostazioni di aggiornamento del processo PID"
|
||||
|
||||
#: src/main/help.c:442
|
||||
msgid "show progress of process PID"
|
||||
msgstr "mostrare il progresso del processo PID"
|
||||
|
||||
#: src/main/help.c:446
|
||||
msgid "run a command and monitor its standard input, output, or both"
|
||||
msgstr ""
|
||||
"eseguire un comando e monitorare il suo standard input, output, o entrambi"
|
||||
|
||||
#: src/main/help.c:450
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "salvare ID processo in FILE"
|
||||
|
||||
#: src/main/help.c:453
|
||||
msgid "show this help and exit"
|
||||
msgstr "mostra questo help ed esce"
|
||||
|
||||
#: src/main/help.c:456
|
||||
msgid "show version information and exit"
|
||||
msgstr "stampa le informazioni sulla versione ed esce"
|
||||
|
||||
#: src/main/help.c:460
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "scrivi i log di debug su FILE"
|
||||
|
||||
#: src/main/help.c:486
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Uso: %s [OPZIONE] [FILE]..."
|
||||
|
||||
#: src/main/help.c:497
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
"Concatena i FILE, o lo standard input, allo standard output, con "
|
||||
"monitoraggio."
|
||||
|
||||
#: src/main/help.c:639
|
||||
msgid "Supported format sequences:"
|
||||
msgstr "Sequenze di formato supportate:"
|
||||
|
||||
#: src/main/help.c:653
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Per favore segnalare i bug a: %s"
|
||||
|
||||
#: src/main/main.c:225
|
||||
msgid "(input)"
|
||||
msgstr "(input)"
|
||||
|
||||
#: src/main/main.c:381 src/main/options.c:1359
|
||||
msgid "a command to run must be specified"
|
||||
msgstr "un comando da eseguire deve essere specificato"
|
||||
|
||||
#: src/main/main.c:704 src/main/options.c:757 src/main/options.c:777
|
||||
#: src/pv/display.c:1086 src/pv/state.c:45 src/pv/state.c:902
|
||||
#: src/pv/state.c:914 src/pv/state.c:950 src/pv/transfer.c:1335
|
||||
#: src/pv/transfer.c:1451 src/pv/transfer.c:1778
|
||||
msgid "memory allocation failure"
|
||||
msgstr "fallimento nell'allocazione della memoria"
|
||||
|
||||
#: src/main/options.c:418
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr "file di elenco non possono contenere linee @"
|
||||
|
||||
#: src/main/options.c:438 src/main/options.c:440 src/main/options.c:901
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr "è previsto un ID di processo o una coppia pid:fd"
|
||||
|
||||
#: src/main/options.c:449 src/main/options.c:451 src/main/options.c:908
|
||||
msgid "invalid process ID"
|
||||
msgstr "ID processo non valido"
|
||||
|
||||
#: src/main/options.c:829
|
||||
msgid "numeric value not understood"
|
||||
msgstr "valore numerico non compreso"
|
||||
|
||||
#: src/main/options.c:843
|
||||
msgid "integer argument expected"
|
||||
msgstr "argomento integer previsto"
|
||||
|
||||
#: src/main/options.c:853
|
||||
msgid "numeric argument expected"
|
||||
msgstr "argomento numerico previsto"
|
||||
|
||||
#: src/main/options.c:864
|
||||
msgid "missing filename"
|
||||
msgstr "nome del file mancante"
|
||||
|
||||
#: src/main/options.c:890
|
||||
msgid "missing process name"
|
||||
msgstr "nome del processo mancante"
|
||||
|
||||
#: src/main/options.c:1182
|
||||
msgid "invalid side specification"
|
||||
msgstr "specifica del lato non valida"
|
||||
|
||||
#: src/main/options.c:1197
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Usare «%s --help» per ulteriori informazioni."
|
||||
|
||||
#: src/main/options.c:1199
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Usare «%s -h» per ulteriori informazioni."
|
||||
|
||||
#: src/main/options.c:1231
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
msgstr ""
|
||||
"non è possibile utilizzare la modalità riga o il modificatore di "
|
||||
"trasferimento durante la visualizzazione dei descrittori di file"
|
||||
|
||||
#: src/main/options.c:1239
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
"non può utilizzare il posizionamento del cursore durante la visualizzazione "
|
||||
"dei descrittori di file"
|
||||
|
||||
#: src/main/options.c:1247
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr "non può usare il telecomando quando si guarda i descrittori di file"
|
||||
|
||||
#: src/main/options.c:1255
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr "non può utilizzare query remoto quando si guarda i descrittori di file"
|
||||
|
||||
#: src/main/options.c:1263
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
"non può trasferire i file durante la visualizzazione dei descrittori di file"
|
||||
|
||||
#: src/main/options.c:1287
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "non disponibile su sistemi senza /proc/self/fdinfo"
|
||||
|
||||
#: src/main/options.c:1298
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr "non può utilizzare il telecomando e la query remota insieme"
|
||||
|
||||
#: src/main/options.c:1325
|
||||
msgid "monitor mode cannot be specified with this option"
|
||||
msgstr "la modalità monitor non può essere specificata con questa opzione"
|
||||
|
||||
#: src/main/options.c:1337
|
||||
msgid "monitor mode cannot be used with store-and-forward"
|
||||
msgstr "modalità monitor non può essere utilizzato con negozio e in avanti"
|
||||
|
||||
#: src/main/options.c:1348
|
||||
msgid "files cannot be specified with this option"
|
||||
msgstr "i file non possono essere specificati con questa opzione"
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid "License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
msgstr "Licenza: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
|
||||
#: src/main/version.c:29
|
||||
msgid "This is free software: you are free to change and redistribute it."
|
||||
msgstr "Questo è software libero: è possibile modificarlo e ridistribuirlo."
|
||||
|
||||
#: src/main/version.c:30
|
||||
msgid "There is NO WARRANTY, to the extent permitted by law."
|
||||
msgstr "Non c'è ALCUNA GARANZIA, nei limiti permessi dalla legge."
|
||||
|
||||
#: src/main/version.c:32
|
||||
msgid "Project web site"
|
||||
msgstr "Sito web del progetto"
|
||||
|
||||
#: src/pv/cursor.c:108 src/pv/cursor.c:135
|
||||
msgid "failed to open lock file"
|
||||
msgstr "non è riuscito ad aprire il file di blocco"
|
||||
|
||||
#: src/pv/cursor.c:790 src/pv/cursor.c:792
|
||||
msgid "interrupted by a signal"
|
||||
msgstr "interrotta da un segnale"
|
||||
|
||||
#: src/pv/display.c:311
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr "yzafpnum kMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:329
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr "yzafpnum KMGTPEZY"
|
||||
|
||||
#: src/pv/file.c:81
|
||||
msgid "/dev/null is not usable"
|
||||
msgstr "/dev/null non è utilizzabile"
|
||||
|
||||
#: src/pv/file.c:371
|
||||
msgid "error closing file"
|
||||
msgstr "errore nel chiudere il file"
|
||||
|
||||
#: src/pv/file.c:438
|
||||
msgid "input file is also the output"
|
||||
msgstr "il file di input coincide con quello di output"
|
||||
|
||||
#: src/pv/file.c:596
|
||||
msgid "(none)"
|
||||
msgstr "(nessuno)"
|
||||
|
||||
#: src/pv/file.c:598
|
||||
msgid "(stdin)"
|
||||
msgstr "(stdin)"
|
||||
|
||||
#: src/pv/format/averagerate.c:34 src/pv/format/progressbar.c:92
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:181
|
||||
msgid "b/s"
|
||||
msgstr "b/s"
|
||||
|
||||
#: src/pv/format/averagerate.c:38 src/pv/format/progressbar.c:96
|
||||
#: src/pv/format/rate.c:40
|
||||
msgid "/s"
|
||||
msgstr "/s"
|
||||
|
||||
#: src/pv/format/averagerate.c:38 src/pv/format/progressbar.c:96
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:181
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
#: src/pv/format/bytes.c:35
|
||||
msgid "b"
|
||||
msgstr "b"
|
||||
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:1284
|
||||
msgid "B"
|
||||
msgstr "B"
|
||||
|
||||
#: src/pv/format/eta.c:63 src/pv/format/eta.c:67
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/format/fineta.c:93
|
||||
msgid "FIN"
|
||||
msgstr "FIN"
|
||||
|
||||
#: src/pv/loop.c:180
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr "tasso min/med/mas/mdev"
|
||||
|
||||
#: src/pv/loop.c:192
|
||||
msgid "rate not measured"
|
||||
msgstr "tasso non misurato"
|
||||
|
||||
#: src/pv/loop.c:1098 src/pv/loop.c:1114 src/pv/loop.c:1132 src/pv/remote.c:93
|
||||
#: src/pv/remote.c:188 src/pv/remote.c:536 src/pv/remote.c:582
|
||||
#: src/pv/watchpid.c:123 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:158 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:206 src/pv/watchpid.c:218 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:286 src/pv/watchpid.c:401
|
||||
#: src/pv/watchpid.c:409 src/pv/watchpid.c:556 src/pv/watchpid.c:565
|
||||
#: src/pv/watchpid.c:586
|
||||
msgid "pid"
|
||||
msgstr "pid"
|
||||
|
||||
#: src/pv/loop.c:1132 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:160 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:288
|
||||
msgid "fd"
|
||||
msgstr "fd"
|
||||
|
||||
#: src/pv/remote.c:242 src/pv/remote.c:636
|
||||
msgid "message not received"
|
||||
msgstr "messaggio non ricevuto"
|
||||
|
||||
#: src/pv/remote.c:659 src/pv/remote.c:677
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO non supportato su questo sistema"
|
||||
|
||||
#: src/pv/transfer.c:1173
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "avvertimento: errori di lettura rilevati"
|
||||
|
||||
#: src/pv/transfer.c:1283
|
||||
msgid "skipped past read error"
|
||||
msgstr "saltato l'errore di lettura"
|
||||
|
||||
#: src/pv/transfer.c:1642
|
||||
msgid "write error"
|
||||
msgstr "errore di scrittura"
|
||||
|
||||
#: src/pv/watchpid.c:160 src/pv/watchpid.c:288
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "non è un file regolare o un dispositivo a blocchi"
|
||||
@@ -2,477 +2,464 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pv 1.9.34\n"
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-12-15 20:10+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"POT-Creation-Date: 2026-08-01 14:53+0100\n"
|
||||
"PO-Revision-Date: 2026-05-16 19:25+0000\n"
|
||||
"Last-Translator: a-j-wood <a-j-wood@noreply.codeberg.org>\n"
|
||||
"Language-Team: Georgian <https://translate.codeberg.org/projects/pv/pv/ka/>\n"
|
||||
"Language: ka\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/main/help.c:236
|
||||
msgid "show progress bar"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:239
|
||||
msgid "show elapsed time"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:242
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:245
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:248
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:251
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:254
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:257
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:259
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:260
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:262
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:263
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:266
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:269
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:273
|
||||
msgid "show number of bits transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:276
|
||||
msgid "treat suffixes as multiples of 1000 rather than 1024"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:279
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:281 src/main/help.c:296 src/main/help.c:299
|
||||
msgid "SEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:282
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:284
|
||||
msgid "SIZE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:285
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:288
|
||||
msgid "if size unknown, show rate vs max rate"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:291
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:294
|
||||
msgid "lines are null-terminated"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:297
|
||||
msgid "update every SEC seconds"
|
||||
msgstr ""
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.17.1\n"
|
||||
|
||||
#: src/main/help.c:300
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:302
|
||||
msgid "WIDTH"
|
||||
msgstr ""
|
||||
msgid "show progress bar"
|
||||
msgstr "პროგრესის ზოლის ჩვენება"
|
||||
|
||||
#: src/main/help.c:303
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:305
|
||||
msgid "HEIGHT"
|
||||
msgstr ""
|
||||
msgid "show elapsed time"
|
||||
msgstr "გასული დროის ჩვენება"
|
||||
|
||||
#: src/main/help.c:306
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:308
|
||||
msgid "NAME"
|
||||
msgstr ""
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "სავარაუდო დასრულების დროის ჩვენება"
|
||||
|
||||
#: src/main/help.c:309
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:311
|
||||
msgid "STYLE"
|
||||
msgstr ""
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "დასრულების აბსოლუტური სავარაუდო დროის ჩვენება"
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "set default bar style to NAME"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:314
|
||||
msgid "SPEC"
|
||||
msgstr ""
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "მონაცემთა გადაცემის სიჩქარის ჩვენება"
|
||||
|
||||
#: src/main/help.c:315
|
||||
msgid "also send progress to SPEC"
|
||||
msgstr ""
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "საშუალო მონაცემთა გადაცემის სიჩქარის ჩვენება"
|
||||
|
||||
#: src/main/help.c:318
|
||||
msgid "output transfer statistics at the end"
|
||||
msgstr ""
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "გადატანილი ბაიტების რაოდენობის ჩვენება"
|
||||
|
||||
#: src/main/help.c:321
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr ""
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "გამოყენებული გადაცემის ბუფერის პროცენტული მაჩვენებლის ჩვენება"
|
||||
|
||||
#: src/main/help.c:323
|
||||
msgid "NUM"
|
||||
msgstr "ႬႭႫ"
|
||||
|
||||
#: src/main/help.c:324
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr ""
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "ბოლოს დაწერილი ႬႭႫ ბაიტის ჩვენება"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
#: src/main/help.c:326
|
||||
msgid "FORMAT"
|
||||
msgstr "ႴႭႰႫႠႲႨ"
|
||||
|
||||
#: src/main/help.c:328
|
||||
msgid "write output to FILE instead of stdout"
|
||||
msgstr ""
|
||||
#: src/main/help.c:327
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "გამომავალი ფორმატის დაყენება ႴႭႰႫႠႲႨ"
|
||||
|
||||
#: src/main/help.c:330
|
||||
msgid "RATE"
|
||||
msgstr ""
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "გამომავალი პროცენტები, არა ვიზუალური ინფორმაცია"
|
||||
|
||||
#: src/main/help.c:331
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:333 src/main/help.c:342
|
||||
msgid "BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:334
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr ""
|
||||
#: src/main/help.c:333
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "პროგრესის ინფორმაცია არ აჩვენოთ"
|
||||
|
||||
#: src/main/help.c:337
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr ""
|
||||
msgid "show number of bits transferred"
|
||||
msgstr "გადაცემული ბიტების რაოდენობის ჩვენება"
|
||||
|
||||
#: src/main/help.c:340
|
||||
msgid "skip read errors in input"
|
||||
msgstr ""
|
||||
msgid "treat suffixes as multiples of 1000 rather than 1024"
|
||||
msgstr "სუფიქსების 1000-ის ჯერადად განხილვა 1024-ის ნაცვლად"
|
||||
|
||||
#: src/main/help.c:343
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr ""
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "არაფერი აჩვენოს პირველი ბაიტის გადატანამდე"
|
||||
|
||||
#: src/main/help.c:345 src/main/help.c:360 src/main/help.c:363
|
||||
msgid "SEC"
|
||||
msgstr "ႼႠႫ"
|
||||
|
||||
#: src/main/help.c:346
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr ""
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "არაფერი აჩვენოს ႼႠႫ წამების გასვლამდე"
|
||||
|
||||
#: src/main/help.c:348
|
||||
msgid "SIZE"
|
||||
msgstr "ႦႭႫႠ"
|
||||
|
||||
#: src/main/help.c:349
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr ""
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "მონაცემთა სავარაუდო ზომის ႦႭႫႠ ბაიტებზე დაყენება"
|
||||
|
||||
#: src/main/help.c:352
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
msgid "if size unknown, show rate vs max rate"
|
||||
msgstr "თუ ზომა უცნობია, აჩვენეთ სიჩქარე მაქსიმალურ სიჩქარესთან შედარებით"
|
||||
|
||||
#: src/main/help.c:355
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "ბაიტების ნაცვლად ხაზების დათვლა"
|
||||
|
||||
#: src/main/help.c:358
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "ხაზები ნულით დასრულებულია"
|
||||
|
||||
#: src/main/help.c:361
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr ""
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "განახლება ყოველ ႼႠႫ წამში"
|
||||
|
||||
#: src/main/help.c:364
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
"გამოთვალეთ საშუალო მაჩვენებელი ბოლო ႼႠႫ წამების განმავლობაში (ნაგულისხმევი "
|
||||
"30 წმ)"
|
||||
|
||||
#: src/main/help.c:365
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr ""
|
||||
#: src/main/help.c:366
|
||||
msgid "WIDTH"
|
||||
msgstr "ႱႨႢႠႬႤ"
|
||||
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
#: src/main/help.c:367
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "ვივარაუდოთ, რომ ტერმინალი ႱႨႢႠႬႤ სიმბოლოს სიგანისაა"
|
||||
|
||||
#: src/main/help.c:369
|
||||
msgid "update settings of process PID"
|
||||
msgstr ""
|
||||
msgid "HEIGHT"
|
||||
msgstr "ႱႨႫႠႶႪႤ"
|
||||
|
||||
#: src/main/help.c:370
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "ვივარაუდოთ, რომ ტერმინალი ႱႨႫႠႶႪႤ რიგის სიმაღლისაა"
|
||||
|
||||
#: src/main/help.c:372
|
||||
msgid "show progress of process PID"
|
||||
msgid "NAME"
|
||||
msgstr "ႱႠႾႤႪႨ"
|
||||
|
||||
#: src/main/help.c:373
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "გამომავალი ხაზის დასაწყისში ႱႠႾႤႪႨ-ის ჩვენება"
|
||||
|
||||
#: src/main/help.c:375
|
||||
msgid "STYLE"
|
||||
msgstr "ႱႲႨႪႨ"
|
||||
|
||||
#: src/main/help.c:376
|
||||
msgid "set default bar style to STYLE"
|
||||
msgstr "ნაგულისხმევი ზოლის სტილი ႱႲႨႪႨ-ზე დააყენეთ"
|
||||
|
||||
#: src/main/help.c:378
|
||||
msgid "SPEC"
|
||||
msgstr "ႱႮႤႺႨႴႨႩႠ"
|
||||
|
||||
#: src/main/help.c:379
|
||||
msgid "also send progress to SPEC"
|
||||
msgstr "ასევე გაუგზავნეთ პროგრესი ႱႮႤႺႨႴႨႩႠ-ს"
|
||||
|
||||
#: src/main/help.c:382
|
||||
msgid "set terminal progress state with OSC 9;4 (ConEmu)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
msgid "save process ID in FILE"
|
||||
msgstr ""
|
||||
#: src/main/help.c:385
|
||||
msgid "output transfer statistics at the end"
|
||||
msgstr "სტატისტიკის ჩვენება ბოლოს"
|
||||
|
||||
#: src/main/help.c:380
|
||||
msgid "show this help and exit"
|
||||
msgstr ""
|
||||
#: src/main/help.c:388
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "გამომავალი მაშინაც კი, თუ სტანდარტული შეცდომა ტერმინალი არ არის"
|
||||
|
||||
#: src/main/help.c:383
|
||||
msgid "show version information and exit"
|
||||
msgstr ""
|
||||
#: src/main/help.c:391
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "კურსორის პოზიციონირება ტერმინალის კოდებით"
|
||||
|
||||
#: src/main/help.c:387
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
#: src/main/help.c:394 src/main/help.c:430 src/main/help.c:449
|
||||
#: src/main/help.c:459
|
||||
msgid "FILE"
|
||||
msgstr "ႴႠႨႪႨ"
|
||||
|
||||
#: src/main/help.c:395
|
||||
msgid "write output to FILE instead of stdout"
|
||||
msgstr "ჩაწერეთ გამომავალი ႴႠႨႪႨ-ში სტანდარტული გამომავალის ნაცვლად"
|
||||
|
||||
#: src/main/help.c:397
|
||||
msgid "RATE"
|
||||
msgstr "ႱႨႹႵႠႰႤ"
|
||||
|
||||
#: src/main/help.c:398
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "სიჩქარის შეზღუდვა წამში ႱႨႹႵႠႰႤ ბაიტამდე"
|
||||
|
||||
#: src/main/help.c:400 src/main/help.c:406 src/main/help.c:412
|
||||
msgid "BYTES"
|
||||
msgstr "ႡႠႨႲႤႡႨ"
|
||||
|
||||
#: src/main/help.c:401
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "გამოიყენეთ ႡႠႨႲႤႡႨ ბუფერის ზომა"
|
||||
|
||||
#: src/main/help.c:404
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "არასდროს გამოიყენოთ splice(), ყოველთვის გამოიყენეთ წაკითხვა/ჩაწერა"
|
||||
|
||||
#: src/main/help.c:407
|
||||
msgid "set the pipe buffer size to BYTES"
|
||||
msgstr "მილის ბუფერის ზომა დააყენეთ ႡႠႨႲႤႡႨ ბაიტზე"
|
||||
|
||||
#: src/main/help.c:410
|
||||
msgid "skip read errors in input"
|
||||
msgstr "შეყვანის შეცდომების გამოტოვება"
|
||||
|
||||
#: src/main/help.c:413
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr "შეცდომების გამოტოვება ႡႠႨႲႤႡႨ ბაიტის ბლოკებში"
|
||||
|
||||
#: src/main/help.c:416
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "შეჩერება --size ბაიტების გადატანის შემდეგ"
|
||||
|
||||
#: src/main/help.c:419
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr "დისკის ჩაწერის ქეშის გასუფთავება ყოველი ჩაწერის შემდეგ"
|
||||
|
||||
#: src/main/help.c:422
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr "ქეშის გვერდის ავლით პირდაპირი შეყვანის/გამოყვანის გამოყენებით"
|
||||
|
||||
#: src/main/help.c:425
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr "დატოვეთ ხვრელები გამომავალში ნულოვანი ბაიტების ჩაწერის ნაცვლად"
|
||||
|
||||
#: src/main/help.c:428
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr "შეყვანის გაუქმება გამოსავალში ჩაწერის ნაცვლად"
|
||||
|
||||
#: src/main/help.c:431
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr "ყველა შემავალი მონაცემი ႴႠႨႪႨ-ში ჩაწერეთ გამოსავალში ჩაწერამდე"
|
||||
|
||||
#: src/main/help.c:434
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr "ႮႨႣ[:ႴႠ]|=ႱႠႾႤႪႨ|@ႴႠႨႪႨ"
|
||||
|
||||
#: src/main/help.c:435
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "ფაილის აღწერის ყურება ႴႠ გახსნილია ႮႨႣ პროცესის მიერ"
|
||||
|
||||
#: src/main/help.c:438 src/main/help.c:441
|
||||
msgid "PID"
|
||||
msgstr "ႮႨႣ"
|
||||
|
||||
#: src/main/help.c:439
|
||||
msgid "update settings of process PID"
|
||||
msgstr "პროცესის ႮႨႣ-ის პარამეტრების განახლება"
|
||||
|
||||
#: src/main/help.c:442
|
||||
msgid "show progress of process PID"
|
||||
msgstr "პროცესის ႮႨႣ პროგრესის ჩვენება"
|
||||
|
||||
#: src/main/help.c:446
|
||||
msgid "run a command and monitor its standard input, output, or both"
|
||||
msgstr ""
|
||||
"ბრძანების გაშვება და მისი სტანდარტული შეყვანის, გამომავალი ან ორივეს "
|
||||
"მონიტორინგი"
|
||||
|
||||
#: src/main/help.c:450
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "პროცესის იდენტიფიკატორის შენახვა ႴႠႨႪႨ-ში"
|
||||
|
||||
#: src/main/help.c:453
|
||||
msgid "show this help and exit"
|
||||
msgstr "აჩვენეთ ეს დახმარება და გადით"
|
||||
|
||||
#: src/main/help.c:456
|
||||
msgid "show version information and exit"
|
||||
msgstr "ვერსიის ინფორმაციის ჩვენება და გასვლა"
|
||||
|
||||
#: src/main/help.c:460
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "გამართვის ჟურნალების ႴႠႨႪႨ-ში ჩაწერა"
|
||||
|
||||
#: src/main/help.c:486
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr ""
|
||||
msgstr "გამოყენება: %s [ႠႰႹႤႥႠ] [ႴႠႨႪႨ]..."
|
||||
|
||||
#: src/main/help.c:424
|
||||
#: src/main/help.c:497
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
msgstr "შეყვანის ფაილების გადატანა გამოსავალზე მონიტორინგით."
|
||||
|
||||
#: src/main/help.c:562
|
||||
#: src/main/help.c:639
|
||||
msgid "Supported format sequences:"
|
||||
msgstr ""
|
||||
msgstr "მხარდაჭერილი ფორმატის თანმიმდევრობები:"
|
||||
|
||||
#: src/main/help.c:576
|
||||
#: src/main/help.c:653
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr ""
|
||||
msgstr "ნებისმიერი შეცდომის შესახებ, გთხოვთ, შეატყობინოთ შემდეგ მისამართზე: %s"
|
||||
|
||||
#: src/main/main.c:228
|
||||
#: src/main/main.c:225
|
||||
msgid "(input)"
|
||||
msgstr ""
|
||||
msgstr "(შეყვანა)"
|
||||
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr ""
|
||||
#: src/main/main.c:381 src/main/options.c:1359
|
||||
msgid "a command to run must be specified"
|
||||
msgstr "შესასრულებელი ბრძანება უნდა იყოს მითითებული"
|
||||
|
||||
#: src/main/options.c:370
|
||||
#: src/main/main.c:704 src/main/options.c:757 src/main/options.c:777
|
||||
#: src/pv/display.c:1086 src/pv/state.c:45 src/pv/state.c:902
|
||||
#: src/pv/state.c:914 src/pv/state.c:950 src/pv/transfer.c:1335
|
||||
#: src/pv/transfer.c:1451 src/pv/transfer.c:1778
|
||||
msgid "memory allocation failure"
|
||||
msgstr "მეხსიერების გამოყოფის შეცდომა"
|
||||
|
||||
#: src/main/options.c:418
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
msgstr "სიის ფაილები არ შეიძლება შეიცავდეს \"@\" ხაზებს"
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
#: src/main/options.c:438 src/main/options.c:440 src/main/options.c:901
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
#: src/main/options.c:449 src/main/options.c:451 src/main/options.c:908
|
||||
msgid "invalid process ID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:448 src/pv/file.c:342
|
||||
msgid "failed to stat file"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:462
|
||||
msgid "is a directory"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:491
|
||||
msgid "failed to generate sysfs filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:513
|
||||
msgid "failed to read sysfs size file"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:533
|
||||
msgid "failed to open block device"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:543
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:723
|
||||
#: src/main/options.c:829
|
||||
msgid "numeric value not understood"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:743
|
||||
#: src/main/options.c:843
|
||||
msgid "integer argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:755
|
||||
#: src/main/options.c:853
|
||||
msgid "numeric argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:767
|
||||
#: src/main/options.c:864
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
msgstr "ფაილის სახელი აკლია"
|
||||
|
||||
#: src/main/options.c:795
|
||||
#: src/main/options.c:890
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1056
|
||||
#: src/main/options.c:1182
|
||||
msgid "invalid side specification"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1197
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr ""
|
||||
msgstr "დამატებითი ინფორმაციისთვის სცადეთ `%s --help'."
|
||||
|
||||
#: src/main/options.c:1058
|
||||
#: src/main/options.c:1199
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr ""
|
||||
msgstr "დამატებითი ინფორმაციისთვის სცადეთ `%s -h'."
|
||||
|
||||
#: src/main/options.c:1089
|
||||
#: src/main/options.c:1231
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1098
|
||||
#: src/main/options.c:1239
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1107
|
||||
#: src/main/options.c:1247
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1116
|
||||
#: src/main/options.c:1255
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
#: src/main/options.c:1263
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1150
|
||||
#: src/main/options.c:1287
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1162
|
||||
#: src/main/options.c:1298
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1189
|
||||
#: src/main/options.c:1325
|
||||
msgid "monitor mode cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1337
|
||||
msgid "monitor mode cannot be used with store-and-forward"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1348
|
||||
msgid "files cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid "License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
msgstr ""
|
||||
msgstr "ლიცენზია: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
|
||||
#: src/main/version.c:29
|
||||
msgid "This is free software: you are free to change and redistribute it."
|
||||
msgstr ""
|
||||
"ეს არის უფასო პროგრამული უზრუნველყოფა: თქვენ შეგიძლიათ შეცვალოთ და ხელახლა "
|
||||
"გაავრცელოთ იგი."
|
||||
|
||||
#: src/main/version.c:30
|
||||
msgid "There is NO WARRANTY, to the extent permitted by law."
|
||||
msgstr ""
|
||||
msgstr "კანონით დაშვებული ფარგლებში, გარანტია არ არსებობს."
|
||||
|
||||
#: src/main/version.c:32
|
||||
msgid "Project web site"
|
||||
msgstr ""
|
||||
msgstr "პროექტის ვებსაიტი"
|
||||
|
||||
#: src/pv/cursor.c:61
|
||||
msgid "failed to get terminal name"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:106
|
||||
#: src/pv/cursor.c:108 src/pv/cursor.c:135
|
||||
msgid "failed to open lock file"
|
||||
msgstr ""
|
||||
msgstr "დაბლოკვის ფაილის გახსნა ვერ მოხერხდა"
|
||||
|
||||
#: src/pv/cursor.c:139
|
||||
msgid "lock attempt failed"
|
||||
msgstr ""
|
||||
#: src/pv/cursor.c:790 src/pv/cursor.c:792
|
||||
msgid "interrupted by a signal"
|
||||
msgstr "შეწყვეტილია სიგნალის მიერ"
|
||||
|
||||
#: src/pv/cursor.c:400
|
||||
msgid "failed to open terminal"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:285
|
||||
#: src/pv/display.c:311
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:303
|
||||
#: src/pv/display.c:329
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
msgstr ""
|
||||
#: src/pv/file.c:81
|
||||
msgid "/dev/null is not usable"
|
||||
msgstr "/dev/null არ არის გამოსაყენებელი"
|
||||
|
||||
#: src/pv/file.c:153
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr ""
|
||||
#: src/pv/file.c:371
|
||||
msgid "error closing file"
|
||||
msgstr "ფაილის დახურვის შეცდომა"
|
||||
|
||||
#: src/pv/file.c:303
|
||||
msgid "failed to close file"
|
||||
msgstr ""
|
||||
#: src/pv/file.c:438
|
||||
msgid "input file is also the output"
|
||||
msgstr "შეტანის ფაილი ასევე გამოსატანიცაა"
|
||||
|
||||
#: src/pv/file.c:335
|
||||
msgid "failed to read file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:350
|
||||
msgid "failed to stat output file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:372
|
||||
msgid "input file is output file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:429
|
||||
#: src/pv/file.c:596
|
||||
msgid "(none)"
|
||||
msgstr ""
|
||||
msgstr "(არცერთი)"
|
||||
|
||||
#: src/pv/file.c:431
|
||||
#: src/pv/file.c:598
|
||||
msgid "(stdin)"
|
||||
msgstr ""
|
||||
msgstr "(stdin)"
|
||||
|
||||
#: src/pv/format/averagerate.c:34 src/pv/format/progressbar.c:92
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:181
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
@@ -482,7 +469,7 @@ msgid "/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/averagerate.c:38 src/pv/format/progressbar.c:96
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:181
|
||||
msgid "B/s"
|
||||
msgstr ""
|
||||
|
||||
@@ -490,100 +477,63 @@ msgstr ""
|
||||
msgid "b"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:620
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:1284
|
||||
msgid "B"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/eta.c:52 src/pv/format/eta.c:56
|
||||
#: src/pv/format/eta.c:63 src/pv/format/eta.c:67
|
||||
msgid "ETA"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/fineta.c:80
|
||||
#: src/pv/format/fineta.c:93
|
||||
msgid "FIN"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:120
|
||||
#: src/pv/loop.c:180
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr ""
|
||||
msgstr "სიჩქარე მინიმალური/საშუალო/მაქსიმალური/სტანდარტული გადახრა"
|
||||
|
||||
#: src/pv/loop.c:132
|
||||
#: src/pv/loop.c:192
|
||||
msgid "rate not measured"
|
||||
msgstr ""
|
||||
msgstr "სიჩქარე არ იზომებოდა"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/loop.c:818 src/pv/loop.c:836 src/pv/watchpid.c:101
|
||||
#: src/pv/watchpid.c:110 src/pv/watchpid.c:121 src/pv/watchpid.c:129
|
||||
#: src/pv/watchpid.c:166 src/pv/watchpid.c:185 src/pv/watchpid.c:193
|
||||
#: src/pv/watchpid.c:203 src/pv/watchpid.c:307 src/pv/watchpid.c:315
|
||||
#: src/pv/watchpid.c:447 src/pv/watchpid.c:470
|
||||
#: src/pv/loop.c:1098 src/pv/loop.c:1114 src/pv/loop.c:1132 src/pv/remote.c:93
|
||||
#: src/pv/remote.c:188 src/pv/remote.c:536 src/pv/remote.c:582
|
||||
#: src/pv/watchpid.c:123 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:158 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:206 src/pv/watchpid.c:218 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:286 src/pv/watchpid.c:401
|
||||
#: src/pv/watchpid.c:409 src/pv/watchpid.c:556 src/pv/watchpid.c:565
|
||||
#: src/pv/watchpid.c:586
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:836 src/pv/watchpid.c:110 src/pv/watchpid.c:122
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:185 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:205
|
||||
#: src/pv/loop.c:1132 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:160 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:288
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
#: src/pv/remote.c:242 src/pv/remote.c:636
|
||||
msgid "message not received"
|
||||
msgstr ""
|
||||
msgstr "შეტყობინება არ არის მიღებული"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
#: src/pv/remote.c:659 src/pv/remote.c:677
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:42
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:506
|
||||
#: src/pv/transfer.c:1173
|
||||
msgid "warning: read errors detected"
|
||||
msgstr ""
|
||||
msgstr "გაფრთხილება: წაკითხვის შეცდომები აღმოჩენილია"
|
||||
|
||||
#: src/pv/transfer.c:522
|
||||
msgid "file is not seekable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:599
|
||||
msgid "failed to seek past error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:619
|
||||
#: src/pv/transfer.c:1283
|
||||
msgid "skipped past read error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
#: src/pv/transfer.c:1642
|
||||
msgid "write error"
|
||||
msgstr "ჩაწერის შეცდომა"
|
||||
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
#: src/pv/watchpid.c:160 src/pv/watchpid.c:288
|
||||
msgid "not a regular file or block device"
|
||||
msgstr ""
|
||||
|
||||
@@ -6,9 +6,9 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-12-15 20:10+0000\n"
|
||||
"PO-Revision-Date: 2025-10-02 13:23+0000\n"
|
||||
"Last-Translator: Coral Pink <coralpink@noreply.codeberg.org>\n"
|
||||
"POT-Creation-Date: 2026-08-01 14:53+0100\n"
|
||||
"PO-Revision-Date: 2026-08-01 18:32+0000\n"
|
||||
"Last-Translator: a-j-wood <a-j-wood@noreply.codeberg.org>\n"
|
||||
"Language-Team: Polish <https://translate.codeberg.org/projects/pv/pv/pl/>\n"
|
||||
"Language: pl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -16,371 +16,362 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
|
||||
"|| n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.13.2\n"
|
||||
"X-Generator: Weblate 2026.7.1\n"
|
||||
|
||||
#: src/main/help.c:236
|
||||
#: src/main/help.c:300
|
||||
msgid "show progress bar"
|
||||
msgstr "pokaż pasek postępu"
|
||||
|
||||
#: src/main/help.c:239
|
||||
#: src/main/help.c:303
|
||||
msgid "show elapsed time"
|
||||
msgstr "pokaż upływający czas"
|
||||
|
||||
#: src/main/help.c:242
|
||||
#: src/main/help.c:306
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "pokaż szacowany czas ukończenia"
|
||||
|
||||
#: src/main/help.c:245
|
||||
#: src/main/help.c:309
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "pokaż bezwzględny szacowany czas ukończenia"
|
||||
|
||||
#: src/main/help.c:248
|
||||
#: src/main/help.c:312
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "pokaż licznik prędkości przesyłania"
|
||||
|
||||
#: src/main/help.c:251
|
||||
#: src/main/help.c:315
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "pokaż licznik uśrednionej prędkości przesyłania"
|
||||
|
||||
#: src/main/help.c:254
|
||||
#: src/main/help.c:318
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "pokaż ilość przesłanych bajtów"
|
||||
|
||||
#: src/main/help.c:257
|
||||
#: src/main/help.c:321
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "pokaż procentowe użycie bufora transferu"
|
||||
|
||||
#: src/main/help.c:259
|
||||
#: src/main/help.c:323
|
||||
msgid "NUM"
|
||||
msgstr "LICZBA"
|
||||
|
||||
#: src/main/help.c:260
|
||||
#: src/main/help.c:324
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "pokaż ostatnie LICZBA przesłanych bajtów"
|
||||
|
||||
#: src/main/help.c:262
|
||||
#: src/main/help.c:326
|
||||
msgid "FORMAT"
|
||||
msgstr "FORMAT"
|
||||
|
||||
#: src/main/help.c:263
|
||||
#: src/main/help.c:327
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "ustaw FORMAT jako format wyjściowy"
|
||||
|
||||
#: src/main/help.c:266
|
||||
#: src/main/help.c:330
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "wyświetl wyjście procentowo, bez graficznej prezentacji"
|
||||
|
||||
#: src/main/help.c:269
|
||||
#: src/main/help.c:333
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "nie wyświetlaj żadnych informacji o przesyłaniu"
|
||||
|
||||
#: src/main/help.c:273
|
||||
#: src/main/help.c:337
|
||||
msgid "show number of bits transferred"
|
||||
msgstr "pokaż ilość przesłanych bitów"
|
||||
|
||||
#: src/main/help.c:276
|
||||
#: src/main/help.c:340
|
||||
msgid "treat suffixes as multiples of 1000 rather than 1024"
|
||||
msgstr "traktuj przyrostki jako wielokrotności 1000 zamiast 1024"
|
||||
|
||||
#: src/main/help.c:279
|
||||
#: src/main/help.c:343
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "nie wyświetlaj nic aż do pierwszego przesłanego bajtu"
|
||||
|
||||
#: src/main/help.c:281 src/main/help.c:296 src/main/help.c:299
|
||||
#: src/main/help.c:345 src/main/help.c:360 src/main/help.c:363
|
||||
msgid "SEC"
|
||||
msgstr "SEKUNDY"
|
||||
|
||||
#: src/main/help.c:282
|
||||
#: src/main/help.c:346
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "nie wyświetlaj nic do momentu upłynięcia SEKUNDY sekund"
|
||||
|
||||
#: src/main/help.c:284
|
||||
#: src/main/help.c:348
|
||||
msgid "SIZE"
|
||||
msgstr "ROZMIAR"
|
||||
|
||||
#: src/main/help.c:285
|
||||
#: src/main/help.c:349
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "ustaw oczekiwany rozmiar danych na ROZMIAR bajtów"
|
||||
|
||||
#: src/main/help.c:288
|
||||
#: src/main/help.c:352
|
||||
msgid "if size unknown, show rate vs max rate"
|
||||
msgstr ""
|
||||
"jeśli rozmiar nie jest znany, wyświetl zestawienie prędkości do maksymalnej "
|
||||
"prędkości"
|
||||
|
||||
#: src/main/help.c:291
|
||||
#: src/main/help.c:355
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "zliczaj linie zamiast bajty"
|
||||
|
||||
#: src/main/help.c:294
|
||||
#: src/main/help.c:358
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "linie są zakończone znakiem NUL"
|
||||
|
||||
#: src/main/help.c:297
|
||||
#: src/main/help.c:361
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "aktualizuj co każde SEKUNDY sekund"
|
||||
|
||||
#: src/main/help.c:300
|
||||
#: src/main/help.c:364
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
"oblicz średnią prędkość transferu na podstawie poprzednich SEKUNDY sekund "
|
||||
"(domyślnie 30 s)"
|
||||
|
||||
#: src/main/help.c:302
|
||||
#: src/main/help.c:366
|
||||
msgid "WIDTH"
|
||||
msgstr "SZEROKOŚĆ"
|
||||
|
||||
#: src/main/help.c:303
|
||||
#: src/main/help.c:367
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "przyjmij, że terminal ma szerokość SZEROKOŚĆ znaków"
|
||||
|
||||
#: src/main/help.c:305
|
||||
#: src/main/help.c:369
|
||||
msgid "HEIGHT"
|
||||
msgstr "WYSOKOŚĆ"
|
||||
|
||||
#: src/main/help.c:306
|
||||
#: src/main/help.c:370
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "przyjmij, że terminal ma wysokość WYSOKOŚĆ linii"
|
||||
|
||||
#: src/main/help.c:308
|
||||
#: src/main/help.c:372
|
||||
msgid "NAME"
|
||||
msgstr "NAZWA"
|
||||
|
||||
#: src/main/help.c:309
|
||||
#: src/main/help.c:373
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "poprzedź informacje prefiksem NAZWA"
|
||||
|
||||
#: src/main/help.c:311
|
||||
#: src/main/help.c:375
|
||||
msgid "STYLE"
|
||||
msgstr "STYL"
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "set default bar style to NAME"
|
||||
#: src/main/help.c:376
|
||||
msgid "set default bar style to STYLE"
|
||||
msgstr "ustaw domyślny styl paska postępu na STYL"
|
||||
|
||||
#: src/main/help.c:314
|
||||
#: src/main/help.c:378
|
||||
msgid "SPEC"
|
||||
msgstr "SPEC"
|
||||
|
||||
#: src/main/help.c:315
|
||||
#: src/main/help.c:379
|
||||
msgid "also send progress to SPEC"
|
||||
msgstr "wysyłaj postęp również do SPEC"
|
||||
|
||||
#: src/main/help.c:318
|
||||
#: src/main/help.c:382
|
||||
msgid "set terminal progress state with OSC 9;4 (ConEmu)"
|
||||
msgstr "aktualizacja stanu zaawansowania terminala za pomocą OSC 9;4 (ConEmu)"
|
||||
|
||||
#: src/main/help.c:385
|
||||
msgid "output transfer statistics at the end"
|
||||
msgstr "wyświetl na końcu statystyki transferu"
|
||||
|
||||
#: src/main/help.c:321
|
||||
#: src/main/help.c:388
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "pokaż wyjście nawet standardowe wyjście błędu nie jest terminalem"
|
||||
|
||||
#: src/main/help.c:324
|
||||
#: src/main/help.c:391
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "używaj znaków ucieczki do pozycjonowania kursora"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
#: src/main/help.c:394 src/main/help.c:430 src/main/help.c:449
|
||||
#: src/main/help.c:459
|
||||
msgid "FILE"
|
||||
msgstr "PLIK"
|
||||
|
||||
#: src/main/help.c:328
|
||||
#: src/main/help.c:395
|
||||
msgid "write output to FILE instead of stdout"
|
||||
msgstr "zapisz wyjście do PLIK zamiast do wyjścia standardowego"
|
||||
|
||||
#: src/main/help.c:330
|
||||
#: src/main/help.c:397
|
||||
msgid "RATE"
|
||||
msgstr "PRĘDKOŚĆ"
|
||||
|
||||
#: src/main/help.c:331
|
||||
#: src/main/help.c:398
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "ogranicz przesyłane dane do PRĘDKOŚĆ bajtów na sekundę"
|
||||
|
||||
#: src/main/help.c:333 src/main/help.c:342
|
||||
#: src/main/help.c:400 src/main/help.c:406 src/main/help.c:412
|
||||
msgid "BYTES"
|
||||
msgstr "BAJTY"
|
||||
|
||||
#: src/main/help.c:334
|
||||
#: src/main/help.c:401
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "użyj bufora o rozmiarze BAJTY"
|
||||
|
||||
#: src/main/help.c:337
|
||||
#: src/main/help.c:404
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "nigdy nie używaj splice(), zawsze używaj read/write"
|
||||
|
||||
#: src/main/help.c:340
|
||||
#: src/main/help.c:407
|
||||
msgid "set the pipe buffer size to BYTES"
|
||||
msgstr "użyj bufora potokowego o rozmiarze BAJTY"
|
||||
|
||||
#: src/main/help.c:410
|
||||
msgid "skip read errors in input"
|
||||
msgstr "pomijaj błędy odczytu wejścia"
|
||||
|
||||
#: src/main/help.c:343
|
||||
#: src/main/help.c:413
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr "pomijaj błędy w blokach po BAJTY bajtów na raz"
|
||||
|
||||
#: src/main/help.c:346
|
||||
#: src/main/help.c:416
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "zakończ po przesłaniu --size bajtów"
|
||||
|
||||
#: src/main/help.c:349
|
||||
#: src/main/help.c:419
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr "wymuś zapis pamięci podręcznej na dysk po każdym zapisie"
|
||||
|
||||
#: src/main/help.c:352
|
||||
#: src/main/help.c:422
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
"użyj bezpośredniego wejścia/wyjścia celem pominięcia pamięci podręcznej"
|
||||
|
||||
#: src/main/help.c:355
|
||||
#: src/main/help.c:425
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
msgstr "próbuj przewinąć zamiast wypisywać zerowe bajty"
|
||||
|
||||
#: src/main/help.c:358
|
||||
#: src/main/help.c:428
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr "zignoruj dane wejściowe zamiast wyświetlić je na wyjściu standardowym"
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:431
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr ""
|
||||
"zapisz wszystkie dane wejściowe do PLIK przed wyświetleniem ich na wyjściu"
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:434
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
msgstr "PID[:FD]|=NAZWA|@PLIKLISTY"
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:435
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "obserwuj plik FD otworzony przez proces PID"
|
||||
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
#: src/main/help.c:438 src/main/help.c:441
|
||||
msgid "PID"
|
||||
msgstr "PID"
|
||||
|
||||
#: src/main/help.c:369
|
||||
#: src/main/help.c:439
|
||||
msgid "update settings of process PID"
|
||||
msgstr "zaktualizuj ustawienia procesu PID"
|
||||
|
||||
#: src/main/help.c:372
|
||||
#: src/main/help.c:442
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
msgstr "pokaż postęp procesu PID"
|
||||
|
||||
#: src/main/help.c:377
|
||||
#: src/main/help.c:446
|
||||
msgid "run a command and monitor its standard input, output, or both"
|
||||
msgstr "uruchom polecenie i monitoruj jego wejście i/lub wyjście standardowe"
|
||||
|
||||
#: src/main/help.c:450
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "zapisz ID procesu do PLIK"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:453
|
||||
msgid "show this help and exit"
|
||||
msgstr "wyświetl te informacje z pomocą i wyjdź"
|
||||
|
||||
#: src/main/help.c:383
|
||||
#: src/main/help.c:456
|
||||
msgid "show version information and exit"
|
||||
msgstr "wyświetl informacje o wersji i wyjdź"
|
||||
|
||||
#: src/main/help.c:387
|
||||
#: src/main/help.c:460
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "zapisz logi debugujące do PLIK"
|
||||
|
||||
#: src/main/help.c:413
|
||||
#: src/main/help.c:486
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Sposób użycia: %s [OPCJA] [PLIK]..."
|
||||
|
||||
#: src/main/help.c:424
|
||||
#: src/main/help.c:497
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
"Łączenie PLIK(ów) lub wejścia standardowego, do wyjścia standardowego z "
|
||||
"monitoringiem."
|
||||
"monitorowaniem."
|
||||
|
||||
#: src/main/help.c:562
|
||||
#: src/main/help.c:639
|
||||
msgid "Supported format sequences:"
|
||||
msgstr "Wspierane sekwencje formatowania:"
|
||||
|
||||
#: src/main/help.c:576
|
||||
#: src/main/help.c:653
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Proszę przesyłać zgłoszenia błędów do %s"
|
||||
|
||||
#: src/main/main.c:228
|
||||
#: src/main/main.c:225
|
||||
msgid "(input)"
|
||||
msgstr "(wejście)"
|
||||
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr "alokacja stanu programu nie powiodła się"
|
||||
#: src/main/main.c:381 src/main/options.c:1359
|
||||
msgid "a command to run must be specified"
|
||||
msgstr "polecenie do uruchomienia musi zostać określone"
|
||||
|
||||
#: src/main/options.c:370
|
||||
#: src/main/main.c:704 src/main/options.c:757 src/main/options.c:777
|
||||
#: src/pv/display.c:1086 src/pv/state.c:45 src/pv/state.c:902
|
||||
#: src/pv/state.c:914 src/pv/state.c:950 src/pv/transfer.c:1335
|
||||
#: src/pv/transfer.c:1451 src/pv/transfer.c:1778
|
||||
msgid "memory allocation failure"
|
||||
msgstr "błąd przydziału pamięci"
|
||||
|
||||
#: src/main/options.c:418
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
msgstr "pliki list nie mogą zawierać linii wykorzystujących @"
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
#: src/main/options.c:438 src/main/options.c:440 src/main/options.c:901
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr "oczekiwany proces ID lub para PID:FD"
|
||||
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
#: src/main/options.c:449 src/main/options.c:451 src/main/options.c:908
|
||||
msgid "invalid process ID"
|
||||
msgstr "niepoprawne ID procesu"
|
||||
|
||||
#: src/main/options.c:448 src/pv/file.c:342
|
||||
msgid "failed to stat file"
|
||||
msgstr "nie udało się wykonać operacji stat na pliku"
|
||||
|
||||
#: src/main/options.c:462
|
||||
msgid "is a directory"
|
||||
msgstr "jest katalogiem"
|
||||
|
||||
#: src/main/options.c:491
|
||||
msgid "failed to generate sysfs filename"
|
||||
msgstr "nie udało się wygenerować nazwy pliku dla sysfs"
|
||||
|
||||
#: src/main/options.c:513
|
||||
msgid "failed to read sysfs size file"
|
||||
msgstr "nie udało się odczytać rozmiaru pliku sysfs"
|
||||
|
||||
#: src/main/options.c:533
|
||||
msgid "failed to open block device"
|
||||
msgstr "nie udało się otworzyć urządzenia blokowego"
|
||||
|
||||
#: src/main/options.c:543
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr "nie udało się ustalić rozmiaru urządzenia blokowego"
|
||||
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "nie udało się zaalokować struktur opcji"
|
||||
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "nie udało się zaalokować struktur opcji argv"
|
||||
|
||||
#: src/main/options.c:723
|
||||
#: src/main/options.c:829
|
||||
msgid "numeric value not understood"
|
||||
msgstr "wartość liczbowa niezrozumiana"
|
||||
|
||||
#: src/main/options.c:743
|
||||
#: src/main/options.c:843
|
||||
msgid "integer argument expected"
|
||||
msgstr "oczekiwany argument typu liczby całkowitej"
|
||||
|
||||
#: src/main/options.c:755
|
||||
#: src/main/options.c:853
|
||||
msgid "numeric argument expected"
|
||||
msgstr "oczekiwany argument liczbowy"
|
||||
|
||||
#: src/main/options.c:767
|
||||
#: src/main/options.c:864
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
msgstr "brakująca nazwa pliku"
|
||||
|
||||
#: src/main/options.c:795
|
||||
#: src/main/options.c:890
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
msgstr "brakująca nazwa procesu"
|
||||
|
||||
#: src/main/options.c:1056
|
||||
#: src/main/options.c:1182
|
||||
msgid "invalid side specification"
|
||||
msgstr "niepoprawne określenie monitorowanych stron"
|
||||
|
||||
#: src/main/options.c:1197
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Spróbuj `%s --help' by uzyskać więcej informacji."
|
||||
|
||||
#: src/main/options.c:1058
|
||||
#: src/main/options.c:1199
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Spróbuj `%s -h' by uzyskać więcej informacji."
|
||||
|
||||
#: src/main/options.c:1089
|
||||
#: src/main/options.c:1231
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -388,37 +379,47 @@ msgstr ""
|
||||
"nie można użyć trybu zliczania linii lub opcji modyfikujących przesył "
|
||||
"łącznie z opcją obserwowania deskryptorów plików"
|
||||
|
||||
#: src/main/options.c:1098
|
||||
#: src/main/options.c:1239
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
"nie można użyć pozycjonowania kursora łącznie z opcją obserwowania "
|
||||
"deskryptorów plików"
|
||||
|
||||
#: src/main/options.c:1107
|
||||
#: src/main/options.c:1247
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
"nie można użyć opcji zaktualizowania ustawień procesu łącznie z opcją "
|
||||
"obserwowania deskryptorów plików"
|
||||
"nie można korzystać ze zdalnego sterowania łącznie z obserwowaniem "
|
||||
"deskryptorów plików"
|
||||
|
||||
#: src/main/options.c:1116
|
||||
#: src/main/options.c:1255
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
"nie można korzystać ze zdalnego odczytu łącznie z obserwowaniem deskryptorów "
|
||||
"plików"
|
||||
|
||||
#: src/main/options.c:1125
|
||||
#: src/main/options.c:1263
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr "nie można przesyłać plików z opcją obserwowania deskryptorów plików"
|
||||
|
||||
#: src/main/options.c:1150
|
||||
#: src/main/options.c:1287
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "niedostępne na systemach bez /proc/self/fdinfo"
|
||||
|
||||
#: src/main/options.c:1162
|
||||
#: src/main/options.c:1298
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
msgstr "nie można użyć zdalnego sterowania i zdalnego odczytu jednocześnie"
|
||||
|
||||
#: src/main/options.c:1189
|
||||
#: src/main/options.c:1325
|
||||
msgid "monitor mode cannot be specified with this option"
|
||||
msgstr "tryb monitorowania nie może być określony z tą opcją"
|
||||
|
||||
#: src/main/options.c:1337
|
||||
msgid "monitor mode cannot be used with store-and-forward"
|
||||
msgstr "tryb monitorowania nie może być użyty z store-and-forward"
|
||||
|
||||
#: src/main/options.c:1348
|
||||
msgid "files cannot be specified with this option"
|
||||
msgstr ""
|
||||
msgstr "pliki nie mogą być określone przy użyciu tej opcji"
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid "License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
@@ -436,66 +437,44 @@ msgstr "Nie udziela się GWARANCJI w zakresie dozwolonym przez prawo."
|
||||
msgid "Project web site"
|
||||
msgstr "Strona projektu"
|
||||
|
||||
#: src/pv/cursor.c:61
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "nie udało się uzyskać nazwy terminala"
|
||||
|
||||
# "Przewidywany czas ukończenia" for ETA is too long
|
||||
#: src/pv/cursor.c:106
|
||||
#: src/pv/cursor.c:108 src/pv/cursor.c:135
|
||||
msgid "failed to open lock file"
|
||||
msgstr "nie udało się otworzyć pliku blokowania zasobów"
|
||||
|
||||
#: src/pv/cursor.c:139
|
||||
msgid "lock attempt failed"
|
||||
msgstr "blokada zasobów nie powiodła się"
|
||||
#: src/pv/cursor.c:790 src/pv/cursor.c:792
|
||||
msgid "interrupted by a signal"
|
||||
msgstr "przerwany przez sygnał"
|
||||
|
||||
#: src/pv/cursor.c:400
|
||||
msgid "failed to open terminal"
|
||||
msgstr "nie udało się otworzyć terminala"
|
||||
|
||||
#: src/pv/display.c:285
|
||||
#: src/pv/display.c:311
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr "yzafpnum kMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:303
|
||||
#: src/pv/display.c:329
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr "yzafpnum KMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "nie udało się zaalokować bufora"
|
||||
#: src/pv/file.c:81
|
||||
msgid "/dev/null is not usable"
|
||||
msgstr "/dev/null nie nadaje się do użytku"
|
||||
|
||||
#: src/pv/file.c:153
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr "nie udało się przewinąć wyjścia do początku"
|
||||
#: src/pv/file.c:371
|
||||
msgid "error closing file"
|
||||
msgstr "błąd zamknięcia pliku"
|
||||
|
||||
# "Przewidywany czas ukończenia" for ETA is too long
|
||||
#: src/pv/file.c:303
|
||||
msgid "failed to close file"
|
||||
msgstr "nie udało się zamknąć pliku"
|
||||
#: src/pv/file.c:438
|
||||
msgid "input file is also the output"
|
||||
msgstr "plik wejściowy jest również plikiem wyjściowym"
|
||||
|
||||
#: src/pv/file.c:335
|
||||
msgid "failed to read file"
|
||||
msgstr "nie udało się odczytać pliku"
|
||||
|
||||
#: src/pv/file.c:350
|
||||
msgid "failed to stat output file"
|
||||
msgstr "nie udało się wykonać operacji stat na pliku wyjściowym"
|
||||
|
||||
#: src/pv/file.c:372
|
||||
msgid "input file is output file"
|
||||
msgstr "plik wejściowy jest zarazem plikiem wyjściowym"
|
||||
|
||||
#: src/pv/file.c:429
|
||||
#: src/pv/file.c:596
|
||||
msgid "(none)"
|
||||
msgstr "(brak)"
|
||||
|
||||
#: src/pv/file.c:431
|
||||
#: src/pv/file.c:598
|
||||
msgid "(stdin)"
|
||||
msgstr "(stdin)"
|
||||
|
||||
#: src/pv/format/averagerate.c:34 src/pv/format/progressbar.c:92
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:181
|
||||
msgid "b/s"
|
||||
msgstr "b/s"
|
||||
|
||||
@@ -505,7 +484,7 @@ msgid "/s"
|
||||
msgstr "/s"
|
||||
|
||||
#: src/pv/format/averagerate.c:38 src/pv/format/progressbar.c:96
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:181
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
@@ -513,105 +492,143 @@ msgstr "B/s"
|
||||
msgid "b"
|
||||
msgstr "b"
|
||||
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:620
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:1284
|
||||
msgid "B"
|
||||
msgstr "B"
|
||||
|
||||
#: src/pv/format/eta.c:52 src/pv/format/eta.c:56
|
||||
# "Przewidywany czas ukończenia" for ETA is too long
|
||||
#: src/pv/format/eta.c:63 src/pv/format/eta.c:67
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/format/fineta.c:80
|
||||
#: src/pv/format/fineta.c:93
|
||||
msgid "FIN"
|
||||
msgstr "FIN"
|
||||
|
||||
#: src/pv/loop.c:120
|
||||
#: src/pv/loop.c:180
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr "prędkość min/śr/max/odch"
|
||||
|
||||
#: src/pv/loop.c:132
|
||||
#: src/pv/loop.c:192
|
||||
msgid "rate not measured"
|
||||
msgstr "prędkość niezmierzona"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/loop.c:818 src/pv/loop.c:836 src/pv/watchpid.c:101
|
||||
#: src/pv/watchpid.c:110 src/pv/watchpid.c:121 src/pv/watchpid.c:129
|
||||
#: src/pv/watchpid.c:166 src/pv/watchpid.c:185 src/pv/watchpid.c:193
|
||||
#: src/pv/watchpid.c:203 src/pv/watchpid.c:307 src/pv/watchpid.c:315
|
||||
#: src/pv/watchpid.c:447 src/pv/watchpid.c:470
|
||||
#: src/pv/loop.c:1098 src/pv/loop.c:1114 src/pv/loop.c:1132 src/pv/remote.c:93
|
||||
#: src/pv/remote.c:188 src/pv/remote.c:536 src/pv/remote.c:582
|
||||
#: src/pv/watchpid.c:123 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:158 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:206 src/pv/watchpid.c:218 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:286 src/pv/watchpid.c:401
|
||||
#: src/pv/watchpid.c:409 src/pv/watchpid.c:556 src/pv/watchpid.c:565
|
||||
#: src/pv/watchpid.c:586
|
||||
msgid "pid"
|
||||
msgstr "pid"
|
||||
|
||||
#: src/pv/loop.c:836 src/pv/watchpid.c:110 src/pv/watchpid.c:122
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:185 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:205
|
||||
#: src/pv/loop.c:1132 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:160 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:288
|
||||
msgid "fd"
|
||||
msgstr "fd"
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
#: src/pv/remote.c:242 src/pv/remote.c:636
|
||||
msgid "message not received"
|
||||
msgstr "wiadomość nieodebrana"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
#: src/pv/remote.c:659 src/pv/remote.c:677
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO nie jest wspierane na tym systemie"
|
||||
|
||||
#: src/pv/state.c:42
|
||||
msgid "history structure allocation failed"
|
||||
msgstr "nie udało się zaalokować struktury historii"
|
||||
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr "nie udało się zaalokować listy plików"
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr "błąd odczytu"
|
||||
|
||||
#: src/pv/transfer.c:506
|
||||
#: src/pv/transfer.c:1173
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "ostrzeżenie: błędy odczytu wykryte"
|
||||
|
||||
#: src/pv/transfer.c:522
|
||||
msgid "file is not seekable"
|
||||
msgstr "pliku nie da się przewijać"
|
||||
|
||||
#: src/pv/transfer.c:599
|
||||
msgid "failed to seek past error"
|
||||
msgstr "nie udało się przewinąć za błąd"
|
||||
|
||||
#: src/pv/transfer.c:619
|
||||
#: src/pv/transfer.c:1283
|
||||
msgid "skipped past read error"
|
||||
msgstr "pominięto błąd odczytu"
|
||||
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr "brak zaalokowanego bufora transferu"
|
||||
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr "nie udało się ustawić interwału czasowego"
|
||||
|
||||
# "Przewidywany czas ukończenia" for ETA is too long
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr "nie udało się wyczyścić interwału czasowego"
|
||||
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr "alokacja buforu pozycji linii nie powiodła się"
|
||||
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
#: src/pv/transfer.c:1642
|
||||
msgid "write error"
|
||||
msgstr "błąd zapisu"
|
||||
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "nie udało się wywołać funkcji select"
|
||||
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
#: src/pv/watchpid.c:160 src/pv/watchpid.c:288
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "plik nie jest plikiem regularnym lub urządzeniem blokowym"
|
||||
|
||||
#~ msgid "state allocation failed"
|
||||
#~ msgstr "alokacja stanu programu nie powiodła się"
|
||||
|
||||
#~ msgid "failed to stat file"
|
||||
#~ msgstr "nie udało się wykonać operacji stat na pliku"
|
||||
|
||||
#~ msgid "is a directory"
|
||||
#~ msgstr "jest katalogiem"
|
||||
|
||||
#~ msgid "failed to generate sysfs filename"
|
||||
#~ msgstr "nie udało się wygenerować nazwy pliku dla sysfs"
|
||||
|
||||
#~ msgid "failed to read sysfs size file"
|
||||
#~ msgstr "nie udało się odczytać rozmiaru pliku sysfs"
|
||||
|
||||
#~ msgid "failed to open block device"
|
||||
#~ msgstr "nie udało się otworzyć urządzenia blokowego"
|
||||
|
||||
#~ msgid "failed to determine size of block device"
|
||||
#~ msgstr "nie udało się ustalić rozmiaru urządzenia blokowego"
|
||||
|
||||
#~ msgid "option structure allocation failed"
|
||||
#~ msgstr "nie udało się zaalokować struktur opcji"
|
||||
|
||||
#~ msgid "option structure argv allocation failed"
|
||||
#~ msgstr "nie udało się zaalokować struktur opcji argv"
|
||||
|
||||
#~ msgid "failed to get terminal name"
|
||||
#~ msgstr "nie udało się uzyskać nazwy terminala"
|
||||
|
||||
#~ msgid "lock attempt failed"
|
||||
#~ msgstr "blokada zasobów nie powiodła się"
|
||||
|
||||
#~ msgid "failed to open terminal"
|
||||
#~ msgstr "nie udało się otworzyć terminala"
|
||||
|
||||
#~ msgid "failed to seek to start of output"
|
||||
#~ msgstr "nie udało się przewinąć wyjścia do początku"
|
||||
|
||||
#~ msgid "failed to read file"
|
||||
#~ msgstr "nie udało się odczytać pliku"
|
||||
|
||||
#~ msgid "failed to stat output file"
|
||||
#~ msgstr "nie udało się wykonać operacji stat na pliku wyjściowym"
|
||||
|
||||
#~ msgid "history structure allocation failed"
|
||||
#~ msgstr "nie udało się zaalokować struktury historii"
|
||||
|
||||
#~ msgid "file list allocation failed"
|
||||
#~ msgstr "nie udało się zaalokować listy plików"
|
||||
|
||||
#~ msgid "read failed"
|
||||
#~ msgstr "błąd odczytu"
|
||||
|
||||
#~ msgid "file is not seekable"
|
||||
#~ msgstr "pliku nie da się przewijać"
|
||||
|
||||
#~ msgid "failed to seek past error"
|
||||
#~ msgstr "nie udało się przewinąć za błąd"
|
||||
|
||||
#~ msgid "no transfer buffer allocated"
|
||||
#~ msgstr "brak zaalokowanego bufora transferu"
|
||||
|
||||
#~ msgid "failed to set interval timer"
|
||||
#~ msgstr "nie udało się ustawić interwału czasowego"
|
||||
|
||||
#~ msgid "failed to clear interval timer"
|
||||
#~ msgstr "nie udało się wyczyścić interwału czasowego"
|
||||
|
||||
#~ msgid "line position buffer allocation failed"
|
||||
#~ msgstr "alokacja buforu pozycji linii nie powiodła się"
|
||||
|
||||
#~ msgid "select call failed"
|
||||
#~ msgstr "nie udało się wywołać funkcji select"
|
||||
|
||||
#~ msgid "process list allocation failed"
|
||||
#~ msgstr "nie udało się zaalokować listy procesów"
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-12-15 20:10+0000\n"
|
||||
"POT-Creation-Date: 2026-08-01 14:53+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -15,363 +15,354 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/main/help.c:236
|
||||
#: src/main/help.c:300
|
||||
msgid "show progress bar"
|
||||
msgstr "exibe barra de progressão"
|
||||
|
||||
#: src/main/help.c:239
|
||||
#: src/main/help.c:303
|
||||
msgid "show elapsed time"
|
||||
msgstr "exibe tempo passado"
|
||||
|
||||
#: src/main/help.c:242
|
||||
#: src/main/help.c:306
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "exibe o tempo estimado de término"
|
||||
|
||||
#: src/main/help.c:245
|
||||
#: src/main/help.c:309
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "exibe o tempo absoluto estimado de término"
|
||||
|
||||
#: src/main/help.c:248
|
||||
#: src/main/help.c:312
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "exibe a taxa de transferência"
|
||||
|
||||
#: src/main/help.c:251
|
||||
#: src/main/help.c:315
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "exibe o contador da taxa média de transferência de dados"
|
||||
|
||||
#: src/main/help.c:254
|
||||
#: src/main/help.c:318
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "exibe a quantidade de bytes transferidos"
|
||||
|
||||
#: src/main/help.c:257
|
||||
#: src/main/help.c:321
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "exibe a porcentagem de buffer de transferência em uso"
|
||||
|
||||
#: src/main/help.c:259
|
||||
#: src/main/help.c:323
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:260
|
||||
#: src/main/help.c:324
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "exibe NUM bytes gravados pela última vez"
|
||||
|
||||
#: src/main/help.c:262
|
||||
#: src/main/help.c:326
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:263
|
||||
#: src/main/help.c:327
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "definir o formato de saída para FORMAT"
|
||||
|
||||
#: src/main/help.c:266
|
||||
#: src/main/help.c:330
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "exibe apenas as porcentagens, sem informações visuais"
|
||||
|
||||
#: src/main/help.c:269
|
||||
#: src/main/help.c:333
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "executa programa sem exibir quaisquer informações"
|
||||
|
||||
#: src/main/help.c:273
|
||||
#: src/main/help.c:337
|
||||
msgid "show number of bits transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:276
|
||||
#: src/main/help.c:340
|
||||
msgid "treat suffixes as multiples of 1000 rather than 1024"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:279
|
||||
#: src/main/help.c:343
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "não exibe nada até iniciar o processamento"
|
||||
|
||||
#: src/main/help.c:281 src/main/help.c:296 src/main/help.c:299
|
||||
#: src/main/help.c:345 src/main/help.c:360 src/main/help.c:363
|
||||
msgid "SEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:282
|
||||
#: src/main/help.c:346
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "não exibir nada até que os segundos SEC tenham passado"
|
||||
|
||||
#: src/main/help.c:284
|
||||
#: src/main/help.c:348
|
||||
msgid "SIZE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:285
|
||||
#: src/main/help.c:349
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "seta a quantidade estimada de dados em SIZE bytes"
|
||||
|
||||
#: src/main/help.c:288
|
||||
#: src/main/help.c:352
|
||||
msgid "if size unknown, show rate vs max rate"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:291
|
||||
#: src/main/help.c:355
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "contar linhas em vez de bytes"
|
||||
|
||||
#: src/main/help.c:294
|
||||
#: src/main/help.c:358
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "linhas são terminadas em nulo"
|
||||
|
||||
#: src/main/help.c:297
|
||||
#: src/main/help.c:361
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "atualiza informações a cada SEC segundos"
|
||||
|
||||
#: src/main/help.c:300
|
||||
#: src/main/help.c:364
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:302
|
||||
#: src/main/help.c:366
|
||||
msgid "WIDTH"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:303
|
||||
#: src/main/help.c:367
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "presuma que o terminal tem WIDTH caracteres de largura"
|
||||
|
||||
#: src/main/help.c:305
|
||||
#: src/main/help.c:369
|
||||
msgid "HEIGHT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:306
|
||||
#: src/main/help.c:370
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "presuma que o terminal tem HEIGHT caracteres de altura"
|
||||
|
||||
#: src/main/help.c:308
|
||||
#: src/main/help.c:372
|
||||
msgid "NAME"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:309
|
||||
#: src/main/help.c:373
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "exibe NAME antes das demais informações"
|
||||
|
||||
#: src/main/help.c:311
|
||||
#: src/main/help.c:375
|
||||
msgid "STYLE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "set default bar style to NAME"
|
||||
#: src/main/help.c:376
|
||||
msgid "set default bar style to STYLE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:314
|
||||
#: src/main/help.c:378
|
||||
msgid "SPEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:315
|
||||
#: src/main/help.c:379
|
||||
msgid "also send progress to SPEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:318
|
||||
#: src/main/help.c:382
|
||||
msgid "set terminal progress state with OSC 9;4 (ConEmu)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:385
|
||||
msgid "output transfer statistics at the end"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:321
|
||||
#: src/main/help.c:388
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "gera dados mesmo que a saída de erro seja redirecionada"
|
||||
|
||||
#: src/main/help.c:324
|
||||
#: src/main/help.c:391
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "utiliza caracteres de escape para posicionar o cursor"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
#: src/main/help.c:394 src/main/help.c:430 src/main/help.c:449
|
||||
#: src/main/help.c:459
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:328
|
||||
#: src/main/help.c:395
|
||||
msgid "write output to FILE instead of stdout"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:330
|
||||
#: src/main/help.c:397
|
||||
msgid "RATE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:331
|
||||
#: src/main/help.c:398
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "limita a transferência a RATE bytes por segundo"
|
||||
|
||||
#: src/main/help.c:333 src/main/help.c:342
|
||||
#: src/main/help.c:400 src/main/help.c:406 src/main/help.c:412
|
||||
msgid "BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:334
|
||||
#: src/main/help.c:401
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "use um tamanho de buffer de BYTES"
|
||||
|
||||
#: src/main/help.c:337
|
||||
#: src/main/help.c:404
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "nunca use splice(), sempre use read/write"
|
||||
|
||||
#: src/main/help.c:340
|
||||
#: src/main/help.c:407
|
||||
msgid "set the pipe buffer size to BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:410
|
||||
msgid "skip read errors in input"
|
||||
msgstr "ignorar erros de leitura em entrada"
|
||||
|
||||
#: src/main/help.c:343
|
||||
#: src/main/help.c:413
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:346
|
||||
#: src/main/help.c:416
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "parar após --size bytes terem sido transferidos"
|
||||
|
||||
#: src/main/help.c:349
|
||||
#: src/main/help.c:419
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:352
|
||||
#: src/main/help.c:422
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:355
|
||||
#: src/main/help.c:425
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
#: src/main/help.c:428
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:431
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:434
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:435
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "assistir arquivo FD aberto pelo processo PID"
|
||||
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
#: src/main/help.c:438 src/main/help.c:441
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:369
|
||||
#: src/main/help.c:439
|
||||
msgid "update settings of process PID"
|
||||
msgstr "atualizar as configurações do processo PID"
|
||||
|
||||
#: src/main/help.c:372
|
||||
#: src/main/help.c:442
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
#: src/main/help.c:446
|
||||
msgid "run a command and monitor its standard input, output, or both"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:450
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "salvar ID do processo em FILE"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:453
|
||||
msgid "show this help and exit"
|
||||
msgstr "exibe esta tela de ajuda e termina"
|
||||
|
||||
#: src/main/help.c:383
|
||||
#: src/main/help.c:456
|
||||
msgid "show version information and exit"
|
||||
msgstr "exibe a versão e termina"
|
||||
|
||||
#: src/main/help.c:387
|
||||
#: src/main/help.c:460
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:413
|
||||
#: src/main/help.c:486
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Uso: %s [OPÇÕES] [ARQUIVOS]..."
|
||||
|
||||
#: src/main/help.c:424
|
||||
#: src/main/help.c:497
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
"Concatena ARQUIVO(s) ou a entrada padrão e grava na saída padrão, com "
|
||||
"monitoramento."
|
||||
|
||||
#: src/main/help.c:562
|
||||
#: src/main/help.c:639
|
||||
msgid "Supported format sequences:"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:576
|
||||
#: src/main/help.c:653
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Por favor, reporte quaisquer defeitos para %s"
|
||||
|
||||
#: src/main/main.c:228
|
||||
#: src/main/main.c:225
|
||||
msgid "(input)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr "alocação de memória de status falhou"
|
||||
#: src/main/main.c:381 src/main/options.c:1359
|
||||
msgid "a command to run must be specified"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:370
|
||||
#: src/main/main.c:704 src/main/options.c:757 src/main/options.c:777
|
||||
#: src/pv/display.c:1086 src/pv/state.c:45 src/pv/state.c:902
|
||||
#: src/pv/state.c:914 src/pv/state.c:950 src/pv/transfer.c:1335
|
||||
#: src/pv/transfer.c:1451 src/pv/transfer.c:1778
|
||||
msgid "memory allocation failure"
|
||||
msgstr "falha de alocação de memória"
|
||||
|
||||
#: src/main/options.c:418
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
#: src/main/options.c:438 src/main/options.c:440 src/main/options.c:901
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr "ID do processo ou par pid:fd esperado"
|
||||
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
#: src/main/options.c:449 src/main/options.c:451 src/main/options.c:908
|
||||
msgid "invalid process ID"
|
||||
msgstr "ID de processo inválido"
|
||||
|
||||
#: src/main/options.c:448 src/pv/file.c:342
|
||||
msgid "failed to stat file"
|
||||
msgstr "erro obtendo informações do arquivo"
|
||||
|
||||
#: src/main/options.c:462
|
||||
msgid "is a directory"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:491
|
||||
msgid "failed to generate sysfs filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:513
|
||||
msgid "failed to read sysfs size file"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:533
|
||||
msgid "failed to open block device"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:543
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "erro na alocação da estrutura de opções"
|
||||
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "erro na alocação da estrutura de opções argv"
|
||||
|
||||
#: src/main/options.c:723
|
||||
#: src/main/options.c:829
|
||||
msgid "numeric value not understood"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:743
|
||||
#: src/main/options.c:843
|
||||
msgid "integer argument expected"
|
||||
msgstr "argumento inteiro esperado"
|
||||
|
||||
#: src/main/options.c:755
|
||||
#: src/main/options.c:853
|
||||
msgid "numeric argument expected"
|
||||
msgstr "argumento numérico esperado"
|
||||
|
||||
#: src/main/options.c:767
|
||||
#: src/main/options.c:864
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:795
|
||||
#: src/main/options.c:890
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1056
|
||||
#: src/main/options.c:1182
|
||||
msgid "invalid side specification"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1197
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Tente `%s --help' para maiores informações."
|
||||
|
||||
#: src/main/options.c:1058
|
||||
#: src/main/options.c:1199
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Tente `%s -h' para maiores informações."
|
||||
|
||||
#: src/main/options.c:1089
|
||||
#: src/main/options.c:1231
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -379,33 +370,41 @@ msgstr ""
|
||||
"não pode usar o modo de linha ou opções de modificador de transferência ao "
|
||||
"assistir os descritores de arquivo"
|
||||
|
||||
#: src/main/options.c:1098
|
||||
#: src/main/options.c:1239
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
"não pode usar o posicionamento do cursor ao observar os descritores de "
|
||||
"arquivo"
|
||||
|
||||
#: src/main/options.c:1107
|
||||
#: src/main/options.c:1247
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr "não pode usar o controle remoto ao assistir os descritores de arquivo"
|
||||
|
||||
#: src/main/options.c:1116
|
||||
#: src/main/options.c:1255
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
#: src/main/options.c:1263
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr "não pode transferir arquivos ao assistir descritores de arquivo"
|
||||
|
||||
#: src/main/options.c:1150
|
||||
#: src/main/options.c:1287
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "não disponível em sistemas sem /proc/self/fdinfo"
|
||||
|
||||
#: src/main/options.c:1162
|
||||
#: src/main/options.c:1298
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1189
|
||||
#: src/main/options.c:1325
|
||||
msgid "monitor mode cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1337
|
||||
msgid "monitor mode cannot be used with store-and-forward"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1348
|
||||
msgid "files cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
@@ -425,64 +424,44 @@ msgstr ""
|
||||
msgid "Project web site"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:61
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "erro ao ler o nome do terminal"
|
||||
|
||||
#: src/pv/cursor.c:106
|
||||
#: src/pv/cursor.c:108 src/pv/cursor.c:135
|
||||
msgid "failed to open lock file"
|
||||
msgstr "erro ao abrir arquivo de bloqueio"
|
||||
|
||||
#: src/pv/cursor.c:139
|
||||
msgid "lock attempt failed"
|
||||
msgstr "tentativa de bloqueio falhou"
|
||||
#: src/pv/cursor.c:790 src/pv/cursor.c:792
|
||||
msgid "interrupted by a signal"
|
||||
msgstr "interrompido por um sinal"
|
||||
|
||||
#: src/pv/cursor.c:400
|
||||
msgid "failed to open terminal"
|
||||
msgstr "erro abrindo o terminal"
|
||||
|
||||
#: src/pv/display.c:285
|
||||
#: src/pv/display.c:311
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:303
|
||||
#: src/pv/display.c:329
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "erro alocando o buffer"
|
||||
#: src/pv/file.c:81
|
||||
msgid "/dev/null is not usable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:153
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr "não pode mover para o início da produção"
|
||||
#: src/pv/file.c:371
|
||||
msgid "error closing file"
|
||||
msgstr "erro ao fechar o ficheiro"
|
||||
|
||||
#: src/pv/file.c:303
|
||||
msgid "failed to close file"
|
||||
msgstr "erro fechando o arquivo"
|
||||
#: src/pv/file.c:438
|
||||
msgid "input file is also the output"
|
||||
msgstr "ficheiro de entrada também é a saída"
|
||||
|
||||
#: src/pv/file.c:335
|
||||
msgid "failed to read file"
|
||||
msgstr "erro lendo o arquivo"
|
||||
|
||||
#: src/pv/file.c:350
|
||||
msgid "failed to stat output file"
|
||||
msgstr "erro obtendo informações do arquivo de saída"
|
||||
|
||||
#: src/pv/file.c:372
|
||||
msgid "input file is output file"
|
||||
msgstr "os arquivos de entrada e saída são o mesmo"
|
||||
|
||||
#: src/pv/file.c:429
|
||||
#: src/pv/file.c:596
|
||||
msgid "(none)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:431
|
||||
#: src/pv/file.c:598
|
||||
msgid "(stdin)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/averagerate.c:34 src/pv/format/progressbar.c:92
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:181
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
@@ -492,7 +471,7 @@ msgid "/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/averagerate.c:38 src/pv/format/progressbar.c:96
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:181
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
@@ -500,100 +479,105 @@ msgstr "B/s"
|
||||
msgid "b"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:620
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:1284
|
||||
msgid "B"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/eta.c:52 src/pv/format/eta.c:56
|
||||
#: src/pv/format/eta.c:63 src/pv/format/eta.c:67
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/format/fineta.c:80
|
||||
#: src/pv/format/fineta.c:93
|
||||
msgid "FIN"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:120
|
||||
#: src/pv/loop.c:180
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:132
|
||||
#: src/pv/loop.c:192
|
||||
msgid "rate not measured"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/loop.c:818 src/pv/loop.c:836 src/pv/watchpid.c:101
|
||||
#: src/pv/watchpid.c:110 src/pv/watchpid.c:121 src/pv/watchpid.c:129
|
||||
#: src/pv/watchpid.c:166 src/pv/watchpid.c:185 src/pv/watchpid.c:193
|
||||
#: src/pv/watchpid.c:203 src/pv/watchpid.c:307 src/pv/watchpid.c:315
|
||||
#: src/pv/watchpid.c:447 src/pv/watchpid.c:470
|
||||
#: src/pv/loop.c:1098 src/pv/loop.c:1114 src/pv/loop.c:1132 src/pv/remote.c:93
|
||||
#: src/pv/remote.c:188 src/pv/remote.c:536 src/pv/remote.c:582
|
||||
#: src/pv/watchpid.c:123 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:158 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:206 src/pv/watchpid.c:218 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:286 src/pv/watchpid.c:401
|
||||
#: src/pv/watchpid.c:409 src/pv/watchpid.c:556 src/pv/watchpid.c:565
|
||||
#: src/pv/watchpid.c:586
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:836 src/pv/watchpid.c:110 src/pv/watchpid.c:122
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:185 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:205
|
||||
#: src/pv/loop.c:1132 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:160 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:288
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
#: src/pv/remote.c:242 src/pv/remote.c:636
|
||||
msgid "message not received"
|
||||
msgstr "mensagem não recebida"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
#: src/pv/remote.c:659 src/pv/remote.c:677
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO não suportado neste sistema"
|
||||
|
||||
#: src/pv/state.c:42
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr "erro de leitura"
|
||||
|
||||
#: src/pv/transfer.c:506
|
||||
#: src/pv/transfer.c:1173
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "aviso: erros de leitura detectados"
|
||||
|
||||
#: src/pv/transfer.c:522
|
||||
msgid "file is not seekable"
|
||||
msgstr "não pode mover dentro do arquivo"
|
||||
|
||||
#: src/pv/transfer.c:599
|
||||
msgid "failed to seek past error"
|
||||
msgstr "não pode ir além do erro"
|
||||
|
||||
#: src/pv/transfer.c:619
|
||||
#: src/pv/transfer.c:1283
|
||||
msgid "skipped past read error"
|
||||
msgstr "ignorado erro de leitura"
|
||||
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
#: src/pv/transfer.c:1642
|
||||
msgid "write error"
|
||||
msgstr "erro de escrita"
|
||||
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "erro de gravação"
|
||||
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "erro na chamada da função select"
|
||||
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
#: src/pv/watchpid.c:160 src/pv/watchpid.c:288
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "não é um arquivo regular ou dispositivo de bloqueio"
|
||||
|
||||
#~ msgid "state allocation failed"
|
||||
#~ msgstr "alocação de memória de status falhou"
|
||||
|
||||
#~ msgid "failed to stat file"
|
||||
#~ msgstr "erro obtendo informações do arquivo"
|
||||
|
||||
#~ msgid "option structure allocation failed"
|
||||
#~ msgstr "erro na alocação da estrutura de opções"
|
||||
|
||||
#~ msgid "option structure argv allocation failed"
|
||||
#~ msgstr "erro na alocação da estrutura de opções argv"
|
||||
|
||||
#~ msgid "failed to get terminal name"
|
||||
#~ msgstr "erro ao ler o nome do terminal"
|
||||
|
||||
#~ msgid "lock attempt failed"
|
||||
#~ msgstr "tentativa de bloqueio falhou"
|
||||
|
||||
#~ msgid "failed to open terminal"
|
||||
#~ msgstr "erro abrindo o terminal"
|
||||
|
||||
#~ msgid "failed to seek to start of output"
|
||||
#~ msgstr "não pode mover para o início da produção"
|
||||
|
||||
#~ msgid "failed to read file"
|
||||
#~ msgstr "erro lendo o arquivo"
|
||||
|
||||
#~ msgid "failed to stat output file"
|
||||
#~ msgstr "erro obtendo informações do arquivo de saída"
|
||||
|
||||
#~ msgid "read failed"
|
||||
#~ msgstr "erro de leitura"
|
||||
|
||||
#~ msgid "file is not seekable"
|
||||
#~ msgstr "não pode mover dentro do arquivo"
|
||||
|
||||
#~ msgid "failed to seek past error"
|
||||
#~ msgstr "não pode ir além do erro"
|
||||
|
||||
#~ msgid "select call failed"
|
||||
#~ msgstr "erro na chamada da função select"
|
||||
|
||||
+164
-219
@@ -1,397 +1,399 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pv 1.11.0\n"
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-12-15 20:10+0000\n"
|
||||
"Language: es\n"
|
||||
"POT-Creation-Date: 2026-08-01 14:53+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Language-Team: Romanian <https://translate.codeberg.org/projects/pv/pv/ro/>\n"
|
||||
"Language: ro\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/main/help.c:236
|
||||
#: src/main/help.c:300
|
||||
msgid "show progress bar"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:239
|
||||
#: src/main/help.c:303
|
||||
msgid "show elapsed time"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:242
|
||||
#: src/main/help.c:306
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:245
|
||||
#: src/main/help.c:309
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:248
|
||||
#: src/main/help.c:312
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:251
|
||||
#: src/main/help.c:315
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:254
|
||||
#: src/main/help.c:318
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:257
|
||||
#: src/main/help.c:321
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:259
|
||||
#: src/main/help.c:323
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:260
|
||||
#: src/main/help.c:324
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:262
|
||||
#: src/main/help.c:326
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:263
|
||||
#: src/main/help.c:327
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:266
|
||||
#: src/main/help.c:330
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:269
|
||||
#: src/main/help.c:333
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:273
|
||||
#: src/main/help.c:337
|
||||
msgid "show number of bits transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:276
|
||||
#: src/main/help.c:340
|
||||
msgid "treat suffixes as multiples of 1000 rather than 1024"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:279
|
||||
#: src/main/help.c:343
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:281 src/main/help.c:296 src/main/help.c:299
|
||||
#: src/main/help.c:345 src/main/help.c:360 src/main/help.c:363
|
||||
msgid "SEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:282
|
||||
#: src/main/help.c:346
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:284
|
||||
#: src/main/help.c:348
|
||||
msgid "SIZE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:285
|
||||
#: src/main/help.c:349
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:288
|
||||
#: src/main/help.c:352
|
||||
msgid "if size unknown, show rate vs max rate"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:291
|
||||
#: src/main/help.c:355
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:294
|
||||
#: src/main/help.c:358
|
||||
msgid "lines are null-terminated"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:297
|
||||
#: src/main/help.c:361
|
||||
msgid "update every SEC seconds"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:300
|
||||
#: src/main/help.c:364
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:302
|
||||
#: src/main/help.c:366
|
||||
msgid "WIDTH"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:303
|
||||
#: src/main/help.c:367
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:305
|
||||
#: src/main/help.c:369
|
||||
msgid "HEIGHT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:306
|
||||
#: src/main/help.c:370
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:308
|
||||
#: src/main/help.c:372
|
||||
msgid "NAME"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:309
|
||||
#: src/main/help.c:373
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:311
|
||||
#: src/main/help.c:375
|
||||
msgid "STYLE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "set default bar style to NAME"
|
||||
#: src/main/help.c:376
|
||||
msgid "set default bar style to STYLE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:314
|
||||
#: src/main/help.c:378
|
||||
msgid "SPEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:315
|
||||
#: src/main/help.c:379
|
||||
msgid "also send progress to SPEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:318
|
||||
#: src/main/help.c:382
|
||||
msgid "set terminal progress state with OSC 9;4 (ConEmu)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:385
|
||||
msgid "output transfer statistics at the end"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:321
|
||||
#: src/main/help.c:388
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:324
|
||||
#: src/main/help.c:391
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
#: src/main/help.c:394 src/main/help.c:430 src/main/help.c:449
|
||||
#: src/main/help.c:459
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:328
|
||||
#: src/main/help.c:395
|
||||
msgid "write output to FILE instead of stdout"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:330
|
||||
#: src/main/help.c:397
|
||||
msgid "RATE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:331
|
||||
#: src/main/help.c:398
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:333 src/main/help.c:342
|
||||
#: src/main/help.c:400 src/main/help.c:406 src/main/help.c:412
|
||||
msgid "BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:334
|
||||
#: src/main/help.c:401
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:337
|
||||
#: src/main/help.c:404
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:340
|
||||
#: src/main/help.c:407
|
||||
msgid "set the pipe buffer size to BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:410
|
||||
msgid "skip read errors in input"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:343
|
||||
#: src/main/help.c:413
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:346
|
||||
#: src/main/help.c:416
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:349
|
||||
#: src/main/help.c:419
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:352
|
||||
#: src/main/help.c:422
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:355
|
||||
#: src/main/help.c:425
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
#: src/main/help.c:428
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:431
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:434
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:435
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
#: src/main/help.c:438 src/main/help.c:441
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:369
|
||||
#: src/main/help.c:439
|
||||
msgid "update settings of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:372
|
||||
#: src/main/help.c:442
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
#: src/main/help.c:446
|
||||
msgid "run a command and monitor its standard input, output, or both"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:450
|
||||
msgid "save process ID in FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:453
|
||||
msgid "show this help and exit"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:383
|
||||
#: src/main/help.c:456
|
||||
msgid "show version information and exit"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:387
|
||||
#: src/main/help.c:460
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:413
|
||||
#: src/main/help.c:486
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:424
|
||||
#: src/main/help.c:497
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:562
|
||||
#: src/main/help.c:639
|
||||
msgid "Supported format sequences:"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:576
|
||||
#: src/main/help.c:653
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/main.c:228
|
||||
#: src/main/main.c:225
|
||||
msgid "(input)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
#: src/main/main.c:381 src/main/options.c:1359
|
||||
msgid "a command to run must be specified"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:370
|
||||
#: src/main/main.c:704 src/main/options.c:757 src/main/options.c:777
|
||||
#: src/pv/display.c:1086 src/pv/state.c:45 src/pv/state.c:902
|
||||
#: src/pv/state.c:914 src/pv/state.c:950 src/pv/transfer.c:1335
|
||||
#: src/pv/transfer.c:1451 src/pv/transfer.c:1778
|
||||
msgid "memory allocation failure"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:418
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
#: src/main/options.c:438 src/main/options.c:440 src/main/options.c:901
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
#: src/main/options.c:449 src/main/options.c:451 src/main/options.c:908
|
||||
msgid "invalid process ID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:448 src/pv/file.c:342
|
||||
msgid "failed to stat file"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:462
|
||||
msgid "is a directory"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:491
|
||||
msgid "failed to generate sysfs filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:513
|
||||
msgid "failed to read sysfs size file"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:533
|
||||
msgid "failed to open block device"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:543
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:723
|
||||
#: src/main/options.c:829
|
||||
msgid "numeric value not understood"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:743
|
||||
#: src/main/options.c:843
|
||||
msgid "integer argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:755
|
||||
#: src/main/options.c:853
|
||||
msgid "numeric argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:767
|
||||
#: src/main/options.c:864
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:795
|
||||
#: src/main/options.c:890
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1056
|
||||
#: src/main/options.c:1182
|
||||
msgid "invalid side specification"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1197
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1058
|
||||
#: src/main/options.c:1199
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1089
|
||||
#: src/main/options.c:1231
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1098
|
||||
#: src/main/options.c:1239
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1107
|
||||
#: src/main/options.c:1247
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1116
|
||||
#: src/main/options.c:1255
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
#: src/main/options.c:1263
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1150
|
||||
#: src/main/options.c:1287
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1162
|
||||
#: src/main/options.c:1298
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1189
|
||||
#: src/main/options.c:1325
|
||||
msgid "monitor mode cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1337
|
||||
msgid "monitor mode cannot be used with store-and-forward"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1348
|
||||
msgid "files cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
@@ -411,64 +413,44 @@ msgstr ""
|
||||
msgid "Project web site"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:61
|
||||
msgid "failed to get terminal name"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:106
|
||||
#: src/pv/cursor.c:108 src/pv/cursor.c:135
|
||||
msgid "failed to open lock file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:139
|
||||
msgid "lock attempt failed"
|
||||
#: src/pv/cursor.c:790 src/pv/cursor.c:792
|
||||
msgid "interrupted by a signal"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/cursor.c:400
|
||||
msgid "failed to open terminal"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:285
|
||||
#: src/pv/display.c:311
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:303
|
||||
#: src/pv/display.c:329
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
#: src/pv/file.c:81
|
||||
msgid "/dev/null is not usable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:153
|
||||
msgid "failed to seek to start of output"
|
||||
#: src/pv/file.c:371
|
||||
msgid "error closing file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:303
|
||||
msgid "failed to close file"
|
||||
#: src/pv/file.c:438
|
||||
msgid "input file is also the output"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:335
|
||||
msgid "failed to read file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:350
|
||||
msgid "failed to stat output file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:372
|
||||
msgid "input file is output file"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:429
|
||||
#: src/pv/file.c:596
|
||||
msgid "(none)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:431
|
||||
#: src/pv/file.c:598
|
||||
msgid "(stdin)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/averagerate.c:34 src/pv/format/progressbar.c:92
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:181
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
@@ -478,7 +460,7 @@ msgid "/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/averagerate.c:38 src/pv/format/progressbar.c:96
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:181
|
||||
msgid "B/s"
|
||||
msgstr ""
|
||||
|
||||
@@ -486,100 +468,63 @@ msgstr ""
|
||||
msgid "b"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:620
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:1284
|
||||
msgid "B"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/eta.c:52 src/pv/format/eta.c:56
|
||||
#: src/pv/format/eta.c:63 src/pv/format/eta.c:67
|
||||
msgid "ETA"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/format/fineta.c:80
|
||||
#: src/pv/format/fineta.c:93
|
||||
msgid "FIN"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:120
|
||||
#: src/pv/loop.c:180
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:132
|
||||
#: src/pv/loop.c:192
|
||||
msgid "rate not measured"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/loop.c:818 src/pv/loop.c:836 src/pv/watchpid.c:101
|
||||
#: src/pv/watchpid.c:110 src/pv/watchpid.c:121 src/pv/watchpid.c:129
|
||||
#: src/pv/watchpid.c:166 src/pv/watchpid.c:185 src/pv/watchpid.c:193
|
||||
#: src/pv/watchpid.c:203 src/pv/watchpid.c:307 src/pv/watchpid.c:315
|
||||
#: src/pv/watchpid.c:447 src/pv/watchpid.c:470
|
||||
#: src/pv/loop.c:1098 src/pv/loop.c:1114 src/pv/loop.c:1132 src/pv/remote.c:93
|
||||
#: src/pv/remote.c:188 src/pv/remote.c:536 src/pv/remote.c:582
|
||||
#: src/pv/watchpid.c:123 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:158 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:206 src/pv/watchpid.c:218 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:286 src/pv/watchpid.c:401
|
||||
#: src/pv/watchpid.c:409 src/pv/watchpid.c:556 src/pv/watchpid.c:565
|
||||
#: src/pv/watchpid.c:586
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:836 src/pv/watchpid.c:110 src/pv/watchpid.c:122
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:185 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:205
|
||||
#: src/pv/loop.c:1132 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:160 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:288
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
#: src/pv/remote.c:242 src/pv/remote.c:636
|
||||
msgid "message not received"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
#: src/pv/remote.c:659 src/pv/remote.c:677
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:42
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:506
|
||||
#: src/pv/transfer.c:1173
|
||||
msgid "warning: read errors detected"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:522
|
||||
msgid "file is not seekable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:599
|
||||
msgid "failed to seek past error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:619
|
||||
#: src/pv/transfer.c:1283
|
||||
msgid "skipped past read error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
#: src/pv/transfer.c:1642
|
||||
msgid "write error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
#: src/pv/watchpid.c:160 src/pv/watchpid.c:288
|
||||
msgid "not a regular file or block device"
|
||||
msgstr ""
|
||||
@@ -1,9 +1,9 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-12-15 20:10+0000\n"
|
||||
"PO-Revision-Date: 2025-01-15 19:08+0000\n"
|
||||
"Last-Translator: 0ko <0ko@users.noreply.translate.codeberg.org>\n"
|
||||
"POT-Creation-Date: 2026-08-01 14:53+0100\n"
|
||||
"PO-Revision-Date: 2026-08-17 12:27+0000\n"
|
||||
"Last-Translator: some_user <some_user@noreply.codeberg.org>\n"
|
||||
"Language-Team: Russian <https://translate.codeberg.org/projects/pv/pv/ru/>\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -11,394 +11,394 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.9.2\n"
|
||||
"X-Generator: Weblate 2026.8.1\n"
|
||||
|
||||
#: src/main/help.c:236
|
||||
#: src/main/help.c:300
|
||||
msgid "show progress bar"
|
||||
msgstr "показать полосу прогресса"
|
||||
|
||||
#: src/main/help.c:239
|
||||
#: src/main/help.c:303
|
||||
msgid "show elapsed time"
|
||||
msgstr "показать прошедшее время"
|
||||
|
||||
#: src/main/help.c:242
|
||||
#: src/main/help.c:306
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "показать примерное время завершения"
|
||||
|
||||
#: src/main/help.c:245
|
||||
#: src/main/help.c:309
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "показать примерное абсолютное время завершения"
|
||||
|
||||
#: src/main/help.c:248
|
||||
#: src/main/help.c:312
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "показать скорость передачи данных"
|
||||
|
||||
#: src/main/help.c:251
|
||||
#: src/main/help.c:315
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "показать среднюю скорость передачи данных"
|
||||
|
||||
#: src/main/help.c:254
|
||||
#: src/main/help.c:318
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "показать объём переданных данных в байтах"
|
||||
|
||||
#: src/main/help.c:257
|
||||
#: src/main/help.c:321
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "показать использование буфера передачи в процентах"
|
||||
|
||||
#: src/main/help.c:259
|
||||
#: src/main/help.c:323
|
||||
msgid "NUM"
|
||||
msgstr "КОЛ"
|
||||
|
||||
#: src/main/help.c:260
|
||||
#: src/main/help.c:324
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "показать КОЛ байт, переданных в последний раз"
|
||||
|
||||
#: src/main/help.c:262
|
||||
#: src/main/help.c:326
|
||||
msgid "FORMAT"
|
||||
msgstr "ФОРМАТ"
|
||||
|
||||
#: src/main/help.c:263
|
||||
#: src/main/help.c:327
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "указать формат вывода как ФОРМАТ"
|
||||
|
||||
#: src/main/help.c:266
|
||||
#: src/main/help.c:330
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "показать проценты вместо визуальной информации"
|
||||
|
||||
#: src/main/help.c:269
|
||||
#: src/main/help.c:333
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "не отображать никакую информацию о передаче"
|
||||
|
||||
#: src/main/help.c:273
|
||||
#: src/main/help.c:337
|
||||
msgid "show number of bits transferred"
|
||||
msgstr "показать объём переданных данных в битах"
|
||||
|
||||
#: src/main/help.c:276
|
||||
#: src/main/help.c:340
|
||||
msgid "treat suffixes as multiples of 1000 rather than 1024"
|
||||
msgstr "считать суффиксы как умножители на 1000, а не на 1024"
|
||||
|
||||
#: src/main/help.c:279
|
||||
#: src/main/help.c:343
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "ничего не показывать, пока не будет передан первый байт"
|
||||
|
||||
#: src/main/help.c:281 src/main/help.c:296 src/main/help.c:299
|
||||
#: src/main/help.c:345 src/main/help.c:360 src/main/help.c:363
|
||||
msgid "SEC"
|
||||
msgstr "СЕК"
|
||||
|
||||
#: src/main/help.c:282
|
||||
#: src/main/help.c:346
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "ничего не показывать, пока не пройдёт СЕК секунд"
|
||||
|
||||
#: src/main/help.c:284
|
||||
#: src/main/help.c:348
|
||||
msgid "SIZE"
|
||||
msgstr "РАЗМ"
|
||||
|
||||
#: src/main/help.c:285
|
||||
#: src/main/help.c:349
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "указать ожидаемый объём данных как РАЗМ байт"
|
||||
|
||||
#: src/main/help.c:288
|
||||
#: src/main/help.c:352
|
||||
msgid "if size unknown, show rate vs max rate"
|
||||
msgstr "если объём неизвестен, показать скорость и макс. скорость"
|
||||
|
||||
#: src/main/help.c:291
|
||||
#: src/main/help.c:355
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "считать линии вместо байт"
|
||||
|
||||
#: src/main/help.c:294
|
||||
#: src/main/help.c:358
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "строки прерываются нулями"
|
||||
|
||||
#: src/main/help.c:297
|
||||
#: src/main/help.c:361
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "обновлять каждые СЕК секунд"
|
||||
|
||||
#: src/main/help.c:300
|
||||
#: src/main/help.c:364
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr "вычислять среднюю скорость за последние СЕК секунд (по умолчанию 30)"
|
||||
|
||||
#: src/main/help.c:302
|
||||
#: src/main/help.c:366
|
||||
msgid "WIDTH"
|
||||
msgstr "ШИРИНА"
|
||||
|
||||
#: src/main/help.c:303
|
||||
#: src/main/help.c:367
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "считать, что в одной строке помещается ШИРИНА символов"
|
||||
|
||||
#: src/main/help.c:305
|
||||
#: src/main/help.c:369
|
||||
msgid "HEIGHT"
|
||||
msgstr "ВЫСОТА"
|
||||
|
||||
#: src/main/help.c:306
|
||||
#: src/main/help.c:370
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "считать, что на экране помещается ВЫСОТА строк"
|
||||
|
||||
#: src/main/help.c:308
|
||||
#: src/main/help.c:372
|
||||
msgid "NAME"
|
||||
msgstr "ИМЯ"
|
||||
|
||||
#: src/main/help.c:309
|
||||
#: src/main/help.c:373
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "писать ИМЯ до визуальной информации"
|
||||
|
||||
#: src/main/help.c:311
|
||||
#: src/main/help.c:375
|
||||
msgid "STYLE"
|
||||
msgstr "СТИЛЬ"
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "set default bar style to NAME"
|
||||
msgstr "задать стиль полоски по умолчанию как НАЗВАНИЕ"
|
||||
#: src/main/help.c:376
|
||||
msgid "set default bar style to STYLE"
|
||||
msgstr "задать стиль полоски по умолчанию как СТИЛЬ"
|
||||
|
||||
#: src/main/help.c:314
|
||||
#: src/main/help.c:378
|
||||
msgid "SPEC"
|
||||
msgstr ""
|
||||
msgstr "НАЗНАЧ"
|
||||
|
||||
#: src/main/help.c:315
|
||||
#: src/main/help.c:379
|
||||
msgid "also send progress to SPEC"
|
||||
msgstr "дополнительно выводить прогресс в НАЗНАЧ"
|
||||
|
||||
#: src/main/help.c:382
|
||||
msgid "set terminal progress state with OSC 9;4 (ConEmu)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:318
|
||||
#: src/main/help.c:385
|
||||
msgid "output transfer statistics at the end"
|
||||
msgstr "после завершения показать статистику"
|
||||
|
||||
#: src/main/help.c:321
|
||||
#: src/main/help.c:388
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "вевести, даже если стд. ошибка не является терминалом"
|
||||
|
||||
#: src/main/help.c:324
|
||||
#: src/main/help.c:391
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr ""
|
||||
"использовать символьные последовательности для позиционирования курсора"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
#: src/main/help.c:394 src/main/help.c:430 src/main/help.c:449
|
||||
#: src/main/help.c:459
|
||||
msgid "FILE"
|
||||
msgstr "ФАЙЛ"
|
||||
|
||||
#: src/main/help.c:328
|
||||
#: src/main/help.c:395
|
||||
msgid "write output to FILE instead of stdout"
|
||||
msgstr "направить вывод в ФАЙЛ вместо стд. вывода"
|
||||
|
||||
#: src/main/help.c:330
|
||||
#: src/main/help.c:397
|
||||
msgid "RATE"
|
||||
msgstr "СКОР"
|
||||
|
||||
#: src/main/help.c:331
|
||||
#: src/main/help.c:398
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "ограничить скорость передачи до СКОР байт/сек"
|
||||
|
||||
#: src/main/help.c:333 src/main/help.c:342
|
||||
#: src/main/help.c:400 src/main/help.c:406 src/main/help.c:412
|
||||
msgid "BYTES"
|
||||
msgstr "БАЙТ"
|
||||
|
||||
#: src/main/help.c:334
|
||||
#: src/main/help.c:401
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "использовать буфер размера БАЙТ"
|
||||
|
||||
#: src/main/help.c:337
|
||||
#: src/main/help.c:404
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "использовать чтение/запись вместо splice()"
|
||||
|
||||
#: src/main/help.c:340
|
||||
#: src/main/help.c:407
|
||||
msgid "set the pipe buffer size to BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:410
|
||||
msgid "skip read errors in input"
|
||||
msgstr "пропустить ошибки чтения во вводе"
|
||||
|
||||
#: src/main/help.c:343
|
||||
#: src/main/help.c:413
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr "пропускать ошибки в <БАЙТ> блоках за раз"
|
||||
|
||||
#: src/main/help.c:346
|
||||
#: src/main/help.c:416
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "остановить после передачи --size байт"
|
||||
|
||||
#: src/main/help.c:349
|
||||
#: src/main/help.c:419
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr "сбрасывать кеш на диск каждый раз"
|
||||
|
||||
#: src/main/help.c:352
|
||||
#: src/main/help.c:422
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr "использовать прямой ввод/вывод для обхода кеша"
|
||||
|
||||
#: src/main/help.c:355
|
||||
#: src/main/help.c:425
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
#: src/main/help.c:428
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr "отбрасывать ввод вместо записи в вывод"
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:431
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr "записывать весь ввод в ФАЙЛ прежде, чем отправлять на вывод"
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:434
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:435
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "следить за FD файла, открытого процессом ИДпр"
|
||||
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
#: src/main/help.c:438 src/main/help.c:441
|
||||
msgid "PID"
|
||||
msgstr "ИДпр"
|
||||
|
||||
#: src/main/help.c:369
|
||||
#: src/main/help.c:439
|
||||
msgid "update settings of process PID"
|
||||
msgstr "обновить настройки ИДпр процесса"
|
||||
|
||||
#: src/main/help.c:372
|
||||
#: src/main/help.c:442
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
msgstr "показать прогресс процесса ИДпр"
|
||||
|
||||
#: src/main/help.c:377
|
||||
#: src/main/help.c:446
|
||||
msgid "run a command and monitor its standard input, output, or both"
|
||||
msgstr ""
|
||||
"запустить команду и отслеживать её стандартный ввод, вывод или и то, и другое"
|
||||
|
||||
#: src/main/help.c:450
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "сохранить ИД процесса в ФАЙЛ"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:453
|
||||
msgid "show this help and exit"
|
||||
msgstr "показать справку и завершить работу"
|
||||
|
||||
#: src/main/help.c:383
|
||||
#: src/main/help.c:456
|
||||
msgid "show version information and exit"
|
||||
msgstr "показать версию программы и завершить работу"
|
||||
|
||||
#: src/main/help.c:387
|
||||
#: src/main/help.c:460
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "вести запись отладочного журнала в ФАЙЛ"
|
||||
|
||||
#: src/main/help.c:413
|
||||
#: src/main/help.c:486
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Использование: %s [ОПЦИИ] [ФАЙЛ]..."
|
||||
|
||||
#: src/main/help.c:424
|
||||
#: src/main/help.c:497
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:562
|
||||
#: src/main/help.c:639
|
||||
msgid "Supported format sequences:"
|
||||
msgstr "Поддерживаемые последовательности:"
|
||||
|
||||
#: src/main/help.c:576
|
||||
#: src/main/help.c:653
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Сообщайте о проблемах на: %s"
|
||||
|
||||
#: src/main/main.c:228
|
||||
#: src/main/main.c:225
|
||||
msgid "(input)"
|
||||
msgstr "(ввод)"
|
||||
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr ""
|
||||
#: src/main/main.c:381 src/main/options.c:1359
|
||||
msgid "a command to run must be specified"
|
||||
msgstr "необходимо указать команду для запуска"
|
||||
|
||||
#: src/main/options.c:370
|
||||
#: src/main/main.c:704 src/main/options.c:757 src/main/options.c:777
|
||||
#: src/pv/display.c:1086 src/pv/state.c:45 src/pv/state.c:902
|
||||
#: src/pv/state.c:914 src/pv/state.c:950 src/pv/transfer.c:1335
|
||||
#: src/pv/transfer.c:1451 src/pv/transfer.c:1778
|
||||
msgid "memory allocation failure"
|
||||
msgstr "ошибка выделения памяти"
|
||||
|
||||
#: src/main/options.c:418
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
msgstr "файлы списка не должны содержать строк, начинающихся с символа @"
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
#: src/main/options.c:438 src/main/options.c:440 src/main/options.c:901
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr "ожидался ИД процесса или пара ИДпр:ДФ"
|
||||
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
#: src/main/options.c:449 src/main/options.c:451 src/main/options.c:908
|
||||
msgid "invalid process ID"
|
||||
msgstr "неправильный ИД процесса"
|
||||
|
||||
#: src/main/options.c:448 src/pv/file.c:342
|
||||
msgid "failed to stat file"
|
||||
msgstr "не удалось получить информацию о файле"
|
||||
|
||||
#: src/main/options.c:462
|
||||
msgid "is a directory"
|
||||
msgstr "является каталогом"
|
||||
|
||||
#: src/main/options.c:491
|
||||
msgid "failed to generate sysfs filename"
|
||||
msgstr "не удалось создать имя файла sysfs"
|
||||
|
||||
#: src/main/options.c:513
|
||||
msgid "failed to read sysfs size file"
|
||||
msgstr "не удалось узнать размер файла sysfs"
|
||||
|
||||
#: src/main/options.c:533
|
||||
msgid "failed to open block device"
|
||||
msgstr "не удалось открыть блочное устройство"
|
||||
|
||||
#: src/main/options.c:543
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr "не удалось определить размер блочного устройства"
|
||||
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "не удалось выделить память для структуры опций"
|
||||
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "не удалось выделить память для структуры опций argv"
|
||||
|
||||
#: src/main/options.c:723
|
||||
#: src/main/options.c:829
|
||||
msgid "numeric value not understood"
|
||||
msgstr "число не распознано"
|
||||
|
||||
#: src/main/options.c:743
|
||||
#: src/main/options.c:843
|
||||
msgid "integer argument expected"
|
||||
msgstr "ожидалось целое число"
|
||||
|
||||
#: src/main/options.c:755
|
||||
#: src/main/options.c:853
|
||||
msgid "numeric argument expected"
|
||||
msgstr "ожидалось число"
|
||||
|
||||
#: src/main/options.c:767
|
||||
#: src/main/options.c:864
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:795
|
||||
#: src/main/options.c:890
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1056
|
||||
#: src/main/options.c:1182
|
||||
msgid "invalid side specification"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1197
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Выполните `%s --help' для получения подробностей."
|
||||
|
||||
#: src/main/options.c:1058
|
||||
#: src/main/options.c:1199
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Выполните `%s -h' для получения подробностей."
|
||||
|
||||
#: src/main/options.c:1089
|
||||
#: src/main/options.c:1231
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1098
|
||||
#: src/main/options.c:1239
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1107
|
||||
#: src/main/options.c:1247
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr "удалённое управление невозможно при отслеживании дескрипторов файлов"
|
||||
|
||||
#: src/main/options.c:1116
|
||||
#: src/main/options.c:1255
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
#: src/main/options.c:1263
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr "передача файлов невозможна при отслеживании дескрипторов файлов"
|
||||
|
||||
#: src/main/options.c:1150
|
||||
#: src/main/options.c:1287
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "невозможно на системах без /proc/self/fdinfo"
|
||||
|
||||
#: src/main/options.c:1162
|
||||
#: src/main/options.c:1298
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1189
|
||||
#: src/main/options.c:1325
|
||||
msgid "monitor mode cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1337
|
||||
msgid "monitor mode cannot be used with store-and-forward"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1348
|
||||
msgid "files cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
@@ -420,64 +420,44 @@ msgstr ""
|
||||
msgid "Project web site"
|
||||
msgstr "Веб-сайт проекта"
|
||||
|
||||
#: src/pv/cursor.c:61
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "не удалось получить имя терминала"
|
||||
|
||||
#: src/pv/cursor.c:106
|
||||
#: src/pv/cursor.c:108 src/pv/cursor.c:135
|
||||
msgid "failed to open lock file"
|
||||
msgstr "не удалось открыть блокирующий файл"
|
||||
|
||||
#: src/pv/cursor.c:139
|
||||
msgid "lock attempt failed"
|
||||
msgstr "попытка блокировки не удалась"
|
||||
#: src/pv/cursor.c:790 src/pv/cursor.c:792
|
||||
msgid "interrupted by a signal"
|
||||
msgstr "прервано по сигналу"
|
||||
|
||||
#: src/pv/cursor.c:400
|
||||
msgid "failed to open terminal"
|
||||
msgstr "не удалось открыть терминал"
|
||||
|
||||
#: src/pv/display.c:285
|
||||
#: src/pv/display.c:311
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:303
|
||||
#: src/pv/display.c:329
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "не удалось выделить память для буфера"
|
||||
|
||||
#: src/pv/file.c:153
|
||||
msgid "failed to seek to start of output"
|
||||
#: src/pv/file.c:81
|
||||
msgid "/dev/null is not usable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:303
|
||||
msgid "failed to close file"
|
||||
msgstr "не удалось закрыть файл"
|
||||
#: src/pv/file.c:371
|
||||
msgid "error closing file"
|
||||
msgstr "ошибка закрытия файла"
|
||||
|
||||
#: src/pv/file.c:335
|
||||
msgid "failed to read file"
|
||||
msgstr "не удалось прочесть файл"
|
||||
#: src/pv/file.c:438
|
||||
msgid "input file is also the output"
|
||||
msgstr "файл ввода также используется и для вывода"
|
||||
|
||||
#: src/pv/file.c:350
|
||||
msgid "failed to stat output file"
|
||||
msgstr "не удалось получить информацию о выходном файле"
|
||||
|
||||
#: src/pv/file.c:372
|
||||
msgid "input file is output file"
|
||||
msgstr "пути исходного и выходного файлов одинаковы"
|
||||
|
||||
#: src/pv/file.c:429
|
||||
#: src/pv/file.c:596
|
||||
msgid "(none)"
|
||||
msgstr "(нет)"
|
||||
|
||||
#: src/pv/file.c:431
|
||||
#: src/pv/file.c:598
|
||||
msgid "(stdin)"
|
||||
msgstr "(стд. ввод)"
|
||||
|
||||
#: src/pv/format/averagerate.c:34 src/pv/format/progressbar.c:92
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:181
|
||||
msgid "b/s"
|
||||
msgstr "бит/с"
|
||||
|
||||
@@ -487,7 +467,7 @@ msgid "/s"
|
||||
msgstr "/с"
|
||||
|
||||
#: src/pv/format/averagerate.c:38 src/pv/format/progressbar.c:96
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:181
|
||||
msgid "B/s"
|
||||
msgstr "байт/с"
|
||||
|
||||
@@ -495,103 +475,126 @@ msgstr "байт/с"
|
||||
msgid "b"
|
||||
msgstr "бит"
|
||||
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:620
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:1284
|
||||
msgid "B"
|
||||
msgstr "байт"
|
||||
|
||||
#: src/pv/format/eta.c:52 src/pv/format/eta.c:56
|
||||
#: src/pv/format/eta.c:63 src/pv/format/eta.c:67
|
||||
msgid "ETA"
|
||||
msgstr "ОЖИД"
|
||||
|
||||
#: src/pv/format/fineta.c:80
|
||||
#: src/pv/format/fineta.c:93
|
||||
msgid "FIN"
|
||||
msgstr "ЗАВЕРШ"
|
||||
|
||||
#: src/pv/loop.c:120
|
||||
#: src/pv/loop.c:180
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr "скор. мин/сред/макс/дев"
|
||||
|
||||
#: src/pv/loop.c:132
|
||||
#: src/pv/loop.c:192
|
||||
msgid "rate not measured"
|
||||
msgstr "скорость не изменяется"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/loop.c:818 src/pv/loop.c:836 src/pv/watchpid.c:101
|
||||
#: src/pv/watchpid.c:110 src/pv/watchpid.c:121 src/pv/watchpid.c:129
|
||||
#: src/pv/watchpid.c:166 src/pv/watchpid.c:185 src/pv/watchpid.c:193
|
||||
#: src/pv/watchpid.c:203 src/pv/watchpid.c:307 src/pv/watchpid.c:315
|
||||
#: src/pv/watchpid.c:447 src/pv/watchpid.c:470
|
||||
#: src/pv/loop.c:1098 src/pv/loop.c:1114 src/pv/loop.c:1132 src/pv/remote.c:93
|
||||
#: src/pv/remote.c:188 src/pv/remote.c:536 src/pv/remote.c:582
|
||||
#: src/pv/watchpid.c:123 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:158 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:206 src/pv/watchpid.c:218 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:286 src/pv/watchpid.c:401
|
||||
#: src/pv/watchpid.c:409 src/pv/watchpid.c:556 src/pv/watchpid.c:565
|
||||
#: src/pv/watchpid.c:586
|
||||
msgid "pid"
|
||||
msgstr "ИДпр"
|
||||
|
||||
#: src/pv/loop.c:836 src/pv/watchpid.c:110 src/pv/watchpid.c:122
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:185 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:205
|
||||
#: src/pv/loop.c:1132 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:160 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:288
|
||||
msgid "fd"
|
||||
msgstr "дф"
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
#: src/pv/remote.c:242 src/pv/remote.c:636
|
||||
msgid "message not received"
|
||||
msgstr "сообщение не получено"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
#: src/pv/remote.c:659 src/pv/remote.c:677
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "Этой системой не поддерживается SA_SIGINFO"
|
||||
|
||||
#: src/pv/state.c:42
|
||||
msgid "history structure allocation failed"
|
||||
msgstr "не удалось выделить память для структуры истории"
|
||||
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr "не удалось выделить память для списка файлов"
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr "чтение не удалось"
|
||||
|
||||
#: src/pv/transfer.c:506
|
||||
#: src/pv/transfer.c:1173
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "внимание: замечены ошибки чтения"
|
||||
|
||||
#: src/pv/transfer.c:522
|
||||
msgid "file is not seekable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:599
|
||||
msgid "failed to seek past error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:619
|
||||
#: src/pv/transfer.c:1283
|
||||
msgid "skipped past read error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr "не выделена память для буфера передачи"
|
||||
#: src/pv/transfer.c:1642
|
||||
msgid "write error"
|
||||
msgstr "ошибка записи"
|
||||
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr "не удалось задать измеритель временного промежутка"
|
||||
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr "не удалось очистить измеритель временного промежутка"
|
||||
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "запись не удалась"
|
||||
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "запрос выборки не удался"
|
||||
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
#: src/pv/watchpid.c:160 src/pv/watchpid.c:288
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "не является обычным файлом или блочным устройством"
|
||||
|
||||
#~ msgid "failed to stat file"
|
||||
#~ msgstr "не удалось получить информацию о файле"
|
||||
|
||||
#~ msgid "is a directory"
|
||||
#~ msgstr "является каталогом"
|
||||
|
||||
#~ msgid "failed to generate sysfs filename"
|
||||
#~ msgstr "не удалось создать имя файла sysfs"
|
||||
|
||||
#~ msgid "failed to read sysfs size file"
|
||||
#~ msgstr "не удалось узнать размер файла sysfs"
|
||||
|
||||
#~ msgid "failed to open block device"
|
||||
#~ msgstr "не удалось открыть блочное устройство"
|
||||
|
||||
#~ msgid "failed to determine size of block device"
|
||||
#~ msgstr "не удалось определить размер блочного устройства"
|
||||
|
||||
#~ msgid "option structure allocation failed"
|
||||
#~ msgstr "не удалось выделить память для структуры опций"
|
||||
|
||||
#~ msgid "option structure argv allocation failed"
|
||||
#~ msgstr "не удалось выделить память для структуры опций argv"
|
||||
|
||||
#~ msgid "failed to get terminal name"
|
||||
#~ msgstr "не удалось получить имя терминала"
|
||||
|
||||
#~ msgid "lock attempt failed"
|
||||
#~ msgstr "попытка блокировки не удалась"
|
||||
|
||||
#~ msgid "failed to open terminal"
|
||||
#~ msgstr "не удалось открыть терминал"
|
||||
|
||||
#~ msgid "failed to read file"
|
||||
#~ msgstr "не удалось прочесть файл"
|
||||
|
||||
#~ msgid "failed to stat output file"
|
||||
#~ msgstr "не удалось получить информацию о выходном файле"
|
||||
|
||||
#~ msgid "history structure allocation failed"
|
||||
#~ msgstr "не удалось выделить память для структуры истории"
|
||||
|
||||
#~ msgid "file list allocation failed"
|
||||
#~ msgstr "не удалось выделить память для списка файлов"
|
||||
|
||||
#~ msgid "read failed"
|
||||
#~ msgstr "чтение не удалось"
|
||||
|
||||
#~ msgid "no transfer buffer allocated"
|
||||
#~ msgstr "не выделена память для буфера передачи"
|
||||
|
||||
#~ msgid "failed to set interval timer"
|
||||
#~ msgstr "не удалось задать измеритель временного промежутка"
|
||||
|
||||
#~ msgid "failed to clear interval timer"
|
||||
#~ msgstr "не удалось очистить измеритель временного промежутка"
|
||||
|
||||
#~ msgid "select call failed"
|
||||
#~ msgstr "запрос выборки не удался"
|
||||
|
||||
#~ msgid "PID[:FD]"
|
||||
#~ msgstr "ИДпр[:FD]"
|
||||
|
||||
@@ -2,7 +2,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: pv 1.8.14\n"
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-12-15 20:10+0000\n"
|
||||
"POT-Creation-Date: 2026-08-01 14:53+0100\n"
|
||||
"PO-Revision-Date: 2025-10-05 20:09+0000\n"
|
||||
"Last-Translator: Oğuz Ersen <ersen@noreply.codeberg.org>\n"
|
||||
"Language-Team: Turkish <https://translate.codeberg.org/projects/pv/pv/tr/>\n"
|
||||
@@ -13,362 +13,353 @@ msgstr ""
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.13.2\n"
|
||||
|
||||
#: src/main/help.c:236
|
||||
#: src/main/help.c:300
|
||||
msgid "show progress bar"
|
||||
msgstr "ilerleme çubuğunu göster"
|
||||
|
||||
#: src/main/help.c:239
|
||||
#: src/main/help.c:303
|
||||
msgid "show elapsed time"
|
||||
msgstr "geçen süreyi göster"
|
||||
|
||||
#: src/main/help.c:242
|
||||
#: src/main/help.c:306
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "tahmini varış (tamamlanma) zamanını göster"
|
||||
|
||||
#: src/main/help.c:245
|
||||
#: src/main/help.c:309
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "mutlak tahmini varış (tamamlanma) zamanını göster"
|
||||
|
||||
#: src/main/help.c:248
|
||||
#: src/main/help.c:312
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "veri aktarım oranı sayacını göster"
|
||||
|
||||
#: src/main/help.c:251
|
||||
#: src/main/help.c:315
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "veri aktarımı ortalama hız sayacını göster"
|
||||
|
||||
#: src/main/help.c:254
|
||||
#: src/main/help.c:318
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "aktarılan bayt sayısını göster"
|
||||
|
||||
#: src/main/help.c:257
|
||||
#: src/main/help.c:321
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "aktarım tamponunun kullanım yüzdesini göster"
|
||||
|
||||
#: src/main/help.c:259
|
||||
#: src/main/help.c:323
|
||||
msgid "NUM"
|
||||
msgstr "NUM"
|
||||
|
||||
#: src/main/help.c:260
|
||||
#: src/main/help.c:324
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "son yazılan NUM baytlarını göster"
|
||||
|
||||
#: src/main/help.c:262
|
||||
#: src/main/help.c:326
|
||||
msgid "FORMAT"
|
||||
msgstr "FORMAT"
|
||||
|
||||
#: src/main/help.c:263
|
||||
#: src/main/help.c:327
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "çıktı formatını FORMAT olarak ayarlayın"
|
||||
|
||||
#: src/main/help.c:266
|
||||
#: src/main/help.c:330
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "görsel bilgileri değil, yüzdeleri çıktı olarak yazdır"
|
||||
|
||||
#: src/main/help.c:269
|
||||
#: src/main/help.c:333
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "hiçbir transfer bilgisini yazdırma"
|
||||
|
||||
#: src/main/help.c:273
|
||||
#: src/main/help.c:337
|
||||
msgid "show number of bits transferred"
|
||||
msgstr "aktarılan bit sayısını göster"
|
||||
|
||||
#: src/main/help.c:276
|
||||
#: src/main/help.c:340
|
||||
msgid "treat suffixes as multiples of 1000 rather than 1024"
|
||||
msgstr "ekleri 1024 yerine 1000'in katları olarak değerlendir"
|
||||
|
||||
#: src/main/help.c:279
|
||||
#: src/main/help.c:343
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "ilk bayt aktarılana kadar hiçbir şey gösterme"
|
||||
|
||||
#: src/main/help.c:281 src/main/help.c:296 src/main/help.c:299
|
||||
#: src/main/help.c:345 src/main/help.c:360 src/main/help.c:363
|
||||
msgid "SEC"
|
||||
msgstr "SEC"
|
||||
|
||||
#: src/main/help.c:282
|
||||
#: src/main/help.c:346
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "SEC saniye geçene kadar hiçbir şey gösterme"
|
||||
|
||||
#: src/main/help.c:284
|
||||
#: src/main/help.c:348
|
||||
msgid "SIZE"
|
||||
msgstr "BOYUT"
|
||||
|
||||
#: src/main/help.c:285
|
||||
#: src/main/help.c:349
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "tahmini veri boyutunu BOYUT bayt olarak ayarlayın"
|
||||
|
||||
#: src/main/help.c:288
|
||||
#: src/main/help.c:352
|
||||
msgid "if size unknown, show rate vs max rate"
|
||||
msgstr "boyut bilinmiyorsa, oranı maksimum oranla göster"
|
||||
|
||||
#: src/main/help.c:291
|
||||
#: src/main/help.c:355
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "bayt yerine satır say"
|
||||
|
||||
#: src/main/help.c:294
|
||||
#: src/main/help.c:358
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "satırlar boş sonlandırılır"
|
||||
|
||||
#: src/main/help.c:297
|
||||
#: src/main/help.c:361
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "her SEC saniyede bir güncelleme"
|
||||
|
||||
#: src/main/help.c:300
|
||||
#: src/main/help.c:364
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr "geçmiş SEC saniyeleri üzerinden ortalama hızı hesapla (varsayılan 30s)"
|
||||
|
||||
#: src/main/help.c:302
|
||||
#: src/main/help.c:366
|
||||
msgid "WIDTH"
|
||||
msgstr "GENİŞLİK"
|
||||
|
||||
#: src/main/help.c:303
|
||||
#: src/main/help.c:367
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "terminalin GENİŞLİK karakter genişliğinde olduğunu varsayalım"
|
||||
|
||||
#: src/main/help.c:305
|
||||
#: src/main/help.c:369
|
||||
msgid "HEIGHT"
|
||||
msgstr "YÜKSEKLİK"
|
||||
|
||||
#: src/main/help.c:306
|
||||
#: src/main/help.c:370
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "terminalin YÜKSEKLİK sıraları yüksekliğinde olduğunu varsayalım"
|
||||
|
||||
#: src/main/help.c:308
|
||||
#: src/main/help.c:372
|
||||
msgid "NAME"
|
||||
msgstr "İSİM"
|
||||
|
||||
#: src/main/help.c:309
|
||||
#: src/main/help.c:373
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "görsel bilgiyi İSİM ile öne ekle"
|
||||
|
||||
#: src/main/help.c:311
|
||||
#: src/main/help.c:375
|
||||
msgid "STYLE"
|
||||
msgstr "BİÇİM"
|
||||
|
||||
#: src/main/help.c:312
|
||||
msgid "set default bar style to NAME"
|
||||
msgstr "öntanımlı çubuk biçimini İSİM olarak ayarla"
|
||||
#: src/main/help.c:376
|
||||
msgid "set default bar style to STYLE"
|
||||
msgstr "öntanımlı çubuk biçimini BİÇİM olarak ayarla"
|
||||
|
||||
#: src/main/help.c:314
|
||||
#: src/main/help.c:378
|
||||
msgid "SPEC"
|
||||
msgstr "BELİRT"
|
||||
|
||||
#: src/main/help.c:315
|
||||
#: src/main/help.c:379
|
||||
msgid "also send progress to SPEC"
|
||||
msgstr "ilerlemeyi BELİRT ögesine de gönder"
|
||||
|
||||
#: src/main/help.c:318
|
||||
#: src/main/help.c:382
|
||||
msgid "set terminal progress state with OSC 9;4 (ConEmu)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:385
|
||||
msgid "output transfer statistics at the end"
|
||||
msgstr "transfer istatistiklerini sonda göster"
|
||||
|
||||
#: src/main/help.c:321
|
||||
#: src/main/help.c:388
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "standart hata bir terminal olmasa bile çıktı yazdır"
|
||||
|
||||
#: src/main/help.c:324
|
||||
#: src/main/help.c:391
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "imleç konumlandırma kaçış dizilerini kullan"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
#: src/main/help.c:394 src/main/help.c:430 src/main/help.c:449
|
||||
#: src/main/help.c:459
|
||||
msgid "FILE"
|
||||
msgstr "DOSYA"
|
||||
|
||||
#: src/main/help.c:328
|
||||
#: src/main/help.c:395
|
||||
msgid "write output to FILE instead of stdout"
|
||||
msgstr "çıktıyı stdout yerine DOSYA'ya yaz"
|
||||
|
||||
#: src/main/help.c:330
|
||||
#: src/main/help.c:397
|
||||
msgid "RATE"
|
||||
msgstr "ORAN"
|
||||
|
||||
#: src/main/help.c:331
|
||||
#: src/main/help.c:398
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "aktarımı saniye başına ORAN bayt ile sınırlandırın"
|
||||
|
||||
#: src/main/help.c:333 src/main/help.c:342
|
||||
#: src/main/help.c:400 src/main/help.c:406 src/main/help.c:412
|
||||
msgid "BYTES"
|
||||
msgstr "BAYTLAR"
|
||||
|
||||
#: src/main/help.c:334
|
||||
#: src/main/help.c:401
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "BAYTLAR tampon boyutu kullanın"
|
||||
|
||||
#: src/main/help.c:337
|
||||
#: src/main/help.c:404
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "splice() kullanma, her zaman read/write kullan"
|
||||
|
||||
#: src/main/help.c:340
|
||||
#: src/main/help.c:407
|
||||
msgid "set the pipe buffer size to BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:410
|
||||
msgid "skip read errors in input"
|
||||
msgstr "girdideki okuma hatalarını atla"
|
||||
|
||||
#: src/main/help.c:343
|
||||
#: src/main/help.c:413
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr "BAYTLAR blokları halinde hataları atla"
|
||||
|
||||
#: src/main/help.c:346
|
||||
#: src/main/help.c:416
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "--size bayt transfer edildikten sonra dur"
|
||||
|
||||
#: src/main/help.c:349
|
||||
#: src/main/help.c:419
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr "her yazmadan sonra önbelleği diske boşalt"
|
||||
|
||||
#: src/main/help.c:352
|
||||
#: src/main/help.c:422
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr "Önbelleği atlamak için doğrudan I/O kullan"
|
||||
|
||||
#: src/main/help.c:355
|
||||
#: src/main/help.c:425
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
#: src/main/help.c:428
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr "Girdiyi çıktıya yazmak yerine yok say"
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:431
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr "çıktıya yazmadan önce tüm girdiyi DOSYA'ya yaz"
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:434
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:435
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "FD izleme dosyası PID işlemi tarafından açıldı"
|
||||
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
#: src/main/help.c:438 src/main/help.c:441
|
||||
msgid "PID"
|
||||
msgstr "PID"
|
||||
|
||||
#: src/main/help.c:369
|
||||
#: src/main/help.c:439
|
||||
msgid "update settings of process PID"
|
||||
msgstr "süreç PID ayarlarını güncelle"
|
||||
|
||||
#: src/main/help.c:372
|
||||
#: src/main/help.c:442
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
#: src/main/help.c:446
|
||||
msgid "run a command and monitor its standard input, output, or both"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:450
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "FILE'da işlem kimliğini (ID) kaydet"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:453
|
||||
msgid "show this help and exit"
|
||||
msgstr "bu yardımı göster ve çık"
|
||||
|
||||
#: src/main/help.c:383
|
||||
#: src/main/help.c:456
|
||||
msgid "show version information and exit"
|
||||
msgstr "sürüm bilgilerini göster ve çık"
|
||||
|
||||
#: src/main/help.c:387
|
||||
#: src/main/help.c:460
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "Hata ayıklama kayıtlarını DOSYA'ya yaz"
|
||||
|
||||
#: src/main/help.c:413
|
||||
#: src/main/help.c:486
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Kullanım şekli: %s [AYAR] [DOSYA]..."
|
||||
|
||||
#: src/main/help.c:424
|
||||
#: src/main/help.c:497
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
"İzleme ile DOSYA(lar)ı veya standart girdiyi standart çıktı ile birleştirin."
|
||||
|
||||
#: src/main/help.c:562
|
||||
#: src/main/help.c:639
|
||||
msgid "Supported format sequences:"
|
||||
msgstr "Desteklenen biçim dizileri:"
|
||||
|
||||
#: src/main/help.c:576
|
||||
#: src/main/help.c:653
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Lütfen hataları şu adrese bildirin: %s"
|
||||
|
||||
#: src/main/main.c:228
|
||||
#: src/main/main.c:225
|
||||
msgid "(input)"
|
||||
msgstr "(giriş)"
|
||||
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr "durum tahsisi başarısız oldu"
|
||||
#: src/main/main.c:381 src/main/options.c:1359
|
||||
msgid "a command to run must be specified"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:370
|
||||
#: src/main/main.c:704 src/main/options.c:757 src/main/options.c:777
|
||||
#: src/pv/display.c:1086 src/pv/state.c:45 src/pv/state.c:902
|
||||
#: src/pv/state.c:914 src/pv/state.c:950 src/pv/transfer.c:1335
|
||||
#: src/pv/transfer.c:1451 src/pv/transfer.c:1778
|
||||
msgid "memory allocation failure"
|
||||
msgstr "bellek ayırma başarısız"
|
||||
|
||||
#: src/main/options.c:418
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
#: src/main/options.c:438 src/main/options.c:440 src/main/options.c:901
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr "süreç kimliği (ID) veya pid:fd çifti bekleniyor"
|
||||
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
#: src/main/options.c:449 src/main/options.c:451 src/main/options.c:908
|
||||
msgid "invalid process ID"
|
||||
msgstr "geçersiz süreç kimliği (ID)"
|
||||
|
||||
#: src/main/options.c:448 src/pv/file.c:342
|
||||
msgid "failed to stat file"
|
||||
msgstr "dosya statüsünde başarısız oldu"
|
||||
|
||||
#: src/main/options.c:462
|
||||
msgid "is a directory"
|
||||
msgstr "bir dizindir"
|
||||
|
||||
#: src/main/options.c:491
|
||||
msgid "failed to generate sysfs filename"
|
||||
msgstr "sysfs dosya adı oluşturulamadı"
|
||||
|
||||
#: src/main/options.c:513
|
||||
msgid "failed to read sysfs size file"
|
||||
msgstr "sysfs boyut dosyası okunamadı"
|
||||
|
||||
#: src/main/options.c:533
|
||||
msgid "failed to open block device"
|
||||
msgstr "blok aygıtı açılamadı"
|
||||
|
||||
#: src/main/options.c:543
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr "blok aygıtının boyutu belirlenemedi"
|
||||
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "seçenek yapısı tahsisi başarısız oldu"
|
||||
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "seçenek yapısı argv tahsisi başarısız oldu"
|
||||
|
||||
#: src/main/options.c:723
|
||||
#: src/main/options.c:829
|
||||
msgid "numeric value not understood"
|
||||
msgstr "sayısal değer anlaşılmadı"
|
||||
|
||||
#: src/main/options.c:743
|
||||
#: src/main/options.c:843
|
||||
msgid "integer argument expected"
|
||||
msgstr "tamsayı bağımsız değişkeni bekleniyor"
|
||||
|
||||
#: src/main/options.c:755
|
||||
#: src/main/options.c:853
|
||||
msgid "numeric argument expected"
|
||||
msgstr "sayısal bağımsız değişken bekleniyor"
|
||||
|
||||
#: src/main/options.c:767
|
||||
#: src/main/options.c:864
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:795
|
||||
#: src/main/options.c:890
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1056
|
||||
#: src/main/options.c:1182
|
||||
msgid "invalid side specification"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1197
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Daha fazla bilgi için `%s --help' seçeneğini deneyin."
|
||||
|
||||
#: src/main/options.c:1058
|
||||
#: src/main/options.c:1199
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Daha fazla bilgi için `%s -h' seçeneğini deneyin."
|
||||
|
||||
#: src/main/options.c:1089
|
||||
#: src/main/options.c:1231
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -376,31 +367,39 @@ msgstr ""
|
||||
"dosya tanımlayıcılarını izlerken satır modu veya aktarım değiştirici "
|
||||
"seçeneklerini kullanamaz"
|
||||
|
||||
#: src/main/options.c:1098
|
||||
#: src/main/options.c:1239
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr "dosya tanımlayıcılarını izlerken imleç konumlandırmayı kullanamaz"
|
||||
|
||||
#: src/main/options.c:1107
|
||||
#: src/main/options.c:1247
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr "dosya tanımlayıcılarını izlerken uzaktan kumandayı kullanamaz"
|
||||
|
||||
#: src/main/options.c:1116
|
||||
#: src/main/options.c:1255
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
#: src/main/options.c:1263
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr "dosya tanımlayıcıları izlenirken dosya aktarılamıyor"
|
||||
|
||||
#: src/main/options.c:1150
|
||||
#: src/main/options.c:1287
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "/proc/self/fdinfo olmayan sistemlerde kullanılamaz"
|
||||
|
||||
#: src/main/options.c:1162
|
||||
#: src/main/options.c:1298
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1189
|
||||
#: src/main/options.c:1325
|
||||
msgid "monitor mode cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1337
|
||||
msgid "monitor mode cannot be used with store-and-forward"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1348
|
||||
msgid "files cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
@@ -421,64 +420,44 @@ msgstr "Yasaların izin verdiği ölçüde GARANTİ YOKTUR."
|
||||
msgid "Project web site"
|
||||
msgstr "Proje web sitesi"
|
||||
|
||||
#: src/pv/cursor.c:61
|
||||
msgid "failed to get terminal name"
|
||||
msgstr "terminal adı alınamadı"
|
||||
|
||||
#: src/pv/cursor.c:106
|
||||
#: src/pv/cursor.c:108 src/pv/cursor.c:135
|
||||
msgid "failed to open lock file"
|
||||
msgstr "lock dosyası açılamadı"
|
||||
|
||||
#: src/pv/cursor.c:139
|
||||
msgid "lock attempt failed"
|
||||
msgstr "kilit denemesi başarısız oldu"
|
||||
#: src/pv/cursor.c:790 src/pv/cursor.c:792
|
||||
msgid "interrupted by a signal"
|
||||
msgstr "bir işaret tarafından kesildi"
|
||||
|
||||
#: src/pv/cursor.c:400
|
||||
msgid "failed to open terminal"
|
||||
msgstr "terminal açılamadı"
|
||||
|
||||
#: src/pv/display.c:285
|
||||
#: src/pv/display.c:311
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr "yzafpnum kMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:303
|
||||
#: src/pv/display.c:329
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr "yzafpnum KMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "arabellek tahsisi başarısız oldu"
|
||||
#: src/pv/file.c:81
|
||||
msgid "/dev/null is not usable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/file.c:153
|
||||
msgid "failed to seek to start of output"
|
||||
msgstr "çıktının başlangıcına ulaşılamadı"
|
||||
#: src/pv/file.c:371
|
||||
msgid "error closing file"
|
||||
msgstr "dosya kapatılırken hata"
|
||||
|
||||
#: src/pv/file.c:303
|
||||
msgid "failed to close file"
|
||||
msgstr "dosya kapatılamadı"
|
||||
#: src/pv/file.c:438
|
||||
msgid "input file is also the output"
|
||||
msgstr "girdi dosyası aynı zamanda çıkış"
|
||||
|
||||
#: src/pv/file.c:335
|
||||
msgid "failed to read file"
|
||||
msgstr "dosya okunamadı"
|
||||
|
||||
#: src/pv/file.c:350
|
||||
msgid "failed to stat output file"
|
||||
msgstr "çıktı dosyası stat edilemedi"
|
||||
|
||||
#: src/pv/file.c:372
|
||||
msgid "input file is output file"
|
||||
msgstr "girdi dosyası çıktı dosyasıdır"
|
||||
|
||||
#: src/pv/file.c:429
|
||||
#: src/pv/file.c:596
|
||||
msgid "(none)"
|
||||
msgstr "(yok)"
|
||||
|
||||
#: src/pv/file.c:431
|
||||
#: src/pv/file.c:598
|
||||
msgid "(stdin)"
|
||||
msgstr "(stdin)"
|
||||
|
||||
#: src/pv/format/averagerate.c:34 src/pv/format/progressbar.c:92
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:181
|
||||
msgid "b/s"
|
||||
msgstr "b/s"
|
||||
|
||||
@@ -488,7 +467,7 @@ msgid "/s"
|
||||
msgstr "/s"
|
||||
|
||||
#: src/pv/format/averagerate.c:38 src/pv/format/progressbar.c:96
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:181
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
@@ -496,104 +475,142 @@ msgstr "B/s"
|
||||
msgid "b"
|
||||
msgstr "b"
|
||||
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:620
|
||||
#: src/pv/format/bytes.c:39 src/pv/transfer.c:1284
|
||||
msgid "B"
|
||||
msgstr "B"
|
||||
|
||||
#: src/pv/format/eta.c:52 src/pv/format/eta.c:56
|
||||
#: src/pv/format/eta.c:63 src/pv/format/eta.c:67
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
#: src/pv/format/fineta.c:80
|
||||
#: src/pv/format/fineta.c:93
|
||||
msgid "FIN"
|
||||
msgstr "FIN"
|
||||
|
||||
#: src/pv/loop.c:120
|
||||
#: src/pv/loop.c:180
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr "oran min/ortalama/maks/standart sapma"
|
||||
|
||||
#: src/pv/loop.c:132
|
||||
#: src/pv/loop.c:192
|
||||
msgid "rate not measured"
|
||||
msgstr "oran ölçülmedi"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/loop.c:818 src/pv/loop.c:836 src/pv/watchpid.c:101
|
||||
#: src/pv/watchpid.c:110 src/pv/watchpid.c:121 src/pv/watchpid.c:129
|
||||
#: src/pv/watchpid.c:166 src/pv/watchpid.c:185 src/pv/watchpid.c:193
|
||||
#: src/pv/watchpid.c:203 src/pv/watchpid.c:307 src/pv/watchpid.c:315
|
||||
#: src/pv/watchpid.c:447 src/pv/watchpid.c:470
|
||||
#: src/pv/loop.c:1098 src/pv/loop.c:1114 src/pv/loop.c:1132 src/pv/remote.c:93
|
||||
#: src/pv/remote.c:188 src/pv/remote.c:536 src/pv/remote.c:582
|
||||
#: src/pv/watchpid.c:123 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:158 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:206 src/pv/watchpid.c:218 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:286 src/pv/watchpid.c:401
|
||||
#: src/pv/watchpid.c:409 src/pv/watchpid.c:556 src/pv/watchpid.c:565
|
||||
#: src/pv/watchpid.c:586
|
||||
msgid "pid"
|
||||
msgstr "pid"
|
||||
|
||||
#: src/pv/loop.c:836 src/pv/watchpid.c:110 src/pv/watchpid.c:122
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:185 src/pv/watchpid.c:194
|
||||
#: src/pv/watchpid.c:205
|
||||
#: src/pv/loop.c:1132 src/pv/watchpid.c:132 src/pv/watchpid.c:142
|
||||
#: src/pv/watchpid.c:151 src/pv/watchpid.c:160 src/pv/watchpid.c:268
|
||||
#: src/pv/watchpid.c:277 src/pv/watchpid.c:288
|
||||
msgid "fd"
|
||||
msgstr "fd"
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
#: src/pv/remote.c:242 src/pv/remote.c:636
|
||||
msgid "message not received"
|
||||
msgstr "mesaj alınamadı"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
#: src/pv/remote.c:659 src/pv/remote.c:677
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO bu sistemde desteklenmiyor"
|
||||
|
||||
#: src/pv/state.c:42
|
||||
msgid "history structure allocation failed"
|
||||
msgstr "geçmiş yapısı tahsisi başarısız oldu"
|
||||
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr "dosya listesi tahsisi başarısız oldu"
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr "okuma başarısız"
|
||||
|
||||
#: src/pv/transfer.c:506
|
||||
#: src/pv/transfer.c:1173
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "uyarı: okuma hataları tespit edildi"
|
||||
|
||||
#: src/pv/transfer.c:522
|
||||
msgid "file is not seekable"
|
||||
msgstr "dosya aranabilir değil"
|
||||
|
||||
#: src/pv/transfer.c:599
|
||||
msgid "failed to seek past error"
|
||||
msgstr "geçmiş hatayı aramakta başarısız oldu"
|
||||
|
||||
#: src/pv/transfer.c:619
|
||||
#: src/pv/transfer.c:1283
|
||||
msgid "skipped past read error"
|
||||
msgstr "geçmiş okuma hatası atlandı"
|
||||
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr "aktarım arabelleği ayrılmamış"
|
||||
#: src/pv/transfer.c:1642
|
||||
msgid "write error"
|
||||
msgstr "yazma hatası"
|
||||
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr "aralık zamanlayıcısı ayarlanamadı"
|
||||
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr "aralık zamanlayıcısı temizlenemedi"
|
||||
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr "satır konumu arabellek tahsisi başarısız oldu"
|
||||
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "yazma başarısız"
|
||||
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "seçme çağrısı başarısız oldu"
|
||||
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
#: src/pv/watchpid.c:160 src/pv/watchpid.c:288
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "normal bir dosya veya blok aygıtı değil"
|
||||
|
||||
#~ msgid "state allocation failed"
|
||||
#~ msgstr "durum tahsisi başarısız oldu"
|
||||
|
||||
#~ msgid "failed to stat file"
|
||||
#~ msgstr "dosya statüsünde başarısız oldu"
|
||||
|
||||
#~ msgid "is a directory"
|
||||
#~ msgstr "bir dizindir"
|
||||
|
||||
#~ msgid "failed to generate sysfs filename"
|
||||
#~ msgstr "sysfs dosya adı oluşturulamadı"
|
||||
|
||||
#~ msgid "failed to read sysfs size file"
|
||||
#~ msgstr "sysfs boyut dosyası okunamadı"
|
||||
|
||||
#~ msgid "failed to open block device"
|
||||
#~ msgstr "blok aygıtı açılamadı"
|
||||
|
||||
#~ msgid "failed to determine size of block device"
|
||||
#~ msgstr "blok aygıtının boyutu belirlenemedi"
|
||||
|
||||
#~ msgid "option structure allocation failed"
|
||||
#~ msgstr "seçenek yapısı tahsisi başarısız oldu"
|
||||
|
||||
#~ msgid "option structure argv allocation failed"
|
||||
#~ msgstr "seçenek yapısı argv tahsisi başarısız oldu"
|
||||
|
||||
#~ msgid "failed to get terminal name"
|
||||
#~ msgstr "terminal adı alınamadı"
|
||||
|
||||
#~ msgid "lock attempt failed"
|
||||
#~ msgstr "kilit denemesi başarısız oldu"
|
||||
|
||||
#~ msgid "failed to open terminal"
|
||||
#~ msgstr "terminal açılamadı"
|
||||
|
||||
#~ msgid "failed to seek to start of output"
|
||||
#~ msgstr "çıktının başlangıcına ulaşılamadı"
|
||||
|
||||
#~ msgid "failed to read file"
|
||||
#~ msgstr "dosya okunamadı"
|
||||
|
||||
#~ msgid "failed to stat output file"
|
||||
#~ msgstr "çıktı dosyası stat edilemedi"
|
||||
|
||||
#~ msgid "history structure allocation failed"
|
||||
#~ msgstr "geçmiş yapısı tahsisi başarısız oldu"
|
||||
|
||||
#~ msgid "file list allocation failed"
|
||||
#~ msgstr "dosya listesi tahsisi başarısız oldu"
|
||||
|
||||
#~ msgid "read failed"
|
||||
#~ msgstr "okuma başarısız"
|
||||
|
||||
#~ msgid "file is not seekable"
|
||||
#~ msgstr "dosya aranabilir değil"
|
||||
|
||||
#~ msgid "failed to seek past error"
|
||||
#~ msgstr "geçmiş hatayı aramakta başarısız oldu"
|
||||
|
||||
#~ msgid "no transfer buffer allocated"
|
||||
#~ msgstr "aktarım arabelleği ayrılmamış"
|
||||
|
||||
#~ msgid "failed to set interval timer"
|
||||
#~ msgstr "aralık zamanlayıcısı ayarlanamadı"
|
||||
|
||||
#~ msgid "failed to clear interval timer"
|
||||
#~ msgstr "aralık zamanlayıcısı temizlenemedi"
|
||||
|
||||
#~ msgid "line position buffer allocation failed"
|
||||
#~ msgstr "satır konumu arabellek tahsisi başarısız oldu"
|
||||
|
||||
#~ msgid "select call failed"
|
||||
#~ msgstr "seçme çağrısı başarısız oldu"
|
||||
|
||||
#~ msgid "process list allocation failed"
|
||||
#~ msgstr "işlem listesi tahsisi başarısız oldu"
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
config.h.in
|
||||
@@ -3,7 +3,7 @@
|
||||
* `configure' script. Include this after config.h and before anything
|
||||
* else.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -51,3 +51,18 @@ typedef bool _Bool;
|
||||
#define PV_REMOTE_CONTROL 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SPLINT
|
||||
/* Remove __attribute__(()) if not using GCC. */
|
||||
#ifndef __GNUC__
|
||||
#define __attribute__(x) /* GCC-only feature */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Support for the fallthrough attribute is not universal. */
|
||||
/* From https://stackoverflow.com/questions/45349079/how-to-use-attribute-fallthrough-correctly-in-gcc */
|
||||
#if defined(__GNUC__) && __GNUC__ >= 7
|
||||
#define FALL_THROUGH __attribute__ ((fallthrough))
|
||||
#else
|
||||
#define FALL_THROUGH /*@-noeffect@*/ ((void)0) /*@+noeffect@*/
|
||||
#endif /* __GNUC__ >= 7 */
|
||||
|
||||
@@ -1,387 +0,0 @@
|
||||
/* src/include/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Debugging support enabled */
|
||||
#undef ENABLE_DEBUGGING
|
||||
|
||||
/* Build with ncurses support */
|
||||
#undef ENABLE_NCURSES
|
||||
|
||||
/* Define to 1 if translation of program messages to the user's native
|
||||
language is requested. */
|
||||
#undef ENABLE_NLS
|
||||
|
||||
/* Define to 1 if you have the `alarm' function. */
|
||||
#undef HAVE_ALARM
|
||||
|
||||
/* Define to 1 if you have the `basename' function. */
|
||||
#undef HAVE_BASENAME
|
||||
|
||||
/* Define to 1 if you have the Mac OS X function
|
||||
CFLocaleCopyPreferredLanguages in the CoreFoundation framework. */
|
||||
#undef HAVE_CFLOCALECOPYPREFERREDLANGUAGES
|
||||
|
||||
/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in
|
||||
the CoreFoundation framework. */
|
||||
#undef HAVE_CFPREFERENCESCOPYAPPVALUE
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
/* Define if the GNU dcgettext() function is already present or preinstalled.
|
||||
*/
|
||||
#undef HAVE_DCGETTEXT
|
||||
|
||||
/* Define to 1 if you have the declaration of `SA_SIGINFO', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_SA_SIGINFO
|
||||
|
||||
/* Define to 1 if you have the `dup2' function. */
|
||||
#undef HAVE_DUP2
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define to 1 if you have the `fdatasync' function. */
|
||||
#undef HAVE_FDATASYNC
|
||||
|
||||
/* Define to 1 if you have the `fmod' function. */
|
||||
#undef HAVE_FMOD
|
||||
|
||||
/* Define to 1 if you have the `fpathconf' function. */
|
||||
#undef HAVE_FPATHCONF
|
||||
|
||||
/* Define to 1 if you have the `getcwd' function. */
|
||||
#undef HAVE_GETCWD
|
||||
|
||||
/* Define to 1 if you have the <getopt.h> header file. */
|
||||
#undef HAVE_GETOPT_H
|
||||
|
||||
/* Define to 1 if you have the `getopt_long' function. */
|
||||
#undef HAVE_GETOPT_LONG
|
||||
|
||||
/* Define if the GNU gettext() function is already present or preinstalled. */
|
||||
#undef HAVE_GETTEXT
|
||||
|
||||
/* Define if you have the iconv() function and it works. */
|
||||
#undef HAVE_ICONV
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* IPC support enabled */
|
||||
#undef HAVE_IPC
|
||||
|
||||
/* Define to 1 if you have the <langinfo.h> header file. */
|
||||
#undef HAVE_LANGINFO_H
|
||||
|
||||
/* Define to 1 if you have the <libgen.h> header file. */
|
||||
#undef HAVE_LIBGEN_H
|
||||
|
||||
/* Define to 1 if you have the <libintl.h> header file. */
|
||||
#undef HAVE_LIBINTL_H
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#undef HAVE_LIMITS_H
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#undef HAVE_LOCALE_H
|
||||
|
||||
/* Define to 1 if you have the <math.h> header file. */
|
||||
#undef HAVE_MATH_H
|
||||
|
||||
/* Define to 1 if you have the `memcpy' function. */
|
||||
#undef HAVE_MEMCPY
|
||||
|
||||
/* Define to 1 if you have the `memmove' function. */
|
||||
#undef HAVE_MEMMOVE
|
||||
|
||||
/* Define to 1 if you have the `memrchr' function. */
|
||||
#undef HAVE_MEMRCHR
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#undef HAVE_MEMSET
|
||||
|
||||
/* Define to 1 if you have the <minix/config.h> header file. */
|
||||
#undef HAVE_MINIX_CONFIG_H
|
||||
|
||||
/* Define to 1 if you have the `mkdir' function. */
|
||||
#undef HAVE_MKDIR
|
||||
|
||||
/* Define to 1 if you have the `nanosleep' function. */
|
||||
#undef HAVE_NANOSLEEP
|
||||
|
||||
/* Define to 1 if you have the `posix_fadvise' function. */
|
||||
#undef HAVE_POSIX_FADVISE
|
||||
|
||||
/* Define to 1 if you have the `posix_memalign' function. */
|
||||
#undef HAVE_POSIX_MEMALIGN
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#undef HAVE_SELECT
|
||||
|
||||
/* Define to 1 if you have the `setitimer' function. */
|
||||
#undef HAVE_SETITIMER
|
||||
|
||||
/* Define to 1 if you have the `setlocale' function. */
|
||||
#undef HAVE_SETLOCALE
|
||||
|
||||
/* Define to 1 if you have the `setproctitle' function. */
|
||||
#undef HAVE_SETPROCTITLE
|
||||
|
||||
/* Define to 1 if you have the `shmget' function. */
|
||||
#undef HAVE_SHMGET
|
||||
|
||||
/* Define to 1 if you have the `splice' function. */
|
||||
#undef HAVE_SPLICE
|
||||
|
||||
/* Define to 1 if you have the `sqrtl' function. */
|
||||
#undef HAVE_SQRTL
|
||||
|
||||
/* Define to 1 if stdbool.h conforms to C99. */
|
||||
#undef HAVE_STDBOOL_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#undef HAVE_STDIO_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the `strchr' function. */
|
||||
#undef HAVE_STRCHR
|
||||
|
||||
/* Define to 1 if you have the `strerror' function. */
|
||||
#undef HAVE_STRERROR
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strlcat' function. */
|
||||
#undef HAVE_STRLCAT
|
||||
|
||||
/* Define to 1 if you have the `strrchr' function. */
|
||||
#undef HAVE_STRRCHR
|
||||
|
||||
/* Define to 1 if you have the `strstr' function. */
|
||||
#undef HAVE_STRSTR
|
||||
|
||||
/* Define to 1 if you have the `strtoul' function. */
|
||||
#undef HAVE_STRTOUL
|
||||
|
||||
/* Define to 1 if `st_blksize' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
|
||||
/* Define to 1 if `st_rdev' is a member of `struct stat'. */
|
||||
#undef HAVE_STRUCT_STAT_ST_RDEV
|
||||
|
||||
/* Define to 1 if you have the `sysconf' function. */
|
||||
#undef HAVE_SYSCONF
|
||||
|
||||
/* Define to 1 if you have the <sys/file.h> header file. */
|
||||
#undef HAVE_SYS_FILE_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#undef HAVE_SYS_IOCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ipc.h> header file. */
|
||||
#undef HAVE_SYS_IPC_H
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#undef HAVE_SYS_PARAM_H
|
||||
|
||||
/* Define to 1 if you have the <sys/shm.h> header file. */
|
||||
#undef HAVE_SYS_SHM_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/sysmacros.h> header file. */
|
||||
#undef HAVE_SYS_SYSMACROS_H
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#undef HAVE_SYS_TIME_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <termios.h> header file. */
|
||||
#undef HAVE_TERMIOS_H
|
||||
|
||||
/* Define to 1 if you have the <term.h> header file. */
|
||||
#undef HAVE_TERM_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the `vsnprintf' function. */
|
||||
#undef HAVE_VSNPRINTF
|
||||
|
||||
/* Define to 1 if you have the <wchar.h> header file. */
|
||||
#undef HAVE_WCHAR_H
|
||||
|
||||
/* Define to 1 if you have the <wctype.h> header file. */
|
||||
#undef HAVE_WCTYPE_H
|
||||
|
||||
/* Define to 1 if the system has the type `_Bool'. */
|
||||
#undef HAVE__BOOL
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Signal handlers can determine the sending PID */
|
||||
#undef SIGINFO_PROVIDES_PID
|
||||
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on macOS. */
|
||||
#ifndef _DARWIN_C_SOURCE
|
||||
# undef _DARWIN_C_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
/* Enable X/Open compliant socket functions that do not require linking
|
||||
with -lxnet on HP-UX 11.11. */
|
||||
#ifndef _HPUX_ALT_XOPEN_SOCKET_API
|
||||
# undef _HPUX_ALT_XOPEN_SOCKET_API
|
||||
#endif
|
||||
/* Identify the host operating system as Minix.
|
||||
This macro does not affect the system headers' behavior.
|
||||
A future release of Autoconf may stop defining this macro. */
|
||||
#ifndef _MINIX
|
||||
# undef _MINIX
|
||||
#endif
|
||||
/* Enable general extensions on NetBSD.
|
||||
Enable NetBSD compatibility extensions on Minix. */
|
||||
#ifndef _NETBSD_SOURCE
|
||||
# undef _NETBSD_SOURCE
|
||||
#endif
|
||||
/* Enable OpenBSD compatibility extensions on NetBSD.
|
||||
Oddly enough, this does nothing on OpenBSD. */
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
# undef _OPENBSD_SOURCE
|
||||
#endif
|
||||
/* Define to 1 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_SOURCE
|
||||
# undef _POSIX_SOURCE
|
||||
#endif
|
||||
/* Define to 2 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_1_SOURCE
|
||||
# undef _POSIX_1_SOURCE
|
||||
#endif
|
||||
/* Enable POSIX-compatible threading on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_BFP_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_DFP_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
|
||||
#ifndef __STDC_WANT_LIB_EXT2__
|
||||
# undef __STDC_WANT_LIB_EXT2__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC 24747:2009. */
|
||||
#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
|
||||
# undef __STDC_WANT_MATH_SPEC_FUNCS__
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
/* Enable X/Open extensions. Define to 500 only if necessary
|
||||
to make mbstate_t available. */
|
||||
#ifndef _XOPEN_SOURCE
|
||||
# undef _XOPEN_SOURCE
|
||||
#endif
|
||||
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef gid_t
|
||||
|
||||
/* Define to the type of a signed integer type of width exactly 32 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
#undef int32_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef mode_t
|
||||
|
||||
/* Define to `long int' if <sys/types.h> does not define. */
|
||||
#undef off_t
|
||||
|
||||
/* Define as a signed integer type capable of holding a process identifier. */
|
||||
#undef pid_t
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef ssize_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef uid_t
|
||||
|
||||
#include "config-aux.h"
|
||||
+26
-6
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Global program option structure and the parsing function prototype.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -32,9 +32,22 @@ typedef enum {
|
||||
PV_ACTION_STORE_AND_FORWARD, /* store to file, then output from it */
|
||||
PV_ACTION_WATCHFD, /* watch process file descriptors */
|
||||
PV_ACTION_REMOTE_CONTROL, /* remotely control another pv */
|
||||
PV_ACTION_QUERY /* watch the state of another pv */
|
||||
PV_ACTION_QUERY, /* watch the state of another pv */
|
||||
PV_ACTION_MONITOR /* run a process, watch its stdin/out */
|
||||
} pvaction_t;
|
||||
|
||||
/*
|
||||
* Sides of a monitored command to monitor with PV_ACTION_MONITOR.
|
||||
*/
|
||||
typedef enum {
|
||||
PV_SIDE_NONE, /* don't monitor a command */
|
||||
PV_SIDE_IN, /* monitor only the input side */
|
||||
PV_SIDE_OUT, /* monitor only the output side */
|
||||
PV_SIDE_BOTH /* monitor both sides */
|
||||
} pvside_t;
|
||||
|
||||
typedef /*@null@*/ const char * argv_string;
|
||||
|
||||
/*
|
||||
* Structure describing run-time options.
|
||||
*
|
||||
@@ -46,17 +59,20 @@ struct opts_s {
|
||||
/*@keep@*/ const char *program_name; /* name the program is running as */
|
||||
/*@keep@*/ /*@null@*/ char *output; /* fd to write output to */
|
||||
/*@keep@*/ /*@null@*/ char *name; /* display name, if any */
|
||||
/*@keep@*/ /*@null@*/ char *name1; /* first name, if two were given */
|
||||
/*@keep@*/ /*@null@*/ char *default_bar_style; /* default bar style */
|
||||
/*@keep@*/ /*@null@*/ char *format; /* output format, if any */
|
||||
/*@keep@*/ /*@null@*/ char *format1; /* first format, if two were given */
|
||||
/*@keep@*/ /*@null@*/ char *pidfile; /* PID file, if any */
|
||||
/*@keep@*/ /*@null@*/ char *store_and_forward_file; /* store and forward file, if any */
|
||||
/*@keep@*/ /*@null@*/ char *extra_display; /* extra display specifier, if any */
|
||||
/*@keep@*/ /*@null@*/ pid_t *watchfd_pid; /* array of processes to watch fds of */
|
||||
/*@keep@*/ /*@null@*/ int *watchfd_fd; /* array of fds to watch in each one (0=all) */
|
||||
/*@keep@*/ /*@null@*/ const char **argv; /* array of non-option arguments */
|
||||
/*@keep@*/ /*@null@*/ argv_string *argv; /* array of non-option arguments */
|
||||
size_t lastwritten; /* show N bytes last written */
|
||||
off_t rate_limit; /* rate limit, in bytes per second */
|
||||
long double rate_limit; /* rate limit, in bytes per second */
|
||||
size_t buffer_size; /* buffer size, in bytes (0=default) */
|
||||
size_t pipe_buffer_size; /* pipe buffer size, in bytes (0=default) */
|
||||
off_t size; /* total size of data */
|
||||
off_t error_skip_block; /* skip block size, 0 for adaptive */
|
||||
pid_t remote; /* PID of pv to update settings of */
|
||||
@@ -66,10 +82,11 @@ struct opts_s {
|
||||
unsigned int width; /* screen width */
|
||||
unsigned int height; /* screen height */
|
||||
unsigned int argc; /* number of non-option arguments */
|
||||
unsigned int argv_length; /* allocated array size */
|
||||
unsigned int argv_length; /* allocated array size for non-option arguments */
|
||||
unsigned int watchfd_count; /* number of watchfd items */
|
||||
unsigned int watchfd_length; /* allocated array size */
|
||||
unsigned int watchfd_length; /* allocated watchfd item array size */
|
||||
pvaction_t action; /* the program action to perform */
|
||||
pvside_t side; /* which side of the monitored command to monitor */
|
||||
bool progress; /* progress bar flag */
|
||||
bool timer; /* timer flag */
|
||||
bool eta; /* ETA flag */
|
||||
@@ -94,9 +111,12 @@ struct opts_s {
|
||||
bool direct_io; /* set if O_DIRECT is to be used */
|
||||
bool sparse_output; /* set if we leave holes in the output */
|
||||
bool discard_input; /* set to write nothing to output */
|
||||
bool use_osc94; /* set to enable OSC 9;4 sequences */
|
||||
bool show_stats; /* set to write statistics at the end */
|
||||
bool width_set_manually; /* width was set manually, not detected */
|
||||
bool height_set_manually; /* height was set manually, not detected */
|
||||
bool rate_limit_specified; /* whether a rate limit value was given */
|
||||
bool rate_limit_active; /* whether rate limiting is in effect (>0) */
|
||||
};
|
||||
|
||||
/*@-exportlocal@*/
|
||||
|
||||
+103
-70
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Functions internal to the PV library. Include "config.h" first.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -24,35 +24,40 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define RATE_GRANULARITY 100000000 /* nsec between -L rate chunks */
|
||||
#define RATE_BURST_WINDOW 5 /* rate burst window (multiples of rate) */
|
||||
#define RATE_BURST_WINDOW 5.0 /* rate burst window (multiples of rate) */
|
||||
#define REMOTE_INTERVAL 100000000 /* nsec between checks for -R and -Q */
|
||||
#define MONITOR_EXCHANGE_INTERVAL 100000000 /* nsec between "-M both" data exchanges */
|
||||
#define BUFFER_SIZE (size_t) 409600 /* default transfer buffer size */
|
||||
#define BUFFER_SIZE_MAX (size_t) 524288 /* max auto transfer buffer size */
|
||||
#define MAX_READ_AT_ONCE (size_t) 524288 /* max to read() in one go */
|
||||
#define MAX_WRITE_AT_ONCE (size_t) 524288 /* max to write() in one go */
|
||||
#define MAX_SPLICE_AT_ONCE 1048576 /* max to splice() in one go */
|
||||
#define MAX_CFR_AT_ONCE 1073741824 /* max to copy_file_range() in one go */
|
||||
#define TRANSFER_READ_TIMEOUT 0.09L /* seconds to time reads out at */
|
||||
#define TRANSFER_WRITE_TIMEOUT 0.9L /* seconds to time writes out at */
|
||||
#define MAX_LINE_POSITIONS 100000 /* number of lines to remember positions of */
|
||||
|
||||
/*
|
||||
* Whether to always try to use the whole transfer buffer, reducing the
|
||||
* number of reads and writes at the expense of moving bytes around.
|
||||
*/
|
||||
#define MAXIMISE_BUFFER_FILL 1
|
||||
|
||||
/* Sizes for various statically sized buffers. */
|
||||
|
||||
#define PV_SIZEOF_DEFAULT_FORMAT 512
|
||||
#define PV_SIZEOF_CWD 4096
|
||||
#define PV_SIZEOF_LASTWRITTEN_BUFFER 256
|
||||
#define PV_SIZEOF_PREVLINE_BUFFER 1024
|
||||
#define PV_FORMAT_ARRAY_MAX 100
|
||||
#define PV_SIZEOF_FORMAT_SEGMENTS_BUF 4096
|
||||
#define PV_SIZEOF_CRS_LOCK_FILE 1024
|
||||
|
||||
#define PV_SIZEOF_FILE_FDINFO 4096
|
||||
#define PV_SIZEOF_FILE_FD 4096
|
||||
#define PV_SIZEOF_FILE_FDPATH 4096
|
||||
#define PV_SIZEOF_DISPLAY_NAME 512
|
||||
|
||||
#define PV_BARSTYLE_MAX 4 /* number of different styles allowed in a format */
|
||||
#define PV_BARSTYLE_SIZEOF_STRING 10 /* max length of a bar constituent component in bytes */
|
||||
#define PV_BARSTYLE_MAX_FILLERS 10 /* max number of bar filler strings */
|
||||
|
||||
/* Bit values for the extra displays bitmap. */
|
||||
|
||||
#define PV_DISPLAY_WINDOWTITLE 1
|
||||
#define PV_DISPLAY_PROCESSTITLE 2
|
||||
|
||||
@@ -63,6 +68,7 @@ extern "C" {
|
||||
struct pvipccursorstate_s {
|
||||
int y_topmost; /* terminal row of topmost "pv" instance */
|
||||
bool tty_tostop_added; /* whether any instance had to set TOSTOP on the terminal */
|
||||
bool tty_echoctl_cleared; /* whether any instance had to clear ECHOCTL on the terminal */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -74,6 +80,14 @@ typedef enum {
|
||||
PV_TRANSFERCOUNT_LINES
|
||||
} pvtransfercount_t;
|
||||
|
||||
/* Methods used to transfer bytes from input to output. */
|
||||
typedef enum {
|
||||
PV_TRANSFERMETHOD_READWRITE, /* read() + write() */
|
||||
PV_TRANSFERMETHOD_SPLICE, /* splice() */
|
||||
PV_TRANSFERMETHOD_SPLICE_INTERMEDIATE, /* splice() through an intermediate input pipe */
|
||||
PV_TRANSFERMETHOD_COPY_FILE_RANGE, /* copy_file_range() */
|
||||
PV_TRANSFERMETHOD__UNSET
|
||||
} pvtransfermethod_t;
|
||||
|
||||
/*
|
||||
* Structure describing a short string used as part of a progress bar, whose
|
||||
@@ -138,7 +152,7 @@ struct pvwatchfd_s;
|
||||
typedef /*@null@*/ struct pvwatchfd_s *pvwatchfd_t;
|
||||
|
||||
/* String pointer, that is the only pointer to this resource, that can be null. */
|
||||
typedef /*@only@*/ /*@null@*/ char * nullable_string_t;
|
||||
typedef /*@only@*/ /*@null@*/ char * nullable_only_string_t;
|
||||
|
||||
/*
|
||||
* Structure for holding PV internal state. Opaque outside the PV library.
|
||||
@@ -150,19 +164,23 @@ struct pvstate_s {
|
||||
* Program status *
|
||||
******************/
|
||||
struct pvprogramstatus_s {
|
||||
char cwd[PV_SIZEOF_CWD]; /* current working directory for relative path */
|
||||
nullable_only_string_t cwd; /* for relative paths in --watchfd */
|
||||
int current_input_file; /* index of current file being read */
|
||||
int exit_status; /* exit status to give (0=OK) */
|
||||
bool terminal_supports_utf8; /* whether the terminal supports UTF-8 */
|
||||
bool terminal_supports_colour; /* whether the terminal supports colour */
|
||||
bool checked_colour_support; /* whether we have checked colour support yet */
|
||||
bool current_input_is_pipe; /* whether the current input file is a pipe */
|
||||
bool current_input_is_file; /* whether the current input is a regular file */
|
||||
bool output_is_pipe; /* whether the output is a pipe */
|
||||
bool output_is_file; /* whether the output is a regular file */
|
||||
} status;
|
||||
|
||||
/***************
|
||||
* Input files *
|
||||
***************/
|
||||
struct pvinputfiles_s {
|
||||
/*@only@*/ /*@null@*/ nullable_string_t *filename; /* input filenames */
|
||||
/*@only@*/ /*@null@*/ nullable_only_string_t *filename; /* input filenames */
|
||||
unsigned int file_count; /* number of input files */
|
||||
} files;
|
||||
|
||||
@@ -196,27 +214,21 @@ struct pvstate_s {
|
||||
/*@null@*/ char *output_name; /* name of the output, for diagnostics */
|
||||
/*@null@*/ char *default_bar_style; /* which bar style to use by default */
|
||||
off_t error_skip_block; /* skip block size, 0 for adaptive */
|
||||
off_t rate_limit; /* rate limit, in bytes per second */
|
||||
size_t target_buffer_size; /* buffer size (0=default) */
|
||||
long double rate_limit; /* rate limit, in bytes per second */
|
||||
size_t target_buffer_size; /* transfer buffer size (0=default) */
|
||||
size_t pipe_buffer_size; /* pipe buffer size (0=default) */
|
||||
off_t size; /* total size of data */
|
||||
unsigned int skip_errors; /* skip read errors counter */
|
||||
int output_fd; /* fd to write output to */
|
||||
pid_t othermonitor_pid; /* pid of the other monitor, in "-M both" mode */
|
||||
int othermonitor_read_fd; /* fd to read transfer counts from other monitor */
|
||||
int othermonitor_write_fd; /* fd to write transfer counts to other monitor */
|
||||
unsigned int average_rate_window; /* time window in seconds for average rate calculations */
|
||||
unsigned int history_interval; /* seconds between each average rate calc history entry */
|
||||
pvdisplay_width_t width; /* screen width */
|
||||
unsigned int height; /* screen height */
|
||||
unsigned int extra_displays; /* bitmask of extra display destinations */
|
||||
struct { /* old-style format options (used by -R) */
|
||||
size_t lastwritten; /* --last-written (amount) */
|
||||
bool progress; /* --progress */
|
||||
bool timer; /* --timer */
|
||||
bool eta; /* --eta */
|
||||
bool fineta; /* --fineta */
|
||||
bool rate; /* --rate */
|
||||
bool average_rate; /* --average-rate */
|
||||
bool bytes; /* --bytes */
|
||||
bool bufpercent; /* --buffer-percent */
|
||||
} format_option;
|
||||
pvformatoptions_s format_option; /* non "--format" format options (used by -R) */
|
||||
bool force; /* display even if not on terminal */
|
||||
bool cursor; /* use cursor positioning */
|
||||
bool numeric; /* numeric output only */
|
||||
@@ -228,15 +240,18 @@ struct pvstate_s {
|
||||
bool null_terminated_lines; /* lines are null-terminated */
|
||||
bool no_display; /* do nothing other than pipe data */
|
||||
bool no_splice; /* never use splice() */
|
||||
bool stop_at_size; /* set if we stop at "size" bytes */
|
||||
bool sync_after_write; /* set if we sync after every write */
|
||||
bool direct_io; /* set if O_DIRECT is to be used */
|
||||
bool direct_io_changed; /* set when direct_io is changed */
|
||||
bool sparse_output; /* set if we leave holes in the output */
|
||||
bool stop_at_size; /* transfer is to stop at "size" bytes */
|
||||
bool sync_after_write; /* sync after every write */
|
||||
bool direct_io; /* use O_DIRECT */
|
||||
bool direct_io_changed; /* set when direct_io is changed mid-transfer */
|
||||
bool sparse_output; /* convert runs of null bytes into holes */
|
||||
bool discard_input; /* write nothing to stdout */
|
||||
bool show_stats; /* show statistics on exit */
|
||||
bool use_osc94; /* enable OSC 9;4 sequences */
|
||||
bool width_set_manually; /* width was set manually, not detected */
|
||||
bool height_set_manually; /* height was set manually, not detected */
|
||||
bool rate_limit_specified; /* whether a rate limit value was given */
|
||||
bool rate_limit_active; /* whether a rate limit is in effect (>0) */
|
||||
} control;
|
||||
|
||||
/*******************
|
||||
@@ -272,9 +287,11 @@ struct pvstate_s {
|
||||
*******************/
|
||||
struct pvtransientflags_s {
|
||||
volatile sig_atomic_t reparse_display; /* whether to re-check format string */
|
||||
volatile sig_atomic_t terminal_resized; /* whether we need to get term size again */
|
||||
volatile sig_atomic_t trigger_exit; /* whether we need to abort right now */
|
||||
volatile sig_atomic_t terminal_resized; /* whether terminal size needs re-reading */
|
||||
volatile sig_atomic_t trigger_exit; /* whether an immediate abort is required */
|
||||
volatile sig_atomic_t terminating_signal; /* signal number that triggered an exit */
|
||||
volatile sig_atomic_t clear_tty_tostop_on_exit; /* whether to clear tty TOSTOP on exit */
|
||||
volatile sig_atomic_t set_tty_echoctl_on_exit; /* whether to set tty ECHOCTL on exit */
|
||||
volatile sig_atomic_t suspend_stderr; /* whether writing to stderr is suspended */
|
||||
volatile sig_atomic_t skip_next_sigcont; /* whether to ignore the next SIGCONT */
|
||||
volatile sig_atomic_t pipe_closed; /* whether the output pipe was closed */
|
||||
@@ -309,21 +326,22 @@ struct pvstate_s {
|
||||
|
||||
/*@only@*/ /*@null@*/ char *display_buffer; /* buffer for display string */
|
||||
off_t initial_offset; /* offset when first opened (when watching fds) */
|
||||
size_t next_line_len; /* length of currently receiving line so far */
|
||||
size_t next_line_len; /* length of currently receiving line so far */
|
||||
|
||||
size_t format_segment_count; /* number of format string segments */
|
||||
|
||||
pvtransfercount_t count_type; /* type of count for transfer, rate, etc */
|
||||
|
||||
pvdisplay_width_t prev_screen_width; /* screen width last time we were called */
|
||||
pvdisplay_width_t prev_screen_width; /* screen width last time pv_display() was called */
|
||||
|
||||
pvdisplay_bytecount_t display_buffer_size; /* size allocated to display buffer */
|
||||
pvdisplay_bytecount_t display_string_bytes; /* byte length of string in display buffer */
|
||||
pvdisplay_width_t display_string_width; /* displayed width of string in display buffer */
|
||||
pvdisplay_bytecount_t lastwritten_bytes; /* largest number of last-written bytes to show */
|
||||
pvdisplay_bytecount_t lastwritten_bytes; /* largest number of last-written bytes to show */
|
||||
|
||||
bool showing_timer; /* set if showing timer */
|
||||
bool showing_bytes; /* set if showing byte/line count */
|
||||
bool showing_ratio; /* set if showing monitoring in:out ratio */
|
||||
bool showing_rate; /* set if showing transfer rate */
|
||||
bool showing_last_written; /* set if displaying the last few bytes written */
|
||||
bool showing_previous_line; /* set if displaying the previously output line */
|
||||
@@ -331,6 +349,7 @@ struct pvstate_s {
|
||||
bool format_uses_colour; /* set if the format string uses colours */
|
||||
bool colour_permitted; /* whether colour is permitted for this display */
|
||||
bool sgr_code_active; /* set while SGR code is active in a display line */
|
||||
bool using_osc94; /* set if the format contains an OSC 9;4 code */
|
||||
bool final_update; /* set internally on the final update */
|
||||
bool output_produced; /* set once anything written to terminal */
|
||||
|
||||
@@ -375,20 +394,20 @@ struct pvstate_s {
|
||||
* Cursor/IPC state *
|
||||
********************/
|
||||
struct pvcursorstate_s {
|
||||
char lock_file[PV_SIZEOF_CRS_LOCK_FILE];
|
||||
/*@only@*/ /*@null@*/ char *lock_file; /* terminal lock filename */
|
||||
#ifdef HAVE_IPC
|
||||
/*@keep@*/ /*@null@*/ struct pvipccursorstate_s *shared; /* data shared between instances */
|
||||
int shmid; /* ID of our shared memory segment */
|
||||
int shmid; /* ID of the shared memory segment */
|
||||
int pvcount; /* number of `pv' processes in total */
|
||||
int pvmax; /* highest number of `pv's seen */
|
||||
int y_lastread; /* last value of _y_top seen */
|
||||
int y_offset; /* our Y offset from this top position */
|
||||
int needreinit; /* counter if we need to reinit cursor pos */
|
||||
int needreinit; /* counter for reinitialising cursor position */
|
||||
#endif /* HAVE_IPC */
|
||||
int lock_fd; /* fd of lockfile, -1 if none open */
|
||||
int y_start; /* our initial Y coordinate */
|
||||
#ifdef HAVE_IPC
|
||||
bool noipc; /* set if we can't use IPC */
|
||||
bool noipc; /* set if IPC can't be used */
|
||||
#endif /* HAVE_IPC */
|
||||
bool disable; /* set if cursor positioning can't be used */
|
||||
} cursor;
|
||||
@@ -405,14 +424,14 @@ struct pvstate_s {
|
||||
* buffer_size equal to control.target_buffer_size.
|
||||
*
|
||||
* Data from the input files is read into the buffer; read_position
|
||||
* is the offset in the buffer that we've read data up to.
|
||||
* is the offset in the buffer that data has been read up to.
|
||||
*
|
||||
* Data is written to the output from the buffer, and write_position
|
||||
* is the offset in the buffer that we've written data up to. It
|
||||
* is the offset in the buffer that data has been written up to. It
|
||||
* will always be less than or equal to read_position.
|
||||
*/
|
||||
struct pvtransferstate_s {
|
||||
long double elapsed_seconds; /* how long we have been transferring data for */
|
||||
long double elapsed_seconds; /* how long the transfer has been running for */
|
||||
/*@only@*/ /*@null@*/ char *transfer_buffer; /* data transfer buffer */
|
||||
size_t buffer_size; /* size of buffer */
|
||||
size_t read_position; /* amount of data in buffer */
|
||||
@@ -427,6 +446,8 @@ struct pvstate_s {
|
||||
off_t total_written; /* total bytes or lines written */
|
||||
off_t transferred; /* amount transferred (written - unconsumed) */
|
||||
|
||||
off_t otherside_transferred; /* amount transferred by the other side ("-M both") */
|
||||
|
||||
/* Keep track of line positions to backtrack written_but_not_consumed. */
|
||||
/*@only@*/ /*@null@*/ off_t *line_positions; /* line separator write positions (circular buffer) */
|
||||
size_t line_positions_capacity; /* total size of line position array */
|
||||
@@ -435,35 +456,52 @@ struct pvstate_s {
|
||||
off_t last_output_position; /* write position last sent to output */
|
||||
|
||||
/*
|
||||
* While reading from a file descriptor we keep track of how
|
||||
* many times in a row we've seen errors
|
||||
* (read_errors_in_a_row), and whether or not we have put a
|
||||
* warning on stderr about read errors on this fd
|
||||
* While reading from a file descriptor, a count is kept of
|
||||
* how many times in a row there have been errors
|
||||
* (read_errors_in_a_row), and whether or not a warning has
|
||||
* been written to stderr about read errors on this fd
|
||||
* (read_error_warning_shown).
|
||||
*
|
||||
* Whenever the active file descriptor changes from
|
||||
* last_read_skip_fd, we reset read_errors_in_a_row to 0 and
|
||||
* read_error_warning_shown to false for the new file
|
||||
* descriptor and set last_read_skip_fd to the new fd
|
||||
* number.
|
||||
* last_read_skip_fd, the read_errors_in_a_row is reset to 0
|
||||
* and read_error_warning_shown is set to false for the new
|
||||
* file descriptor, and last_read_skip_fd is set to the new
|
||||
* fd number.
|
||||
*
|
||||
* This way, we're treating each input file separately.
|
||||
* This allows each input file to be treated separately.
|
||||
*/
|
||||
off_t read_errors_in_a_row;
|
||||
int last_read_skip_fd;
|
||||
/* read_error_warning_shown is defined below. */
|
||||
#ifdef HAVE_SPLICE
|
||||
/*
|
||||
* These variables are used to keep track of whether
|
||||
* splice() was used; splice_failed_fd is the file
|
||||
* descriptor that splice() last failed on, so that we don't
|
||||
* keep trying to use it on an fd that doesn't support it,
|
||||
* and splice_used is set to true if splice() was used this
|
||||
* time within pv_transfer().
|
||||
* File descriptors for an intermediate pipe, used when
|
||||
* neither input nor output are pipes; the size of the pipe
|
||||
* buffer; and how much input data is in the intermediate
|
||||
* pipe waiting to be passed to the output.
|
||||
*/
|
||||
int intermediate_pipe[2];
|
||||
int intermediate_pipe_buffer_size;
|
||||
int intermediate_pipe_buffer_used;
|
||||
/* File descriptor to /dev/null for splicing with -X. */
|
||||
int discard_fd;
|
||||
/*
|
||||
* splice_failed_fd is the input file descriptor that
|
||||
* splice() last failed on, to avoid continuing to try using
|
||||
* it on a file descriptor that doesn't support it.
|
||||
*/
|
||||
int splice_failed_fd;
|
||||
bool splice_used;
|
||||
#endif
|
||||
#ifdef HAVE_COPY_FILE_RANGE
|
||||
/*
|
||||
* copy_file_range_failed_fd is the input file descriptor
|
||||
* that copy_file_range() last failed on, to avoid
|
||||
* continuing to try using it on a file descriptor that
|
||||
* doesn't support it.
|
||||
*/
|
||||
int copy_file_range_failed_fd;
|
||||
#endif
|
||||
pvtransfermethod_t method; /* method used for most recent transfer */
|
||||
bool read_error_warning_shown;
|
||||
bool output_not_seekable; /* set if lseek() fails on output */
|
||||
} transfer;
|
||||
@@ -492,16 +530,16 @@ struct pvwatchfd_s {
|
||||
struct pvdisplay_s display; /* display data */
|
||||
#ifdef __APPLE__
|
||||
#else
|
||||
char file_fdinfo[PV_SIZEOF_FILE_FDINFO]; /* path to /proc fdinfo file */
|
||||
char file_fd[PV_SIZEOF_FILE_FD]; /* path to /proc fd symlink */
|
||||
nullable_string_ptr file_fdinfo; /* path to /proc fdinfo file */
|
||||
nullable_string_ptr file_fdsymlink; /* path to /proc fd symlink */
|
||||
#endif
|
||||
char file_fdpath[PV_SIZEOF_FILE_FDPATH]; /* path to file that was opened */
|
||||
nullable_string_ptr file_fdpath; /* path to file that was opened */
|
||||
/*@keep@ */ char display_name[PV_SIZEOF_DISPLAY_NAME]; /* name to show on progress bar */
|
||||
struct stat sb_fd; /* stat of fd symlink */
|
||||
struct stat sb_fd_link; /* lstat of fd symlink */
|
||||
off_t size; /* size of whole file, 0 if unknown */
|
||||
off_t position; /* position last seen at */
|
||||
struct timespec start_time; /* time we started watching the fd */
|
||||
struct timespec start_time; /* time the watch of this fd began */
|
||||
struct timespec end_time; /* time the fd was marked as closed */
|
||||
struct timespec total_stoppage_time; /* total time spent stopped */
|
||||
pid_t watch_pid; /* PID the fd belongs to */
|
||||
@@ -557,15 +595,12 @@ struct pvdisplay_component_s {
|
||||
bool dynamic; /* whether it can scale with screen size */
|
||||
};
|
||||
|
||||
void pv_error(char *, ...);
|
||||
|
||||
int pv_main_loop(pvstate_t);
|
||||
void pv_calculate_transfer_rate(pvtransfercalc_t, readonly_pvtransferstate_t, readonly_pvcontrol_t, readonly_pvdisplay_t, bool);
|
||||
|
||||
long pv_bound_long(long, long, long);
|
||||
long pv_seconds_remaining(const off_t, const off_t, const long double);
|
||||
void pv_si_prefix(long double *, char *, const long double, pvtransfercount_t);
|
||||
void pv_describe_amount(char *, size_t, char *, long double, char *, char *, pvtransfercount_t);
|
||||
void pv_describe_amount(char *, size_t, const char *, long double, char *, char *, pvtransfercount_t);
|
||||
|
||||
int8_t pv_display_barstyle_index(pvformatter_args_t, const char *);
|
||||
|
||||
@@ -595,6 +630,8 @@ pvdisplay_bytecount_t pv_formatter_segmentcontent(char *, pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_progress(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_progress_bar_only(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_progress_amount_only(pvformatter_args_t);
|
||||
size_t pv_osc94_format(char *, size_t, readonly_pvcontrol_t, readonly_pvtransfercalc_t);
|
||||
pvdisplay_bytecount_t pv_formatter_progress_conemu(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_bar_default(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_bar_plain(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_bar_block(pvformatter_args_t);
|
||||
@@ -606,15 +643,13 @@ pvdisplay_bytecount_t pv_formatter_fineta(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_rate(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_average_rate(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_bytes(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_ratio(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_buffer_percent(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_last_written(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_previous_line(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_name(pvformatter_args_t);
|
||||
pvdisplay_bytecount_t pv_formatter_sgr(pvformatter_args_t);
|
||||
|
||||
bool pv_format (pvprogramstatus_t, readonly_pvcontrol_t,
|
||||
readonly_pvtransferstate_t, readonly_pvtransfercalc_t,
|
||||
/*@null@ */ const char *, pvdisplay_t, bool, bool);
|
||||
void pv_display (pvprogramstatus_t, readonly_pvcontrol_t, pvtransientflags_t,
|
||||
readonly_pvtransferstate_t, pvtransfercalc_t,
|
||||
pvcursorstate_t, pvdisplay_t, /*@null@ */ pvdisplay_t, bool);
|
||||
@@ -628,7 +663,6 @@ void pv_reset_calc(pvtransfercalc_t);
|
||||
void pv_reset_transfer(pvtransferstate_t);
|
||||
void pv_reset_flags(pvtransientflags_t);
|
||||
void pv_reset_display(pvdisplay_t);
|
||||
void pv_reset_watchfd(pvwatchfd_t);
|
||||
void pv_freecontents_display(pvdisplay_t);
|
||||
void pv_freecontents_transfer(pvtransferstate_t);
|
||||
void pv_freecontents_calc(pvtransfercalc_t);
|
||||
@@ -651,7 +685,6 @@ void pv_sig_nopause(void);
|
||||
|
||||
bool pv_remote_check(pvstate_t);
|
||||
|
||||
int pv_watchfd_info(pvstate_t, pvwatchfd_t, bool);
|
||||
bool pv_watchfd_changed(pvwatchfd_t);
|
||||
off_t pv_watchfd_position(pvwatchfd_t);
|
||||
int pv_watchpid_scanfds(pvstate_t, pid_t, int, int *, pvwatchfd_t *);
|
||||
|
||||
+76
-28
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Functions used across the program.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -29,6 +29,7 @@ extern "C" {
|
||||
*/
|
||||
#define PV_ERROREXIT_REMOTE_OR_PID 1
|
||||
#define PV_ERROREXIT_SAF 1 /* store and forward error */
|
||||
#define PV_ERROREXIT_MONITOR 1 /* monitor mode error */
|
||||
#define PV_ERROREXIT_ACCESS 2
|
||||
#define PV_ERROREXIT_OUROBOROS 4
|
||||
#define PV_ERROREXIT_TRANSITION 8
|
||||
@@ -62,27 +63,29 @@ typedef enum {
|
||||
extern bool pv_isdigit(char);
|
||||
|
||||
/*
|
||||
* Return the given string converted to a double, for use as a time
|
||||
* Return the numeric value of a string representing a positive decimal time
|
||||
* interval.
|
||||
*/
|
||||
extern double pv_getnum_interval(const char *);
|
||||
|
||||
/*
|
||||
* Return the given string converted to an off_t, for use as a size,
|
||||
* optionally interpreting suffixes in decimal units (multiples of 1000)
|
||||
* instead of multiples of 1024.
|
||||
* Return the numeric value of a string representing a size, interpreting
|
||||
* suffixes in decimal units (multiples of 1000) instead of multiples of
|
||||
* 1024 if the second argument is true.
|
||||
*
|
||||
* Optionally also places the result in a long double.
|
||||
*/
|
||||
extern off_t pv_getnum_size(const char *, bool);
|
||||
extern off_t pv_getnum_size(const char *, bool, /*@null@ */ long double *);
|
||||
|
||||
/*
|
||||
* Return the given string converted to an unsigned integer, for use as a
|
||||
* count such as screen width.
|
||||
* Return the numeric value of a string representing a count such as screen
|
||||
* width, interpreting it the same way as pv_getnum_size().
|
||||
*/
|
||||
extern unsigned int pv_getnum_count(const char *, bool);
|
||||
|
||||
/*
|
||||
* Return true if the given string is a number of the given type. NB an
|
||||
* integer is both a valid integer and a valid double.
|
||||
* Return true if the given string is a number of the given type. Note that
|
||||
* an integer is both a valid integer and a valid double.
|
||||
*/
|
||||
extern bool pv_getnum_check(const char *, pv_numtype);
|
||||
|
||||
@@ -97,12 +100,21 @@ extern double pv_percentage(off_t, const off_t);
|
||||
* String handling wrappers.
|
||||
*/
|
||||
|
||||
/* String pointer that can be null. */
|
||||
typedef /*@null@*/ char * nullable_string_ptr;
|
||||
|
||||
/*
|
||||
* Wrapper for sprintf(), falling back to sprintf() on systems without that
|
||||
* Wrapper for snprintf(), falling back to sprintf() on systems without that
|
||||
* function.
|
||||
*/
|
||||
extern int pv_snprintf(char *, size_t, const char *, ...);
|
||||
|
||||
/*
|
||||
* Wrapper for asprintf(), providing an equivalent on systems without that
|
||||
* function.
|
||||
*/
|
||||
extern int pv_asprintf(nullable_string_ptr *, const char *, ...);
|
||||
|
||||
/*
|
||||
* Implementation of strlcat() where it is unavailable: append a string to a
|
||||
* buffer, constraining the buffer to a particular size and ensuring
|
||||
@@ -114,7 +126,7 @@ extern size_t pv_strlcat(char *, const char *, size_t);
|
||||
* Allocate and return a duplicate of a \0-terminated string, ensuring that
|
||||
* the duplicate is also \0-terminated. Returns NULL on error.
|
||||
*/
|
||||
/*@null@ */ /*@only@ */ extern char *pv_strdup(const char *);
|
||||
/*@null@ */ /*@only@ */ extern char *pv_strdup(const /*@null@ */ char *);
|
||||
|
||||
/*
|
||||
* Return a pointer to the last matching character in the buffer, or NULL if
|
||||
@@ -128,7 +140,7 @@ extern size_t pv_strlcat(char *, const char *, size_t);
|
||||
extern size_t pv_strwidth(const char *, size_t);
|
||||
|
||||
/*
|
||||
* Return true if the character is printable.
|
||||
* Return true if the character is printable 7-bit ASCII.
|
||||
*/
|
||||
extern bool pv_isprint(char);
|
||||
|
||||
@@ -144,7 +156,7 @@ extern bool pv_isprint(char);
|
||||
*/
|
||||
void pv_elapsedtime_read(struct timespec *);
|
||||
|
||||
/* Set the time in the given timespec to zero. */
|
||||
/* Set the time in the timespec to zero. */
|
||||
void pv_elapsedtime_zero(struct timespec *);
|
||||
|
||||
/* Copy the second timespec into the first. Analogous to strcpy(3). */
|
||||
@@ -159,7 +171,7 @@ int pv_elapsedtime_compare(const struct timespec *, const struct timespec *);
|
||||
/* Add the latter two timespecs and store them in the first timespec. */
|
||||
void pv_elapsedtime_add(struct timespec *, const struct timespec *, const struct timespec *);
|
||||
|
||||
/* Add a number of nanoseconds to the given timespec. */
|
||||
/* Add a number of nanoseconds to a timespec. */
|
||||
void pv_elapsedtime_add_nsec(struct timespec *, long long);
|
||||
|
||||
/* Set the first timespec to the second minus the third. */
|
||||
@@ -177,9 +189,31 @@ void pv_nanosleep(long long);
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the prefix (program name) for any PV error messages.
|
||||
* Set the error message prefix. If the new prefix is NULL, the current
|
||||
* prefix is cleared.
|
||||
*/
|
||||
extern void pv_set_error_prefix(/*@unique@ */ const char *);
|
||||
extern void pv_set_error_prefix(/*@null@ */ const char *);
|
||||
|
||||
/*
|
||||
* Output an error message. If anything has been sent to the terminal
|
||||
* already, then put a newline before the message, to avoid writing over
|
||||
* what was sent earlier.
|
||||
*/
|
||||
extern void pv_error(char *, ...);
|
||||
|
||||
/*
|
||||
* Output an error message, like pv_error(), but following the message with
|
||||
* a colon, a space, and the result of strerror(errno).
|
||||
*/
|
||||
extern void pv_perror(char *, ...);
|
||||
|
||||
/*
|
||||
* Check that a file descriptor is open on /dev/null, returning true if so.
|
||||
* Otherwise return false; if the second argument is true, reports the
|
||||
* problem with pv_error() before returning.
|
||||
*/
|
||||
extern bool pv_fd_is_dev_null(int, bool);
|
||||
|
||||
|
||||
/*
|
||||
* Create a new state structure, and return it, or 0 (NULL) on error.
|
||||
@@ -192,21 +226,31 @@ extern /*@null@*/ /*@only@*/ pvstate_t pv_state_alloc(void);
|
||||
extern void pv_state_reset(pvstate_t state);
|
||||
|
||||
/*
|
||||
* Set the formatting string, given a set of old-style formatting options.
|
||||
* Set the format options and use them to build a default formatting string.
|
||||
* The default string is used if no format string is explicitly set.
|
||||
*/
|
||||
extern void pv_state_set_format(pvstate_t state, bool progress,
|
||||
bool timer, bool eta,
|
||||
bool fineta, bool rate,
|
||||
bool average_rate, bool bytes,
|
||||
bool bufpercent,
|
||||
size_t lastwritten,
|
||||
/*@null@*/ const char *name);
|
||||
typedef struct {
|
||||
size_t lastwritten; /* --last-written (amount) */
|
||||
bool progress; /* --progress */
|
||||
bool timer; /* --timer */
|
||||
bool eta; /* --eta */
|
||||
bool fineta; /* --fineta */
|
||||
bool rate; /* --rate */
|
||||
bool average_rate; /* --average-rate */
|
||||
bool bytes; /* --bytes */
|
||||
bool bufpercent; /* --buffer-percent */
|
||||
} pvformatoptions_s;
|
||||
extern void pv_state_set_format_options(pvstate_t, pvformatoptions_s);
|
||||
|
||||
/* Append a string to the default format, and trigger a format reparse. */
|
||||
void pv_state_append_to_default_format(pvstate_t, /*@null@ */ const char *);
|
||||
|
||||
/*
|
||||
* Set the various options.
|
||||
*/
|
||||
extern void pv_state_force_set(pvstate_t, bool);
|
||||
extern void pv_state_cursor_set(pvstate_t, bool);
|
||||
extern void pv_state_use_osc94_set(pvstate_t, bool);
|
||||
extern void pv_state_show_stats_set(pvstate_t, bool);
|
||||
extern void pv_state_numeric_set(pvstate_t, bool);
|
||||
extern void pv_state_wait_set(pvstate_t, bool);
|
||||
@@ -223,9 +267,10 @@ extern void pv_state_stop_at_size_set(pvstate_t, bool);
|
||||
extern void pv_state_sync_after_write_set(pvstate_t, bool);
|
||||
extern void pv_state_direct_io_set(pvstate_t, bool);
|
||||
extern void pv_state_sparse_output_set(pvstate_t, bool);
|
||||
extern void pv_state_rate_limit_set(pvstate_t, off_t);
|
||||
extern void pv_state_rate_limit_set(pvstate_t, long double, bool, bool);
|
||||
extern void pv_state_target_buffer_size_set(pvstate_t, size_t);
|
||||
extern void pv_state_no_splice_set(pvstate_t, bool);
|
||||
extern void pv_state_pipe_buffer_size_set(pvstate_t, size_t);
|
||||
extern void pv_state_discard_input_set(pvstate_t, bool);
|
||||
extern void pv_state_size_set(pvstate_t, off_t);
|
||||
extern void pv_state_interval_set(pvstate_t, double);
|
||||
@@ -238,17 +283,20 @@ extern void pv_state_extra_display_set(pvstate_t, /*@null@*/ const char *);
|
||||
extern void pv_state_output_set(pvstate_t, int, const char *);
|
||||
extern void pv_state_average_rate_window_set(pvstate_t, unsigned int);
|
||||
extern void pv_state_set_terminal_supports_utf8(pvstate_t, bool);
|
||||
extern void pv_state_othermonitor_set(pvstate_t, pid_t, int, int);
|
||||
extern void pv_state_cancel_output_if_empty_format_string(pvstate_t);
|
||||
|
||||
extern void pv_state_inputfiles(pvstate_t, unsigned int, const char **);
|
||||
extern void pv_state_watchfds(pvstate_t, unsigned int, const pid_t *, const int *);
|
||||
|
||||
/*
|
||||
* Work out whether we are in the foreground.
|
||||
* Return true if either this is the foreground process on the terminal, or
|
||||
* if the output is not a terminal; false otherwise.
|
||||
*/
|
||||
extern bool pv_in_foreground(void);
|
||||
|
||||
/*
|
||||
* Work out the terminal size.
|
||||
* Populate *width and *height with the current terminal size.
|
||||
*/
|
||||
extern void pv_screensize(unsigned int *width, unsigned int *height);
|
||||
|
||||
|
||||
+11
-12
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Output debugging information.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -39,21 +39,21 @@ void debugging_output(const char *function, const char *file, int line, const ch
|
||||
static FILE *debugfptr = NULL;
|
||||
va_list ap;
|
||||
time_t t;
|
||||
struct tm *tm;
|
||||
const struct tm *tm;
|
||||
char tbuf[128]; /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* flawfinder note: tbuf is only written to by strftime() which
|
||||
* takes its size, and we enforce string termination.
|
||||
* takes its size, and string termination is enforced.
|
||||
*/
|
||||
|
||||
if (false == tried_open) {
|
||||
if (NULL != debug_filename) {
|
||||
debugfptr = fopen(debug_filename, "a"); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder note: caller directly controls
|
||||
* filename, the safest we can manage is to use
|
||||
* append mode.
|
||||
* flawfinder note: the caller directly controls the
|
||||
* filename, so using append mode is the safest
|
||||
* option.
|
||||
*/
|
||||
}
|
||||
tried_open = true;
|
||||
@@ -64,10 +64,9 @@ void debugging_output(const char *function, const char *file, int line, const ch
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that here we use gmtime() rather than localtime(), otherwise
|
||||
* we can get stuck in signal handlers - testing with "strace"
|
||||
* showed many cases where "pv </dev/zero | cat >/dev/null" being
|
||||
* paused and backgrounded would cause pv to be stuck in
|
||||
* Note gmtime() is used rather than localtime(). Testing with
|
||||
* "strace" showed many cases where "pv </dev/zero | cat >/dev/null"
|
||||
* being paused and backgrounded would cause pv to be stuck in
|
||||
* futex_wait() inside a pv_sig_alrm() inside a pv_sig_cont(). The
|
||||
* backtrace mentioned many time zone conversion steps, and all of
|
||||
* that goes away with gmtime().
|
||||
@@ -79,7 +78,7 @@ void debugging_output(const char *function, const char *file, int line, const ch
|
||||
if (0 == strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M:%S", tm)) {
|
||||
tbuf[0] = '\0';
|
||||
}
|
||||
tbuf[sizeof(tbuf) - 1] = '\0'; /* enforce termination */
|
||||
tbuf[sizeof(tbuf) - 1] = '\0'; /* enforce termination. */
|
||||
|
||||
(void) fprintf(debugfptr, "[%s] (%d) %s (%s:%d): ", tbuf, getpid(), function, file, line);
|
||||
|
||||
@@ -89,7 +88,7 @@ void debugging_output(const char *function, const char *file, int line, const ch
|
||||
|
||||
/*
|
||||
* flawfinder note: vfprintf format is explicitly controlled by the
|
||||
* caller of this function - no mitigation possible or desirable.
|
||||
* caller of this function - no mitigation is possible or desirable.
|
||||
*/
|
||||
|
||||
(void) fprintf(debugfptr, "\n");
|
||||
|
||||
+120
-43
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Output command-line help to stdout.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -37,9 +37,8 @@ static size_t display_width(const char *string)
|
||||
|
||||
bytes = strlen(string); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: we have already checked for NULL, and it is
|
||||
* explicitly required of the caller to provide a null-terminated
|
||||
* string.
|
||||
* flawfinder rationale: it is explicitly required of the caller to
|
||||
* provide a null-terminated string.
|
||||
*/
|
||||
|
||||
return pv_strwidth(string, bytes);
|
||||
@@ -50,97 +49,147 @@ static size_t display_width(const char *string)
|
||||
* The 7-bit ASCII version of display_word_wrap() below - does not
|
||||
* understand multi-byte characters.
|
||||
*/
|
||||
static void display_word_wrap_7bit(const char *string, size_t display_width, size_t left_margin)
|
||||
static void display_word_wrap_7bit(const char *string, size_t display_width, size_t first_line_start,
|
||||
size_t left_margin)
|
||||
{
|
||||
const char *start;
|
||||
const char *end;
|
||||
size_t wrap_at_width;
|
||||
|
||||
if (NULL == string)
|
||||
return;
|
||||
|
||||
start = string;
|
||||
wrap_at_width = display_width;
|
||||
if (wrap_at_width > first_line_start)
|
||||
wrap_at_width -= first_line_start;
|
||||
|
||||
while (strlen(start) > display_width) { /* flawfinder: ignore */
|
||||
/* Wrap lines that are too long. */
|
||||
while (strlen(start) > wrap_at_width) { /* flawfinder: ignore */
|
||||
/* flawfinder rationale: see above. */
|
||||
|
||||
end = start + display_width;
|
||||
/*
|
||||
* Find the last space before the end of the display line,
|
||||
* or if there isn't one, behave as if there was one at the
|
||||
* end of the display line.
|
||||
*/
|
||||
end = start + wrap_at_width;
|
||||
while ((end > start) && (end[0] != ' '))
|
||||
end--;
|
||||
if (end == start) {
|
||||
end = start + display_width;
|
||||
end = start + wrap_at_width;
|
||||
} else {
|
||||
end++;
|
||||
}
|
||||
/* Display the string up to that space. */
|
||||
printf("%.*s", (int) (end - start), start);
|
||||
if (end == start)
|
||||
end++;
|
||||
start = end;
|
||||
if (start[0] != '\0')
|
||||
/*
|
||||
* If there's more text left, start a new display line and
|
||||
* pad it with spaces to the left margin, and change the
|
||||
* wrap width to the display width minus the left margin.
|
||||
*/
|
||||
if (start[0] != '\0') {
|
||||
printf("\n%*s", (int) left_margin, "");
|
||||
if (display_width > left_margin) {
|
||||
wrap_at_width = display_width - left_margin;
|
||||
} else {
|
||||
wrap_at_width = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Display the remainder of the string. */
|
||||
printf("%s", start);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Output a null-terminated string to standard output, word wrapping to
|
||||
* "display_width" display character positions, and left-padding any new
|
||||
* lines after the first one with "left_margin" spaces.
|
||||
* "display_width" display character positions, assuming that the first line
|
||||
* starts with the cursor already at "first_line_start" display character
|
||||
* positions from the left, and left-padding any new lines after the first
|
||||
* one with "left_margin" spaces.
|
||||
*
|
||||
* Wide characters are handled if NLS is enabled, but if they can't be, this
|
||||
* falls back to a version which just counts bytes as characters.
|
||||
*/
|
||||
static void display_word_wrap(const char *string, size_t display_width, size_t left_margin)
|
||||
static void display_word_wrap(const char *string, size_t display_width, size_t first_line_start, size_t left_margin)
|
||||
{
|
||||
#if defined(ENABLE_NLS) && defined(HAVE_WCHAR_H)
|
||||
size_t wrap_at_width;
|
||||
size_t wide_char_count;
|
||||
size_t wide_string_buffer_size;
|
||||
wchar_t *wide_string;
|
||||
size_t start_idx, end_idx, chars_remaining;
|
||||
size_t start_idx, chars_remaining;
|
||||
|
||||
debug("[%s], display_width=%d, first_line_start=%d, left_margin=%d", string, (int) display_width,
|
||||
(int) first_line_start, (int) left_margin);
|
||||
|
||||
if (NULL == string)
|
||||
return;
|
||||
|
||||
/* Calculate how many wide characters are in the multibyte string. */
|
||||
|
||||
/*@-nullpass@ */
|
||||
/* splint note: see mbstowcs() call in pv_strwidth(). */
|
||||
wide_char_count = mbstowcs(NULL, string, 0);
|
||||
/*@+nullpass@ */
|
||||
if (wide_char_count == (size_t) -1) {
|
||||
debug("%s: %s: %s", "mbstowcs", string, strerror(errno));
|
||||
display_word_wrap_7bit(string, display_width, left_margin);
|
||||
display_word_wrap_7bit(string, display_width, first_line_start, left_margin);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a buffer in which to convert the multibyte string to a
|
||||
* wide-character string, plus one character for zero padding.
|
||||
*/
|
||||
|
||||
wide_string_buffer_size = sizeof(*wide_string) * (1 + wide_char_count);
|
||||
wide_string = malloc(wide_string_buffer_size);
|
||||
if (NULL == wide_string) {
|
||||
perror("malloc");
|
||||
display_word_wrap_7bit(string, display_width, left_margin);
|
||||
display_word_wrap_7bit(string, display_width, first_line_start, left_margin);
|
||||
return;
|
||||
}
|
||||
memset(wide_string, 0, wide_string_buffer_size);
|
||||
|
||||
/* Convert the multibyte string to a wide-character string. */
|
||||
|
||||
if (mbstowcs(wide_string, string, 1 + wide_char_count) == (size_t) -1) {
|
||||
debug("%s: %s: %s", "mbstowcs", string, strerror(errno));
|
||||
free(wide_string);
|
||||
display_word_wrap_7bit(string, display_width, left_margin);
|
||||
display_word_wrap_7bit(string, display_width, first_line_start, left_margin);
|
||||
return;
|
||||
}
|
||||
|
||||
start_idx = 0;
|
||||
wrap_at_width = display_width;
|
||||
if (wrap_at_width > first_line_start)
|
||||
wrap_at_width -= first_line_start;
|
||||
chars_remaining = wide_char_count;
|
||||
|
||||
/*@-unrecog@ *//* splint seems unable to see the prototype for wcswidth(). */
|
||||
while (chars_remaining > 0 && wcswidth(&(wide_string[start_idx]), chars_remaining) > display_width) {
|
||||
/*@+unrecog@ */
|
||||
size_t next_idx;
|
||||
/* Wrap lines that are too long. */
|
||||
|
||||
end_idx = start_idx + display_width;
|
||||
/*@-unrecog@ *//* splint doesn't see the prototype for wcswidth(). */
|
||||
while (chars_remaining > 0 && wcswidth(&(wide_string[start_idx]), chars_remaining) > (int) wrap_at_width) {
|
||||
/*@+unrecog@ */
|
||||
size_t next_idx, end_idx;
|
||||
|
||||
/*
|
||||
* Find the last space before the end of the display line,
|
||||
* or if there isn't one, behave as if there was one at the
|
||||
* end of the display line.
|
||||
*/
|
||||
|
||||
end_idx = start_idx + wrap_at_width;
|
||||
while ((end_idx > start_idx) && (!iswspace(wide_string[end_idx])))
|
||||
end_idx--;
|
||||
if (end_idx == start_idx) {
|
||||
end_idx = start_idx + display_width;
|
||||
end_idx = start_idx + wrap_at_width;
|
||||
} else {
|
||||
end_idx++;
|
||||
}
|
||||
@@ -149,12 +198,13 @@ static void display_word_wrap(const char *string, size_t display_width, size_t l
|
||||
if (end_idx == start_idx)
|
||||
next_idx++;
|
||||
|
||||
/* Display the string up to that space, a character at a time. */
|
||||
while (start_idx < end_idx && start_idx < wide_char_count) {
|
||||
char multi_byte_string[MB_CUR_MAX + 1]; /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: array is explicitly
|
||||
* flawfinder rationale: the array is explicitly
|
||||
* cleared, large enough according to the wctomb()
|
||||
* manual, and we explicitly terminate the string.
|
||||
* manual, and the string is explicitly terminated.
|
||||
*/
|
||||
memset(multi_byte_string, 0, MB_CUR_MAX + 1);
|
||||
if (wctomb(multi_byte_string, wide_string[start_idx]) >= 0) {
|
||||
@@ -165,12 +215,26 @@ static void display_word_wrap(const char *string, size_t display_width, size_t l
|
||||
}
|
||||
|
||||
start_idx = next_idx;
|
||||
if (start_idx < wide_char_count)
|
||||
/*
|
||||
* If there's more text left, start a new display line and
|
||||
* pad it with spaces to the left margin, and change the
|
||||
* wrap width to the display width minus the left margin.
|
||||
*/
|
||||
if (start_idx < wide_char_count) {
|
||||
printf("\n%*s", (int) left_margin, "");
|
||||
|
||||
chars_remaining = wide_char_count - start_idx;
|
||||
if (display_width > left_margin) {
|
||||
wrap_at_width = display_width - left_margin;
|
||||
} else {
|
||||
wrap_at_width = 1;
|
||||
}
|
||||
chars_remaining = wide_char_count - start_idx;
|
||||
} else {
|
||||
/* Explicitly set to 0 to avoid underflow. */
|
||||
chars_remaining = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Display the remainder of the string, a character at a time. */
|
||||
while (start_idx < wide_char_count) {
|
||||
char multi_byte_string[MB_CUR_MAX + 1]; /* flawfinder: ignore */
|
||||
/* flawfinder rationale as above. */
|
||||
@@ -185,7 +249,7 @@ static void display_word_wrap(const char *string, size_t display_width, size_t l
|
||||
free(wide_string);
|
||||
|
||||
#else /* ! defined(ENABLE_NLS) && defined(HAVE_WCHAR_H) */
|
||||
display_word_wrap_7bit(string, display_width, left_margin);
|
||||
display_word_wrap_7bit(string, display_width, first_line_start, left_margin);
|
||||
#endif /* defined(ENABLE_NLS) && defined(HAVE_WCHAR_H) */
|
||||
}
|
||||
|
||||
@@ -309,11 +373,14 @@ void display_help(void)
|
||||
N_("prefix visual information with NAME"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-u", "--bar-style", N_("STYLE"),
|
||||
N_("set default bar style to NAME"),
|
||||
N_("set default bar style to STYLE"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-x", "--extra-display", N_("SPEC"),
|
||||
N_("also send progress to SPEC"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-9", "--conemu", NULL,
|
||||
N_("set terminal progress state with OSC 9;4 (ConEmu)"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-v", "--stats", NULL,
|
||||
N_("output transfer statistics at the end"),
|
||||
{ 0, 0, 0, 0} },
|
||||
@@ -336,6 +403,9 @@ void display_help(void)
|
||||
{ "-C", "--no-splice", NULL,
|
||||
N_("never use splice(), always use read/write"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-J", "--pipe-buffer-size", N_("BYTES"),
|
||||
N_("set the pipe buffer size to BYTES"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-E", "--skip-errors", NULL,
|
||||
N_("skip read errors in input"),
|
||||
{ 0, 0, 0, 0} },
|
||||
@@ -372,6 +442,9 @@ void display_help(void)
|
||||
N_("show progress of process PID"),
|
||||
{ 0, 0, 0, 0} },
|
||||
#endif /* PV_REMOTE_CONTROL */
|
||||
{ "-M", "--monitor", "in|0|out|1|both|2",
|
||||
N_("run a command and monitor its standard input, output, or both"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "", NULL, NULL, NULL, { 0, 0, 0, 0} },
|
||||
{ "-P", "--pidfile", N_("FILE"),
|
||||
N_("save process ID in FILE"),
|
||||
@@ -419,11 +492,11 @@ void display_help(void)
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory leak
|
||||
* warnings, but in this case it's unavoidable, and mitigated by the
|
||||
* fact we only translate each string once.
|
||||
* fact that each string is only translated once.
|
||||
*/
|
||||
program_description = _("Concatenate FILE(s), or standard input, to standard output, with monitoring.");
|
||||
if (NULL != program_description) {
|
||||
display_word_wrap(program_description, right_margin, 0);
|
||||
display_word_wrap(program_description, right_margin, 0, 0);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@@ -433,8 +506,8 @@ void display_help(void)
|
||||
* Translate the help text, and calculate the displayed width of
|
||||
* each part of each option definition. The total display width of
|
||||
* the short option, long option, and option argument together form
|
||||
* the "option" width - we look for the widest one to calculate the
|
||||
* left margin for all of the descriptions to start at.
|
||||
* the "option" width. The widest one is used to calculate the left
|
||||
* margin for all of the descriptions to start at.
|
||||
*/
|
||||
for (option_index = 0; NULL != option_definitions[option_index].opt_short; option_index++) {
|
||||
struct option_definition_s *definition;
|
||||
@@ -478,7 +551,8 @@ void display_help(void)
|
||||
*
|
||||
* " <short>, <long> <arg> <description>"
|
||||
*
|
||||
* If we don't have getopt_long() then ", <long>" is omitted.
|
||||
* If getopt_long() is unavailable then ", <long>" is
|
||||
* omitted.
|
||||
*/
|
||||
option_width += 2 + definition->width.opt_short; /* " short" */
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
@@ -496,9 +570,12 @@ void display_help(void)
|
||||
* Set the left margin for the option descriptions, based on the
|
||||
* widest option width, or (right margin - min_description_width),
|
||||
* whichever is less, so that there is always room for
|
||||
* "min_description_width" characters of description.
|
||||
* "min_description_width" characters of description. If there's
|
||||
* not even room for that, set the left margin to 2.
|
||||
*/
|
||||
description_left_margin = right_margin - min_description_width;
|
||||
description_left_margin = 2;
|
||||
if (right_margin > (min_description_width + 2))
|
||||
description_left_margin = right_margin - min_description_width;
|
||||
if (widest_option_width < description_left_margin) {
|
||||
description_left_margin = widest_option_width;
|
||||
}
|
||||
@@ -539,18 +616,18 @@ void display_help(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* If the option is too wide, start a new line for the
|
||||
* description. In both cases, pad with spaces up to the
|
||||
* description left margin.
|
||||
* If the option (with 2 trailing spaces) is too wide, start
|
||||
* a new line for the description. Either way, pad with
|
||||
* spaces up to the description left margin.
|
||||
*/
|
||||
if (option_width > description_left_margin) {
|
||||
if ((option_width + 2) > description_left_margin) {
|
||||
printf("\n%*s", (int) description_left_margin, "");
|
||||
} else if (option_width < description_left_margin) {
|
||||
printf("%*s", (int) (description_left_margin - option_width), "");
|
||||
}
|
||||
|
||||
/* Output the description, word wrapped. */
|
||||
display_word_wrap(definition->opt_description, right_margin - description_left_margin,
|
||||
display_word_wrap(definition->opt_description, right_margin, description_left_margin,
|
||||
description_left_margin);
|
||||
|
||||
printf("\n");
|
||||
@@ -562,11 +639,11 @@ void display_help(void)
|
||||
format_sequence_header = _("Supported format sequences:");
|
||||
if (NULL != format_sequence_header) {
|
||||
printf("\n");
|
||||
display_word_wrap(format_sequence_header, right_margin, 0);
|
||||
display_word_wrap(format_sequence_header, right_margin, 0, 0);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n ");
|
||||
display_word_wrap(format_sequences, right_margin, 2);
|
||||
display_word_wrap(format_sequences, right_margin, 2, 2);
|
||||
free(format_sequences);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
+483
-80
@@ -2,7 +2,7 @@
|
||||
* Main program entry point - read the command line options, then perform
|
||||
* the appropriate actions.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#ifdef HAVE_LANGINFO_H
|
||||
#include <langinfo.h>
|
||||
#endif
|
||||
@@ -43,38 +44,37 @@ static int pv__write_pidfile(opts_t opts)
|
||||
|
||||
/*
|
||||
* The buffer needs to be long enough to hold the pidfile with the
|
||||
* mkstemp template ".XXXXXX" after it. The "%s" of our
|
||||
* pidfile_template adds 2 extra bytes to the length, of which we
|
||||
* need 1 byte for the terminating \0, so we subtract 1 byte more to
|
||||
* get the exact amount of space we need.
|
||||
* mkstemp template ".XXXXXX" after it. The "%s" of the
|
||||
* pidfile_template adds 2 extra bytes to the length, of which 1
|
||||
* byte is used for the terminating \0, so subtract 1 byte more to
|
||||
* get the exact amount of space needed.
|
||||
*/
|
||||
pidfile_tmp_bufsize = strlen(pidfile_template) + strlen(opts->pidfile) - 1; /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* flawfinder rationale: flawfinder never likes strlen() in case
|
||||
* it's called on a string that isn't \0 terminated. We have to use
|
||||
* strlen() to find the length of opts->pidfile, so have to trust
|
||||
* that the arguments in argv[] were \0 terminated. We can be sure
|
||||
* that pidfile_template is \0 terminated because we've set it to a
|
||||
* constant value. So we tell flawfinder to skip this check here.
|
||||
* flawfinder rationale: the warning is about strlen() being called
|
||||
* on a string that may not be \0 terminated. pidfile_template is a
|
||||
* constant so is always \0-terminated. opts->pidfile comes from
|
||||
* argv[] whose entries are \0-terminated.
|
||||
*/
|
||||
|
||||
pidfile_tmp_name = malloc(pidfile_tmp_bufsize);
|
||||
if (NULL == pidfile_tmp_name) {
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name, strerror(errno));
|
||||
pv_perror("%s", opts->pidfile);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
memset(pidfile_tmp_name, 0, pidfile_tmp_bufsize);
|
||||
(void) pv_snprintf(pidfile_tmp_name, pidfile_tmp_bufsize, pidfile_template, opts->pidfile);
|
||||
|
||||
/*@-type@ *//* splint doesn't like mode_t */
|
||||
/*@-type@ *//* splint doesn't like mode_t. */
|
||||
prev_umask = umask(0000); /* flawfinder: ignore */
|
||||
(void) umask(prev_umask | 0133); /* flawfinder: ignore */
|
||||
|
||||
/*@-unrecog@ *//* splint doesn't know mkstemp() */
|
||||
/*@-unrecog@ *//* splint doesn't know mkstemp(). */
|
||||
pidfile_tmp_fd = mkstemp(pidfile_tmp_name); /* flawfinder: ignore */
|
||||
/*@+unrecog@ */
|
||||
if (pidfile_tmp_fd < 0) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, pidfile_tmp_name, strerror(errno));
|
||||
pv_perror("%s", pidfile_tmp_name);
|
||||
(void) umask(prev_umask); /* flawfinder: ignore */
|
||||
free(pidfile_tmp_name);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
@@ -83,21 +83,18 @@ static int pv__write_pidfile(opts_t opts)
|
||||
(void) umask(prev_umask); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* flawfinder rationale (umask, mkstemp) - flawfinder
|
||||
* recommends setting the most restrictive umask possible
|
||||
* when calling mkstemp(), so this is what we have done.
|
||||
*
|
||||
* We get the original umask and OR it with 0133 to make
|
||||
* sure new files will be at least chmod 644. Then we put
|
||||
* the umask back to what it was, after creating the
|
||||
* temporary file.
|
||||
* flawfinder rationale (umask, mkstemp) - flawfinder recommends
|
||||
* setting the most restrictive umask possible when calling
|
||||
* mkstemp(). To do this, the original umask is ORed with 0133 to
|
||||
* ensure that new files will be chmod 644 or more restricted.
|
||||
* After creating the temporary file, the old umask is restored.
|
||||
*/
|
||||
|
||||
/*@+type@ */
|
||||
|
||||
pidfile_tmp_fptr = fdopen(pidfile_tmp_fd, "w");
|
||||
if (NULL == pidfile_tmp_fptr) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, pidfile_tmp_name, strerror(errno));
|
||||
pv_perror("%s", pidfile_tmp_name);
|
||||
(void) close(pidfile_tmp_fd);
|
||||
(void) remove(pidfile_tmp_name);
|
||||
free(pidfile_tmp_name);
|
||||
@@ -106,12 +103,14 @@ static int pv__write_pidfile(opts_t opts)
|
||||
|
||||
fprintf(pidfile_tmp_fptr, "%d\n", getpid());
|
||||
if (0 != fclose(pidfile_tmp_fptr)) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, opts->pidfile, strerror(errno));
|
||||
pv_perror("%s", pidfile_tmp_name);
|
||||
}
|
||||
|
||||
if (rename(pidfile_tmp_name, opts->pidfile) < 0) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, opts->pidfile, strerror(errno));
|
||||
pv_perror("%s", opts->pidfile);
|
||||
(void) remove(pidfile_tmp_name);
|
||||
free(pidfile_tmp_name);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
free(pidfile_tmp_name);
|
||||
@@ -131,20 +130,21 @@ static int pv__set_output(pvstate_t state, opts_t opts, /*@null@ */ const char *
|
||||
return 0;
|
||||
|
||||
if (NULL == output_file || 0 == strcmp(output_file, "-")) {
|
||||
debug("%s", "setting output to stdout");
|
||||
pv_state_output_set(state, STDOUT_FILENO, "(stdout)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug("%s: %s", "setting output", output_file);
|
||||
output_fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: the output filename has been
|
||||
* explicitly provided, and in many cases the operator will
|
||||
* want to write to device files and other special
|
||||
* destinations, so there is no sense-checking we can do to
|
||||
* make this safer.
|
||||
* flawfinder rationale: the output filename has been explicitly
|
||||
* provided, and in many cases the operator will want to write to
|
||||
* device files and other special destinations, so there is no
|
||||
* checking that could be done to make this safer.
|
||||
*/
|
||||
if (output_fd < 0) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, output_file, strerror(errno));
|
||||
pv_perror("%s", output_file);
|
||||
return PV_ERROREXIT_ACCESS;
|
||||
}
|
||||
|
||||
@@ -154,13 +154,12 @@ static int pv__set_output(pvstate_t state, opts_t opts, /*@null@ */ const char *
|
||||
|
||||
|
||||
/*
|
||||
* Run in store-and-forward mode: run the main loop once with the output
|
||||
* forced to the store-and-forward file (taking care of creation and removal
|
||||
* of a temporary file if "-" was specified); then run the main loop again
|
||||
* with the input file list forced to be just the store-and-forward file.
|
||||
* Returns nonzero on error.
|
||||
* Store-and-forward mode: run the main loop once with the output forced to
|
||||
* the store-and-forward file (creating and removing a temporary file if "-"
|
||||
* was specified); then run the main loop again with the input file list
|
||||
* forced to be just the store-and-forward file. Returns nonzero on error.
|
||||
*/
|
||||
static int pv__store_and_forward(pvstate_t state, opts_t opts, bool can_have_eta)
|
||||
static int pv__store_and_forward(pvstate_t state, opts_t opts, pvformatoptions_s format_options)
|
||||
{
|
||||
char tmp_filename[4096]; /* flawfinder: ignore */
|
||||
bool use_temporary_file;
|
||||
@@ -197,11 +196,11 @@ static int pv__store_and_forward(pvstate_t state, opts_t opts, bool can_have_eta
|
||||
*/
|
||||
|
||||
(void) pv_snprintf(tmp_filename, sizeof(tmp_filename), "%s/pv.XXXXXX", tmpdir);
|
||||
/*@-unrecog@ *//* splint doesn't know mkstemp() */
|
||||
/*@-unrecog@ *//* splint doesn't know mkstemp(). */
|
||||
tmp_fd = mkstemp(tmp_filename); /* flawfinder: ignore */
|
||||
/*@+unrecog@ */
|
||||
if (tmp_fd < 0) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, tmp_filename, strerror(errno));
|
||||
pv_perror("%s", tmp_filename);
|
||||
return PV_ERROREXIT_SAF;
|
||||
}
|
||||
(void) close(tmp_fd);
|
||||
@@ -221,11 +220,10 @@ static int pv__store_and_forward(pvstate_t state, opts_t opts, bool can_have_eta
|
||||
if (0 != retcode)
|
||||
goto end_store_and_forward;
|
||||
|
||||
/* Reset the formatting to set the displayed name to "(input)". */
|
||||
/* Set the displayed name to "(input)" and trigger a format reparse. */
|
||||
/*@-mustfreefresh@ */
|
||||
pv_state_set_format(state, opts->progress, opts->timer, can_have_eta ? opts->eta : false,
|
||||
can_have_eta ? opts->fineta : false, opts->rate, opts->average_rate,
|
||||
opts->bytes, opts->bufpercent, opts->lastwritten, _("(input)"));
|
||||
pv_state_name_set(state, _("(input)"));
|
||||
pv_state_set_format_options(state, format_options);
|
||||
/*@+mustfreefresh@ *//* see below about gettext _() calls. */
|
||||
|
||||
/* Run the main loop as normal. */
|
||||
@@ -247,10 +245,12 @@ static int pv__store_and_forward(pvstate_t state, opts_t opts, bool can_have_eta
|
||||
/* Recalculate the input size. */
|
||||
pv_state_size_set(state, pv_calc_total_size(state));
|
||||
|
||||
/* Reset the format, since we might have been asked to show ETA. */
|
||||
pv_state_set_format(state, opts->progress, opts->timer, opts->eta,
|
||||
opts->fineta, opts->rate, opts->average_rate,
|
||||
opts->bytes, opts->bufpercent, opts->lastwritten, opts->name);
|
||||
/* Set the displayed name to whatever was requested. */
|
||||
pv_state_name_set(state, opts->name);
|
||||
/* Reset the format, in case ETA was originally requested. */
|
||||
format_options.eta = opts->eta;
|
||||
format_options.fineta = opts->fineta;
|
||||
pv_state_set_format_options(state, format_options);
|
||||
|
||||
/* Reset calculated values in the state. */
|
||||
pv_state_reset(state);
|
||||
@@ -267,6 +267,381 @@ static int pv__store_and_forward(pvstate_t state, opts_t opts, bool can_have_eta
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Run the main transfer loop for the given side of monitor mode, using the
|
||||
* "command_fd" file descriptor as the transfer loop's output (on the "in"
|
||||
* side, it's a pipe to the command) or as its input (on the "out" side,
|
||||
* it's a pipe from the command).
|
||||
*
|
||||
* If both sides are active, "othermonitor_pid" is the PID of the monitor on
|
||||
* the other side, "othermonitor_read_fd" is for reading transfer progress
|
||||
* from the other monitor, and "othermonitor_write_fd" is for writing
|
||||
* transfer progress to the other monitor.
|
||||
*
|
||||
* Returns the appropriate exit status.
|
||||
*
|
||||
* As a side effect, "command_fd" is closed.
|
||||
*/
|
||||
static int pv__run_monitor(pvstate_t state, pvside_t side, int command_fd,
|
||||
pid_t othermonitor_pid, int othermonitor_read_fd, int othermonitor_write_fd, off_t size,
|
||||
pvformatoptions_s format_options)
|
||||
{
|
||||
const char *dummy_argv[1]; /* flawfinder: ignore */
|
||||
|
||||
/* flawfinder - the array length is passed along with the array. */
|
||||
|
||||
switch (side) {
|
||||
case PV_SIDE_NONE: /* fall through */
|
||||
case PV_SIDE_BOTH:
|
||||
return PV_ERROREXIT_MONITOR;
|
||||
case PV_SIDE_IN:
|
||||
/* Replace stdout with the pipe to the command. */
|
||||
debug("replacing stdout with fd %d", command_fd);
|
||||
if (dup2(command_fd, STDOUT_FILENO) < 0) {
|
||||
pv_perror("%s", "dup2");
|
||||
return PV_ERROREXIT_MONITOR;
|
||||
}
|
||||
break;
|
||||
case PV_SIDE_OUT:
|
||||
/* Replace stdin with the pipe from the command. */
|
||||
debug("replacing stdin with fd %d", command_fd);
|
||||
if (dup2(command_fd, STDIN_FILENO) < 0) {
|
||||
pv_perror("%s", "dup2");
|
||||
return PV_ERROREXIT_MONITOR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Close command_fd now it's been duplicated to the appropriate fd. */
|
||||
if (close(command_fd) < 0) {
|
||||
pv_perror("%s", "close");
|
||||
}
|
||||
|
||||
/* Copy details of the other monitor into the main state. */
|
||||
pv_state_othermonitor_set(state, othermonitor_pid, othermonitor_read_fd, othermonitor_write_fd);
|
||||
|
||||
/* Set the input files list to just "-". */
|
||||
/*@-observertrans@ */
|
||||
dummy_argv[0] = "-";
|
||||
/*@+observertrans@ */
|
||||
pv_state_inputfiles(state, 1, dummy_argv);
|
||||
|
||||
/* Calculate the size for this side. */
|
||||
if (0 == size) {
|
||||
size = pv_calc_total_size(state);
|
||||
debug("%s: %llu", "no size given - calculated", size);
|
||||
}
|
||||
|
||||
/* If the size is unknown, ETA cannot be displayed. */
|
||||
if (size < 1) {
|
||||
format_options.eta = false;
|
||||
format_options.fineta = false;
|
||||
pv_state_set_format_options(state, format_options);
|
||||
debug("%s", "size unknown - ETA disabled");
|
||||
}
|
||||
|
||||
/* Copy the calculated size into the main state. */
|
||||
pv_state_size_set(state, size);
|
||||
|
||||
/* Add ratio to the default format on the out side of a "both". */
|
||||
if ((othermonitor_pid > 0) && (PV_SIDE_OUT == side)) {
|
||||
pv_state_append_to_default_format(state, "%{ratio}");
|
||||
}
|
||||
|
||||
/* Prevent any progress output if the format was explicitly made empty. */
|
||||
pv_state_cancel_output_if_empty_format_string(state);
|
||||
|
||||
/* Run the main transfer loop. */
|
||||
return pv_main_loop(state);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Monitor mode: run a process and run the main transfer loop on its input,
|
||||
* output, or both. Returns the appropriate exit status.
|
||||
*
|
||||
* When monitoring both sides, two pipes are set up between the monitor
|
||||
* processes for each side - in to out, and out to in - for them to exchange
|
||||
* information about the transfer, so both sides can see how many bytes the
|
||||
* other side has transferred. This is what allows the in:out ratio to be
|
||||
* displayed.
|
||||
*/
|
||||
static int pv__monitor(pvstate_t state, opts_t opts, pvformatoptions_s format_options)
|
||||
{
|
||||
int pipefd_cmd_in[2]; /* pipe from the monitor to the command */
|
||||
int pipefd_cmd_out[2]; /* pipe from the command to the monitor */
|
||||
int pipefd_in_to_out[2]; /* from in monitor to out monitor */
|
||||
int pipefd_out_to_in[2]; /* from out monitor to in monitor */
|
||||
int retcode, pid_status;
|
||||
pid_t command_pid, in_monitor_pid, out_monitor_pid, waited_pid;
|
||||
|
||||
/* Arguments check. */
|
||||
if ((NULL == opts->argv) || (opts->argc < 1) || (NULL == opts->argv[0])) {
|
||||
/*@-mustfreefresh@ */
|
||||
pv_error("-M: %s", _("a command to run must be specified"));
|
||||
return PV_ERROREXIT_MONITOR;
|
||||
/*@+mustfreefresh@ *//* see below about gettext _() calls. */
|
||||
}
|
||||
|
||||
retcode = 0;
|
||||
|
||||
/*
|
||||
* Create the pipes for communicating with the command.
|
||||
*/
|
||||
|
||||
pipefd_cmd_in[0] = -1;
|
||||
pipefd_cmd_in[1] = -1;
|
||||
pipefd_cmd_out[0] = -1;
|
||||
pipefd_cmd_out[1] = -1;
|
||||
|
||||
/* Pipe for the input side of the command, if it's to be monitored. */
|
||||
if ((PV_SIDE_IN == opts->side) || (PV_SIDE_BOTH == opts->side)) {
|
||||
if (0 != pipe(pipefd_cmd_in)) {
|
||||
pv_perror("%s", "pipe");
|
||||
return PV_ERROREXIT_MONITOR;
|
||||
}
|
||||
debug("pipefd_cmd_in[]=(%d,%d)", pipefd_cmd_in[0], pipefd_cmd_in[1]);
|
||||
}
|
||||
|
||||
/* Pipe for the output side of the command, if it's to be monitored. */
|
||||
if ((PV_SIDE_OUT == opts->side) || (PV_SIDE_BOTH == opts->side)) {
|
||||
if (0 != pipe(pipefd_cmd_out)) {
|
||||
pv_perror("%s", "pipe");
|
||||
if (-1 != pipefd_cmd_in[0])
|
||||
(void) close(pipefd_cmd_in[0]);
|
||||
if (-1 != pipefd_cmd_in[1])
|
||||
(void) close(pipefd_cmd_in[1]);
|
||||
return PV_ERROREXIT_MONITOR;
|
||||
}
|
||||
debug("pipefd_cmd_out[]=(%d,%d)", pipefd_cmd_out[0], pipefd_cmd_out[1]);
|
||||
}
|
||||
|
||||
/* Common idiom to close an fd, and set it to -1, if it's open. */
|
||||
#define close_if_open(x) if (-1 != x) { \
|
||||
(void) close(x); \
|
||||
x = -1; \
|
||||
}
|
||||
|
||||
/* Create a process to run the command. */
|
||||
command_pid = (pid_t) fork();
|
||||
if (command_pid < 0) {
|
||||
pv_perror("%s", "fork");
|
||||
close_if_open(pipefd_cmd_in[0]);
|
||||
close_if_open(pipefd_cmd_in[1]);
|
||||
close_if_open(pipefd_cmd_out[0]);
|
||||
close_if_open(pipefd_cmd_out[1]);
|
||||
return PV_ERROREXIT_MONITOR;
|
||||
} else if (0 == command_pid) {
|
||||
/* Command process. */
|
||||
|
||||
/* Close the write end of the "in" pipe. */
|
||||
close_if_open(pipefd_cmd_in[1]);
|
||||
|
||||
/* Close the read end of the "out" pipe. */
|
||||
close_if_open(pipefd_cmd_out[0]);
|
||||
|
||||
/* Put the read end of the "in" pipe on stdin. */
|
||||
if (-1 != pipefd_cmd_in[0]) {
|
||||
debug("replacing command stdin with fd %d", pipefd_cmd_in[0]);
|
||||
if (dup2(pipefd_cmd_in[0], STDIN_FILENO) < 0) {
|
||||
pv_perror("%s", "dup2");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
(void) close(pipefd_cmd_in[0]);
|
||||
debug("replaced command stdin with fd %d", pipefd_cmd_in[0]);
|
||||
pipefd_cmd_in[0] = -1;
|
||||
}
|
||||
|
||||
/* Put the write end of the "out" pipe on stdout. */
|
||||
if (-1 != pipefd_cmd_out[1]) {
|
||||
debug("replacing command stdout with fd %d", pipefd_cmd_out[1]);
|
||||
if (dup2(pipefd_cmd_out[1], STDOUT_FILENO) < 0) {
|
||||
pv_perror("%s", "dup2");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
(void) close(pipefd_cmd_out[1]);
|
||||
debug("replaced command stdout with fd %d", pipefd_cmd_out[1]);
|
||||
pipefd_cmd_out[1] = -1;
|
||||
}
|
||||
|
||||
/* Execute the command. */
|
||||
(void) execvp(opts->argv[0], (char *const *) (opts->argv)); /* flawfinder: ignore */
|
||||
pv_perror("%s", "exec");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
/*
|
||||
* flawfinder recommends using a library call instead of
|
||||
* executing another program with execvp(), but that isn't
|
||||
* appropriate here, the whole purpose of monitor mode is to
|
||||
* execute a process and monitor it.
|
||||
*/
|
||||
}
|
||||
|
||||
/* Main process, not the command process. */
|
||||
|
||||
/* Close the read end of the "in" pipe. */
|
||||
close_if_open(pipefd_cmd_in[0]);
|
||||
|
||||
/* Close the write end of the "out" pipe. */
|
||||
close_if_open(pipefd_cmd_out[1]);
|
||||
|
||||
/*
|
||||
* If monitoring both input and output, create pipes for the two
|
||||
* monitors to talk to each other in both directions.
|
||||
*/
|
||||
pipefd_in_to_out[0] = -1;
|
||||
pipefd_in_to_out[1] = -1;
|
||||
pipefd_out_to_in[0] = -1;
|
||||
pipefd_out_to_in[1] = -1;
|
||||
if (PV_SIDE_BOTH == opts->side) {
|
||||
if (0 != pipe(pipefd_in_to_out)) {
|
||||
pv_perror("%s", "pipe");
|
||||
close_if_open(pipefd_cmd_in[1]);
|
||||
close_if_open(pipefd_cmd_out[0]);
|
||||
(void) kill(command_pid, SIGTERM);
|
||||
return PV_ERROREXIT_MONITOR;
|
||||
}
|
||||
debug("pipefd_in_to_out[]=(%d,%d)", pipefd_in_to_out[0], pipefd_in_to_out[1]);
|
||||
if (0 != pipe(pipefd_out_to_in)) {
|
||||
pv_perror("%s", "pipe");
|
||||
close_if_open(pipefd_in_to_out[0]);
|
||||
close_if_open(pipefd_in_to_out[1]);
|
||||
close_if_open(pipefd_cmd_in[1]);
|
||||
close_if_open(pipefd_cmd_out[0]);
|
||||
(void) kill(command_pid, SIGTERM);
|
||||
return PV_ERROREXIT_MONITOR;
|
||||
}
|
||||
debug("pipefd_out_to_in[]=(%d,%d)", pipefd_out_to_in[0], pipefd_out_to_in[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* If monitoring both input and output, create a process for
|
||||
* monitoring the output side.
|
||||
*/
|
||||
in_monitor_pid = -1;
|
||||
out_monitor_pid = -1;
|
||||
if (PV_SIDE_BOTH == opts->side) {
|
||||
in_monitor_pid = (pid_t) getpid();
|
||||
out_monitor_pid = (pid_t) fork();
|
||||
if (out_monitor_pid < 0) {
|
||||
pv_perror("%s", "fork");
|
||||
close_if_open(pipefd_in_to_out[0]);
|
||||
close_if_open(pipefd_in_to_out[1]);
|
||||
close_if_open(pipefd_out_to_in[0]);
|
||||
close_if_open(pipefd_out_to_in[1]);
|
||||
close_if_open(pipefd_cmd_in[1]);
|
||||
close_if_open(pipefd_cmd_out[0]);
|
||||
(void) kill(command_pid, SIGTERM);
|
||||
return PV_ERROREXIT_MONITOR;
|
||||
} else if (0 == out_monitor_pid) {
|
||||
/* Output side monitoring process. */
|
||||
|
||||
/* Close the write end of the command "in" pipe. */
|
||||
close_if_open(pipefd_cmd_in[1]);
|
||||
|
||||
/* Close the write end of the in-to-out pipe. */
|
||||
close_if_open(pipefd_in_to_out[1]);
|
||||
|
||||
/* Close the read end of the out-to-in pipe. */
|
||||
close_if_open(pipefd_out_to_in[0]);
|
||||
|
||||
retcode =
|
||||
pv__run_monitor(state, PV_SIDE_OUT, pipefd_cmd_out[0], in_monitor_pid,
|
||||
pipefd_in_to_out[0], pipefd_out_to_in[1], opts->size, format_options);
|
||||
|
||||
/* Close the other ends of the intra-monitor pipes. */
|
||||
close_if_open(pipefd_in_to_out[0]);
|
||||
close_if_open(pipefd_out_to_in[1]);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/* Input side monitoring process. */
|
||||
|
||||
/* Close the read end of the in-to-out pipe. */
|
||||
close_if_open(pipefd_in_to_out[0]);
|
||||
|
||||
/* Close the write end of the out-to-in pipe. */
|
||||
close_if_open(pipefd_out_to_in[1]);
|
||||
}
|
||||
|
||||
/* Monitor the remaining side. */
|
||||
|
||||
/*
|
||||
* In "both" mode, the remaining side is "in", so if two sets of
|
||||
* name and/or format options were given, switch to using the ones
|
||||
* that had been given first.
|
||||
*/
|
||||
if (PV_SIDE_BOTH == opts->side) {
|
||||
if (NULL != opts->name1) {
|
||||
pv_state_name_set(state, opts->name1);
|
||||
}
|
||||
if (NULL != opts->format1) {
|
||||
pv_state_format_string_set(state, opts->format1);
|
||||
}
|
||||
/* Trigger a format reparse. */
|
||||
pv_state_set_format_options(state, format_options);
|
||||
}
|
||||
|
||||
switch (opts->side) {
|
||||
case PV_SIDE_NONE:
|
||||
retcode = PV_ERROREXIT_MONITOR;
|
||||
break;
|
||||
case PV_SIDE_BOTH:
|
||||
case PV_SIDE_IN:
|
||||
/* Close the read end of the "out" pipe. */
|
||||
close_if_open(pipefd_cmd_out[0]);
|
||||
retcode =
|
||||
pv__run_monitor(state, PV_SIDE_IN, pipefd_cmd_in[1], out_monitor_pid,
|
||||
pipefd_out_to_in[0], pipefd_in_to_out[1], opts->size, format_options);
|
||||
break;
|
||||
case PV_SIDE_OUT:
|
||||
/* Close the write end of the "in" pipe. */
|
||||
close_if_open(pipefd_cmd_in[1]);
|
||||
retcode =
|
||||
pv__run_monitor(state, PV_SIDE_OUT, pipefd_cmd_out[0], in_monitor_pid,
|
||||
pipefd_in_to_out[0], pipefd_out_to_in[1], opts->size, format_options);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If monitoring the "in" side, close stdout to signal EOF,
|
||||
* otherwise the wait for the monitored command would wait forever.
|
||||
*/
|
||||
if (PV_SIDE_IN == opts->side || PV_SIDE_BOTH == opts->side) {
|
||||
if (close(STDOUT_FILENO) < 0) {
|
||||
pv_perror("%s", "close");
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for the monitored command to exit. */
|
||||
do {
|
||||
/*@-type@ */
|
||||
/* splint disagreement about __pid_t vs pid_t. */
|
||||
pid_status = 0;
|
||||
waited_pid = waitpid(command_pid, &pid_status, 0);
|
||||
/*@+type@ */
|
||||
} while (-1 == waited_pid && EINTR == errno);
|
||||
|
||||
/* If monitoring both sides, wait for the "out" side to exit. */
|
||||
if (PV_SIDE_BOTH == opts->side && -1 != out_monitor_pid) {
|
||||
/* Close our ends of the intra-monitor pipes. */
|
||||
close_if_open(pipefd_in_to_out[1]);
|
||||
close_if_open(pipefd_out_to_in[0]);
|
||||
/* Wait for the "out" side to exit. */
|
||||
do {
|
||||
/*@-type@ */
|
||||
/* splint disagreement about __pid_t vs pid_t. */
|
||||
pid_status = 0;
|
||||
waited_pid = waitpid(out_monitor_pid, &pid_status, 0);
|
||||
/*@+type@ */
|
||||
} while (-1 == waited_pid && EINTR == errno);
|
||||
}
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Process command-line arguments and set option flags, then call functions
|
||||
* to initialise, and finally enter the main loop.
|
||||
@@ -278,6 +653,7 @@ int main(int argc, char **argv)
|
||||
int retcode = 0;
|
||||
bool can_have_eta = true;
|
||||
bool terminal_supports_utf8 = false;
|
||||
pvformatoptions_s format_options;
|
||||
|
||||
#if ! HAVE_SETPROCTITLE
|
||||
initproctitle(argc, argv);
|
||||
@@ -289,13 +665,16 @@ int main(int argc, char **argv)
|
||||
(void) bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
(void) textdomain(PACKAGE);
|
||||
#ifdef HAVE_LANGINFO_H
|
||||
/*@-mustfreefresh@ *//* splint thinks nl_langinfo() leaks memory */
|
||||
/*@-mustfreefresh@ *//* splint thinks nl_langinfo() leaks memory. */
|
||||
if (0 == strcmp(nl_langinfo(CODESET), "UTF-8"))
|
||||
terminal_supports_utf8 = true;
|
||||
/*@+mustfreefresh@ */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Set an initial value for the error message prefix. */
|
||||
pv_set_error_prefix(argv[0]);
|
||||
|
||||
/* Parse the command line arguments. */
|
||||
opts = opts_parse(argc >= 0 ? (unsigned int) argc : 0, argv);
|
||||
if (NULL == opts) {
|
||||
@@ -310,12 +689,6 @@ int main(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the error message prefix. */
|
||||
/*@-keeptrans@ */
|
||||
pv_set_error_prefix(opts->program_name);
|
||||
/* splint - this function doesn't add an alias or release it. */
|
||||
/*@+keeptrans@ */
|
||||
|
||||
/*
|
||||
* Allocate our internal state buffer.
|
||||
*/
|
||||
@@ -325,11 +698,13 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory
|
||||
* leak warnings, but in this case it's unavoidable, and
|
||||
* mitigated by the fact we only translate each string once.
|
||||
* mitigated by the fact that each string is only translated
|
||||
* once.
|
||||
*/
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, _("state allocation failed"), strerror(errno));
|
||||
pv_perror("%s", _("memory allocation failure"));
|
||||
opts_free(opts);
|
||||
debug("%s: %d", "exiting with status", PV_ERROREXIT_MEMORY);
|
||||
pv_set_error_prefix(NULL);
|
||||
return PV_ERROREXIT_MEMORY;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
@@ -343,26 +718,31 @@ int main(int argc, char **argv)
|
||||
if (0 != pidfile_rc) {
|
||||
pv_state_free(state);
|
||||
opts_free(opts);
|
||||
pv_set_error_prefix(NULL);
|
||||
return pidfile_rc;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If no files were given, pretend "-" was given (stdin).
|
||||
* If no files were given, behave as if "-" was given (stdin).
|
||||
*/
|
||||
if (0 == opts->argc) {
|
||||
debug("%s", "no files given - adding fake argument `-'");
|
||||
if (!opts_add_file(opts, "-")) {
|
||||
pv_state_free(state);
|
||||
opts_free(opts);
|
||||
pv_set_error_prefix(NULL);
|
||||
return PV_ERROREXIT_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Put our list of input files into the PV internal state.
|
||||
* Put the list of input files into the PV internal state.
|
||||
*
|
||||
* Don't do this in monitor mode, since the rest of PV won't be
|
||||
* using the list in that case.
|
||||
*/
|
||||
if (NULL != opts->argv) {
|
||||
if ((NULL != opts->argv) && (PV_ACTION_MONITOR != opts->action)) {
|
||||
pv_state_inputfiles(state, opts->argc, (const char **) (opts->argv));
|
||||
}
|
||||
|
||||
@@ -374,8 +754,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
/*
|
||||
* If stderr is not a terminal and we're neither forcing output nor
|
||||
* outputting numerically, we will have nothing to display at all.
|
||||
* If stderr is not a terminal and neither --force nor --numeric is
|
||||
* active, there will be nothing to display at all.
|
||||
*/
|
||||
if ((0 == isatty(STDERR_FILENO))
|
||||
&& (false == opts->force)
|
||||
@@ -423,28 +803,31 @@ int main(int argc, char **argv)
|
||||
opts->interval = 600;
|
||||
|
||||
/*
|
||||
* Set output file, treating no output or "-" as stdout; we have to
|
||||
* do this before looking at setting the size, as the size
|
||||
* Set the output file, treating no output or "-" as stdout. This
|
||||
* must be done before trying to set the size, as the size
|
||||
* calculation looks at the output file if the input size can't be
|
||||
* calculated (issue #91).
|
||||
*
|
||||
* We have to set the sparse output flag before doing this, so that
|
||||
* in sparse mode the lseek() on O_APPEND can be done (issue #45);
|
||||
* see the comments in pv_state_output_set() in src/pv/state.c.
|
||||
* The sparse output flag before doing this, so that in sparse mode
|
||||
* the lseek() on O_APPEND can be done (issue #45); see the comments
|
||||
* in pv_state_output_set() in src/pv/state.c.
|
||||
*/
|
||||
pv_state_sparse_output_set(state, opts->sparse_output);
|
||||
retcode = pv__set_output(state, opts, opts->output);
|
||||
if (0 != retcode) {
|
||||
pv_state_free(state);
|
||||
opts_free(opts);
|
||||
pv_set_error_prefix(NULL);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the "stop at size" option before checking the total size,
|
||||
* since calculating the size from the output block device size
|
||||
* after this may want to force this setting on, and if we set it
|
||||
* afterwards, we undo the override.
|
||||
* Copy the "stop at size" option into the main state before
|
||||
* checking the total size. If pv_calc_total_size() finds that the
|
||||
* output is a block device, it will use the size of the block
|
||||
* device, and also set the stop-at-size flag. So
|
||||
* pv_state_stop_at_size_set() must be called before
|
||||
* pv_calc_total_size(), otherwise it would undo that override.
|
||||
*/
|
||||
pv_state_stop_at_size_set(state, opts->stop_at_size);
|
||||
|
||||
@@ -461,7 +844,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
/*
|
||||
* If the size is unknown, we cannot have an ETA.
|
||||
* If the size is unknown, ETA cannot be shown.
|
||||
*/
|
||||
if (opts->size < 1) {
|
||||
can_have_eta = false;
|
||||
@@ -475,8 +858,8 @@ int main(int argc, char **argv)
|
||||
/*
|
||||
* Get the total size, in query mode.
|
||||
*
|
||||
* Note that this uses signals, so signal handling has to have been
|
||||
* set up first.
|
||||
* Since pv_remote_transferstate_fetch() uses signals, signal
|
||||
* handling has to have been set up first.
|
||||
*/
|
||||
if (PV_ACTION_QUERY == opts->action) {
|
||||
opts->size = 0;
|
||||
@@ -485,6 +868,7 @@ int main(int argc, char **argv)
|
||||
pv_sig_fini(state);
|
||||
pv_state_free(state);
|
||||
opts_free(opts);
|
||||
pv_set_error_prefix(NULL);
|
||||
return retcode;
|
||||
}
|
||||
/* As above - no ETA if the size is unknown. */
|
||||
@@ -505,6 +889,7 @@ int main(int argc, char **argv)
|
||||
pv_state_no_display_set(state, opts->no_display);
|
||||
pv_state_force_set(state, opts->force);
|
||||
pv_state_cursor_set(state, opts->cursor);
|
||||
pv_state_use_osc94_set(state, opts->use_osc94);
|
||||
pv_state_show_stats_set(state, opts->show_stats);
|
||||
pv_state_numeric_set(state, opts->numeric);
|
||||
pv_state_wait_set(state, opts->wait);
|
||||
@@ -519,9 +904,10 @@ int main(int argc, char **argv)
|
||||
pv_state_sync_after_write_set(state, opts->sync_after_write);
|
||||
pv_state_direct_io_set(state, opts->direct_io);
|
||||
pv_state_discard_input_set(state, opts->discard_input);
|
||||
pv_state_rate_limit_set(state, opts->rate_limit);
|
||||
pv_state_rate_limit_set(state, opts->rate_limit, opts->rate_limit_specified, opts->rate_limit_active);
|
||||
pv_state_target_buffer_size_set(state, opts->buffer_size);
|
||||
pv_state_no_splice_set(state, opts->no_splice);
|
||||
pv_state_pipe_buffer_size_set(state, opts->pipe_buffer_size);
|
||||
pv_state_size_set(state, opts->size);
|
||||
pv_state_name_set(state, opts->name);
|
||||
pv_state_default_bar_style_set(state, opts->default_bar_style);
|
||||
@@ -529,9 +915,17 @@ int main(int argc, char **argv)
|
||||
pv_state_extra_display_set(state, opts->extra_display);
|
||||
pv_state_average_rate_window_set(state, opts->average_rate_window);
|
||||
|
||||
pv_state_set_format(state, opts->progress, opts->timer, can_have_eta ? opts->eta : false,
|
||||
can_have_eta ? opts->fineta : false, opts->rate, opts->average_rate,
|
||||
opts->bytes, opts->bufpercent, opts->lastwritten, opts->name);
|
||||
format_options.progress = opts->progress;
|
||||
format_options.timer = opts->timer;
|
||||
format_options.eta = can_have_eta ? opts->eta : false;
|
||||
format_options.fineta = can_have_eta ? opts->fineta : false;
|
||||
format_options.rate = opts->rate;
|
||||
format_options.average_rate = opts->average_rate;
|
||||
format_options.bytes = opts->bytes;
|
||||
format_options.bufpercent = opts->bufpercent;
|
||||
format_options.lastwritten = opts->lastwritten;
|
||||
|
||||
pv_state_set_format_options(state, format_options);
|
||||
|
||||
debug("%s: %s", "terminal_supports_utf8", terminal_supports_utf8 ? "true" : "false");
|
||||
pv_state_set_terminal_supports_utf8(state, terminal_supports_utf8);
|
||||
@@ -542,11 +936,13 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
case PV_ACTION_TRANSFER:
|
||||
/* Normal "transfer data" mode. */
|
||||
pv_state_cancel_output_if_empty_format_string(state);
|
||||
retcode = pv_main_loop(state);
|
||||
break;
|
||||
case PV_ACTION_STORE_AND_FORWARD:
|
||||
/* Store-and-forward transfer mode. */
|
||||
retcode = pv__store_and_forward(state, opts, can_have_eta);
|
||||
pv_state_cancel_output_if_empty_format_string(state);
|
||||
retcode = pv__store_and_forward(state, opts, format_options);
|
||||
break;
|
||||
case PV_ACTION_WATCHFD:
|
||||
/* "Watch file descriptor(s) of another process" mode. */
|
||||
@@ -560,12 +956,16 @@ int main(int argc, char **argv)
|
||||
/* Query the progress of another running pv. */
|
||||
retcode = pv_query_loop(state, opts->query);
|
||||
break;
|
||||
case PV_ACTION_MONITOR:
|
||||
/* Run a process and monitor its input and output. */
|
||||
retcode = pv__monitor(state, opts, format_options);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Clear up the PID file, if one was written. */
|
||||
if (opts->pidfile != NULL) {
|
||||
if (0 != remove(opts->pidfile)) {
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, opts->pidfile, strerror(errno));
|
||||
pv_perror("%s", opts->pidfile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,6 +978,9 @@ int main(int argc, char **argv)
|
||||
/* Free the data from parsing the command-line arguments. */
|
||||
opts_free(opts);
|
||||
|
||||
/* Clear the error message prefix. */
|
||||
pv_set_error_prefix(NULL);
|
||||
|
||||
debug("%s: %d", "exiting with status", retcode);
|
||||
|
||||
return retcode;
|
||||
|
||||
+346
-176
File diff suppressed because it is too large
Load Diff
+7
-7
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Output version information to stdout.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -18,16 +18,16 @@ void display_version(void)
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory leak
|
||||
* warnings, but in this case it's unavoidable, and mitigated by the
|
||||
* fact we only translate each string once.
|
||||
* fact that each string is only translated once.
|
||||
*/
|
||||
/* GNU standard first line format: program and version only */
|
||||
/* GNU standard first line format: program and version only. */
|
||||
printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
|
||||
/* GNU standard second line format - "Copyright" always in English */
|
||||
printf("Copyright %s %s\n", "2025", "Andrew Wood");
|
||||
/* GNU standard license line and free software notice */
|
||||
/* GNU standard second line format - "Copyright" always in English. */
|
||||
printf("Copyright %s %s\n", "2026", "Andrew Wood");
|
||||
/* GNU standard license line and free software notice. */
|
||||
printf("%s\n", _("License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"));
|
||||
printf("%s\n", _("This is free software: you are free to change and redistribute it."));
|
||||
printf("%s\n", _("There is NO WARRANTY, to the extent permitted by law."));
|
||||
/* Project web site link */
|
||||
/* Project web site link. */
|
||||
printf("\n%s: <%s>\n", _("Project web site"), PACKAGE_URL);
|
||||
}
|
||||
|
||||
+15
-17
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Functions for updating the calculated state of the transfer.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -14,8 +14,10 @@
|
||||
/*
|
||||
* Update the current average rate, using a ring buffer of past transfer
|
||||
* positions - if this is the first entry, use the provided instantaneous
|
||||
* rate, otherwise calulate the average rate from the difference between the
|
||||
* current position + elapsed time pair, and the oldest pair in the buffer.
|
||||
* rate, otherwise calculate the average rate from the difference between
|
||||
* the current position + elapsed time pair, and the oldest pair in the
|
||||
* buffer. The current elapsed time and amount transferred (both from
|
||||
* "transfer") are added to the buffer.
|
||||
*/
|
||||
static void pv__update_average_rate_history(pvtransfercalc_t calc, readonly_pvtransferstate_t transfer,
|
||||
unsigned int history_interval, long double rate)
|
||||
@@ -38,7 +40,7 @@ static void pv__update_average_rate_history(pvtransfercalc_t calc, readonly_pvtr
|
||||
return;
|
||||
|
||||
/*
|
||||
* If this is not the first call, add a new entry to the circular
|
||||
* If this is not the first call, add a new entry to the ring
|
||||
* buffer.
|
||||
*/
|
||||
if (last_elapsed > 0.0) {
|
||||
@@ -101,8 +103,8 @@ void pv_calculate_transfer_rate(pvtransfercalc_t calc, readonly_pvtransferstate_
|
||||
}
|
||||
|
||||
/*
|
||||
* In case the time since the last update is very small, we keep
|
||||
* track of amount transferred since the last update, and just keep
|
||||
* When the time since the last update is very small, keep track of
|
||||
* the amount transferred since the last update, and just keep
|
||||
* adding to that until a reasonable amount of time has passed to
|
||||
* avoid rate spikes or division by zero.
|
||||
*/
|
||||
@@ -119,9 +121,6 @@ void pv_calculate_transfer_rate(pvtransfercalc_t calc, readonly_pvtransferstate_
|
||||
calc->prev_elapsed_sec = transfer->elapsed_seconds;
|
||||
calc->prev_trans = 0;
|
||||
|
||||
if (control->bits)
|
||||
measured_rate = 8.0 * measured_rate;
|
||||
|
||||
if ((calc->measurements_taken < 1) || (measured_rate < calc->rate_min)) {
|
||||
calc->rate_min = measured_rate;
|
||||
}
|
||||
@@ -134,12 +133,12 @@ void pv_calculate_transfer_rate(pvtransfercalc_t calc, readonly_pvtransferstate_
|
||||
}
|
||||
calc->prev_rate = transfer_rate;
|
||||
|
||||
/* Update history and current average rate for ETA. */
|
||||
/* Update the history and current average rate. */
|
||||
pv__update_average_rate_history(calc, transfer, control->history_interval, transfer_rate);
|
||||
average_rate = calc->current_avg_rate;
|
||||
|
||||
/*
|
||||
* If this is the final update at the end of the transfer, we
|
||||
* If this is the final update at the end of the transfer,
|
||||
* recalculate the rate - and the average rate - across the whole
|
||||
* period of the transfer.
|
||||
*/
|
||||
@@ -159,12 +158,11 @@ void pv_calculate_transfer_rate(pvtransfercalc_t calc, readonly_pvtransferstate_
|
||||
|
||||
if (control->size <= 0) {
|
||||
/*
|
||||
* If we don't know the total size of the incoming data,
|
||||
* then for a percentage, we gradually increase the
|
||||
* percentage completion as data arrives, to a maximum of
|
||||
* 200, then reset it - we use this if we can't calculate
|
||||
* it, so that the numeric percentage output will go
|
||||
* 0%-100%, 100%-0%, 0%-100%, and so on.
|
||||
* If the total size of the incoming data is unknown, then
|
||||
* for a percentage, gradually increase the percentage
|
||||
* completion as data arrives, to a maximum of 200, then
|
||||
* reset it. This means that the numeric percentage output
|
||||
* will go 0%-100%, 100%-0%, 0%-100%, and so on.
|
||||
*/
|
||||
if (transfer_rate > 0)
|
||||
calc->percentage += 2;
|
||||
|
||||
+166
-69
@@ -7,10 +7,10 @@
|
||||
* first `pv' process.
|
||||
*
|
||||
* However, some OSes (FreeBSD and MacOS X so far) don't allow locking of a
|
||||
* terminal, so we try to use a lockfile if terminal locking doesn't work,
|
||||
* and finally abort if even that is unavailable.
|
||||
* terminal - so if terminal locking doesn't work, a separate lock file is
|
||||
* used, and cursor positioning is abandoned if that also fails.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -44,7 +44,14 @@
|
||||
|
||||
|
||||
/*
|
||||
* Create a per-euid, per-tty, lockfile in ${TMPDIR:-${TMP:-/tmp}} for the
|
||||
* Flag to allow reporting of "interrupted by signal" errors - cleared in
|
||||
* secondary instances in a pipeline, so that only one will report them.
|
||||
*/
|
||||
static bool pv__allow_signal_interrupt_reporting = true;
|
||||
|
||||
|
||||
/*
|
||||
* Create a per-euid, per-tty, lock file in ${TMPDIR:-${TMP:-/tmp}} for the
|
||||
* tty on the given file descriptor.
|
||||
*/
|
||||
static void pv_crs_open_lockfile(pvcursorstate_t cursor, readonly_pvcontrol_t control, int fd)
|
||||
@@ -55,14 +62,25 @@ static void pv_crs_open_lockfile(pvcursorstate_t cursor, readonly_pvcontrol_t co
|
||||
|
||||
cursor->lock_fd = -1;
|
||||
|
||||
ttydev = ttyname(fd);
|
||||
if (!ttydev) {
|
||||
/*
|
||||
* Note that a copy is made of result of ttyname(), so it's not in a
|
||||
* static buffer, because basename() may modify it.
|
||||
*/
|
||||
|
||||
ttydev = pv_strdup(ttyname(fd));
|
||||
if (NULL == ttydev) {
|
||||
if (!control->force) {
|
||||
pv_error("%s: %s", _("failed to get terminal name"), strerror(errno));
|
||||
/*
|
||||
* Error not translated as this should never be
|
||||
* reached, since ttyname() will have been called
|
||||
* earlier, and if it failed, cursor positioning
|
||||
* would have been turned off.
|
||||
*/
|
||||
pv_perror("%s", "ttyname");
|
||||
}
|
||||
/*
|
||||
* If we don't know our terminal name, we can neither do IPC
|
||||
* nor make a lock file, so turn off cursor positioning.
|
||||
* If the terminal name is unknown, then neither IPC nor a
|
||||
* lock file are feasible, so turn off cursor positioning.
|
||||
*/
|
||||
cursor->disable = true;
|
||||
debug("%s", "ttyname failed - cursor positioning disabled");
|
||||
@@ -80,9 +98,20 @@ static void pv_crs_open_lockfile(pvcursorstate_t cursor, readonly_pvcontrol_t co
|
||||
* $TMP are rejected, and the destination buffer is bounded.
|
||||
*/
|
||||
|
||||
memset(cursor->lock_file, 0, PV_SIZEOF_CRS_LOCK_FILE);
|
||||
(void) pv_snprintf(cursor->lock_file,
|
||||
PV_SIZEOF_CRS_LOCK_FILE, "%s/pv-%s-%i.lock", tmpdir, basename(ttydev), (int) geteuid());
|
||||
if (NULL != cursor->lock_file) {
|
||||
free(cursor->lock_file);
|
||||
cursor->lock_file = NULL;
|
||||
}
|
||||
(void) pv_asprintf(&(cursor->lock_file), "%s/pv-%s-%i.lock", tmpdir, basename(ttydev), (int) geteuid());
|
||||
|
||||
if (NULL == cursor->lock_file) {
|
||||
pv_perror("%s: %s", ttydev, _("failed to open lock file"));
|
||||
free(ttydev);
|
||||
cursor->disable = true;
|
||||
return;
|
||||
}
|
||||
|
||||
free(ttydev);
|
||||
|
||||
/*
|
||||
* Pawel Piatek - not everyone has O_NOFOLLOW, e.g. AIX doesn't.
|
||||
@@ -96,14 +125,14 @@ static void pv_crs_open_lockfile(pvcursorstate_t cursor, readonly_pvcontrol_t co
|
||||
cursor->lock_fd = open(cursor->lock_file, openflags, 0600); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* flawfinder rationale: we aren't truncating the lock file, we
|
||||
* don't change its contents, and we are attempting to use
|
||||
* O_NOFOLLOW where possible to avoid symlink attacks, so this
|
||||
* open() is as safe as we can make it.
|
||||
* flawfinder rationale: the file isn't being truncated and its
|
||||
* contents won't be changed, and O_NOFOLLOW will be used if
|
||||
* available (to avoid symlink attacks), so this open() has been made
|
||||
* as safe as possible.
|
||||
*/
|
||||
|
||||
if (cursor->lock_fd < 0) {
|
||||
pv_error("%s: %s: %s", cursor->lock_file, _("failed to open lock file"), strerror(errno));
|
||||
pv_perror("%s: %s", cursor->lock_file, _("failed to open lock file"));
|
||||
cursor->disable = true;
|
||||
return;
|
||||
}
|
||||
@@ -112,7 +141,7 @@ static void pv_crs_open_lockfile(pvcursorstate_t cursor, readonly_pvcontrol_t co
|
||||
|
||||
/*
|
||||
* Lock the terminal on the given file descriptor, falling back to using a
|
||||
* lockfile if the terminal itself cannot be locked.
|
||||
* lock file if the terminal itself cannot be locked.
|
||||
*/
|
||||
static void pv_crs_lock(pvcursorstate_t cursor, readonly_pvcontrol_t control, int fd)
|
||||
{
|
||||
@@ -136,14 +165,15 @@ static void pv_crs_lock(pvcursorstate_t cursor, readonly_pvcontrol_t control, in
|
||||
lock_fd = cursor->lock_fd;
|
||||
}
|
||||
} else {
|
||||
pv_error("%s: %s", _("lock attempt failed"), strerror(errno));
|
||||
pv_perror("%s", NULL == cursor->lock_file ? "(tty)" : cursor->lock_file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cursor->lock_fd >= 0) {
|
||||
debug("%s: %s", cursor->lock_file, "terminal lockfile acquired");
|
||||
debug("%s: %s", NULL == cursor->lock_file ? "(null)" : cursor->lock_file,
|
||||
"terminal lock file acquired");
|
||||
} else {
|
||||
debug("%s", "terminal lock acquired");
|
||||
}
|
||||
@@ -152,7 +182,7 @@ static void pv_crs_lock(pvcursorstate_t cursor, readonly_pvcontrol_t control, in
|
||||
|
||||
/*
|
||||
* Unlock the terminal on the given file descriptor. If pv_crs_lock used
|
||||
* lockfile locking, unlock the lockfile.
|
||||
* lock file locking, unlock the lock file.
|
||||
*/
|
||||
static void pv_crs_unlock(pvcursorstate_t cursor, int fd)
|
||||
{
|
||||
@@ -171,7 +201,8 @@ static void pv_crs_unlock(pvcursorstate_t cursor, int fd)
|
||||
(void) fcntl(lock_fd, F_SETLK, &lock);
|
||||
|
||||
if (cursor->lock_fd >= 0) {
|
||||
debug("%s: %s", cursor->lock_file, "terminal lockfile released");
|
||||
debug("%s: %s", NULL == cursor->lock_file ? "(null)" : cursor->lock_file,
|
||||
"terminal lock file released");
|
||||
} else {
|
||||
debug("%s", "terminal lock released");
|
||||
}
|
||||
@@ -182,8 +213,8 @@ static void pv_crs_unlock(pvcursorstate_t cursor, int fd)
|
||||
/*
|
||||
* Get the current number of processes attached to our shared memory
|
||||
* segment, i.e. find out how many `pv' processes in total are running in
|
||||
* cursor mode (including us), and store it in pv_crs_pvcount. If this is
|
||||
* larger than pv_crs_pvmax, update pv_crs_pvmax.
|
||||
* cursor mode (including this process), and store it in pv_crs_pvcount. If
|
||||
* this is larger than pv_crs_pvmax, update pv_crs_pvmax.
|
||||
*/
|
||||
static void pv_crs_ipccount(pvcursorstate_t cursor)
|
||||
{
|
||||
@@ -239,7 +270,7 @@ static int pv_crs_get_ypos(int terminalfd)
|
||||
memset(cpr, 0, sizeof(cpr));
|
||||
|
||||
#ifdef CURSOR_ANSWERBACK_BYTE_BY_BYTE
|
||||
/* Read answerback byte by byte - fails on AIX */
|
||||
/* Read answerback byte by byte - fails on AIX. */
|
||||
for (got = 0, r = 0; got < (int) (sizeof(cpr) - 2); got += r) {
|
||||
r = read(terminalfd, cpr + got, 1); /* flawfinder: ignore */
|
||||
/* flawfinder rationale: bounded to buffer size by "for" */
|
||||
@@ -256,9 +287,9 @@ static int pv_crs_get_ypos(int terminalfd)
|
||||
terminalfd, got, cpr[0], cpr[1], cpr[2], cpr[3], cpr[4], cpr[5]);
|
||||
|
||||
#else /* !CURSOR_ANSWERBACK_BYTE_BY_BYTE */
|
||||
/* Read answerback in one big lump - may fail on Solaris */
|
||||
/* Read answerback in one big lump - may fail on Solaris. */
|
||||
r = read(terminalfd, cpr, sizeof(cpr) - 2); /* flawfinder: ignore */
|
||||
/* flawfinder rationale: bounded to buffer size */
|
||||
/* flawfinder rationale: bounded to buffer size. */
|
||||
if (r <= 0) {
|
||||
debug("r=%d: %s", r, strerror(errno));
|
||||
} else {
|
||||
@@ -285,23 +316,24 @@ static int pv_crs_get_ypos(int terminalfd)
|
||||
/*
|
||||
* Initialise the IPC data, returning nonzero on error.
|
||||
*
|
||||
* To do this, we attach to the shared memory segment (creating it if it
|
||||
* does not exist). If we are the only process attached to it, then we
|
||||
* initialise it with the current cursor position.
|
||||
* Attaches to the shared memory segment (creating it if it does not exist).
|
||||
* If this is the only process attached to it, then the memory is
|
||||
* initialised with the current cursor position.
|
||||
*
|
||||
* There is a race condition here: another process could attach before we've
|
||||
* had a chance to check, such that no process ends up getting an "attach
|
||||
* count" of one, and so no initialisation occurs. So, we lock the terminal
|
||||
* with pv_crs_lock() while we are attaching and checking.
|
||||
* To avoid a race condition, this function locks the terminal with
|
||||
* pv_crs_lock() while attaching and checking. The race condition is that
|
||||
* another process could attach before this one checks, such that no process
|
||||
* ends up getting an "attach count" of one, and so no initialisation
|
||||
* occurs.
|
||||
*/
|
||||
static int pv_crs_ipcinit(pvcursorstate_t cursor, readonly_pvcontrol_t control, char *ttyfile, int terminalfd)
|
||||
{
|
||||
key_t key;
|
||||
|
||||
/*
|
||||
* Base the key for the shared memory segment on our current tty, so
|
||||
* we don't end up interfering in any way with instances of `pv'
|
||||
* running on another terminal.
|
||||
* Base the key for the shared memory segment on the current tty, to
|
||||
* avoid interfering in any way with instances of `pv' running on
|
||||
* another terminal.
|
||||
*/
|
||||
key = ftok(ttyfile, (int) 'p');
|
||||
if (-1 == key) {
|
||||
@@ -323,15 +355,15 @@ static int pv_crs_ipcinit(pvcursorstate_t cursor, readonly_pvcontrol_t control,
|
||||
}
|
||||
|
||||
/*@-nullpass@ */
|
||||
/* splint doesn't know shmaddr can be NULL */
|
||||
/* splint doesn't know shmaddr can be NULL. */
|
||||
cursor->shared = shmat(cursor->shmid, NULL, 0);
|
||||
/*@+nullpass@ */
|
||||
|
||||
pv_crs_ipccount(cursor);
|
||||
|
||||
/*
|
||||
* If nobody else is attached to the shared memory segment, we're
|
||||
* the first, so we need to initialise the shared memory with our
|
||||
* If no other process is attached to the shared memory segment,
|
||||
* this one is the first, so initialise the shared memory with the
|
||||
* current Y cursor co-ordinate and with an initial false value for
|
||||
* the TOSTOP-added flag.
|
||||
*/
|
||||
@@ -341,6 +373,14 @@ static int pv_crs_ipcinit(pvcursorstate_t cursor, readonly_pvcontrol_t control,
|
||||
cursor->shared->tty_tostop_added = false;
|
||||
cursor->y_lastread = cursor->y_start;
|
||||
debug("%s", "we are the first to attach");
|
||||
} else {
|
||||
/*
|
||||
* Another process was first, so prevent the current
|
||||
* instance from reporting "interrupted by signal" errors
|
||||
* since the first one will do that.
|
||||
*/
|
||||
debug("%s", "not the first to attach - clearing pv__allow_signal_interrupt_reporting");
|
||||
pv__allow_signal_interrupt_reporting = false;
|
||||
}
|
||||
|
||||
cursor->y_offset = cursor->pvcount - 1;
|
||||
@@ -348,8 +388,8 @@ static int pv_crs_ipcinit(pvcursorstate_t cursor, readonly_pvcontrol_t control,
|
||||
cursor->y_offset = 0;
|
||||
|
||||
/*
|
||||
* If anyone else had attached to the shared memory segment, we need
|
||||
* to read the top Y co-ordinate from it.
|
||||
* If any other process had attached to the shared memory segment
|
||||
* already, read the top Y co-ordinate from it.
|
||||
*/
|
||||
if (cursor->pvcount > 1) {
|
||||
cursor->y_start = cursor->shared->y_topmost;
|
||||
@@ -373,7 +413,10 @@ void pv_crs_init(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtransie
|
||||
int terminalfd;
|
||||
|
||||
cursor->lock_fd = -2;
|
||||
cursor->lock_file[0] = '\0';
|
||||
if (NULL != cursor->lock_file) {
|
||||
free(cursor->lock_file);
|
||||
cursor->lock_file = NULL;
|
||||
}
|
||||
|
||||
if ((!control->cursor) || (cursor->disable))
|
||||
return;
|
||||
@@ -390,14 +433,14 @@ void pv_crs_init(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtransie
|
||||
terminalfd = open(ttyfile, O_RDWR); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* flawfinder rationale: the file we open won't be truncated but
|
||||
* could be corrupted by writes attempting to get the current Y
|
||||
* position; but we get the filename from ttyname() and it could be
|
||||
* a symbolic link, so we can't do much more than trust it.
|
||||
* flawfinder rationale: the file won't be truncated but could be
|
||||
* corrupted by writes attempting to get the current Y position; but
|
||||
* the filename is from ttyname() and it could be a symbolic link,
|
||||
* so O_NOFOLLOW isn't feasible and it has to be trusted as-is.
|
||||
*/
|
||||
|
||||
if (terminalfd < 0) {
|
||||
pv_error("%s: %s: %s", _("failed to open terminal"), ttyfile, strerror(errno));
|
||||
pv_perror("%s", ttyfile);
|
||||
cursor->disable = true;
|
||||
return;
|
||||
}
|
||||
@@ -408,18 +451,30 @@ void pv_crs_init(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtransie
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have already set the terminal TOSTOP attribute, set the
|
||||
* flag in shared memory to let the other instances know.
|
||||
* If the terminal TOSTOP attribute was already set by this process,
|
||||
* set the flag in shared memory to let the other instances know.
|
||||
*/
|
||||
if ((!cursor->noipc) && (1 == flags->clear_tty_tostop_on_exit) && (NULL != cursor->shared)) {
|
||||
debug("%s", "propagating local clear_tty_tostop_on_exit true value to shared tty_tostop_added flag");
|
||||
cursor->shared->tty_tostop_added = true;
|
||||
}
|
||||
|
||||
#ifdef ECHOCTL
|
||||
/*
|
||||
* If we are not using IPC, then we need to get the current Y
|
||||
* co-ordinate. If we are using IPC, then the pv_crs_ipcinit()
|
||||
* function takes care of this in a more multi-process-friendly way.
|
||||
* If the terminal ECHOCTL attribute was already cleared by this
|
||||
* process, set the flag in shared memory to let the other instances
|
||||
* know.
|
||||
*/
|
||||
if ((!cursor->noipc) && (1 == flags->set_tty_echoctl_on_exit) && (NULL != cursor->shared)) {
|
||||
debug("%s", "propagating local set_tty_echoctl_on_exit true value to shared tty_echoctl_cleared flag");
|
||||
cursor->shared->tty_echoctl_cleared = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If IPC is not being used, the current Y needs to be determined.
|
||||
* If IPC is being used, then the pv_crs_ipcinit() function takes
|
||||
* care of this in a more multi-process-friendly way.
|
||||
*/
|
||||
if (cursor->noipc) {
|
||||
#else /* ! HAVE_IPC */
|
||||
@@ -449,7 +504,7 @@ void pv_crs_init(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtransie
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
/*
|
||||
* Set the "we need to reinitialise cursor positioning" flag.
|
||||
* Set the "need to reinitialise cursor positioning" flag.
|
||||
*/
|
||||
void pv_crs_needreinit(pvcursorstate_t cursor)
|
||||
{
|
||||
@@ -462,8 +517,8 @@ void pv_crs_needreinit(pvcursorstate_t cursor)
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
/*
|
||||
* Reinitialise the cursor positioning code (called if we are backgrounded
|
||||
* then foregrounded again).
|
||||
* Reinitialise the cursor positioning code (called if the process is
|
||||
* backgrounded then foregrounded again).
|
||||
*/
|
||||
static void pv_crs_reinit(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtransientflags_t flags)
|
||||
{
|
||||
@@ -517,7 +572,7 @@ void pv_crs_update(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtrans
|
||||
/*
|
||||
* flawfinder rationale: the "cup_cmd" buffer is always zeroed
|
||||
* before each use, and is only written to by pv_snprintf() bounded
|
||||
* by its size; also, that function explictly zero-terminates the
|
||||
* by its size; also, that function explicitly zero-terminates the
|
||||
* string it writes. The write() call is also bounded.
|
||||
*/
|
||||
|
||||
@@ -548,8 +603,8 @@ void pv_crs_update(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtrans
|
||||
/*
|
||||
* If the screen has scrolled, or is about to scroll, due to
|
||||
* multiple `pv' instances taking us near the bottom of the screen,
|
||||
* scroll the screen (only if we're the first `pv'), and then move
|
||||
* our initial Y co-ordinate up.
|
||||
* scroll the screen (only if this is the first `pv'), and then move
|
||||
* the initial Y co-ordinate up.
|
||||
*/
|
||||
if (((cursor->y_start + cursor->pvmax) > (int) (control->height))
|
||||
&& (!cursor->noipc)
|
||||
@@ -565,7 +620,7 @@ void pv_crs_update(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtrans
|
||||
debug("%s: %d", "scroll offset", offs);
|
||||
|
||||
/*
|
||||
* Scroll the screen if we're the first `pv'.
|
||||
* Scroll the screen if this is the first `pv'.
|
||||
*/
|
||||
if (0 == cursor->y_offset) {
|
||||
pv_crs_lock(cursor, control, STDERR_FILENO);
|
||||
@@ -589,8 +644,8 @@ void pv_crs_update(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtrans
|
||||
#endif /* HAVE_IPC */
|
||||
|
||||
/*
|
||||
* Keep the Y co-ordinate within sensible bounds, so we can never
|
||||
* overflow the "cup_cmd" buffer.
|
||||
* Clamp the Y co-ordinate to sensible bounds, to avoid overflowing
|
||||
* the "cup_cmd" buffer.
|
||||
*/
|
||||
if ((y < 1) || (y > 999999))
|
||||
y = 1;
|
||||
@@ -623,7 +678,7 @@ void pv_crs_fini(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtransie
|
||||
char cup_cmd[32]; /* flawfinder: ignore */
|
||||
unsigned int y;
|
||||
|
||||
/* flawfinder - "cup_cmd" is zeroed, and only written by pv_snprintf() */
|
||||
/* flawfinder - "cup_cmd" is zeroed, and only written by pv_snprintf(). */
|
||||
|
||||
debug("%s", "fini");
|
||||
|
||||
@@ -638,7 +693,7 @@ void pv_crs_fini(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtransie
|
||||
y = control->height;
|
||||
|
||||
/*
|
||||
* Absolute bounds check.
|
||||
* Clamp to reasonable values.
|
||||
*/
|
||||
if ((y < 1) || (y > 999999))
|
||||
y = 1;
|
||||
@@ -656,7 +711,7 @@ void pv_crs_fini(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtransie
|
||||
#ifdef HAVE_IPC
|
||||
/*
|
||||
* If any other "pv -c" instances have set the terminal TOSTOP
|
||||
* attribute, set our local flag so pv_sig_fini() will know about
|
||||
* attribute, set the local flag so pv_sig_fini() will know about
|
||||
* it.
|
||||
*/
|
||||
if ((!cursor->noipc) && (NULL != cursor->shared) && cursor->shared->tty_tostop_added) {
|
||||
@@ -667,6 +722,21 @@ void pv_crs_fini(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtransie
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ECHOCTL
|
||||
/*
|
||||
* If any other "pv -c" instances have cleared the terminal ECHOCTL
|
||||
* attribute, set the local flag so pv_sig_fini() will know about
|
||||
* it.
|
||||
*/
|
||||
if ((!cursor->noipc) && (NULL != cursor->shared) && cursor->shared->tty_echoctl_cleared) {
|
||||
if (0 == flags->set_tty_echoctl_on_exit) {
|
||||
debug("%s",
|
||||
"propagating shared tty_echoctl_cleared true value to local set_tty_echoctl_on_exit flag");
|
||||
flags->set_tty_echoctl_on_exit = 1;
|
||||
}
|
||||
}
|
||||
#endif /* ECHOCTL */
|
||||
|
||||
pv_crs_ipccount(cursor);
|
||||
if (NULL != cursor->shared) {
|
||||
(void) shmdt(cursor->shared);
|
||||
@@ -674,7 +744,7 @@ void pv_crs_fini(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtransie
|
||||
cursor->shared = NULL;
|
||||
|
||||
/*
|
||||
* If we are the last instance detaching from the shared memory,
|
||||
* If this is the last instance detaching from the shared memory,
|
||||
* delete it so it's not left lying around.
|
||||
*/
|
||||
if (cursor->pvcount < 2) {
|
||||
@@ -690,9 +760,36 @@ void pv_crs_fini(pvcursorstate_t cursor, readonly_pvcontrol_t control, pvtransie
|
||||
if (cursor->lock_fd >= 0) {
|
||||
(void) close(cursor->lock_fd);
|
||||
/*
|
||||
* We can get away with removing this on exit because all
|
||||
* the other PVs will be finishing at the same sort of time.
|
||||
* Since all PVs in a pipeline are likely to finish around
|
||||
* the same time, the lock file can be removed without
|
||||
* further co-ordination.
|
||||
*/
|
||||
(void) remove(cursor->lock_file);
|
||||
if (NULL != cursor->lock_file) {
|
||||
(void) remove(cursor->lock_file);
|
||||
free(cursor->lock_file);
|
||||
cursor->lock_file = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Report a signal interrupt, unless the flag allowing it has been cleared
|
||||
* due to another instance already taking responsibility.
|
||||
*/
|
||||
void pv_report_signal_interrupt(int signum)
|
||||
{
|
||||
if (pv__allow_signal_interrupt_reporting) {
|
||||
char *signal_name = NULL;
|
||||
#ifdef HAVE_STRSIGNAL
|
||||
/*@-unrecog @ *//* splint doesn't know strsignal(). */
|
||||
signal_name = strsignal(signum);
|
||||
/*@+unrecog @ */
|
||||
#endif
|
||||
if (NULL != signal_name) {
|
||||
pv_error("%s: %s", _("interrupted by a signal"), signal_name);
|
||||
} else {
|
||||
pv_error("%s", _("interrupted by a signal"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+177
-106
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Display functions.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
#include <termios.h>
|
||||
@@ -28,73 +29,67 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_MATH_H
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If USE_POPEN_TPUTS is defined, then we call popen("tputs") if ncurses is
|
||||
* unavailable, when we need to know whether colours are supported.
|
||||
* If ncurses is unavailable, and USE_POPEN_TPUTS is defined, then
|
||||
* popen("tputs") if used to find out whether colours are supported.
|
||||
*
|
||||
* Since popen() is risky to call (in case $PATH has been altered), it is
|
||||
* safer to just assume colour is available if we can't check, so
|
||||
* USE_POPEN_TPUTS is undefined here by default.
|
||||
* Calling popen() can be risky (in case $PATH has been altered), so the
|
||||
* safer option when ncurses is unavailable is to just always assume colour
|
||||
* is available - so USE_POPEN_TPUTS is undefined here by default.
|
||||
*/
|
||||
#undef USE_POPEN_TPUTS
|
||||
|
||||
|
||||
/*
|
||||
* We need sys/ioctl.h for ioctl() regardless of whether TIOCGWINSZ is
|
||||
* defined in termios.h, so we no longer use AC_HEADER_TIOCGWINSZ in
|
||||
* configure.in, and just include both header files if they are available.
|
||||
* (GH#74, 2023-08-06)
|
||||
* Include sys/ioctl.h for ioctl() regardless of whether TIOCGWINSZ is
|
||||
* defined in termios.h, so rather than using AC_HEADER_TIOCGWINSZ in
|
||||
* configure.in, always include both header files if they are available.
|
||||
* (issue #74, 2023-08-06)
|
||||
*/
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The error prefix for messages (the program name); whether it has been
|
||||
* set; and whether any output has been displayed yet, indicating whether
|
||||
* any errors must be preceded by a newline.
|
||||
* The error prefix for messages (the program name); and whether any output
|
||||
* has been displayed yet, indicating whether any errors must be preceded by
|
||||
* a newline.
|
||||
*/
|
||||
static char pv__error_prefix[64]; /* flawfinder: ignore */
|
||||
static bool pv__error_prefix_set = false;
|
||||
/*@only@ */ static /*@null@ */ char *pv__error_prefix = NULL;
|
||||
static bool pv__output_produced = false;
|
||||
|
||||
/*
|
||||
* flawfinder rationale: zeroed before use, string copy is bounded to 1 less
|
||||
* than size so it always has \0 termination. Not used unless initialised,
|
||||
* by checking pv__error_prefix_set.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the error message prefix.
|
||||
* Set the error message prefix. If the new prefix is NULL, the current
|
||||
* prefix is cleared.
|
||||
*/
|
||||
void pv_set_error_prefix( /*@unique@ */ const char *prefix)
|
||||
void pv_set_error_prefix( /*@null@ */ const char *prefix)
|
||||
{
|
||||
if (NULL != pv__error_prefix) {
|
||||
free(pv__error_prefix);
|
||||
pv__error_prefix = NULL;
|
||||
}
|
||||
if (NULL == prefix)
|
||||
return;
|
||||
memset(pv__error_prefix, 0, sizeof(pv__error_prefix));
|
||||
strncpy(pv__error_prefix, prefix, sizeof(pv__error_prefix) - 1); /* flawfinder: ignore */
|
||||
pv__error_prefix_set = true;
|
||||
/*
|
||||
* flawfinder rationale: strncpy's pointers are as valid as we can
|
||||
* make them since the first is a static buffer and the second is
|
||||
* caller-supplied. The caller must \0-terminate the string but in
|
||||
* any case it is bounded to 1 less than the size of the
|
||||
* destination. The destination is zeroed before use so the result
|
||||
* is guaranteed to be \0-terminated.
|
||||
*/
|
||||
pv__error_prefix = pv_strdup(prefix);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Output an error message. If we've displayed anything to the terminal
|
||||
* already, then put a newline before our error so we don't write over what
|
||||
* we've written.
|
||||
* Output an error message. If anything has been sent to the terminal
|
||||
* already, then put a newline before the message, to avoid writing over
|
||||
* what was sent earlier.
|
||||
*/
|
||||
void pv_error(char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
if (pv__output_produced)
|
||||
fprintf(stderr, "\n");
|
||||
if (pv__error_prefix_set)
|
||||
if (NULL != pv__error_prefix)
|
||||
fprintf(stderr, "%s: ", pv__error_prefix);
|
||||
va_start(ap, format);
|
||||
(void) vfprintf(stderr, format, ap); /* flawfinder: ignore */
|
||||
@@ -108,8 +103,35 @@ void pv_error(char *format, ...)
|
||||
|
||||
|
||||
/*
|
||||
* Return true if we are the foreground process on the terminal, or if we
|
||||
* aren't outputting to a terminal; false otherwise.
|
||||
* Output an error message, like pv_error(), but following the message with
|
||||
* a colon, a space, and the result of strerror(errno).
|
||||
*/
|
||||
void pv_perror(char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int orig_errno;
|
||||
|
||||
orig_errno = errno;
|
||||
|
||||
if (pv__output_produced)
|
||||
fprintf(stderr, "\n");
|
||||
if (NULL != pv__error_prefix)
|
||||
fprintf(stderr, "%s: ", pv__error_prefix);
|
||||
va_start(ap, format);
|
||||
(void) vfprintf(stderr, format, ap); /* flawfinder: ignore */
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, ": %s\n", strerror(orig_errno));
|
||||
/*
|
||||
* flawfinder: this function relies on callers always having a
|
||||
* static format string, not directly subject to outside influences.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return true if either this is the foreground process on the terminal, or
|
||||
* if the output is not a terminal; false otherwise.
|
||||
*/
|
||||
bool pv_in_foreground(void)
|
||||
{
|
||||
@@ -121,10 +143,8 @@ bool pv_in_foreground(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*@-type@ *//* __pid_t vs pid_t, not significant */
|
||||
our_process_group = getpgrp();
|
||||
tty_process_group = tcgetpgrp(STDERR_FILENO);
|
||||
/*@+type@ */
|
||||
our_process_group = (pid_t) getpgrp();
|
||||
tty_process_group = (pid_t) tcgetpgrp(STDERR_FILENO);
|
||||
|
||||
if (tty_process_group == -1 && errno == ENOTTY) {
|
||||
debug("true: %s", "tty_process_group is -1, errno is ENOTTY");
|
||||
@@ -147,8 +167,8 @@ bool pv_in_foreground(void)
|
||||
|
||||
|
||||
/*
|
||||
* Write the given buffer to the given file descriptor, retrying until all
|
||||
* bytes have been written or an error has occurred.
|
||||
* Write a buffer to a file descriptor, retrying until all bytes have been
|
||||
* written or an error has occurred.
|
||||
*/
|
||||
void pv_write_retry(int fd, const char *buf, size_t count)
|
||||
{
|
||||
@@ -173,8 +193,8 @@ void pv_write_retry(int fd, const char *buf, size_t count)
|
||||
|
||||
|
||||
/*
|
||||
* Write the given buffer to the terminal, like pv_write_retry(), unless
|
||||
* stderr is suspended.
|
||||
* Write a buffer to the terminal, like pv_write_retry(), unless stderr is
|
||||
* suspended.
|
||||
*/
|
||||
void pv_tty_write(readonly_pvtransientflags_t flags, const char *buf, size_t count)
|
||||
{
|
||||
@@ -199,8 +219,7 @@ void pv_tty_write(readonly_pvtransientflags_t flags, const char *buf, size_t cou
|
||||
|
||||
|
||||
/*
|
||||
* Fill in *width and *height with the current terminal size,
|
||||
* if possible.
|
||||
* Fill in *width and *height with the current terminal size, if possible.
|
||||
*/
|
||||
void pv_screensize(unsigned int *width, unsigned int *height)
|
||||
{
|
||||
@@ -219,16 +238,6 @@ void pv_screensize(unsigned int *width, unsigned int *height)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the original value x so that it has been clamped between
|
||||
* [min..max]
|
||||
*/
|
||||
long pv_bound_long(long x, long min, long max)
|
||||
{
|
||||
return x < min ? min : x > max ? max : x;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Given how many bytes have been transferred, the total byte count to
|
||||
* transfer, and the current average transfer rate, return the estimated
|
||||
@@ -243,13 +252,30 @@ long pv_seconds_remaining(const off_t so_far, const off_t total, const long doub
|
||||
|
||||
amount_left = (long double) (total - so_far) / rate;
|
||||
|
||||
/* Clamp the amount to a value that fits inside a long integer. */
|
||||
#ifdef LONG_MAX
|
||||
if (amount_left > (long double) LONG_MAX)
|
||||
amount_left = (long double) LONG_MAX;
|
||||
#endif
|
||||
#ifdef LONG_MIN
|
||||
if (amount_left < (long double) LONG_MIN)
|
||||
amount_left = (long double) LONG_MIN;
|
||||
#endif
|
||||
|
||||
#if HAVE_LROUNDL
|
||||
/*@-unrecog@ */
|
||||
return lroundl(amount_left);
|
||||
/*@+unrecog@ *//* splint doesn't know of lroundl(). */
|
||||
#else
|
||||
return (long) amount_left;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a long double value, it is divided or multiplied by the ratio until
|
||||
* a value in the range 1.0 to 999.999... is found. The string "prefix" to
|
||||
* is updated to the corresponding SI prefix.
|
||||
* Given a pointer to long double value, divide or multiply it by the ratio
|
||||
* (1000 or 1024) until it reaches the range 1.0 to 999.999. The string
|
||||
* "prefix" is updated to the corresponding SI prefix, and *value is
|
||||
* modified.
|
||||
*
|
||||
* If the count type is PV_TRANSFERCOUNT_BYTES, then the second byte of
|
||||
* "prefix" is set to "i" to denote MiB etc (IEEE1541). Thus "prefix"
|
||||
@@ -261,9 +287,9 @@ void pv_si_prefix(long double *value, char *prefix, const long double ratio, pvt
|
||||
static char *pfx_024 = NULL; /* kibi, mibi, etc */
|
||||
static char const *pfx_middle_000 = NULL;
|
||||
static char const *pfx_middle_024 = NULL;
|
||||
char *pfx;
|
||||
char const *pfx_middle;
|
||||
char const *pfx_ptr;
|
||||
const char *pfx;
|
||||
const char *pfx_middle;
|
||||
const char *pfx_ptr;
|
||||
long double cutoff;
|
||||
|
||||
prefix[0] = ' '; /* Make the prefix start blank. */
|
||||
@@ -325,11 +351,11 @@ void pv_si_prefix(long double *value, char *prefix, const long double ratio, pvt
|
||||
|
||||
/*
|
||||
* Force an empty prefix if the value is almost zero, to avoid
|
||||
* "0yB". NB we don't compare directly with zero because of
|
||||
* potential floating-point inaccuracies.
|
||||
* "0yB". Don't compare directly with zero because of potential
|
||||
* floating-point inaccuracies.
|
||||
*
|
||||
* See the "count_type" check below for the reason we add another
|
||||
* space in bytes mode.
|
||||
* See the "count_type" check below for the rationale behind adding
|
||||
* another space in bytes mode.
|
||||
*/
|
||||
if ((*value > -0.00000001) && (*value < 0.00000001)) {
|
||||
if (count_type == PV_TRANSFERCOUNT_BYTES) {
|
||||
@@ -412,9 +438,9 @@ void pv_si_prefix(long double *value, char *prefix, const long double ratio, pvt
|
||||
* is 1024 instead of 1000.
|
||||
*
|
||||
* The "format" string is in sprintf format and must contain exactly one %
|
||||
* parameter (a %s) which will expand to the string described above.
|
||||
* parameter, a %s, which will expand to the string described above.
|
||||
*/
|
||||
void pv_describe_amount(char *buffer, size_t bufsize, char *format,
|
||||
void pv_describe_amount(char *buffer, size_t bufsize, const char *format,
|
||||
long double amount, char *suffix_basic, char *suffix_bytes, pvtransfercount_t count_type)
|
||||
{
|
||||
char sizestr_buffer[256]; /* flawfinder: ignore */
|
||||
@@ -451,7 +477,7 @@ void pv_describe_amount(char *buffer, size_t bufsize, char *format,
|
||||
|
||||
pv_si_prefix(&display_amount, si_prefix, divider, count_type);
|
||||
|
||||
/* Make sure we don't overrun our buffer. */
|
||||
/* Clamp the value to avoid a buffer overrun. */
|
||||
if (display_amount > 100000)
|
||||
display_amount = 100000;
|
||||
if (display_amount < -100000)
|
||||
@@ -463,12 +489,12 @@ void pv_describe_amount(char *buffer, size_t bufsize, char *format,
|
||||
"%4ld%.2s%.16s", (long) display_amount, si_prefix, suffix);
|
||||
} else {
|
||||
/*
|
||||
* AIX blows up with %4.3Lg%.2s%.16s for some reason, so we
|
||||
* write display_amount separately first.
|
||||
* AIX breaks with %4.3Lg%.2s%.16s for some reason, so
|
||||
* instead, display_amount is written separately first.
|
||||
*/
|
||||
char str_disp[64]; /* flawfinder: ignore - only used with pv_snprintf(). */
|
||||
memset(str_disp, 0, sizeof(str_disp));
|
||||
/* # to get 13.0GB instead of 13GB (#1477) */
|
||||
/* Use '#' to get 13.0GB instead of 13GB for consistency (#1477). */
|
||||
(void) pv_snprintf(str_disp, sizeof(str_disp), "%#4.3Lg", display_amount);
|
||||
(void) pv_snprintf(sizestr_buffer, sizeof(sizestr_buffer), "%s%.2s%.16s", str_disp, si_prefix, suffix);
|
||||
}
|
||||
@@ -478,9 +504,10 @@ void pv_describe_amount(char *buffer, size_t bufsize, char *format,
|
||||
|
||||
|
||||
/*
|
||||
* Add a null-terminated string to the buffer if there is room for it,
|
||||
* updating the segment's offset and bytes values and returning the bytes
|
||||
* value, or treating the byte count as zero if there's insufficient space.
|
||||
* Add a null-terminated string of content to the formatter's buffer if
|
||||
* there is room for it, updating the segment's offset and bytes values and
|
||||
* returning the bytes value, or treating the byte count as zero if there's
|
||||
* insufficient space.
|
||||
*/
|
||||
pvdisplay_bytecount_t pv_formatter_segmentcontent(char *content, pvformatter_args_t formatter_info)
|
||||
{
|
||||
@@ -516,6 +543,7 @@ pvdisplay_bytecount_t pv_formatter_segmentcontent(char *content, pvformatter_arg
|
||||
{ "{progress}", &pv_formatter_progress, true },
|
||||
{ "{progress-amount-only}", &pv_formatter_progress_amount_only, false },
|
||||
{ "{progress-bar-only}", &pv_formatter_bar_default, true },
|
||||
{ "{progress-conemu}", &pv_formatter_progress_conemu, false },
|
||||
{ "{bar-plain}", &pv_formatter_bar_plain, true },
|
||||
{ "{bar-block}", &pv_formatter_bar_block, true },
|
||||
{ "{bar-granular}", &pv_formatter_bar_granular, true },
|
||||
@@ -533,6 +561,7 @@ pvdisplay_bytecount_t pv_formatter_segmentcontent(char *content, pvformatter_arg
|
||||
{ "b", &pv_formatter_bytes, false },
|
||||
{ "{bytes}", &pv_formatter_bytes, false },
|
||||
{ "{transferred}", &pv_formatter_bytes, false },
|
||||
{ "{ratio}", &pv_formatter_ratio, false },
|
||||
{ "T", &pv_formatter_buffer_percent, false },
|
||||
{ "{buffer-percent}", &pv_formatter_buffer_percent, false },
|
||||
{ "A", &pv_formatter_last_written, false },
|
||||
@@ -620,6 +649,7 @@ static void pv__format_init(pvprogramstatus_t status, readonly_pvcontrol_t contr
|
||||
|
||||
display->showing_timer = false;
|
||||
display->showing_bytes = false;
|
||||
display->showing_ratio = false;
|
||||
display->showing_rate = false;
|
||||
display->showing_last_written = false;
|
||||
display->showing_previous_line = false;
|
||||
@@ -632,7 +662,7 @@ static void pv__format_init(pvprogramstatus_t status, readonly_pvcontrol_t contr
|
||||
|
||||
/*
|
||||
* Split the format string into static strings and calculated
|
||||
* components - a calculated component is is what replaces a
|
||||
* components - a calculated component is what replaces a
|
||||
* placeholder sequence like "%b".
|
||||
*
|
||||
* A "static string" is part of the original format string that is
|
||||
@@ -647,8 +677,8 @@ static void pv__format_init(pvprogramstatus_t status, readonly_pvcontrol_t contr
|
||||
* first populating all the other components referenced by the
|
||||
* format segments.
|
||||
*
|
||||
* Then, that function generates the output string by sticking all
|
||||
* of these segments together.
|
||||
* Then, that function generates the output string by concatenating
|
||||
* all of these segments.
|
||||
*/
|
||||
segment = 0;
|
||||
for (strpos = 0; display_format[strpos] != '\0' && segment < PV_FORMAT_ARRAY_MAX; strpos++, segment++) {
|
||||
@@ -711,7 +741,7 @@ static void pv__format_init(pvprogramstatus_t status, readonly_pvcontrol_t contr
|
||||
component_type = -1;
|
||||
for (component_idx = 0; NULL != format_component_array[component_idx].match; component_idx++) {
|
||||
size_t component_sequence_length = strlen(format_component_array[component_idx].match); /* flawfinder: ignore */
|
||||
char *component_colon_pointer =
|
||||
const char *component_colon_pointer =
|
||||
strchr(format_component_array[component_idx].match, (int) ':');
|
||||
|
||||
/* flawfinder - static strings, guaranteed null-terminated. */
|
||||
@@ -817,10 +847,10 @@ static void pv__format_init(pvprogramstatus_t status, readonly_pvcontrol_t contr
|
||||
* buffer, to invoke its side effects such as
|
||||
* setting display->showing_timer.
|
||||
*
|
||||
* These side effects are required for other parts
|
||||
* of the program to understand what is required,
|
||||
* such as the transfer functions knowning to track
|
||||
* the previous line, or numeric mode knowing which
|
||||
* These side effects are used by other parts of the
|
||||
* program to understand what is required, such as
|
||||
* the transfer functions knowing to track the
|
||||
* previous line, or numeric mode knowing which
|
||||
* additional display options are enabled.
|
||||
*/
|
||||
memset(&formatter_info, 0, sizeof(formatter_info));
|
||||
@@ -840,8 +870,8 @@ static void pv__format_init(pvprogramstatus_t status, readonly_pvcontrol_t contr
|
||||
(void) format_component_array[component_type].function(&formatter_info);
|
||||
/*@+compmempass@ */
|
||||
/*
|
||||
* splint - the buffer we point formatter_info to is
|
||||
* on the stack so doesn't match the "dependent"
|
||||
* splint - the formatter_info's buffer is on the
|
||||
* stack so doesn't match the "dependent"
|
||||
* annotation, but there's no other appropriate
|
||||
* annotation that doesn't make splint think there's
|
||||
* a leak here.
|
||||
@@ -855,9 +885,9 @@ static void pv__format_init(pvprogramstatus_t status, readonly_pvcontrol_t contr
|
||||
status->checked_colour_support = true;
|
||||
#ifdef ENABLE_NCURSES
|
||||
/*
|
||||
* If we have terminal info support, check whether the
|
||||
* current terminal supports colour - or just assume it's
|
||||
* supported if we're forcing output.
|
||||
* With terminal info support, check whether the current
|
||||
* terminal supports colour - or just assume it's supported,
|
||||
* if --force was supplied.
|
||||
*/
|
||||
if (true == control->force) {
|
||||
status->terminal_supports_colour = true;
|
||||
@@ -907,9 +937,9 @@ static void pv__format_init(pvprogramstatus_t status, readonly_pvcontrol_t contr
|
||||
/*@+unrecog@ */
|
||||
|
||||
/*
|
||||
* flawfinder - we acknowledge that popen() is risky
|
||||
* to call, though we have the mitigation that we're
|
||||
* calling it with a static string.
|
||||
* flawfinder - warns that popen() is risky to call,
|
||||
* though this is mitigated by calling it with a
|
||||
* static string.
|
||||
*/
|
||||
|
||||
if (NULL == command_fptr) {
|
||||
@@ -959,6 +989,9 @@ static void pv__format_init(pvprogramstatus_t status, readonly_pvcontrol_t contr
|
||||
* If "final" is true, this is the final update so the rate is given as an
|
||||
* an average over the whole transfer; otherwise the current rate is shown.
|
||||
*
|
||||
* If "is_primary" is true, this is the primary display, not an extra one,
|
||||
* which means extra terminal control codes like OSC 9;4 may be inserted.
|
||||
*
|
||||
* Returns true if the display buffer can be used, false if not.
|
||||
*
|
||||
* When returning true, this function will have also set
|
||||
@@ -969,9 +1002,9 @@ static void pv__format_init(pvprogramstatus_t status, readonly_pvcontrol_t contr
|
||||
*
|
||||
* See pv__format_init for the adjustments that may be made to "status".
|
||||
*/
|
||||
bool pv_format(pvprogramstatus_t status, readonly_pvcontrol_t control, readonly_pvtransferstate_t transfer,
|
||||
readonly_pvtransfercalc_t calc, /*@null@ */ const char *format_supplied, pvdisplay_t display,
|
||||
bool reinitialise, bool final)
|
||||
static bool pv_format(pvprogramstatus_t status, readonly_pvcontrol_t control, readonly_pvtransferstate_t transfer,
|
||||
readonly_pvtransfercalc_t calc, /*@null@ */ const char *format_supplied, pvdisplay_t display,
|
||||
bool reinitialise, bool final, bool is_primary)
|
||||
{
|
||||
struct pvdisplay_component_s *format_component_array;
|
||||
char display_segments[PV_SIZEOF_FORMAT_SEGMENTS_BUF]; /* flawfinder: ignore - always bounded */
|
||||
@@ -1011,7 +1044,7 @@ bool pv_format(pvprogramstatus_t status, readonly_pvcontrol_t control, readonly_
|
||||
/* Populate the display's "final" flag, for formatters. */
|
||||
display->final_update = final;
|
||||
|
||||
/* Reinitialise if we were asked to. */
|
||||
/* Reinitialise if requested. */
|
||||
if (reinitialise)
|
||||
pv__format_init(status, control, transfer, calc, format_supplied, display);
|
||||
|
||||
@@ -1037,7 +1070,7 @@ bool pv_format(pvprogramstatus_t status, readonly_pvcontrol_t control, readonly_
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate output buffer if there isn't one.
|
||||
* Allocate the output buffer if there isn't one.
|
||||
*/
|
||||
if (NULL == display->display_buffer) {
|
||||
char *new_buffer;
|
||||
@@ -1050,7 +1083,7 @@ bool pv_format(pvprogramstatus_t status, readonly_pvcontrol_t control, readonly_
|
||||
|
||||
new_buffer = malloc(new_size + 16);
|
||||
if (NULL == new_buffer) {
|
||||
pv_error("%s: %s", _("buffer allocation failed"), strerror(errno));
|
||||
pv_perror("%s", _("memory allocation failure"));
|
||||
status->exit_status |= PV_ERROREXIT_MEMORY;
|
||||
display->display_buffer = NULL;
|
||||
return false;
|
||||
@@ -1064,6 +1097,9 @@ bool pv_format(pvprogramstatus_t status, readonly_pvcontrol_t control, readonly_
|
||||
/* Clear the SGR active codes flag, for the SGR formatter. */
|
||||
display->sgr_code_active = false;
|
||||
|
||||
/* Clear the OSC 9;4 active flag. */
|
||||
display->using_osc94 = false;
|
||||
|
||||
/*
|
||||
* Populate the internal segments buffer with each component's
|
||||
* output, in two passes.
|
||||
@@ -1101,7 +1137,7 @@ bool pv_format(pvprogramstatus_t status, readonly_pvcontrol_t control, readonly_
|
||||
formatter_info.segment = segment;
|
||||
/*@-compmempass@ */
|
||||
bytes_added = component->function(&formatter_info);
|
||||
/*@+compmempass@ *//* see previous ->function() note. */
|
||||
/*@+compmempass@ *//* see format_component_array[].function() in pv__format_init(). */
|
||||
|
||||
segment->width = 0;
|
||||
if (bytes_added > 0) {
|
||||
@@ -1199,7 +1235,30 @@ bool pv_format(pvprogramstatus_t status, readonly_pvcontrol_t control, readonly_
|
||||
segment->bytes, display->display_buffer + display_buffer_offset - segment->bytes);
|
||||
}
|
||||
|
||||
/* If the SGR active codes flag is set, we need to emit an SGR reset. */
|
||||
/*
|
||||
* If OSC 9;4 is enabled globally but wasn't present in the format
|
||||
* string, and this is the primary display, run its formatter to add
|
||||
* the sequences.
|
||||
*/
|
||||
if (is_primary && control->use_osc94 && !display->using_osc94) {
|
||||
char content[128]; /* flawfinder: ignore */
|
||||
size_t bytes_added;
|
||||
|
||||
/* flawfinder - null-terminated and bounded with pv_snprintf(). */
|
||||
|
||||
memset(content, 0, sizeof(content));
|
||||
|
||||
debug("%s", "OSC 9;4 enabled globally but not in format string - adding sequence");
|
||||
bytes_added = pv_osc94_format(content, sizeof(content), control, calc);
|
||||
memmove(display->display_buffer + display_buffer_offset, content, bytes_added);
|
||||
display_buffer_offset += bytes_added;
|
||||
display_buffer_remaining -= bytes_added;
|
||||
new_display_string_bytes += bytes_added;
|
||||
|
||||
display->using_osc94 = true;
|
||||
}
|
||||
|
||||
/* If the SGR active codes flag is set, emit an SGR reset. */
|
||||
if (display->sgr_code_active) {
|
||||
debug("%s", "SGR codes still active - adding reset");
|
||||
(void) pv_strlcat(display->display_buffer, "\033[m", display->display_buffer_size);
|
||||
@@ -1213,8 +1272,8 @@ bool pv_format(pvprogramstatus_t status, readonly_pvcontrol_t control, readonly_
|
||||
debug("%s: %d", "new display string width", (int) new_display_string_width);
|
||||
|
||||
/*
|
||||
* If the width of our output shrinks, we need to keep appending
|
||||
* spaces at the end, so that we don't leave dangling bits behind.
|
||||
* If the width of the output shrinks, pad with spaces to the old
|
||||
* width, to avoid leaving dangling bits behind.
|
||||
*/
|
||||
if ((new_display_string_width < display->display_string_width)
|
||||
&& (control->width >= display->prev_screen_width)) {
|
||||
@@ -1291,12 +1350,13 @@ void pv_display(pvprogramstatus_t status, readonly_pvcontrol_t control, pvtransi
|
||||
flags->reparse_display = 0;
|
||||
}
|
||||
|
||||
if (!pv_format(status, control, transfer, calc, control->format_string, display, reinitialise, final))
|
||||
if (!pv_format(status, control, transfer, calc, control->format_string, display, reinitialise, final, true))
|
||||
return;
|
||||
|
||||
if ((NULL != extra_display) && (0 != control->extra_displays)) {
|
||||
if (!pv_format
|
||||
(status, control, transfer, calc, control->extra_format_string, extra_display, reinitialise, final))
|
||||
(status, control, transfer, calc, control->extra_format_string, extra_display, reinitialise, final,
|
||||
false))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1344,3 +1404,14 @@ void pv_display(pvprogramstatus_t status, readonly_pvcontrol_t control, pvtransi
|
||||
debug("%s: [%s]", "processtitle display", extra_display->display_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clear the local pv__output_produced flag to indicate that the progress
|
||||
* bar display is no longer being updated and the cursor has moved past it,
|
||||
* so error messages don't need a preceding line any more.
|
||||
*/
|
||||
void pv_end_display(void)
|
||||
{
|
||||
pv__output_produced = false;
|
||||
}
|
||||
|
||||
+19
-19
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Functions relating to elapsed time.
|
||||
*
|
||||
* Copyright 2023-2025 Andrew Wood
|
||||
* Copyright 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -16,19 +16,19 @@
|
||||
|
||||
/*
|
||||
* Read the current elapsed time, relative to an unspecified point in the
|
||||
* past, and store it in the given timespec buffer. The time is guaranteed
|
||||
* to not go backwards and does not count time when the system was
|
||||
* suspended. See clock_gettime(2) with CLOCK_MONOTONIC.
|
||||
* past, and store it in "return_time". The time is guaranteed to not go
|
||||
* backwards and does not count time when the system was suspended. See
|
||||
* clock_gettime(2) with CLOCK_MONOTONIC.
|
||||
*
|
||||
* The read should not fail; if it does, the program is aborted with exit
|
||||
* status 16 (transfer error).
|
||||
*/
|
||||
void pv_elapsedtime_read(struct timespec *return_time)
|
||||
{
|
||||
/*@-unrecog@ *//* splint doesn't know clock_gettime */
|
||||
/*@-unrecog@ *//* splint doesn't know clock_gettime. */
|
||||
if (0 != clock_gettime(CLOCK_MONOTONIC, return_time)) {
|
||||
fprintf(stderr, "%s: %s: %s\n", PACKAGE_NAME, "clock_gettime", strerror(errno));
|
||||
/*@-exitarg@ *//* we explicitly want a special exit status */
|
||||
pv_perror("%s", "clock_gettime");
|
||||
/*@-exitarg@ *//* The special exit status is explicitly chosen. */
|
||||
exit(PV_ERROREXIT_TRANSFER);
|
||||
/*@+exitarg@ */
|
||||
}
|
||||
@@ -37,7 +37,7 @@ void pv_elapsedtime_read(struct timespec *return_time)
|
||||
|
||||
|
||||
/*
|
||||
* Set the time in the given timespec to zero.
|
||||
* Set the time in the timespec to zero.
|
||||
*/
|
||||
void pv_elapsedtime_zero(struct timespec *zero_time)
|
||||
{
|
||||
@@ -132,16 +132,16 @@ void pv_elapsedtime_add(struct timespec *return_time, const struct timespec *fir
|
||||
/*@+type@ */
|
||||
|
||||
/*
|
||||
* splint rationale: we know the types are different but should be
|
||||
* large enough and are relying on the compiler to do the casting
|
||||
* correctly, since the manual for timespec(3) states the types are
|
||||
* implementation-defined.
|
||||
* splint rationale: the manual for timespec(3) states that its
|
||||
* types are implementation-defined, so the best option is to use
|
||||
* types that are the most likely to be large enough, and let the
|
||||
* compiler do the casting.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add a number of nanoseconds to the given timespec.
|
||||
* Add a number of nanoseconds to a timespec.
|
||||
*/
|
||||
void pv_elapsedtime_add_nsec(struct timespec *return_time, long long add_nanoseconds)
|
||||
{
|
||||
@@ -156,7 +156,7 @@ void pv_elapsedtime_add_nsec(struct timespec *return_time, long long add_nanosec
|
||||
seconds += nanoseconds / 1000000000;
|
||||
nanoseconds = nanoseconds % 1000000000;
|
||||
|
||||
/*@-type@ *//* see above */
|
||||
/*@-type@ *//* See above. */
|
||||
return_time->tv_sec = seconds;
|
||||
return_time->tv_nsec = nanoseconds;
|
||||
/*@+type@ */
|
||||
@@ -195,7 +195,7 @@ void pv_elapsedtime_subtract(struct timespec *return_time, const struct timespec
|
||||
nanoseconds = 1000000000 + nanoseconds;
|
||||
}
|
||||
|
||||
/*@-type@ *//* see above */
|
||||
/*@-type@ *//* See above. */
|
||||
return_time->tv_sec = seconds;
|
||||
return_time->tv_nsec = nanoseconds;
|
||||
/*@+type@ */
|
||||
@@ -233,18 +233,18 @@ void pv_nanosleep(long long nanoseconds)
|
||||
sleep_for.tv_sec = 0;
|
||||
/*@-type@ */
|
||||
sleep_for.tv_nsec = nanoseconds;
|
||||
/*@+type@ *//* splint rationale - best effort */
|
||||
/*@+type@ *//* splint rationale - best effort. */
|
||||
/*@-unrecog@ */
|
||||
(void) nanosleep(&sleep_for, &time_remaining);
|
||||
/*@+unrecog@ *//* splint rationale - doesn't know of nanosleep() */
|
||||
/*@+unrecog@ *//* splint doesn't know of nanosleep(). */
|
||||
#else
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
/*@-type@ */
|
||||
tv.tv_usec = nanoseconds / 1000;
|
||||
/*@+type@ *//* splint rationale - best effort */
|
||||
/*@+type@ *//* splint rationale - best effort. */
|
||||
/*@-null@ */
|
||||
(void) select(0, NULL, NULL, NULL, &tv);
|
||||
/*@+null@ *//* splint doesn't know about select() */
|
||||
/*@+null@ *//* splint doesn't know about select(). */
|
||||
#endif
|
||||
}
|
||||
|
||||
+235
-68
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Functions for opening and closing files, and calculating their size.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -18,18 +18,80 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
|
||||
/*@-type@*/
|
||||
/* splint has trouble with off_t and mode_t throughout this file. */
|
||||
|
||||
/*
|
||||
* Check that a file descriptor is open on /dev/null, returning true if so.
|
||||
* Otherwise return false; if the second argument is true, reports the
|
||||
* problem with pv_error() before returning.
|
||||
*
|
||||
* No error is reported if the file descriptor is less than zero.
|
||||
*/
|
||||
bool pv_fd_is_dev_null(int fd, bool report_error)
|
||||
{
|
||||
struct stat sb;
|
||||
struct utsname uts;
|
||||
unsigned long expected_rdev;
|
||||
bool is_dev_null;
|
||||
|
||||
if (fd < 0)
|
||||
return false;
|
||||
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
if (fstat(fd, &sb) < 0) {
|
||||
if (report_error)
|
||||
pv_perror("%s", "/dev/null");
|
||||
return false;
|
||||
}
|
||||
|
||||
expected_rdev = 0x0103; /* device 1,3 on Linux. */
|
||||
|
||||
is_dev_null = true;
|
||||
if (!S_ISCHR(sb.st_mode)) {
|
||||
debug("%s", "/dev/null: not a character device");
|
||||
is_dev_null = false;
|
||||
}
|
||||
|
||||
memset(&uts, 0, sizeof(uts));
|
||||
if (uname(&uts) >= 0) {
|
||||
if (0 == strncmp(uts.sysname, "OpenBSD", 7)) {
|
||||
expected_rdev = 0x0202;
|
||||
} else if (0 == strncmp(uts.sysname, "FreeBSD", 7)) {
|
||||
expected_rdev = 0x0022;
|
||||
} else if (0 == strncmp(uts.sysname, "NetBSD", 6)) {
|
||||
expected_rdev = 0x0202;
|
||||
} else if (0 == strncmp(uts.sysname, "Darwin", 6)) {
|
||||
expected_rdev = 0x03000002;
|
||||
}
|
||||
}
|
||||
|
||||
if ((unsigned long) (sb.st_rdev) != expected_rdev) {
|
||||
debug("/dev/null: fd is %08lx, expected %08lx", sb.st_rdev, expected_rdev);
|
||||
is_dev_null = false;
|
||||
}
|
||||
|
||||
if (is_dev_null)
|
||||
return true;
|
||||
|
||||
if (report_error)
|
||||
pv_error("%s", _("/dev/null is not usable"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculate the total number of bytes to be transferred by adding up the
|
||||
* sizes of all input files. If any of the input files are of indeterminate
|
||||
* size (such as if they are a pipe), the total size is set to zero.
|
||||
*
|
||||
* Any files that cannot be stat()ed or that access() says we can't read
|
||||
* will be skipped, and the total size will be set to zero.
|
||||
* If there are any files that cannot be stat()ed, or that access() says are
|
||||
* not readable, they will be skipped, and the total size will be set to
|
||||
* zero.
|
||||
*
|
||||
* Returns the total size, or 0 if it is unknown.
|
||||
*/
|
||||
@@ -69,15 +131,16 @@ static off_t pv_calc_total_bytes(pvstate_t state)
|
||||
if (0 == rc) {
|
||||
rc = access(state->files.filename[file_idx], R_OK); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: we're not really
|
||||
* using access() to do permissions checks,
|
||||
* but to zero the total if we might be
|
||||
* unable to read the file later, so if an
|
||||
* attacker redirected one of the input
|
||||
* files in between this part and the actual
|
||||
* reading, the outcome would be that the
|
||||
* total byte count would be wrong or
|
||||
* missing, nothing useful.
|
||||
* flawfinder rationale: access() can lead
|
||||
* to TOCTOU issues but here it isn't being
|
||||
* used to check permissions, only to zero
|
||||
* the total if the file is likely to be
|
||||
* unreadable later. If an attacker
|
||||
* redirected one of the input files in
|
||||
* between this part and the actual reading,
|
||||
* the outcome would be that the total byte
|
||||
* count would be wrong or missing, nothing
|
||||
* otherwise exploitable.
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -99,10 +162,10 @@ static off_t pv_calc_total_bytes(pvstate_t state)
|
||||
fd = open("/dev/stdin", O_RDONLY); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: "/dev/stdin" may be
|
||||
* a symlink, so can't use O_NOFOLLOW, and
|
||||
* so we have to assume that it being under
|
||||
* "/dev" means the path is less likely to
|
||||
* be under the control of someone else.
|
||||
* a symlink, so O_NOFOLLOW is not suitable;
|
||||
* in mitigation, a path under "/dev" is
|
||||
* unlikely to be under the control of
|
||||
* someone else.
|
||||
*/
|
||||
} else {
|
||||
fd = open(state->files.filename[file_idx], O_RDONLY); /* flawfinder: ignore */
|
||||
@@ -127,12 +190,13 @@ static off_t pv_calc_total_bytes(pvstate_t state)
|
||||
}
|
||||
|
||||
/*
|
||||
* Patch from Peter Samuelson: if we cannot work out the size of the
|
||||
* input, but we are writing to a block device, then use the size of
|
||||
* the output block device.
|
||||
* Patch from Peter Samuelson: if the input size can't be
|
||||
* determined, but the output is being written to a block device,
|
||||
* then use the size of the output block device.
|
||||
*
|
||||
* Further modified to check that output is not in append-only mode
|
||||
* and that we can seek back to the start after getting the size.
|
||||
* Further modified to check that output is not in append-only mode,
|
||||
* such that it is possible to seek back to the start after getting
|
||||
* the size.
|
||||
*/
|
||||
if (total < 1) {
|
||||
int rc;
|
||||
@@ -148,16 +212,14 @@ static off_t pv_calc_total_bytes(pvstate_t state)
|
||||
total = end_position;
|
||||
}
|
||||
if (lseek(state->control.output_fd, 0, SEEK_SET) != 0) {
|
||||
pv_error("%s: %s: %s",
|
||||
NULL == state->control.output_name ? "(null)" : state->control.output_name,
|
||||
_("failed to seek to start of output"), strerror(errno));
|
||||
pv_perror("%s",
|
||||
NULL == state->control.output_name ? "(null)" : state->control.output_name);
|
||||
state->status.exit_status |= PV_ERROREXIT_ACCESS;
|
||||
}
|
||||
/*
|
||||
* If we worked out a size, then set the
|
||||
* stop-at-size flag to prevent a "no space left on
|
||||
* device" error when we reach the end of the output
|
||||
* device.
|
||||
* If a size was found, then set the stop-at-size
|
||||
* flag to prevent a "no space left on device" error
|
||||
* when the end of the output device is reached.
|
||||
*/
|
||||
if (total > 0) {
|
||||
state->control.stop_at_size = true;
|
||||
@@ -174,8 +236,9 @@ static off_t pv_calc_total_bytes(pvstate_t state)
|
||||
* input files. If any of the inputs are not regular files (such as if they
|
||||
* are a pipe or a block device), the total size is set to zero.
|
||||
*
|
||||
* Any files that cannot be stat()ed or that access() says we can't read
|
||||
* will be skipped, and the total size will be set to zero.
|
||||
* If there are any files that cannot be stat()ed, or that access() says are
|
||||
* not readable, they will be skipped, and the total size will be set to
|
||||
* zero.
|
||||
*
|
||||
* Returns the total size, or 0 if it is unknown.
|
||||
*/
|
||||
@@ -218,7 +281,7 @@ static off_t pv_calc_total_lines(pvstate_t state)
|
||||
return total;
|
||||
}
|
||||
#if HAVE_POSIX_FADVISE
|
||||
/* Advise the OS that we will only be reading sequentially. */
|
||||
/* Advise the OS that all reads will be sequential. */
|
||||
(void) posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
#endif
|
||||
|
||||
@@ -230,13 +293,12 @@ static off_t pv_calc_total_lines(pvstate_t state)
|
||||
|
||||
numread = read(fd, scanbuf, sizeof(scanbuf)); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: each time around the loop
|
||||
* we are always reading into the start of the
|
||||
* buffer, not moving along it, so the bounding is
|
||||
* OK.
|
||||
* flawfinder rationale: every read is reading into
|
||||
* the start of the buffer, not moving along it, so
|
||||
* the bounding is OK.
|
||||
*/
|
||||
if (numread < 0) {
|
||||
pv_error("%s: %s", state->files.filename[file_idx], strerror(errno));
|
||||
pv_perror("%s", state->files.filename[file_idx]);
|
||||
state->status.exit_status |= PV_ERROREXIT_ACCESS;
|
||||
break;
|
||||
} else if (0 == numread) {
|
||||
@@ -254,7 +316,7 @@ static off_t pv_calc_total_lines(pvstate_t state)
|
||||
}
|
||||
|
||||
if (0 != lseek(fd, 0, SEEK_SET)) {
|
||||
pv_error("%s: %s", state->files.filename[file_idx], strerror(errno));
|
||||
pv_perror("%s", state->files.filename[file_idx]);
|
||||
state->status.exit_status |= PV_ERROREXIT_ACCESS;
|
||||
}
|
||||
|
||||
@@ -288,7 +350,13 @@ off_t pv_calc_total_size(pvstate_t state)
|
||||
* error). It is an error if the next input file is the same as the file
|
||||
* the output is pointing to.
|
||||
*
|
||||
* Updates state->status.current_input_file in the process.
|
||||
* Updates state->status.current_input_file and
|
||||
* state->status.current_input_is_pipe.
|
||||
*
|
||||
* If the input is not a pipe, and state->status.output_is_pipe is false,
|
||||
* and state->control.no_splice is false, also creates a pipe and populates
|
||||
* state->transfer.intermediate_pipe[] with its file descriptors, if a pipe
|
||||
* had not already been created (i.e. that array contained [-1,-1]).
|
||||
*/
|
||||
int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
{
|
||||
@@ -300,7 +368,7 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
|
||||
if (oldfd >= 0) {
|
||||
if (0 != close(oldfd)) {
|
||||
pv_error("%s: %s", _("failed to close file"), strerror(errno));
|
||||
pv_perror("%s: %s", pv_current_file_name(state), _("error closing file"));
|
||||
state->status.exit_status |= PV_ERROREXIT_TRANSITION;
|
||||
return -1;
|
||||
}
|
||||
@@ -328,35 +396,33 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
fd = open(next_filename, O_RDONLY); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: the input file list is under the
|
||||
* control of the operator by its nature, so we can't refuse
|
||||
* to open symlinks etc as that would be counterintuitive.
|
||||
* control of the operator by its nature, so refusing to
|
||||
* open symlinks would be counterintuitive.
|
||||
*/
|
||||
if (fd < 0) {
|
||||
pv_error("%s: %s: %s", _("failed to read file"), next_filename, strerror(errno));
|
||||
pv_perror("%s", next_filename);
|
||||
state->status.exit_status |= PV_ERROREXIT_ACCESS;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != fstat(fd, &isb)) {
|
||||
pv_error("%s: %s: %s", _("failed to stat file"),
|
||||
NULL == next_filename ? "-" : next_filename, strerror(errno));
|
||||
pv_perror("%s", NULL == next_filename ? "-" : next_filename);
|
||||
(void) close(fd);
|
||||
state->status.exit_status |= PV_ERROREXIT_ACCESS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != fstat(state->control.output_fd, &osb)) {
|
||||
pv_error("%s: %s", _("failed to stat output file"), strerror(errno));
|
||||
pv_perror("%s", NULL == state->control.output_name ? "(null)" : state->control.output_name);
|
||||
(void) close(fd);
|
||||
state->status.exit_status |= PV_ERROREXIT_ACCESS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that this new input file is not the same as output's
|
||||
* destination. This restriction is ignored for anything other
|
||||
* than a regular file or block device.
|
||||
* If the input file is a regular file or a block device, check that
|
||||
* it is not the same as the output's destination.
|
||||
*/
|
||||
input_file_is_output = true;
|
||||
if (isb.st_dev != osb.st_dev)
|
||||
@@ -369,12 +435,28 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
input_file_is_output = false;
|
||||
|
||||
if (input_file_is_output) {
|
||||
pv_error("%s: %s", _("input file is output file"), NULL == next_filename ? "-" : next_filename);
|
||||
pv_error("%s: %s", NULL == next_filename ? "-" : next_filename, _("input file is also the output"));
|
||||
(void) close(fd);
|
||||
state->status.exit_status |= PV_ERROREXIT_OUROBOROS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect whether the input file is a pipe, a regular file, or
|
||||
* neither. This is used later, in pv__transfer_read(), when
|
||||
* determining the transfer method - read/write, splice(),
|
||||
* copy_file_range().
|
||||
*/
|
||||
state->status.current_input_is_pipe = false;
|
||||
state->status.current_input_is_file = false;
|
||||
if ((isb.st_mode & S_IFMT) == S_IFIFO) {
|
||||
state->status.current_input_is_pipe = true;
|
||||
debug("%s (fd %d)", "input is a pipe", fd);
|
||||
} else if ((isb.st_mode & S_IFMT) == S_IFREG) {
|
||||
state->status.current_input_is_file = true;
|
||||
debug("%s (fd %d)", "input is a regular file", fd);
|
||||
}
|
||||
|
||||
state->status.current_input_file = filenum;
|
||||
#ifdef O_DIRECT
|
||||
/*
|
||||
@@ -384,19 +466,106 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
/*@-compdef@ */
|
||||
/*
|
||||
* splint - passed or returned storage is undefined - but at
|
||||
* this point we know the input file list is been populated,
|
||||
* so that's OK.
|
||||
* this point, the input file list has been populated, so
|
||||
* that's OK.
|
||||
*/
|
||||
debug("%s: %s: %s", pv_current_file_name(state), "fcntl", strerror(errno));
|
||||
/*@+compdef@ */
|
||||
}
|
||||
/*
|
||||
* We don't clear direct_io_changed here, to avoid race conditions
|
||||
* that could cause the input and output settings to differ.
|
||||
* Don't clear direct_io_changed here, to avoid race conditions that
|
||||
* could cause the input and output settings to differ.
|
||||
*/
|
||||
#endif /* O_DIRECT */
|
||||
|
||||
debug("%s: %d: %s: fd=%d", "next file opened", filenum, pv_current_file_name(state), fd);
|
||||
debug("%s: %d: %s: fd=%d, is_pipe=%s, is_file=%s", "next file opened", filenum, pv_current_file_name(state), fd,
|
||||
state->status.current_input_is_pipe ? "true" : "false",
|
||||
state->status.current_input_is_file ? "true" : "false");
|
||||
|
||||
#ifdef HAVE_SPLICE
|
||||
if (state->control.discard_input && !state->control.no_splice && state->transfer.discard_fd < 0) {
|
||||
/*
|
||||
* Open a file descriptor to /dev/null, so that input can be
|
||||
* spliced to it to implement -X.
|
||||
*
|
||||
* If this fails, transfer.discard_fd will be left at -1,
|
||||
* which means the transfer functions will not use splice().
|
||||
*/
|
||||
state->transfer.discard_fd = open("/dev/null", O_WRONLY); /* flawfinder: ignore */
|
||||
/* flawfinder: /dev/null is trusted. */
|
||||
if (state->transfer.discard_fd < 0) {
|
||||
debug("%s: %s", "/dev/null", strerror(errno));
|
||||
state->transfer.discard_fd = -1;
|
||||
}
|
||||
if (!pv_fd_is_dev_null(state->transfer.discard_fd, false)) {
|
||||
if (state->transfer.discard_fd >= 0)
|
||||
(void) close(state->transfer.discard_fd);
|
||||
state->transfer.discard_fd = -1;
|
||||
}
|
||||
debug("%s: %d", "discard_fd", state->transfer.discard_fd);
|
||||
/*
|
||||
* If discard_fd was successfully opened, it will be used as
|
||||
* the output, so set the output status flags appropriately.
|
||||
*/
|
||||
if (state->transfer.discard_fd >= 0) {
|
||||
state->status.output_is_pipe = false;
|
||||
state->status.output_is_file = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(state->status.output_is_pipe || state->status.current_input_is_pipe || state->control.no_splice)
|
||||
&& (-1 == state->transfer.intermediate_pipe[0])) {
|
||||
/*
|
||||
* Create an intermediate pipe to allow the input to be used
|
||||
* with splice() even though neither it nor the output are
|
||||
* themselves pipes.
|
||||
*/
|
||||
state->transfer.intermediate_pipe_buffer_used = 0;
|
||||
if (pipe(state->transfer.intermediate_pipe) < 0) {
|
||||
debug("%s: %s", "pipe()", strerror(errno));
|
||||
state->transfer.intermediate_pipe[0] = -1;
|
||||
state->transfer.intermediate_pipe[1] = -1;
|
||||
} else {
|
||||
state->transfer.intermediate_pipe_buffer_size = 64 * 1024;
|
||||
#if defined F_SETPIPE_SZ && defined F_GETPIPE_SZ
|
||||
{
|
||||
size_t target_pipe_buffer_size = state->control.pipe_buffer_size;
|
||||
int new_size;
|
||||
|
||||
/* If no pipe buffer size was set, try for 1MiB. */
|
||||
if (0 == target_pipe_buffer_size)
|
||||
target_pipe_buffer_size = 1024 * 1024;
|
||||
|
||||
/*
|
||||
* Try to set the pipe buffer size, halving
|
||||
* repeatedly on failure.
|
||||
*/
|
||||
new_size = -1;
|
||||
while (new_size < 0 && target_pipe_buffer_size >= 4096) {
|
||||
new_size =
|
||||
fcntl(state->transfer.intermediate_pipe[1], F_SETPIPE_SZ,
|
||||
(int) target_pipe_buffer_size);
|
||||
if (new_size < 0)
|
||||
target_pipe_buffer_size = target_pipe_buffer_size / 2;
|
||||
}
|
||||
/* If all attempts failed, read the current size. */
|
||||
if (new_size < 0) {
|
||||
new_size = fcntl(state->transfer.intermediate_pipe[1], F_GETPIPE_SZ);
|
||||
/* If unable to read, assume 64KiB. */
|
||||
if (new_size < 0) {
|
||||
new_size = 64 * 1024;
|
||||
}
|
||||
}
|
||||
|
||||
state->transfer.intermediate_pipe_buffer_size = new_size;
|
||||
}
|
||||
#endif /* defined F_SETPIPE_SZ && defined F_GETPIPE_SZ */
|
||||
}
|
||||
debug("%s: [%d,%d]", "intermediate pipe fds", state->transfer.intermediate_pipe[0],
|
||||
state->transfer.intermediate_pipe[1]);
|
||||
debug("%s: %d", "intermediate pipe buffer size", state->transfer.intermediate_pipe_buffer_size);
|
||||
}
|
||||
#endif /* HAVE_SPLICE */
|
||||
|
||||
return fd;
|
||||
}
|
||||
@@ -417,12 +586,10 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
/*@-onlytrans@ */
|
||||
/*@-statictrans@ */
|
||||
/*
|
||||
* Here we are doing bad things with regards to whether the returned
|
||||
* string is an allocated string from the state->files.filename array,
|
||||
* a constant string, or a returned string from gettext(), but it
|
||||
* has no impact. We explicitly document, above, that the returned
|
||||
* string expires with the state, and hence switch off the
|
||||
* associated splint warnings.
|
||||
* The returned string could be an allocated string from the
|
||||
* state->files.filename array, a constant string, or a returned
|
||||
* string from gettext(). The documentation, above, explains that
|
||||
* the returned string expires with the state.
|
||||
*/
|
||||
|
||||
if (NULL == str_none)
|
||||
@@ -455,8 +622,8 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
return input_file_name;
|
||||
/*@+compdef@ */
|
||||
/*
|
||||
* splint warns about state->files.filename being undefined, but we
|
||||
* know it's been populated fully by the time this function is
|
||||
* splint warns about state->files.filename being undefined, but it
|
||||
* has definitely been fully populated by the time this function is
|
||||
* called.
|
||||
*/
|
||||
|
||||
@@ -530,12 +697,12 @@ FILE *pv_open_controlfile(char *filename, size_t bufsize, pid_t control_pid, int
|
||||
|
||||
/*
|
||||
* flawfinder rationale: the files are in a directory whose parents
|
||||
* cannot be manipulated, and we are not allowing the final
|
||||
* component to be a symbolic link. We are checking that $HOME is
|
||||
* not NULL, and it's bounded by pv_snprintf() so it can't overshoot
|
||||
* the filename buffer. When we chmod $HOME/.pv, we assume that an
|
||||
* attacker is unlikely to be able to manipulate $HOME's contents to
|
||||
* make use of us setting $HOME/.pv to mode 700.
|
||||
* cannot be manipulated, and the final component is not allowed to
|
||||
* be a symbolic link. $HOME is checked for a NULL value, and the
|
||||
* filename is bounded by pv_snprintf() so it can't overshoot the
|
||||
* filename buffer. When chmod() is called on $HOME/.pv, an
|
||||
* attacker is assumed to be unlikely to be able to manipulate
|
||||
* $HOME's contents to make use of $HOME/.pv's mode of 700.
|
||||
*/
|
||||
|
||||
if (control_fd < 0)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Formatter function for average rate.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -25,20 +25,20 @@ pvdisplay_bytecount_t pv_formatter_average_rate(pvformatter_args_t args)
|
||||
|
||||
/*@-mustfreefresh@ */
|
||||
if (args->control->numeric) {
|
||||
/* numeric - raw value without suffix. */
|
||||
/* Numeric - raw value without suffix. */
|
||||
(void) pv_snprintf(content, sizeof(content),
|
||||
"%.4Lf", ((args->control->bits ? 8.0 : 1.0) * args->calc->average_rate));
|
||||
} else if (args->control->bits && !args->control->linemode) {
|
||||
/* bits per second */
|
||||
/* Bits per second. */
|
||||
pv_describe_amount(content, sizeof(content),
|
||||
"(%s)", 8 * args->calc->average_rate, "", _("b/s"), args->display->count_type);
|
||||
} else {
|
||||
/* bytes or lines per second */
|
||||
/* Bytes or lines per second. */
|
||||
pv_describe_amount(content,
|
||||
sizeof(content), "(%s)", args->calc->average_rate, _("/s"), _("B/s"),
|
||||
args->display->count_type);
|
||||
}
|
||||
/*@+mustfreefresh@ *//* splint: see above. */
|
||||
/*@+mustfreefresh@ *//* splint - false positive from gettext(). */
|
||||
|
||||
return pv_formatter_segmentcontent(content, args);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Formatter functions for styled progress bars.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -39,7 +39,7 @@ static bool pv_barstyle(pvformatter_args_t args, pvbarstyle_t style, const char
|
||||
}
|
||||
/*
|
||||
* flawfinder - strlen() on null-terminated static strings is OK,
|
||||
* and with the memcpy(), we check the buffer is big enough.
|
||||
* and with the memcpy(), the buffer size has been checked.
|
||||
*/
|
||||
|
||||
memset(style, 0, sizeof(*style));
|
||||
@@ -169,7 +169,7 @@ pvdisplay_bytecount_t pv_formatter_bar_default(pvformatter_args_t args)
|
||||
if (NULL == default_name)
|
||||
default_name = "plain";
|
||||
/*@+branchstate@ */
|
||||
/* splint - it doesn't matter that default_name may be static */
|
||||
/* splint - it doesn't matter that default_name may be static. */
|
||||
args->segment->parameter = 1 + pv_display_barstyle_index(args, default_name);
|
||||
}
|
||||
return pv_formatter_progress_bar_only(args);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Formatter function for transfer buffer percentage utilisation.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -30,10 +30,22 @@ pvdisplay_bytecount_t pv_formatter_buffer_percent(pvformatter_args_t args)
|
||||
(args->transfer->buffer_size));
|
||||
(void) pv_snprintf(content, sizeof(content), "{%3.0f%%}", pct_used);
|
||||
}
|
||||
#ifdef HAVE_SPLICE
|
||||
if (args->transfer->splice_used)
|
||||
switch (args->transfer->method) {
|
||||
case PV_TRANSFERMETHOD_READWRITE:
|
||||
break;
|
||||
case PV_TRANSFERMETHOD_SPLICE:
|
||||
(void) pv_snprintf(content, sizeof(content), "{%s}", "----");
|
||||
#endif
|
||||
break;
|
||||
case PV_TRANSFERMETHOD_SPLICE_INTERMEDIATE:
|
||||
(void) pv_snprintf(content, sizeof(content), "{%s}", "-||-");
|
||||
break;
|
||||
case PV_TRANSFERMETHOD_COPY_FILE_RANGE:
|
||||
(void) pv_snprintf(content, sizeof(content), "{%s}", "--->");
|
||||
break;
|
||||
case PV_TRANSFERMETHOD__UNSET:
|
||||
(void) pv_snprintf(content, sizeof(content), "{%s}", "????");
|
||||
break;
|
||||
}
|
||||
|
||||
return pv_formatter_segmentcontent(content, args);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Formatter function for bytes or lines transferred.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Formatter function for OSC 9;4 - ConEmu progress bar - codes.
|
||||
*
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_MATH_H
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Populate a buffer with OSC 9;4 progress bar codes for terminal title
|
||||
* tabs, returning the length of the string.
|
||||
*/
|
||||
size_t pv_osc94_format(char *buffer, size_t bufsize, readonly_pvcontrol_t control, readonly_pvtransfercalc_t calc)
|
||||
{
|
||||
int formatted_size = 0;
|
||||
|
||||
if (NULL == buffer)
|
||||
return 0;
|
||||
if (bufsize < 1)
|
||||
return 0;
|
||||
buffer[0] = '\0';
|
||||
|
||||
if (control->size > 0 || control->rate_gauge) {
|
||||
/* Known size or rate gauge - percentage progress. */
|
||||
formatted_size = pv_snprintf(buffer, bufsize, "\033]9;4;1;%.0f\033\\", calc->percentage);
|
||||
} else {
|
||||
/* Unknown size - indeterminate progress. */
|
||||
/* See pv_formatter_progress_unknownsize() in progressbar.c. */
|
||||
double indicator_position;
|
||||
|
||||
indicator_position = calc->percentage;
|
||||
if (indicator_position > 200.0)
|
||||
#if HAVE_FMOD
|
||||
indicator_position = fmod(indicator_position, 200.0);
|
||||
#else
|
||||
{
|
||||
while (indicator_position > 200.0)
|
||||
indicator_position -= 200.0;
|
||||
}
|
||||
#endif
|
||||
if (indicator_position > 100.0) {
|
||||
indicator_position = 200.0 - indicator_position;
|
||||
}
|
||||
if (indicator_position < 0.0) {
|
||||
indicator_position = 0.0;
|
||||
}
|
||||
|
||||
formatted_size = pv_snprintf(buffer, bufsize, "\033]9;4;3;%.0f\033\\", indicator_position);
|
||||
}
|
||||
|
||||
if (formatted_size < 0)
|
||||
return 0;
|
||||
if (formatted_size >= (int) bufsize)
|
||||
return bufsize - 1;
|
||||
return (size_t) formatted_size;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Produce OSC 9;4 progress bar codes for terminal title tabs.
|
||||
*/
|
||||
pvdisplay_bytecount_t pv_formatter_progress_conemu(pvformatter_args_t args)
|
||||
{
|
||||
char content[128]; /* flawfinder: ignore */
|
||||
|
||||
/* flawfinder - null-terminated and bounded with pv_snprintf(). */
|
||||
|
||||
memset(content, 0, sizeof(content));
|
||||
|
||||
(void) pv_osc94_format(content, sizeof(content), args->control, args->calc);
|
||||
|
||||
args->display->using_osc94 = true;
|
||||
|
||||
return pv_formatter_segmentcontent(content, args);
|
||||
}
|
||||
+20
-9
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Formatter function for ETA display.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -10,14 +10,16 @@
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
/*
|
||||
* Estimated time until completion.
|
||||
*/
|
||||
pvdisplay_bytecount_t pv_formatter_eta(pvformatter_args_t args)
|
||||
{
|
||||
char content[128]; /* flawfinder: ignore - always bounded */
|
||||
long eta;
|
||||
char content[128]; /* flawfinder: ignore - bounded in pv_snprintf(). */
|
||||
long eta, max_days;
|
||||
|
||||
content[0] = '\0';
|
||||
|
||||
@@ -34,11 +36,20 @@ pvdisplay_bytecount_t pv_formatter_eta(pvformatter_args_t args)
|
||||
pv_seconds_remaining((args->transfer->transferred - args->display->initial_offset),
|
||||
args->control->size - args->display->initial_offset, args->calc->current_avg_rate);
|
||||
|
||||
/*
|
||||
* Bounds check, so we don't overrun the suffix buffer. This means
|
||||
* the ETA will always be less than 100,000 hours.
|
||||
*/
|
||||
eta = pv_bound_long(eta, 0, (long) 360000000L);
|
||||
/* The ETA must always be positive. */
|
||||
if (eta < 0)
|
||||
eta = 0;
|
||||
|
||||
/* The ETA must be under 1,000,000 days so it's not too wide. */
|
||||
/* If a "long" is 32 bits, only 24,855 days will fit in it. */
|
||||
max_days = 24855L;
|
||||
#ifdef LONG_MAX
|
||||
if (LONG_MAX > 2147483647L)
|
||||
max_days = 1000000;
|
||||
#endif
|
||||
|
||||
if ((eta / 86400L) >= max_days)
|
||||
eta = max_days * 86400L - 1L;
|
||||
|
||||
/*
|
||||
* If the ETA is more than a day, include a day count as well as
|
||||
@@ -55,7 +66,7 @@ pvdisplay_bytecount_t pv_formatter_eta(pvformatter_args_t args)
|
||||
sizeof(content),
|
||||
"%.16s %ld:%02ld:%02ld", _("ETA"), eta / 3600, (eta / 60) % 60, eta % 60);
|
||||
}
|
||||
/*@+mustfreefresh@ *//* splint: see above. */
|
||||
/*@+mustfreefresh@ *//* splint: false positives from gettext(). */
|
||||
|
||||
/*
|
||||
* If this is the final update, show a blank space where the ETA
|
||||
|
||||
+22
-9
@@ -2,7 +2,7 @@
|
||||
* Formatter function for the local time at which the transfer is expected
|
||||
* to complete.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
/*
|
||||
@@ -20,10 +21,10 @@
|
||||
*/
|
||||
pvdisplay_bytecount_t pv_formatter_fineta(pvformatter_args_t args)
|
||||
{
|
||||
char content[128]; /* flawfinder: ignore - always bounded */
|
||||
char content[128]; /* flawfinder: ignore - bounded by strftime(). */
|
||||
time_t now, then;
|
||||
struct tm *time_ptr;
|
||||
long eta;
|
||||
const struct tm *time_ptr;
|
||||
long eta, max_years;
|
||||
const char *time_format;
|
||||
bool show_fineta;
|
||||
|
||||
@@ -43,15 +44,27 @@ pvdisplay_bytecount_t pv_formatter_fineta(pvformatter_args_t args)
|
||||
time_format = NULL;
|
||||
|
||||
/*
|
||||
* The completion clock time may be hidden by a failed localtime
|
||||
* lookup.
|
||||
* Note that the completion clock time may be hidden by a failed
|
||||
* localtime lookup.
|
||||
*/
|
||||
|
||||
eta = pv_seconds_remaining(args->transfer->transferred - args->display->initial_offset,
|
||||
args->control->size - args->display->initial_offset, args->calc->current_avg_rate);
|
||||
|
||||
/* Bounds check - see pv_formatter_eta(). */
|
||||
eta = pv_bound_long(eta, 0, (long) 360000000L);
|
||||
/* The ETA must always be positive. */
|
||||
if (eta < 0)
|
||||
eta = 0;
|
||||
|
||||
/* Clamp the ETA to 7,000 years max so the date isn't too wide. */
|
||||
/* If a "long" is 32 bits, only 68 years will fit in it. */
|
||||
max_years = 68;
|
||||
#ifdef LONG_MAX
|
||||
if (LONG_MAX > 2147483647L)
|
||||
max_years = 7000;
|
||||
#endif
|
||||
|
||||
if ((eta / 31536000L) > max_years)
|
||||
eta = 31536000L * max_years;
|
||||
|
||||
/*
|
||||
* Only include the date if the ETA is more than 6 hours
|
||||
@@ -78,7 +91,7 @@ pvdisplay_bytecount_t pv_formatter_fineta(pvformatter_args_t args)
|
||||
|
||||
/*@-mustfreefresh@ */
|
||||
(void) pv_snprintf(content, sizeof(content), "%.16s ", _("FIN"));
|
||||
/*@+mustfreefresh@ *//* splint: see above. */
|
||||
/*@+mustfreefresh@ *//* splint: false positive from gettext(). */
|
||||
content_bytes = strlen(content); /* flawfinder: ignore */
|
||||
/* flawfinder: always bounded with \0 by pv_snprintf(). */
|
||||
(void) strftime(content + content_bytes, sizeof(content) - 1 - content_bytes, time_format, &time);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Formatter function for showing the last bytes written.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Formatter function for showing the name of the transfer.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Formatter function for the most recently written line.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
+12
-12
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Formatter functions for progress bars.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -24,8 +24,8 @@
|
||||
} \
|
||||
}
|
||||
/*
|
||||
* flawfinder - we are checking that there is room in the destination
|
||||
* buffer, given its size and our current offset.
|
||||
* flawfinder - the byte count and offset are checked against the buffer
|
||||
* size before memcpy() is called.
|
||||
*/
|
||||
|
||||
|
||||
@@ -87,15 +87,15 @@ static pvdisplay_bytecount_t pv_formatter_progress_knownsize(pvformatter_args_t
|
||||
|
||||
/*@-mustfreefresh@ */
|
||||
if (args->control->bits && !args->control->linemode) {
|
||||
/* bits per second */
|
||||
/* Bits per second. */
|
||||
pv_describe_amount(after_bar, sizeof(after_bar), "/%s",
|
||||
8.0 * args->calc->rate_max, "", _("b/s"), args->display->count_type);
|
||||
} else {
|
||||
/* bytes or lines per second */
|
||||
/* Bytes or lines per second. */
|
||||
pv_describe_amount(after_bar, sizeof(after_bar),
|
||||
"/%s", args->calc->rate_max, _("/s"), _("B/s"), args->display->count_type);
|
||||
}
|
||||
/*@+mustfreefresh@ *//* splint: see above about gettext(). */
|
||||
/*@+mustfreefresh@ *//* splint: false positives from gettext(). */
|
||||
}
|
||||
|
||||
if (!include_amount)
|
||||
@@ -113,7 +113,7 @@ static pvdisplay_bytecount_t pv_formatter_progress_knownsize(pvformatter_args_t
|
||||
if (buffer_size < after_bar_bytes)
|
||||
return 0;
|
||||
if (after_bar_bytes > 1) {
|
||||
/* NB we skip the leading space. */
|
||||
/* NB skip the leading space. */
|
||||
memmove(buffer, after_bar + 1, after_bar_bytes - 1);
|
||||
buffer[after_bar_bytes - 1] = '\0';
|
||||
return after_bar_bytes - 1;
|
||||
@@ -161,7 +161,7 @@ static pvdisplay_bytecount_t pv_formatter_progress_knownsize(pvformatter_args_t
|
||||
pad_count += style->tip.width;
|
||||
}
|
||||
|
||||
/* A partial cell, if there are intermediates and we're not at 100%. */
|
||||
/* A partial cell, if below 100% and there are intermediates. */
|
||||
if (pad_count < bar_area_width && full_cell_index > 1 && !has_tip) {
|
||||
double exact_width = (((double) bar_area_width) * bar_percentage) / 100.0;
|
||||
double cell_portion = exact_width - (double) filled_bar_width;
|
||||
@@ -242,8 +242,8 @@ static pvdisplay_bytecount_t pv_formatter_progress_unknownsize(pvformatter_args_
|
||||
/*
|
||||
* Note that pv_calculate_transfer_rate() sets the percentage when
|
||||
* the size is unknown to a value that goes 0 - 200 and resets, so
|
||||
* here we make values above 100 send the indicator back down again,
|
||||
* so it moves back and forth.
|
||||
* here this is used make values above 100 send the indicator back
|
||||
* down again, so it moves back and forth.
|
||||
*/
|
||||
indicator_position = args->calc->percentage;
|
||||
if (indicator_position > 200.0)
|
||||
@@ -319,7 +319,7 @@ pvdisplay_bytecount_t pv_formatter_progress(pvformatter_args_t args)
|
||||
if (NULL == default_name)
|
||||
default_name = "plain";
|
||||
/*@+branchstate@ */
|
||||
/* splint - it doesn't matter that default_name may be static */
|
||||
/* splint - it doesn't matter that default_name may be static. */
|
||||
args->segment->parameter = 1 + pv_display_barstyle_index(args, default_name);
|
||||
}
|
||||
|
||||
@@ -357,7 +357,7 @@ pvdisplay_bytecount_t pv_formatter_progress_bar_only(pvformatter_args_t args)
|
||||
if (NULL == default_name)
|
||||
default_name = "plain";
|
||||
/*@+branchstate@ */
|
||||
/* splint - it doesn't matter that default_name may be static */
|
||||
/* splint - it doesn't matter that default_name may be static. */
|
||||
args->segment->parameter = 1 + pv_display_barstyle_index(args, default_name);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Formatter function for the current rate of transfer.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -27,19 +27,19 @@ pvdisplay_bytecount_t pv_formatter_rate(pvformatter_args_t args)
|
||||
|
||||
/*@-mustfreefresh@ */
|
||||
if (args->control->numeric) {
|
||||
/* numeric - raw value without suffix. */
|
||||
/* Numeric - raw value without suffix. */
|
||||
(void) pv_snprintf(content, sizeof(content),
|
||||
"%.4Lf", ((args->control->bits ? 8.0 : 1.0) * args->calc->transfer_rate));
|
||||
} else if (args->control->bits && !args->control->linemode) {
|
||||
/* bits per second */
|
||||
/* Bits per second. */
|
||||
pv_describe_amount(content, sizeof(content), "[%s]",
|
||||
8 * args->calc->transfer_rate, "", _("b/s"), args->display->count_type);
|
||||
} else {
|
||||
/* bytes or lines per second */
|
||||
/* Bytes or lines per second. */
|
||||
pv_describe_amount(content, sizeof(content),
|
||||
"[%s]", args->calc->transfer_rate, _("/s"), _("B/s"), args->display->count_type);
|
||||
}
|
||||
/*@+mustfreefresh@ *//* splint: see above. */
|
||||
/*@+mustfreefresh@ *//* splint - false positives from gettext(). */
|
||||
|
||||
return pv_formatter_segmentcontent(content, args);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Formatter function for ratio of bytes transferred by the other monitored
|
||||
* side to bytes transferred by this side.
|
||||
*
|
||||
* Copyright 2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
|
||||
|
||||
/*
|
||||
* Ratio of bytes or lines transferred by the other monitored side ("-M
|
||||
* both") to the bytes or lines transferred by this side.
|
||||
*/
|
||||
pvdisplay_bytecount_t pv_formatter_ratio(pvformatter_args_t args)
|
||||
{
|
||||
char content[128]; /* flawfinder: ignore - always bounded */
|
||||
|
||||
args->display->showing_ratio = true;
|
||||
|
||||
if (0 == args->buffer_size)
|
||||
return 0;
|
||||
|
||||
content[0] = '\0';
|
||||
|
||||
if (0 == args->transfer->otherside_transferred || 0 == args->transfer->transferred) {
|
||||
(void) pv_snprintf(content, sizeof(content), "%s:%s", "-", "-");
|
||||
} else if (args->transfer->otherside_transferred == args->transfer->transferred) {
|
||||
(void) pv_snprintf(content, sizeof(content), "%d:%d", 1, 1);
|
||||
} else {
|
||||
long double side1, side2, ratio;
|
||||
|
||||
side1 = (long double) (args->transfer->otherside_transferred);
|
||||
side2 = (long double) (args->transfer->transferred);
|
||||
|
||||
if (side1 > side2) {
|
||||
ratio = side1 / side2;
|
||||
(void) pv_snprintf(content, sizeof(content), "%.4Lg:%d", ratio, 1);
|
||||
} else {
|
||||
ratio = side2 / side1;
|
||||
(void) pv_snprintf(content, sizeof(content), "%d:%.4Lg", 1, ratio);
|
||||
}
|
||||
}
|
||||
|
||||
return pv_formatter_segmentcontent(content, args);
|
||||
}
|
||||
+13
-9
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Formatter function for ECMA-48 SGR codes.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -72,10 +72,10 @@ struct sgr_keyword_map_s {
|
||||
{ "bg-default", 0, 49 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
int keyword_index;
|
||||
|
||||
/* Calculate the lengths of each keyword on the first call. */
|
||||
if (0 == keywords[0].bytes) {
|
||||
int keyword_index;
|
||||
for (keyword_index = 0; NULL != keywords[keyword_index].keyword; keyword_index++) {
|
||||
keywords[keyword_index].bytes = strlen(keywords[keyword_index].keyword); /* flawfinder: ignore */
|
||||
/* flawfinder - strlen() on a static null-terminated string is OK. */
|
||||
@@ -86,7 +86,7 @@ struct sgr_keyword_map_s {
|
||||
return keywords;
|
||||
/*@+compmempass@ */
|
||||
/*
|
||||
* splint - found no other way to pass static back without a false
|
||||
* splint - no other way to pass static back without a false
|
||||
* positive warning about a memory leak.
|
||||
*/
|
||||
}
|
||||
@@ -99,6 +99,7 @@ pvdisplay_bytecount_t pv_formatter_sgr(pvformatter_args_t args)
|
||||
{
|
||||
/*@keep@ */ static struct sgr_keyword_map_s *keywords;
|
||||
char content[1024]; /* flawfinder: ignore */
|
||||
size_t content_buffer_size = sizeof(content);
|
||||
pvdisplay_bytecount_t write_position, read_position, keyword_start, keyword_length;
|
||||
int numeric_value, code_count, most_recent_code;
|
||||
|
||||
@@ -175,23 +176,26 @@ pvdisplay_bytecount_t pv_formatter_sgr(pvformatter_args_t args)
|
||||
debug("code=%d", code);
|
||||
|
||||
if (code >= 0) {
|
||||
if (code_count > 15) {
|
||||
if (code_count > 15 && write_position < content_buffer_size) {
|
||||
write_position +=
|
||||
pv_snprintf(content + write_position, sizeof(content) - write_position,
|
||||
"%s", "m");
|
||||
code_count = 0;
|
||||
}
|
||||
if (0 == code_count) {
|
||||
if (0 == code_count && write_position < content_buffer_size) {
|
||||
write_position +=
|
||||
pv_snprintf(content + write_position, sizeof(content) - write_position,
|
||||
"%s", "\033[");
|
||||
} else {
|
||||
} else if (write_position < content_buffer_size) {
|
||||
write_position +=
|
||||
pv_snprintf(content + write_position, sizeof(content) - write_position,
|
||||
"%s", ";");
|
||||
}
|
||||
write_position +=
|
||||
pv_snprintf(content + write_position, sizeof(content) - write_position, "%d", code);
|
||||
if (write_position < content_buffer_size) {
|
||||
write_position +=
|
||||
pv_snprintf(content + write_position, sizeof(content) - write_position,
|
||||
"%d", code);
|
||||
}
|
||||
code_count++;
|
||||
most_recent_code = code;
|
||||
}
|
||||
@@ -201,7 +205,7 @@ pvdisplay_bytecount_t pv_formatter_sgr(pvformatter_args_t args)
|
||||
}
|
||||
}
|
||||
|
||||
if (code_count > 0)
|
||||
if (code_count > 0 && write_position < content_buffer_size)
|
||||
write_position += pv_snprintf(content + write_position, sizeof(content) - write_position, "%s", "m");
|
||||
|
||||
if (most_recent_code > 0) {
|
||||
|
||||
+16
-13
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Formatter function for the elapsed transfer time.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
pvdisplay_bytecount_t pv_formatter_timer(pvformatter_args_t args)
|
||||
{
|
||||
char content[128]; /* flawfinder: ignore - always bounded */
|
||||
char content[128]; /* flawfinder: ignore - bounded with pv_snprintf(). */
|
||||
long double elapsed_seconds;
|
||||
|
||||
args->display->showing_timer = true;
|
||||
@@ -28,21 +28,24 @@ pvdisplay_bytecount_t pv_formatter_timer(pvformatter_args_t args)
|
||||
|
||||
elapsed_seconds = args->transfer->elapsed_seconds;
|
||||
|
||||
/*
|
||||
* Bounds check, so we don't overrun the prefix buffer. This does
|
||||
* mean that the timer will stop at a 100,000 hours, but since
|
||||
* that's 11 years, it shouldn't be a problem.
|
||||
*/
|
||||
if (elapsed_seconds > (long double) 360000000.0L)
|
||||
elapsed_seconds = (long double) 360000000.0L;
|
||||
|
||||
/* Also check it's not negative. */
|
||||
if (elapsed_seconds < 0.0)
|
||||
elapsed_seconds = 0.0;
|
||||
/* The timer must always be positive. */
|
||||
if (elapsed_seconds < 0.0L)
|
||||
elapsed_seconds = 0.0L;
|
||||
|
||||
if (args->control->numeric) {
|
||||
/* Numeric mode - show the number of seconds, unformatted. */
|
||||
(void) pv_snprintf(content, sizeof(content), "%.4Lf", elapsed_seconds);
|
||||
} else if (elapsed_seconds > (long double) (999999.999999L * 86400.0L)) {
|
||||
/*
|
||||
* At a million days, the timer would be too wide, so avoid
|
||||
* an overflow.
|
||||
*/
|
||||
(void) pv_snprintf(content,
|
||||
sizeof(content),
|
||||
"%s:%02ld:%02ld:%02ld",
|
||||
">=1e6",
|
||||
(((long) (elapsed_seconds)) / 3600) %
|
||||
24, (((long) (elapsed_seconds)) / 60) % 60, ((long) (elapsed_seconds)) % 60);
|
||||
} else if (elapsed_seconds > (long double) 86400.0L) {
|
||||
/*
|
||||
* If the elapsed time is more than a day, include a day count as
|
||||
|
||||
+416
-106
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* Functions providing the main transfer or file descriptor watching loop.
|
||||
* Functions providing the main transfer loop, the file descriptor watching
|
||||
* loop, and the query loop (watching another PV process).
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -24,11 +25,19 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
#elif HAVE_SYS_POLL_H
|
||||
#include <sys/poll.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_MATH_H
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
int pv_remote_transferstate_fetch(pvstate_t, pid_t, /*@null@ */ off_t *, bool);
|
||||
void pv_end_display(void);
|
||||
void pv_report_signal_interrupt(int);
|
||||
|
||||
|
||||
#if HAVE_SQRTL
|
||||
@@ -53,9 +62,18 @@ static long ldsqrt(long double value)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Turn off the OSC 9;4 (ConEmu) progress bar.
|
||||
*/
|
||||
static void pv_clear_osc94(pvstate_t state)
|
||||
{
|
||||
pv_tty_write(&(state->flags), "\033]9;4;0;0\033\\", 11);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If the flag is set to say that a terminal resize signal was received,
|
||||
* clear the flag and resize the display, and return true.
|
||||
* clear the flag, resize the display, and return true.
|
||||
*/
|
||||
static bool pv__resize_display_on_signal(pvstate_t state)
|
||||
{
|
||||
@@ -81,6 +99,48 @@ static bool pv__resize_display_on_signal(pvstate_t state)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return true if the write end of a pipe reports that its readers have gone
|
||||
* away. This is only used after PV has reached EOF and is waiting for the
|
||||
* output pipe buffer to drain; live readers still get the existing behaviour.
|
||||
*/
|
||||
static bool pv__output_pipe_has_no_reader(int output_fd)
|
||||
{
|
||||
#if HAVE_POLL && (HAVE_POLL_H || HAVE_SYS_POLL_H)
|
||||
struct pollfd pfd;
|
||||
int result;
|
||||
|
||||
memset(&pfd, 0, sizeof(pfd));
|
||||
pfd.fd = output_fd;
|
||||
pfd.events = POLLOUT;
|
||||
|
||||
result = poll(&pfd, 1, 0);
|
||||
if (result < 0) {
|
||||
if (EINTR != errno) {
|
||||
debug("%s(%d): %s", "poll", output_fd, strerror(errno));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (0 == result)
|
||||
return false;
|
||||
|
||||
#if defined(POLLERR)
|
||||
if (0 != (pfd.revents & POLLERR))
|
||||
return true;
|
||||
#endif
|
||||
#if defined(POLLHUP)
|
||||
if (0 != (pfd.revents & POLLHUP))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
#else
|
||||
(void) output_fd;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculate and display the transfer statistics at the end of the transfer,
|
||||
* if stats are enabled and any measurements were taken.
|
||||
@@ -95,7 +155,7 @@ static void pv__show_stats(pvstate_t state)
|
||||
long double rate_mean, rate_variance, rate_deviation;
|
||||
int stats_size;
|
||||
|
||||
/* flawfinder: made safe by use of pv_snprintf() */
|
||||
/* flawfinder: made safe by use of pv_snprintf(). */
|
||||
|
||||
rate_mean = state->calc.rate_sum / ((long double) (state->calc.measurements_taken));
|
||||
rate_variance =
|
||||
@@ -122,11 +182,11 @@ static void pv__show_stats(pvstate_t state)
|
||||
|
||||
if (stats_size > 0 && stats_size < (int) (sizeof(stats_buf)))
|
||||
pv_tty_write(&(state->flags), stats_buf, (size_t) stats_size);
|
||||
} else if (state->control.show_stats && state->calc.measurements_taken < 1) {
|
||||
} else {
|
||||
char msg_buf[256]; /* flawfinder: ignore */
|
||||
int msg_size;
|
||||
|
||||
/* flawfinder: made safe by use of pv_snprintf() */
|
||||
/* flawfinder: made safe by use of pv_snprintf(). */
|
||||
|
||||
memset(msg_buf, 0, sizeof(msg_buf));
|
||||
msg_size = pv_snprintf(msg_buf, sizeof(msg_buf), "%s\n", _("rate not measured"));
|
||||
@@ -151,8 +211,8 @@ static long double pv__elapsed_transfer_time(const struct timespec *loop_start_t
|
||||
memset(&transfer_elapsed, 0, sizeof(transfer_elapsed));
|
||||
|
||||
/*
|
||||
* Calculate the effective start time: the time we actually started,
|
||||
* plus the total time we spent stopped.
|
||||
* Calculate the effective start time: the time the loop started,
|
||||
* plus the total time spent stopped.
|
||||
*/
|
||||
pv_elapsedtime_add(&effective_start_time, loop_start_time, total_stoppage_time);
|
||||
|
||||
@@ -167,7 +227,128 @@ static long double pv__elapsed_transfer_time(const struct timespec *loop_start_t
|
||||
|
||||
|
||||
/*
|
||||
* Pipe data from a list of files to standard output, giving information
|
||||
* Exchange information with the other side of the "-M both" monitor about
|
||||
* the amount of data transferred.
|
||||
*/
|
||||
static void pv__monitor_exchange(pvstate_t state)
|
||||
{
|
||||
bool written_yet = false;
|
||||
|
||||
while ((state->control.othermonitor_read_fd >= 0) || (state->control.othermonitor_write_fd >= 0)) {
|
||||
struct timeval tv;
|
||||
fd_set readfds;
|
||||
fd_set writefds;
|
||||
fd_set exceptfds;
|
||||
int max_fd;
|
||||
int result;
|
||||
|
||||
max_fd = -1;
|
||||
if (state->control.othermonitor_read_fd > max_fd)
|
||||
max_fd = state->control.othermonitor_read_fd;
|
||||
if ((!written_yet) && (state->control.othermonitor_write_fd > max_fd))
|
||||
max_fd = state->control.othermonitor_write_fd;
|
||||
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
|
||||
#if SPLINT
|
||||
/* splint doesn't like FD_ZERO, FD_SET, FD_ISSET. */
|
||||
/* Refer to src/pv/transfer.c for more details. */
|
||||
memset(&readfds, 0, sizeof(readfds));
|
||||
memset(&writefds, 0, sizeof(writefds));
|
||||
memset(&exceptfds, 0, sizeof(exceptfds));
|
||||
#else /* !SPLINT */
|
||||
FD_ZERO(&readfds);
|
||||
FD_ZERO(&writefds);
|
||||
FD_ZERO(&exceptfds);
|
||||
if (state->control.othermonitor_read_fd >= 0)
|
||||
FD_SET(state->control.othermonitor_read_fd, &readfds);
|
||||
if ((!written_yet) && (state->control.othermonitor_write_fd >= 0))
|
||||
FD_SET(state->control.othermonitor_write_fd, &writefds);
|
||||
#endif /* !SPLINT */
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
result = select(max_fd + 1, &readfds, &writefds, &exceptfds, &tv);
|
||||
|
||||
/* End the loop if the select() failed or there's no action to take. */
|
||||
if (result <= 0)
|
||||
break;
|
||||
|
||||
if ((state->control.othermonitor_read_fd >= 0)
|
||||
#ifndef SPLINT
|
||||
&& (FD_ISSET(state->control.othermonitor_read_fd, &readfds))
|
||||
#endif
|
||||
) {
|
||||
off_t otherside_transferred;
|
||||
ssize_t nread;
|
||||
|
||||
/* Read the position of the other monitor. */
|
||||
|
||||
otherside_transferred = 0;
|
||||
|
||||
nread = read(state->control.othermonitor_read_fd, &otherside_transferred, /* flawfinder: ignore */
|
||||
sizeof(otherside_transferred));
|
||||
/*
|
||||
* flawfinder rationale: no buffer overflow possible
|
||||
* as the read() is of a fixed size, to a fixed
|
||||
* position.
|
||||
*/
|
||||
|
||||
if (0 == nread) {
|
||||
/* EOF - close. */
|
||||
debug("%d: %s", state->control.othermonitor_read_fd, "EOF - closing");
|
||||
(void) close(state->control.othermonitor_read_fd);
|
||||
state->control.othermonitor_read_fd = -1;
|
||||
} else if (nread < 0) {
|
||||
debug("%d: %s: %s", state->control.othermonitor_read_fd, "error on read",
|
||||
strerror(errno));
|
||||
} else if (nread != (ssize_t) (sizeof(otherside_transferred))) {
|
||||
debug("%d: %d: %s", state->control.othermonitor_read_fd, (int) nread,
|
||||
"incorrect byte count - ignoring");
|
||||
} else {
|
||||
debug("%s: %lu", "other side transfer amount", (unsigned long) otherside_transferred);
|
||||
state->transfer.otherside_transferred = otherside_transferred;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!written_yet) && (state->control.othermonitor_write_fd >= 0)
|
||||
#ifndef SPLINT
|
||||
&& (FD_ISSET(state->control.othermonitor_write_fd, &writefds))
|
||||
#endif
|
||||
) {
|
||||
ssize_t nwritten;
|
||||
|
||||
/* Write the current position to the other monitor. */
|
||||
|
||||
nwritten =
|
||||
write(state->control.othermonitor_write_fd, &(state->transfer.transferred),
|
||||
sizeof(state->transfer.transferred));
|
||||
|
||||
if ((nwritten < 0) && ((EINTR == errno) || (EAGAIN == errno))) {
|
||||
debug("%d: %s: %s", state->control.othermonitor_write_fd, "transient write error",
|
||||
strerror(errno));
|
||||
} else if (nwritten < 0) {
|
||||
debug("%d: %s: %s", state->control.othermonitor_write_fd, "write error - closing",
|
||||
strerror(errno));
|
||||
(void) close(state->control.othermonitor_write_fd);
|
||||
state->control.othermonitor_write_fd = -1;
|
||||
} else if (nwritten != (ssize_t) (sizeof(state->transfer.transferred))) {
|
||||
debug("%d: %d: %s", state->control.othermonitor_write_fd, (int) nwritten,
|
||||
"incorrect byte count written - closing");
|
||||
(void) close(state->control.othermonitor_write_fd);
|
||||
state->control.othermonitor_write_fd = -1;
|
||||
} else {
|
||||
written_yet = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Transfer data from a list of files to standard output, giving information
|
||||
* about the transfer on standard error according to the given options.
|
||||
*
|
||||
* Returns nonzero on error.
|
||||
@@ -176,16 +357,17 @@ int pv_main_loop(pvstate_t state)
|
||||
{
|
||||
long lineswritten;
|
||||
off_t cansend;
|
||||
long double rate_limited_target;
|
||||
ssize_t written;
|
||||
long double target;
|
||||
bool eof_in, eof_out, final_update;
|
||||
struct timespec start_time, next_update, next_ratecheck, cur_time;
|
||||
struct timespec next_remotecheck;
|
||||
struct timespec next_remotecheck, next_monitor_exchange;
|
||||
int input_fd, output_fd;
|
||||
unsigned int file_idx;
|
||||
bool output_is_pipe;
|
||||
|
||||
/*
|
||||
* Notes on line mode:
|
||||
*
|
||||
* "written" is ALWAYS bytes written by the last transfer.
|
||||
*
|
||||
* "lineswritten" is the lines written by the last transfer,
|
||||
@@ -198,22 +380,24 @@ int pv_main_loop(pvstate_t state)
|
||||
* The remaining variables are all unchanged by linemode.
|
||||
*/
|
||||
|
||||
input_fd = -1;
|
||||
|
||||
output_fd = state->control.output_fd;
|
||||
if (output_fd < 0)
|
||||
output_fd = STDOUT_FILENO;
|
||||
|
||||
/* Determine whether the output is a pipe. */
|
||||
output_is_pipe = false;
|
||||
/* Determine whether the output is a regular file, a pipe, or neither. */
|
||||
state->status.output_is_pipe = false;
|
||||
state->status.output_is_file = false;
|
||||
{
|
||||
struct stat sb;
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
if (0 == fstat(output_fd, &sb)) {
|
||||
/*@-type@ */
|
||||
if ((sb.st_mode & S_IFMT) == S_IFIFO) {
|
||||
output_is_pipe = true;
|
||||
debug("%s", "output is a pipe");
|
||||
state->status.output_is_pipe = true;
|
||||
debug("%s (fd %d)", "output is a pipe", output_fd);
|
||||
} else if ((sb.st_mode & S_IFMT) == S_IFREG) {
|
||||
state->status.output_is_file = true;
|
||||
debug("%s (fd %d)", "output is a regular file", output_fd);
|
||||
}
|
||||
/*@+type@ *//* splint says st_mode is __mode_t, not mode_t */
|
||||
} else {
|
||||
@@ -222,15 +406,21 @@ int pv_main_loop(pvstate_t state)
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that we could reduce the size of the output pipe buffer like
|
||||
* this, to avoid the case where we write a load of data and it just
|
||||
* goes into the buffer so we think we're done, but the consumer
|
||||
* takes ages to process it:
|
||||
* There can be a problem where data is written to the output and
|
||||
* from the writer's point of view, it's complete, but because the
|
||||
* consumer is processing it slowly, the data is really sitting in
|
||||
* the pipe buffer between the writer and the consumer. This gives
|
||||
* a misleading impression of progress.
|
||||
*
|
||||
* It could be avoided by reducing the size of the pipe buffer:
|
||||
*
|
||||
* fcntl(output_fd, F_SETPIPE_SZ, 4096);
|
||||
*
|
||||
* If we can peek at how much has been consumed by the other end, we
|
||||
* don't need to.
|
||||
* That isn't always available, and can have side effects such as
|
||||
* reducing efficiency. Instead, if the FIONREAD ioctl is
|
||||
* available, the amount of data waiting in the pipe buffer is
|
||||
* checked ("written_but_not_consumed"), and used to adjust the
|
||||
* reported progress.
|
||||
*/
|
||||
|
||||
pv_crs_init(&(state->cursor), &(state->control), &(state->flags));
|
||||
@@ -250,10 +440,12 @@ int pv_main_loop(pvstate_t state)
|
||||
|
||||
memset(&next_ratecheck, 0, sizeof(next_ratecheck));
|
||||
memset(&next_remotecheck, 0, sizeof(next_remotecheck));
|
||||
memset(&next_monitor_exchange, 0, sizeof(next_monitor_exchange));
|
||||
memset(&next_update, 0, sizeof(next_update));
|
||||
|
||||
pv_elapsedtime_copy(&next_ratecheck, &cur_time);
|
||||
pv_elapsedtime_copy(&next_remotecheck, &cur_time);
|
||||
pv_elapsedtime_copy(&next_monitor_exchange, &cur_time);
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
if ((state->control.delay_start > 0)
|
||||
&& (state->control.delay_start > state->control.interval)) {
|
||||
@@ -262,7 +454,7 @@ int pv_main_loop(pvstate_t state)
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval));
|
||||
}
|
||||
|
||||
target = 0;
|
||||
rate_limited_target = 0.0;
|
||||
final_update = false;
|
||||
file_idx = 0;
|
||||
|
||||
@@ -277,15 +469,17 @@ int pv_main_loop(pvstate_t state)
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit early if there was no readable input file.
|
||||
* Return early if there was no readable input file.
|
||||
*/
|
||||
if (input_fd < 0) {
|
||||
if (state->control.cursor)
|
||||
pv_crs_fini(&(state->cursor), &(state->control), &(state->flags));
|
||||
if (state->display.using_osc94)
|
||||
pv_clear_osc94(state);
|
||||
return state->status.exit_status;
|
||||
}
|
||||
#if HAVE_POSIX_FADVISE
|
||||
/* Advise the OS that we will only be reading sequentially. */
|
||||
/* Advise the OS that reads will all be sequential. */
|
||||
(void) posix_fadvise(input_fd, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
#endif
|
||||
|
||||
@@ -301,8 +495,8 @@ int pv_main_loop(pvstate_t state)
|
||||
|
||||
#if HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
/*
|
||||
* Set target buffer size if the initial file's block size can be
|
||||
* read and we weren't given a target buffer size.
|
||||
* Set the target buffer size if the initial file's block size can
|
||||
* be read and a target buffer size wasn't explicitly set already.
|
||||
*/
|
||||
if (0 == state->control.target_buffer_size) {
|
||||
struct stat sb;
|
||||
@@ -321,6 +515,46 @@ int pv_main_loop(pvstate_t state)
|
||||
if (0 == state->control.target_buffer_size)
|
||||
state->control.target_buffer_size = BUFFER_SIZE;
|
||||
|
||||
#ifdef F_GETPIPE_SZ
|
||||
#ifdef F_SETPIPE_SZ
|
||||
/*
|
||||
* If a pipe buffer size was explicitly set, then set the output
|
||||
* pipe buffer size to that.
|
||||
*
|
||||
* If no pipe buffer size was set, and the first input is a pipe,
|
||||
* then increase the output pipe buffer size to the same as the
|
||||
* input pipe buffer size, if the output buffer was smaller.
|
||||
*/
|
||||
if (state->status.output_is_pipe) {
|
||||
size_t target_pipe_buffer_size = state->control.pipe_buffer_size;
|
||||
|
||||
if (0 == target_pipe_buffer_size) {
|
||||
int input_pipe_size;
|
||||
input_pipe_size = fcntl(input_fd, F_GETPIPE_SZ);
|
||||
|
||||
debug("%s %d: %s=%d", "input fd", input_fd, "pipe size", input_pipe_size);
|
||||
if (input_pipe_size > 0) {
|
||||
int output_pipe_size;
|
||||
output_pipe_size = fcntl(output_fd, F_GETPIPE_SZ);
|
||||
debug("%s %d: %s=%d", "output fd", output_fd, "pipe size", output_pipe_size);
|
||||
if (output_pipe_size > 0 && output_pipe_size < input_pipe_size) {
|
||||
target_pipe_buffer_size = (size_t) input_pipe_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target_pipe_buffer_size > 0) {
|
||||
int output_pipe_size;
|
||||
|
||||
output_pipe_size = fcntl(output_fd, F_SETPIPE_SZ, (int) target_pipe_buffer_size);
|
||||
debug("%s %d: %s=%d", "output fd", output_fd, "updated pipe size", output_pipe_size);
|
||||
if (output_pipe_size < 0) {
|
||||
debug("%s: %s", "failed to set pipe buffer size", strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* F_SETPIPE_SZ */
|
||||
#endif /* F_GETPIPE_SZ */
|
||||
|
||||
/*
|
||||
* Repeat until eof_in is true, eof_out is true, and final_update is
|
||||
* true.
|
||||
@@ -338,33 +572,62 @@ int pv_main_loop(pvstate_t state)
|
||||
pv_elapsedtime_add_nsec(&next_remotecheck, REMOTE_INTERVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Exchange messages with the other side of the monitor
|
||||
* every short while, in monitor mode.
|
||||
*/
|
||||
if ((state->control.othermonitor_pid > 0)
|
||||
&& (pv_elapsedtime_compare(&cur_time, &next_monitor_exchange) > 0)) {
|
||||
pv__monitor_exchange(state);
|
||||
pv_elapsedtime_add_nsec(&next_monitor_exchange, MONITOR_EXCHANGE_INTERVAL);
|
||||
}
|
||||
|
||||
if (1 == state->flags.trigger_exit)
|
||||
break;
|
||||
|
||||
if (state->control.rate_limit > 0) {
|
||||
/*
|
||||
* If rate limiting is active, set "cansend" to the maximum
|
||||
* transfer amount allowable that would maintain the
|
||||
* requested rate.
|
||||
*/
|
||||
if (state->control.rate_limit_active) {
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_ratecheck) > 0) {
|
||||
target +=
|
||||
while (pv_elapsedtime_compare(&cur_time, &next_ratecheck) > 0) {
|
||||
rate_limited_target +=
|
||||
((long double) (state->control.rate_limit)) / (long double) (1000000000.0 /
|
||||
(long double)
|
||||
(RATE_GRANULARITY));
|
||||
/*
|
||||
* Cap the "target amount to transfer" so it
|
||||
* doesn't go too high - otherwise it just
|
||||
* keeps going up while there is no, or
|
||||
* slow, input data, and then when lots of
|
||||
* input data does arrive, the rate limit is
|
||||
* ineffective until the counter drops back
|
||||
* down (see PR #62).
|
||||
*
|
||||
* Only apply this cap if it is at least
|
||||
* 1.0, otherwise the target will always be
|
||||
* below 1, and nothing will ever get
|
||||
* transferred (see issue #193).
|
||||
*/
|
||||
long double burst_max = ((long double) (state->control.rate_limit * RATE_BURST_WINDOW));
|
||||
if (target > burst_max) {
|
||||
target = burst_max;
|
||||
if (burst_max > 1.0 && rate_limited_target > burst_max) {
|
||||
rate_limited_target = burst_max;
|
||||
}
|
||||
pv_elapsedtime_add_nsec(&next_ratecheck, RATE_GRANULARITY);
|
||||
}
|
||||
cansend = (off_t) target;
|
||||
cansend = (off_t) (rate_limited_target);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have to stop at "size" bytes, make sure we don't
|
||||
* try to write more than we're allowed to.
|
||||
* If stopping at "size" bytes, restrict "cansend" to keep
|
||||
* within that limit, and flag EOF when it is reached.
|
||||
*/
|
||||
if ((0 < state->control.size) && (state->control.stop_at_size)) {
|
||||
if ((state->control.size < (state->transfer.total_written + cansend))
|
||||
|| ((0 == cansend)
|
||||
&& (0 == state->control.rate_limit))) {
|
||||
&& (!state->control.rate_limit_active))) {
|
||||
cansend = state->control.size - state->transfer.total_written;
|
||||
if (0 >= cansend) {
|
||||
debug("%s", "write limit reached (size explicitly set) - setting EOF flags");
|
||||
@@ -386,17 +649,29 @@ int pv_main_loop(pvstate_t state)
|
||||
debug("%s: %s", "write error from pv_transfer", strerror(errno));
|
||||
if (state->control.cursor)
|
||||
pv_crs_fini(&(state->cursor), &(state->control), &(state->flags));
|
||||
if (state->display.using_osc94)
|
||||
pv_clear_osc94(state);
|
||||
return state->status.exit_status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Increment the total_written counter (lines or bytes
|
||||
* depending on line mode) by the amount written.
|
||||
*
|
||||
* If rate limiting is active, subtract the amount written
|
||||
* from the target amount to transfer. Whatever
|
||||
* (fractional) value is left will carry over to the next
|
||||
* loop iteration so that the transfer rate will average out
|
||||
* to the requested rate.
|
||||
*/
|
||||
if (state->control.linemode) {
|
||||
state->transfer.total_written += lineswritten;
|
||||
if (state->control.rate_limit > 0)
|
||||
target -= lineswritten;
|
||||
if (state->control.rate_limit_active)
|
||||
rate_limited_target -= lineswritten;
|
||||
} else {
|
||||
state->transfer.total_written += written;
|
||||
if (state->control.rate_limit > 0)
|
||||
target -= written;
|
||||
if (state->control.rate_limit_active)
|
||||
rate_limited_target -= written;
|
||||
}
|
||||
|
||||
#ifdef FIONREAD
|
||||
@@ -404,7 +679,7 @@ int pv_main_loop(pvstate_t state)
|
||||
* If writing to a pipe, look at how much is sitting in the
|
||||
* pipe buffer waiting for the receiver to read.
|
||||
*/
|
||||
if (output_is_pipe) {
|
||||
if (state->status.output_is_pipe) {
|
||||
int nbytes;
|
||||
nbytes = 0;
|
||||
if (0 != state->flags.pipe_closed) {
|
||||
@@ -429,25 +704,25 @@ int pv_main_loop(pvstate_t state)
|
||||
#endif
|
||||
|
||||
state->transfer.transferred = state->transfer.total_written;
|
||||
if (output_is_pipe && !state->control.linemode) {
|
||||
if (state->status.output_is_pipe && !state->control.linemode) {
|
||||
/*
|
||||
* Writing bytes to a pipe - the amount transferred
|
||||
* to the receiver is the total amount we've
|
||||
* written, minus what's sitting in the pipe buffer
|
||||
* waiting for the receiver to consume it.
|
||||
* to the receiver is the total amount written,
|
||||
* minus what's sitting in the pipe buffer waiting
|
||||
* for the receiver to consume it.
|
||||
*/
|
||||
state->transfer.transferred -= state->transfer.written_but_not_consumed;
|
||||
|
||||
} else if (output_is_pipe && state->control.linemode && state->transfer.written_but_not_consumed > 0
|
||||
&& NULL != state->transfer.line_positions) {
|
||||
} else if (state->status.output_is_pipe && state->control.linemode
|
||||
&& state->transfer.written_but_not_consumed > 0 && NULL != state->transfer.line_positions) {
|
||||
/*
|
||||
* Writing lines to a pipe - similar to above, but
|
||||
* we have to work out how many lines the
|
||||
* yet-to-be-consumed data in the buffer equates to.
|
||||
* with the added complication of having to
|
||||
* determine how many lines the yet-to-be-consumed
|
||||
* data in the buffer equates to.
|
||||
*
|
||||
* To do this, we walk backwards through our record
|
||||
* of the line positions in the output we've
|
||||
* written.
|
||||
* To do this, walk backwards through the record of
|
||||
* the line positions in the output.
|
||||
*/
|
||||
off_t last_consumed_position =
|
||||
state->transfer.last_output_position - state->transfer.written_but_not_consumed;
|
||||
@@ -459,10 +734,10 @@ int pv_main_loop(pvstate_t state)
|
||||
* positions[head-2] = position of second last separator written
|
||||
* etc
|
||||
*
|
||||
* We start at [head-1] and go backwards, wrapping
|
||||
* Start at [head-1] and go backwards, wrapping
|
||||
* around as it's a circular buffer, stopping at the
|
||||
* length (number of positions stored), or when we
|
||||
* have gone before the last consumed position.
|
||||
* length (number of positions stored), or after
|
||||
* going before the last consumed position.
|
||||
*/
|
||||
for (line_from_end = 0; line_from_end < state->transfer.line_positions_length; line_from_end++) {
|
||||
size_t array_index;
|
||||
@@ -493,7 +768,7 @@ int pv_main_loop(pvstate_t state)
|
||||
eof_in = false;
|
||||
eof_out = false;
|
||||
#if HAVE_POSIX_FADVISE
|
||||
/* Advise the OS that we will only be reading sequentially. */
|
||||
/* Advise the OS that reads will all be sequential. */
|
||||
(void) posix_fadvise(input_fd, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
#endif
|
||||
}
|
||||
@@ -503,9 +778,9 @@ int pv_main_loop(pvstate_t state)
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
|
||||
/*
|
||||
* If we've read everything and written everything, and the
|
||||
* output pipe buffer is empty, then set the final update
|
||||
* flag, and force a display update.
|
||||
* If everything has been read and written, and the output
|
||||
* pipe buffer is empty, then set the final update flag, and
|
||||
* force a display update.
|
||||
*/
|
||||
if (eof_in && eof_out && 0 == state->transfer.written_but_not_consumed) {
|
||||
final_update = true;
|
||||
@@ -513,24 +788,37 @@ int pv_main_loop(pvstate_t state)
|
||||
|| (state->control.delay_start < 0.001)) {
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
}
|
||||
/*
|
||||
* In "--monitor both" mode, run a final exchange of
|
||||
* information with the other side.
|
||||
*/
|
||||
if (state->control.othermonitor_pid > 0) {
|
||||
pv__monitor_exchange(state);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've read everything and written everything, and the
|
||||
* output pipe buffer is NOT empty, then pause a short while
|
||||
* so we don't spin in a tight loop waiting for the output
|
||||
* If everything has been read and written, and the output
|
||||
* pipe buffer is NOT empty, then pause a short while to
|
||||
* avoid spinning in a tight loop waiting for the output
|
||||
* buffer to empty (#164).
|
||||
*/
|
||||
if (eof_in && eof_out && state->transfer.written_but_not_consumed > 0) {
|
||||
debug("%s", "EOF but bytes remain in output pipe - sleeping");
|
||||
pv_nanosleep(50000000);
|
||||
if (pv__output_pipe_has_no_reader(output_fd)) {
|
||||
debug("%s", "EOF but output pipe readers are gone - clearing written_but_not_consumed");
|
||||
state->flags.pipe_closed = 1;
|
||||
state->transfer.written_but_not_consumed = 0;
|
||||
} else {
|
||||
debug("%s", "EOF but bytes remain in output pipe - sleeping");
|
||||
pv_nanosleep(50000000);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If -W was given, we don't output anything until we have
|
||||
* written a byte (or line, in line mode), at which point
|
||||
* we then count time as if we started when the first byte
|
||||
* was received.
|
||||
* If -W was given, produce no display until one byte (or
|
||||
* line, in line mode) has been written, at which point the
|
||||
* transfer time is counted as if it started when that first
|
||||
* byte was received.
|
||||
*/
|
||||
if (state->control.wait) {
|
||||
/* Restart the loop if nothing written yet. */
|
||||
@@ -546,13 +834,13 @@ int pv_main_loop(pvstate_t state)
|
||||
|
||||
/*
|
||||
* Reset the timer offset counter now that data
|
||||
* transfer has begun, otherwise if we had been
|
||||
* stopped and started (with ^Z / SIGTSTOP)
|
||||
* previously (while waiting for data), the timers
|
||||
* will be wrongly offset.
|
||||
* transfer has begun. Otherwise, if there had
|
||||
* already been a stop and start (with ^Z /
|
||||
* SIGTSTOP) while waiting for data, the timers
|
||||
* would be wrongly offset.
|
||||
*
|
||||
* While we reset the offset counter we must disable
|
||||
* SIGTSTOP so things don't mess up.
|
||||
* While this reset is being done, SIGTSTOP must be
|
||||
* disabled so it doesn't update the offset again.
|
||||
*/
|
||||
pv_sig_nopause();
|
||||
pv_elapsedtime_read(&start_time);
|
||||
@@ -572,8 +860,8 @@ int pv_main_loop(pvstate_t state)
|
||||
pv__elapsed_transfer_time(&start_time, &cur_time, &(state->signal.total_stoppage_time));
|
||||
|
||||
/*
|
||||
* Just go round the loop again if there's no display and
|
||||
* we're not reporting statistics.
|
||||
* Restart the loop if there's no display and statistics are
|
||||
* not being reported.
|
||||
*/
|
||||
if (state->control.no_display && !state->control.show_stats) {
|
||||
continue;
|
||||
@@ -616,8 +904,11 @@ int pv_main_loop(pvstate_t state)
|
||||
pv_tty_write(&(state->flags), "\n", 1);
|
||||
}
|
||||
|
||||
if (1 == state->flags.trigger_exit)
|
||||
state->status.exit_status |= PV_ERROREXIT_SIGNAL;
|
||||
if (state->display.using_osc94)
|
||||
pv_clear_osc94(state);
|
||||
|
||||
/* Tell the error routines that progress bar display has finished. */
|
||||
pv_end_display();
|
||||
|
||||
if (input_fd >= 0)
|
||||
(void) close(input_fd);
|
||||
@@ -625,6 +916,11 @@ int pv_main_loop(pvstate_t state)
|
||||
/* Calculate and display the transfer statistics. */
|
||||
pv__show_stats(state);
|
||||
|
||||
if (1 == state->flags.trigger_exit) {
|
||||
state->status.exit_status |= PV_ERROREXIT_SIGNAL;
|
||||
pv_report_signal_interrupt((int) (state->flags.terminating_signal));
|
||||
}
|
||||
|
||||
return state->status.exit_status;
|
||||
}
|
||||
|
||||
@@ -636,20 +932,20 @@ int pv_main_loop(pvstate_t state)
|
||||
static bool format_contains_name(const char *format_string)
|
||||
{
|
||||
while ('\0' != format_string[0]) {
|
||||
/* If we're not on a '%' character, move on. */
|
||||
/* If not on a '%' character, move on. */
|
||||
if ('%' != format_string[0]) {
|
||||
format_string++;
|
||||
continue;
|
||||
}
|
||||
/* Move past the '%'. */
|
||||
format_string++;
|
||||
/* Early return if we've run out of string. */
|
||||
/* Early return if the string ran out. */
|
||||
if ('\0' == format_string[0])
|
||||
return false;
|
||||
/* If we've found "%N", return true. */
|
||||
/* True result if "%N" was found. */
|
||||
if ('N' == format_string[0])
|
||||
return true;
|
||||
/* If we've found "%%", move on and go back round the loop. */
|
||||
/* If "%%" was found, move past it and go back round the loop. */
|
||||
if ('%' == format_string[0]) {
|
||||
format_string++;
|
||||
continue;
|
||||
@@ -699,8 +995,8 @@ static void pv_watchfd_update_format_string(pvstate_t state)
|
||||
|
||||
/*
|
||||
* Make sure there's a format string, and then insert %N into it if
|
||||
* it's not present AND we're either watching more than one item, or
|
||||
* the item we're watching is a whole PID, not a single FD.
|
||||
* it's not present AND either more than one item is being watched,
|
||||
* or the item being watched is a whole PID, not a single FD.
|
||||
*/
|
||||
original_format_string = state->control.format_string;
|
||||
if (NULL == original_format_string)
|
||||
@@ -799,7 +1095,7 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
|
||||
if (kill(watching[watch_idx].pid, 0) != 0) {
|
||||
/* Inaccessible PID - error, mark as finished. */
|
||||
pv_error("%s %u: %s", _("pid"), watching[watch_idx].pid, strerror(errno));
|
||||
pv_perror("%s %u", _("pid"), watching[watch_idx].pid);
|
||||
state->status.exit_status |= PV_ERROREXIT_ACCESS;
|
||||
watching[watch_idx].finished = true;
|
||||
continue;
|
||||
@@ -815,7 +1111,7 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
&(watching[watch_idx].info_array));
|
||||
if (rc != 0) {
|
||||
/* Scan failed - error, mark as finished. */
|
||||
pv_error("%s %u: %s", _("pid"), watching[watch_idx].pid, strerror(errno));
|
||||
pv_perror("%s %u", _("pid"), watching[watch_idx].pid);
|
||||
state->status.exit_status |= PV_ERROREXIT_ACCESS;
|
||||
watching[watch_idx].finished = true;
|
||||
}
|
||||
@@ -919,11 +1215,11 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
|
||||
/*
|
||||
* Resize the display, if a resize signal was received.
|
||||
* If a resize signal was received, resize the display.
|
||||
*
|
||||
* We also set a local flag to tell the display loop below
|
||||
* to trigger a name reset and display reparse for every FD
|
||||
* output line, to inherit the size change.
|
||||
* This also sets a local flag to tell the display loop
|
||||
* below to trigger a name reset and display reparse for
|
||||
* every FD output line, to inherit the size change.
|
||||
*/
|
||||
terminal_resized = pv__resize_display_on_signal(state);
|
||||
|
||||
@@ -981,7 +1277,7 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
if (info_item->unused)
|
||||
continue;
|
||||
|
||||
/* No more lines if we've filled the display. */
|
||||
/* No more lines if the display is full. */
|
||||
if (displayed_lines >= (int) (state->control.height))
|
||||
break;
|
||||
|
||||
@@ -1097,9 +1393,9 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
/*@-mustfreeonly@ */
|
||||
state->control.name = NULL;
|
||||
/*
|
||||
* splint warns of a memory leak, but we'd
|
||||
* set name to be an alias of display_name,
|
||||
* so nothing is lost here.
|
||||
* splint warns of a memory leak, but name
|
||||
* was an alias of display_name, so nothing
|
||||
* is lost here.
|
||||
*/
|
||||
/*@+mustfreeonly@ */
|
||||
|
||||
@@ -1109,8 +1405,8 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
}
|
||||
|
||||
/*
|
||||
* Write blank lines if we're writing fewer lines than last
|
||||
* time.
|
||||
* Write extra blank lines if fewer lines were written than
|
||||
* last time around the loop.
|
||||
*/
|
||||
blank_lines = prev_displayed_lines - displayed_lines;
|
||||
prev_displayed_lines = displayed_lines;
|
||||
@@ -1158,14 +1454,20 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
}
|
||||
}
|
||||
|
||||
end_pv_watchfd_loop:
|
||||
|
||||
/* Tell the error routines that progress bar display has finished. */
|
||||
pv_end_display();
|
||||
|
||||
/*
|
||||
* If a signal caused the end of the loop, reflect that in the
|
||||
* return code.
|
||||
*/
|
||||
if (1 == state->flags.trigger_exit)
|
||||
if (1 == state->flags.trigger_exit) {
|
||||
state->status.exit_status |= PV_ERROREXIT_SIGNAL;
|
||||
pv_report_signal_interrupt((int) (state->flags.terminating_signal));
|
||||
}
|
||||
|
||||
end_pv_watchfd_loop:
|
||||
/* Free all allocated sub-structures. */
|
||||
pv_freecontents_watchfd_items(watching, state->watchfd.count);
|
||||
|
||||
@@ -1237,8 +1539,8 @@ int pv_query_loop(pvstate_t state, pid_t query)
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
|
||||
/*
|
||||
* Just go round the loop again if there's no display and
|
||||
* we're not reporting statistics.
|
||||
* If there's no display and statistics aren't being
|
||||
* reported, do nothing but go round the loop again.
|
||||
*/
|
||||
if (state->control.no_display && !state->control.show_stats) {
|
||||
pv_nanosleep(50000000);
|
||||
@@ -1246,8 +1548,8 @@ int pv_query_loop(pvstate_t state, pid_t query)
|
||||
}
|
||||
|
||||
/*
|
||||
* If -W was given, we don't output anything until something
|
||||
* has been transferred.
|
||||
* If -W was given, produce no display until something has
|
||||
* been transferred.
|
||||
*/
|
||||
if (state->control.wait) {
|
||||
/* Restart the loop if nothing written yet. */
|
||||
@@ -1299,11 +1601,19 @@ int pv_query_loop(pvstate_t state, pid_t query)
|
||||
pv_tty_write(&(state->flags), "\n", 1);
|
||||
}
|
||||
|
||||
if (1 == state->flags.trigger_exit)
|
||||
state->status.exit_status |= PV_ERROREXIT_SIGNAL;
|
||||
if (state->display.using_osc94)
|
||||
pv_clear_osc94(state);
|
||||
|
||||
/* Tell the error routines that progress bar display has finished. */
|
||||
pv_end_display();
|
||||
|
||||
/* Calculate and display the transfer statistics. */
|
||||
pv__show_stats(state);
|
||||
|
||||
if (1 == state->flags.trigger_exit) {
|
||||
state->status.exit_status |= PV_ERROREXIT_SIGNAL;
|
||||
pv_report_signal_interrupt((int) (state->flags.terminating_signal));
|
||||
}
|
||||
|
||||
return state->status.exit_status;
|
||||
}
|
||||
|
||||
+30
-16
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Functions for converting strings to numbers.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -29,8 +29,11 @@ bool pv_isdigit(char c)
|
||||
* a fractional part, optionally followed by a units suffix such as "K" for
|
||||
* kibibytes. If "decimal_units" is true, suffixes are interpreted as
|
||||
* multiples of 1000, rather than multiples of 1024.
|
||||
*
|
||||
* If resultptr is not NULL, it is populated with the result as a long
|
||||
* double.
|
||||
*/
|
||||
off_t pv_getnum_size(const char *str, bool decimal_units)
|
||||
off_t pv_getnum_size(const char *str, bool decimal_units, /*@null@ */ long double *resultptr)
|
||||
{
|
||||
off_t integral_part = 0;
|
||||
off_t fractional_part = 0;
|
||||
@@ -39,8 +42,11 @@ off_t pv_getnum_size(const char *str, bool decimal_units)
|
||||
off_t decimal_multiplier = 0;
|
||||
size_t readpos = 0;
|
||||
|
||||
if (NULL == str)
|
||||
if (NULL == str) {
|
||||
if (NULL != resultptr)
|
||||
*resultptr = 0.0;
|
||||
return (off_t) 0;
|
||||
}
|
||||
|
||||
/* Skip any non-numeric leading characters. */
|
||||
while (str[readpos] != '\0' && (!pv_isdigit(str[readpos])))
|
||||
@@ -59,9 +65,9 @@ off_t pv_getnum_size(const char *str, bool decimal_units)
|
||||
* If the next character is a decimal mark, skip over it and parse
|
||||
* the following digits as the fractional part of the number.
|
||||
*
|
||||
* Note that we hard-code the decimal mark as '.' or ',' so this
|
||||
* will fail if there are any locales whose decimal mark is not one
|
||||
* of those two characters.
|
||||
* Note that the decimal mark is hard-coded as being either '.' or
|
||||
* ',' so this will fail if there are any locales whose decimal mark
|
||||
* is not one of those two characters.
|
||||
*/
|
||||
if (('.' == str[readpos]) || (',' == str[readpos])) {
|
||||
readpos++;
|
||||
@@ -110,8 +116,9 @@ off_t pv_getnum_size(const char *str, bool decimal_units)
|
||||
}
|
||||
|
||||
/*
|
||||
* If decimal_units is false, zero decimal_multiplier; if true, zero
|
||||
* binary_shift. This is so we only do one or the other.
|
||||
* If decimal_units is true, set binary_shift to zero; if false, set
|
||||
* decimal_multiplier to zero. This is so that only one of the two
|
||||
* multipliers can be active.
|
||||
*/
|
||||
if (decimal_units) {
|
||||
binary_shift = 0;
|
||||
@@ -133,9 +140,8 @@ off_t pv_getnum_size(const char *str, bool decimal_units)
|
||||
|
||||
/*@-shiftimplementation@ */
|
||||
/*
|
||||
* splint note: ignore the fact that the types we are
|
||||
* shifting are signed, because we know they are definitely
|
||||
* not negative.
|
||||
* splint note: ignore the fact that the types being shifted
|
||||
* are signed, because they are definitely not negative.
|
||||
*/
|
||||
integral_part = (off_t) (integral_part << shiftby);
|
||||
fractional_part = (off_t) (fractional_part << shiftby);
|
||||
@@ -154,13 +160,21 @@ off_t pv_getnum_size(const char *str, bool decimal_units)
|
||||
|
||||
/*
|
||||
* Add the fractional part, divided by its divisor, to the integral
|
||||
* part, now that we've multiplied everything by the appropriate
|
||||
* units.
|
||||
* part, now that the multiplier for the units has been applied.
|
||||
*/
|
||||
if (NULL != resultptr) {
|
||||
*resultptr = ((long double) fractional_part) / (long double) fractional_divisor;
|
||||
*resultptr += (long double) integral_part;
|
||||
}
|
||||
fractional_part = fractional_part / fractional_divisor;
|
||||
integral_part += fractional_part;
|
||||
|
||||
debug("%s [%s] = %lld", str, decimal_units ? "decimal" : "binary", (long long) integral_part);
|
||||
if (NULL != resultptr) {
|
||||
debug("%s [%s] = %lld = %Lf", str, decimal_units ? "decimal" : "binary", (long long) integral_part,
|
||||
*resultptr);
|
||||
} else {
|
||||
debug("%s [%s] = %lld", str, decimal_units ? "decimal" : "binary", (long long) integral_part);
|
||||
}
|
||||
|
||||
return integral_part;
|
||||
}
|
||||
@@ -212,7 +226,7 @@ double pv_getnum_interval(const char *str)
|
||||
*/
|
||||
unsigned int pv_getnum_count(const char *str, bool decimal_units)
|
||||
{
|
||||
return (unsigned int) pv_getnum_size(str, decimal_units);
|
||||
return (unsigned int) pv_getnum_size(str, decimal_units, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -260,7 +274,7 @@ bool pv_getnum_check(const char *str, pv_numtype type)
|
||||
while ((' ' == str[0]) || ('\t' == str[0]))
|
||||
str++;
|
||||
|
||||
/* Check the units suffix is one we know about. */
|
||||
/* Check the units suffix is known. */
|
||||
switch (str[0]) {
|
||||
case 'k':
|
||||
case 'K':
|
||||
|
||||
+10
-12
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Functions for setting the process title.
|
||||
*
|
||||
* Copyright 2024-2025 Andrew Wood
|
||||
* Copyright 2024-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -21,9 +21,9 @@ static size_t space_available = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Assuming the environment comes after the command line arguments, we make
|
||||
* a duplicate of the environment array and all its values, so we can use
|
||||
* the space the environment used to occupy for the process title.
|
||||
* Assuming the environment comes after the command line arguments, make a
|
||||
* duplicate of the environment array and all its values, to allow the
|
||||
* process title to use the space the environment used to occupy.
|
||||
*
|
||||
* The logic for this was derived from util-linux-ng.
|
||||
*/
|
||||
@@ -36,8 +36,7 @@ void initproctitle(int argc, char **argv)
|
||||
size_t env_array_size, env_index;
|
||||
|
||||
/* Find the number of entries in the environment array. */
|
||||
for (env_array_size = 0; environ[env_array_size] != NULL; env_array_size++)
|
||||
continue;
|
||||
for (env_array_size = 0; environ[env_array_size] != NULL; env_array_size++);
|
||||
|
||||
/* Allocate a new environment array. */
|
||||
new_environment = (char **) malloc(sizeof(char *) * (env_array_size + 1));
|
||||
@@ -54,7 +53,7 @@ void initproctitle(int argc, char **argv)
|
||||
|
||||
base_argv = argv;
|
||||
|
||||
/* Work out how much room we have. */
|
||||
/* Work out how much room is available. */
|
||||
if (env_index > 0) {
|
||||
/* From argv[0] to the end of the last environment value. */
|
||||
space_available = (size_t)
|
||||
@@ -65,9 +64,8 @@ void initproctitle(int argc, char **argv)
|
||||
}
|
||||
|
||||
/*
|
||||
* flawfinder - we have to trust that the environment and argument
|
||||
* strings are null-terminated, since that's what the OS is supposed
|
||||
* to guarantee.
|
||||
* flawfinder - the OS is supposed to guarantee that the environment
|
||||
* and argument strings are null-terminated.
|
||||
*/
|
||||
|
||||
environ = new_environment;
|
||||
@@ -87,7 +85,7 @@ void setproctitle(const char *format, ...)
|
||||
size_t length;
|
||||
va_list ap;
|
||||
|
||||
/* flawfinder - buffer is zeroed and users of it are bounded. */
|
||||
/* flawfinder - buffer is zeroed and calls using it are bounded. */
|
||||
|
||||
if (NULL == base_argv)
|
||||
return;
|
||||
@@ -105,7 +103,7 @@ void setproctitle(const char *format, ...)
|
||||
*/
|
||||
|
||||
length = strlen(title); /* flawfinder: ignore */
|
||||
/* flawfinder - we left a byte at the end to force null-termination. */
|
||||
/* flawfinder - a byte was left at the end to force null-termination. */
|
||||
|
||||
if (length > space_available - 2)
|
||||
length = space_available - 2;
|
||||
|
||||
+62
-47
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Remote-control and remote-query functions.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -34,7 +34,7 @@ struct remote_msg {
|
||||
bool bytes; /* bytes transferred flag */
|
||||
bool bufpercent; /* transfer buffer percentage flag */
|
||||
size_t lastwritten; /* last-written bytes count */
|
||||
off_t rate_limit; /* rate limit, in bytes per second */
|
||||
long double rate_limit; /* rate limit, in bytes per second */
|
||||
size_t buffer_size; /* buffer size, in bytes (0=default) */
|
||||
off_t size; /* total size of data */
|
||||
double interval; /* interval between updates */
|
||||
@@ -42,6 +42,8 @@ struct remote_msg {
|
||||
unsigned int height; /* screen height */
|
||||
bool width_set_manually; /* width was set manually, not detected */
|
||||
bool height_set_manually; /* height was set manually, not detected */
|
||||
bool rate_limit_specified; /* whether a rate limit value was set */
|
||||
bool rate_limit_active; /* whether rate limiting is in effect (>0) */
|
||||
char name[256]; /* flawfinder: ignore */
|
||||
char format[256]; /* flawfinder: ignore */
|
||||
char extra_display[256]; /* flawfinder: ignore */
|
||||
@@ -88,7 +90,7 @@ int pv_remote_set(pvstate_t state, pid_t remote)
|
||||
* Check that the remote process exists.
|
||||
*/
|
||||
if (kill((pid_t) (remote), 0) != 0) {
|
||||
pv_error("%u: %s", remote, strerror(errno));
|
||||
pv_perror("%s %u", _("pid"), remote);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
@@ -106,6 +108,8 @@ int pv_remote_set(pvstate_t state, pid_t remote)
|
||||
msgbuf.bufpercent = state->control.format_option.bufpercent;
|
||||
msgbuf.lastwritten = state->control.format_option.lastwritten;
|
||||
msgbuf.rate_limit = state->control.rate_limit;
|
||||
msgbuf.rate_limit_specified = state->control.rate_limit_specified;
|
||||
msgbuf.rate_limit_active = state->control.rate_limit_active;
|
||||
msgbuf.buffer_size = state->control.target_buffer_size;
|
||||
msgbuf.size = state->control.size;
|
||||
msgbuf.interval = state->control.interval;
|
||||
@@ -152,7 +156,7 @@ int pv_remote_set(pvstate_t state, pid_t remote)
|
||||
memset(control_filename, 0, sizeof(control_filename));
|
||||
control_fptr = pv_open_controlfile(control_filename, sizeof(control_filename), (pid_t) getpid(), SIGUSR2, true);
|
||||
if (NULL == control_fptr) {
|
||||
pv_error("%s", strerror(errno));
|
||||
pv_perror("%s", control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
@@ -161,26 +165,27 @@ int pv_remote_set(pvstate_t state, pid_t remote)
|
||||
* it.
|
||||
*/
|
||||
if (1 != fwrite(&msgbuf, sizeof(msgbuf), 1, control_fptr)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
pv_perror("%s", control_filename);
|
||||
(void) fclose(control_fptr);
|
||||
(void) remove(control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
if (0 != fclose(control_fptr)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
pv_perror("%s", control_filename);
|
||||
(void) remove(control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a SIGUSR2 signal to the remote process, to tell it a message
|
||||
* is ready to read, after clearing our own "SIGUSR2 received" flag.
|
||||
* Clear this process's "SIGUSR2 received" flag, and then send a
|
||||
* SIGUSR2 signal to the remote process, to tell it a message is
|
||||
* ready to read.
|
||||
*/
|
||||
signal_sender = 0;
|
||||
(void) pv_sigusr2_received(state, &signal_sender);
|
||||
if (kill((pid_t) (remote), SIGUSR2) != 0) {
|
||||
pv_error("%u: %s", remote, strerror(errno));
|
||||
pv_perror("%s %u", _("pid"), remote);
|
||||
(void) remove(control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
@@ -219,7 +224,7 @@ int pv_remote_set(pvstate_t state, pid_t remote)
|
||||
*/
|
||||
debug("%s: %s", "removing", control_filename);
|
||||
if (0 != remove(control_filename)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
pv_perror("%s", control_filename);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -232,7 +237,7 @@ int pv_remote_set(pvstate_t state, pid_t remote)
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory leak
|
||||
* warnings, but in this case it's unavoidable, and mitigated by the
|
||||
* fact we only translate each string once.
|
||||
* fact that each string is only translated once.
|
||||
*/
|
||||
pv_error("%u: %s", remote, _("message not received"));
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
@@ -247,8 +252,8 @@ int pv_remote_set(pvstate_t state, pid_t remote)
|
||||
* If a message was received, update the current process's options with the
|
||||
* ones in the message.
|
||||
*
|
||||
* Note that this relies on pv_state_set_format() causing the output format
|
||||
* to be reparsed.
|
||||
* Note that this relies on pv_state_set_format_options() causing the output
|
||||
* format to be reparsed.
|
||||
*/
|
||||
static bool pv__rxsignal_usr2(pvstate_t state)
|
||||
{
|
||||
@@ -256,6 +261,7 @@ static bool pv__rxsignal_usr2(pvstate_t state)
|
||||
char control_filename[4096]; /* flawfinder: ignore */
|
||||
FILE *control_fptr;
|
||||
struct remote_msg msgbuf;
|
||||
pvformatoptions_s format_options;
|
||||
|
||||
/* flawfinder rationale: as above. */
|
||||
|
||||
@@ -269,7 +275,7 @@ static bool pv__rxsignal_usr2(pvstate_t state)
|
||||
memset(control_filename, 0, sizeof(control_filename));
|
||||
control_fptr = pv_open_controlfile(control_filename, sizeof(control_filename), signal_sender, SIGUSR2, false);
|
||||
if (NULL == control_fptr) {
|
||||
pv_error("%s: %s", control_filename, strerror(errno));
|
||||
pv_perror("%s", control_filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -278,13 +284,13 @@ static bool pv__rxsignal_usr2(pvstate_t state)
|
||||
* it.
|
||||
*/
|
||||
if (1 != fread(&msgbuf, sizeof(msgbuf), 1, control_fptr)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
pv_perror("%s", control_filename);
|
||||
(void) fclose(control_fptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 != fclose(control_fptr)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
pv_perror("%s", control_filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -306,14 +312,23 @@ static bool pv__rxsignal_usr2(pvstate_t state)
|
||||
msgbuf.format[sizeof(msgbuf.format) - 1] = '\0';
|
||||
msgbuf.extra_display[sizeof(msgbuf.extra_display) - 1] = '\0';
|
||||
|
||||
pv_state_set_format(state, msgbuf.progress, msgbuf.timer,
|
||||
msgbuf.eta, msgbuf.fineta, msgbuf.rate,
|
||||
msgbuf.average_rate,
|
||||
msgbuf.bytes, msgbuf.bufpercent,
|
||||
msgbuf.lastwritten, '\0' == msgbuf.name[0] ? NULL : msgbuf.name);
|
||||
pv_state_name_set(state, '\0' == msgbuf.name[0] ? NULL : msgbuf.name);
|
||||
|
||||
if (msgbuf.rate_limit > 0)
|
||||
pv_state_rate_limit_set(state, msgbuf.rate_limit);
|
||||
format_options.progress = msgbuf.progress;
|
||||
format_options.timer = msgbuf.timer;
|
||||
format_options.eta = msgbuf.eta;
|
||||
format_options.fineta = msgbuf.fineta;
|
||||
format_options.rate = msgbuf.rate;
|
||||
format_options.average_rate = msgbuf.average_rate;
|
||||
format_options.bytes = msgbuf.bytes;
|
||||
format_options.bufpercent = msgbuf.bufpercent;
|
||||
format_options.lastwritten = msgbuf.lastwritten;
|
||||
|
||||
pv_state_set_format_options(state, format_options);
|
||||
|
||||
if (msgbuf.rate_limit_specified)
|
||||
pv_state_rate_limit_set(state, msgbuf.rate_limit, msgbuf.rate_limit_specified,
|
||||
msgbuf.rate_limit_active);
|
||||
if (msgbuf.buffer_size > 0) {
|
||||
pv_state_target_buffer_size_set(state, msgbuf.buffer_size);
|
||||
}
|
||||
@@ -337,8 +352,8 @@ static bool pv__rxsignal_usr2(pvstate_t state)
|
||||
/*
|
||||
* Check for a --query message (SIGUSR1).
|
||||
*
|
||||
* If a type 0 message was received (query), then write a type 1 (response)
|
||||
* message to the control file and send a SIGUSR1 to the sending process.
|
||||
* If a type 0 message was received (query), then write a type 1 message
|
||||
* (response) to the control file and send a SIGUSR1 to the sending process.
|
||||
*
|
||||
* If a type 1 message was received (response), update the state from the
|
||||
* message in the control file.
|
||||
@@ -380,9 +395,9 @@ static bool pv__rxsignal_usr1(pvstate_t state, pid_t match_sender)
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that we use debug() rather than pv_error() here so that the
|
||||
* display of a running pv doesn't get interrupted by, for example,
|
||||
* a querying pv being terminated.
|
||||
* Note that errors are only reported with debug() rather than
|
||||
* pv_error() here so that the display of a running pv doesn't get
|
||||
* interrupted by, for example, a querying pv being terminated.
|
||||
*/
|
||||
|
||||
memset(control_filename, 0, sizeof(control_filename));
|
||||
@@ -472,11 +487,11 @@ static bool pv__rxsignal_usr1(pvstate_t state, pid_t match_sender)
|
||||
* Check for remote control messages. For a SIGUSR2 (--remote), replace the
|
||||
* current process's options with those being passed in. For a SIGUSR1
|
||||
* (--query), either receive transfer state from the sending process, or
|
||||
* send our transfer state to the sending process, depending on the content
|
||||
* of the message.
|
||||
* send the current transfer state to the sending process, depending on the
|
||||
* content of the message.
|
||||
*
|
||||
* NB --remote relies on pv_state_set_format() causing the output format to
|
||||
* be reparsed.
|
||||
* NB --remote relies on pv_state_set_format_options() causing the output
|
||||
* format to be reparsed.
|
||||
*
|
||||
* Returns true if a --remote message was received, false otherwise.
|
||||
*/
|
||||
@@ -499,7 +514,7 @@ bool pv_remote_check(pvstate_t state)
|
||||
*
|
||||
* Returns nonzero on error. If "silent" is false, reports the error.
|
||||
*/
|
||||
int pv_remote_transferstate_fetch(pvstate_t state, pid_t query, /*@null@ */ off_t * sizeptr, bool silent)
|
||||
int pv_remote_transferstate_fetch(pvstate_t state, pid_t query, /*@null@ */ off_t *sizeptr, bool silent)
|
||||
{
|
||||
char control_filename[4096]; /* flawfinder: ignore */
|
||||
FILE *control_fptr;
|
||||
@@ -510,8 +525,7 @@ int pv_remote_transferstate_fetch(pvstate_t state, pid_t query, /*@null@ */ off_
|
||||
|
||||
/*
|
||||
* flawfinder rationale: buffer is large enough, explicitly zeroed,
|
||||
* and always bounded properly as we are only writing to it with
|
||||
* pv_snprintf().
|
||||
* and always bounded properly, as only pv_snprintf() writes to it.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -519,7 +533,7 @@ int pv_remote_transferstate_fetch(pvstate_t state, pid_t query, /*@null@ */ off_
|
||||
*/
|
||||
if (kill((pid_t) (query), 0) != 0) {
|
||||
if (!silent)
|
||||
pv_error("%u: %s", query, strerror(errno));
|
||||
pv_perror("%s %u", _("pid"), query);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
@@ -534,7 +548,7 @@ int pv_remote_transferstate_fetch(pvstate_t state, pid_t query, /*@null@ */ off_
|
||||
control_fptr = pv_open_controlfile(control_filename, sizeof(control_filename), (pid_t) getpid(), SIGUSR1, true);
|
||||
if (NULL == control_fptr) {
|
||||
if (!silent)
|
||||
pv_error("%s", strerror(errno));
|
||||
pv_perror("%s", control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
@@ -543,7 +557,7 @@ int pv_remote_transferstate_fetch(pvstate_t state, pid_t query, /*@null@ */ off_
|
||||
*/
|
||||
if (1 != fwrite(&msgbuf, sizeof(msgbuf), 1, control_fptr)) {
|
||||
if (!silent)
|
||||
pv_error("%s", strerror(errno));
|
||||
pv_perror("%s", control_filename);
|
||||
(void) fclose(control_fptr);
|
||||
(void) remove(control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
@@ -551,21 +565,21 @@ int pv_remote_transferstate_fetch(pvstate_t state, pid_t query, /*@null@ */ off_
|
||||
|
||||
if (0 != fclose(control_fptr)) {
|
||||
if (!silent)
|
||||
pv_error("%s", strerror(errno));
|
||||
pv_perror("%s", control_filename);
|
||||
(void) remove(control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a SIGUSR1 signal to the remote process, to tell it a query
|
||||
* message is ready, after first clearing our own SIGUSR1 received
|
||||
* flag.
|
||||
* Clear this process's "SIGUSR1 received" flag and send a SIGUSR1
|
||||
* signal to the remote process, to tell it a query message is
|
||||
* ready.
|
||||
*/
|
||||
signal_sender = 0;
|
||||
(void) pv_sigusr1_received(state, &signal_sender);
|
||||
if (kill((pid_t) (query), SIGUSR1) != 0) {
|
||||
if (!silent)
|
||||
pv_error("%u: %s", query, strerror(errno));
|
||||
pv_perror("%s %u", _("pid"), query);
|
||||
(void) remove(control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
@@ -616,7 +630,7 @@ int pv_remote_transferstate_fetch(pvstate_t state, pid_t query, /*@null@ */ off_
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory leak
|
||||
* warnings, but in this case it's unavoidable, and mitigated by the
|
||||
* fact we only translate each string once.
|
||||
* fact that each string is only translated once.
|
||||
*/
|
||||
if (!silent)
|
||||
pv_error("%u: %s", query, _("message not received"));
|
||||
@@ -629,11 +643,12 @@ int pv_remote_transferstate_fetch(pvstate_t state, pid_t query, /*@null@ */ off_
|
||||
#else /* !PV_REMOTE_CONTROL */
|
||||
|
||||
/*
|
||||
* Dummy stubs for remote control when we don't have PV_REMOTE_CONTROL.
|
||||
* Dummy stubs for remote control when PV_REMOTE_CONTROL is not set.
|
||||
*/
|
||||
|
||||
bool pv_remote_check( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -653,13 +668,13 @@ int pv_remote_transferstate_fetch( /*@unused@ */
|
||||
__attribute__((unused)) pid_t query,
|
||||
/*@null@ */
|
||||
/*@unused@ */
|
||||
__attribute__((unused)) off_t * sizeptr,
|
||||
__attribute__((unused)) off_t *sizeptr,
|
||||
/*@unused@ */
|
||||
__attribute__((unused))
|
||||
bool silent)
|
||||
{
|
||||
/*@-mustfreefresh@ *//* splint - see above */
|
||||
fprintf(stderr, "%s\n", _("SA_SIGINFO not supported on this system"));
|
||||
pv_error("%s", _("SA_SIGINFO not supported on this system"));
|
||||
/*@+mustfreefresh@ */
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
+172
-68
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Signal handling functions.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -26,14 +26,14 @@ void pv_crs_needreinit(pvcursorstate_t);
|
||||
|
||||
|
||||
/*
|
||||
* Ensure that terminal attribute TOSTOP is set. If we have to set it,
|
||||
* record that fact by setting "clear_tty_tostop_on_exit" to 1, so that in
|
||||
* pv_sig_fini() we can turn it back off again.
|
||||
* Check whether the terminal attribute TOSTOP is set. If it is not, set
|
||||
* it, and record that fact by setting "clear_tty_tostop_on_exit" to true,
|
||||
* so that pv_sig_fini() knows to clear it again.
|
||||
*
|
||||
* In "-c" mode with IPC, then if we have to set TOSTOP, we also tell the
|
||||
* other PV instances about it via the shared "tty_tostop_added" flag, so
|
||||
* those instances can set their own on-exit flag, meaning that if any of
|
||||
* the PV instances set it, the last one to exit will clear it.
|
||||
* In "-c" mode with IPC, that flag is propagated to other PV instances via
|
||||
* the shared "tty_tostop_added" flag, so those instances can set their own
|
||||
* on-exit flag, meaning that if any of the PV instances set it, the last
|
||||
* one to exit will clear it.
|
||||
*/
|
||||
static void pv_sig_ensure_tty_tostop()
|
||||
{
|
||||
@@ -77,17 +77,72 @@ static void pv_sig_ensure_tty_tostop()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef ECHOCTL
|
||||
/*
|
||||
* Check whether the terminal attribute ECHOCTL is set. If it is, clear it,
|
||||
* and record that fact by setting "set_tty_echoctl_on_exit" to true, so
|
||||
* that pv_sig_fini() knows to clear it again.
|
||||
*
|
||||
* In "-c" mode with IPC, that flag is propagated to other PV instances via
|
||||
* the shared "tty_echoctl_cleared" flag, so those instances can set their
|
||||
* own on-exit flag, meaning that if any of the PV instances clear it, the
|
||||
* last one to exit will set it.
|
||||
*/
|
||||
static void pv_sig_ensure_tty_noechoctl()
|
||||
{
|
||||
struct termios terminal_attributes;
|
||||
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
|
||||
/* Can't look at terminal flags if backgrounded. */
|
||||
if (1 == pv_sig_state->flags.suspend_stderr)
|
||||
return;
|
||||
|
||||
if (0 != tcgetattr(STDERR_FILENO, &terminal_attributes)) {
|
||||
debug("%s: %s", "failed to read terminal attributes", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Can't set terminal flags if backgrounded. */
|
||||
if (1 == pv_sig_state->flags.suspend_stderr)
|
||||
return;
|
||||
|
||||
if (0 != (terminal_attributes.c_lflag & ECHOCTL)) {
|
||||
terminal_attributes.c_lflag -= ECHOCTL;
|
||||
if (0 == tcsetattr(STDERR_FILENO, TCSANOW, &terminal_attributes)) {
|
||||
pv_sig_state->flags.set_tty_echoctl_on_exit = 1;
|
||||
debug("%s", "cleared terminal ECHOCTL attribute");
|
||||
#if HAVE_IPC
|
||||
/*
|
||||
* In "-c" mode with IPC, make all "pv -c" instances
|
||||
* aware that ECHOCTL was cleared, so the last one
|
||||
* can set it on exit.
|
||||
*/
|
||||
if (pv_sig_state->control.cursor && (NULL != pv_sig_state->cursor.shared)
|
||||
&& (!pv_sig_state->cursor.noipc)) {
|
||||
pv_sig_state->cursor.shared->tty_echoctl_cleared = true;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
debug("%s: %s", "failed to clear terminal ECHOCTL attribute", strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* ECHOCTL */
|
||||
|
||||
/*
|
||||
* Handle SIGTTOU (tty output for background process) by setting the flag to
|
||||
* suspend writes to stderr, so that we can be stopped and backgrounded
|
||||
* without messing up the terminal. On a subsequent SIGCONT we will try
|
||||
* writing to the terminal again, in case we get backgrounded and later get
|
||||
* foregrounded again.
|
||||
* suspend writes to stderr, to stop the terminal being interfered with when
|
||||
* pv is stopped and put into the background. On a subsequent SIGCONT, pv
|
||||
* will try writing to the terminal again, in case it was put into the
|
||||
* background and later put into the foreground again.
|
||||
*
|
||||
* When we get backgrounded and cause a SIGTTOU, the rest of the pipeline
|
||||
* gets stopped too, so transfers involving pipelines need us to send a
|
||||
* SIGCONT to the rest of the process group here, otherwise backgrounding
|
||||
* stops transfers involving pipes.
|
||||
* When a SIGTTOU is raised, the rest of the pipeline gets stopped too, so
|
||||
* transfers involving pipelines need pv to send a SIGCONT to the rest of
|
||||
* the process group here, otherwise backgrounding stops transfers involving
|
||||
* pipes.
|
||||
*/
|
||||
static void pv_sig_ttou( /*@unused@ */ __attribute__((unused))
|
||||
int s)
|
||||
@@ -157,8 +212,8 @@ static void pv_sig_cont( /*@unused@ */ __attribute__((unused))
|
||||
pv_sig_state->flags.terminal_resized = 1;
|
||||
|
||||
/*
|
||||
* We can only make the time adjustments if this SIGCONT followed a
|
||||
* SIGTSTP such that we have a stop time.
|
||||
* Time adjustments can only be made if this SIGCONT followed a
|
||||
* SIGTSTP, such that there is a stop-time to measure from.
|
||||
*/
|
||||
if (0 != pv_sig_state->signal.when_tstp_arrived.tv_sec) {
|
||||
|
||||
@@ -167,10 +222,10 @@ static void pv_sig_cont( /*@unused@ */ __attribute__((unused))
|
||||
|
||||
pv_elapsedtime_read(¤t_time);
|
||||
|
||||
/* time spent stopped = current time - time SIGTSTP received */
|
||||
/* time spent stopped = current time - time SIGTSTP received. */
|
||||
pv_elapsedtime_subtract(&time_spent_stopped, ¤t_time, &(pv_sig_state->signal.when_tstp_arrived));
|
||||
|
||||
/* add time spent stopped the total stopped-time count */
|
||||
/* add time spent stopped to the total stopped-time count. */
|
||||
pv_elapsedtime_add(&(pv_sig_state->signal.total_stoppage_time),
|
||||
&(pv_sig_state->signal.total_stoppage_time), &time_spent_stopped);
|
||||
|
||||
@@ -204,13 +259,13 @@ static void pv_sig_cont( /*@unused@ */ __attribute__((unused))
|
||||
}
|
||||
}
|
||||
|
||||
/* reset the SIGTSTP receipt time */
|
||||
/* reset the SIGTSTP receipt time. */
|
||||
pv_elapsedtime_zero(&(pv_sig_state->signal.when_tstp_arrived));
|
||||
}
|
||||
|
||||
/*
|
||||
* Try resuming our use of stderr, if we had suspended it, but only
|
||||
* if we're now in the foreground.
|
||||
* Try resuming the use of stderr, if it had been suspended, but
|
||||
* only if pv is now in the foreground.
|
||||
*/
|
||||
if (1 == pv_sig_state->flags.suspend_stderr) {
|
||||
if (pv_in_foreground()) {
|
||||
@@ -245,24 +300,25 @@ static void pv_sig_winch( /*@unused@ */ __attribute__((unused))
|
||||
|
||||
|
||||
/*
|
||||
* Handle termination signals by setting the abort flag.
|
||||
* Handle termination signals by recording which one was received, and then
|
||||
* setting the abort flag.
|
||||
*/
|
||||
static void pv_sig_term( /*@unused@ */ __attribute__((unused))
|
||||
int s)
|
||||
static void pv_sig_term(int s)
|
||||
{
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
pv_sig_state->flags.terminating_signal = (sig_atomic_t) s;
|
||||
pv_sig_state->flags.trigger_exit = 1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PV_REMOTE_CONTROL
|
||||
/*
|
||||
* Handle a SIGUSR2 by setting a flag to say we received it, after recording
|
||||
* the sending PID.
|
||||
* Handle a SIGUSR2 by recording the PID that sent it, and setting a flag to
|
||||
* say it was received.
|
||||
*/
|
||||
static void pv_sig_usr2( /*@unused@ */ __attribute__((unused))
|
||||
int sig, siginfo_t * info, /*@unused@ */ __attribute__((unused))
|
||||
int sig, siginfo_t *info, /*@unused@ */ __attribute__((unused))
|
||||
void *ucontext)
|
||||
{
|
||||
if (NULL == pv_sig_state)
|
||||
@@ -278,7 +334,7 @@ static void pv_sig_usr2( /*@unused@ */ __attribute__((unused))
|
||||
* Return true if a SIGUSR2 signal has been received since the last time
|
||||
* this function was called, populating *pid with the sending PID if so.
|
||||
*/
|
||||
bool pv_sigusr2_received(pvstate_t state, pid_t * pid)
|
||||
bool pv_sigusr2_received(pvstate_t state, pid_t *pid)
|
||||
{
|
||||
if (NULL == state)
|
||||
return false;
|
||||
@@ -292,11 +348,11 @@ bool pv_sigusr2_received(pvstate_t state, pid_t * pid)
|
||||
|
||||
|
||||
/*
|
||||
* Handle a SIGUSR1 by setting a flag to say we received it, after recording
|
||||
* the sending PID.
|
||||
* Handle a SIGUSR1 by recording the PID that sent it, and setting a flag to
|
||||
* say it was received.
|
||||
*/
|
||||
static void pv_sig_usr1( /*@unused@ */ __attribute__((unused))
|
||||
int sig, siginfo_t * info, /*@unused@ */ __attribute__((unused))
|
||||
int sig, siginfo_t *info, /*@unused@ */ __attribute__((unused))
|
||||
void *ucontext)
|
||||
{
|
||||
if (NULL == pv_sig_state)
|
||||
@@ -312,7 +368,7 @@ static void pv_sig_usr1( /*@unused@ */ __attribute__((unused))
|
||||
* Return true if a SIGUSR1 signal has been received since the last time
|
||||
* this function was called, populating *pid with the sending PID if so.
|
||||
*/
|
||||
bool pv_sigusr1_received(pvstate_t state, pid_t * pid)
|
||||
bool pv_sigusr1_received(pvstate_t state, pid_t *pid)
|
||||
{
|
||||
if (NULL == state)
|
||||
return false;
|
||||
@@ -330,10 +386,10 @@ bool pv_sigusr1_received(pvstate_t state, pid_t * pid)
|
||||
/*
|
||||
* Handle alarm signals by doing nothing.
|
||||
*
|
||||
* Note that we have to use a signal handler like this, instead of using
|
||||
* SIG_IGN, because if we ignore the signal entirely, it does nothing,
|
||||
* including not interrupting blocking write() calls - which is what we're
|
||||
* using alarm signals for in the first place.
|
||||
* An empty signal handler is used, instead of SIG_IGN, because ignoring the
|
||||
* signal with SIG_IGN prevents it from doing anything at all - meaning it
|
||||
* would not interrupt blocking write() calls, which is what pv uses alarm
|
||||
* signals for.
|
||||
*/
|
||||
static void pv_sig_alrm( /*@unused@ */ __attribute__((unused))
|
||||
int s)
|
||||
@@ -353,10 +409,10 @@ void pv_sig_init(pvstate_t state)
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
|
||||
/*
|
||||
* Note that wherever we use a "struct sigaction", we declare it
|
||||
* static and explicitly zero it before use, because it may contain
|
||||
* deeper structures (e.g. "sigset_t") which trigger splint
|
||||
* warnings about potential memory leaks.
|
||||
* Wherever a "struct sigaction" is used, it is declared static and
|
||||
* explicitly zeroed before use, because it may contain deeper
|
||||
* structures (e.g. "sigset_t") which trigger splint warnings about
|
||||
* potential memory leaks.
|
||||
*/
|
||||
|
||||
pv_sig_state = state;
|
||||
@@ -366,14 +422,14 @@ void pv_sig_init(pvstate_t state)
|
||||
pv_elapsedtime_zero(&(pv_sig_state->signal.total_stoppage_time));
|
||||
|
||||
/*
|
||||
* Note that we cast all sigemptyset() and sigaction() return values
|
||||
* to void, because there's nothing we can reasonably do about any
|
||||
* conceivable error they may return.
|
||||
* All sigemptyset() and sigaction() return values are ignored, as
|
||||
* there is no reasonable action to take about any error they
|
||||
* return.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Ignore SIGPIPE, so we don't die if the output is a pipe and the
|
||||
* other end closes unexpectedly.
|
||||
* Ignore SIGPIPE, in case the output is a pipe and the other end
|
||||
* closes unexpectedly.
|
||||
*/
|
||||
sa.sa_handler = SIG_IGN;
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
@@ -381,8 +437,9 @@ void pv_sig_init(pvstate_t state)
|
||||
(void) sigaction(SIGPIPE, &sa, &(pv_sig_state->signal.old_sigpipe));
|
||||
|
||||
/*
|
||||
* Handle SIGTTOU by continuing with output switched off, so that we
|
||||
* can be stopped and backgrounded without messing up the terminal.
|
||||
* Handle SIGTTOU by continuing with the display switched off, to
|
||||
* allow pv to be stopped and backgrounded without messing up the
|
||||
* terminal.
|
||||
*/
|
||||
pv_sig_state->flags.skip_next_sigcont = 0;
|
||||
sa.sa_handler = pv_sig_ttou;
|
||||
@@ -469,13 +526,18 @@ void pv_sig_init(pvstate_t state)
|
||||
|
||||
/*
|
||||
* Ensure that the TOSTOP terminal attribute is set, so that a
|
||||
* SIGTTOU signal will be raised if we try to write to the terminal
|
||||
* while backgrounded (see the SIGTTOU handler above).
|
||||
* SIGTTOU signal will be raised if pv attempts to write to the
|
||||
* terminal while backgrounded (see the SIGTTOU handler above).
|
||||
*/
|
||||
pv_sig_ensure_tty_tostop();
|
||||
|
||||
#ifdef ECHOCTL
|
||||
/* Clear the ECHOCTL terminal attribute if it's set. */
|
||||
pv_sig_ensure_tty_noechoctl();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handle SIGALRM by doing nothing, so we can use alarms or interval
|
||||
* Handle SIGALRM by doing nothing, allowing alarms or interval
|
||||
* timers to interrupt blocking writes (returning EINTR).
|
||||
*/
|
||||
sa.sa_handler = pv_sig_alrm;
|
||||
@@ -486,14 +548,15 @@ void pv_sig_init(pvstate_t state)
|
||||
|
||||
|
||||
/*
|
||||
* Shut down signal handling. If we had set the TOSTOP terminal attribute,
|
||||
* and we're in the foreground, also turn that off (though if we're in
|
||||
* cursor "-c" mode, only do that if we're the last PV instance, otherwise
|
||||
* leave the terminal alone).
|
||||
* Shut down signal handling. If this pv had set the TOSTOP terminal
|
||||
* attribute, and is in the foreground, also turn that off (with the
|
||||
* restriction that if in cursor "-c" mode, only do that if this is the last
|
||||
* PV instance, otherwise leave the terminal alone).
|
||||
*/
|
||||
void pv_sig_fini( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
{
|
||||
bool need_to_clear_tostop = false;
|
||||
bool need_to_set_echoctl = false;
|
||||
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
@@ -519,20 +582,17 @@ void pv_sig_fini( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
if (pv_sig_state->control.cursor) {
|
||||
#ifdef HAVE_IPC
|
||||
/*
|
||||
* We won't clear TOSTOP if other "pv -c" instances
|
||||
* were still running when pv_crs_fini() ran.
|
||||
*
|
||||
* TODO: we need a better way to determine if we're the last
|
||||
* "pv" left.
|
||||
* Don't clear TOSTOP if other "pv -c" instances were still
|
||||
* running when pv_crs_fini() ran.
|
||||
*/
|
||||
if (pv_sig_state->control.cursor && pv_sig_state->cursor.pvcount > 1) {
|
||||
need_to_clear_tostop = false;
|
||||
}
|
||||
#else /* !HAVE_IPC */
|
||||
/*
|
||||
* Without IPC we can't tell whether the other "pv -c"
|
||||
* instances in the pipeline have finished so we will just
|
||||
* have to clear TOSTOP anyway.
|
||||
* Without IPC there's no way to tell whether other "pv -c"
|
||||
* instances in the pipeline have finished, so clear TOSTOP
|
||||
* anyway.
|
||||
*/
|
||||
#endif /* !HAVE_IPC */
|
||||
}
|
||||
@@ -542,7 +602,7 @@ void pv_sig_fini( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
if (need_to_clear_tostop && pv_in_foreground()) {
|
||||
struct termios terminal_attributes;
|
||||
|
||||
debug("%s", "about to to clear TOSTOP terminal attribute if it is set");
|
||||
debug("%s", "about to clear TOSTOP terminal attribute if it is set");
|
||||
|
||||
if (0 != tcgetattr(STDERR_FILENO, &terminal_attributes)) {
|
||||
debug("%s: %s", "tcgetattr", strerror(errno));
|
||||
@@ -557,6 +617,49 @@ void pv_sig_fini( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
|
||||
pv_sig_state->flags.clear_tty_tostop_on_exit = 0;
|
||||
}
|
||||
|
||||
#ifdef ECHOCTL
|
||||
need_to_set_echoctl = (1 == pv_sig_state->flags.set_tty_echoctl_on_exit) ? true : false;
|
||||
|
||||
if (pv_sig_state->control.cursor) {
|
||||
#ifdef HAVE_IPC
|
||||
/*
|
||||
* Don't set ECHOCTL if other "pv -c" instances were still
|
||||
* running when pv_crs_fini() ran.
|
||||
*/
|
||||
if (pv_sig_state->control.cursor && pv_sig_state->cursor.pvcount > 1) {
|
||||
need_to_set_echoctl = false;
|
||||
}
|
||||
#else /* !HAVE_IPC */
|
||||
/*
|
||||
* Without IPC there's no way to tell whether other "pv -c"
|
||||
* instances in the pipeline have finished, so set ECHOCTL
|
||||
* anyway.
|
||||
*/
|
||||
#endif /* !HAVE_IPC */
|
||||
}
|
||||
|
||||
debug("%s=%s", "need_to_set_echoctl", need_to_set_echoctl ? "true" : "false");
|
||||
|
||||
if (need_to_set_echoctl && pv_in_foreground()) {
|
||||
struct termios terminal_attributes;
|
||||
|
||||
debug("%s", "about to set ECHOCTL terminal attribute if it is not set");
|
||||
|
||||
if (0 != tcgetattr(STDERR_FILENO, &terminal_attributes)) {
|
||||
debug("%s: %s", "tcgetattr", strerror(errno));
|
||||
} else if (0 == (terminal_attributes.c_lflag & ECHOCTL)) {
|
||||
terminal_attributes.c_lflag |= ECHOCTL;
|
||||
if (0 == tcsetattr(STDERR_FILENO, TCSANOW, &terminal_attributes)) {
|
||||
debug("%s", "set TOSTOP terminal attribute");
|
||||
} else {
|
||||
debug("%s: %s", "failed to set TOSTOP terminal attribute", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
pv_sig_state->flags.clear_tty_tostop_on_exit = 0;
|
||||
}
|
||||
#endif /* ECHOCTL */
|
||||
}
|
||||
|
||||
|
||||
@@ -599,9 +702,10 @@ void pv_sig_allowpause(void)
|
||||
|
||||
|
||||
/*
|
||||
* If we have suspended stderr, check every second or so to see whether we
|
||||
* can write to the terminal again - this is so that if we get backgrounded,
|
||||
* then foregrounded again, we start writing to the terminal again.
|
||||
* If output to stderr is suspended, check once a second whether it is safe
|
||||
* to write to the terminal. This is so that if pv is put into the
|
||||
* background, and then brought into the foreground again, it can resume
|
||||
* terminal output.
|
||||
*/
|
||||
void pv_sig_checkbg(void)
|
||||
{
|
||||
|
||||
+183
-75
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* State management functions.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -10,7 +10,10 @@
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
|
||||
/* We do not set this because it breaks "dd" - see below. */
|
||||
/*
|
||||
* Do not use non-blocking I/O, because it has caused problems with some
|
||||
* applications, such as dd, in the past.
|
||||
*/
|
||||
/* #undef MAKE_OUTPUT_NONBLOCKING */
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -35,17 +38,21 @@ static void pv_alloc_calc_history(pvtransfercalc_t calc)
|
||||
if (NULL == calc->history) {
|
||||
/*@-mustfreefresh@ */
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory
|
||||
* leak warnings, but in this case it's unavoidable, and
|
||||
* mitigated by the fact we only translate each string once.
|
||||
* splint note: the gettext calls made by _() cause
|
||||
* unavoidable memory leak warnings, but they are mitigated
|
||||
* by the fact that each string is only translated once.
|
||||
*/
|
||||
pv_error("%s: %s", _("history structure allocation failed"), strerror(errno));
|
||||
pv_perror("%s", _("memory allocation failure"));
|
||||
/*@+mustfreefresh@ */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Explicitly set these values to zero, as memset() is not
|
||||
* recommended for floating point types.
|
||||
*/
|
||||
calc->history_first = calc->history_last = 0;
|
||||
calc->history[0].elapsed_sec = 0.0; /* to be safe, memset() not recommended for doubles */
|
||||
calc->history[0].elapsed_sec = 0.0;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,8 +131,14 @@ void pv_reset_transfer(pvtransferstate_t transfer)
|
||||
transfer->written_but_not_consumed = 0;
|
||||
transfer->read_errors_in_a_row = 0;
|
||||
transfer->last_read_skip_fd = 0;
|
||||
#ifdef HAVE_COPY_FILE_RANGE
|
||||
transfer->copy_file_range_failed_fd = -1;
|
||||
#endif /* HAVE_COPY_FILE_RANGE */
|
||||
#ifdef HAVE_SPLICE
|
||||
transfer->splice_failed_fd = -1;
|
||||
transfer->intermediate_pipe[0] = -1;
|
||||
transfer->intermediate_pipe[1] = -1;
|
||||
transfer->discard_fd = -1;
|
||||
#endif /* HAVE_SPLICE */
|
||||
|
||||
transfer->line_positions_length = 0;
|
||||
@@ -178,11 +191,12 @@ void pv_state_reset(pvstate_t state)
|
||||
|
||||
|
||||
/*
|
||||
* Create a new state structure, and return it, or 0 (NULL) on error.
|
||||
* Create a new state structure, and return it, or NULL on error.
|
||||
*/
|
||||
pvstate_t pv_state_alloc(void)
|
||||
{
|
||||
pvstate_t state;
|
||||
size_t try_size;
|
||||
|
||||
state = calloc(1, sizeof(*state));
|
||||
if (NULL == state)
|
||||
@@ -191,6 +205,9 @@ pvstate_t pv_state_alloc(void)
|
||||
|
||||
state->watchfd.count = 0;
|
||||
state->control.output_fd = -1;
|
||||
state->control.othermonitor_pid = 0;
|
||||
state->control.othermonitor_read_fd = -1;
|
||||
state->control.othermonitor_write_fd = -1;
|
||||
#ifdef HAVE_IPC
|
||||
state->cursor.shmid = -1;
|
||||
state->cursor.pvcount = 1;
|
||||
@@ -199,19 +216,39 @@ pvstate_t pv_state_alloc(void)
|
||||
|
||||
pv_state_reset(state);
|
||||
|
||||
#ifdef HAVE_GETCWD
|
||||
/*
|
||||
* Get the current working directory, if possible, as a base for
|
||||
* showing relative filenames with --watchfd.
|
||||
*
|
||||
* If this fails then --watchfd will fall back to always showing the
|
||||
* full path.
|
||||
*/
|
||||
if (NULL == getcwd(state->status.cwd, PV_SIZEOF_CWD - 1)) {
|
||||
/* failed - will always show full path */
|
||||
state->status.cwd[0] = '\0';
|
||||
for (try_size = 32; try_size <= 16384; try_size = try_size * 2) {
|
||||
bool buffer_too_small;
|
||||
|
||||
if (NULL != state->status.cwd) {
|
||||
free(state->status.cwd);
|
||||
state->status.cwd = NULL;
|
||||
}
|
||||
/*@-mustfreeonly@ *//* splint mis-detects this as a memory leak. */
|
||||
state->status.cwd = malloc(try_size);
|
||||
/*@+mustfreeonly@ */
|
||||
if (NULL == state->status.cwd)
|
||||
break;
|
||||
|
||||
buffer_too_small = false;
|
||||
if (NULL == getcwd(state->status.cwd, try_size)) {
|
||||
if (errno != ERANGE)
|
||||
buffer_too_small = true;
|
||||
free(state->status.cwd);
|
||||
state->status.cwd = NULL;
|
||||
}
|
||||
|
||||
if (!buffer_too_small)
|
||||
break;
|
||||
}
|
||||
if ('\0' == state->status.cwd[1]) {
|
||||
/* CWD is root directory - always show full path */
|
||||
state->status.cwd[0] = '\0';
|
||||
}
|
||||
state->status.cwd[PV_SIZEOF_CWD - 1] = '\0';
|
||||
#endif /* HAVE_GETCWD */
|
||||
|
||||
return state;
|
||||
}
|
||||
@@ -240,6 +277,25 @@ void pv_freecontents_transfer(pvtransferstate_t transfer)
|
||||
/*@+keeptrans@ */
|
||||
/* splint - explicitly freeing this structure, so free() here is OK. */
|
||||
|
||||
#ifdef HAVE_SPLICE
|
||||
/* Close the intermediate pipe, if there was one. */
|
||||
if (transfer->intermediate_pipe_buffer_size > 0) {
|
||||
int idx;
|
||||
for (idx = 0; idx < 2; idx++) {
|
||||
if (transfer->intermediate_pipe[idx] >= 0) {
|
||||
(void) close(transfer->intermediate_pipe[idx]);
|
||||
transfer->intermediate_pipe[idx] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the discard file descriptor, if there was one. */
|
||||
if (transfer->discard_fd >= 0) {
|
||||
(void) close(transfer->discard_fd);
|
||||
transfer->discard_fd = -1;
|
||||
}
|
||||
#endif /* HAVE_SPLICE */
|
||||
|
||||
if (NULL != transfer->line_positions)
|
||||
free(transfer->line_positions);
|
||||
transfer->line_positions = NULL;
|
||||
@@ -292,7 +348,7 @@ void pv_freecontents_watchfd_items(struct pvwatcheditem_s *watching, unsigned in
|
||||
|
||||
/*
|
||||
* Truncate the output file descriptor to its current position, if it's a
|
||||
* valid fd, we're in sparse output mode, and no lseek() failed.
|
||||
* valid fd, sparse output mode is active, and no lseek() failed.
|
||||
*/
|
||||
static void pv_truncate_output(pvstate_t state)
|
||||
{
|
||||
@@ -331,16 +387,15 @@ void pv_state_free(pvstate_t state)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Close the output file first, so we can report any errors while we
|
||||
* still know the program name and output filename.
|
||||
* Close the output file first, while the output filename is still
|
||||
* available to include in an error message.
|
||||
*/
|
||||
if (state->control.output_fd >= 0) {
|
||||
pv_truncate_output(state);
|
||||
if (STDOUT_FILENO != state->control.output_fd) {
|
||||
if (close(state->control.output_fd) < 0) {
|
||||
pv_error("%s: %s",
|
||||
NULL == state->control.output_name ? "(null)" : state->control.output_name,
|
||||
strerror(errno));
|
||||
pv_perror("%s",
|
||||
NULL == state->control.output_name ? "(null)" : state->control.output_name);
|
||||
}
|
||||
}
|
||||
state->control.output_fd = -1;
|
||||
@@ -351,6 +406,11 @@ void pv_state_free(pvstate_t state)
|
||||
state->control.output_name = NULL;
|
||||
}
|
||||
|
||||
if (NULL != state->status.cwd) {
|
||||
free(state->status.cwd);
|
||||
state->status.cwd = NULL;
|
||||
}
|
||||
|
||||
pv_freecontents_display(&(state->display));
|
||||
pv_freecontents_display(&(state->extra_display));
|
||||
|
||||
@@ -408,10 +468,13 @@ void pv_state_free(pvstate_t state)
|
||||
|
||||
|
||||
/*
|
||||
* Set the formatting string, given a set of old-style formatting options.
|
||||
* Set the format options and use them to build a default formatting string.
|
||||
* The default string is used if no format string is explicitly set.
|
||||
*
|
||||
* Call this *after* setting a name, so it can determine whether there
|
||||
* should be a name in the default format.
|
||||
*/
|
||||
void pv_state_set_format(pvstate_t state, bool progress, bool timer, bool eta, bool fineta, bool rate, bool average_rate, bool bytes, bool bufpercent, size_t lastwritten, /*@null@ */
|
||||
const char *name)
|
||||
void pv_state_set_format_options(pvstate_t state, pvformatoptions_s format)
|
||||
{
|
||||
#define PV_ADDFORMAT(x,y) if (x) { \
|
||||
if (state->control.default_format[0] != '\0') \
|
||||
@@ -419,15 +482,15 @@ void pv_state_set_format(pvstate_t state, bool progress, bool timer, bool eta, b
|
||||
(void) pv_strlcat(state->control.default_format, y, sizeof(state->control.default_format)); \
|
||||
}
|
||||
|
||||
state->control.format_option.progress = progress;
|
||||
state->control.format_option.timer = timer;
|
||||
state->control.format_option.eta = eta;
|
||||
state->control.format_option.fineta = fineta;
|
||||
state->control.format_option.rate = rate;
|
||||
state->control.format_option.average_rate = average_rate;
|
||||
state->control.format_option.bytes = bytes;
|
||||
state->control.format_option.bufpercent = bufpercent;
|
||||
state->control.format_option.lastwritten = lastwritten;
|
||||
state->control.format_option.progress = format.progress;
|
||||
state->control.format_option.timer = format.timer;
|
||||
state->control.format_option.eta = format.eta;
|
||||
state->control.format_option.fineta = format.fineta;
|
||||
state->control.format_option.rate = format.rate;
|
||||
state->control.format_option.average_rate = format.average_rate;
|
||||
state->control.format_option.bytes = format.bytes;
|
||||
state->control.format_option.bufpercent = format.bufpercent;
|
||||
state->control.format_option.lastwritten = format.lastwritten;
|
||||
|
||||
state->control.default_format[0] = '\0';
|
||||
|
||||
@@ -438,21 +501,21 @@ void pv_state_set_format(pvstate_t state, bool progress, bool timer, bool eta, b
|
||||
* Add the format strings for the enabled options in a
|
||||
* standard order.
|
||||
*/
|
||||
PV_ADDFORMAT(name, "%N");
|
||||
PV_ADDFORMAT(bytes, "%b");
|
||||
PV_ADDFORMAT(bufpercent, "%T");
|
||||
PV_ADDFORMAT(timer, "%t");
|
||||
PV_ADDFORMAT(rate, "%r");
|
||||
PV_ADDFORMAT(average_rate, "%a");
|
||||
PV_ADDFORMAT(progress, "%p");
|
||||
PV_ADDFORMAT(eta, "%e");
|
||||
PV_ADDFORMAT(fineta, "%I");
|
||||
PV_ADDFORMAT(NULL != state->control.name, "%N");
|
||||
PV_ADDFORMAT(format.bytes, "%b");
|
||||
PV_ADDFORMAT(format.bufpercent, "%T");
|
||||
PV_ADDFORMAT(format.timer, "%t");
|
||||
PV_ADDFORMAT(format.rate, "%r");
|
||||
PV_ADDFORMAT(format.average_rate, "%a");
|
||||
PV_ADDFORMAT(format.progress, "%p");
|
||||
PV_ADDFORMAT(format.eta, "%e");
|
||||
PV_ADDFORMAT(format.fineta, "%I");
|
||||
|
||||
if (lastwritten > 0) {
|
||||
if (format.lastwritten > 0) {
|
||||
char buf[16]; /* flawfinder: ignore */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
(void) pv_snprintf(buf, sizeof(buf), "%%%uA", (unsigned int) lastwritten);
|
||||
PV_ADDFORMAT(lastwritten > 0, buf);
|
||||
(void) pv_snprintf(buf, sizeof(buf), "%%%uA", (unsigned int) format.lastwritten);
|
||||
PV_ADDFORMAT(format.lastwritten > 0, buf);
|
||||
/*
|
||||
* flawfinder rationale: large enough for string,
|
||||
* zeroed before use, only written to by
|
||||
@@ -463,30 +526,35 @@ void pv_state_set_format(pvstate_t state, bool progress, bool timer, bool eta, b
|
||||
} else {
|
||||
/* Numeric mode has different behaviour. */
|
||||
|
||||
PV_ADDFORMAT(timer, "%t");
|
||||
PV_ADDFORMAT(bytes, "%b");
|
||||
PV_ADDFORMAT(rate, "%r");
|
||||
PV_ADDFORMAT(!(bytes || rate), "%{progress-amount-only}");
|
||||
PV_ADDFORMAT(format.timer, "%t");
|
||||
PV_ADDFORMAT(format.bytes, "%b");
|
||||
PV_ADDFORMAT(format.rate, "%r");
|
||||
PV_ADDFORMAT(!(format.bytes || format.rate), "%{progress-amount-only}");
|
||||
|
||||
}
|
||||
|
||||
debug("%s: [%s]", "default format set", state->control.default_format);
|
||||
|
||||
/* Free any previously set name. */
|
||||
if (NULL != state->control.name) {
|
||||
free(state->control.name);
|
||||
state->control.name = NULL;
|
||||
}
|
||||
|
||||
/* Set a new name if one was given. */
|
||||
if (NULL != name)
|
||||
state->control.name = pv_strdup(name);
|
||||
|
||||
/* Tell pv_format() that the format has changed. */
|
||||
state->flags.reparse_display = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Append a string to the default format, and trigger a format reparse.
|
||||
*/
|
||||
void pv_state_append_to_default_format(pvstate_t state, /*@null@ */ const char *val)
|
||||
{
|
||||
PV_ADDFORMAT(NULL != val, val);
|
||||
state->flags.reparse_display = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Simple setter functions.
|
||||
*/
|
||||
|
||||
|
||||
void pv_state_force_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->control.force = val;
|
||||
@@ -497,6 +565,11 @@ void pv_state_cursor_set(pvstate_t state, bool val)
|
||||
state->control.cursor = val;
|
||||
}
|
||||
|
||||
void pv_state_use_osc94_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->control.use_osc94 = val;
|
||||
}
|
||||
|
||||
void pv_state_show_stats_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->control.show_stats = val;
|
||||
@@ -570,6 +643,7 @@ void pv_state_sync_after_write_set(pvstate_t state, bool val)
|
||||
void pv_state_direct_io_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->control.direct_io = val;
|
||||
/* Tell pv_transfer() to take action when this value changes. */
|
||||
state->control.direct_io_changed = true;
|
||||
}
|
||||
|
||||
@@ -583,9 +657,19 @@ void pv_state_discard_input_set(pvstate_t state, bool val)
|
||||
state->control.discard_input = val;
|
||||
}
|
||||
|
||||
void pv_state_rate_limit_set(pvstate_t state, off_t val)
|
||||
/*
|
||||
* If "was_specified" is true, the limit was specified on the command line.
|
||||
* This is used with --remote to determine whether to affect the remote
|
||||
* process's rate limit settings.
|
||||
*
|
||||
* if "is_active" is true, the limit ("val") is not zero so rate limiting is
|
||||
* active.
|
||||
*/
|
||||
void pv_state_rate_limit_set(pvstate_t state, long double val, bool was_specified, bool is_active)
|
||||
{
|
||||
state->control.rate_limit = val;
|
||||
state->control.rate_limit_specified = was_specified;
|
||||
state->control.rate_limit_active = is_active;
|
||||
}
|
||||
|
||||
void pv_state_target_buffer_size_set(pvstate_t state, size_t val)
|
||||
@@ -598,6 +682,11 @@ void pv_state_no_splice_set(pvstate_t state, bool val)
|
||||
state->control.no_splice = val;
|
||||
}
|
||||
|
||||
void pv_state_pipe_buffer_size_set(pvstate_t state, size_t val)
|
||||
{
|
||||
state->control.pipe_buffer_size = val;
|
||||
}
|
||||
|
||||
void pv_state_size_set(pvstate_t state, off_t val)
|
||||
{
|
||||
state->control.size = val;
|
||||
@@ -655,7 +744,6 @@ void pv_state_format_string_set(pvstate_t state, /*@null@ */ const char *val)
|
||||
void pv_state_extra_display_set(pvstate_t state, /*@null@ */ const char *val)
|
||||
{
|
||||
const char *word_start;
|
||||
size_t offset;
|
||||
|
||||
if (NULL != state->control.extra_display_spec) {
|
||||
free(state->control.extra_display_spec);
|
||||
@@ -676,6 +764,8 @@ void pv_state_extra_display_set(pvstate_t state, /*@null@ */ const char *val)
|
||||
|
||||
word_start = val;
|
||||
while (NULL != word_start && '\0' != word_start[0]) {
|
||||
size_t offset;
|
||||
|
||||
offset = 0;
|
||||
while ('\0' != word_start[offset] && ',' != word_start[offset] && ':' != word_start[offset])
|
||||
offset++;
|
||||
@@ -714,15 +804,14 @@ void pv_state_extra_display_set(pvstate_t state, /*@null@ */ const char *val)
|
||||
void pv_state_output_set(pvstate_t state, int fd, const char *name)
|
||||
{
|
||||
/*
|
||||
* Close any previous output file first, so we can report any errors
|
||||
* before we store the new output filename.
|
||||
* Close any previous output file first, before the old output
|
||||
* filename is replaced, so any associated error can be reported
|
||||
* with the right filename.
|
||||
*/
|
||||
pv_truncate_output(state);
|
||||
if (state->control.output_fd >= 0 && state->control.output_fd != STDOUT_FILENO) {
|
||||
if (close(state->control.output_fd) < 0) {
|
||||
pv_error("%s: %s",
|
||||
NULL == state->control.output_name ? "(null)" : state->control.output_name,
|
||||
strerror(errno));
|
||||
pv_perror("%s", NULL == state->control.output_name ? "(null)" : state->control.output_name);
|
||||
}
|
||||
}
|
||||
if (NULL != state->control.output_name)
|
||||
@@ -733,8 +822,8 @@ void pv_state_output_set(pvstate_t state, int fd, const char *name)
|
||||
/*
|
||||
* Try and make the output use non-blocking I/O.
|
||||
*
|
||||
* Note that this can cause problems with (broken) applications
|
||||
* such as dd when used in a pipeline.
|
||||
* This can cause problems with some, but not all, applications -
|
||||
* such as dd - when used in a pipeline.
|
||||
*/
|
||||
fcntl(state->control.output_fd, F_SETFL, O_NONBLOCK | fcntl(state->control.output_fd, F_GETFL));
|
||||
#endif /* MAKE_OUTPUT_NONBLOCKING */
|
||||
@@ -743,7 +832,7 @@ void pv_state_output_set(pvstate_t state, int fd, const char *name)
|
||||
* In sparse output mode, if the output is in append mode (>>),
|
||||
* explicitly lseek() to the end of the file. Otherwise, the file
|
||||
* offset is not set until the first write(), which means that if
|
||||
* the input starts with null bytes, when we lseek() past them
|
||||
* the input starts with null bytes, upon lseek()ing past them
|
||||
* relative to the current position, the "current position" is 0
|
||||
* rather than the end of the file, and the file gets truncated on
|
||||
* exit to the wrong size.
|
||||
@@ -769,13 +858,32 @@ void pv_state_set_terminal_supports_utf8(pvstate_t state, bool val)
|
||||
state->status.terminal_supports_utf8 = val;
|
||||
}
|
||||
|
||||
void pv_state_othermonitor_set(pvstate_t state, pid_t pid, int read_fd, int write_fd)
|
||||
{
|
||||
state->control.othermonitor_pid = pid;
|
||||
state->control.othermonitor_read_fd = read_fd;
|
||||
state->control.othermonitor_write_fd = write_fd;
|
||||
}
|
||||
|
||||
/* If the format string is set to an empty string, stop all display output. */
|
||||
void pv_state_cancel_output_if_empty_format_string(pvstate_t state)
|
||||
{
|
||||
if (NULL == state->control.format_string)
|
||||
return;
|
||||
if ('\0' != state->control.format_string[0])
|
||||
return;
|
||||
debug("%s", "empty format string - setting no_display and turning off cursor positioning");
|
||||
state->control.no_display = true;
|
||||
state->control.cursor = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the array of input files.
|
||||
*/
|
||||
void pv_state_inputfiles(pvstate_t state, unsigned int input_file_count, const char **input_files)
|
||||
{
|
||||
unsigned int file_idx;
|
||||
/*@only@ */ nullable_string_t *new_array;
|
||||
/*@only@ */ nullable_only_string_t *new_array;
|
||||
|
||||
/* Free the old array and its contents, if there was one. */
|
||||
if (NULL != state->files.filename) {
|
||||
@@ -791,7 +899,7 @@ void pv_state_inputfiles(pvstate_t state, unsigned int input_file_count, const c
|
||||
new_array = calloc((size_t) (input_file_count + 1), sizeof(char *));
|
||||
if (NULL == new_array) {
|
||||
/*@-mustfreefresh@ *//* see similar _() issue above */
|
||||
pv_error("%s: %s", _("file list allocation failed"), strerror(errno));
|
||||
pv_perror("%s", _("memory allocation failure"));
|
||||
/*@+mustfreefresh@ */
|
||||
return;
|
||||
}
|
||||
@@ -803,7 +911,7 @@ void pv_state_inputfiles(pvstate_t state, unsigned int input_file_count, const c
|
||||
new_string = pv_strdup(input_files[file_idx]);
|
||||
if (NULL == new_string) {
|
||||
/*@-mustfreefresh@ *//* see similar _() issue above */
|
||||
pv_error("%s: %s", _("file list allocation failed"), strerror(errno));
|
||||
pv_perror("%s", _("memory allocation failure"));
|
||||
/*@+mustfreefresh@ */
|
||||
return;
|
||||
}
|
||||
@@ -815,7 +923,7 @@ void pv_state_inputfiles(pvstate_t state, unsigned int input_file_count, const c
|
||||
/*
|
||||
* Set the arrays of watchfd process IDs and file descriptors.
|
||||
*/
|
||||
void pv_state_watchfds(pvstate_t state, unsigned int watchfd_count, const pid_t * pids, const int *fds)
|
||||
void pv_state_watchfds(pvstate_t state, unsigned int watchfd_count, const pid_t *pids, const int *fds)
|
||||
{
|
||||
unsigned int item_idx;
|
||||
/*@only@ */ struct pvwatcheditem_s *new_array = NULL;
|
||||
@@ -839,7 +947,7 @@ void pv_state_watchfds(pvstate_t state, unsigned int watchfd_count, const pid_t
|
||||
new_array = malloc((1 + watchfd_count) * sizeof(*new_array));
|
||||
if (NULL == new_array) {
|
||||
/*@-mustfreefresh@ *//* see similar _() issue above */
|
||||
pv_error("%s: %s", _("buffer allocation failed"), strerror(errno));
|
||||
pv_perror("%s", _("memory allocation failure"));
|
||||
/*@+mustfreefresh@ */
|
||||
return;
|
||||
}
|
||||
|
||||
+182
-35
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Functions for portably managing strings.
|
||||
*
|
||||
* Copyright 2023-2025 Andrew Wood
|
||||
* Copyright 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -22,10 +22,10 @@
|
||||
|
||||
|
||||
/*
|
||||
* Wrapper for sprintf(), falling back to sprintf() on systems without that
|
||||
* Wrapper for snprintf(), falling back to sprintf() on systems without that
|
||||
* function.
|
||||
*
|
||||
* Returns -1 if "str" or "format" are NULL or if "size" is 0.
|
||||
* Returns -1 if "format" is NULL.
|
||||
*
|
||||
* Otherwise, ensures that the buffer "str" is always terminated with a '\0'
|
||||
* byte, before returning whatever the system's vsnprintf() or vsprintf()
|
||||
@@ -36,24 +36,26 @@ int pv_snprintf(char *str, size_t size, const char *format, ...)
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
if (NULL == str)
|
||||
return -1;
|
||||
if (0 == size)
|
||||
return -1;
|
||||
if (NULL == format)
|
||||
if (NULL == format) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
str[0] = '\0';
|
||||
if (NULL != str && size > 0)
|
||||
str[0] = '\0';
|
||||
|
||||
va_start(ap, format);
|
||||
/*@-nullpass@ */
|
||||
#ifdef HAVE_VSNPRINTF
|
||||
ret = vsnprintf(str, size, format, ap); /* flawfinder: ignore */
|
||||
#else /* ! HAVE_VSNPRINTF */
|
||||
ret = vsprintf(str, format, ap); /* flawfinder: ignore */
|
||||
#endif /* HAVE_VSNPRINTF */
|
||||
/*@+nullpass@ *//* explicitly allowing NULL to behave as vsnprintf() does. */
|
||||
va_end(ap);
|
||||
|
||||
str[size - 1] = '\0';
|
||||
if (NULL != str && size > 0)
|
||||
str[size - 1] = '\0';
|
||||
|
||||
/*
|
||||
* flawfinder rationale: this function replaces snprintf so
|
||||
@@ -65,6 +67,131 @@ int pv_snprintf(char *str, size_t size, const char *format, ...)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Wrapper for asprintf(), working around it on systems without that
|
||||
* function.
|
||||
*
|
||||
* Allocates a buffer large enough for the expanded format string plus a
|
||||
* terminating '\0' byte, points *strp to it, and returns whatever the
|
||||
* system's vasprintf() or vsprintf() returned.
|
||||
*
|
||||
* Returns -1 if "strp" is NULL.
|
||||
* Returns -1 and sets *strp to NULL if "format" is NULL.
|
||||
*/
|
||||
int pv_asprintf(nullable_string_ptr *strp, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *new_string = NULL;
|
||||
size_t new_size = 0;
|
||||
int ret;
|
||||
|
||||
if (NULL == strp)
|
||||
return -1;
|
||||
*strp = NULL;
|
||||
if (NULL == format)
|
||||
return -1;
|
||||
|
||||
#ifdef HAVE_VASPRINTF
|
||||
va_start(ap, format);
|
||||
/*@-unrecog@ */
|
||||
ret = vasprintf(strp, format, ap); /* flawfinder: ignore */
|
||||
/*@+unrecog@ *//* splint doesn't know about vasprintf(). */
|
||||
va_end(ap);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
new_string = *strp;
|
||||
new_size = (size_t) ret + 1;
|
||||
#else /* ! HAVE_VASPRINTF */
|
||||
|
||||
#ifdef HAVE_VSNPRINTF
|
||||
/* Find out the required size. */
|
||||
{
|
||||
char tmpbuf[8]; /* flawfinder: ignore - bounded by vsnprintf(). */
|
||||
va_start(ap, format);
|
||||
ret = vsnprintf(tmpbuf, 7, format, ap); /* flawfinder: ignore */
|
||||
va_end(ap);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allocate a buffer big enough to include a terminating \0. */
|
||||
new_size = (size_t) ret + 1;
|
||||
new_string = malloc(new_size);
|
||||
if (NULL == new_string)
|
||||
return -1;
|
||||
new_string[0] = '\0';
|
||||
|
||||
/* Generate the string. */
|
||||
va_start(ap, format);
|
||||
ret = vsnprintf(new_string, new_size, format, ap); /* flawfinder: ignore */
|
||||
va_end(ap);
|
||||
if (ret < 0) {
|
||||
int old_errno;
|
||||
old_errno = errno;
|
||||
free(new_string);
|
||||
errno = old_errno;
|
||||
return ret;
|
||||
}
|
||||
*strp = new_string;
|
||||
#else /* ! HAVE_VSNPRINTF */
|
||||
/*
|
||||
* Without vsnprintf(), determining the required size is impossible
|
||||
* without a buffer to write to. The best effort here is to
|
||||
* allocate a large buffer, write to it, then duplicate the string
|
||||
* afterwards. This means there's an arbitrary upper bound on
|
||||
* string size and there will be some heap fragmentation.
|
||||
*/
|
||||
|
||||
/* Allocate a large buffer for the string. */
|
||||
new_size = 16384;
|
||||
new_string = malloc(new_size);
|
||||
if (NULL == new_string)
|
||||
return -1;
|
||||
new_string[0] = '\0';
|
||||
|
||||
/* Generate the string. */
|
||||
va_start(ap, format);
|
||||
ret = vsprintf(new_string, format, ap); /* flawfinder: ignore */
|
||||
va_end(ap);
|
||||
if (ret < 0) {
|
||||
int old_errno;
|
||||
old_errno = errno;
|
||||
free(new_string);
|
||||
errno = old_errno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Duplicate the string into a buffer just long enough for it. */
|
||||
*strp = pv_strdup(new_string);
|
||||
if (NULL == *strp) {
|
||||
int old_errno;
|
||||
old_errno = errno;
|
||||
free(new_string);
|
||||
errno = old_errno;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Free the original large buffer, and use the new one instead. */
|
||||
free(new_string);
|
||||
new_string = *strp;
|
||||
#endif /* HAVE_VSNPRINTF */
|
||||
#endif /* HAVE_VASPRINTF */
|
||||
|
||||
/* Terminate the new string. */
|
||||
if (NULL != new_string && new_size > 0)
|
||||
new_string[new_size - 1] = '\0';
|
||||
|
||||
/*
|
||||
* flawfinder rationale: this function replaces asprintf so
|
||||
* explicitly takes a non-constant format; also it explicitly
|
||||
* \0-terminates the output buffer.
|
||||
*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of strlcat() where it is unavailable: append a string to a
|
||||
* buffer, constraining the buffer to a particular size and ensuring
|
||||
@@ -75,7 +202,7 @@ int pv_snprintf(char *str, size_t size, const char *format, ...)
|
||||
* byte.
|
||||
*
|
||||
* Returns the intended length of the string, not including the terminating
|
||||
* '\0', i.e. strlen(src)+strlen(dst), regardless of whether truncation
|
||||
* '\0', i.e. strlen(src)+strlen(dst), regardless of whether truncation
|
||||
* occurred.
|
||||
*
|
||||
* Note that this implementation has the side effect that "dst" will always
|
||||
@@ -86,7 +213,9 @@ size_t pv_strlcat(char *dst, const char *src, size_t dstsize)
|
||||
#ifdef HAVE_STRLCAT
|
||||
size_t result;
|
||||
|
||||
/*@-unrecog@ *//* splint doesn't recognise strlcat. */
|
||||
result = strlcat(dst, src, dstsize);
|
||||
/*@+unrecog@ */
|
||||
|
||||
if ((NULL != dst) && (dstsize > 0))
|
||||
dst[dstsize - 1] = '\0';
|
||||
@@ -108,8 +237,8 @@ size_t pv_strlcat(char *dst, const char *src, size_t dstsize)
|
||||
|
||||
/*
|
||||
* flawfinder rationale: src must explicitly be \0 terminated, so
|
||||
* this is up to the caller; with dst, we enforce \0 termination
|
||||
* before calling strlen().
|
||||
* this is up to the caller; with dst, \0 termination is enforced
|
||||
* before strlen() is called.
|
||||
*/
|
||||
|
||||
available = dstsize - dstlen;
|
||||
@@ -127,7 +256,7 @@ size_t pv_strlcat(char *dst, const char *src, size_t dstsize)
|
||||
*/
|
||||
/*@null@ */
|
||||
/*@only@ */
|
||||
char *pv_strdup(const char *original)
|
||||
char *pv_strdup(const /*@null@ */ char *original)
|
||||
{
|
||||
size_t length;
|
||||
char *duplicate;
|
||||
@@ -192,14 +321,15 @@ void *pv_memrchr(const void *buffer, int match, size_t length)
|
||||
* Return the number of display columns needed to show the
|
||||
* non-null-terminated string "string" whose length in bytes is "bytes".
|
||||
*
|
||||
* Skips ECMA-48 CSI (ESC [ ...) sequences, but any other control characters
|
||||
* are treated as printable.
|
||||
* Skips ECMA-48 CSI (ESC [ ...) sequences, and OSC (ESC ] ...) sequences,
|
||||
* but any other control characters are treated as printable.
|
||||
*
|
||||
* To do this, we convert it to a wide character string, and use the wide
|
||||
* character display width function "wcswidth()" on it.
|
||||
* Internally, after skipping CSI or OSC sequences, the string is converted
|
||||
* to a wide character string, and each wide character's width is checked
|
||||
* with "wcswidth()".
|
||||
*
|
||||
* If NLS is disabled, or the string cannot be converted, this just returns
|
||||
* the value of "bytes".
|
||||
* the number of bytes in the string that aren't part of CSI sequences.
|
||||
*
|
||||
* Note that this function uses internal buffers if the string is short
|
||||
* enough, otherwise it has to call malloc() and free(), so it becomes less
|
||||
@@ -234,19 +364,36 @@ size_t pv_strwidth(const char *string, size_t bytes)
|
||||
raw_string = allocated_raw;
|
||||
}
|
||||
|
||||
/* Copy the original string, skipping ECMA-48 CSI sequences. */
|
||||
/*
|
||||
* Copy the original string, skipping ECMA-48 CSI and OSC sequences.
|
||||
*/
|
||||
for (read_pos = 0, write_pos = 0; read_pos < bytes; read_pos++) {
|
||||
if ((string[read_pos] != '\033') || (read_pos >= bytes - 1) || (string[read_pos + 1] != '[')) {
|
||||
if ((string[read_pos] == '\033') && (read_pos < bytes - 1) && (string[read_pos + 1] == '[')) {
|
||||
/* Skip CSI - ends with anything other than 0-9 or ';'. */
|
||||
read_pos += 2;
|
||||
while ((read_pos < bytes - 1)
|
||||
&& ((string[read_pos] >= '0' && string[read_pos] <= '9')
|
||||
|| (';' == string[read_pos])
|
||||
)
|
||||
) {
|
||||
read_pos++;
|
||||
}
|
||||
} else if ((string[read_pos] == '\033') && (read_pos < bytes - 1) && (string[read_pos + 1] == ']')) {
|
||||
/* Skip OSC - ends with BEL or ST (ESC \). */
|
||||
read_pos += 2;
|
||||
while (read_pos < bytes - 1) {
|
||||
if (string[read_pos] == '\007') {
|
||||
break;
|
||||
}
|
||||
if ((string[read_pos] == '\033') && (string[1 + read_pos] == '\\')) {
|
||||
read_pos++;
|
||||
break;
|
||||
}
|
||||
read_pos++;
|
||||
}
|
||||
} else {
|
||||
/* Don't skip, copy across. */
|
||||
raw_string[write_pos++] = string[read_pos];
|
||||
continue;
|
||||
}
|
||||
read_pos += 2;
|
||||
while ((read_pos < bytes - 1)
|
||||
&& ((string[read_pos] >= '0' && string[read_pos] <= '9')
|
||||
|| (';' == string[read_pos])
|
||||
)
|
||||
) {
|
||||
read_pos++;
|
||||
}
|
||||
}
|
||||
raw_string[write_pos] = '\0';
|
||||
@@ -276,7 +423,7 @@ size_t pv_strwidth(const char *string, size_t bytes)
|
||||
} else {
|
||||
allocated_wide = malloc(wide_string_buffer_size);
|
||||
if (NULL == allocated_wide) {
|
||||
perror("malloc");
|
||||
pv_perror("%s", "malloc");
|
||||
if (NULL != allocated_raw)
|
||||
free(allocated_raw);
|
||||
return raw_bytes;
|
||||
@@ -288,7 +435,7 @@ size_t pv_strwidth(const char *string, size_t bytes)
|
||||
if (mbstowcs(wide_string, raw_string, 1 + wide_char_count) == (size_t) -1) {
|
||||
debug("%s: %s: %s", "mbstowcs", raw_string, strerror(errno));
|
||||
} else if (NULL != wide_string) {
|
||||
/*@-unrecog@ *//* splint seems unable to see the prototype. */
|
||||
/*@-unrecog@ *//* splint doesn't see the prototype. */
|
||||
width = wcswidth(wide_string, wide_char_count);
|
||||
/*@+unrecog@ */
|
||||
} else {
|
||||
@@ -307,9 +454,9 @@ size_t pv_strwidth(const char *string, size_t bytes)
|
||||
|
||||
|
||||
/*
|
||||
* Return true if the character is printable. This function is used instead
|
||||
* of the macro from <ctype.h> to avoid causing versioned glibc dependencies
|
||||
* on some systems.
|
||||
* Return true if the character is printable 7-bit ASCII. This function is
|
||||
* used instead of the macro from <ctype.h> to avoid causing versioned glibc
|
||||
* dependencies on some systems.
|
||||
*/
|
||||
bool pv_isprint(char c)
|
||||
{
|
||||
|
||||
+999
-358
File diff suppressed because it is too large
Load Diff
+183
-62
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Functions for watching file descriptors in other processes.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2026 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
@@ -36,25 +36,27 @@
|
||||
|
||||
/*
|
||||
* Set info->size to the size of the file info->file_fdpath points to,
|
||||
* assuming that info->sb_fd has been populated by stat(), or to 0 if the
|
||||
* file size could not be determined or the file was opened in write mode;
|
||||
* returns false if the file was not a block device or regular file.
|
||||
* assuming that info->sb_fd has already been populated by stat(), or to 0
|
||||
* if the file size could not be determined or the file was opened in write
|
||||
* mode; returns false if the file was not a block device or regular file.
|
||||
*/
|
||||
static bool filesize(pvwatchfd_t info)
|
||||
{
|
||||
if (NULL == info)
|
||||
return false;
|
||||
if (NULL == info->file_fdpath)
|
||||
return false;
|
||||
if (S_ISBLK(info->sb_fd.st_mode)) {
|
||||
int fd;
|
||||
|
||||
/*
|
||||
* Get the size of block devices by opening
|
||||
* them and seeking to the end.
|
||||
* Get the size of block devices by opening them and seeking
|
||||
* to the end.
|
||||
*/
|
||||
fd = open(info->file_fdpath, O_RDONLY); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder: redirection check below; risk is minimal as
|
||||
* we are not actually reading any data here.
|
||||
* no reads are performed.
|
||||
*/
|
||||
if (fd >= 0) {
|
||||
/*
|
||||
@@ -74,10 +76,14 @@ static bool filesize(pvwatchfd_t info)
|
||||
info->size = 0;
|
||||
}
|
||||
} else if (S_ISREG(info->sb_fd.st_mode)) {
|
||||
|
||||
/* Regular file - use its st_size. */
|
||||
if ((info->sb_fd_link.st_mode & S_IWUSR) == 0) {
|
||||
info->size = info->sb_fd.st_size;
|
||||
}
|
||||
} else {
|
||||
|
||||
/* Not a block device or a file, so the size is unknown. */
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -87,7 +93,23 @@ static bool filesize(pvwatchfd_t info)
|
||||
/*@+type@*/
|
||||
|
||||
#ifdef __APPLE__
|
||||
int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
/*
|
||||
* Populate the "info" structure with the file paths and stat details of the
|
||||
* process and file descriptor pair given within that structure.
|
||||
*
|
||||
* Returns nonzero on error - error codes are:
|
||||
*
|
||||
* -1 - info or state were NULL
|
||||
* 1 - process does not exist
|
||||
* 2 - not applicable (see the alternative pv_watchfd_info() below)
|
||||
* 3 - lookup of the file descriptor destination failed
|
||||
* 4 - file descriptor is not opened on a regular file
|
||||
*
|
||||
* If "automatic" is true, then this fd was picked automatically, and so if
|
||||
* it's not readable or not a regular file, no error is reported with
|
||||
* pv_error() when returning the error code.
|
||||
*/
|
||||
static int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
{
|
||||
struct vnode_fdinfowithpath vnodeInfo = { };
|
||||
|
||||
@@ -98,7 +120,7 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
|
||||
if (kill(info->watch_pid, 0) != 0) {
|
||||
if (!automatic)
|
||||
pv_error("%s %u: %s", _("pid"), info->watch_pid, strerror(errno));
|
||||
pv_perror("%s %u", _("pid"), info->watch_pid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -107,19 +129,26 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
PROC_PIDFDVNODEPATHINFO, &vnodeInfo,
|
||||
PROC_PIDFDVNODEPATHINFO_SIZE);
|
||||
if (size != PROC_PIDFDVNODEPATHINFO_SIZE) {
|
||||
pv_error("%s %u: %s %d: %s", _("pid"), info->watch_pid, _("fd"), info->watch_fd, strerror(errno));
|
||||
pv_perror("%s %u: %s %d", _("pid"), info->watch_pid, _("fd"), info->watch_fd);
|
||||
return 3;
|
||||
}
|
||||
|
||||
strlcpy(info->file_fdpath, vnodeInfo.pvip.vip_path, PV_SIZEOF_FILE_FDPATH);
|
||||
if (NULL != info->file_fdpath) {
|
||||
free(info->file_fdpath);
|
||||
info->file_fdpath = NULL;
|
||||
}
|
||||
info->file_fdpath = pv_strdup(vnodeInfo.pvip.vip_path);
|
||||
if (NULL == info->file_fdpath) {
|
||||
pv_perror("%s %u: %s %d", _("pid"), info->watch_pid, _("fd"), info->watch_fd);
|
||||
return 3;
|
||||
}
|
||||
|
||||
info->size = 0;
|
||||
|
||||
if (!(0 == stat(info->file_fdpath, &(info->sb_fd)))) {
|
||||
if (!automatic)
|
||||
pv_error("%s %u: %s %d: %s: %s",
|
||||
_("pid"),
|
||||
info->watch_pid, _("fd"), info->watch_fd, info->file_fdpath, strerror(errno));
|
||||
pv_perror("%s %u: %s %d: %s",
|
||||
_("pid"), info->watch_pid, _("fd"), info->watch_fd, info->file_fdpath);
|
||||
return 3;
|
||||
}
|
||||
|
||||
@@ -138,9 +167,8 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
#else
|
||||
|
||||
/*
|
||||
* Fill in the given information structure with the file paths and stat
|
||||
* details of the given file descriptor within the given process (given
|
||||
* within the info structure).
|
||||
* Populate the "info" structure with the file paths and stat details of the
|
||||
* process and file descriptor pair given within that structure.
|
||||
*
|
||||
* Returns nonzero on error - error codes are:
|
||||
*
|
||||
@@ -151,10 +179,10 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
* 4 - file descriptor is not opened on a regular file
|
||||
*
|
||||
* If "automatic" is true, then this fd was picked automatically, and so if
|
||||
* it's not readable or not a regular file, no error is displayed and the
|
||||
* function just returns an error code.
|
||||
* it's not readable or not a regular file, no error is reported with
|
||||
* pv_error() when returning the error code.
|
||||
*/
|
||||
int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
static int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
{
|
||||
if (NULL == state)
|
||||
return -1;
|
||||
@@ -163,40 +191,95 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
|
||||
if (kill(info->watch_pid, 0) != 0) {
|
||||
if (!automatic)
|
||||
pv_error("%s %u: %s", _("pid"), info->watch_pid, strerror(errno));
|
||||
pv_perror("%s %u", _("pid"), info->watch_pid);
|
||||
return 1;
|
||||
}
|
||||
(void) pv_snprintf(info->file_fdinfo, PV_SIZEOF_FILE_FDINFO,
|
||||
"/proc/%u/fdinfo/%d", info->watch_pid, info->watch_fd);
|
||||
(void) pv_snprintf(info->file_fd, PV_SIZEOF_FILE_FD, "/proc/%u/fd/%d", info->watch_pid, info->watch_fd);
|
||||
|
||||
memset(info->file_fdpath, 0, PV_SIZEOF_FILE_FDPATH);
|
||||
if (readlink(info->file_fd, info->file_fdpath, PV_SIZEOF_FILE_FDPATH - 1) < 0) { /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder: memset() has put \0 at the end already, and
|
||||
* we tell readlink() to use 1 byte less than the buffer
|
||||
* length, so \0 termination is assured. There is no
|
||||
* mitigation for the risk of the link changing while we
|
||||
* read it, but we are only reading from the destination,
|
||||
* and then only if it's a block device - see filesize().
|
||||
*/
|
||||
/* Build the string containing the path to the /proc fdinfo file. */
|
||||
if (NULL != info->file_fdinfo) {
|
||||
free(info->file_fdinfo);
|
||||
info->file_fdinfo = NULL;
|
||||
}
|
||||
if ((pv_asprintf(&(info->file_fdinfo), "/proc/%u/fdinfo/%d", info->watch_pid, info->watch_fd) < 0)
|
||||
|| (NULL == info->file_fdinfo)) {
|
||||
if (!automatic)
|
||||
pv_error("%s %u: %s %d: %s",
|
||||
_("pid"), info->watch_pid, _("fd"), info->watch_fd, strerror(errno));
|
||||
pv_perror("%s %u", _("pid"), info->watch_pid);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (!((0 == stat(info->file_fd, &(info->sb_fd)))
|
||||
&& (0 == lstat(info->file_fd, &(info->sb_fd_link))))) {
|
||||
/* Build the string containing the path to the /proc fd symlink. */
|
||||
if (NULL != info->file_fdsymlink) {
|
||||
free(info->file_fdsymlink);
|
||||
info->file_fdsymlink = NULL;
|
||||
}
|
||||
if ((pv_asprintf(&(info->file_fdsymlink), "/proc/%u/fd/%d", info->watch_pid, info->watch_fd) < 0)
|
||||
|| (NULL == info->file_fdsymlink)) {
|
||||
if (!automatic)
|
||||
pv_error("%s %u: %s %d: %s: %s",
|
||||
_("pid"),
|
||||
info->watch_pid, _("fd"), info->watch_fd, info->file_fdpath, strerror(errno));
|
||||
pv_perror("%s %u", _("pid"), info->watch_pid);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Get a string containing the path that the /proc fd symlink points to. */
|
||||
if (NULL != info->file_fdpath) {
|
||||
free(info->file_fdpath);
|
||||
info->file_fdpath = NULL;
|
||||
}
|
||||
/* Try buffers of different sizes - see readlink(2). */
|
||||
{
|
||||
size_t try_size;
|
||||
|
||||
for (try_size = 16; try_size <= 16384; try_size = try_size * 2) {
|
||||
ssize_t bytes_stored;
|
||||
|
||||
if (NULL != info->file_fdpath) {
|
||||
free(info->file_fdpath);
|
||||
info->file_fdpath = NULL;
|
||||
}
|
||||
/*@-mustfreeonly@ *//* splint mis-detects this as a memory leak. */
|
||||
info->file_fdpath = calloc(1, try_size);
|
||||
/*@+mustfreeonly@ */
|
||||
if (NULL == info->file_fdpath)
|
||||
break;
|
||||
|
||||
bytes_stored = readlink(info->file_fdsymlink, info->file_fdpath, try_size - 1); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder: the risk is minimal, as no reads are
|
||||
* performed.
|
||||
*/
|
||||
if (bytes_stored < 0) {
|
||||
int old_errno;
|
||||
old_errno = errno;
|
||||
free(info->file_fdpath);
|
||||
info->file_fdpath = NULL;
|
||||
errno = old_errno;
|
||||
break;
|
||||
} else if (bytes_stored < (ssize_t) (try_size - 1)) {
|
||||
info->file_fdpath[bytes_stored] = '\0';
|
||||
break;
|
||||
} else {
|
||||
free(info->file_fdpath);
|
||||
info->file_fdpath = NULL;
|
||||
errno = ENAMETOOLONG;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NULL == info->file_fdpath) {
|
||||
if (!automatic)
|
||||
pv_perror("%s %u: %s %d", _("pid"), info->watch_pid, _("fd"), info->watch_fd);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Run stat() on the /proc fd symlink and the path it points to. */
|
||||
if (!((0 == stat(info->file_fdsymlink, &(info->sb_fd)))
|
||||
&& (0 == lstat(info->file_fdsymlink, &(info->sb_fd_link))))) {
|
||||
if (!automatic)
|
||||
pv_perror("%s %u: %s %d: %s",
|
||||
_("pid"), info->watch_pid, _("fd"), info->watch_fd, info->file_fdpath);
|
||||
return 3;
|
||||
}
|
||||
|
||||
/* Find the size of the path pointed to. */
|
||||
info->size = 0;
|
||||
|
||||
if (!filesize(info)) {
|
||||
if (!automatic)
|
||||
pv_error("%s %u: %s %d: %s: %s",
|
||||
@@ -218,7 +301,7 @@ bool pv_watchfd_changed(pvwatchfd_t info)
|
||||
#else
|
||||
/*
|
||||
* Return true if the given file descriptor has changed in some way since
|
||||
* we started looking at it (i.e. changed destination or permissions).
|
||||
* it was first detected (i.e. changed destination or permissions).
|
||||
*/
|
||||
bool pv_watchfd_changed(pvwatchfd_t info)
|
||||
{
|
||||
@@ -226,12 +309,14 @@ bool pv_watchfd_changed(pvwatchfd_t info)
|
||||
|
||||
if (NULL == info)
|
||||
return false;
|
||||
if (NULL == info->file_fdsymlink)
|
||||
return false;
|
||||
|
||||
memset(&sb_fd, 0, sizeof(sb_fd));
|
||||
memset(&sb_fd_link, 0, sizeof(sb_fd_link));
|
||||
|
||||
if ((0 == stat(info->file_fd, &sb_fd))
|
||||
&& (0 == lstat(info->file_fd, &sb_fd_link))) {
|
||||
if ((0 == stat(info->file_fdsymlink, &sb_fd))
|
||||
&& (0 == lstat(info->file_fdsymlink, &sb_fd_link))) {
|
||||
if ((sb_fd.st_dev != info->sb_fd.st_dev)
|
||||
|| (sb_fd.st_ino != info->sb_fd.st_ino)
|
||||
|| (sb_fd_link.st_mode != info->sb_fd_link.st_mode)
|
||||
@@ -276,6 +361,8 @@ off_t pv_watchfd_position(pvwatchfd_t info)
|
||||
if (pv_watchfd_changed(info))
|
||||
return -1;
|
||||
|
||||
if (NULL == info->file_fdinfo)
|
||||
return -1;
|
||||
fptr = fopen(info->file_fdinfo, "r"); /* flawfinder: ignore */
|
||||
/* flawfinder: trusted location (/proc). */
|
||||
if (NULL == fptr)
|
||||
@@ -300,11 +387,18 @@ off_t pv_watchfd_position(pvwatchfd_t info)
|
||||
|
||||
|
||||
#ifdef __APPLE__
|
||||
/*
|
||||
* Allocate an array of proc_fdinfo structs containing details of the file
|
||||
* descriptors opened by process "pid", placing the pointer to the array
|
||||
* into *fds and the number of entries in it into *count.
|
||||
*
|
||||
* Returns nonzero on error, and reports the error.
|
||||
*/
|
||||
static int pidfds(pvstate_t state, unsigned int pid, struct proc_fdinfo **fds, int *count)
|
||||
{
|
||||
int size_needed = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, 0, 0);
|
||||
if (size_needed == -1) {
|
||||
pv_error("%s: unable to list pid fds: %s", _("pid"), strerror(errno));
|
||||
pv_perror("%s %u", _("pid"), pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -312,7 +406,7 @@ static int pidfds(pvstate_t state, unsigned int pid, struct proc_fdinfo **fds, i
|
||||
|
||||
*fds = (struct proc_fdinfo *) malloc(size_needed);
|
||||
if (*fds == NULL) {
|
||||
pv_error("%s: alloc failed: %s", _("pid"), strerror(errno));
|
||||
pv_perror("%s %u", _("pid"), pid);
|
||||
return -1;
|
||||
}
|
||||
memset(*fds, 0, size_needed);
|
||||
@@ -336,7 +430,7 @@ static int pidfds(pvstate_t state, unsigned int pid, struct proc_fdinfo **fds, i
|
||||
/*
|
||||
* Extend the info array by one, returning false on error.
|
||||
*/
|
||||
static bool extend_info_array(int *array_length_ptr, pvwatchfd_t * info_array_ptr)
|
||||
static bool extend_info_array(int *array_length_ptr, pvwatchfd_t *info_array_ptr)
|
||||
{
|
||||
int array_length = 0;
|
||||
struct pvwatchfd_s *info_array = NULL;
|
||||
@@ -378,7 +472,7 @@ static bool extend_info_array(int *array_length_ptr, pvwatchfd_t * info_array_pt
|
||||
/*
|
||||
* Reset calculated values in the given watchfd info structure.
|
||||
*/
|
||||
void pv_reset_watchfd(pvwatchfd_t info)
|
||||
static void pv_reset_watchfd(pvwatchfd_t info)
|
||||
{
|
||||
if (NULL == info)
|
||||
return;
|
||||
@@ -399,6 +493,21 @@ void pv_freecontents_watchfd(pvwatchfd_t info)
|
||||
pv_freecontents_calc(&(info->calc));
|
||||
pv_freecontents_transfer(&(info->transfer));
|
||||
pv_freecontents_display(&(info->display));
|
||||
#ifdef __APPLE__
|
||||
#else
|
||||
if (NULL != info->file_fdinfo) {
|
||||
free(info->file_fdinfo);
|
||||
info->file_fdinfo = NULL;
|
||||
}
|
||||
if (NULL != info->file_fdsymlink) {
|
||||
free(info->file_fdsymlink);
|
||||
info->file_fdsymlink = NULL;
|
||||
}
|
||||
#endif
|
||||
if (NULL != info->file_fdpath) {
|
||||
free(info->file_fdpath);
|
||||
info->file_fdpath = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -425,7 +534,7 @@ static int pv_compare_watchfd(const void *a, const void *b)
|
||||
|
||||
|
||||
/*
|
||||
* Scan the given process and update the arrays with any new file
|
||||
* Scan the process "watch_pid" and update the arrays with any new file
|
||||
* descriptors. If "watch_fd" is not -1, then all other file descriptor
|
||||
* numbers will be ignored,
|
||||
*
|
||||
@@ -433,7 +542,7 @@ static int pv_compare_watchfd(const void *a, const void *b)
|
||||
* read, or 2 for a memory allocation error.
|
||||
*/
|
||||
int pv_watchpid_scanfds(pvstate_t state, pid_t watch_pid, int watch_fd, int *array_length_ptr,
|
||||
pvwatchfd_t * info_array_ptr)
|
||||
pvwatchfd_t *info_array_ptr)
|
||||
{
|
||||
int array_length = 0;
|
||||
struct pvwatchfd_s *info_array = NULL;
|
||||
@@ -444,20 +553,27 @@ int pv_watchpid_scanfds(pvstate_t state, pid_t watch_pid, int watch_fd, int *arr
|
||||
int fd_infos_count = 0;
|
||||
|
||||
if (pidfds(state, watch_pid, &fd_infos, &fd_infos_count) != 0) {
|
||||
pv_error("%s: pidfds failed", _("pid"));
|
||||
pv_error("%s %u: pidfds failed", _("pid"), watch_pid);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
char fd_dir[512]; /* flawfinder: ignore - zeroed, bounded with pv_snprintf(). */
|
||||
nullable_string_ptr fd_dir = NULL;
|
||||
DIR *dptr;
|
||||
struct dirent *d;
|
||||
const struct dirent *d;
|
||||
|
||||
memset(fd_dir, 0, sizeof(fd_dir));
|
||||
(void) pv_snprintf(fd_dir, sizeof(fd_dir), "/proc/%u/fd", watch_pid);
|
||||
if ((pv_asprintf(&fd_dir, "/proc/%u/fd", watch_pid) < 0) || (NULL == fd_dir)) {
|
||||
pv_perror("%s %u", _("pid"), watch_pid);
|
||||
return 2;
|
||||
}
|
||||
|
||||
dptr = opendir(fd_dir);
|
||||
if (NULL == dptr)
|
||||
if (NULL == dptr) {
|
||||
free(fd_dir);
|
||||
return 1;
|
||||
}
|
||||
|
||||
free(fd_dir);
|
||||
fd_dir = NULL;
|
||||
#endif
|
||||
|
||||
array_length = *array_length_ptr;
|
||||
@@ -467,7 +583,7 @@ int pv_watchpid_scanfds(pvstate_t state, pid_t watch_pid, int watch_fd, int *arr
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (fd_infos_count < 1) {
|
||||
pv_error("%s: no fds found", _("pid"));
|
||||
pv_error("%s %u: no fds found", _("pid"), watch_pid);
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < fd_infos_count; i++) {
|
||||
@@ -494,7 +610,7 @@ int pv_watchpid_scanfds(pvstate_t state, pid_t watch_pid, int watch_fd, int *arr
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Skip if this fd is already known to us.
|
||||
* Skip if this fd is already known.
|
||||
*/
|
||||
found_idx = -1;
|
||||
for (check_idx = 0; check_idx < array_length && NULL != info_array; check_idx++) {
|
||||
@@ -519,7 +635,7 @@ int pv_watchpid_scanfds(pvstate_t state, pid_t watch_pid, int watch_fd, int *arr
|
||||
continue;
|
||||
|
||||
/*
|
||||
* See if there's an empty slot we can re-use.
|
||||
* Check for an empty slot to re-use.
|
||||
*/
|
||||
use_idx = -1;
|
||||
for (check_idx = 0; check_idx < array_length && NULL != info_array; check_idx++) {
|
||||
@@ -658,11 +774,16 @@ void pv_watchpid_setname(pvstate_t state, pvwatchfd_t info)
|
||||
file_fdpath = info->file_fdpath;
|
||||
|
||||
memset(info->display_name, 0, PV_SIZEOF_DISPLAY_NAME);
|
||||
if (NULL == file_fdpath)
|
||||
return;
|
||||
|
||||
path_length = strlen(info->file_fdpath); /* flawfinder: ignore */
|
||||
cwd_length = strlen(state->status.cwd); /* flawfinder: ignore */
|
||||
cwd_length = 0;
|
||||
if (NULL != state->status.cwd) {
|
||||
cwd_length = strlen(state->status.cwd); /* flawfinder: ignore */
|
||||
}
|
||||
/* flawfinder: both strings are always \0 terminated. */
|
||||
if (cwd_length > 0 && path_length > cwd_length) {
|
||||
if (cwd_length > 0 && path_length > cwd_length && NULL != state->status.cwd) {
|
||||
if (0 == strncmp(info->file_fdpath, state->status.cwd, cwd_length)) {
|
||||
file_fdpath += cwd_length + 1;
|
||||
path_length -= cwd_length + 1;
|
||||
|
||||
@@ -22,10 +22,10 @@ if ! test "${valueCount}" -gt 0; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 8 or more different values - not OK.
|
||||
# 10 or more different values - not OK.
|
||||
#
|
||||
if ! test "${valueCount}" -lt 8; then
|
||||
echo "more than 7 different values (${valueCount})"
|
||||
if ! test "${valueCount}" -lt 10; then
|
||||
echo "more than 9 different values (${valueCount})"
|
||||
tr '\r' '\n' < "${workFile1}" | sed '/^ *$/d' | sort | uniq
|
||||
exit 1
|
||||
fi
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that EOF does not wait forever when the output pipe reader exits
|
||||
# without consuming bytes already written into the pipe.
|
||||
|
||||
# Allow all tests to be skipped, e.g. during a release build
|
||||
test "${SKIP_ALL_TESTS}" = "1" && exit 77
|
||||
|
||||
true "${testSubject:?not set - call this from 'make check'}"
|
||||
|
||||
TIMEOUT=""
|
||||
if command -v timeout >/dev/null 2>&1; then
|
||||
TIMEOUT="timeout"
|
||||
elif command -v gtimeout >/dev/null 2>&1; then
|
||||
TIMEOUT="gtimeout"
|
||||
else
|
||||
echo "timeout command not available"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
# The reader keeps the pipe open briefly but reads nothing. When it exits,
|
||||
# PV has no further input, so it must notice the closed reader without
|
||||
# relying on a later write returning EPIPE.
|
||||
if ! "${TIMEOUT}" 4 sh <<EOF
|
||||
printf "x" | "${testSubject}" -q -B 1 | sleep 1
|
||||
EOF
|
||||
then
|
||||
echo "PV did not finish after the output pipe reader exited"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that EOF does not wait forever when the upstream producer exits with
|
||||
# failure and the output pipe reader exits without consuming buffered bytes.
|
||||
|
||||
# Allow all tests to be skipped, e.g. during a release build
|
||||
test "${SKIP_ALL_TESTS}" = "1" && exit 77
|
||||
|
||||
true "${testSubject:?not set - call this from 'make check'}"
|
||||
|
||||
TIMEOUT=""
|
||||
if command -v timeout >/dev/null 2>&1; then
|
||||
TIMEOUT="timeout"
|
||||
elif command -v gtimeout >/dev/null 2>&1; then
|
||||
TIMEOUT="gtimeout"
|
||||
else
|
||||
echo "timeout command not available"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
if ! command -v gzip >/dev/null 2>&1; then
|
||||
echo "gzip command not available"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
# The producer fails immediately and writes no data. gzip still emits a small
|
||||
# valid empty stream, so PV writes bytes to its output pipe before reaching EOF.
|
||||
# The reader keeps the pipe open briefly but consumes nothing.
|
||||
if ! "${TIMEOUT}" 4 sh <<EOF
|
||||
false | gzip -1 -c -n | "${testSubject}" -q -B 1 | sleep 1
|
||||
EOF
|
||||
then
|
||||
echo "PV did not finish after the input producer failed and the output reader exited"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -17,11 +17,11 @@ dd if=/dev/zero bs=100 count=1 2>/dev/null \
|
||||
lineCount=$(wc -l < "${workFile1}" | tr -dc '0-9')
|
||||
finalLine=$(sed -n '$p' < "${workFile1}")
|
||||
|
||||
# The number of output lines should be >8 and <13, and the final percentage
|
||||
# The number of output lines should be >6 and <13, and the final percentage
|
||||
# should be 50.
|
||||
#
|
||||
if ! test "${lineCount}" -gt 8; then
|
||||
echo "part 1: fewer than 9 output lines (${lineCount})"
|
||||
if ! test "${lineCount}" -gt 6; then
|
||||
echo "part 1: fewer than 7 output lines (${lineCount})"
|
||||
exit 1
|
||||
fi
|
||||
if ! test "${lineCount}" -lt 13; then
|
||||
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Similar to the "--size" check but, instead, using directory's size with
|
||||
# "--size @".
|
||||
|
||||
# Allow all tests to be skipped, e.g. during a release build
|
||||
test "${SKIP_ALL_TESTS}" = "1" && exit 77
|
||||
|
||||
true "${testSubject:?not set - call this from 'make check'}"
|
||||
true "${workFile1:?not set - call this from 'make check'}"
|
||||
true "${workFile2:?not set - call this from 'make check'}"
|
||||
|
||||
# Process 100 bytes at 100 bytes per second, interval 0.1 seconds, with the
|
||||
# size set from a directory containing 10 files of $1/10 bytes, and
|
||||
# expecting a percentage of $2 at the end.
|
||||
sizeCheck () {
|
||||
# Make a directory containing 10 files of $1/10 bytes each.
|
||||
rm -rf "${workFile2}"
|
||||
mkdir "${workFile2}"
|
||||
mkdir "${workFile2}/subdir"
|
||||
s="$1"
|
||||
s=$((s/10))
|
||||
for f in 1 2 3 4 5; do
|
||||
dd if=/dev/zero bs="$s" count=1 2>/dev/null >"${workFile2}/$f"
|
||||
dd if=/dev/zero bs="$s" count=1 2>/dev/null >"${workFile2}/subdir/$f"
|
||||
done
|
||||
|
||||
# Run 100 bytes through the program, using the reference directory's
|
||||
# total size as the percentage reference.
|
||||
dd if=/dev/zero bs=100 count=1 2>/dev/null \
|
||||
| "${testSubject}" -s "@${workFile2}" -n -i 0.1 -L 100 >/dev/null 2>"${workFile1}"
|
||||
|
||||
# If "-s @<directory>" is unsupported, skip the test.
|
||||
if test $? -eq 64; then
|
||||
rm -rf "${workFile2}"
|
||||
echo 'not available on this build'
|
||||
exit 77
|
||||
fi
|
||||
|
||||
rm -rf "${workFile2}"
|
||||
|
||||
lineCount=$(wc -l < "${workFile1}" | tr -dc '0-9')
|
||||
finalLine=$(sed -n '$p' < "${workFile1}")
|
||||
|
||||
# The number of output lines should be >5 and <13, and the final
|
||||
# percentage should be $2.
|
||||
#
|
||||
if ! test "${lineCount}" -gt 5; then
|
||||
echo "(reference size=$1) fewer than 6 output lines (${lineCount})"
|
||||
exit 1
|
||||
fi
|
||||
if ! test "${lineCount}" -lt 13; then
|
||||
echo "(reference size=$1) more than 12 output lines (${lineCount})"
|
||||
exit 1
|
||||
fi
|
||||
if ! test "${finalLine}" = "$2"; then
|
||||
echo "(reference size=$1): final percentage was not $2 (${finalLine})"
|
||||
cat "${workFile1}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
sizeCheck 100 100
|
||||
sizeCheck 200 50
|
||||
sizeCheck 50 200
|
||||
|
||||
exit 0
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check that monitoring of a simple command works.
|
||||
|
||||
# Allow all tests to be skipped, e.g. during a release build
|
||||
test "${SKIP_ALL_TESTS}" = "1" && exit 77
|
||||
|
||||
true "${testSubject:?not set - call this from 'make check'}"
|
||||
true "${workFile1:?not set - call this from 'make check'}"
|
||||
|
||||
seq 1 100 | "${testSubject}" -M in -f -l -b -- awk 'FNR%2==0{print}' >/dev/null 2>"${workFile1}"
|
||||
|
||||
counterValue=$(tr '\r' '\n' < "${workFile1}" | awk '/[0-9]/{print int($1)}' | sed -n '$p')
|
||||
if ! test "${counterValue}" = "100"; then
|
||||
echo "in monitor: unexpected byte counter value: ${counterValue}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
seq 1 100 | "${testSubject}" -M out -f -l -b -- awk 'FNR%2==0{print}' >/dev/null 2>"${workFile1}"
|
||||
|
||||
counterValue=$(tr '\r' '\n' < "${workFile1}" | awk '/[0-9]/{print int($1)}' | sed -n '$p')
|
||||
if ! test "${counterValue}" = "50"; then
|
||||
echo "out monitor: unexpected byte counter value: ${counterValue}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user