Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
864895f8f2 | ||
|
|
5d185398ac | ||
|
|
94b8b8625f | ||
|
|
282823f660 | ||
|
|
a5fd8d662e | ||
|
|
2904eacefe | ||
|
|
5d538da63a | ||
|
|
fdfceb79c6 | ||
|
|
5aff62414a | ||
|
|
c7a6f85dd2 | ||
|
|
22e9e00f63 | ||
|
|
60ca91209a | ||
|
|
8c440b5417 | ||
|
|
07e6255e7e | ||
|
|
82283ee434 | ||
|
|
42cf7ed628 | ||
|
|
b1cac9b78d | ||
|
|
528889888c | ||
|
|
e6e6ab3b6d | ||
|
|
d2d3ec1cde | ||
|
|
f518257bc9 | ||
|
|
96a411671c | ||
|
|
f07a7b1c87 | ||
|
|
7598b4d46c | ||
|
|
15ed99eee7 | ||
|
|
4df6fbf6f7 | ||
|
|
f125f41428 | ||
|
|
2e9fc77ccd | ||
|
|
590a3535d8 | ||
|
|
b34bba8b4a | ||
|
|
4f82525c39 | ||
|
|
a2191ff270 | ||
|
|
8361ed1fe2 | ||
|
|
9bd96614b3 | ||
|
|
d27672b7a3 | ||
|
|
36d82e313a | ||
|
|
8b3b61e2d3 | ||
|
|
60067ed4ea | ||
|
|
de71cc2389 | ||
|
|
3f1782a573 | ||
|
|
fc379727cc | ||
|
|
0b687edfbe | ||
|
|
546074853e | ||
|
|
7deef78ea5 | ||
|
|
a38e05e749 | ||
|
|
493634e26c | ||
|
|
f96a43e366 | ||
|
|
b434c858a2 | ||
|
|
30e30f0196 | ||
|
|
1a70cc228a | ||
|
|
17ca4fc9c9 | ||
|
|
0aac6d6aac | ||
|
|
61021eab6b | ||
|
|
e59452d765 | ||
|
|
d2647ac55c | ||
|
|
c2c58762f0 | ||
|
|
0a55710cfc | ||
|
|
660d3da704 | ||
|
|
972f8b7df8 | ||
|
|
a40bdfb55f | ||
|
|
3c9ab822fe | ||
|
|
fb5ce33518 | ||
|
|
5c15337662 | ||
|
|
71f929e29c | ||
|
|
c21ad6fdf1 | ||
|
|
f0895177e7 | ||
|
|
72686655cf | ||
|
|
2efe598855 | ||
|
|
54913fddbe | ||
|
|
023cf22a59 | ||
|
|
164d7f7738 | ||
|
|
6b8acd9e01 |
+3
-2
@@ -8,14 +8,13 @@ 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.sh docs/test-on-vm-lab.sh docs/build-package.sh docs/release.sh
|
||||
EXTRA_DIST = docs/pv.1.md docs/benchmark.sh docs/release.cf
|
||||
|
||||
pv_SOURCES = \
|
||||
src/main/debug.c \
|
||||
src/main/help.c \
|
||||
src/main/main.c \
|
||||
src/main/options.c \
|
||||
src/main/remote.c \
|
||||
src/main/version.c \
|
||||
src/pv/calc.c \
|
||||
src/pv/cursor.c \
|
||||
@@ -38,6 +37,7 @@ src/pv/format/timer.c \
|
||||
src/pv/loop.c \
|
||||
src/pv/number.c \
|
||||
src/pv/proctitle.c \
|
||||
src/pv/remote.c \
|
||||
src/pv/signal.c \
|
||||
src/pv/state.c \
|
||||
src/pv/string.c \
|
||||
@@ -95,6 +95,7 @@ tests/Modifiers_-_--line-mode.test \
|
||||
tests/Modifiers_-_--size_from_file_size.test \
|
||||
tests/Modifiers_-_--size.test \
|
||||
tests/Modifiers_-_--sync.test \
|
||||
tests/Sparse_-_Basic.test \
|
||||
tests/Terminal_-_Detect_width.test \
|
||||
tests/Transfer_-_--rate-limit.test \
|
||||
tests/Transfer_-_--remote.test \
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
# Introduction
|
||||
|
||||
This is the README for **pv** ("Pipe Viewer"), a terminal-based tool for
|
||||
monitoring the progress of data through a pipeline. 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.
|
||||
**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.
|
||||
|
||||
In "**\--watchfd**" mode, **pv** will inspect another process and show its
|
||||
progress through the files it has open.
|
||||
|
||||
|
||||
# Documentation
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ dnl Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
dnl
|
||||
dnl License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
|
||||
AC_INIT([pv], [1.9.42], [https://codeberg.org/ivarch/pv/issues], [pv], [https://ivarch.com/p/pv])
|
||||
AC_INIT([pv], [1.10.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])
|
||||
|
||||
@@ -108,6 +108,8 @@ is acknowledged and greatly appreciated:
|
||||
* [Alexander Petrossian](https://github.com/neopaf) - suggested using Unicode output for a more granular progress bar, and provided the codepoints to use ([#15](https://codeberg.org/ivarch/pv/issues/15))
|
||||
* [jmealo](https://codeberg.org/jmealo) - suggested JSON progress output ([#127](https://codeberg.org/ivarch/pv/issues/127))
|
||||
* [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))
|
||||
|
||||
Translations provided through [Codeberg Weblate](https://translate.codeberg.org/projects/pv/):
|
||||
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
### 1.10.0 - 7 November 2025
|
||||
|
||||
* *feature:* new **--query** option to show the transfer status of another running **pv** ([#101](https://codeberg.org/ivarch/pv/issues/101))
|
||||
* *fix:* make the timers work consistently in **--watchfd** if paused and resumed ([#169](https://codeberg.org/ivarch/pv/issues/169))
|
||||
|
||||
### 1.9.44 - 18 October 2025
|
||||
|
||||
* *feature:* new **--sparse** option to write sparse output ([#45](https://codeberg.org/ivarch/pv/issues/45))
|
||||
* *fix:* don't clear the **--watchfd** display when the watched process ends ([#81](https://codeberg.org/ivarch/pv/issues/81))
|
||||
|
||||
### 1.9.42 - 11 October 2025
|
||||
|
||||
* *feature:* permit multiple arguments to **--watchfd** ([#12](https://codeberg.org/ivarch/pv/issues/12))
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Usage: sh build-package.sh source-1.2.3.tar.gz
|
||||
#
|
||||
# Given a tar.gz, build a package for the current OS.
|
||||
#
|
||||
# Supports these packaging types:
|
||||
#
|
||||
# .deb (Debian, Ubuntu, etc) - requires dpkg-dev, debhelper
|
||||
# .rpm (AlmaLinux, Rocky Linux, OpenSUSE etc) - requires rpmbuild
|
||||
#
|
||||
# If the MAINTAINER environment variable is set, this is used as a GPG key
|
||||
# ID for package signing.
|
||||
#
|
||||
# The packages built with this script are not "official", in that they are
|
||||
# not part of any Linux distribution and may not follow the distribution's
|
||||
# policies. Use at your own risk.
|
||||
#
|
||||
# Copyright 2024-2025 Andrew Wood
|
||||
# License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
|
||||
sourceArchive="$1"
|
||||
test -n "${sourceArchive}" && test -f "${sourceArchive}" \
|
||||
|| { printf "%s: %s: %s\n" "${0##*/}" "${sourceArchive}" "source archive not found" 1>&2; exit 1; }
|
||||
|
||||
packageName="pv"
|
||||
packageSummary="Shell pipeline element to meter data passing through"
|
||||
packageDescription="\
|
||||
pv (Pipe Viewer) 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."
|
||||
packageUrl="https://ivarch.com/p/pv"
|
||||
sourceUrl="https://ivarch.com/programs/sources/${packageName}-%{version}.tar.gz"
|
||||
packageEmail="Andrew Wood <pv@ivarch.com>"
|
||||
|
||||
workDir="$(mktemp -d)" || exit 1
|
||||
trap 'rm -rf "${workDir}"' EXIT
|
||||
|
||||
# Infer the version from the most recent NEWS entry.
|
||||
version="$(tar xzf "${sourceArchive}" --wildcards -O '*/docs/NEWS.md' 2>/dev/null | awk '/^### [0-9]/{print $2}' | sed -n 1p)"
|
||||
|
||||
if command -v rpmbuild >/dev/null 2>&1; then
|
||||
# Build an RPM.
|
||||
cat > "${workDir}"/spec <<EOF
|
||||
Summary: ${packageSummary}
|
||||
Name: ${packageName}
|
||||
Version: ${version}
|
||||
Release: 1%{?dist}
|
||||
License: GPLv3+
|
||||
Source: ${sourceUrl}
|
||||
Url: ${packageUrl}
|
||||
|
||||
%description
|
||||
${packageDescription}
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
%configure
|
||||
make %{?_smp_mflags}
|
||||
|
||||
%install
|
||||
test -n "\${RPM_BUILD_ROOT}" && test "\${RPM_BUILD_ROOT}" != '/' && rm -rf "\${RPM_BUILD_ROOT}"
|
||||
make install DESTDIR="\${RPM_BUILD_ROOT}"
|
||||
rm -rf "\${RPM_BUILD_ROOT}/usr/share/doc"
|
||||
%find_lang %{name}
|
||||
|
||||
%check
|
||||
make check SKIP_VALGRIND_TESTS=1
|
||||
|
||||
%clean
|
||||
test -n "\${RPM_BUILD_ROOT}" && test "\${RPM_BUILD_ROOT}" != '/' && rm -rf "\${RPM_BUILD_ROOT}"
|
||||
|
||||
%files -f %{name}.lang
|
||||
%defattr(-, root, root)
|
||||
%{_bindir}/*
|
||||
%{_mandir}/man1/*
|
||||
|
||||
%doc README.md docs/NEWS.md docs/ACKNOWLEDGEMENTS.md docs/COPYING
|
||||
|
||||
%changelog
|
||||
* $(date '+%a %b %d %Y') ${packageEmail} - ${version}-1
|
||||
- Package built from main source.
|
||||
EOF
|
||||
mkdir "${workDir}/SOURCES"
|
||||
cp "${sourceArchive}" "${workDir}/SOURCES/${packageName}-${version}.tar.gz"
|
||||
rpmbuild -D "%_topdir ${workDir}" -bb "${workDir}/spec" || exit 1
|
||||
if test -n "${MAINTAINER}"; then
|
||||
# Sign the RPMs.
|
||||
rpm -D "%_gpg_name ${MAINTAINER}" --addsign "${workDir}/RPMS"/*/*.rpm || exit 1
|
||||
fi
|
||||
cp -v "${workDir}/RPMS"/*/*.rpm .
|
||||
fi
|
||||
|
||||
if command -v dpkg-buildpackage >/dev/null 2>&1; then
|
||||
# Build a Debian package.
|
||||
mkdir "${workDir}/build" "${workDir}/build/debian" "${workDir}/build/debian/source"
|
||||
|
||||
tar xzf "${sourceArchive}" -C "${workDir}/build" --strip-components=1
|
||||
|
||||
printf "%s\n" "10" > "${workDir}/build/debian/compat"
|
||||
touch "${workDir}/build/debian/copyright"
|
||||
printf "%s\n" "3.0 (quilt)" > "${workDir}/build/debian/source/format"
|
||||
|
||||
cat > "${workDir}/build/debian/rules" <<EOF
|
||||
#!/usr/bin/make -f
|
||||
export DH_VERBOSE = 1
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
|
||||
export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
|
||||
|
||||
%:
|
||||
dh \$@
|
||||
EOF
|
||||
chmod 700 "${workDir}/build/debian/rules"
|
||||
|
||||
cat > "${workDir}/build/debian/control" <<EOF
|
||||
Source: ${packageName}
|
||||
Maintainer: ${packageEmail}
|
||||
Section: misc
|
||||
Priority: optional
|
||||
Standards-Version: 3.9.2
|
||||
Build-Depends: debhelper (>= 9)
|
||||
|
||||
Package: ${packageName}
|
||||
Architecture: any
|
||||
Depends: \${misc:Depends}
|
||||
Description: ${packageSummary}
|
||||
$(printf "%s\n.\n" "${packageDescription}" | sed 's,^, ,')
|
||||
EOF
|
||||
|
||||
cat > "${workDir}/build/debian/changelog" <<EOF
|
||||
${packageName} (${version}-1) UNRELEASED; urgency=low
|
||||
|
||||
* Package built from main source.
|
||||
|
||||
-- ${packageEmail} $(date -R)
|
||||
EOF
|
||||
|
||||
if test -n "${MAINTAINER}"; then
|
||||
(cd "${workDir}/build" && dpkg-buildpackage --build=binary --force-sign --sign-key="${MAINTAINER}") || exit 1
|
||||
else
|
||||
(cd "${workDir}/build" && dpkg-buildpackage --build=binary) || exit 1
|
||||
fi
|
||||
|
||||
cp -v "${workDir}"/*.deb . || exit 1
|
||||
fi
|
||||
@@ -1,7 +1,7 @@
|
||||
.TH PV 1 2025-10-11 pv-1.9.42 "User Commands"
|
||||
.TH PV 1 2025-11-07 pv-1.10.0 "User Commands"
|
||||
.\"
|
||||
.SH NAME
|
||||
pv \- monitor the progress of data through a pipe
|
||||
pv \- monitor and manage the progress of data through a pipe
|
||||
.\"
|
||||
.SH SYNOPSIS
|
||||
.B pv
|
||||
@@ -11,16 +11,22 @@ pv \- monitor the progress of data through a pipe
|
||||
\fIPID\fR[:\fIFD\fR]|=\fINAME\fR|@\fILISTFILE\fR...
|
||||
.PP
|
||||
\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]...
|
||||
.\"
|
||||
.SH DESCRIPTION
|
||||
Show the progress of data through a pipeline by giving information such as
|
||||
time elapsed, percentage completed (with progress bar), current throughput
|
||||
rate, total data transferred, and ETA.
|
||||
The data flow rate, error handling strategy, buffer size, and cache
|
||||
interaction can all be adjusted.
|
||||
.PP
|
||||
Each \fIFILE\fR is copied to standard output.
|
||||
With no \fIFILE\fR, or when \fIFILE\fR is \*(lq-\*(rq, standard input is
|
||||
read.
|
||||
This is the same behaviour as \fBcat\fR(1).
|
||||
.PP
|
||||
In \*(lq\fB\-\-watchfd\fR\*(rq mode, inspect another process and show its
|
||||
progress through the files it has open.
|
||||
.\"
|
||||
.SH OPTIONS
|
||||
.\"
|
||||
@@ -273,9 +279,9 @@ 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\-\-discard\fR\*(rq, and makes \*(lq\fB\-\-buffer\-size\fR\*(rq
|
||||
redundant, so using any of those options automatically switches on
|
||||
\*(lq\fB\-\-no\-splice\fR\*(rq.
|
||||
\*(lq\fB\-\-sparse\fR\*(rq or \*(lq\fB\-\-discard\fR\*(rq, 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.
|
||||
.TP
|
||||
@@ -325,6 +331,13 @@ failures with an error of \*(lqInvalid argument\*(rq, especially if reading
|
||||
and writing files across a variety of filesystems in a single \fBpv\fR call.
|
||||
Use this option with caution.
|
||||
.TP
|
||||
.B \-O, \-\-sparse
|
||||
When writing null bytes, try to seek, producing a sparse output file.
|
||||
Implies \*(lq\fB\-\-no\-splice\fR\*(rq.
|
||||
On filesystems without sparse file support, or when the output is not
|
||||
seekable, this option will have no effect other than to turn on
|
||||
\*(lq\fB\-\-no\-splice\fR\*(rq.
|
||||
.TP
|
||||
.B \-X, \-\-discard
|
||||
Instead of transferring input data to standard output, discard it.
|
||||
This is equivalent to redirecting standard output to \fI/dev/null\fR,
|
||||
@@ -384,6 +397,17 @@ Note that some options cannot be changed while running, such as
|
||||
\*(lq\fB\-\-cursor\fR\*(rq, \*(lq\fB\-\-line\-mode\fR\*(rq,
|
||||
\*(lq\fB\-\-force\fR\*(rq, \*(lq\fB\-\-delay\-start\fR\*(rq,
|
||||
\*(lq\fB\-\-skip\-errors\fR\*(rq, and \*(lq\fB\-\-stop\-at\-size\fR\*(rq.
|
||||
.TP
|
||||
.BI \-Q\ PID \fR,\ \fB\-\-query\ PID
|
||||
Display the transfer progress of another instance of \fBpv\fR with process
|
||||
ID \fIPID\fR, owned by the same user.
|
||||
.IP
|
||||
Some output modifiers can only be used while querying another process if
|
||||
they match those of that process - such as
|
||||
\*(lq\fB\-\-line\-mode\fR\*(rq,
|
||||
\*(lq\fB\-\-null\fR\*(rq, and
|
||||
\*(lq\fB\-\-average\-rate\-window\fR\*(rq.
|
||||
Data transfer modifiers will have no effect.
|
||||
.\"
|
||||
.SS "Other options"
|
||||
.TP
|
||||
@@ -684,8 +708,8 @@ pv \-\-numeric \-\-format '{"elapsed":%t,"bytes":%b,"rate":%r,"percentage":%{pro
|
||||
.in
|
||||
.\"
|
||||
.SH EXIT STATUS
|
||||
An exit status of 1 indicates a problem with the \*(lq\fB\-\-remote\fR\*(rq
|
||||
or \*(lq\fB\-\-pidfile\fR\*(rq options.
|
||||
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.
|
||||
.PP
|
||||
Any other exit status is a bitmask of the following:
|
||||
.TP 5
|
||||
@@ -714,10 +738,10 @@ The following environment variables may affect \fBpv\fR:
|
||||
.TP
|
||||
.B HOME
|
||||
The current user's home directory.
|
||||
This may be used by \*(lq\fB\-\-remote\fR\*(rq to exchange messages between
|
||||
\fBpv\fR instances: if the \fI/run/user/UID/\fR directory does not exist
|
||||
(where \fIUID\fR is the current user ID), then \fI$HOME/.pv/\fR will be used
|
||||
instead.
|
||||
This may be used by \*(lq\fB\-\-remote\fR\*(rq and \*(lq\fB\-\-query\fR\*(rq
|
||||
to exchange messages between \fBpv\fR instances: if the \fI/run/user/UID/\fR
|
||||
directory does not exist (where \fIUID\fR is the current user ID), then
|
||||
\fI$HOME/.pv/\fR will be used instead.
|
||||
.TP
|
||||
.BR TMPDIR ", " TMP
|
||||
The directory to create per-tty lock files for the terminal when using
|
||||
@@ -761,9 +785,9 @@ issue #105
|
||||
.UE
|
||||
for full details.
|
||||
.PP
|
||||
The \*(lq\fB\-\-remote\fR\*(rq option requires that either
|
||||
\fI/run/user/<uid>/\fR or \fI$HOME/\fR can be written to, for inter-process
|
||||
communication.
|
||||
The \*(lq\fB\-\-remote\fR\*(rq and \*(lq\fB\-\-query\fR\*(rq options require
|
||||
that either \fI/run/user/<uid>/\fR or \fI$HOME/\fR can be written to, for
|
||||
inter-process communication.
|
||||
.PP
|
||||
The \*(lq\fB\-\-size\fR\*(rq option has no effect if used with
|
||||
\*(lq\fB\-\-watchfd\fR\~\fIPID\fR\*(rq to watch all file descriptors of a
|
||||
@@ -791,8 +815,15 @@ have a suffix.
|
||||
.PP
|
||||
Numbers passed to \*(lq\fB\-\-last\-written\fR\*(rq,
|
||||
\*(lq\fB\-\-width\fR\*(rq, \*(lq\fB\-\-height\fR\*(rq,
|
||||
\*(lq\fB\-\-average\-rate\-window\fR\*(rq, and \*(lq\fB\-\-remote\fR\*(rq
|
||||
must be integers with no suffix.
|
||||
\*(lq\fB\-\-average\-rate\-window\fR\*(rq, \*(lq\fB\-\-remote\fR\*(rq, and
|
||||
\*(lq\fB\-\-query\fR\*(rq must be integers with no suffix.
|
||||
.PP
|
||||
When \*(lq\fB\-\-sparse\fR\*(rq is in effect and output is being written to
|
||||
a file, that file may look like it has stopped growing if inspected with
|
||||
\fBls\fR(1) while null bytes are being written, even though \fBpv\fR still
|
||||
reports progress.
|
||||
This is because of the way sparse output is achieved, and the file will be
|
||||
the correct size when the transfer ends.
|
||||
.\"
|
||||
.SH REPORTING BUGS
|
||||
Please report bugs or feature requests via the issue tracker linked from the
|
||||
|
||||
+49
-18
@@ -1,6 +1,6 @@
|
||||
# NAME
|
||||
|
||||
pv - monitor the progress of data through a pipe
|
||||
pv - monitor and manage the progress of data through a pipe
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
@@ -11,15 +11,21 @@ pv - monitor the progress of data through a pipe
|
||||
|
||||
**pv** **-R**\|**\--remote** *PID* \[*OPTION*\]\...
|
||||
|
||||
**pv** **-Q**\|**\--query** *PID* \[*OPTION*\]\...
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
Show the progress of data through a pipeline by giving information such
|
||||
as time elapsed, percentage completed (with progress bar), current
|
||||
throughput rate, total data transferred, and ETA.
|
||||
throughput rate, total data transferred, and ETA. The data flow rate,
|
||||
error handling strategy, buffer size, and cache interaction can all be
|
||||
adjusted.
|
||||
|
||||
Each *FILE* is copied to standard output. With no *FILE*, or when *FILE*
|
||||
is "-", standard input is read. This is the same behaviour as
|
||||
**cat**(1).
|
||||
is "-", standard input is read.
|
||||
|
||||
In "**\--watchfd**" mode, inspect another process and show its progress
|
||||
through the files it has open.
|
||||
|
||||
# OPTIONS
|
||||
|
||||
@@ -281,11 +287,11 @@ are explicitly switched on will be shown.
|
||||
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 "**\--discard**", 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.
|
||||
cannot work with "**\--sparse**" or "**\--discard**", 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.
|
||||
|
||||
**-E, \--skip-errors**
|
||||
|
||||
@@ -336,6 +342,13 @@ are explicitly switched on will be shown.
|
||||
especially if reading and writing files across a variety of
|
||||
filesystems in a single **pv** call. Use this option with caution.
|
||||
|
||||
**-O, \--sparse**
|
||||
|
||||
: When writing null bytes, try to seek, producing a sparse output
|
||||
file. Implies "**\--no-splice**". On filesystems without sparse file
|
||||
support, or when the output is not seekable, this option will have
|
||||
no effect other than to turn on "**\--no-splice**".
|
||||
|
||||
**-X, \--discard**
|
||||
|
||||
: Instead of transferring input data to standard output, discard it.
|
||||
@@ -399,6 +412,16 @@ are explicitly switched on will be shown.
|
||||
"**\--delay-start**", "**\--skip-errors**", and
|
||||
"**\--stop-at-size**".
|
||||
|
||||
**-Q PID, \--query PID**
|
||||
|
||||
: Display the transfer progress of another instance of **pv** with
|
||||
process ID *PID*, owned by the same user.
|
||||
|
||||
Some output modifiers can only be used while querying another
|
||||
process if they match those of that process - such as
|
||||
"**\--line-mode**", "**\--null**", and "**\--average-rate-window**".
|
||||
Data transfer modifiers will have no effect.
|
||||
|
||||
## Other options
|
||||
|
||||
**-P FILE, \--pidfile FILE**
|
||||
@@ -652,8 +675,8 @@ Showing progress as lines of JSON data:
|
||||
|
||||
# EXIT STATUS
|
||||
|
||||
An exit status of 1 indicates a problem with the "**\--remote**" or
|
||||
"**\--pidfile**" options.
|
||||
An exit status of 1 indicates a problem with the "**\--remote**",
|
||||
"**\--query**", or "**\--pidfile**" options.
|
||||
|
||||
Any other exit status is a bitmask of the following:
|
||||
|
||||
@@ -691,9 +714,10 @@ The following environment variables may affect **pv**:
|
||||
**HOME**
|
||||
|
||||
: The current user\'s home directory. This may be used by
|
||||
"**\--remote**" to exchange messages between **pv** instances: if
|
||||
the */run/user/UID/* directory does not exist (where *UID* is the
|
||||
current user ID), then *\$HOME/.pv/* will be used instead.
|
||||
"**\--remote**" and "**\--query**" to exchange messages between
|
||||
**pv** instances: if the */run/user/UID/* directory does not exist
|
||||
(where *UID* is the current user ID), then *\$HOME/.pv/* will be
|
||||
used instead.
|
||||
|
||||
**TMPDIR**, **TMP**
|
||||
|
||||
@@ -725,8 +749,9 @@ brackets to force the use of a subshell:
|
||||
Refer to [issue #105](https://codeberg.org/ivarch/pv/issues/105) for
|
||||
full details.
|
||||
|
||||
The "**\--remote**" option requires that either */run/user/\<uid\>/* or
|
||||
*\$HOME/* can be written to, for inter-process communication.
|
||||
The "**\--remote**" and "**\--query**" options require that either
|
||||
*/run/user/\<uid\>/* or *\$HOME/* can be written to, for inter-process
|
||||
communication.
|
||||
|
||||
The "**\--size**" option has no effect if used with
|
||||
"**\--watchfd** *PID*" to watch all file descriptors of a process, but
|
||||
@@ -750,8 +775,14 @@ Numbers passed to "**\--interval**" and "**\--delay-start**" may be
|
||||
integers or decimals, but may not have a suffix.
|
||||
|
||||
Numbers passed to "**\--last-written**", "**\--width**",
|
||||
"**\--height**", "**\--average-rate-window**", and "**\--remote**" must
|
||||
be integers with no suffix.
|
||||
"**\--height**", "**\--average-rate-window**", "**\--remote**", and
|
||||
"**\--query**" must be integers with no suffix.
|
||||
|
||||
When "**\--sparse**" is in effect and output is being written to a file,
|
||||
that file may look like it has stopped growing if inspected with
|
||||
**ls**(1) while null bytes are being written, even though **pv** still
|
||||
reports progress. This is because of the way sparse output is achieved,
|
||||
and the file will be the correct size when the transfer ends.
|
||||
|
||||
# REPORTING BUGS
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# Configuration for the foss-release.sh script.
|
||||
# The script is here: https://codeberg.org/ivarch/scripts
|
||||
|
||||
set maintainer andrew.wood@ivarch.com
|
||||
set mainprogram auto
|
||||
set version auto
|
||||
set mandir docs
|
||||
set newsdir docs
|
||||
|
||||
export SKIP_VALGRIND_TESTS=1
|
||||
|
||||
section Initial checks
|
||||
action check_po
|
||||
action check_version_news
|
||||
action check_version_autoconf
|
||||
action check_version_man
|
||||
|
||||
section Initial build
|
||||
action configure
|
||||
action make
|
||||
action check_analyse
|
||||
action check_version_program
|
||||
action check_version_year
|
||||
|
||||
section Documentation and source reformatting
|
||||
action man_md
|
||||
action man_html
|
||||
action news_html
|
||||
action make_indent
|
||||
|
||||
section Update po files
|
||||
action make_update_po
|
||||
|
||||
section Run autoreconf
|
||||
action autoreconf
|
||||
|
||||
section Commit check
|
||||
action check_git_status
|
||||
|
||||
section Release archive
|
||||
action check_make_distcheck
|
||||
action make_dist
|
||||
|
||||
section Lab tests
|
||||
action labtest
|
||||
|
||||
section Sign release
|
||||
action sign_tarball
|
||||
|
||||
section Build OS packages
|
||||
action parmo_build
|
||||
-217
@@ -1,217 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Automate a portion of the release checklist. Expects to be run from a
|
||||
# build directory, such as one in which "configure" has been run, i.e.
|
||||
# there should be a Makefile present.
|
||||
#
|
||||
# Requires "parmo" (https://ivarch.com/p/parmo); builds for all targets that
|
||||
# parmo supports.
|
||||
#
|
||||
# All of the release artefacts are placed in a "PV-RELEASE-x" directory,
|
||||
# where "x" is the version.
|
||||
#
|
||||
# Copyright 2024-2025 Andrew Wood
|
||||
# License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
|
||||
srcdir="$(awk '/^VPATH/{print $NF}' < Makefile | sed -n 1p)"
|
||||
manuals="$(find "${srcdir}/docs" -mindepth 1 -maxdepth 1 -type f -name "*.[0-9]" -printf "%f\n")"
|
||||
mainProgram="$(awk '/^[a-z]+_PROGRAMS/{print $3}' Makefile |cut -d '$' -f 1 | sed -n 1p)"
|
||||
labTestScript="${srcdir}/docs/test-on-vm-lab.sh"
|
||||
|
||||
status () {
|
||||
test -n "$*" && printf "\n"
|
||||
printf '\e]0;%s\007\r' "$*" >&2
|
||||
if test -n "$*"; then
|
||||
tput rev >&2
|
||||
printf " -- %s -- " "$*" >&2
|
||||
tput sgr0 >&2
|
||||
printf "\n\n"
|
||||
fi
|
||||
}
|
||||
|
||||
possiblyDie () {
|
||||
printf "\n" >&2
|
||||
tput bold >&2
|
||||
printf "%s: %s\n" "release" "$*" >&2
|
||||
tput sgr0 >&2
|
||||
printf "\n%s\n" "Type 'y' and hit Enter to continue anyway."
|
||||
read -r line
|
||||
test "${line}" = "y" || { status ""; exit 1; }
|
||||
}
|
||||
|
||||
test -e "${labTestScript}" || labTestScript=""
|
||||
|
||||
# The checklist is re-ordered a little so that we defer making changes (like
|
||||
# "make indent") until as late as possible, in case any checks fail.
|
||||
|
||||
status "Initial checks"
|
||||
|
||||
# Check MAINTAINER is provided.
|
||||
test -n "${MAINTAINER}" || possiblyDie "environment variable MAINTAINER is empty"
|
||||
|
||||
# * Check that _po/POTFILES.in_ is up to date
|
||||
if test -d "${srcdir}/po"; then
|
||||
inFile="$(sort < "${srcdir}/po/POTFILES.in")"
|
||||
realList="$(find "${srcdir}" -name "*.c" -printf "%P\n" | sort)"
|
||||
test "${inFile}" = "${realList}" || possiblyDie "po/POTFILES.in is incorrect"
|
||||
fi
|
||||
|
||||
status "Initial build"
|
||||
make || possiblyDie "failed 'make'"
|
||||
|
||||
# * Run "_make analyse_" and see whether remaining warnings can be addressed
|
||||
status "Source analysis"
|
||||
make analyse || possiblyDie "failed 'make analyse'"
|
||||
|
||||
# * Version bump and documentation checks:
|
||||
|
||||
status "Version checks"
|
||||
|
||||
# * Check that _docs/NEWS.md_ is up to date
|
||||
sed -n 1p docs/NEWS.md | grep -Fqi unreleased && possiblyDie "NEWS.md says 'unreleased' on line 1"
|
||||
versionInNews="$(awk 'FNR==1{print $2}' "${srcdir}/docs/NEWS.md")"
|
||||
printf "%s\n" "${versionInNews}" | grep -Eq '^[0-9]' || possiblyDie "version in NEWS.md (${versionInNews}) is not numeric"
|
||||
|
||||
# * Check the version in both _configure.ac_ and _docs/NEWS.md_ was updated
|
||||
versionInConfig="$(grep ^AC_INIT "${srcdir}/configure.ac" | cut -d '[' -f 3 | cut -d ']' -f 1)"
|
||||
test "${versionInConfig}" = "${versionInNews}" || possiblyDie "version in configure.ac (${versionInConfig}) mismatches NEWS.md (${versionInNews})"
|
||||
|
||||
# * Check that the manuals are up to date
|
||||
for manPage in ${manuals}; do
|
||||
versionInManual="$(awk 'FNR==1 {print $5}' "${srcdir}/docs/${manPage}" | cut -d - -f 2)"
|
||||
test "${versionInManual}" = "${versionInNews}" || possiblyDie "version in ${manPage} (${versionInManual}) mismatches NEWS.md (${versionInNews})"
|
||||
done
|
||||
|
||||
# * Check that the program version is correct
|
||||
versionInVersionOutput="$(./"${mainProgram}" --version | awk 'FNR==1{print $NF}')"
|
||||
test "${versionInVersionOutput}" = "${versionInNews}" || possiblyDie "version in '${mainProgram} --version' (${versionInVersionOutput}) mismatches NEWS.md (${versionInNews})"
|
||||
|
||||
# * Check that the year displayed by --version is correct
|
||||
yearInVersion="$(./"${mainProgram}" --version | awk '/^Copyright/{print $2}')"
|
||||
yearNow="$(date '+%Y')"
|
||||
test "${yearInVersion}" = "${yearNow}" || possiblyDie "the year in '--version' (${yearInVersion}) is not this year (${yearNow})"
|
||||
|
||||
# * Make the Markdown version of the manuals and, if using VPATH, copy the result to the source directory
|
||||
# We also wipe everything in "docs" so we don't accidentally package
|
||||
# leftover working files.
|
||||
|
||||
status "Markdown manual"
|
||||
|
||||
rm -f docs/*
|
||||
for manPage in ${manuals}; do
|
||||
make "docs/${manPage}.md"
|
||||
cp "docs/${manPage}.md" "${srcdir}/docs/${manPage}.md"
|
||||
done
|
||||
|
||||
# * Run "_make indent; make indent indentclean check_"
|
||||
status "Reformat source"
|
||||
make indent
|
||||
make indent indentclean
|
||||
# The check will run later as part of "make distcheck".
|
||||
|
||||
# * Run "_make -C po update-po_"
|
||||
status "Update po files"
|
||||
if test -d "${srcdir}/po"; then
|
||||
make -C po update-po || possiblyDie "update-po failed"
|
||||
fi
|
||||
|
||||
# * Run "_autoreconf_" in the source directory
|
||||
status "Run autoreconf"
|
||||
(cd "${srcdir}" && autoreconf -is) || possiblyDie "autoreconf failed"
|
||||
|
||||
# * Ensure everything has been committed to the repository
|
||||
status "Commit check"
|
||||
gitStatus="$(cd "${srcdir}" && git status --porcelain=v1)" || possiblyDie "failed to run 'git status'"
|
||||
test -z "${gitStatus}" || possiblyDie "not everything is committed - 'git status' is not empty"
|
||||
|
||||
# * Consistency and build checks:
|
||||
# * Wipe the build directory, and run "_configure_" there
|
||||
# * Run "_make distcheck_"
|
||||
# * Run "_make release MAINTAINER=<signing-user>_"
|
||||
# NB "make release" implies "make distcheck".
|
||||
# We set SKIP_VALGRIND_TESTS=1 because the full tests will run in the lab
|
||||
# check.
|
||||
status "Release archive"
|
||||
workDir="$(mktemp -d)" || possiblyDie "mktemp failed"
|
||||
trap 'chmod -R u+w "${workDir}"; rm -rf "${workDir}"' EXIT
|
||||
(
|
||||
cd "${workDir}" || exit 1
|
||||
sh "${srcdir}/configure" || exit 1
|
||||
make -j8 release SKIP_VALGRIND_TESTS=1 || exit 1
|
||||
exit 0
|
||||
) || possiblyDie "failed on 'make release'"
|
||||
|
||||
sourceArchive="$(find "${workDir}" -mindepth 1 -maxdepth 1 -type f -name "*.tar.gz")"
|
||||
test -e "${sourceArchive}.asc" || possiblyDie "release was not signed"
|
||||
|
||||
# * Run "_./configure && make check_" on all test systems, using the _tar.gz_ that was just created
|
||||
# * Run a cross-compilation check
|
||||
if test -n "${labTestScript}"; then
|
||||
status "Lab test"
|
||||
sh "${labTestScript}" "${sourceArchive}" || possiblyDie "lab test failed"
|
||||
fi
|
||||
|
||||
# * Update the project web site:
|
||||
# * Copy the release _.tar.gz_, _.txt_, and _.asc_ files to the web site
|
||||
# * Use "_pandoc --from markdown --to html_" to convert the news and manual to HTML
|
||||
status "Release dir"
|
||||
releaseDir="PV-RELEASE-${versionInNews}"
|
||||
rm -rf "${releaseDir}"
|
||||
mkdir "${releaseDir}"
|
||||
cp "${sourceArchive}" "${sourceArchive}.asc" "${sourceArchive}.txt" "${releaseDir}/" || possiblyDie "failed to copy release files"
|
||||
|
||||
status "HTML docs"
|
||||
for manPage in ${manuals}; do
|
||||
pandoc --from markdown --to html --shift-heading-level-by=1 < "${srcdir}/docs/${manPage}.md" > "${releaseDir}/${manPage}.html"
|
||||
done
|
||||
pandoc --from markdown --to html < "${srcdir}/docs/NEWS.md" > "${releaseDir}/news.html"
|
||||
|
||||
# Build OS packages.
|
||||
buildTargets=$(parmo targets)
|
||||
if test -n "${MAINTAINER}"; then
|
||||
gpg --export-secret-key --armor "${MAINTAINER}" > "${workDir}/signing-key" \
|
||||
|| possiblyDie 'failed to export signing key'
|
||||
fi
|
||||
for buildTarget in ${buildTargets}; do
|
||||
status "Package: ${buildTarget}"
|
||||
buildOK=true
|
||||
rm -rf "${workDir}/package"
|
||||
mkdir "${workDir}/package"
|
||||
if test -s "${workDir}/signing-key"; then
|
||||
parmo --key "${workDir}/signing-key" --source "${sourceArchive}" --destination "${workDir}/package" --target "${buildTarget}" build-package \
|
||||
|| possiblyDie "${buildTarget}: build failed"
|
||||
else
|
||||
parmo --source "${sourceArchive}" --destination "${workDir}/package" --target "${buildTarget}" build-package \
|
||||
|| possiblyDie "${buildTarget}: build failed"
|
||||
fi
|
||||
find "${workDir}/package" -type f \
|
||||
| while read -r packageFile; do
|
||||
destinationFile="${releaseDir}/${packageFile##*/}"
|
||||
case "${destinationFile}" in
|
||||
*.deb) destinationFile="${destinationFile%.deb}_${buildTarget}.deb" ;;
|
||||
*.txt) destinationFile="" ;;
|
||||
esac
|
||||
test -n "${destinationFile}" || continue
|
||||
cp "${packageFile}" "${destinationFile}"
|
||||
chmod 644 "${destinationFile}"
|
||||
done
|
||||
done
|
||||
|
||||
find "${releaseDir}/" -type f -exec chmod 644 '{}' ';'
|
||||
find "${releaseDir}/" -type d -exec chmod 755 '{}' ';'
|
||||
|
||||
status "Done"
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Files are under: ${releaseDir}/
|
||||
|
||||
Still to do:
|
||||
* Update the news and manual on the web site
|
||||
* Update the version numbers on the web site
|
||||
* Update the package index on the web site
|
||||
* Create a new release in the repository, and apply the associated tag
|
||||
|
||||
EOF
|
||||
|
||||
exit 0
|
||||
@@ -1,343 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Run "make check" from a source tarball, on a whole lab of VMs.
|
||||
#
|
||||
# The source tarball should contain a directory; this directory must contain
|
||||
# a "configure" script. After running "configure", this script calls "make"
|
||||
# and then "make check", from a build subdirectory.
|
||||
#
|
||||
# Hostnames need to be listed on the command line after the tarball, or in
|
||||
# ~/.config/lab-hosts. They need to be reachable over SSH with no password.
|
||||
#
|
||||
# Cross-compilation is performed if the hostname is of the form "x:y", where
|
||||
# "x" is a target like "arm-linux-gnueabi", and "y" is the name of a host of
|
||||
# that architecture. The package is built locally with "--host=x" and the
|
||||
# result is copied to "y" and "make check" is run.
|
||||
#
|
||||
# Displays progress to the terminal and produces a tarball of results. In
|
||||
# the results, the file "latest-status.txt" contains the last status
|
||||
# display, and there is a directory for each host. The directories contain
|
||||
# SCW metrics files plus "output.log" (timestamped), "raw-output.log"
|
||||
# (without timestamps), "framework-output.log" (messages from this script),
|
||||
# and the "config.log", "test-suite.log", and "tests/" from the build area.
|
||||
#
|
||||
# Requires "scw" (https://ivarch.com/p/scw).
|
||||
#
|
||||
# Copyright 2024-2025 Andrew Wood
|
||||
# License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
#
|
||||
# Version: 0.0.1 / 16 Dec 2024
|
||||
|
||||
# Number of tests to run in parallel on each host.
|
||||
concurrency="1"
|
||||
|
||||
# Run a build and check, according to these environment variables:
|
||||
#
|
||||
# sourceArchive local source tarball path
|
||||
# buildHost where to build, or "" for local
|
||||
# checkHost where to test, or "" for local
|
||||
# remoteBuildDir temp directory for remote build or check
|
||||
# localBuildDir temp directory for local build
|
||||
# configureArguments extra "configure" script arguments
|
||||
#
|
||||
# Does not return - always exits.
|
||||
#
|
||||
# Expects to be run under SCW, so writes status to fd 3.
|
||||
#
|
||||
testRunner () {
|
||||
printf '%s %s\n' 'notice' 'creating build area' >&3
|
||||
if test -n "${buildHost}"; then
|
||||
ssh "${buildHost}" mkdir "${remoteBuildDir}" || exit 1
|
||||
else
|
||||
mkdir "${localBuildDir}" || exit 1
|
||||
fi
|
||||
printf '%s %s\n' 'ok' 'created build area' >&3
|
||||
|
||||
if test -n "${checkHost}"; then
|
||||
printf '%s %s\n' 'notice' 'creating check area' >&3
|
||||
ssh "${checkHost}" mkdir "${remoteBuildDir}" || exit 1
|
||||
printf '%s %s\n' 'ok' 'created check area' >&3
|
||||
fi
|
||||
|
||||
printf '%s %s\n' 'notice' 'copying source archive' >&3
|
||||
if test -n "${buildHost}"; then
|
||||
scp "${sourceArchive}" "${buildHost}:${remoteBuildDir}/" || exit 1
|
||||
elif test -n "${checkHost}"; then
|
||||
scp "${sourceArchive}" "${checkHost}:${remoteBuildDir}/" || exit 1
|
||||
fi
|
||||
printf '%s %s\n' 'ok' 'source archive copied' >&3
|
||||
|
||||
printf '%s %s\n' 'notice' 'extracting source archive' >&3
|
||||
if test -n "${buildHost}"; then
|
||||
ssh "${buildHost}" tar xzf "${remoteBuildDir}/${sourceArchive##*/}" -C "${remoteBuildDir}" || exit $?
|
||||
else
|
||||
tar xzf "${sourceArchive}" -C "${localBuildDir}" || exit $?
|
||||
ssh "${checkHost}" tar xzf "${remoteBuildDir}/${sourceArchive##*/}" -C "${remoteBuildDir}" || exit $?
|
||||
fi
|
||||
printf '%s %s\n' 'ok' 'source archive extracted' >&3
|
||||
|
||||
stepResult="ok"
|
||||
if test -n "${buildHost}"; then
|
||||
printf '%s %s\n' 'notice' 'configuring' >&3
|
||||
ssh "${buildHost}" "cd \"${remoteBuildDir}\" && mkdir BUILD && cd BUILD && ../*/configure ${configureArguments}" || exit $?
|
||||
else
|
||||
printf '%s %s\n' 'notice' 'configuring locally' >&3
|
||||
( cd "${localBuildDir}" && mkdir BUILD && cd BUILD && ../*/configure ${configureArguments} ) || exit $?
|
||||
printf '%s %s\n' 'notice' "configuring on ${checkHost}" >&3
|
||||
ssh "${checkHost}" "cd \"${remoteBuildDir}\" && mkdir BUILD && cd BUILD && ../*/configure" \
|
||||
|| { stepResult="warning"; printf '%s %s\n' 'warning' "configuration failed on ${checkHost}" >&3; }
|
||||
fi
|
||||
printf '%s %s\n' "${stepResult}" 'configuration completed' >&3
|
||||
|
||||
printf '%s %s\n' 'notice' 'building' >&3
|
||||
if test -n "${buildHost}"; then
|
||||
ssh "${buildHost}" "cd \"${remoteBuildDir}/BUILD\" && make -j${concurrency}" || exit $?
|
||||
else
|
||||
make -j${concurrency} -C "${localBuildDir}/BUILD" || exit $?
|
||||
fi
|
||||
printf '%s %s\n' 'ok' 'build completed' >&3
|
||||
|
||||
if test -n "${buildHost}"; then
|
||||
printf '%s %s\n' 'notice' 'testing' >&3
|
||||
ssh "${buildHost}" "cd \"${remoteBuildDir}/BUILD\" && make -j${concurrency} check" || exit $?
|
||||
printf '%s %s\n' 'ok' 'testing completed' >&3
|
||||
elif test -n "${checkHost}"; then
|
||||
printf '%s %s\n' 'notice' "transferring build to ${checkHost}" >&3
|
||||
tar cvf "${localBuildDir}/build.tar" -C "${localBuildDir}" BUILD || exit $?
|
||||
scp "${localBuildDir}/build.tar" "${checkHost}:${remoteBuildDir}/build.tar" || exit $?
|
||||
ssh "${checkHost}" "tar xf \"${remoteBuildDir}/build.tar\" -C \"${remoteBuildDir}\"" || exit $?
|
||||
printf '%s %s\n' 'ok' "transferred build to ${checkHost}" >&3
|
||||
printf '%s %s\n' 'notice' "testing on ${checkHost}" >&3
|
||||
ssh "${checkHost}" "cd \"${remoteBuildDir}/BUILD\" && make -j${concurrency} check-TESTS XCTEST=1" || exit $?
|
||||
printf '%s %s\n' 'ok' 'testing completed' >&3
|
||||
fi
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
# Using directory $1 for metrics and output, run the remaining arguments as
|
||||
# a command using "scw" to capture metrics and record logs.
|
||||
#
|
||||
recordCommand () {
|
||||
targetDir="$1"
|
||||
shift
|
||||
mkdir -p "${targetDir}"
|
||||
scw -c /dev/null \
|
||||
-s UserConfigFile=/dev/null \
|
||||
-s ItemsDir=/dev/null \
|
||||
-s MetricsDir="${targetDir}" \
|
||||
-s CheckLockFile="${targetDir}/.widelock" \
|
||||
-s OutputMap= \
|
||||
-s OutputMap="OES stamped ${targetDir}/output.log" \
|
||||
-s OutputMap="OES raw ${targetDir}/raw-output.log" \
|
||||
-s Command="$*" \
|
||||
run item
|
||||
}
|
||||
|
||||
if test "$1" = "--testRunner"; then
|
||||
testRunner
|
||||
exit 1
|
||||
fi
|
||||
|
||||
labHosts="$(cat ~/.config/lab-hosts 2>/dev/null)"
|
||||
|
||||
workDir=$(mktemp -d) || exit 1
|
||||
trap 'rm -rf "${workDir}"' EXIT
|
||||
|
||||
sourceArchive="$1"
|
||||
shift
|
||||
hostList="$*"
|
||||
test -n "${hostList}" || hostList="${labHosts}"
|
||||
|
||||
test -n "${sourceArchive}" || { echo "Usage: ${0##*/} TARBALL [HOST...]"; exit 1; }
|
||||
test -s "${sourceArchive}" || { echo "${sourceArchive}: not found"; exit 1; }
|
||||
|
||||
attrBold="$(tput bold 2>/dev/null)"
|
||||
attrUnderline="$(tput smul 2>/dev/null)"
|
||||
attrRed="$(tput setaf 1 2>/dev/null)"
|
||||
attrGreen="$(tput setaf 2 2>/dev/null)"
|
||||
attrYellow="$(tput setaf 3 2>/dev/null)"
|
||||
attrBlue="$(tput setaf 4 2>/dev/null)"
|
||||
attrMagenta="$(tput setaf 5 2>/dev/null)"
|
||||
attrCyan="$(tput setaf 6 2>/dev/null)"
|
||||
attrWhite="$(tput setaf 7 2>/dev/null)"
|
||||
attrNone="$(tput sgr0 2>/dev/null)"
|
||||
|
||||
dateStamp="$(date +%Y%m%d-%H%M)"
|
||||
resultsArchive="result-${dateStamp}.tar.gz"
|
||||
|
||||
startEpoch="$(date +%s)"
|
||||
|
||||
|
||||
for hostSpec in ${hostList}; do
|
||||
localTestDir="${workDir}/${hostSpec}"
|
||||
remoteBuildDir="test-${dateStamp}.$(date +%s).$$"
|
||||
buildHost="${hostSpec}"
|
||||
checkHost=""
|
||||
configureArguments=""
|
||||
|
||||
xcFor="${hostSpec%:*}"
|
||||
xcRunOn="${hostSpec#*:}"
|
||||
|
||||
if ! test "${xcFor}" = "${xcRunOn}"; then
|
||||
localTestDir="${workDir}/${xcFor}-${xcRunOn}"
|
||||
buildHost=""
|
||||
checkHost="${xcRunOn}"
|
||||
configureArguments="--host ${xcFor}"
|
||||
fi
|
||||
|
||||
mkdir "${localTestDir}"
|
||||
printf "%s\n" "${hostSpec}" > "${localTestDir}/hostSpec"
|
||||
|
||||
localBuildDir="${localTestDir}/XC"
|
||||
|
||||
(
|
||||
flock -x 3
|
||||
|
||||
export sourceArchive buildHost checkHost remoteBuildDir localBuildDir configureArguments
|
||||
recordCommand "${localTestDir}" "sh \"$0\" --testRunner" 3<&-
|
||||
|
||||
exec >>"${localTestDir}/output.log" 2>&1
|
||||
|
||||
printf '*** %s\n' 'retrieving build and test artefacts'
|
||||
mkdir "${localTestDir}/tests"
|
||||
if test -n "${buildHost}"; then
|
||||
scp "${buildHost}:${remoteBuildDir}/BUILD/config.log" "${localTestDir}/"
|
||||
scp "${buildHost}:${remoteBuildDir}/BUILD/test-suite.log" "${localTestDir}/"
|
||||
scp "${buildHost}:${remoteBuildDir}/BUILD/tests/*" "${localTestDir}/tests/"
|
||||
elif test -n "${checkHost}"; then
|
||||
scp "${checkHost}:${remoteBuildDir}/BUILD/config.log" "${localTestDir}/"
|
||||
scp "${checkHost}:${remoteBuildDir}/BUILD/test-suite.log" "${localTestDir}/"
|
||||
scp "${checkHost}:${remoteBuildDir}/BUILD/tests/*" "${localTestDir}/tests/"
|
||||
fi
|
||||
|
||||
printf '*** %s\n' 'removing build area'
|
||||
rm -rf "${localBuildDir}"
|
||||
if test -n "${buildHost}"; then
|
||||
ssh "${buildHost}" rm -rf "${remoteBuildDir}"
|
||||
elif test -n "${checkHost}"; then
|
||||
ssh "${checkHost}" rm -rf "${remoteBuildDir}"
|
||||
fi
|
||||
|
||||
printf '\n'
|
||||
|
||||
flock -u 3
|
||||
) > "${localTestDir}/framework-output.log" 2>&1 3>>"${localTestDir}/active" &
|
||||
done
|
||||
|
||||
sleep 0.1
|
||||
|
||||
allTestHostDirs="$(find "${workDir}" -mindepth 1 -maxdepth 1 -name "[0-9A-Za-z_]*" -type d -printf "%f\n" | sort)"
|
||||
|
||||
hostCount=0
|
||||
for testHostDir in ${allTestHostDirs}; do hostCount=$((1+hostCount)); done
|
||||
exitedCount=0
|
||||
overallStatus=""
|
||||
|
||||
while test "${exitedCount}" -lt "${hostCount}"; do
|
||||
width="$(tput cols 2>/dev/null)"
|
||||
test -n "${width}" || width=80
|
||||
|
||||
currentEpoch="$(date +%s)"
|
||||
elapsedSeconds=$((currentEpoch-startEpoch))
|
||||
|
||||
{
|
||||
nameWidth=0
|
||||
runningCount=0
|
||||
failedCount=0
|
||||
passedCount=0
|
||||
exitedCount=0
|
||||
overallStatus=""
|
||||
for testHostDir in ${allTestHostDirs}; do
|
||||
hostSpec="${testHostDir}"
|
||||
{ read -r hostSpec < "${workDir}/${testHostDir}/hostSpec"; } 2>/dev/null
|
||||
test "${#hostSpec}" -gt "${nameWidth}" && nameWidth="${#hostSpec}"
|
||||
|
||||
exec 3>>"${workDir}/${testHostDir}/active"
|
||||
flock -x -n 3 && exitedCount=$((1+exitedCount))
|
||||
exec 3<&-
|
||||
|
||||
test -e "${workDir}/${testHostDir}/ended" || runningCount=$((1+runningCount))
|
||||
if test -e "${workDir}/${testHostDir}/failed"; then
|
||||
overallStatus="FAIL"
|
||||
failedCount=$((1+failedCount))
|
||||
elif test -e "${workDir}/${testHostDir}/succeeded"; then
|
||||
test -z "${overallStatus}" && overallStatus="PASS"
|
||||
passedCount=$((1+passedCount))
|
||||
fi
|
||||
done
|
||||
test -n "${overallStatus}" || overallStatus="----"
|
||||
|
||||
printf "%sT+%04d - %s%s\n\n" "${attrUnderline}" "${elapsedSeconds}" "$(date '+%Y-%m-%d %H:%M:%S')" "${attrNone}"
|
||||
|
||||
for testHostDir in ${allTestHostDirs}; do
|
||||
hostSpec="${testHostDir}"
|
||||
{ read -r hostSpec < "${workDir}/${testHostDir}/hostSpec"; } 2>/dev/null
|
||||
|
||||
lastStatusWord="-"
|
||||
lastStatusMessage="-"
|
||||
{ read -r lastStatusWord lastStatusMessage < "${workDir}/${testHostDir}/last-status"; } 2>/dev/null
|
||||
|
||||
lastLine="-"
|
||||
test -s "${workDir}/${testHostDir}/output.log" && lastLine="$(tail -n 1 "${workDir}/${testHostDir}/output.log" 2>/dev/null | expand)"
|
||||
|
||||
testResult="----"
|
||||
test -e "${workDir}/${testHostDir}/failed" && testResult="FAIL"
|
||||
test -e "${workDir}/${testHostDir}/succeeded" && testResult="PASS"
|
||||
|
||||
remainingWidth=$((width-nameWidth-20))
|
||||
statusWidth=$((remainingWidth*2/3))
|
||||
test "${statusWidth}" -gt 40 && statusWidth=40
|
||||
lastLineWidth=$((remainingWidth-statusWidth))
|
||||
|
||||
printf " %s%${nameWidth}s%s " "${attrBold}${attrYellow}" "${hostSpec}" "${attrNone}"
|
||||
case "${testResult}" in
|
||||
"PASS") printf "%s%s%s" "${attrBold}${attrGreen}" "PASS" "${attrNone}" ;;
|
||||
"FAIL") printf "%s%s%s" "${attrBold}${attrRed}" "FAIL" "${attrNone}" ;;
|
||||
*) printf "%s" "----"
|
||||
esac
|
||||
|
||||
case "${lastStatusWord}" in
|
||||
"(begin)"|"begin") printf " (%s%s%s) " "${attrBold}${attrMagenta}" "begin" "${attrNone}" ;;
|
||||
"(end)"|"end") printf " (%s%s%s) " "${attrBold}${attrMagenta}" "end" "${attrNone}" ;;
|
||||
"(notice)"|"notice") printf " (%s%s%s) " "${attrBold}${attrCyan}" "notice" "${attrNone}" ;;
|
||||
"(ok)"|"ok") printf " (%s%s%s) " "${attrBold}${attrGreen}" "ok" "${attrNone}" ;;
|
||||
"(warning)"|"warning") printf " (%s%s%s)" "${attrBold}${attrYellow}" "warning" "${attrNone}" ;;
|
||||
"(error)"|"error") printf " (%s%s%s) " "${attrBold}${attrRed}" "error" "${attrNone}" ;;
|
||||
*) printf " %7s " ""; lastStatusMessage="${lastStatusWord} ${lastStatusMessage}" ;;
|
||||
esac
|
||||
printf " %s%-${statusWidth}.${statusWidth}s%s" "${attrWhite}" "${lastStatusMessage}" "${attrNone}"
|
||||
printf " %s%-${lastLineWidth}.${lastLineWidth}s%s" "${attrBlue}" "${lastLine}" "${attrNone}"
|
||||
printf "\n"
|
||||
done
|
||||
|
||||
printf "\n%s%s%s " "${attrBold}" "Overall status:" "${attrNone}"
|
||||
case "${overallStatus}" in
|
||||
"PASS") printf "%s%s%s" "${attrBold}${attrGreen}" "PASS" "${attrNone}" ;;
|
||||
"FAIL") printf "%s%s%s" "${attrBold}${attrRed}" "FAIL" "${attrNone}" ;;
|
||||
*) printf "%s" "----"
|
||||
esac
|
||||
|
||||
printf " %s%s%s " "${attrBold}" "Running,Passed,Failed:" "${attrNone}"
|
||||
printf "%sR%d%s" "${attrBold}${attrMagenta}" "${runningCount}" "${attrNone}"
|
||||
printf ",%sP%d%s" "${attrBold}${attrGreen}" "${passedCount}" "${attrNone}"
|
||||
printf ",%sF%d%s" "${attrBold}${attrRed}" "${failedCount}" "${attrNone}"
|
||||
printf " = %d" "${hostCount}"
|
||||
printf "\n\n"
|
||||
} > "${workDir}/latest-status.txt"
|
||||
|
||||
cat "${workDir}/latest-status.txt"
|
||||
sleep 1
|
||||
done
|
||||
|
||||
endEpoch="$(date +%s)"
|
||||
elapsedSeconds=$((endEpoch-startEpoch))
|
||||
|
||||
printf '%s\n' 'Generating results archive'
|
||||
tar czf "${resultsArchive}" -C "${workDir}" .
|
||||
|
||||
printf '%s: %d%s\n' 'Total time taken' "${elapsedSeconds}" "s"
|
||||
printf '%s: %s\n' 'Results archive' "${resultsArchive}"
|
||||
|
||||
test "${overallStatus}" = "PASS" || exit 1
|
||||
+1
-1
@@ -2,7 +2,6 @@ src/main/debug.c
|
||||
src/main/help.c
|
||||
src/main/main.c
|
||||
src/main/options.c
|
||||
src/main/remote.c
|
||||
src/main/version.c
|
||||
src/pv/calc.c
|
||||
src/pv/cursor.c
|
||||
@@ -25,6 +24,7 @@ src/pv/format/timer.c
|
||||
src/pv/loop.c
|
||||
src/pv/number.c
|
||||
src/pv/proctitle.c
|
||||
src/pv/remote.c
|
||||
src/pv/signal.c
|
||||
src/pv/state.c
|
||||
src/pv/string.c
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-10-11 16:00+0100\n"
|
||||
"POT-Creation-Date: 2025-10-31 19:47+0000\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"
|
||||
@@ -168,8 +168,8 @@ msgstr "vypisuj výstup i pokud standardní chybový výstup není terminál"
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "pozicuj kurzor pomocí řídících znaků"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:357 src/main/help.c:369
|
||||
#: src/main/help.c:379
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
msgid "FILE"
|
||||
msgstr "SOUBOR"
|
||||
|
||||
@@ -218,70 +218,78 @@ msgid "use direct I/O to bypass cache"
|
||||
msgstr "použij přímý V/V k obejítí cache"
|
||||
|
||||
#: src/main/help.c:355
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr "zahoď vstup namísto zápisu na výstup"
|
||||
|
||||
#: src/main/help.c:358
|
||||
#: src/main/help.c:361
|
||||
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:360
|
||||
msgid "PID[:FD]"
|
||||
msgstr "PID[:DS]"
|
||||
#: src/main/help.c:364
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:365
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "sleduj soubor DS otevřený procesem PID"
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
msgid "PID"
|
||||
msgstr "PID"
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:369
|
||||
msgid "update settings of process PID"
|
||||
msgstr "aktualizuj nastavení procesu PID"
|
||||
|
||||
#: src/main/help.c:370
|
||||
#: src/main/help.c:372
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "ulož id procesu do SOUBORu"
|
||||
|
||||
#: src/main/help.c:373
|
||||
#: src/main/help.c:380
|
||||
msgid "show this help and exit"
|
||||
msgstr "ukaž pomoc a skonči"
|
||||
|
||||
#: src/main/help.c:376
|
||||
#: src/main/help.c:383
|
||||
msgid "show version information and exit"
|
||||
msgstr "ukaž informace o verzi a skonči"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:387
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "zapiš ladící záznamy do SOUBORu"
|
||||
|
||||
#: src/main/help.c:406
|
||||
#: src/main/help.c:413
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Použití: %s [VOLBY] [SOUBOR]..."
|
||||
|
||||
#: src/main/help.c:417
|
||||
#: src/main/help.c:424
|
||||
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:555
|
||||
#: src/main/help.c:562
|
||||
msgid "Supported format sequences:"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:569
|
||||
#: src/main/help.c:576
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Prosím, hlašte veškeré chyby na: %s"
|
||||
|
||||
#: src/main/main.c:232
|
||||
#: src/main/main.c:228
|
||||
msgid "(input)"
|
||||
msgstr "(vstup)"
|
||||
|
||||
#: src/main/main.c:334
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr "selhala alokace stavu"
|
||||
|
||||
@@ -289,11 +297,11 @@ msgstr "selhala alokace stavu"
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:802
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
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:809
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
msgid "invalid process ID"
|
||||
msgstr "neplatné ID procesu"
|
||||
|
||||
@@ -321,45 +329,45 @@ 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í"
|
||||
|
||||
#: src/main/options.c:649
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "selhala alokace struktury pro volby"
|
||||
|
||||
#: src/main/options.c:668
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "selhala alokace struktury pro argv"
|
||||
|
||||
#: src/main/options.c:720
|
||||
#: src/main/options.c:723
|
||||
msgid "numeric value not understood"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:738
|
||||
#: src/main/options.c:743
|
||||
msgid "integer argument expected"
|
||||
msgstr "očekáván celočíselný argument"
|
||||
|
||||
#: src/main/options.c:750
|
||||
#: src/main/options.c:755
|
||||
msgid "numeric argument expected"
|
||||
msgstr "očekáván číselný argument"
|
||||
|
||||
#: src/main/options.c:762
|
||||
#: src/main/options.c:767
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:790
|
||||
#: src/main/options.c:795
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1042
|
||||
#: src/main/options.c:1056
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Zkuste `%s --help' pro více informací."
|
||||
|
||||
#: src/main/options.c:1044
|
||||
#: src/main/options.c:1058
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Zkuste `%s --h' pro více informací."
|
||||
|
||||
#: src/main/options.c:1075
|
||||
#: src/main/options.c:1089
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -367,29 +375,33 @@ msgstr ""
|
||||
"při sledování deskriptorů souborů nelze použít řádkový mód nebo volby pro "
|
||||
"modifikaci přenosu"
|
||||
|
||||
#: src/main/options.c:1084
|
||||
#: src/main/options.c:1098
|
||||
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:1093
|
||||
#: src/main/options.c:1107
|
||||
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:1102
|
||||
#: src/main/options.c:1116
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
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:1127
|
||||
#: src/main/options.c:1150
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "není dostupné na systémech bez /proc/self/fdinfo"
|
||||
|
||||
#: src/main/remote.c:309
|
||||
msgid "message not received"
|
||||
msgstr "zpráva nepřijata"
|
||||
#: src/main/options.c:1162
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:444
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO není na tomto systému podporováno"
|
||||
#: src/main/options.c:1189
|
||||
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>"
|
||||
@@ -431,7 +443,7 @@ msgstr "yzafpnum kMGTPEZY"
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr "yzafpnum KMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/loop.c:747 src/pv/transfer.c:1083
|
||||
#: 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"
|
||||
|
||||
@@ -464,7 +476,7 @@ 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:565
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
msgid "b/s"
|
||||
msgstr "b/s"
|
||||
|
||||
@@ -474,7 +486,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:565
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
@@ -494,48 +506,44 @@ msgstr "ETA"
|
||||
msgid "FIN"
|
||||
msgstr "FIN"
|
||||
|
||||
#: src/pv/loop.c:564
|
||||
#: src/pv/loop.c:120
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr "rychlost min/avg/max/std"
|
||||
|
||||
#: src/pv/loop.c:576
|
||||
#: src/pv/loop.c:132
|
||||
msgid "rate not measured"
|
||||
msgstr "rychlost neměřena"
|
||||
|
||||
#: src/pv/loop.c:768 src/pv/loop.c:784 src/pv/loop.c:802 src/pv/watchpid.c:99
|
||||
#: src/pv/watchpid.c:108 src/pv/watchpid.c:119 src/pv/watchpid.c:127
|
||||
#: src/pv/watchpid.c:164 src/pv/watchpid.c:183 src/pv/watchpid.c:191
|
||||
#: src/pv/watchpid.c:201 src/pv/watchpid.c:299 src/pv/watchpid.c:307
|
||||
#: src/pv/watchpid.c:439 src/pv/watchpid.c:462
|
||||
#: 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
|
||||
msgid "pid"
|
||||
msgstr "pid"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/watchpid.c:108 src/pv/watchpid.c:120
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:183 src/pv/watchpid.c:192
|
||||
#: src/pv/watchpid.c:203
|
||||
#: 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
|
||||
msgid "fd"
|
||||
msgstr "ds"
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
msgid "message not received"
|
||||
msgstr "zpráva nepřijata"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
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:685 src/pv/state.c:697
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr "selhala alokace seznamu souborů"
|
||||
|
||||
#: src/pv/state.c:731
|
||||
#, fuzzy
|
||||
#| msgid "file list allocation failed"
|
||||
msgid "process list allocation failed"
|
||||
msgstr "selhala alokace seznamu souborů"
|
||||
|
||||
#: src/pv/state.c:739
|
||||
#, fuzzy
|
||||
#| msgid "file list allocation failed"
|
||||
msgid "file descriptor list allocation failed"
|
||||
msgstr "selhala alokace seznamu souborů"
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr "čtení selhalo"
|
||||
@@ -556,30 +564,33 @@ msgstr "selhal skok za chybu"
|
||||
msgid "skipped past read error"
|
||||
msgstr "chyba přeskočena"
|
||||
|
||||
#: src/pv/transfer.c:660
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr "vyrovnávací paměť není alokována"
|
||||
|
||||
#: src/pv/transfer.c:702
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr "selhalo nastavení intervalového časovače"
|
||||
|
||||
#: src/pv/transfer.c:728
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr "selhalo vynulování intervalového časovače"
|
||||
|
||||
#: src/pv/transfer.c:770
|
||||
#: 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:944
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "zápis selhal"
|
||||
|
||||
#: src/pv/transfer.c:1185
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "selhalo volání select"
|
||||
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:203
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "není obyčejný soubor nebo blokové zařízení"
|
||||
|
||||
#~ msgid "PID[:FD]"
|
||||
#~ msgstr "PID[:DS]"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-10-11 16:00+0100\n"
|
||||
"POT-Creation-Date: 2025-10-31 19:47+0000\n"
|
||||
"PO-Revision-Date: 2025-01-14 20:39+0000\n"
|
||||
"Last-Translator: Benny <benny@users.noreply.translate.codeberg.org>\n"
|
||||
"Language-Team: German <https://translate.codeberg.org/projects/pv/pv/de/>\n"
|
||||
@@ -185,8 +185,8 @@ msgstr ""
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "benutze Escape-Sequenzen zur Cursor-Positionierung"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:357 src/main/help.c:369
|
||||
#: src/main/help.c:379
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
msgid "FILE"
|
||||
msgstr "DATEI"
|
||||
|
||||
@@ -235,71 +235,79 @@ msgid "use direct I/O to bypass cache"
|
||||
msgstr "verwende direkte E/A, um den Cache zu umgehen"
|
||||
|
||||
#: src/main/help.c:355
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr "verwirf die Eingabe anstatt in die Ausgabe zu schreiben"
|
||||
|
||||
#: src/main/help.c:358
|
||||
#: src/main/help.c:361
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr "Ausgabe nach FILE schrieben bevor sie ausgegeben wird"
|
||||
|
||||
#: src/main/help.c:360
|
||||
msgid "PID[:FD]"
|
||||
msgstr "PID[:FD]"
|
||||
#: src/main/help.c:364
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:365
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "die vom Prozess PID geöffnete Datei FD beobachten"
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
msgid "PID"
|
||||
msgstr "PID"
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:369
|
||||
msgid "update settings of process PID"
|
||||
msgstr "Einstellungen der Prozess-PID updaten"
|
||||
|
||||
#: src/main/help.c:370
|
||||
#: src/main/help.c:372
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "Prozess-ID in DATEI speichern"
|
||||
|
||||
#: src/main/help.c:373
|
||||
#: src/main/help.c:380
|
||||
msgid "show this help and exit"
|
||||
msgstr "zeige diese Hilfe und beende"
|
||||
|
||||
#: src/main/help.c:376
|
||||
#: src/main/help.c:383
|
||||
msgid "show version information and exit"
|
||||
msgstr "zeige Versionsinformationen und beende"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:387
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "schreibe Debug-Protokolle in DATEI"
|
||||
|
||||
#: src/main/help.c:406
|
||||
#: src/main/help.c:413
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Aufruf: %s [OPTION] [DATEI]..."
|
||||
|
||||
#: src/main/help.c:417
|
||||
#: src/main/help.c:424
|
||||
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:555
|
||||
#: src/main/help.c:562
|
||||
msgid "Supported format sequences:"
|
||||
msgstr "unterstützte Formate:"
|
||||
|
||||
#: src/main/help.c:569
|
||||
#: src/main/help.c:576
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Bitte senden Sie Fehlerberichte an %s"
|
||||
|
||||
#: src/main/main.c:232
|
||||
#: src/main/main.c:228
|
||||
msgid "(input)"
|
||||
msgstr "(eingabe)"
|
||||
|
||||
#: src/main/main.c:334
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr "Speicherzuweisung für `state' fehlgeschlagen"
|
||||
|
||||
@@ -307,11 +315,11 @@ msgstr "Speicherzuweisung für `state' fehlgeschlagen"
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:802
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
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:809
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
msgid "invalid process ID"
|
||||
msgstr "ungültige Prozess-ID"
|
||||
|
||||
@@ -339,45 +347,45 @@ msgstr "konnte Blockgerät nicht öffnen"
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr "konnte Größe des Blockgeräts nicht ermitteln"
|
||||
|
||||
#: src/main/options.c:649
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "Speicherzuweisung für `option' fehlgeschlagen"
|
||||
|
||||
#: src/main/options.c:668
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "Speicherzuweisung für `argv' der Option fehlgeschlagen"
|
||||
|
||||
#: src/main/options.c:720
|
||||
#: src/main/options.c:723
|
||||
msgid "numeric value not understood"
|
||||
msgstr "numerischen Wert nicht verstanden"
|
||||
|
||||
#: src/main/options.c:738
|
||||
#: src/main/options.c:743
|
||||
msgid "integer argument expected"
|
||||
msgstr "Ganzzahliges Argument erwartet"
|
||||
|
||||
#: src/main/options.c:750
|
||||
#: src/main/options.c:755
|
||||
msgid "numeric argument expected"
|
||||
msgstr "numerisches Argument erwartet"
|
||||
|
||||
#: src/main/options.c:762
|
||||
#: src/main/options.c:767
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:790
|
||||
#: src/main/options.c:795
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1042
|
||||
#: src/main/options.c:1056
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "`%s --help' zeigt weitere Informationen an."
|
||||
|
||||
#: src/main/options.c:1044
|
||||
#: src/main/options.c:1058
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "`%s -h' zeigt weitere Informationen an."
|
||||
|
||||
#: src/main/options.c:1075
|
||||
#: src/main/options.c:1089
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -385,34 +393,38 @@ msgstr ""
|
||||
"Beim Beobachten von Dateideskriptoren können keine Optionen für den "
|
||||
"Zeilenmodus oder den Übertragungsmodifikator verwendet werden"
|
||||
|
||||
#: src/main/options.c:1084
|
||||
#: src/main/options.c:1098
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
"Beim Beobachten von Dateideskriptoren kann Cursor-Positionierung nicht "
|
||||
"verwendet werden"
|
||||
|
||||
#: src/main/options.c:1093
|
||||
#: src/main/options.c:1107
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
"Beim Beobachten von Dateideskriptoren kann die Fernbedienung nicht verwenden "
|
||||
"werden"
|
||||
|
||||
#: src/main/options.c:1102
|
||||
#: src/main/options.c:1116
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
"Beim Beobachten von Dateideskriptoren können Dateien nicht übertragen werden"
|
||||
|
||||
#: src/main/options.c:1127
|
||||
#: src/main/options.c:1150
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "Nicht verfügbar auf Systemen ohne /proc/self/fdinfo"
|
||||
|
||||
#: src/main/remote.c:309
|
||||
msgid "message not received"
|
||||
msgstr "Nachricht nicht empfangen"
|
||||
#: src/main/options.c:1162
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:444
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO wird auf diesem System nicht unterstützt"
|
||||
#: src/main/options.c:1189
|
||||
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>"
|
||||
@@ -454,7 +466,7 @@ msgstr "yzafpnµm kMGTPEZY"
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr "yzafpnµm KMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/loop.c:747 src/pv/transfer.c:1083
|
||||
#: 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"
|
||||
|
||||
@@ -487,7 +499,7 @@ 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:565
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
msgid "b/s"
|
||||
msgstr "b/s"
|
||||
|
||||
@@ -497,7 +509,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:565
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
@@ -517,48 +529,44 @@ msgstr "ETA"
|
||||
msgid "FIN"
|
||||
msgstr "Endzeit"
|
||||
|
||||
#: src/pv/loop.c:564
|
||||
#: src/pv/loop.c:120
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr "Rate min/mittel/max/abweichung"
|
||||
|
||||
#: src/pv/loop.c:576
|
||||
#: src/pv/loop.c:132
|
||||
msgid "rate not measured"
|
||||
msgstr "Übertragungsrate nicht gemessen"
|
||||
|
||||
#: src/pv/loop.c:768 src/pv/loop.c:784 src/pv/loop.c:802 src/pv/watchpid.c:99
|
||||
#: src/pv/watchpid.c:108 src/pv/watchpid.c:119 src/pv/watchpid.c:127
|
||||
#: src/pv/watchpid.c:164 src/pv/watchpid.c:183 src/pv/watchpid.c:191
|
||||
#: src/pv/watchpid.c:201 src/pv/watchpid.c:299 src/pv/watchpid.c:307
|
||||
#: src/pv/watchpid.c:439 src/pv/watchpid.c:462
|
||||
#: 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
|
||||
msgid "pid"
|
||||
msgstr "pid"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/watchpid.c:108 src/pv/watchpid.c:120
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:183 src/pv/watchpid.c:192
|
||||
#: src/pv/watchpid.c:203
|
||||
#: 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
|
||||
msgid "fd"
|
||||
msgstr "fd"
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
msgid "message not received"
|
||||
msgstr "Nachricht nicht empfangen"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
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:685 src/pv/state.c:697
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr "Speicherzuweisung für die Dateiliste fehlgeschlagen"
|
||||
|
||||
#: src/pv/state.c:731
|
||||
#, fuzzy
|
||||
#| msgid "file list allocation failed"
|
||||
msgid "process list allocation failed"
|
||||
msgstr "Speicherzuweisung für die Dateiliste fehlgeschlagen"
|
||||
|
||||
#: src/pv/state.c:739
|
||||
#, fuzzy
|
||||
#| msgid "file list allocation failed"
|
||||
msgid "file descriptor list allocation failed"
|
||||
msgstr "Speicherzuweisung für die Dateiliste fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr "read-Aufruf fehlgeschlagen"
|
||||
@@ -579,30 +587,33 @@ msgstr "konnte den Fehler nicht überwinden"
|
||||
msgid "skipped past read error"
|
||||
msgstr "über den Lesefehler hinaus verschoben"
|
||||
|
||||
#: src/pv/transfer.c:660
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr "Speicherzuweisung für den Transferpuffer fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:702
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr "konnte Intervall-Timer nicht setzen"
|
||||
|
||||
#: src/pv/transfer.c:728
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr "konnte Intervall-Timer nicht löschen"
|
||||
|
||||
#: src/pv/transfer.c:770
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr "Zuweisung des Zeilenpuffers fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:944
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "write-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:1185
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "select-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:203
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "ist weder eine normale Datei noch ein Blockgerät"
|
||||
|
||||
#~ msgid "PID[:FD]"
|
||||
#~ msgstr "PID[:FD]"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-10-11 16:00+0100\n"
|
||||
"POT-Creation-Date: 2025-10-31 19:47+0000\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -163,8 +163,8 @@ msgstr ""
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:357 src/main/help.c:369
|
||||
#: src/main/help.c:379
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
@@ -213,69 +213,77 @@ msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:355
|
||||
msgid "discard input instead of writing to output"
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:360
|
||||
msgid "PID[:FD]"
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:361
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:364
|
||||
msgid "PID"
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:365
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:369
|
||||
msgid "update settings of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:370
|
||||
#: src/main/help.c:372
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
msgid "save process ID in FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:373
|
||||
#: src/main/help.c:380
|
||||
msgid "show this help and exit"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:376
|
||||
#: src/main/help.c:383
|
||||
msgid "show version information and exit"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:387
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:406
|
||||
#: src/main/help.c:413
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:417
|
||||
#: src/main/help.c:424
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:555
|
||||
#: src/main/help.c:562
|
||||
msgid "Supported format sequences:"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:569
|
||||
#: src/main/help.c:576
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/main.c:232
|
||||
#: src/main/main.c:228
|
||||
msgid "(input)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/main.c:334
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr ""
|
||||
|
||||
@@ -283,11 +291,11 @@ msgstr ""
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:802
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:809
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
msgid "invalid process ID"
|
||||
msgstr ""
|
||||
|
||||
@@ -315,72 +323,76 @@ msgstr ""
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:649
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:668
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:720
|
||||
#: src/main/options.c:723
|
||||
msgid "numeric value not understood"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:738
|
||||
#: src/main/options.c:743
|
||||
msgid "integer argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:750
|
||||
#: src/main/options.c:755
|
||||
msgid "numeric argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:762
|
||||
#: src/main/options.c:767
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:790
|
||||
#: src/main/options.c:795
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1042
|
||||
#: src/main/options.c:1056
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1044
|
||||
#: src/main/options.c:1058
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1075
|
||||
#: src/main/options.c:1089
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1084
|
||||
#: src/main/options.c:1098
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1093
|
||||
#: src/main/options.c:1107
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1102
|
||||
#: src/main/options.c:1116
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1127
|
||||
#: src/main/options.c:1150
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:309
|
||||
msgid "message not received"
|
||||
#: src/main/options.c:1162
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:444
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
#: src/main/options.c:1189
|
||||
msgid "files cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:28
|
||||
@@ -423,7 +435,7 @@ msgstr ""
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/loop.c:747 src/pv/transfer.c:1083
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
msgstr ""
|
||||
|
||||
@@ -456,7 +468,7 @@ 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:565
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
@@ -466,7 +478,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:565
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
msgid "B/s"
|
||||
msgstr ""
|
||||
|
||||
@@ -486,44 +498,44 @@ msgstr ""
|
||||
msgid "FIN"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:564
|
||||
#: src/pv/loop.c:120
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:576
|
||||
#: src/pv/loop.c:132
|
||||
msgid "rate not measured"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:768 src/pv/loop.c:784 src/pv/loop.c:802 src/pv/watchpid.c:99
|
||||
#: src/pv/watchpid.c:108 src/pv/watchpid.c:119 src/pv/watchpid.c:127
|
||||
#: src/pv/watchpid.c:164 src/pv/watchpid.c:183 src/pv/watchpid.c:191
|
||||
#: src/pv/watchpid.c:201 src/pv/watchpid.c:299 src/pv/watchpid.c:307
|
||||
#: src/pv/watchpid.c:439 src/pv/watchpid.c:462
|
||||
#: 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
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/watchpid.c:108 src/pv/watchpid.c:120
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:183 src/pv/watchpid.c:192
|
||||
#: src/pv/watchpid.c:203
|
||||
#: 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
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
msgid "message not received"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:42
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:685 src/pv/state.c:697
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:731
|
||||
msgid "process list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:739
|
||||
msgid "file descriptor list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr ""
|
||||
@@ -544,30 +556,30 @@ msgstr ""
|
||||
msgid "skipped past read error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:660
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:702
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:728
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:770
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:944
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:1185
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:203
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
msgid "not a regular file or block device"
|
||||
msgstr ""
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#, fuzzy
|
||||
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-10-11 16:00+0100\n"
|
||||
"POT-Creation-Date: 2025-10-31 19:47+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"
|
||||
@@ -168,8 +167,8 @@ msgstr ""
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:357 src/main/help.c:369
|
||||
#: src/main/help.c:379
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
@@ -218,69 +217,77 @@ msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:355
|
||||
msgid "discard input instead of writing to output"
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:360
|
||||
msgid "PID[:FD]"
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:361
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:364
|
||||
msgid "PID"
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:365
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:369
|
||||
msgid "update settings of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:370
|
||||
#: src/main/help.c:372
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
msgid "save process ID in FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:373
|
||||
#: src/main/help.c:380
|
||||
msgid "show this help and exit"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:376
|
||||
#: src/main/help.c:383
|
||||
msgid "show version information and exit"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:387
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:406
|
||||
#: src/main/help.c:413
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:417
|
||||
#: src/main/help.c:424
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:555
|
||||
#: src/main/help.c:562
|
||||
msgid "Supported format sequences:"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:569
|
||||
#: src/main/help.c:576
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/main.c:232
|
||||
#: src/main/main.c:228
|
||||
msgid "(input)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/main.c:334
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr ""
|
||||
|
||||
@@ -288,11 +295,11 @@ msgstr ""
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:802
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:809
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
msgid "invalid process ID"
|
||||
msgstr ""
|
||||
|
||||
@@ -320,72 +327,76 @@ msgstr ""
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:649
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:668
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:720
|
||||
#: src/main/options.c:723
|
||||
msgid "numeric value not understood"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:738
|
||||
#: src/main/options.c:743
|
||||
msgid "integer argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:750
|
||||
#: src/main/options.c:755
|
||||
msgid "numeric argument expected"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:762
|
||||
#: src/main/options.c:767
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:790
|
||||
#: src/main/options.c:795
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1042
|
||||
#: src/main/options.c:1056
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1044
|
||||
#: src/main/options.c:1058
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1075
|
||||
#: src/main/options.c:1089
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1084
|
||||
#: src/main/options.c:1098
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1093
|
||||
#: src/main/options.c:1107
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1102
|
||||
#: src/main/options.c:1116
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1127
|
||||
#: src/main/options.c:1150
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:309
|
||||
msgid "message not received"
|
||||
#: src/main/options.c:1162
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:444
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
#: src/main/options.c:1189
|
||||
msgid "files cannot be specified with this option"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:28
|
||||
@@ -428,7 +439,7 @@ msgstr ""
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/loop.c:747 src/pv/transfer.c:1083
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
msgstr ""
|
||||
|
||||
@@ -461,7 +472,7 @@ 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:565
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
@@ -471,7 +482,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:565
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
msgid "B/s"
|
||||
msgstr ""
|
||||
|
||||
@@ -491,44 +502,44 @@ msgstr ""
|
||||
msgid "FIN"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:564
|
||||
#: src/pv/loop.c:120
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:576
|
||||
#: src/pv/loop.c:132
|
||||
msgid "rate not measured"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:768 src/pv/loop.c:784 src/pv/loop.c:802 src/pv/watchpid.c:99
|
||||
#: src/pv/watchpid.c:108 src/pv/watchpid.c:119 src/pv/watchpid.c:127
|
||||
#: src/pv/watchpid.c:164 src/pv/watchpid.c:183 src/pv/watchpid.c:191
|
||||
#: src/pv/watchpid.c:201 src/pv/watchpid.c:299 src/pv/watchpid.c:307
|
||||
#: src/pv/watchpid.c:439 src/pv/watchpid.c:462
|
||||
#: 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
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/watchpid.c:108 src/pv/watchpid.c:120
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:183 src/pv/watchpid.c:192
|
||||
#: src/pv/watchpid.c:203
|
||||
#: 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
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
msgid "message not received"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:42
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:685 src/pv/state.c:697
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:731
|
||||
msgid "process list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:739
|
||||
msgid "file descriptor list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr ""
|
||||
@@ -549,30 +560,30 @@ msgstr ""
|
||||
msgid "skipped past read error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:660
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:702
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:728
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:770
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:944
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:1185
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:203
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
msgid "not a regular file or block device"
|
||||
msgstr ""
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-10-11 16:00+0100\n"
|
||||
"POT-Creation-Date: 2025-10-31 19:47+0000\n"
|
||||
"PO-Revision-Date: 2025-05-31 08:58+0000\n"
|
||||
"Last-Translator: milimarg <milimarg@noreply.codeberg.org>\n"
|
||||
"Language-Team: French <https://translate.codeberg.org/projects/pv/pv/fr/>\n"
|
||||
@@ -186,8 +186,8 @@ msgstr ""
|
||||
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:357 src/main/help.c:369
|
||||
#: src/main/help.c:379
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
msgid "FILE"
|
||||
msgstr "FICHIER"
|
||||
|
||||
@@ -236,71 +236,79 @@ msgid "use direct I/O to bypass cache"
|
||||
msgstr "utiliser les E/S directes pour contourner le cache"
|
||||
|
||||
#: src/main/help.c:355
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
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:358
|
||||
#: src/main/help.c:361
|
||||
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:360
|
||||
msgid "PID[:FD]"
|
||||
msgstr "PID[:FD]"
|
||||
#: src/main/help.c:364
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:365
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "surveiller le fichier FD ouvert par le processus PID"
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
msgid "PID"
|
||||
msgstr "PID"
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:369
|
||||
msgid "update settings of process PID"
|
||||
msgstr "mettre à jour la configuration du processus PID"
|
||||
|
||||
#: src/main/help.c:370
|
||||
#: src/main/help.c:372
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "enregistrer l'ID de processus dans FICHIER"
|
||||
|
||||
#: src/main/help.c:373
|
||||
#: src/main/help.c:380
|
||||
msgid "show this help and exit"
|
||||
msgstr "afficher cette aide puis quitter"
|
||||
|
||||
#: src/main/help.c:376
|
||||
#: src/main/help.c:383
|
||||
msgid "show version information and exit"
|
||||
msgstr "afficher la version puis quitter"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:387
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "écrire les journaux de déboggage vers FICHIER"
|
||||
|
||||
#: src/main/help.c:406
|
||||
#: src/main/help.c:413
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Utilisation : %s [OPTIONS] [FICHIER]..."
|
||||
|
||||
#: src/main/help.c:417
|
||||
#: src/main/help.c:424
|
||||
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:555
|
||||
#: src/main/help.c:562
|
||||
msgid "Supported format sequences:"
|
||||
msgstr "Séquences de formatage supportées :"
|
||||
|
||||
#: src/main/help.c:569
|
||||
#: src/main/help.c:576
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "SVP rapporter tous bogues à %s"
|
||||
|
||||
#: src/main/main.c:232
|
||||
#: src/main/main.c:228
|
||||
msgid "(input)"
|
||||
msgstr "(entrée)"
|
||||
|
||||
#: src/main/main.c:334
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr "échec de l'allocation de mémoire de condition"
|
||||
|
||||
@@ -308,11 +316,11 @@ msgstr "échec de l'allocation de mémoire de condition"
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:802
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
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:809
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
msgid "invalid process ID"
|
||||
msgstr "ID de processus non valide"
|
||||
|
||||
@@ -340,45 +348,45 @@ 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"
|
||||
|
||||
#: src/main/options.c:649
|
||||
#: 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:668
|
||||
#: 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:720
|
||||
#: src/main/options.c:723
|
||||
msgid "numeric value not understood"
|
||||
msgstr "valeur numérique non comprise"
|
||||
|
||||
#: src/main/options.c:738
|
||||
#: src/main/options.c:743
|
||||
msgid "integer argument expected"
|
||||
msgstr "Valeur entière attendue"
|
||||
|
||||
#: src/main/options.c:750
|
||||
#: src/main/options.c:755
|
||||
msgid "numeric argument expected"
|
||||
msgstr "Valeur numérique attendue"
|
||||
|
||||
#: src/main/options.c:762
|
||||
#: src/main/options.c:767
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:790
|
||||
#: src/main/options.c:795
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1042
|
||||
#: src/main/options.c:1056
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Essayez `%s --help' pour plus d'informations."
|
||||
|
||||
#: src/main/options.c:1044
|
||||
#: src/main/options.c:1058
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Essayez `%s -h' pour plus d'informations."
|
||||
|
||||
#: src/main/options.c:1075
|
||||
#: src/main/options.c:1089
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -386,35 +394,39 @@ 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:1084
|
||||
#: src/main/options.c:1098
|
||||
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:1093
|
||||
#: src/main/options.c:1107
|
||||
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:1102
|
||||
#: src/main/options.c:1116
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
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:1127
|
||||
#: src/main/options.c:1150
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "non disponible sur les systèmes sans /proc/self/fdinfo"
|
||||
|
||||
#: src/main/remote.c:309
|
||||
msgid "message not received"
|
||||
msgstr "message non reçu"
|
||||
#: src/main/options.c:1162
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:444
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO non pris en charge sur ce système"
|
||||
#: src/main/options.c:1189
|
||||
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>"
|
||||
@@ -458,7 +470,7 @@ msgstr "yzafpnum kMGTPEZY"
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr "yzafpnum KMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/loop.c:747 src/pv/transfer.c:1083
|
||||
#: 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"
|
||||
|
||||
@@ -491,7 +503,7 @@ 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:565
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
msgid "b/s"
|
||||
msgstr "b/s"
|
||||
|
||||
@@ -501,7 +513,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:565
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
msgid "B/s"
|
||||
msgstr "O/s"
|
||||
|
||||
@@ -521,48 +533,44 @@ msgstr "ETA"
|
||||
msgid "FIN"
|
||||
msgstr "FIN"
|
||||
|
||||
#: src/pv/loop.c:564
|
||||
#: src/pv/loop.c:120
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr "taux min/moy/max/écart-type"
|
||||
|
||||
#: src/pv/loop.c:576
|
||||
#: src/pv/loop.c:132
|
||||
msgid "rate not measured"
|
||||
msgstr "taux non mesuré"
|
||||
|
||||
#: src/pv/loop.c:768 src/pv/loop.c:784 src/pv/loop.c:802 src/pv/watchpid.c:99
|
||||
#: src/pv/watchpid.c:108 src/pv/watchpid.c:119 src/pv/watchpid.c:127
|
||||
#: src/pv/watchpid.c:164 src/pv/watchpid.c:183 src/pv/watchpid.c:191
|
||||
#: src/pv/watchpid.c:201 src/pv/watchpid.c:299 src/pv/watchpid.c:307
|
||||
#: src/pv/watchpid.c:439 src/pv/watchpid.c:462
|
||||
#: 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
|
||||
msgid "pid"
|
||||
msgstr "pid"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/watchpid.c:108 src/pv/watchpid.c:120
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:183 src/pv/watchpid.c:192
|
||||
#: src/pv/watchpid.c:203
|
||||
#: 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
|
||||
msgid "fd"
|
||||
msgstr "fd"
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
msgid "message not received"
|
||||
msgstr "message non reçu"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
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:685 src/pv/state.c:697
|
||||
#: 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/state.c:731
|
||||
#, fuzzy
|
||||
#| msgid "file list allocation failed"
|
||||
msgid "process list allocation failed"
|
||||
msgstr "échec de l'allocation de la liste de fichiers"
|
||||
|
||||
#: src/pv/state.c:739
|
||||
#, fuzzy
|
||||
#| msgid "file list allocation failed"
|
||||
msgid "file descriptor 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é"
|
||||
@@ -583,33 +591,36 @@ msgstr "n'a pas réussi à dépasser l'erreur"
|
||||
msgid "skipped past read error"
|
||||
msgstr "erreur de lecture dépassée"
|
||||
|
||||
#: src/pv/transfer.c:660
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr "aucun tampon de transfert alloué"
|
||||
|
||||
#: src/pv/transfer.c:702
|
||||
#: 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:728
|
||||
#: 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:770
|
||||
#: 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:944
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "l'écriture a échoué"
|
||||
|
||||
#: src/pv/transfer.c:1185
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "l'appel de sélection a échoué"
|
||||
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:203
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "pas un fichier ordinaire ou un périphérique de bloc"
|
||||
|
||||
#~ msgid "PID[:FD]"
|
||||
#~ msgstr "PID[:FD]"
|
||||
|
||||
#~ msgid "failed to set alarm signal handler"
|
||||
#~ msgstr "échec de la définition du gestionnaire de signal d'alarme"
|
||||
|
||||
@@ -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-10-11 16:00+0100\n"
|
||||
"POT-Creation-Date: 2025-10-31 19:47+0000\n"
|
||||
"PO-Revision-Date: 2025-10-02 13:23+0000\n"
|
||||
"Last-Translator: Coral Pink <coralpink@noreply.codeberg.org>\n"
|
||||
"Language-Team: Polish <https://translate.codeberg.org/projects/pv/pv/pl/>\n"
|
||||
@@ -178,8 +178,8 @@ msgstr "pokaż wyjście nawet standardowe wyjście błędu nie jest terminalem"
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "używaj znaków ucieczki do pozycjonowania kursora"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:357 src/main/help.c:369
|
||||
#: src/main/help.c:379
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
msgid "FILE"
|
||||
msgstr "PLIK"
|
||||
|
||||
@@ -229,72 +229,80 @@ msgstr ""
|
||||
"użyj bezpośredniego wejścia/wyjścia celem pominięcia pamięci podręcznej"
|
||||
|
||||
#: src/main/help.c:355
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
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:358
|
||||
#: src/main/help.c:361
|
||||
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:360
|
||||
msgid "PID[:FD]"
|
||||
msgstr "PID[:FD]"
|
||||
#: src/main/help.c:364
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:365
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "obserwuj plik FD otworzony przez proces PID"
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
msgid "PID"
|
||||
msgstr "PID"
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:369
|
||||
msgid "update settings of process PID"
|
||||
msgstr "zaktualizuj ustawienia procesu PID"
|
||||
|
||||
#: src/main/help.c:370
|
||||
#: src/main/help.c:372
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "zapisz ID procesu do PLIK"
|
||||
|
||||
#: src/main/help.c:373
|
||||
#: src/main/help.c:380
|
||||
msgid "show this help and exit"
|
||||
msgstr "wyświetl te informacje z pomocą i wyjdź"
|
||||
|
||||
#: src/main/help.c:376
|
||||
#: src/main/help.c:383
|
||||
msgid "show version information and exit"
|
||||
msgstr "wyświetl informacje o wersji i wyjdź"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:387
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "zapisz logi debugujące do PLIK"
|
||||
|
||||
#: src/main/help.c:406
|
||||
#: src/main/help.c:413
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Sposób użycia: %s [OPCJA] [PLIK]..."
|
||||
|
||||
#: src/main/help.c:417
|
||||
#: src/main/help.c:424
|
||||
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."
|
||||
|
||||
#: src/main/help.c:555
|
||||
#: src/main/help.c:562
|
||||
msgid "Supported format sequences:"
|
||||
msgstr "Wspierane sekwencje formatowania:"
|
||||
|
||||
#: src/main/help.c:569
|
||||
#: src/main/help.c:576
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Proszę przesyłać zgłoszenia błędów do %s"
|
||||
|
||||
#: src/main/main.c:232
|
||||
#: src/main/main.c:228
|
||||
msgid "(input)"
|
||||
msgstr "(wejście)"
|
||||
|
||||
#: src/main/main.c:334
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr "alokacja stanu programu nie powiodła się"
|
||||
|
||||
@@ -302,11 +310,11 @@ msgstr "alokacja stanu programu nie powiodła się"
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:802
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
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:809
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
msgid "invalid process ID"
|
||||
msgstr "niepoprawne ID procesu"
|
||||
|
||||
@@ -334,45 +342,45 @@ 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"
|
||||
|
||||
#: src/main/options.c:649
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "nie udało się zaalokować struktur opcji"
|
||||
|
||||
#: src/main/options.c:668
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "nie udało się zaalokować struktur opcji argv"
|
||||
|
||||
#: src/main/options.c:720
|
||||
#: src/main/options.c:723
|
||||
msgid "numeric value not understood"
|
||||
msgstr "wartość liczbowa niezrozumiana"
|
||||
|
||||
#: src/main/options.c:738
|
||||
#: src/main/options.c:743
|
||||
msgid "integer argument expected"
|
||||
msgstr "oczekiwany argument typu liczby całkowitej"
|
||||
|
||||
#: src/main/options.c:750
|
||||
#: src/main/options.c:755
|
||||
msgid "numeric argument expected"
|
||||
msgstr "oczekiwany argument liczbowy"
|
||||
|
||||
#: src/main/options.c:762
|
||||
#: src/main/options.c:767
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:790
|
||||
#: src/main/options.c:795
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1042
|
||||
#: src/main/options.c:1056
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Spróbuj `%s --help' by uzyskać więcej informacji."
|
||||
|
||||
#: src/main/options.c:1044
|
||||
#: src/main/options.c:1058
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Spróbuj `%s -h' by uzyskać więcej informacji."
|
||||
|
||||
#: src/main/options.c:1075
|
||||
#: src/main/options.c:1089
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -380,33 +388,37 @@ 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:1084
|
||||
#: src/main/options.c:1098
|
||||
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:1093
|
||||
#: src/main/options.c:1107
|
||||
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"
|
||||
|
||||
#: src/main/options.c:1102
|
||||
#: src/main/options.c:1116
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
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:1127
|
||||
#: src/main/options.c:1150
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "niedostępne na systemach bez /proc/self/fdinfo"
|
||||
|
||||
#: src/main/remote.c:309
|
||||
msgid "message not received"
|
||||
msgstr "wiadomość nieodebrana"
|
||||
#: src/main/options.c:1162
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:444
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO nie jest wspierane na tym systemie"
|
||||
#: src/main/options.c:1189
|
||||
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>"
|
||||
@@ -449,7 +461,7 @@ msgstr "yzafpnum kMGTPEZY"
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr "yzafpnum KMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/loop.c:747 src/pv/transfer.c:1083
|
||||
#: 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"
|
||||
|
||||
@@ -483,7 +495,7 @@ 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:565
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
msgid "b/s"
|
||||
msgstr "b/s"
|
||||
|
||||
@@ -493,7 +505,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:565
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
@@ -513,44 +525,44 @@ msgstr "ETA"
|
||||
msgid "FIN"
|
||||
msgstr "FIN"
|
||||
|
||||
#: src/pv/loop.c:564
|
||||
#: src/pv/loop.c:120
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr "prędkość min/śr/max/odch"
|
||||
|
||||
#: src/pv/loop.c:576
|
||||
#: src/pv/loop.c:132
|
||||
msgid "rate not measured"
|
||||
msgstr "prędkość niezmierzona"
|
||||
|
||||
#: src/pv/loop.c:768 src/pv/loop.c:784 src/pv/loop.c:802 src/pv/watchpid.c:99
|
||||
#: src/pv/watchpid.c:108 src/pv/watchpid.c:119 src/pv/watchpid.c:127
|
||||
#: src/pv/watchpid.c:164 src/pv/watchpid.c:183 src/pv/watchpid.c:191
|
||||
#: src/pv/watchpid.c:201 src/pv/watchpid.c:299 src/pv/watchpid.c:307
|
||||
#: src/pv/watchpid.c:439 src/pv/watchpid.c:462
|
||||
#: 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
|
||||
msgid "pid"
|
||||
msgstr "pid"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/watchpid.c:108 src/pv/watchpid.c:120
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:183 src/pv/watchpid.c:192
|
||||
#: src/pv/watchpid.c:203
|
||||
#: 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
|
||||
msgid "fd"
|
||||
msgstr "fd"
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
msgid "message not received"
|
||||
msgstr "wiadomość nieodebrana"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
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:685 src/pv/state.c:697
|
||||
#: 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/state.c:731
|
||||
msgid "process list allocation failed"
|
||||
msgstr "nie udało się zaalokować listy procesów"
|
||||
|
||||
#: src/pv/state.c:739
|
||||
msgid "file descriptor list allocation failed"
|
||||
msgstr "nie udało się zaalokować listy deskryptorów plików"
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr "błąd odczytu"
|
||||
@@ -571,31 +583,40 @@ msgstr "nie udało się przewinąć za błąd"
|
||||
msgid "skipped past read error"
|
||||
msgstr "pominięto błąd odczytu"
|
||||
|
||||
#: src/pv/transfer.c:660
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr "brak zaalokowanego bufora transferu"
|
||||
|
||||
#: src/pv/transfer.c:702
|
||||
#: 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:728
|
||||
#: 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:770
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr "alokacja buforu pozycji linii nie powiodła się"
|
||||
|
||||
#: src/pv/transfer.c:944
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "błąd zapisu"
|
||||
|
||||
#: src/pv/transfer.c:1185
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "nie udało się wywołać funkcji select"
|
||||
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:203
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "plik nie jest plikiem regularnym lub urządzeniem blokowym"
|
||||
|
||||
#~ msgid "process list allocation failed"
|
||||
#~ msgstr "nie udało się zaalokować listy procesów"
|
||||
|
||||
#~ msgid "file descriptor list allocation failed"
|
||||
#~ msgstr "nie udało się zaalokować listy deskryptorów plików"
|
||||
|
||||
#~ msgid "PID[:FD]"
|
||||
#~ msgstr "PID[:FD]"
|
||||
|
||||
@@ -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-10-11 16:00+0100\n"
|
||||
"POT-Creation-Date: 2025-10-31 19:47+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"
|
||||
@@ -171,8 +171,8 @@ msgstr "gera dados mesmo que a saída de erro seja redirecionada"
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "utiliza caracteres de escape para posicionar o cursor"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:357 src/main/help.c:369
|
||||
#: src/main/help.c:379
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
@@ -221,71 +221,79 @@ msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:355
|
||||
msgid "discard input instead of writing to output"
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:360
|
||||
msgid "PID[:FD]"
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:361
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "assistir arquivo FD aberto pelo processo PID"
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:364
|
||||
msgid "PID"
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:365
|
||||
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
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:369
|
||||
msgid "update settings of process PID"
|
||||
msgstr "atualizar as configurações do processo PID"
|
||||
|
||||
#: src/main/help.c:370
|
||||
#: src/main/help.c:372
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "salvar ID do processo em FILE"
|
||||
|
||||
#: src/main/help.c:373
|
||||
#: src/main/help.c:380
|
||||
msgid "show this help and exit"
|
||||
msgstr "exibe esta tela de ajuda e termina"
|
||||
|
||||
#: src/main/help.c:376
|
||||
#: src/main/help.c:383
|
||||
msgid "show version information and exit"
|
||||
msgstr "exibe a versão e termina"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:387
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:406
|
||||
#: src/main/help.c:413
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Uso: %s [OPÇÕES] [ARQUIVOS]..."
|
||||
|
||||
#: src/main/help.c:417
|
||||
#: src/main/help.c:424
|
||||
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:555
|
||||
#: src/main/help.c:562
|
||||
msgid "Supported format sequences:"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:569
|
||||
#: src/main/help.c:576
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Por favor, reporte quaisquer defeitos para %s"
|
||||
|
||||
#: src/main/main.c:232
|
||||
#: src/main/main.c:228
|
||||
msgid "(input)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/main.c:334
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr "alocação de memória de status falhou"
|
||||
|
||||
@@ -293,11 +301,11 @@ msgstr "alocação de memória de status falhou"
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:802
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
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:809
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
msgid "invalid process ID"
|
||||
msgstr "ID de processo inválido"
|
||||
|
||||
@@ -325,45 +333,45 @@ msgstr ""
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:649
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "erro na alocação da estrutura de opções"
|
||||
|
||||
#: src/main/options.c:668
|
||||
#: 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:720
|
||||
#: src/main/options.c:723
|
||||
msgid "numeric value not understood"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:738
|
||||
#: src/main/options.c:743
|
||||
msgid "integer argument expected"
|
||||
msgstr "argumento inteiro esperado"
|
||||
|
||||
#: src/main/options.c:750
|
||||
#: src/main/options.c:755
|
||||
msgid "numeric argument expected"
|
||||
msgstr "argumento numérico esperado"
|
||||
|
||||
#: src/main/options.c:762
|
||||
#: src/main/options.c:767
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:790
|
||||
#: src/main/options.c:795
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1042
|
||||
#: src/main/options.c:1056
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Tente `%s --help' para maiores informações."
|
||||
|
||||
#: src/main/options.c:1044
|
||||
#: src/main/options.c:1058
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Tente `%s -h' para maiores informações."
|
||||
|
||||
#: src/main/options.c:1075
|
||||
#: src/main/options.c:1089
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -371,31 +379,35 @@ 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:1084
|
||||
#: src/main/options.c:1098
|
||||
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:1093
|
||||
#: src/main/options.c:1107
|
||||
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:1102
|
||||
#: src/main/options.c:1116
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr "não pode transferir arquivos ao assistir descritores de arquivo"
|
||||
|
||||
#: src/main/options.c:1127
|
||||
#: src/main/options.c:1150
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "não disponível em sistemas sem /proc/self/fdinfo"
|
||||
|
||||
#: src/main/remote.c:309
|
||||
msgid "message not received"
|
||||
msgstr "mensagem não recebida"
|
||||
#: src/main/options.c:1162
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:444
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO não suportado neste sistema"
|
||||
#: src/main/options.c:1189
|
||||
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>"
|
||||
@@ -437,7 +449,7 @@ msgstr ""
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/loop.c:747 src/pv/transfer.c:1083
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "erro alocando o buffer"
|
||||
|
||||
@@ -470,7 +482,7 @@ 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:565
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
@@ -480,7 +492,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:565
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
@@ -500,48 +512,44 @@ msgstr "ETA"
|
||||
msgid "FIN"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:564
|
||||
#: src/pv/loop.c:120
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:576
|
||||
#: src/pv/loop.c:132
|
||||
msgid "rate not measured"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:768 src/pv/loop.c:784 src/pv/loop.c:802 src/pv/watchpid.c:99
|
||||
#: src/pv/watchpid.c:108 src/pv/watchpid.c:119 src/pv/watchpid.c:127
|
||||
#: src/pv/watchpid.c:164 src/pv/watchpid.c:183 src/pv/watchpid.c:191
|
||||
#: src/pv/watchpid.c:201 src/pv/watchpid.c:299 src/pv/watchpid.c:307
|
||||
#: src/pv/watchpid.c:439 src/pv/watchpid.c:462
|
||||
#: 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
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/watchpid.c:108 src/pv/watchpid.c:120
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:183 src/pv/watchpid.c:192
|
||||
#: src/pv/watchpid.c:203
|
||||
#: 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
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
msgid "message not received"
|
||||
msgstr "mensagem não recebida"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
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:685 src/pv/state.c:697
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:731
|
||||
#, fuzzy
|
||||
#| msgid "state allocation failed"
|
||||
msgid "process list allocation failed"
|
||||
msgstr "alocação de memória de status falhou"
|
||||
|
||||
#: src/pv/state.c:739
|
||||
#, fuzzy
|
||||
#| msgid "state allocation failed"
|
||||
msgid "file descriptor list allocation failed"
|
||||
msgstr "alocação de memória de status falhou"
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr "erro de leitura"
|
||||
@@ -562,30 +570,30 @@ msgstr "não pode ir além do erro"
|
||||
msgid "skipped past read error"
|
||||
msgstr "ignorado erro de leitura"
|
||||
|
||||
#: src/pv/transfer.c:660
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:702
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:728
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:770
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:944
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "erro de gravação"
|
||||
|
||||
#: src/pv/transfer.c:1185
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "erro na chamada da função select"
|
||||
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:203
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "não é um arquivo regular ou dispositivo de bloqueio"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: https://codeberg.org/ivarch/pv/issues\n"
|
||||
"POT-Creation-Date: 2025-10-11 16:00+0100\n"
|
||||
"POT-Creation-Date: 2025-10-31 19:47+0000\n"
|
||||
"PO-Revision-Date: 2025-01-15 19:08+0000\n"
|
||||
"Last-Translator: 0ko <0ko@users.noreply.translate.codeberg.org>\n"
|
||||
"Language-Team: Russian <https://translate.codeberg.org/projects/pv/pv/ru/>\n"
|
||||
@@ -170,8 +170,8 @@ msgid "use cursor positioning escape sequences"
|
||||
msgstr ""
|
||||
"использовать символьные последовательности для позиционирования курсора"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:357 src/main/help.c:369
|
||||
#: src/main/help.c:379
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
msgid "FILE"
|
||||
msgstr "ФАЙЛ"
|
||||
|
||||
@@ -220,69 +220,77 @@ msgid "use direct I/O to bypass cache"
|
||||
msgstr "использовать прямой ввод/вывод для обхода кеша"
|
||||
|
||||
#: src/main/help.c:355
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr "отбрасывать ввод вместо записи в вывод"
|
||||
|
||||
#: src/main/help.c:358
|
||||
#: src/main/help.c:361
|
||||
msgid "write all input to FILE before writing to output"
|
||||
msgstr "записывать весь ввод в ФАЙЛ прежде, чем отправлять на вывод"
|
||||
|
||||
#: src/main/help.c:360
|
||||
msgid "PID[:FD]"
|
||||
msgstr "ИДпр[:FD]"
|
||||
#: src/main/help.c:364
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:365
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "следить за FD файла, открытого процессом ИДпр"
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
msgid "PID"
|
||||
msgstr "ИДпр"
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:369
|
||||
msgid "update settings of process PID"
|
||||
msgstr "обновить настройки ИДпр процесса"
|
||||
|
||||
#: src/main/help.c:370
|
||||
#: src/main/help.c:372
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "сохранить ИД процесса в ФАЙЛ"
|
||||
|
||||
#: src/main/help.c:373
|
||||
#: src/main/help.c:380
|
||||
msgid "show this help and exit"
|
||||
msgstr "показать справку и завершить работу"
|
||||
|
||||
#: src/main/help.c:376
|
||||
#: src/main/help.c:383
|
||||
msgid "show version information and exit"
|
||||
msgstr "показать версию программы и завершить работу"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:387
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "вести запись отладочного журнала в ФАЙЛ"
|
||||
|
||||
#: src/main/help.c:406
|
||||
#: src/main/help.c:413
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Использование: %s [ОПЦИИ] [ФАЙЛ]..."
|
||||
|
||||
#: src/main/help.c:417
|
||||
#: src/main/help.c:424
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:555
|
||||
#: src/main/help.c:562
|
||||
msgid "Supported format sequences:"
|
||||
msgstr "Поддерживаемые последовательности:"
|
||||
|
||||
#: src/main/help.c:569
|
||||
#: src/main/help.c:576
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Сообщайте о проблемах на: %s"
|
||||
|
||||
#: src/main/main.c:232
|
||||
#: src/main/main.c:228
|
||||
msgid "(input)"
|
||||
msgstr "(ввод)"
|
||||
|
||||
#: src/main/main.c:334
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr ""
|
||||
|
||||
@@ -290,11 +298,11 @@ msgstr ""
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:802
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
msgid "process ID or pid:fd pair expected"
|
||||
msgstr "ожидался ИД процесса или пара ИДпр:ДФ"
|
||||
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:809
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
msgid "invalid process ID"
|
||||
msgstr "неправильный ИД процесса"
|
||||
|
||||
@@ -322,73 +330,77 @@ msgstr "не удалось открыть блочное устройство"
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr "не удалось определить размер блочного устройства"
|
||||
|
||||
#: src/main/options.c:649
|
||||
#: src/main/options.c:652
|
||||
msgid "option structure allocation failed"
|
||||
msgstr "не удалось выделить память для структуры опций"
|
||||
|
||||
#: src/main/options.c:668
|
||||
#: src/main/options.c:671
|
||||
msgid "option structure argv allocation failed"
|
||||
msgstr "не удалось выделить память для структуры опций argv"
|
||||
|
||||
#: src/main/options.c:720
|
||||
#: src/main/options.c:723
|
||||
msgid "numeric value not understood"
|
||||
msgstr "число не распознано"
|
||||
|
||||
#: src/main/options.c:738
|
||||
#: src/main/options.c:743
|
||||
msgid "integer argument expected"
|
||||
msgstr "ожидалось целое число"
|
||||
|
||||
#: src/main/options.c:750
|
||||
#: src/main/options.c:755
|
||||
msgid "numeric argument expected"
|
||||
msgstr "ожидалось число"
|
||||
|
||||
#: src/main/options.c:762
|
||||
#: src/main/options.c:767
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:790
|
||||
#: src/main/options.c:795
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1042
|
||||
#: src/main/options.c:1056
|
||||
#, c-format
|
||||
msgid "Try `%s --help' for more information."
|
||||
msgstr "Выполните `%s --help' для получения подробностей."
|
||||
|
||||
#: src/main/options.c:1044
|
||||
#: src/main/options.c:1058
|
||||
#, c-format
|
||||
msgid "Try `%s -h' for more information."
|
||||
msgstr "Выполните `%s -h' для получения подробностей."
|
||||
|
||||
#: src/main/options.c:1075
|
||||
#: src/main/options.c:1089
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1084
|
||||
#: src/main/options.c:1098
|
||||
msgid "cannot use cursor positioning when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1093
|
||||
#: src/main/options.c:1107
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr "удалённое управление невозможно при отслеживании дескрипторов файлов"
|
||||
|
||||
#: src/main/options.c:1102
|
||||
#: src/main/options.c:1116
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr "передача файлов невозможна при отслеживании дескрипторов файлов"
|
||||
|
||||
#: src/main/options.c:1127
|
||||
#: src/main/options.c:1150
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "невозможно на системах без /proc/self/fdinfo"
|
||||
|
||||
#: src/main/remote.c:309
|
||||
msgid "message not received"
|
||||
msgstr "сообщение не получено"
|
||||
#: src/main/options.c:1162
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:444
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "Этой системой не поддерживается SA_SIGINFO"
|
||||
#: src/main/options.c:1189
|
||||
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>"
|
||||
@@ -432,7 +444,7 @@ msgstr ""
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/loop.c:747 src/pv/transfer.c:1083
|
||||
#: src/pv/display.c:1053 src/pv/state.c:842 src/pv/transfer.c:1135
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "не удалось выделить память для буфера"
|
||||
|
||||
@@ -465,7 +477,7 @@ 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:565
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
msgid "b/s"
|
||||
msgstr "бит/с"
|
||||
|
||||
@@ -475,7 +487,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:565
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
msgid "B/s"
|
||||
msgstr "байт/с"
|
||||
|
||||
@@ -495,48 +507,44 @@ msgstr "ОЖИД"
|
||||
msgid "FIN"
|
||||
msgstr "ЗАВЕРШ"
|
||||
|
||||
#: src/pv/loop.c:564
|
||||
#: src/pv/loop.c:120
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr "скор. мин/сред/макс/дев"
|
||||
|
||||
#: src/pv/loop.c:576
|
||||
#: src/pv/loop.c:132
|
||||
msgid "rate not measured"
|
||||
msgstr "скорость не изменяется"
|
||||
|
||||
#: src/pv/loop.c:768 src/pv/loop.c:784 src/pv/loop.c:802 src/pv/watchpid.c:99
|
||||
#: src/pv/watchpid.c:108 src/pv/watchpid.c:119 src/pv/watchpid.c:127
|
||||
#: src/pv/watchpid.c:164 src/pv/watchpid.c:183 src/pv/watchpid.c:191
|
||||
#: src/pv/watchpid.c:201 src/pv/watchpid.c:299 src/pv/watchpid.c:307
|
||||
#: src/pv/watchpid.c:439 src/pv/watchpid.c:462
|
||||
#: 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
|
||||
msgid "pid"
|
||||
msgstr "ИДпр"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/watchpid.c:108 src/pv/watchpid.c:120
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:183 src/pv/watchpid.c:192
|
||||
#: src/pv/watchpid.c:203
|
||||
#: 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
|
||||
msgid "fd"
|
||||
msgstr "дф"
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
msgid "message not received"
|
||||
msgstr "сообщение не получено"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
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:685 src/pv/state.c:697
|
||||
#: src/pv/state.c:794 src/pv/state.c:806
|
||||
msgid "file list allocation failed"
|
||||
msgstr "не удалось выделить память для списка файлов"
|
||||
|
||||
#: src/pv/state.c:731
|
||||
#, fuzzy
|
||||
#| msgid "file list allocation failed"
|
||||
msgid "process list allocation failed"
|
||||
msgstr "не удалось выделить память для списка файлов"
|
||||
|
||||
#: src/pv/state.c:739
|
||||
#, fuzzy
|
||||
#| msgid "file list allocation failed"
|
||||
msgid "file descriptor list allocation failed"
|
||||
msgstr "не удалось выделить память для списка файлов"
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr "чтение не удалось"
|
||||
@@ -557,30 +565,33 @@ msgstr ""
|
||||
msgid "skipped past read error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:660
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr "не выделена память для буфера передачи"
|
||||
|
||||
#: src/pv/transfer.c:702
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr "не удалось задать измеритель временного промежутка"
|
||||
|
||||
#: src/pv/transfer.c:728
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr "не удалось очистить измеритель временного промежутка"
|
||||
|
||||
#: src/pv/transfer.c:770
|
||||
#: src/pv/transfer.c:822
|
||||
msgid "line position buffer allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:944
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "запись не удалась"
|
||||
|
||||
#: src/pv/transfer.c:1185
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "запрос выборки не удался"
|
||||
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:203
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
msgid "not a regular file or block device"
|
||||
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-10-11 16:00+0100\n"
|
||||
"POT-Creation-Date: 2025-10-31 19:47+0000\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"
|
||||
@@ -169,8 +169,8 @@ msgstr "standart hata bir terminal olmasa bile çıktı yazdır"
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "imleç konumlandırma kaçış dizilerini kullan"
|
||||
|
||||
#: src/main/help.c:327 src/main/help.c:357 src/main/help.c:369
|
||||
#: src/main/help.c:379
|
||||
#: src/main/help.c:327 src/main/help.c:360 src/main/help.c:376
|
||||
#: src/main/help.c:386
|
||||
msgid "FILE"
|
||||
msgstr "DOSYA"
|
||||
|
||||
@@ -219,70 +219,78 @@ msgid "use direct I/O to bypass cache"
|
||||
msgstr "Önbelleği atlamak için doğrudan I/O kullan"
|
||||
|
||||
#: src/main/help.c:355
|
||||
msgid "try to seek instead of writing null bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:358
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr "Girdiyi çıktıya yazmak yerine yok say"
|
||||
|
||||
#: src/main/help.c:358
|
||||
#: src/main/help.c:361
|
||||
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:360
|
||||
msgid "PID[:FD]"
|
||||
msgstr "PID[:FD]"
|
||||
#: src/main/help.c:364
|
||||
msgid "PID[:FD]|=NAME|@LISTFILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:361
|
||||
#: src/main/help.c:365
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "FD izleme dosyası PID işlemi tarafından açıldı"
|
||||
|
||||
#: src/main/help.c:364
|
||||
#: src/main/help.c:368 src/main/help.c:371
|
||||
msgid "PID"
|
||||
msgstr "PID"
|
||||
|
||||
#: src/main/help.c:365
|
||||
#: src/main/help.c:369
|
||||
msgid "update settings of process PID"
|
||||
msgstr "süreç PID ayarlarını güncelle"
|
||||
|
||||
#: src/main/help.c:370
|
||||
#: src/main/help.c:372
|
||||
msgid "show progress of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:377
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "FILE'da işlem kimliğini (ID) kaydet"
|
||||
|
||||
#: src/main/help.c:373
|
||||
#: src/main/help.c:380
|
||||
msgid "show this help and exit"
|
||||
msgstr "bu yardımı göster ve çık"
|
||||
|
||||
#: src/main/help.c:376
|
||||
#: src/main/help.c:383
|
||||
msgid "show version information and exit"
|
||||
msgstr "sürüm bilgilerini göster ve çık"
|
||||
|
||||
#: src/main/help.c:380
|
||||
#: src/main/help.c:387
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr "Hata ayıklama kayıtlarını DOSYA'ya yaz"
|
||||
|
||||
#: src/main/help.c:406
|
||||
#: src/main/help.c:413
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Kullanım şekli: %s [AYAR] [DOSYA]..."
|
||||
|
||||
#: src/main/help.c:417
|
||||
#: src/main/help.c:424
|
||||
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:555
|
||||
#: src/main/help.c:562
|
||||
msgid "Supported format sequences:"
|
||||
msgstr "Desteklenen biçim dizileri:"
|
||||
|
||||
#: src/main/help.c:569
|
||||
#: src/main/help.c:576
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Lütfen hataları şu adrese bildirin: %s"
|
||||
|
||||
#: src/main/main.c:232
|
||||
#: src/main/main.c:228
|
||||
msgid "(input)"
|
||||
msgstr "(giriş)"
|
||||
|
||||
#: src/main/main.c:334
|
||||
#: src/main/main.c:330
|
||||
msgid "state allocation failed"
|
||||
msgstr "durum tahsisi başarısız oldu"
|
||||
|
||||
@@ -290,11 +298,11 @@ msgstr "durum tahsisi başarısız oldu"
|
||||
msgid "list files may not contain @ lines"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:802
|
||||
#: src/main/options.c:391 src/main/options.c:393 src/main/options.c:807
|
||||
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:809
|
||||
#: src/main/options.c:403 src/main/options.c:405 src/main/options.c:814
|
||||
msgid "invalid process ID"
|
||||
msgstr "geçersiz süreç kimliği (ID)"
|
||||
|
||||
@@ -322,45 +330,45 @@ msgstr "blok aygıtı açılamadı"
|
||||
msgid "failed to determine size of block device"
|
||||
msgstr "blok aygıtının boyutu belirlenemedi"
|
||||
|
||||
#: src/main/options.c:649
|
||||
#: 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:668
|
||||
#: 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:720
|
||||
#: src/main/options.c:723
|
||||
msgid "numeric value not understood"
|
||||
msgstr "sayısal değer anlaşılmadı"
|
||||
|
||||
#: src/main/options.c:738
|
||||
#: src/main/options.c:743
|
||||
msgid "integer argument expected"
|
||||
msgstr "tamsayı bağımsız değişkeni bekleniyor"
|
||||
|
||||
#: src/main/options.c:750
|
||||
#: src/main/options.c:755
|
||||
msgid "numeric argument expected"
|
||||
msgstr "sayısal bağımsız değişken bekleniyor"
|
||||
|
||||
#: src/main/options.c:762
|
||||
#: src/main/options.c:767
|
||||
msgid "missing filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:790
|
||||
#: src/main/options.c:795
|
||||
msgid "missing process name"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1042
|
||||
#: src/main/options.c:1056
|
||||
#, 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:1044
|
||||
#: src/main/options.c:1058
|
||||
#, 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:1075
|
||||
#: src/main/options.c:1089
|
||||
msgid ""
|
||||
"cannot use line mode or transfer modifier options when watching file "
|
||||
"descriptors"
|
||||
@@ -368,29 +376,33 @@ msgstr ""
|
||||
"dosya tanımlayıcılarını izlerken satır modu veya aktarım değiştirici "
|
||||
"seçeneklerini kullanamaz"
|
||||
|
||||
#: src/main/options.c:1084
|
||||
#: src/main/options.c:1098
|
||||
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:1093
|
||||
#: src/main/options.c:1107
|
||||
msgid "cannot use remote control when watching file descriptors"
|
||||
msgstr "dosya tanımlayıcılarını izlerken uzaktan kumandayı kullanamaz"
|
||||
|
||||
#: src/main/options.c:1102
|
||||
#: src/main/options.c:1116
|
||||
msgid "cannot use remote query when watching file descriptors"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/options.c:1125
|
||||
msgid "cannot transfer files when watching file descriptors"
|
||||
msgstr "dosya tanımlayıcıları izlenirken dosya aktarılamıyor"
|
||||
|
||||
#: src/main/options.c:1127
|
||||
#: src/main/options.c:1150
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "/proc/self/fdinfo olmayan sistemlerde kullanılamaz"
|
||||
|
||||
#: src/main/remote.c:309
|
||||
msgid "message not received"
|
||||
msgstr "mesaj alınamadı"
|
||||
#: src/main/options.c:1162
|
||||
msgid "cannot use remote control and remote query together"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:444
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO bu sistemde desteklenmiyor"
|
||||
#: src/main/options.c:1189
|
||||
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>"
|
||||
@@ -433,7 +445,7 @@ msgstr "yzafpnum kMGTPEZY"
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr "yzafpnum KMGTPEZY"
|
||||
|
||||
#: src/pv/display.c:1053 src/pv/loop.c:747 src/pv/transfer.c:1083
|
||||
#: 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"
|
||||
|
||||
@@ -466,7 +478,7 @@ 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:565
|
||||
#: src/pv/format/rate.c:36 src/pv/loop.c:121
|
||||
msgid "b/s"
|
||||
msgstr "b/s"
|
||||
|
||||
@@ -476,7 +488,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:565
|
||||
#: src/pv/format/rate.c:40 src/pv/loop.c:121
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
@@ -496,44 +508,44 @@ msgstr "ETA"
|
||||
msgid "FIN"
|
||||
msgstr "FIN"
|
||||
|
||||
#: src/pv/loop.c:564
|
||||
#: src/pv/loop.c:120
|
||||
msgid "rate min/avg/max/mdev"
|
||||
msgstr "oran min/ortalama/maks/standart sapma"
|
||||
|
||||
#: src/pv/loop.c:576
|
||||
#: src/pv/loop.c:132
|
||||
msgid "rate not measured"
|
||||
msgstr "oran ölçülmedi"
|
||||
|
||||
#: src/pv/loop.c:768 src/pv/loop.c:784 src/pv/loop.c:802 src/pv/watchpid.c:99
|
||||
#: src/pv/watchpid.c:108 src/pv/watchpid.c:119 src/pv/watchpid.c:127
|
||||
#: src/pv/watchpid.c:164 src/pv/watchpid.c:183 src/pv/watchpid.c:191
|
||||
#: src/pv/watchpid.c:201 src/pv/watchpid.c:299 src/pv/watchpid.c:307
|
||||
#: src/pv/watchpid.c:439 src/pv/watchpid.c:462
|
||||
#: 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
|
||||
msgid "pid"
|
||||
msgstr "pid"
|
||||
|
||||
#: src/pv/loop.c:802 src/pv/watchpid.c:108 src/pv/watchpid.c:120
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:183 src/pv/watchpid.c:192
|
||||
#: src/pv/watchpid.c:203
|
||||
#: 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
|
||||
msgid "fd"
|
||||
msgstr "fd"
|
||||
|
||||
#: src/pv/remote.c:237 src/pv/remote.c:622
|
||||
msgid "message not received"
|
||||
msgstr "mesaj alınamadı"
|
||||
|
||||
#: src/pv/remote.c:644 src/pv/remote.c:662
|
||||
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:685 src/pv/state.c:697
|
||||
#: 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/state.c:731
|
||||
msgid "process list allocation failed"
|
||||
msgstr "işlem listesi tahsisi başarısız oldu"
|
||||
|
||||
#: src/pv/state.c:739
|
||||
msgid "file descriptor list allocation failed"
|
||||
msgstr "dosya tanımlayıcı listesi tahsisi başarısız oldu"
|
||||
|
||||
#: src/pv/transfer.c:490
|
||||
msgid "read failed"
|
||||
msgstr "okuma başarısız"
|
||||
@@ -554,30 +566,39 @@ msgstr "geçmiş hatayı aramakta başarısız oldu"
|
||||
msgid "skipped past read error"
|
||||
msgstr "geçmiş okuma hatası atlandı"
|
||||
|
||||
#: src/pv/transfer.c:660
|
||||
#: src/pv/transfer.c:663
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr "aktarım arabelleği ayrılmamış"
|
||||
|
||||
#: src/pv/transfer.c:702
|
||||
#: src/pv/transfer.c:751
|
||||
msgid "failed to set interval timer"
|
||||
msgstr "aralık zamanlayıcısı ayarlanamadı"
|
||||
|
||||
#: src/pv/transfer.c:728
|
||||
#: src/pv/transfer.c:777
|
||||
msgid "failed to clear interval timer"
|
||||
msgstr "aralık zamanlayıcısı temizlenemedi"
|
||||
|
||||
#: src/pv/transfer.c:770
|
||||
#: 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:944
|
||||
#: src/pv/transfer.c:996
|
||||
msgid "write failed"
|
||||
msgstr "yazma başarısız"
|
||||
|
||||
#: src/pv/transfer.c:1185
|
||||
#: src/pv/transfer.c:1237
|
||||
msgid "select call failed"
|
||||
msgstr "seçme çağrısı başarısız oldu"
|
||||
|
||||
#: src/pv/watchpid.c:129 src/pv/watchpid.c:203
|
||||
#: src/pv/watchpid.c:131 src/pv/watchpid.c:205
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "normal bir dosya veya blok aygıtı değil"
|
||||
|
||||
#~ msgid "process list allocation failed"
|
||||
#~ msgstr "işlem listesi tahsisi başarısız oldu"
|
||||
|
||||
#~ msgid "file descriptor list allocation failed"
|
||||
#~ msgstr "dosya tanımlayıcı listesi tahsisi başarısız oldu"
|
||||
|
||||
#~ msgid "PID[:FD]"
|
||||
#~ msgstr "PID[:FD]"
|
||||
|
||||
@@ -44,7 +44,7 @@ typedef bool _Bool;
|
||||
# define __bool_true_false_are_defined 1
|
||||
#endif
|
||||
|
||||
/* Whether "--remote" should be available. */
|
||||
/* Whether "--remote" and "--query" should be available. */
|
||||
#undef PV_REMOTE_CONTROL
|
||||
#if HAVE_DECL_SA_SIGINFO
|
||||
# if SIGINFO_PROVIDES_PID
|
||||
|
||||
@@ -30,7 +30,9 @@ typedef enum {
|
||||
PV_ACTION_NOTHING, /* do nothing, and exit */
|
||||
PV_ACTION_TRANSFER, /* transfer data */
|
||||
PV_ACTION_STORE_AND_FORWARD, /* store to file, then output from it */
|
||||
PV_ACTION_WATCHFD /* watch process file descriptors */
|
||||
PV_ACTION_WATCHFD, /* watch process file descriptors */
|
||||
PV_ACTION_REMOTE_CONTROL, /* remotely control another pv */
|
||||
PV_ACTION_QUERY /* watch the state of another pv */
|
||||
} pvaction_t;
|
||||
|
||||
/*
|
||||
@@ -58,6 +60,7 @@ struct opts_s {
|
||||
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 */
|
||||
pid_t query; /* PID of pv to query progress of */
|
||||
unsigned int skip_errors; /* skip read errors counter */
|
||||
unsigned int average_rate_window; /* time window in seconds for average rate calculations */
|
||||
unsigned int width; /* screen width */
|
||||
@@ -89,6 +92,7 @@ struct opts_s {
|
||||
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 sparse_output; /* set if we leave holes in the output */
|
||||
bool discard_input; /* set to write nothing to output */
|
||||
bool show_stats; /* set to write statistics at the end */
|
||||
bool width_set_manually; /* width was set manually, not detected */
|
||||
|
||||
+72
-44
@@ -25,7 +25,7 @@ extern "C" {
|
||||
|
||||
#define RATE_GRANULARITY 100000000 /* nsec between -L rate chunks */
|
||||
#define RATE_BURST_WINDOW 5 /* rate burst window (multiples of rate) */
|
||||
#define REMOTE_INTERVAL 100000000 /* nsec between checks for -R */
|
||||
#define REMOTE_INTERVAL 100000000 /* nsec between checks for -R and -Q */
|
||||
#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 */
|
||||
@@ -131,6 +131,12 @@ typedef uint16_t pvdisplay_bytecount_t;
|
||||
typedef uint16_t pvdisplay_width_t;
|
||||
#define PVDISPLAY_WIDTH_MAX (65535) /* UINT16_MAX */
|
||||
|
||||
/*
|
||||
* Structure defining the current state of a single watched file descriptor.
|
||||
*/
|
||||
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;
|
||||
|
||||
@@ -163,9 +169,15 @@ struct pvstate_s {
|
||||
/*********************************
|
||||
* Items to watch with --watchfd *
|
||||
*********************************/
|
||||
struct pvwatchspec_s {
|
||||
/*@only@*/ /*@null@*/ pid_t *pid; /* array of processes to watch fds of */
|
||||
/*@only@*/ /*@null@*/ int *fd; /* array of fds to watch in each one (0=all) */
|
||||
struct {
|
||||
/*@only@*/ /*@null@*/
|
||||
struct pvwatcheditem_s { /* array of PID or PID:FD items */
|
||||
pid_t pid; /* watched PID */
|
||||
int fd; /* watched fd, or -1 for all */
|
||||
pvwatchfd_t info_array; /* watch information for each fd */
|
||||
int array_length; /* length of watch info array */
|
||||
bool finished; /* "PID:FD": fd closed; or PID gone */
|
||||
} *watching;
|
||||
unsigned int count; /* number of items in these arrays */
|
||||
bool multiple_pids; /* true if more than one distinct PID */
|
||||
} watchfd;
|
||||
@@ -179,7 +191,8 @@ struct pvstate_s {
|
||||
double delay_start; /* delay before first display */
|
||||
/*@only@*/ /*@null@*/ char *name; /* display name */
|
||||
/*@only@*/ /*@null@*/ char *format_string; /* output format string */
|
||||
/*@only@*/ /*@null@*/ char *extra_format_string; /* extra format string */
|
||||
/*@only@*/ /*@null@*/ char *extra_display_spec; /* full spec for extra displays */
|
||||
/*@only@*/ /*@null@*/ char *extra_format_string; /* extra format string alone */
|
||||
/*@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 */
|
||||
@@ -193,6 +206,17 @@ struct pvstate_s {
|
||||
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;
|
||||
bool force; /* display even if not on terminal */
|
||||
bool cursor; /* use cursor positioning */
|
||||
bool numeric; /* numeric output only */
|
||||
@@ -203,11 +227,12 @@ struct pvstate_s {
|
||||
bool decimal_units; /* use decimal prefixes */
|
||||
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 no_splice; /* never use splice() */
|
||||
bool sparse_output; /* set if we leave holes in the output */
|
||||
bool discard_input; /* write nothing to stdout */
|
||||
bool show_stats; /* show statistics on exit */
|
||||
bool width_set_manually; /* width was set manually, not detected */
|
||||
@@ -229,13 +254,16 @@ struct pvstate_s {
|
||||
struct sigaction old_sigterm;
|
||||
#ifdef PV_REMOTE_CONTROL
|
||||
struct sigaction old_sigusr2;
|
||||
struct sigaction old_sigusr1;
|
||||
#endif
|
||||
struct sigaction old_sigalrm;
|
||||
struct timespec tstp_time; /* see pv_sig_tstp() / __cont() */
|
||||
struct timespec toffset; /* total time spent stopped */
|
||||
struct timespec when_tstp_arrived; /* see pv_sig_tstp() / __cont() */
|
||||
struct timespec total_stoppage_time; /* total time spent stopped */
|
||||
#ifdef PV_REMOTE_CONTROL
|
||||
volatile sig_atomic_t rxusr2; /* whether SIGUSR2 was received */
|
||||
volatile pid_t sender; /* PID of sending process for SIGUSR2 */
|
||||
volatile pid_t sender_usr2; /* PID of sending process for SIGUSR2 */
|
||||
volatile sig_atomic_t rxusr1; /* whether SIGUSR1 was received */
|
||||
volatile pid_t sender_usr1; /* PID of sending process for SIGUSR1 */
|
||||
#endif
|
||||
} signal;
|
||||
|
||||
@@ -372,9 +400,9 @@ struct pvstate_s {
|
||||
* The transfer buffer is used for moving data from the input files
|
||||
* to the output when splice() is not available.
|
||||
*
|
||||
* If buffer_size is smaller than pv__target_bufsize, then
|
||||
* If buffer_size is smaller than control.target_buffer_size, then
|
||||
* pv_transfer() will try to reallocate transfer_buffer to make
|
||||
* buffer_size equal to pv__target_bufsize.
|
||||
* 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.
|
||||
@@ -437,6 +465,7 @@ struct pvstate_s {
|
||||
bool splice_used;
|
||||
#endif
|
||||
bool read_error_warning_shown;
|
||||
bool output_not_seekable; /* set if lseek() fails on output */
|
||||
} transfer;
|
||||
};
|
||||
|
||||
@@ -451,6 +480,37 @@ typedef struct pvtransfercalc_s *pvtransfercalc_t;
|
||||
typedef struct pvcursorstate_s *pvcursorstate_t;
|
||||
typedef struct pvtransferstate_s *pvtransferstate_t;
|
||||
|
||||
/*
|
||||
* Structure defining the current state of a single watched file descriptor.
|
||||
* The full definition needs to go here as it refers to sub-structures of
|
||||
* the main state, defined above.
|
||||
*/
|
||||
struct pvwatchfd_s {
|
||||
struct pvtransientflags_s flags; /* transient flags */
|
||||
struct pvtransferstate_s transfer; /* transfer state */
|
||||
struct pvtransfercalc_s calc; /* calculated transfer state */
|
||||
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 */
|
||||
#endif
|
||||
char file_fdpath[PV_SIZEOF_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 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 */
|
||||
int watch_fd; /* fd to watch */
|
||||
bool closed; /* true once the fd is closed */
|
||||
bool displayable; /* false if not displayable */
|
||||
bool unused; /* true if free for re-use */
|
||||
};
|
||||
|
||||
/*
|
||||
* Read-only counterparts to the above structure pointers, to be used in
|
||||
* function declarations where the function definitely shouldn't be altering
|
||||
@@ -497,36 +557,6 @@ struct pvdisplay_component_s {
|
||||
bool dynamic; /* whether it can scale with screen size */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Structure defining the current state of a single watched file descriptor.
|
||||
*/
|
||||
struct pvwatchfd_s {
|
||||
struct pvtransientflags_s flags; /* transient flags */
|
||||
struct pvtransferstate_s transfer; /* transfer state */
|
||||
struct pvtransfercalc_s calc; /* calculated transfer state */
|
||||
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 */
|
||||
#endif
|
||||
char file_fdpath[PV_SIZEOF_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 last_active; /* time the fd was last seen open (TODO, #81) */
|
||||
pid_t watch_pid; /* PID to watch */
|
||||
int watch_fd; /* fd to watch */
|
||||
bool displayable; /* false if not displayable */
|
||||
bool inactive; /* true if the fd is now closed (TODO, #81) */
|
||||
bool unused; /* true if free for re-use */
|
||||
};
|
||||
typedef struct pvwatchfd_s *pvwatchfd_t;
|
||||
|
||||
void pv_error(char *, ...);
|
||||
|
||||
int pv_main_loop(pvstate_t);
|
||||
@@ -603,6 +633,7 @@ void pv_freecontents_display(pvdisplay_t);
|
||||
void pv_freecontents_transfer(pvtransferstate_t);
|
||||
void pv_freecontents_calc(pvtransfercalc_t);
|
||||
void pv_freecontents_watchfd(pvwatchfd_t);
|
||||
void pv_freecontents_watchfd_items(struct pvwatcheditem_s *, unsigned int);
|
||||
|
||||
void pv_write_retry(int, const char *, size_t);
|
||||
void pv_tty_write(readonly_pvtransientflags_t, const char *, size_t);
|
||||
@@ -618,10 +649,7 @@ void pv_sig_allowpause(void);
|
||||
void pv_sig_checkbg(void);
|
||||
void pv_sig_nopause(void);
|
||||
|
||||
void pv_remote_init(pvstate_t);
|
||||
bool pv_remote_check(pvstate_t);
|
||||
void pv_remote_fini(pvstate_t);
|
||||
int pv_remote_set(pvstate_t);
|
||||
|
||||
int pv_watchfd_info(pvstate_t, pvwatchfd_t, bool);
|
||||
bool pv_watchfd_changed(pvwatchfd_t);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <signal.h>
|
||||
@@ -221,6 +222,7 @@ extern void pv_state_error_skip_block_set(pvstate_t, off_t);
|
||||
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_target_buffer_size_set(pvstate_t, size_t);
|
||||
extern void pv_state_no_splice_set(pvstate_t, bool);
|
||||
@@ -265,8 +267,21 @@ extern void pv_sig_init(pvstate_t);
|
||||
* Return true if SIGUSR2 has been received, and indicate the sender.
|
||||
*/
|
||||
extern bool pv_sigusr2_received(pvstate_t, pid_t *);
|
||||
|
||||
/*
|
||||
* Return true if SIGUSR1 has been received, and indicate the sender.
|
||||
*/
|
||||
extern bool pv_sigusr1_received(pvstate_t, pid_t *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return a stream pointer for a control file associated with a particular
|
||||
* process ID and signal.
|
||||
*/
|
||||
/*@null@ */
|
||||
/*@dependent@ */
|
||||
extern FILE *pv_open_controlfile(char *, size_t, pid_t, int, bool);
|
||||
|
||||
/*
|
||||
* Enter the main transfer loop, transferring all input files to the output.
|
||||
*/
|
||||
@@ -277,6 +292,24 @@ extern int pv_main_loop(pvstate_t);
|
||||
*/
|
||||
extern int pv_watchfd_loop(pvstate_t);
|
||||
|
||||
/*
|
||||
* Watch the progress of another pv process.
|
||||
*/
|
||||
extern int pv_query_loop(pvstate_t, pid_t);
|
||||
|
||||
/*
|
||||
* Set the options of another pv process.
|
||||
*/
|
||||
int pv_remote_set(pvstate_t, pid_t);
|
||||
|
||||
/*
|
||||
* Query another pv process for its elapsed transfer time, amount
|
||||
* transferred, and total size, and update the local state with those
|
||||
* values. Optionally also return the total size separately. Reports
|
||||
* errors unless "silent" is true.
|
||||
*/
|
||||
int pv_remote_transferstate_fetch(pvstate_t state, pid_t query, /*@null@ */ off_t *sizeptr, bool silent);
|
||||
|
||||
/*
|
||||
* Shut down signal handlers after running the main loop.
|
||||
*/
|
||||
|
||||
+8
-1
@@ -351,19 +351,26 @@ void display_help(void)
|
||||
{ "-K", "--direct-io", NULL,
|
||||
N_("use direct I/O to bypass cache"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-O", "--sparse", NULL,
|
||||
N_("try to seek instead of writing null bytes"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-X", "--discard", NULL,
|
||||
N_("discard input instead of writing to output"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-U", "--store-and-forward", N_("FILE"),
|
||||
N_("write all input to FILE before writing to output"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-d", "--watchfd", N_("PID[:FD]"),
|
||||
{ "", NULL, NULL, NULL, { 0, 0, 0, 0} },
|
||||
{ "-d", "--watchfd", N_("PID[:FD]|=NAME|@LISTFILE"),
|
||||
N_("watch file FD opened by process PID"),
|
||||
{ 0, 0, 0, 0} },
|
||||
#ifdef PV_REMOTE_CONTROL
|
||||
{ "-R", "--remote", N_("PID"),
|
||||
N_("update settings of process PID"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-Q", "--query", N_("PID"),
|
||||
N_("show progress of process PID"),
|
||||
{ 0, 0, 0, 0} },
|
||||
#endif /* PV_REMOTE_CONTROL */
|
||||
{ "", NULL, NULL, NULL, { 0, 0, 0, 0} },
|
||||
{ "-P", "--pidfile", N_("FILE"),
|
||||
|
||||
+38
-28
@@ -23,10 +23,6 @@
|
||||
#include <langinfo.h>
|
||||
#endif
|
||||
|
||||
int pv_remote_set(opts_t, pvstate_t);
|
||||
void pv_remote_init(void);
|
||||
void pv_remote_fini(void);
|
||||
|
||||
/*
|
||||
* Write a PID file, returning nonzero on error. Write it atomically, such
|
||||
* that the file either exists and contains the PID, or is not updated at
|
||||
@@ -338,23 +334,6 @@ int main(int argc, char **argv)
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
|
||||
/*
|
||||
* -R specified - send the message, then exit.
|
||||
*/
|
||||
if (opts->remote > 0) {
|
||||
/* Initialise signal handling. */
|
||||
pv_sig_init(state);
|
||||
/* Send the message. */
|
||||
retcode = pv_remote_set(opts, state);
|
||||
/* Close down the signal handling. */
|
||||
pv_sig_fini(state);
|
||||
/* Free resources. */
|
||||
pv_state_free(state);
|
||||
opts_free(opts);
|
||||
/* Early exit. */
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a PID file if -P was specified.
|
||||
*/
|
||||
@@ -448,7 +427,12 @@ int main(int argc, char **argv)
|
||||
* do this before looking at setting 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.
|
||||
*/
|
||||
pv_state_sparse_output_set(state, opts->sparse_output);
|
||||
retcode = pv__set_output(state, opts, opts->output);
|
||||
if (0 != retcode) {
|
||||
pv_state_free(state);
|
||||
@@ -485,6 +469,31 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialise the signal handling. */
|
||||
pv_sig_init(state);
|
||||
|
||||
/*
|
||||
* Get the total size, in query mode.
|
||||
*
|
||||
* Note that this uses signals, so signal handling has to have been
|
||||
* set up first.
|
||||
*/
|
||||
if (PV_ACTION_QUERY == opts->action) {
|
||||
opts->size = 0;
|
||||
retcode = pv_remote_transferstate_fetch(state, opts->query, &(opts->size), false);
|
||||
if (0 != retcode) {
|
||||
pv_sig_fini(state);
|
||||
pv_state_free(state);
|
||||
opts_free(opts);
|
||||
return retcode;
|
||||
}
|
||||
/* As above - no ETA if the size is unknown. */
|
||||
if (opts->size < 1) {
|
||||
can_have_eta = false;
|
||||
debug("%s", "size unknown - ETA disabled");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the remaining parameters from the options into the main
|
||||
* state.
|
||||
@@ -527,29 +536,30 @@ int main(int argc, char **argv)
|
||||
debug("%s: %s", "terminal_supports_utf8", terminal_supports_utf8 ? "true" : "false");
|
||||
pv_state_set_terminal_supports_utf8(state, terminal_supports_utf8);
|
||||
|
||||
/* Initialise the signal handling. */
|
||||
pv_sig_init(state);
|
||||
|
||||
/* Run the appropriate main loop. */
|
||||
switch (opts->action) {
|
||||
case PV_ACTION_NOTHING:
|
||||
break;
|
||||
case PV_ACTION_TRANSFER:
|
||||
/* Normal "transfer data" mode. */
|
||||
pv_remote_init();
|
||||
retcode = pv_main_loop(state);
|
||||
pv_remote_fini();
|
||||
break;
|
||||
case PV_ACTION_STORE_AND_FORWARD:
|
||||
/* Store-and-forward transfer mode. */
|
||||
pv_remote_init();
|
||||
retcode = pv__store_and_forward(state, opts, can_have_eta);
|
||||
pv_remote_fini();
|
||||
break;
|
||||
case PV_ACTION_WATCHFD:
|
||||
/* "Watch file descriptor(s) of another process" mode. */
|
||||
retcode = pv_watchfd_loop(state);
|
||||
break;
|
||||
case PV_ACTION_REMOTE_CONTROL:
|
||||
/* Change the options of another running pv. */
|
||||
retcode = pv_remote_set(state, opts->remote);
|
||||
break;
|
||||
case PV_ACTION_QUERY:
|
||||
/* Query the progress of another running pv. */
|
||||
retcode = pv_query_loop(state, opts->query);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Clear up the PID file, if one was written. */
|
||||
|
||||
+46
-1
@@ -612,9 +612,12 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
||||
{ "stop-at-size", 0, NULL, (int) 'S' },
|
||||
{ "sync", 0, NULL, (int) 'Y' },
|
||||
{ "direct-io", 0, NULL, (int) 'K' },
|
||||
{ "sparse", 0, NULL, (int) 'O' },
|
||||
{ "sparse-output", 0, NULL, (int) 'O' },
|
||||
{ "discard", 0, NULL, (int) 'X' },
|
||||
{ "store-and-forward", 1, NULL, (int) 'U' },
|
||||
{ "remote", 1, NULL, (int) 'R' },
|
||||
{ "query", 1, NULL, (int) 'Q' },
|
||||
{ "pidfile", 1, NULL, (int) 'P' },
|
||||
{ "watchfd", 1, NULL, (int) 'd' },
|
||||
{ "output", 1, NULL, (int) 'o' },
|
||||
@@ -627,7 +630,7 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
||||
/*@+nullassign@ */
|
||||
int option_index = 0;
|
||||
#endif /* HAVE_GETOPT_LONG */
|
||||
char *short_options = "hVpteIrab8kTA:fvnqcWD:s:gl0i:w:H:N:u:F:x:L:B:CEZ:SYKXU:R:P:d:m:o:"
|
||||
char *short_options = "hVpteIrab8kTA:fvnqcWD:s:gl0i:w:H:N:u:F:x:L:B:CEZ:SYKOXU:R:Q:P:d:m:o:"
|
||||
#ifdef ENABLE_DEBUGGING
|
||||
"!:"
|
||||
#endif
|
||||
@@ -731,6 +734,8 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
||||
/*@fallthrough@ */
|
||||
case 'R':
|
||||
/*@fallthrough@ */
|
||||
case 'Q':
|
||||
/*@fallthrough@ */
|
||||
case 'm':
|
||||
if (!pv_getnum_check(optarg, PV_NUMTYPE_BARE_INTEGER)) {
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
@@ -972,6 +977,10 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
||||
case 'K':
|
||||
opts->direct_io = true;
|
||||
break;
|
||||
case 'O':
|
||||
opts->sparse_output = true;
|
||||
opts->no_splice = true;
|
||||
break;
|
||||
case 'X':
|
||||
opts->discard_input = true;
|
||||
opts->no_splice = true;
|
||||
@@ -987,6 +996,11 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
||||
break;
|
||||
case 'R':
|
||||
opts->remote = (pid_t) pv_getnum_count(optarg, false);
|
||||
opts->action = PV_ACTION_REMOTE_CONTROL;
|
||||
break;
|
||||
case 'Q':
|
||||
opts->query = (pid_t) pv_getnum_count(optarg, false);
|
||||
opts->action = PV_ACTION_QUERY;
|
||||
break;
|
||||
case 'P':
|
||||
opts->pidfile = pv_strdup(optarg);
|
||||
@@ -1096,6 +1110,15 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
|
||||
if (0 != opts->query) {
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name,
|
||||
_("cannot use remote query when watching file descriptors"));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
|
||||
if (NULL != opts->output) {
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: -o: %s\n", opts->program_name,
|
||||
@@ -1132,6 +1155,16 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Don't allow -R and -Q together. */
|
||||
if ((0 != opts->remote) && (0 != opts->query)) {
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name,
|
||||
_("cannot use remote control and remote query together"));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
|
||||
/*
|
||||
* Default options: -pterb
|
||||
*/
|
||||
@@ -1147,6 +1180,18 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
||||
if (opts->error_skip_block > 0 && 0 == opts->skip_errors)
|
||||
opts->skip_errors = 1;
|
||||
|
||||
/*
|
||||
* Don't allow any non-option arguments with -R or -Q.
|
||||
*/
|
||||
if ((optind < (int) argc) && ((0 != opts->remote) || (0 != opts->query))) {
|
||||
/*@-mustfreefresh@ *//* see above */
|
||||
fprintf(stderr, "%s: %s: %s\n", opts->program_name, 0 != opts->remote ? "-R" : "-Q",
|
||||
_("files cannot be specified with this option"));
|
||||
opts_free(opts);
|
||||
return NULL;
|
||||
/*@+mustfreefresh@ */
|
||||
}
|
||||
|
||||
/*
|
||||
* Store remaining command-line arguments.
|
||||
*/
|
||||
|
||||
@@ -1,449 +0,0 @@
|
||||
/*
|
||||
* Remote-control functions.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "options.h"
|
||||
#include "pv.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef PV_REMOTE_CONTROL
|
||||
void pv_error(char *, ...);
|
||||
|
||||
struct remote_msg {
|
||||
bool progress; /* progress bar flag */
|
||||
bool timer; /* timer flag */
|
||||
bool eta; /* ETA flag */
|
||||
bool fineta; /* absolute ETA flag */
|
||||
bool rate; /* rate counter flag */
|
||||
bool average_rate; /* average rate counter flag */
|
||||
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 */
|
||||
size_t buffer_size; /* buffer size, in bytes (0=default) */
|
||||
off_t size; /* total size of data */
|
||||
double interval; /* interval between updates */
|
||||
unsigned int width; /* screen width */
|
||||
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 */
|
||||
char name[256]; /* flawfinder: ignore */
|
||||
char format[256]; /* flawfinder: ignore */
|
||||
char extra_display[256]; /* flawfinder: ignore */
|
||||
};
|
||||
|
||||
/*
|
||||
* flawfinder rationale: name, format, and extra_display are always
|
||||
* explicitly zeroed and bounded to one less than their size so they are
|
||||
* always \0 terminated.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Return a stream pointer, and populate the filename buffer, for a control
|
||||
* file associated with a particular process ID; it will be opened for
|
||||
* writing if "sender" is true. Returns NULL on error.
|
||||
*/
|
||||
/*@null@ */
|
||||
/*@dependent@ */
|
||||
static FILE *pv__control_file(char *filename, size_t bufsize, pid_t control_pid, bool sender)
|
||||
{
|
||||
int open_flags, open_mode, control_fd;
|
||||
/*@dependent@ */ FILE *control_fptr = NULL;
|
||||
|
||||
open_flags = O_RDONLY;
|
||||
#ifdef O_NOFOLLOW
|
||||
open_flags += O_NOFOLLOW;
|
||||
#endif
|
||||
if (sender)
|
||||
open_flags = O_WRONLY | O_CREAT | O_EXCL;
|
||||
|
||||
open_mode = 0644;
|
||||
|
||||
(void) pv_snprintf(filename, bufsize, "/run/user/%lu/pv.remote.%lu", (unsigned long) geteuid(),
|
||||
(unsigned long) control_pid);
|
||||
control_fd = open(filename, open_flags, open_mode); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* If /run/user/<uid> wasn't usable, try $HOME/.pv instead.
|
||||
*/
|
||||
if (control_fd < 0) {
|
||||
char *home_dir;
|
||||
|
||||
home_dir = getenv("HOME"); /* flawfinder: ignore */
|
||||
if (NULL == home_dir)
|
||||
return NULL;
|
||||
if ('\0' == home_dir[0])
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* flawfinder rationale: null and zero-size values are
|
||||
* rejected, and the destination buffer is bounded.
|
||||
*/
|
||||
|
||||
(void) pv_snprintf(filename, bufsize, "%s/.pv/remote.%lu", home_dir, (unsigned long) control_pid);
|
||||
control_fd = open(filename, open_flags, open_mode); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* If the open failed, try creating the $HOME/.pv directory
|
||||
* first.
|
||||
*/
|
||||
if (control_fd < 0) {
|
||||
(void) pv_snprintf(filename, bufsize, "%s/.pv", home_dir);
|
||||
(void) mkdir(filename, 0700);
|
||||
/* In case of weird umask, explicitly chmod the dir. */
|
||||
(void) chmod(filename, 0700); /* flawfinder: ignore */
|
||||
(void) pv_snprintf(filename, bufsize, "%s/.pv/remote.%lu", home_dir,
|
||||
(unsigned long) control_pid);
|
||||
control_fd = open(filename, open_flags, open_mode); /* flawfinder: ignore */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
if (control_fd < 0)
|
||||
return NULL;
|
||||
|
||||
debug("%s: %s", "control filename", filename);
|
||||
|
||||
control_fptr = fdopen(control_fd, sender ? "wb" : "rb");
|
||||
|
||||
return control_fptr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the options of a remote process by writing them to a file, sending a
|
||||
* signal to the receiving process, and waiting for the message to be
|
||||
* consumed by the remote process.
|
||||
*
|
||||
* Returns nonzero on error.
|
||||
*/
|
||||
int pv_remote_set(opts_t opts, pvstate_t state)
|
||||
{
|
||||
char control_filename[4096]; /* flawfinder: ignore */
|
||||
FILE *control_fptr;
|
||||
struct remote_msg msgbuf;
|
||||
pid_t signal_sender;
|
||||
long timeout;
|
||||
bool received;
|
||||
|
||||
/*
|
||||
* flawfinder rationale: buffer is large enough, explicitly zeroed,
|
||||
* and always bounded properly as we are only writing to it with
|
||||
* pv_snprintf().
|
||||
*/
|
||||
|
||||
/*
|
||||
* Check that the remote process exists.
|
||||
*/
|
||||
if (kill((pid_t) (opts->remote), 0) != 0) {
|
||||
pv_error("%u: %s", opts->remote, strerror(errno));
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure parameters are within sensible bounds.
|
||||
*/
|
||||
if (opts->width < 1)
|
||||
opts->width = 80;
|
||||
if (opts->height < 1)
|
||||
opts->height = 25;
|
||||
if (opts->width > 999999)
|
||||
opts->width = 999999;
|
||||
if (opts->height > 999999)
|
||||
opts->height = 999999;
|
||||
if ((opts->interval > 0) && (opts->interval < 0.1))
|
||||
opts->interval = 0.1;
|
||||
if (opts->interval > 600)
|
||||
opts->interval = 600;
|
||||
|
||||
/*
|
||||
* Copy parameters into message buffer.
|
||||
*/
|
||||
memset(&msgbuf, 0, sizeof(msgbuf));
|
||||
msgbuf.progress = opts->progress;
|
||||
msgbuf.timer = opts->timer;
|
||||
msgbuf.eta = opts->eta;
|
||||
msgbuf.fineta = opts->fineta;
|
||||
msgbuf.rate = opts->rate;
|
||||
msgbuf.average_rate = opts->average_rate;
|
||||
msgbuf.bytes = opts->bytes;
|
||||
msgbuf.bufpercent = opts->bufpercent;
|
||||
msgbuf.lastwritten = opts->lastwritten;
|
||||
msgbuf.rate_limit = opts->rate_limit;
|
||||
msgbuf.buffer_size = opts->buffer_size;
|
||||
msgbuf.size = opts->size;
|
||||
msgbuf.interval = opts->interval;
|
||||
msgbuf.width = opts->width;
|
||||
msgbuf.height = opts->height;
|
||||
msgbuf.width_set_manually = opts->width_set_manually;
|
||||
msgbuf.height_set_manually = opts->height_set_manually;
|
||||
|
||||
if (opts->name != NULL) {
|
||||
strncpy(msgbuf.name, opts->name, sizeof(msgbuf.name) - 1); /* flawfinder: ignore */
|
||||
}
|
||||
if (opts->format != NULL) {
|
||||
strncpy(msgbuf.format, opts->format, sizeof(msgbuf.format) - 1); /* flawfinder: ignore */
|
||||
}
|
||||
if (opts->extra_display != NULL) {
|
||||
strncpy(msgbuf.extra_display, opts->extra_display, sizeof(msgbuf.extra_display) - 1); /* flawfinder: ignore */
|
||||
}
|
||||
|
||||
/*
|
||||
* flawfinder rationale: name, format, and extra_display are
|
||||
* explicitly bounded to 1 less than the size of their buffer and
|
||||
* the buffer is \0 terminated by memset() earlier.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get the filename and file stream to use for remote control.
|
||||
*/
|
||||
memset(control_filename, 0, sizeof(control_filename));
|
||||
control_fptr = pv__control_file(control_filename, sizeof(control_filename), (pid_t) getpid(), true);
|
||||
if (NULL == control_fptr) {
|
||||
pv_error("%s", strerror(errno));
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the message buffer to the remote control file, and close
|
||||
* it.
|
||||
*/
|
||||
if (1 != fwrite(&msgbuf, sizeof(msgbuf), 1, control_fptr)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
(void) fclose(control_fptr);
|
||||
(void) remove(control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
if (0 != fclose(control_fptr)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
(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.
|
||||
*/
|
||||
signal_sender = 0;
|
||||
(void) pv_sigusr2_received(state, &signal_sender);
|
||||
if (kill((pid_t) (opts->remote), SIGUSR2) != 0) {
|
||||
pv_error("%u: %s", opts->remote, strerror(errno));
|
||||
(void) remove(control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
debug("%s", "message sent");
|
||||
|
||||
/*
|
||||
* Wait for a signal from the remote process to say it has received
|
||||
* the message.
|
||||
*/
|
||||
|
||||
timeout = 1100000;
|
||||
received = false;
|
||||
|
||||
while (timeout > 10000 && !received) {
|
||||
struct timeval tv;
|
||||
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000;
|
||||
/*@-nullpass@ *//* splint: NULL is OK with select() */
|
||||
(void) select(0, NULL, NULL, NULL, &tv);
|
||||
/*@+nullpass@ */
|
||||
timeout -= 10000;
|
||||
|
||||
if (pv_sigusr2_received(state, &signal_sender)) {
|
||||
if (signal_sender == opts->remote) {
|
||||
debug("%s", "message received");
|
||||
received = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the remote control file.
|
||||
*/
|
||||
if (0 != remove(control_filename)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 if the message was received.
|
||||
*/
|
||||
if (received)
|
||||
return 0;
|
||||
|
||||
/*@-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.
|
||||
*/
|
||||
pv_error("%u: %s", opts->remote, _("message not received"));
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
/*@+mustfreefresh @ */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check for a remote control message and, if there is one, replace the
|
||||
* current process's options with those being passed in.
|
||||
*
|
||||
* NB relies on pv_state_set_format() causing the output format to be
|
||||
* reparsed.
|
||||
*
|
||||
* Returns true if something was received, false otherwise.
|
||||
*/
|
||||
bool pv_remote_check(pvstate_t state)
|
||||
{
|
||||
pid_t signal_sender;
|
||||
char control_filename[4096]; /* flawfinder: ignore */
|
||||
FILE *control_fptr;
|
||||
struct remote_msg msgbuf;
|
||||
|
||||
/* flawfinder rationale: as above. */
|
||||
|
||||
/*
|
||||
* Return early if a SIGUSR2 signal has not been received.
|
||||
*/
|
||||
signal_sender = 0;
|
||||
if (!pv_sigusr2_received(state, &signal_sender))
|
||||
return false;
|
||||
|
||||
memset(control_filename, 0, sizeof(control_filename));
|
||||
control_fptr = pv__control_file(control_filename, sizeof(control_filename), signal_sender, false);
|
||||
if (NULL == control_fptr) {
|
||||
pv_error("%s: %s", control_filename, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the message buffer from the remote control file, and close
|
||||
* it.
|
||||
*/
|
||||
if (1 != fread(&msgbuf, sizeof(msgbuf), 1, control_fptr)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
(void) fclose(control_fptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 != fclose(control_fptr)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a SIGUSR2 signal to the sending process, to tell it the
|
||||
* message has been received.
|
||||
*/
|
||||
if (kill(signal_sender, SIGUSR2) != 0) {
|
||||
debug("%u: %s", signal_sender, strerror(errno));
|
||||
}
|
||||
|
||||
debug("%s", "received remote message");
|
||||
|
||||
pv_state_format_string_set(state, NULL);
|
||||
pv_state_name_set(state, NULL);
|
||||
pv_state_extra_display_set(state, NULL);
|
||||
|
||||
msgbuf.name[sizeof(msgbuf.name) - 1] = '\0';
|
||||
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);
|
||||
|
||||
if (msgbuf.rate_limit > 0)
|
||||
pv_state_rate_limit_set(state, msgbuf.rate_limit);
|
||||
if (msgbuf.buffer_size > 0) {
|
||||
pv_state_target_buffer_size_set(state, msgbuf.buffer_size);
|
||||
}
|
||||
if (msgbuf.size > 0)
|
||||
pv_state_size_set(state, msgbuf.size);
|
||||
if (msgbuf.interval > 0)
|
||||
pv_state_interval_set(state, msgbuf.interval);
|
||||
if (msgbuf.width > 0 && msgbuf.width_set_manually)
|
||||
pv_state_width_set(state, msgbuf.width, msgbuf.width_set_manually);
|
||||
if (msgbuf.height > 0 && msgbuf.height_set_manually)
|
||||
pv_state_height_set(state, msgbuf.height, msgbuf.height_set_manually);
|
||||
if (msgbuf.format[0] != '\0')
|
||||
pv_state_format_string_set(state, msgbuf.format);
|
||||
if (msgbuf.extra_display[0] != '\0')
|
||||
pv_state_extra_display_set(state, msgbuf.extra_display);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialise remote message reception handling.
|
||||
*/
|
||||
void pv_remote_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Clean up after remote message reception handling.
|
||||
*/
|
||||
void pv_remote_fini(void)
|
||||
{
|
||||
}
|
||||
|
||||
#else /* !PV_REMOTE_CONTROL */
|
||||
|
||||
/*
|
||||
* Dummy stubs for remote control when we don't have PV_REMOTE_CONTROL.
|
||||
*/
|
||||
void pv_remote_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void pv_remote_check( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
{
|
||||
}
|
||||
|
||||
void pv_remote_fini(void)
|
||||
{
|
||||
}
|
||||
|
||||
int pv_remote_set( /*@unused@ */
|
||||
__attribute__((unused)) opts_t opts, /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
{
|
||||
/*@-mustfreefresh@ *//* splint - see above */
|
||||
fprintf(stderr, "%s\n", _("SA_SIGINFO not supported on this system"));
|
||||
/*@+mustfreefresh@ */
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
#endif /* SA_SIGINFO */
|
||||
@@ -464,3 +464,86 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
/*@+onlytrans@ */
|
||||
/*@+observertrans@ */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return a stream pointer, and populate the filename buffer, for a control
|
||||
* file associated with a particular process ID, for the given signal
|
||||
* number; it will be opened for writing if "sender" is true. Returns NULL
|
||||
* on error.
|
||||
*/
|
||||
/*@null@ */
|
||||
/*@dependent@ */
|
||||
FILE *pv_open_controlfile(char *filename, size_t bufsize, pid_t control_pid, int signum, bool sender)
|
||||
{
|
||||
int open_flags, open_mode, control_fd;
|
||||
/*@dependent@ */ FILE *control_fptr = NULL;
|
||||
|
||||
open_flags = O_RDONLY;
|
||||
#ifdef O_NOFOLLOW
|
||||
open_flags += O_NOFOLLOW;
|
||||
#endif
|
||||
if (sender)
|
||||
open_flags = O_WRONLY | O_CREAT | O_EXCL;
|
||||
|
||||
open_mode = 0644;
|
||||
|
||||
(void) pv_snprintf(filename, bufsize, "/run/user/%lu/pv.remote.%d.%lu", (unsigned long) geteuid(), signum,
|
||||
(unsigned long) control_pid);
|
||||
control_fd = open(filename, open_flags, open_mode); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* If /run/user/<uid> wasn't usable, try $HOME/.pv instead.
|
||||
*/
|
||||
if (control_fd < 0) {
|
||||
char *home_dir;
|
||||
|
||||
home_dir = getenv("HOME"); /* flawfinder: ignore */
|
||||
if (NULL == home_dir)
|
||||
return NULL;
|
||||
if ('\0' == home_dir[0])
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* flawfinder rationale: null and zero-size values are
|
||||
* rejected, and the destination buffer is bounded.
|
||||
*/
|
||||
|
||||
(void) pv_snprintf(filename, bufsize, "%s/.pv/remote.%d.%lu", home_dir, signum,
|
||||
(unsigned long) control_pid);
|
||||
control_fd = open(filename, open_flags, open_mode); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* If the open failed, try creating the $HOME/.pv directory
|
||||
* first.
|
||||
*/
|
||||
if (control_fd < 0) {
|
||||
(void) pv_snprintf(filename, bufsize, "%s/.pv", home_dir);
|
||||
(void) mkdir(filename, 0700);
|
||||
/* In case of weird umask, explicitly chmod the dir. */
|
||||
(void) chmod(filename, 0700); /* flawfinder: ignore */
|
||||
(void) pv_snprintf(filename, bufsize, "%s/.pv/remote.%d.%lu", home_dir, signum,
|
||||
(unsigned long) control_pid);
|
||||
control_fd = open(filename, open_flags, open_mode); /* flawfinder: ignore */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
if (control_fd < 0)
|
||||
return NULL;
|
||||
|
||||
debug("%s: %s", "control filename", filename);
|
||||
|
||||
control_fptr = fdopen(control_fd, sender ? "wb" : "rb");
|
||||
|
||||
return control_fptr;
|
||||
}
|
||||
|
||||
+354
-199
@@ -28,6 +28,8 @@
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
int pv_remote_transferstate_fetch(pvstate_t, pid_t, /*@null@ */ off_t *, bool);
|
||||
|
||||
|
||||
#if HAVE_SQRTL
|
||||
#else
|
||||
@@ -51,6 +53,119 @@ static long ldsqrt(long double value)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* If the flag is set to say that a terminal resize signal was received,
|
||||
* clear the flag and resize the display, and return true.
|
||||
*/
|
||||
static bool pv__resize_display_on_signal(pvstate_t state)
|
||||
{
|
||||
unsigned int new_width, new_height;
|
||||
|
||||
if (0 == state->flags.terminal_resized)
|
||||
return false;
|
||||
|
||||
state->flags.terminal_resized = 0;
|
||||
|
||||
new_width = (unsigned int) (state->control.width);
|
||||
new_height = state->control.height;
|
||||
pv_screensize(&new_width, &new_height);
|
||||
|
||||
if (new_width > PVDISPLAY_WIDTH_MAX)
|
||||
new_width = PVDISPLAY_WIDTH_MAX;
|
||||
if (!state->control.width_set_manually)
|
||||
state->control.width = (pvdisplay_width_t) new_width;
|
||||
if (!state->control.height_set_manually)
|
||||
state->control.height = new_height;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Calculate and display the transfer statistics at the end of the transfer,
|
||||
* if stats are enabled and any measurements were taken.
|
||||
*/
|
||||
static void pv__show_stats(pvstate_t state)
|
||||
{
|
||||
if (!state->control.show_stats)
|
||||
return;
|
||||
|
||||
if (state->calc.measurements_taken > 0) {
|
||||
char stats_buf[256]; /* flawfinder: ignore */
|
||||
long double rate_mean, rate_variance, rate_deviation;
|
||||
int stats_size;
|
||||
|
||||
/* flawfinder: made safe by use of pv_snprintf() */
|
||||
|
||||
rate_mean = state->calc.rate_sum / ((long double) (state->calc.measurements_taken));
|
||||
rate_variance =
|
||||
(state->calc.ratesquared_sum / ((long double) (state->calc.measurements_taken))) -
|
||||
(rate_mean * rate_mean);
|
||||
#if HAVE_SQRTL
|
||||
rate_deviation = sqrtl(rate_variance);
|
||||
#else
|
||||
rate_deviation = ldsqrt(rate_variance);
|
||||
#endif
|
||||
|
||||
debug("%s: %ld", "measurements taken", state->calc.measurements_taken);
|
||||
debug("%s: %.3Lf", "rate_sum", state->calc.rate_sum);
|
||||
debug("%s: %.3Lf", "ratesquared_sum", state->calc.ratesquared_sum);
|
||||
debug("%s: %.3Lf", "rate_mean", rate_mean);
|
||||
debug("%s: %.3Lf", "rate_variance", rate_variance);
|
||||
debug("%s: %.3Lf", "rate_deviation", rate_deviation);
|
||||
|
||||
memset(stats_buf, 0, sizeof(stats_buf));
|
||||
stats_size =
|
||||
pv_snprintf(stats_buf, sizeof(stats_buf), "%s = %.3Lf/%.3Lf/%.3Lf/%.3Lf %s\n",
|
||||
_("rate min/avg/max/mdev"), state->calc.rate_min, rate_mean, state->calc.rate_max,
|
||||
rate_deviation, state->control.bits ? _("b/s") : _("B/s"));
|
||||
|
||||
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) {
|
||||
char msg_buf[256]; /* flawfinder: ignore */
|
||||
int msg_size;
|
||||
|
||||
/* 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"));
|
||||
|
||||
if (msg_size > 0 && msg_size < (int) (sizeof(msg_buf)))
|
||||
pv_tty_write(&(state->flags), msg_buf, (size_t) msg_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the elapsed transfer time, given the time the transfer loop
|
||||
* started, the current time, and the total time spent stopped.
|
||||
*/
|
||||
static long double pv__elapsed_transfer_time(const struct timespec *loop_start_time,
|
||||
const struct timespec *current_time,
|
||||
const struct timespec *total_stoppage_time)
|
||||
{
|
||||
struct timespec effective_start_time, transfer_elapsed;
|
||||
|
||||
memset(&effective_start_time, 0, sizeof(effective_start_time));
|
||||
memset(&transfer_elapsed, 0, sizeof(transfer_elapsed));
|
||||
|
||||
/*
|
||||
* Calculate the effective start time: the time we actually started,
|
||||
* plus the total time we spent stopped.
|
||||
*/
|
||||
pv_elapsedtime_add(&effective_start_time, loop_start_time, total_stoppage_time);
|
||||
|
||||
/*
|
||||
* Now get the effective elapsed transfer time - current time minus
|
||||
* effective start time.
|
||||
*/
|
||||
pv_elapsedtime_subtract(&transfer_elapsed, current_time, &effective_start_time);
|
||||
|
||||
return pv_elapsedtime_seconds(&transfer_elapsed);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Pipe data from a list of files to standard output, giving information
|
||||
* about the transfer on standard error according to the given options.
|
||||
@@ -65,7 +180,7 @@ int pv_main_loop(pvstate_t state)
|
||||
long double target;
|
||||
bool eof_in, eof_out, final_update;
|
||||
struct timespec start_time, next_update, next_ratecheck, cur_time;
|
||||
struct timespec init_time, next_remotecheck, transfer_elapsed;
|
||||
struct timespec next_remotecheck;
|
||||
int input_fd, output_fd;
|
||||
unsigned int file_idx;
|
||||
bool output_is_pipe;
|
||||
@@ -216,7 +331,7 @@ int pv_main_loop(pvstate_t state)
|
||||
cansend = 0;
|
||||
|
||||
/*
|
||||
* Check for remote messages from -R every short while.
|
||||
* Check for remote messages from -R, -Q every short while.
|
||||
*/
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_remotecheck) > 0) {
|
||||
(void) pv_remote_check(state);
|
||||
@@ -411,13 +526,6 @@ int pv_main_loop(pvstate_t state)
|
||||
pv_nanosleep(50000000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Just go round the loop again if there's no display and
|
||||
* we're not reporting statistics.
|
||||
*/
|
||||
if (state->control.no_display && !state->control.show_stats)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If -W was given, we don't output anything until we have
|
||||
* written a byte (or line, in line mode), at which point
|
||||
@@ -434,7 +542,7 @@ int pv_main_loop(pvstate_t state)
|
||||
continue;
|
||||
}
|
||||
|
||||
state->control.wait = 0;
|
||||
state->control.wait = false;
|
||||
|
||||
/*
|
||||
* Reset the timer offset counter now that data
|
||||
@@ -448,7 +556,7 @@ int pv_main_loop(pvstate_t state)
|
||||
*/
|
||||
pv_sig_nopause();
|
||||
pv_elapsedtime_read(&start_time);
|
||||
pv_elapsedtime_zero(&(state->signal.toffset));
|
||||
pv_elapsedtime_zero(&(state->signal.total_stoppage_time));
|
||||
pv_sig_allowpause();
|
||||
|
||||
/*
|
||||
@@ -459,6 +567,18 @@ int pv_main_loop(pvstate_t state)
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval));
|
||||
}
|
||||
|
||||
/* Calculate the elapsed transfer time. */
|
||||
state->transfer.elapsed_seconds =
|
||||
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.
|
||||
*/
|
||||
if (state->control.no_display && !state->control.show_stats) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Restart the loop if it's not time to update the display. */
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_update) < 0) {
|
||||
continue;
|
||||
@@ -470,39 +590,8 @@ int pv_main_loop(pvstate_t state)
|
||||
if (pv_elapsedtime_compare(&next_update, &cur_time) < 0)
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
|
||||
/*
|
||||
* Calculate the effective start time: the time we actually
|
||||
* started, plus the total time we spent stopped.
|
||||
*/
|
||||
memset(&init_time, 0, sizeof(init_time));
|
||||
pv_elapsedtime_add(&init_time, &start_time, &(state->signal.toffset));
|
||||
|
||||
/*
|
||||
* Now get the effective elapsed transfer time - current
|
||||
* time minus effective start time.
|
||||
*/
|
||||
memset(&transfer_elapsed, 0, sizeof(transfer_elapsed));
|
||||
pv_elapsedtime_subtract(&transfer_elapsed, &cur_time, &init_time);
|
||||
|
||||
state->transfer.elapsed_seconds = pv_elapsedtime_seconds(&transfer_elapsed);
|
||||
|
||||
/* Resize the display, if a resize signal was received. */
|
||||
if (1 == state->flags.terminal_resized) {
|
||||
unsigned int new_width, new_height;
|
||||
|
||||
state->flags.terminal_resized = 0;
|
||||
|
||||
new_width = (unsigned int) (state->control.width);
|
||||
new_height = state->control.height;
|
||||
pv_screensize(&new_width, &new_height);
|
||||
|
||||
if (new_width > PVDISPLAY_WIDTH_MAX)
|
||||
new_width = PVDISPLAY_WIDTH_MAX;
|
||||
if (!state->control.width_set_manually)
|
||||
state->control.width = (pvdisplay_width_t) new_width;
|
||||
if (!state->control.height_set_manually)
|
||||
state->control.height = new_height;
|
||||
}
|
||||
(void) pv__resize_display_on_signal(state);
|
||||
|
||||
if (state->control.no_display) {
|
||||
/* If there's no display, calculate rate for the statistics. */
|
||||
@@ -534,50 +623,7 @@ int pv_main_loop(pvstate_t state)
|
||||
(void) close(input_fd);
|
||||
|
||||
/* Calculate and display the transfer statistics. */
|
||||
if (state->control.show_stats && state->calc.measurements_taken > 0) {
|
||||
char stats_buf[256]; /* flawfinder: ignore */
|
||||
long double rate_mean, rate_variance, rate_deviation;
|
||||
int stats_size;
|
||||
|
||||
/* flawfinder: made safe by use of pv_snprintf() */
|
||||
|
||||
rate_mean = state->calc.rate_sum / ((long double) (state->calc.measurements_taken));
|
||||
rate_variance =
|
||||
(state->calc.ratesquared_sum / ((long double) (state->calc.measurements_taken))) -
|
||||
(rate_mean * rate_mean);
|
||||
#if HAVE_SQRTL
|
||||
rate_deviation = sqrtl(rate_variance);
|
||||
#else
|
||||
rate_deviation = ldsqrt(rate_variance);
|
||||
#endif
|
||||
|
||||
debug("%s: %ld", "measurements taken", state->calc.measurements_taken);
|
||||
debug("%s: %.3Lf", "rate_sum", state->calc.rate_sum);
|
||||
debug("%s: %.3Lf", "ratesquared_sum", state->calc.ratesquared_sum);
|
||||
debug("%s: %.3Lf", "rate_mean", rate_mean);
|
||||
debug("%s: %.3Lf", "rate_variance", rate_variance);
|
||||
debug("%s: %.3Lf", "rate_deviation", rate_deviation);
|
||||
|
||||
memset(stats_buf, 0, sizeof(stats_buf));
|
||||
stats_size =
|
||||
pv_snprintf(stats_buf, sizeof(stats_buf), "%s = %.3Lf/%.3Lf/%.3Lf/%.3Lf %s\n",
|
||||
_("rate min/avg/max/mdev"), state->calc.rate_min, rate_mean, state->calc.rate_max,
|
||||
rate_deviation, state->control.bits ? _("b/s") : _("B/s"));
|
||||
|
||||
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) {
|
||||
char msg_buf[256]; /* flawfinder: ignore */
|
||||
int msg_size;
|
||||
|
||||
/* 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"));
|
||||
|
||||
if (msg_size > 0 && msg_size < (int) (sizeof(msg_buf)))
|
||||
pv_tty_write(&(state->flags), msg_buf, (size_t) msg_size);
|
||||
}
|
||||
pv__show_stats(state);
|
||||
|
||||
return state->status.exit_status;
|
||||
}
|
||||
@@ -648,9 +694,7 @@ static void pv_watchfd_update_format_string(pvstate_t state)
|
||||
/* If there's nothing to watch, do nothing. */
|
||||
if (state->watchfd.count < 1)
|
||||
return;
|
||||
if (NULL == state->watchfd.pid)
|
||||
return;
|
||||
if (NULL == state->watchfd.fd)
|
||||
if (NULL == state->watchfd.watching)
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -666,7 +710,7 @@ static void pv_watchfd_update_format_string(pvstate_t state)
|
||||
|
||||
memset(new_format_string, 0, sizeof(new_format_string));
|
||||
|
||||
if (state->watchfd.count > 1 || -1 == state->watchfd.fd[0]) {
|
||||
if (state->watchfd.count > 1 || -1 == state->watchfd.watching[0].fd) {
|
||||
/* Watching more than one single FD; need %N. */
|
||||
if (!format_contains_name(original_format_string)) {
|
||||
(void) pv_snprintf(new_format_string, sizeof(new_format_string), "%%N %s",
|
||||
@@ -707,27 +751,29 @@ static void pv_watchfd_update_format_string(pvstate_t state)
|
||||
*/
|
||||
int pv_watchfd_loop(pvstate_t state)
|
||||
{
|
||||
struct { /* details for each PID:FD specified by operator */
|
||||
pid_t pid; /* watched PID */
|
||||
int fd; /* watched fd, or -1 for all */
|
||||
pvwatchfd_t info_array; /* watch information for each fd */
|
||||
int array_length; /* length of watch info array */
|
||||
/* TODO: "finished but not time to stop showing" flag for #81 */
|
||||
bool finished; /* "PID:FD": fd closed; or PID gone */
|
||||
} *watching;
|
||||
struct pvwatcheditem_s *watching;
|
||||
unsigned int watch_idx;
|
||||
bool all_watching_finished;
|
||||
struct timespec next_update, next_remotecheck, cur_time;
|
||||
int prev_displayed_lines, blank_lines;
|
||||
|
||||
/*
|
||||
* In each watching[].info_array[] fd info item, once its "watch_fd"
|
||||
* is closed, its "closed" flag is set to true and its "end_time" to
|
||||
* now. It isn't marked "unused" until its "end_time" is long
|
||||
* enough ago, so the information is held on-screen for a short
|
||||
* while after the fd closes or the PID exits (#81).
|
||||
*/
|
||||
|
||||
/* If there's nothing to watch, do nothing at all. */
|
||||
if (state->watchfd.count < 1)
|
||||
return 0;
|
||||
if (NULL == state->watchfd.pid)
|
||||
return PV_ERROREXIT_MEMORY;
|
||||
if (NULL == state->watchfd.fd)
|
||||
if (NULL == state->watchfd.watching)
|
||||
return PV_ERROREXIT_MEMORY;
|
||||
|
||||
/* Local alias for less cumbersome access. */
|
||||
watching = state->watchfd.watching;
|
||||
|
||||
/*
|
||||
* Make sure there's no name set.
|
||||
*/
|
||||
@@ -739,16 +785,6 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
/* Adjust the format string so PID:FD or FD prefixes are shown. */
|
||||
pv_watchfd_update_format_string(state);
|
||||
|
||||
/*
|
||||
* Allocate the watching array.
|
||||
*/
|
||||
watching = malloc(state->watchfd.count * sizeof(*watching));
|
||||
if (NULL == watching) {
|
||||
pv_error("%s: %s", _("buffer allocation failed"), strerror(errno));
|
||||
return PV_ERROREXIT_MEMORY;
|
||||
}
|
||||
memset(watching, 0, state->watchfd.count * sizeof(*watching));
|
||||
|
||||
/*
|
||||
* Populate the watching array. In the process of doing so, raise
|
||||
* errors if any of the initially specified PIDs or PID:FD pairs
|
||||
@@ -757,8 +793,6 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
for (watch_idx = 0; watch_idx < state->watchfd.count; watch_idx++) {
|
||||
int rc;
|
||||
|
||||
watching[watch_idx].pid = state->watchfd.pid[watch_idx];
|
||||
watching[watch_idx].fd = state->watchfd.fd[watch_idx];
|
||||
watching[watch_idx].info_array = NULL;
|
||||
watching[watch_idx].array_length = 0;
|
||||
watching[watch_idx].finished = false;
|
||||
@@ -796,7 +830,7 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
/* Scan failed - mark as finished. */
|
||||
state->status.exit_status |= PV_ERROREXIT_ACCESS;
|
||||
watching[watch_idx].finished = true;
|
||||
} else if (0 == watching[watch_idx].array_length) {
|
||||
} else if ((0 == watching[watch_idx].array_length) || (NULL == watching[watch_idx].info_array)) {
|
||||
/* FD not found - error, mark as finished. */
|
||||
pv_error("%s %u: %s %d: %s",
|
||||
_("pid"), watching[watch_idx].pid, _("fd"), watching[watch_idx].fd,
|
||||
@@ -850,7 +884,7 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
int displayed_lines;
|
||||
bool terminal_resized;
|
||||
|
||||
/* Check for remote messages from -R every short while. */
|
||||
/* Check for remote messages from -R, -Q every short while. */
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_remotecheck) > 0) {
|
||||
if (pv_remote_check(state)) {
|
||||
/* Message received - ensure format has %N. */
|
||||
@@ -891,24 +925,7 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
* to trigger a name reset and display reparse for every FD
|
||||
* output line, to inherit the size change.
|
||||
*/
|
||||
terminal_resized = false;
|
||||
if (1 == state->flags.terminal_resized) {
|
||||
unsigned int new_width, new_height;
|
||||
|
||||
state->flags.terminal_resized = 0;
|
||||
|
||||
new_width = (unsigned int) (state->control.width);
|
||||
new_height = state->control.height;
|
||||
pv_screensize(&new_width, &new_height);
|
||||
|
||||
if (new_width > PVDISPLAY_WIDTH_MAX)
|
||||
new_width = PVDISPLAY_WIDTH_MAX;
|
||||
|
||||
state->control.width = (pvdisplay_width_t) new_width;
|
||||
state->control.height = new_height;
|
||||
|
||||
terminal_resized = true;
|
||||
}
|
||||
terminal_resized = pv__resize_display_on_signal(state);
|
||||
|
||||
/*
|
||||
* Run through each watched item.
|
||||
@@ -933,10 +950,9 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
if (rc != 0) {
|
||||
/*
|
||||
* PID now inaccessible - mark it as
|
||||
* finished and skip over it.
|
||||
* finished.
|
||||
*/
|
||||
watching[watch_idx].finished = true;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
@@ -959,7 +975,6 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
NULL != watching[watch_idx].info_array && info_idx < watching[watch_idx].array_length;
|
||||
info_idx++) {
|
||||
off_t position_now;
|
||||
struct timespec init_time, transfer_elapsed;
|
||||
pvwatchfd_t info_item = &(watching[watch_idx].info_array[info_idx]);
|
||||
|
||||
/* Skip unused array entries. */
|
||||
@@ -976,7 +991,8 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
* changed.
|
||||
*/
|
||||
if (pv_watchfd_changed(info_item)) {
|
||||
debug("%s %d: %s", "fd", info_item->watch_fd, "removing");
|
||||
debug("%s %d: %s", "fd", info_item->watch_fd,
|
||||
"non-displayable, and has changed - removing");
|
||||
info_item->unused = true;
|
||||
info_item->displayable = false;
|
||||
pv_freecontents_watchfd(info_item);
|
||||
@@ -994,34 +1010,65 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
* changed.
|
||||
*/
|
||||
|
||||
position_now = pv_watchfd_position(info_item);
|
||||
position_now = -1;
|
||||
|
||||
if (position_now < 0) {
|
||||
debug("%s %d: %s", "fd", info_item->watch_fd, "removing");
|
||||
info_item->unused = true;
|
||||
info_item->displayable = false;
|
||||
pv_freecontents_watchfd(info_item);
|
||||
continue;
|
||||
if (info_item->closed) {
|
||||
/*
|
||||
* Closed fd - check how long since
|
||||
* it was closed.
|
||||
*/
|
||||
struct timespec time_since_closed;
|
||||
long double seconds_since_closed;
|
||||
|
||||
memset(&time_since_closed, 0, sizeof(time_since_closed));
|
||||
pv_elapsedtime_subtract(&time_since_closed, &cur_time, &(info_item->end_time));
|
||||
seconds_since_closed = pv_elapsedtime_seconds(&time_since_closed);
|
||||
|
||||
/* Closed for long enough - remove. */
|
||||
if (seconds_since_closed > state->control.interval) {
|
||||
debug("%s %d: %s (%Lf s)", "fd", info_item->watch_fd,
|
||||
"closed for long enough - removing", seconds_since_closed);
|
||||
info_item->unused = true;
|
||||
info_item->displayable = false;
|
||||
pv_freecontents_watchfd(info_item);
|
||||
continue;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Open fd - get its current
|
||||
* position.
|
||||
*/
|
||||
|
||||
position_now = pv_watchfd_position(info_item);
|
||||
|
||||
if (position_now < 0) {
|
||||
/*
|
||||
* The fd was closed - mark
|
||||
* as closed.
|
||||
*/
|
||||
debug("%s %d: %s", "fd", info_item->watch_fd, "marking as closed");
|
||||
pv_elapsedtime_copy(&(info_item->end_time), &cur_time);
|
||||
info_item->closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
info_item->position = position_now;
|
||||
|
||||
memset(&init_time, 0, sizeof(init_time));
|
||||
memset(&transfer_elapsed, 0, sizeof(transfer_elapsed));
|
||||
if (position_now >= 0) {
|
||||
/*
|
||||
* If the fd is still open and we
|
||||
* got its current position, update
|
||||
* its position and timers.
|
||||
*/
|
||||
info_item->position = position_now;
|
||||
info_item->transfer.elapsed_seconds =
|
||||
pv__elapsed_transfer_time(&(info_item->start_time), &cur_time,
|
||||
&(info_item->total_stoppage_time));
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the effective start time: the time we actually
|
||||
* started, plus the total time we spent stopped.
|
||||
* Now display the information about the fd.
|
||||
*/
|
||||
pv_elapsedtime_add(&init_time, &(info_item->start_time), &(state->signal.toffset));
|
||||
|
||||
/*
|
||||
* Now get the effective elapsed transfer time - current
|
||||
* time minus effective start time.
|
||||
*/
|
||||
pv_elapsedtime_subtract(&transfer_elapsed, &cur_time, &init_time);
|
||||
|
||||
info_item->transfer.elapsed_seconds = pv_elapsedtime_seconds(&transfer_elapsed);
|
||||
|
||||
if (displayed_lines > 0) {
|
||||
debug("%s", "adding newline");
|
||||
@@ -1030,15 +1077,15 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
|
||||
debug("%s %d, %s %d [%d/%d]: %Lf / %Ld", "pid", (int) (info_item->watch_pid), "fd",
|
||||
info_item->watch_fd, watch_idx, info_idx, info_item->transfer.elapsed_seconds,
|
||||
position_now);
|
||||
info_item->position);
|
||||
|
||||
if (terminal_resized) {
|
||||
pv_watchpid_setname(state, info_item);
|
||||
info_item->flags.reparse_display = 1;
|
||||
}
|
||||
|
||||
info_item->transfer.transferred = position_now;
|
||||
info_item->transfer.total_written = position_now;
|
||||
info_item->transfer.transferred = info_item->position;
|
||||
info_item->transfer.total_written = info_item->position;
|
||||
state->control.name = info_item->display_name;
|
||||
state->control.size = info_item->size;
|
||||
|
||||
@@ -1099,25 +1146,16 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
}
|
||||
}
|
||||
|
||||
if (!state->control.numeric)
|
||||
pv_tty_write(&(state->flags), "\n", 1);
|
||||
|
||||
/*
|
||||
* Clean up our displayed lines after the display loop.
|
||||
*/
|
||||
blank_lines = prev_displayed_lines;
|
||||
while (blank_lines > 0) {
|
||||
pvdisplay_width_t blank_count;
|
||||
for (blank_count = 0; blank_count < state->control.width; blank_count++)
|
||||
pv_tty_write(&(state->flags), " ", 1);
|
||||
pv_tty_write(&(state->flags), "\r", 1);
|
||||
blank_lines--;
|
||||
if (blank_lines > 0)
|
||||
if (!state->control.numeric) {
|
||||
/*
|
||||
* Move the cursor past the displayed lines, so the last
|
||||
* output stays on the screen and isn't overwritten by the
|
||||
* command prompt (#81).
|
||||
*/
|
||||
while (prev_displayed_lines > 0) {
|
||||
pv_tty_write(&(state->flags), "\n", 1);
|
||||
}
|
||||
while (prev_displayed_lines > 1) {
|
||||
pv_tty_write(&(state->flags), "\033[A", 3);
|
||||
prev_displayed_lines--;
|
||||
prev_displayed_lines--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1128,27 +1166,144 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
state->status.exit_status |= PV_ERROREXIT_SIGNAL;
|
||||
|
||||
end_pv_watchfd_loop:
|
||||
/* Free all allocated memory. */
|
||||
/*@-compdestroy@ */
|
||||
for (watch_idx = 0; NULL != watching && watch_idx < state->watchfd.count; watch_idx++) {
|
||||
int info_idx;
|
||||
if (NULL == watching[watch_idx].info_array)
|
||||
/* Free all allocated sub-structures. */
|
||||
pv_freecontents_watchfd_items(watching, state->watchfd.count);
|
||||
|
||||
return state->status.exit_status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Watch the progress of another pv process.
|
||||
*
|
||||
* Returns nonzero on error.
|
||||
*/
|
||||
int pv_query_loop(pvstate_t state, pid_t query)
|
||||
{
|
||||
struct timespec cur_time, next_remotecheck, next_update;
|
||||
|
||||
pv_crs_init(&(state->cursor), &(state->control), &(state->flags));
|
||||
|
||||
/*
|
||||
* NB transfer.total_written has been initialised by main().
|
||||
*/
|
||||
|
||||
state->display.initial_offset = 0;
|
||||
|
||||
memset(&cur_time, 0, sizeof(cur_time));
|
||||
memset(&next_remotecheck, 0, sizeof(next_remotecheck));
|
||||
memset(&next_update, 0, sizeof(next_update));
|
||||
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
pv_elapsedtime_copy(&next_remotecheck, &cur_time);
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
|
||||
if ((state->control.delay_start > 0)
|
||||
&& (state->control.delay_start > state->control.interval)) {
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.delay_start));
|
||||
} else {
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval));
|
||||
}
|
||||
|
||||
/*
|
||||
* Repeat until the queried process exits.
|
||||
*/
|
||||
|
||||
while (0 == kill(query, 0)) {
|
||||
|
||||
/*
|
||||
* Check for remote messages from -R, and run the query,
|
||||
* every short while.
|
||||
*/
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_remotecheck) > 0) {
|
||||
if (0 != pv_remote_transferstate_fetch(state, query, NULL, true))
|
||||
break;
|
||||
(void) pv_remote_check(state);
|
||||
pv_elapsedtime_add_nsec(&next_remotecheck, REMOTE_INTERVAL);
|
||||
/*
|
||||
* Set the next-remote-check time to now +
|
||||
* REMOTE_INTERVAL, if it's still in the past.
|
||||
*/
|
||||
if (pv_elapsedtime_compare(&next_update, &cur_time) < 0) {
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
pv_elapsedtime_add_nsec(&next_remotecheck, REMOTE_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (1 == state->flags.trigger_exit)
|
||||
break;
|
||||
|
||||
/* Now check the current time. */
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
|
||||
/*
|
||||
* Just go round the loop again if there's no display and
|
||||
* we're not reporting statistics.
|
||||
*/
|
||||
if (state->control.no_display && !state->control.show_stats) {
|
||||
pv_nanosleep(50000000);
|
||||
continue;
|
||||
for (info_idx = 0; info_idx < watching[watch_idx].array_length; info_idx++) {
|
||||
pv_freecontents_watchfd(&(watching[watch_idx].info_array[info_idx]));
|
||||
}
|
||||
free(watching[watch_idx].info_array);
|
||||
watching[watch_idx].info_array = NULL;
|
||||
watching[watch_idx].array_length = 0;
|
||||
|
||||
/*
|
||||
* If -W was given, we don't output anything until something
|
||||
* has been transferred.
|
||||
*/
|
||||
if (state->control.wait) {
|
||||
/* Restart the loop if nothing written yet. */
|
||||
if (state->transfer.transferred < 1) {
|
||||
pv_nanosleep(50000000);
|
||||
continue;
|
||||
}
|
||||
|
||||
state->control.wait = false;
|
||||
|
||||
/*
|
||||
* Start the display at the next interval.
|
||||
*/
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval));
|
||||
}
|
||||
|
||||
/* Restart the loop if it's not time to update the display. */
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_update) < 0) {
|
||||
pv_nanosleep(50000000);
|
||||
continue;
|
||||
}
|
||||
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval));
|
||||
|
||||
/* Set the "next update" time to now, if it's in the past. */
|
||||
if (pv_elapsedtime_compare(&next_update, &cur_time) < 0)
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
|
||||
/* Resize the display, if a resize signal was received. */
|
||||
(void) pv__resize_display_on_signal(state);
|
||||
|
||||
if (state->control.no_display) {
|
||||
/* If there's no display, calculate rate for the statistics. */
|
||||
pv_calculate_transfer_rate(&(state->calc), &(state->transfer), &(state->control),
|
||||
&(state->display), false);
|
||||
} else {
|
||||
/* Produce the display. */
|
||||
pv_display(&(state->status), &(state->control), &(state->flags), &(state->transfer),
|
||||
&(state->calc), &(state->cursor), &(state->display), &(state->extra_display), false);
|
||||
}
|
||||
}
|
||||
|
||||
if (state->control.cursor) {
|
||||
pv_crs_fini(&(state->cursor), &(state->control), &(state->flags));
|
||||
} else {
|
||||
if ((!state->control.numeric) && (!state->control.no_display)
|
||||
&& (state->display.output_produced))
|
||||
pv_tty_write(&(state->flags), "\n", 1);
|
||||
}
|
||||
free(watching);
|
||||
watching = NULL;
|
||||
|
||||
if (1 == state->flags.trigger_exit)
|
||||
state->status.exit_status |= PV_ERROREXIT_SIGNAL;
|
||||
|
||||
/* Calculate and display the transfer statistics. */
|
||||
pv__show_stats(state);
|
||||
|
||||
return state->status.exit_status;
|
||||
/*@+compdestroy @ */
|
||||
/*
|
||||
* splint warns that watching[].info_array->transfer.transfer_buffer
|
||||
* and other deep structures may not be deallocated and so leak
|
||||
* memory, but that's what pv_freecontents_watchfd() takes care of.
|
||||
*/
|
||||
}
|
||||
|
||||
+667
@@ -0,0 +1,667 @@
|
||||
/*
|
||||
* Remote-control and remote-query functions.
|
||||
*
|
||||
* Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023-2025 Andrew Wood
|
||||
*
|
||||
* License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "pv.h"
|
||||
#include "pv-internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef PV_REMOTE_CONTROL
|
||||
|
||||
/* Structure for transferring settings with --remote. */
|
||||
struct remote_msg {
|
||||
bool progress; /* progress bar flag */
|
||||
bool timer; /* timer flag */
|
||||
bool eta; /* ETA flag */
|
||||
bool fineta; /* absolute ETA flag */
|
||||
bool rate; /* rate counter flag */
|
||||
bool average_rate; /* average rate counter flag */
|
||||
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 */
|
||||
size_t buffer_size; /* buffer size, in bytes (0=default) */
|
||||
off_t size; /* total size of data */
|
||||
double interval; /* interval between updates */
|
||||
unsigned int width; /* screen width */
|
||||
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 */
|
||||
char name[256]; /* flawfinder: ignore */
|
||||
char format[256]; /* flawfinder: ignore */
|
||||
char extra_display[256]; /* flawfinder: ignore */
|
||||
};
|
||||
|
||||
/* Structure for transferring transfer state with --query. */
|
||||
struct query_msg {
|
||||
long double elapsed_seconds; /* from state.transfer */
|
||||
off_t transferred; /* from state.transfer */
|
||||
off_t size; /* from state.control */
|
||||
bool response; /* true if this is the response signal. */
|
||||
};
|
||||
|
||||
/*
|
||||
* flawfinder rationale: name, format, and extra_display are always
|
||||
* explicitly zeroed and bounded to one less than their size so they are
|
||||
* always \0 terminated.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Set the options of a remote process by writing them to a file, sending a
|
||||
* signal to the receiving process, and waiting for the message to be
|
||||
* consumed by the remote process.
|
||||
*
|
||||
* Returns nonzero on error.
|
||||
*/
|
||||
int pv_remote_set(pvstate_t state, pid_t remote)
|
||||
{
|
||||
char control_filename[4096]; /* flawfinder: ignore */
|
||||
FILE *control_fptr;
|
||||
struct remote_msg msgbuf;
|
||||
pid_t signal_sender;
|
||||
long timeout;
|
||||
bool received;
|
||||
|
||||
/*
|
||||
* flawfinder rationale: buffer is large enough, explicitly zeroed,
|
||||
* and always bounded properly as we are only writing to it with
|
||||
* pv_snprintf().
|
||||
*/
|
||||
|
||||
/*
|
||||
* Check that the remote process exists.
|
||||
*/
|
||||
if (kill((pid_t) (remote), 0) != 0) {
|
||||
pv_error("%u: %s", remote, strerror(errno));
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy parameters into message buffer.
|
||||
*/
|
||||
memset(&msgbuf, 0, sizeof(msgbuf));
|
||||
msgbuf.progress = state->control.format_option.progress;
|
||||
msgbuf.timer = state->control.format_option.timer;
|
||||
msgbuf.eta = state->control.format_option.eta;
|
||||
msgbuf.fineta = state->control.format_option.fineta;
|
||||
msgbuf.rate = state->control.format_option.rate;
|
||||
msgbuf.average_rate = state->control.format_option.average_rate;
|
||||
msgbuf.bytes = state->control.format_option.bytes;
|
||||
msgbuf.bufpercent = state->control.format_option.bufpercent;
|
||||
msgbuf.lastwritten = state->control.format_option.lastwritten;
|
||||
msgbuf.rate_limit = state->control.rate_limit;
|
||||
msgbuf.buffer_size = state->control.target_buffer_size;
|
||||
msgbuf.size = state->control.size;
|
||||
msgbuf.interval = state->control.interval;
|
||||
msgbuf.width = (unsigned int) (state->control.width);
|
||||
msgbuf.height = (unsigned int) (state->control.height);
|
||||
msgbuf.width_set_manually = state->control.width_set_manually;
|
||||
msgbuf.height_set_manually = state->control.height_set_manually;
|
||||
|
||||
if (state->control.name != NULL) {
|
||||
strncpy(msgbuf.name, state->control.name, sizeof(msgbuf.name) - 1); /* flawfinder: ignore */
|
||||
}
|
||||
if (state->control.format_string != NULL) {
|
||||
strncpy(msgbuf.format, state->control.format_string, sizeof(msgbuf.format) - 1); /* flawfinder: ignore */
|
||||
}
|
||||
if (state->control.extra_display_spec != NULL) {
|
||||
strncpy(msgbuf.extra_display, state->control.extra_display_spec, sizeof(msgbuf.extra_display) - 1); /* flawfinder: ignore */
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure parameters are within sensible bounds.
|
||||
*/
|
||||
if (msgbuf.width < 1)
|
||||
msgbuf.width = 80;
|
||||
if (msgbuf.height < 1)
|
||||
msgbuf.height = 25;
|
||||
if (msgbuf.width > 999999)
|
||||
msgbuf.width = 999999;
|
||||
if (msgbuf.height > 999999)
|
||||
msgbuf.height = 999999;
|
||||
if ((msgbuf.interval > 0) && (msgbuf.interval < 0.1))
|
||||
msgbuf.interval = 0.1;
|
||||
if (msgbuf.interval > 600)
|
||||
msgbuf.interval = 600;
|
||||
|
||||
/*
|
||||
* flawfinder rationale: name, format, and extra_display are
|
||||
* explicitly bounded to 1 less than the size of their buffer and
|
||||
* the buffer is \0 terminated by memset() earlier.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get the filename and file stream to use for remote control.
|
||||
*/
|
||||
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));
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the message buffer to the remote control file, and close
|
||||
* it.
|
||||
*/
|
||||
if (1 != fwrite(&msgbuf, sizeof(msgbuf), 1, control_fptr)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
(void) fclose(control_fptr);
|
||||
(void) remove(control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
if (0 != fclose(control_fptr)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
(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.
|
||||
*/
|
||||
signal_sender = 0;
|
||||
(void) pv_sigusr2_received(state, &signal_sender);
|
||||
if (kill((pid_t) (remote), SIGUSR2) != 0) {
|
||||
pv_error("%u: %s", remote, strerror(errno));
|
||||
(void) remove(control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
debug("%s", "message sent");
|
||||
|
||||
/*
|
||||
* Wait for a signal from the remote process to say it has received
|
||||
* the message.
|
||||
*/
|
||||
|
||||
timeout = 1100000;
|
||||
received = false;
|
||||
|
||||
while (timeout > 10000 && !received) {
|
||||
struct timeval tv;
|
||||
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000;
|
||||
/*@-nullpass@ *//* splint: NULL is OK with select() */
|
||||
(void) select(0, NULL, NULL, NULL, &tv);
|
||||
/*@+nullpass@ */
|
||||
timeout -= 10000;
|
||||
|
||||
if (pv_sigusr2_received(state, &signal_sender)) {
|
||||
if (signal_sender == remote) {
|
||||
debug("%s", "message received");
|
||||
received = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the remote control file.
|
||||
*/
|
||||
debug("%s: %s", "removing", control_filename);
|
||||
if (0 != remove(control_filename)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 if the message was received.
|
||||
*/
|
||||
if (received)
|
||||
return 0;
|
||||
|
||||
/*@-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.
|
||||
*/
|
||||
pv_error("%u: %s", remote, _("message not received"));
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
/*@+mustfreefresh @ */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check for a --remote message (SIGUSR2), returning false if none was
|
||||
* found.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
static bool pv__rxsignal_usr2(pvstate_t state)
|
||||
{
|
||||
pid_t signal_sender;
|
||||
char control_filename[4096]; /* flawfinder: ignore */
|
||||
FILE *control_fptr;
|
||||
struct remote_msg msgbuf;
|
||||
|
||||
/* flawfinder rationale: as above. */
|
||||
|
||||
/*
|
||||
* Return early if a SIGUSR2 signal has not been received.
|
||||
*/
|
||||
signal_sender = 0;
|
||||
if (!pv_sigusr2_received(state, &signal_sender))
|
||||
return false;
|
||||
|
||||
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));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the message buffer from the remote control file, and close
|
||||
* it.
|
||||
*/
|
||||
if (1 != fread(&msgbuf, sizeof(msgbuf), 1, control_fptr)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
(void) fclose(control_fptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 != fclose(control_fptr)) {
|
||||
pv_error("%s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a SIGUSR2 signal to the sending process, to tell it the
|
||||
* message has been received.
|
||||
*/
|
||||
if (kill(signal_sender, SIGUSR2) != 0) {
|
||||
debug("%u: %s", signal_sender, strerror(errno));
|
||||
}
|
||||
|
||||
debug("%s", "received remote control message");
|
||||
|
||||
pv_state_format_string_set(state, NULL);
|
||||
pv_state_name_set(state, NULL);
|
||||
pv_state_extra_display_set(state, NULL);
|
||||
|
||||
msgbuf.name[sizeof(msgbuf.name) - 1] = '\0';
|
||||
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);
|
||||
|
||||
if (msgbuf.rate_limit > 0)
|
||||
pv_state_rate_limit_set(state, msgbuf.rate_limit);
|
||||
if (msgbuf.buffer_size > 0) {
|
||||
pv_state_target_buffer_size_set(state, msgbuf.buffer_size);
|
||||
}
|
||||
if (msgbuf.size > 0)
|
||||
pv_state_size_set(state, msgbuf.size);
|
||||
if (msgbuf.interval > 0)
|
||||
pv_state_interval_set(state, msgbuf.interval);
|
||||
if (msgbuf.width > 0 && msgbuf.width_set_manually)
|
||||
pv_state_width_set(state, msgbuf.width, msgbuf.width_set_manually);
|
||||
if (msgbuf.height > 0 && msgbuf.height_set_manually)
|
||||
pv_state_height_set(state, msgbuf.height, msgbuf.height_set_manually);
|
||||
if (msgbuf.format[0] != '\0')
|
||||
pv_state_format_string_set(state, msgbuf.format);
|
||||
if (msgbuf.extra_display[0] != '\0')
|
||||
pv_state_extra_display_set(state, msgbuf.extra_display);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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 1 message was received (response), update the state from the
|
||||
* message in the control file.
|
||||
*
|
||||
* In both cases, the receiver of the message deletes its control file.
|
||||
*
|
||||
* The state transferred by message is transfer.elapsed_seconds,
|
||||
* transfer.transferred, and control.size.
|
||||
*
|
||||
* Returns true if a signal was received and dealt with, false otherwise.
|
||||
*
|
||||
* If match_sender is not zero, then ignores the signal and returns false if
|
||||
* the sending PID is not match_sender.
|
||||
*/
|
||||
static bool pv__rxsignal_usr1(pvstate_t state, pid_t match_sender)
|
||||
{
|
||||
pid_t signal_sender;
|
||||
char control_filename[4096]; /* flawfinder: ignore */
|
||||
FILE *control_fptr;
|
||||
struct query_msg msgbuf;
|
||||
|
||||
/* flawfinder rationale: as above. */
|
||||
|
||||
/*
|
||||
* Return early if a SIGUSR1 signal has not been received.
|
||||
*/
|
||||
signal_sender = 0;
|
||||
if (!pv_sigusr1_received(state, &signal_sender))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If match_sender was specified, ignore the signal if the sender
|
||||
* doesn't match.
|
||||
*/
|
||||
if ((0 != match_sender) && (signal_sender != match_sender)) {
|
||||
debug("%s=%d, %s=%d - %s", "match_sender", match_sender, "signal_sender", signal_sender,
|
||||
"ignoring USR1");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
memset(control_filename, 0, sizeof(control_filename));
|
||||
control_fptr = pv_open_controlfile(control_filename, sizeof(control_filename), signal_sender, SIGUSR1, false);
|
||||
if (NULL == control_fptr) {
|
||||
debug("%s: %s", control_filename, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the message buffer from the remote control file, close it,
|
||||
* and delete it.
|
||||
*/
|
||||
if (1 != fread(&msgbuf, sizeof(msgbuf), 1, control_fptr)) {
|
||||
debug("fread: %s", strerror(errno));
|
||||
(void) fclose(control_fptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 != fclose(control_fptr)) {
|
||||
debug("fclose: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
debug("%s: %s", "removing", control_filename);
|
||||
if (0 != remove(control_filename)) {
|
||||
debug("remove: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (msgbuf.response) {
|
||||
/* Response message - update local state. */
|
||||
debug("%s: %d [%Lg, %ld, %ld]", "query response received", signal_sender, msgbuf.elapsed_seconds,
|
||||
msgbuf.transferred, msgbuf.size);
|
||||
state->transfer.elapsed_seconds = msgbuf.elapsed_seconds;
|
||||
state->transfer.transferred = msgbuf.transferred;
|
||||
state->control.size = msgbuf.size;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Query message - transmit state to sender. */
|
||||
|
||||
debug("%s: %d", "query received", signal_sender);
|
||||
|
||||
msgbuf.elapsed_seconds = state->transfer.elapsed_seconds;
|
||||
msgbuf.transferred = state->transfer.transferred;
|
||||
msgbuf.size = state->control.size;
|
||||
msgbuf.response = true;
|
||||
|
||||
memset(control_filename, 0, sizeof(control_filename));
|
||||
control_fptr = pv_open_controlfile(control_filename, sizeof(control_filename), (pid_t) getpid(), SIGUSR1, true);
|
||||
if (NULL == control_fptr) {
|
||||
debug("%s", strerror(errno));
|
||||
return true; /* true since the signal was received. */
|
||||
}
|
||||
|
||||
if (1 != fwrite(&msgbuf, sizeof(msgbuf), 1, control_fptr)) {
|
||||
debug("fwrite: %s", strerror(errno));
|
||||
(void) fclose(control_fptr);
|
||||
(void) remove(control_filename);
|
||||
return true; /* as above. */
|
||||
}
|
||||
|
||||
if (0 != fclose(control_fptr)) {
|
||||
debug("fclose: %s", strerror(errno));
|
||||
(void) remove(control_filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a SIGUSR1 signal to the remote process, to tell it this
|
||||
* query response message is ready to read.
|
||||
*/
|
||||
if (kill((pid_t) (signal_sender), SIGUSR1) != 0) {
|
||||
debug("%u: %s", signal_sender, strerror(errno));
|
||||
(void) remove(control_filename);
|
||||
return true;
|
||||
}
|
||||
|
||||
debug("%s: %d", "query response sent", signal_sender);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* NB --remote relies on pv_state_set_format() causing the output format to
|
||||
* be reparsed.
|
||||
*
|
||||
* Returns true if a --remote message was received, false otherwise.
|
||||
*/
|
||||
bool pv_remote_check(pvstate_t state)
|
||||
{
|
||||
bool received_remote;
|
||||
|
||||
received_remote = pv__rxsignal_usr2(state);
|
||||
(void) pv__rxsignal_usr1(state, 0);
|
||||
|
||||
return received_remote;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Replace the transfer state with that of the given process, including the
|
||||
* total transfer size. If sizeptr is not NULL, the size is also copied to
|
||||
* *sizeptr (this is so a caller can get the size without knowing the
|
||||
* structure of pvstate_t).
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
char control_filename[4096]; /* flawfinder: ignore */
|
||||
FILE *control_fptr;
|
||||
struct query_msg msgbuf;
|
||||
pid_t signal_sender;
|
||||
long timeout;
|
||||
bool received;
|
||||
|
||||
/*
|
||||
* flawfinder rationale: buffer is large enough, explicitly zeroed,
|
||||
* and always bounded properly as we are only writing to it with
|
||||
* pv_snprintf().
|
||||
*/
|
||||
|
||||
/*
|
||||
* Check that the remote process exists.
|
||||
*/
|
||||
if (kill((pid_t) (query), 0) != 0) {
|
||||
if (!silent)
|
||||
pv_error("%u: %s", query, strerror(errno));
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
/* Set up the query message. */
|
||||
memset(&msgbuf, 0, sizeof(msgbuf));
|
||||
msgbuf.response = false;
|
||||
|
||||
/*
|
||||
* Get the filename and file stream to use.
|
||||
*/
|
||||
memset(control_filename, 0, sizeof(control_filename));
|
||||
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));
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the message to the control file, and close it.
|
||||
*/
|
||||
if (1 != fwrite(&msgbuf, sizeof(msgbuf), 1, control_fptr)) {
|
||||
if (!silent)
|
||||
pv_error("%s", strerror(errno));
|
||||
(void) fclose(control_fptr);
|
||||
(void) remove(control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
if (0 != fclose(control_fptr)) {
|
||||
if (!silent)
|
||||
pv_error("%s", strerror(errno));
|
||||
(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.
|
||||
*/
|
||||
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));
|
||||
(void) remove(control_filename);
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
debug("%s: %d", "query sent", query);
|
||||
|
||||
/*
|
||||
* Wait for a SIGUSR1 signal to be sent back with a query response
|
||||
* message.
|
||||
*/
|
||||
|
||||
timeout = 1100000;
|
||||
received = false;
|
||||
|
||||
while (timeout > 10000 && !received && 0 == state->flags.trigger_exit) {
|
||||
struct timeval tv;
|
||||
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000;
|
||||
/*@-nullpass@ *//* splint: NULL is OK with select() */
|
||||
(void) select(0, NULL, NULL, NULL, &tv);
|
||||
/*@+nullpass@ */
|
||||
timeout -= 10000;
|
||||
|
||||
if (pv__rxsignal_usr1(state, query)) {
|
||||
debug("%s", "response received");
|
||||
received = true;
|
||||
if (NULL != sizeptr)
|
||||
*sizeptr = state->control.size;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the control file in case it still exists - the other
|
||||
* process should have removed it.
|
||||
*/
|
||||
debug("%s: %s", "cleaning up", control_filename);
|
||||
(void) remove(control_filename);
|
||||
|
||||
/*
|
||||
* Return 0 if the message was received.
|
||||
*/
|
||||
if (received)
|
||||
return 0;
|
||||
|
||||
/*@-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.
|
||||
*/
|
||||
if (!silent)
|
||||
pv_error("%u: %s", query, _("message not received"));
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
/*@+mustfreefresh @ */
|
||||
|
||||
}
|
||||
|
||||
|
||||
#else /* !PV_REMOTE_CONTROL */
|
||||
|
||||
/*
|
||||
* Dummy stubs for remote control when we don't have PV_REMOTE_CONTROL.
|
||||
*/
|
||||
|
||||
bool pv_remote_check( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int pv_remote_set( /*@unused@ */
|
||||
__attribute__((unused)) pvstate_t state, /*@unused@ */ __attribute__((unused)) pid_t remote)
|
||||
{
|
||||
/*@-mustfreefresh@ *//* splint - see above */
|
||||
pv_error("%s", _("SA_SIGINFO not supported on this system"));
|
||||
/*@+mustfreefresh@ */
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
|
||||
int pv_remote_transferstate_fetch( /*@unused@ */
|
||||
__attribute__((unused)) pvstate_t state,
|
||||
/*@unused@ */
|
||||
__attribute__((unused)) pid_t query,
|
||||
/*@null@ */
|
||||
/*@unused@ */
|
||||
__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"));
|
||||
/*@+mustfreefresh@ */
|
||||
return PV_ERROREXIT_REMOTE_OR_PID;
|
||||
}
|
||||
|
||||
#endif /* PV_REMOTE_CONTROL */
|
||||
+90
-12
@@ -121,7 +121,7 @@ static void pv_sig_tstp( /*@unused@ */ __attribute__((unused))
|
||||
{
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
pv_elapsedtime_read(&(pv_sig_state->signal.tstp_time));
|
||||
pv_elapsedtime_read(&(pv_sig_state->signal.when_tstp_arrived));
|
||||
if (0 != raise(SIGSTOP)) {
|
||||
debug("%s: %s", "raise", strerror(errno));
|
||||
}
|
||||
@@ -160,7 +160,7 @@ static void pv_sig_cont( /*@unused@ */ __attribute__((unused))
|
||||
* We can only make the time adjustments if this SIGCONT followed a
|
||||
* SIGTSTP such that we have a stop time.
|
||||
*/
|
||||
if (0 != pv_sig_state->signal.tstp_time.tv_sec) {
|
||||
if (0 != pv_sig_state->signal.when_tstp_arrived.tv_sec) {
|
||||
|
||||
memset(¤t_time, 0, sizeof(current_time));
|
||||
memset(&time_spent_stopped, 0, sizeof(time_spent_stopped));
|
||||
@@ -168,14 +168,44 @@ static void pv_sig_cont( /*@unused@ */ __attribute__((unused))
|
||||
pv_elapsedtime_read(¤t_time);
|
||||
|
||||
/* time spent stopped = current time - time SIGTSTP received */
|
||||
pv_elapsedtime_subtract(&time_spent_stopped, ¤t_time, &(pv_sig_state->signal.tstp_time));
|
||||
pv_elapsedtime_subtract(&time_spent_stopped, ¤t_time, &(pv_sig_state->signal.when_tstp_arrived));
|
||||
|
||||
/* add time spent stopped the total stopped-time count */
|
||||
pv_elapsedtime_add(&(pv_sig_state->signal.toffset), &(pv_sig_state->signal.toffset),
|
||||
&time_spent_stopped);
|
||||
pv_elapsedtime_add(&(pv_sig_state->signal.total_stoppage_time),
|
||||
&(pv_sig_state->signal.total_stoppage_time), &time_spent_stopped);
|
||||
|
||||
/* In watchfd mode, update the stoppage time of all watched fds. */
|
||||
if (pv_sig_state->watchfd.count > 0 && NULL != pv_sig_state->watchfd.watching) {
|
||||
unsigned int watch_idx;
|
||||
|
||||
for (watch_idx = 0; watch_idx < pv_sig_state->watchfd.count; watch_idx++) {
|
||||
int info_idx;
|
||||
|
||||
if (pv_sig_state->watchfd.watching[watch_idx].finished)
|
||||
continue;
|
||||
|
||||
if (NULL == pv_sig_state->watchfd.watching[watch_idx].info_array)
|
||||
continue;
|
||||
|
||||
for (info_idx = 0; info_idx < pv_sig_state->watchfd.watching[watch_idx].array_length;
|
||||
info_idx++) {
|
||||
pvwatchfd_t info_item =
|
||||
&(pv_sig_state->watchfd.watching[watch_idx].info_array[info_idx]);
|
||||
|
||||
if (info_item->unused)
|
||||
continue;
|
||||
|
||||
if (!info_item->displayable)
|
||||
continue;
|
||||
|
||||
pv_elapsedtime_add(&(info_item->total_stoppage_time),
|
||||
&(info_item->total_stoppage_time), &time_spent_stopped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* reset the SIGTSTP receipt time */
|
||||
pv_elapsedtime_zero(&(pv_sig_state->signal.tstp_time));
|
||||
pv_elapsedtime_zero(&(pv_sig_state->signal.when_tstp_arrived));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -239,7 +269,7 @@ static void pv_sig_usr2( /*@unused@ */ __attribute__((unused))
|
||||
return;
|
||||
if (NULL == info)
|
||||
return;
|
||||
pv_sig_state->signal.sender = info->si_pid;
|
||||
pv_sig_state->signal.sender_usr2 = info->si_pid;
|
||||
pv_sig_state->signal.rxusr2 = 1;
|
||||
}
|
||||
|
||||
@@ -255,12 +285,46 @@ bool pv_sigusr2_received(pvstate_t state, pid_t * pid)
|
||||
if (0 == state->signal.rxusr2)
|
||||
return false;
|
||||
if (NULL != pid)
|
||||
*pid = state->signal.sender;
|
||||
*pid = state->signal.sender_usr2;
|
||||
state->signal.rxusr2 = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handle a SIGUSR1 by setting a flag to say we received it, after recording
|
||||
* the sending PID.
|
||||
*/
|
||||
static void pv_sig_usr1( /*@unused@ */ __attribute__((unused))
|
||||
int sig, siginfo_t * info, /*@unused@ */ __attribute__((unused))
|
||||
void *ucontext)
|
||||
{
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
if (NULL == info)
|
||||
return;
|
||||
pv_sig_state->signal.sender_usr1 = info->si_pid;
|
||||
pv_sig_state->signal.rxusr1 = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
if (NULL == state)
|
||||
return false;
|
||||
if (0 == state->signal.rxusr1)
|
||||
return false;
|
||||
if (NULL != pid)
|
||||
*pid = state->signal.sender_usr1;
|
||||
state->signal.rxusr1 = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* PV_REMOTE_CONTROL */
|
||||
|
||||
|
||||
/*
|
||||
@@ -298,8 +362,8 @@ void pv_sig_init(pvstate_t state)
|
||||
pv_sig_state = state;
|
||||
|
||||
pv_sig_state->flags.suspend_stderr = 0;
|
||||
pv_elapsedtime_zero(&(pv_sig_state->signal.tstp_time));
|
||||
pv_elapsedtime_zero(&(pv_sig_state->signal.toffset));
|
||||
pv_elapsedtime_zero(&(pv_sig_state->signal.when_tstp_arrived));
|
||||
pv_elapsedtime_zero(&(pv_sig_state->signal.total_stoppage_time));
|
||||
|
||||
/*
|
||||
* Note that we cast all sigemptyset() and sigaction() return values
|
||||
@@ -388,7 +452,20 @@ void pv_sig_init(pvstate_t state)
|
||||
/*@+unrecog@ */
|
||||
(void) sigaction(SIGUSR2, &sa, &(pv_sig_state->signal.old_sigusr2));
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handle SIGUSR1 by setting a flag to say the signal has been
|
||||
* received, and storing the sending process's PID.
|
||||
*/
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_sigaction = pv_sig_usr1;
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
/*@-unrecog@ *//* splint doesn't know about SA_SIGINFO */
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
/*@+unrecog@ */
|
||||
(void) sigaction(SIGUSR1, &sa, &(pv_sig_state->signal.old_sigusr1));
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
#endif /* PV_REMOTE_CONTROL */
|
||||
|
||||
/*
|
||||
* Ensure that the TOSTOP terminal attribute is set, so that a
|
||||
@@ -433,6 +510,7 @@ void pv_sig_fini( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
(void) sigaction(SIGTERM, &(pv_sig_state->signal.old_sigterm), NULL);
|
||||
#ifdef PV_REMOTE_CONTROL
|
||||
(void) sigaction(SIGUSR2, &(pv_sig_state->signal.old_sigusr2), NULL);
|
||||
(void) sigaction(SIGUSR1, &(pv_sig_state->signal.old_sigusr1), NULL);
|
||||
#endif
|
||||
(void) sigaction(SIGALRM, &(pv_sig_state->signal.old_sigalrm), NULL);
|
||||
|
||||
|
||||
+136
-32
@@ -131,6 +131,7 @@ void pv_reset_transfer(pvtransferstate_t transfer)
|
||||
transfer->line_positions_length = 0;
|
||||
transfer->line_positions_head = 0;
|
||||
transfer->last_output_position = 0;
|
||||
transfer->output_not_seekable = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -256,6 +257,71 @@ void pv_freecontents_calc(pvtransfercalc_t calc)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free the contents of a watchfd watched-items array.
|
||||
*/
|
||||
void pv_freecontents_watchfd_items(struct pvwatcheditem_s *watching, unsigned int count)
|
||||
{
|
||||
unsigned int watch_idx;
|
||||
|
||||
if (NULL == watching)
|
||||
return;
|
||||
|
||||
/*@-compdestroy@ */
|
||||
for (watch_idx = 0; watch_idx < count; watch_idx++) {
|
||||
int info_idx;
|
||||
if (NULL == watching[watch_idx].info_array)
|
||||
continue;
|
||||
for (info_idx = 0; info_idx < watching[watch_idx].array_length; info_idx++) {
|
||||
pv_freecontents_watchfd(&(watching[watch_idx].info_array[info_idx]));
|
||||
}
|
||||
free(watching[watch_idx].info_array);
|
||||
watching[watch_idx].info_array = NULL;
|
||||
watching[watch_idx].array_length = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
/*@+compdestroy @ */
|
||||
/*
|
||||
* splint warns that watching[].info_array->transfer.transfer_buffer
|
||||
* and other deep structures may not be deallocated and so leak
|
||||
* memory, but that's what pv_freecontents_watchfd() takes care of.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static void pv_truncate_output(pvstate_t state)
|
||||
{
|
||||
off_t current_offset;
|
||||
|
||||
if (!state->control.sparse_output)
|
||||
return;
|
||||
if (state->transfer.output_not_seekable)
|
||||
return;
|
||||
if (state->control.output_fd < 0)
|
||||
return;
|
||||
|
||||
current_offset = (off_t) lseek(state->control.output_fd, (off_t) 0, SEEK_CUR);
|
||||
if (current_offset == (off_t) - 1)
|
||||
return;
|
||||
|
||||
debug("%s: %ld", "truncating to current offset", (long) current_offset);
|
||||
|
||||
/*@+longintegral@ */
|
||||
/*
|
||||
* splint has trouble with off_t / __off_t.
|
||||
*/
|
||||
if (0 != ftruncate(state->control.output_fd, current_offset)) {
|
||||
debug("%s: %s", "output ftruncate() failed", strerror(errno));
|
||||
}
|
||||
/*@-longintegral@ */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free a state structure, after which it can no longer be used.
|
||||
*/
|
||||
@@ -269,6 +335,7 @@ void pv_state_free(pvstate_t state)
|
||||
* still know the program name and output filename.
|
||||
*/
|
||||
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",
|
||||
@@ -302,6 +369,11 @@ void pv_state_free(pvstate_t state)
|
||||
state->control.format_string = NULL;
|
||||
}
|
||||
|
||||
if (NULL != state->control.extra_display_spec) {
|
||||
free(state->control.extra_display_spec);
|
||||
state->control.extra_display_spec = NULL;
|
||||
}
|
||||
|
||||
if (NULL != state->control.extra_format_string) {
|
||||
free(state->control.extra_format_string);
|
||||
state->control.extra_format_string = NULL;
|
||||
@@ -323,13 +395,10 @@ void pv_state_free(pvstate_t state)
|
||||
state->files.filename = NULL;
|
||||
}
|
||||
|
||||
if (NULL != state->watchfd.pid) {
|
||||
free(state->watchfd.pid);
|
||||
state->watchfd.pid = NULL;
|
||||
}
|
||||
if (NULL != state->watchfd.fd) {
|
||||
free(state->watchfd.fd);
|
||||
state->watchfd.fd = NULL;
|
||||
if (NULL != state->watchfd.watching) {
|
||||
pv_freecontents_watchfd_items(state->watchfd.watching, state->watchfd.count);
|
||||
free(state->watchfd.watching);
|
||||
state->watchfd.watching = NULL;
|
||||
}
|
||||
|
||||
free(state);
|
||||
@@ -350,6 +419,16 @@ 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.default_format[0] = '\0';
|
||||
|
||||
if (false == state->control.numeric) {
|
||||
@@ -494,6 +573,11 @@ void pv_state_direct_io_set(pvstate_t state, bool val)
|
||||
state->control.direct_io_changed = true;
|
||||
}
|
||||
|
||||
void pv_state_sparse_output_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->control.sparse_output = val;
|
||||
}
|
||||
|
||||
void pv_state_discard_input_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->control.discard_input = val;
|
||||
@@ -573,6 +657,11 @@ 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);
|
||||
state->control.extra_display_spec = NULL;
|
||||
}
|
||||
|
||||
if (NULL != state->control.extra_format_string) {
|
||||
free(state->control.extra_format_string);
|
||||
state->control.extra_format_string = NULL;
|
||||
@@ -582,6 +671,9 @@ void pv_state_extra_display_set(pvstate_t state, /*@null@ */ const char *val)
|
||||
if (NULL == val)
|
||||
return;
|
||||
|
||||
if (NULL != val)
|
||||
state->control.extra_display_spec = pv_strdup(val);
|
||||
|
||||
word_start = val;
|
||||
while (NULL != word_start && '\0' != word_start[0]) {
|
||||
offset = 0;
|
||||
@@ -625,6 +717,7 @@ 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.
|
||||
*/
|
||||
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",
|
||||
@@ -645,6 +738,22 @@ void pv_state_output_set(pvstate_t state, int fd, const char *name)
|
||||
*/
|
||||
fcntl(state->control.output_fd, F_SETFL, O_NONBLOCK | fcntl(state->control.output_fd, F_GETFL));
|
||||
#endif /* MAKE_OUTPUT_NONBLOCKING */
|
||||
|
||||
/*
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
if (state->control.sparse_output && 0 != (fcntl(fd, F_GETFL) & O_APPEND)) {
|
||||
debug("%s", "sparse output mode, and appending - seeking output to the end");
|
||||
if ((off_t) lseek(fd, 0, SEEK_END) == (off_t) - 1) {
|
||||
debug("%s: %s", "lseek failed", strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pv_state_average_rate_window_set(pvstate_t state, unsigned int val)
|
||||
@@ -709,43 +818,38 @@ void pv_state_inputfiles(pvstate_t state, unsigned int input_file_count, const c
|
||||
void pv_state_watchfds(pvstate_t state, unsigned int watchfd_count, const pid_t * pids, const int *fds)
|
||||
{
|
||||
unsigned int item_idx;
|
||||
/*@only@ */ pid_t *new_pid_array = NULL;
|
||||
/*@only@ */ int *new_fd_array = NULL;
|
||||
/*@only@ */ struct pvwatcheditem_s *new_array = NULL;
|
||||
|
||||
/* Free the old arrays, if there were any. */
|
||||
if (NULL != state->watchfd.pid) {
|
||||
free(state->watchfd.pid);
|
||||
state->watchfd.pid = NULL;
|
||||
}
|
||||
if (NULL != state->watchfd.fd) {
|
||||
free(state->watchfd.fd);
|
||||
state->watchfd.fd = NULL;
|
||||
if (NULL != state->watchfd.watching) {
|
||||
/*@-compdestroy@ */
|
||||
pv_freecontents_watchfd_items(state->watchfd.watching, state->watchfd.count);
|
||||
free(state->watchfd.watching);
|
||||
state->watchfd.watching = NULL;
|
||||
/*@+compdestroy@ */
|
||||
/*
|
||||
* splint warns about deep structures not being deallocated,
|
||||
* but that's what pv_freecontents_watchfd_items() does.
|
||||
*/
|
||||
}
|
||||
state->watchfd.count = 0;
|
||||
state->watchfd.multiple_pids = false;
|
||||
|
||||
/* Allocate empty new arrays of the right size. */
|
||||
new_pid_array = calloc((size_t) (watchfd_count + 1), sizeof(pid_t));
|
||||
if (NULL == new_pid_array) {
|
||||
/* Allocate an empty new array of the right size. */
|
||||
new_array = malloc((1 + state->watchfd.count) * sizeof(*new_array));
|
||||
if (NULL == new_array) {
|
||||
/*@-mustfreefresh@ *//* see similar _() issue above */
|
||||
pv_error("%s: %s", _("process list allocation failed"), strerror(errno));
|
||||
pv_error("%s: %s", _("buffer allocation failed"), strerror(errno));
|
||||
/*@+mustfreefresh@ */
|
||||
return;
|
||||
}
|
||||
state->watchfd.pid = new_pid_array;
|
||||
new_fd_array = calloc((size_t) (watchfd_count + 1), sizeof(int));
|
||||
if (NULL == new_fd_array) {
|
||||
/*@-mustfreefresh@ *//* see similar _() issue above */
|
||||
pv_error("%s: %s", _("file descriptor list allocation failed"), strerror(errno));
|
||||
/*@+mustfreefresh@ */
|
||||
return;
|
||||
}
|
||||
state->watchfd.fd = new_fd_array;
|
||||
memset(new_array, 0, (1 + state->watchfd.count) * sizeof(*new_array));
|
||||
state->watchfd.watching = new_array;
|
||||
|
||||
/* Populate the new arrays with the values supplied. */
|
||||
/* Populate the new array with the values supplied. */
|
||||
for (item_idx = 0; item_idx < watchfd_count; item_idx++) {
|
||||
state->watchfd.pid[item_idx] = pids[item_idx];
|
||||
state->watchfd.fd[item_idx] = fds[item_idx];
|
||||
state->watchfd.watching[item_idx].pid = pids[item_idx];
|
||||
state->watchfd.watching[item_idx].fd = fds[item_idx];
|
||||
if ((item_idx > 0) && (pids[item_idx] != pids[item_idx - 1]))
|
||||
state->watchfd.multiple_pids = true;
|
||||
}
|
||||
|
||||
@@ -655,6 +655,9 @@ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long
|
||||
{
|
||||
ssize_t nwritten;
|
||||
int write_errno;
|
||||
bool all_nulls;
|
||||
off_t output_offset;
|
||||
size_t write_check_position, write_end_position;
|
||||
|
||||
if (NULL == state->transfer.transfer_buffer) {
|
||||
pv_error("%s", _("no transfer buffer allocated"));
|
||||
@@ -671,6 +674,52 @@ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long
|
||||
nwritten = state->transfer.to_write;
|
||||
} else if (state->transfer.to_write > 0) {
|
||||
|
||||
/*
|
||||
* In sparse output mode, check whether all of the bytes to
|
||||
* be written are null, and if so, try to seek the output
|
||||
* instead of writing the null bytes.
|
||||
*/
|
||||
if (state->control.sparse_output && !state->transfer.output_not_seekable) {
|
||||
write_check_position = state->transfer.write_position;
|
||||
write_end_position = write_check_position + (size_t) (state->transfer.to_write);
|
||||
all_nulls = true;
|
||||
while (all_nulls && write_check_position < write_end_position) {
|
||||
if ('\0' == state->transfer.transfer_buffer[write_check_position]) {
|
||||
write_check_position++;
|
||||
} else {
|
||||
all_nulls = false;
|
||||
}
|
||||
}
|
||||
if (all_nulls) {
|
||||
|
||||
/*
|
||||
* Use lseek() to move forward in the file,
|
||||
* and then ftruncate() it to its new size.
|
||||
*
|
||||
* If any step fails, mark the output not
|
||||
* seekable so we stop trying.
|
||||
*/
|
||||
|
||||
/*@+longintegral@ */
|
||||
/*
|
||||
* splint has trouble with off_t / __off_t, in the lseek() call.
|
||||
*/
|
||||
output_offset =
|
||||
lseek(state->control.output_fd, (off_t) (state->transfer.to_write), SEEK_CUR);
|
||||
if (output_offset == (off_t) - 1) {
|
||||
debug("%s: %s", "output lseek() failed", strerror(errno));
|
||||
state->transfer.output_not_seekable = true;
|
||||
} else {
|
||||
/* Seek successful - skip write. */
|
||||
debug("%s (%ld) -> %s: %ld", "skipped null writes",
|
||||
(long) (state->transfer.to_write), "new position", (long) output_offset);
|
||||
nwritten = state->transfer.to_write;
|
||||
goto pv__transfer_write_completed;
|
||||
}
|
||||
/*@-longintegral@ */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set an interval timer or an alarm to interrupt the write
|
||||
* with a signal if the write takes too long, so we can
|
||||
@@ -735,6 +784,9 @@ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long
|
||||
#endif /* HAVE_SETITIMER */
|
||||
}
|
||||
|
||||
pv__transfer_write_completed:
|
||||
/* If lseek() worked for sparse output, it jumps down here. */
|
||||
|
||||
if (nwritten > 0) {
|
||||
bool tracking_lines = false;
|
||||
|
||||
|
||||
+32
-4
@@ -42,6 +42,8 @@
|
||||
*/
|
||||
static bool filesize(pvwatchfd_t info)
|
||||
{
|
||||
if (NULL == info)
|
||||
return false;
|
||||
if (S_ISBLK(info->sb_fd.st_mode)) {
|
||||
int fd;
|
||||
|
||||
@@ -222,6 +224,9 @@ bool pv_watchfd_changed(pvwatchfd_t info)
|
||||
{
|
||||
struct stat sb_fd, sb_fd_link;
|
||||
|
||||
if (NULL == info)
|
||||
return false;
|
||||
|
||||
memset(&sb_fd, 0, sizeof(sb_fd));
|
||||
memset(&sb_fd_link, 0, sizeof(sb_fd_link));
|
||||
|
||||
@@ -265,6 +270,9 @@ off_t pv_watchfd_position(pvwatchfd_t info)
|
||||
long long pos_long;
|
||||
FILE *fptr;
|
||||
|
||||
if (NULL == info)
|
||||
return -1;
|
||||
|
||||
if (pv_watchfd_changed(info))
|
||||
return -1;
|
||||
|
||||
@@ -418,7 +426,7 @@ static int pv_compare_watchfd(const void *a, const void *b)
|
||||
|
||||
/*
|
||||
* Scan the given process and update the arrays with any new file
|
||||
* descriptors. If "watch_fd" is not -1, then all other file descriptors
|
||||
* descriptors. If "watch_fd" is not -1, then all other file descriptor
|
||||
* numbers will be ignored,
|
||||
*
|
||||
* Returns 0 on success, 1 if the process no longer exists or could not be
|
||||
@@ -489,11 +497,21 @@ int pv_watchpid_scanfds(pvstate_t state, pid_t watch_pid, int watch_fd, int *arr
|
||||
* Skip if this fd is already known to us.
|
||||
*/
|
||||
found_idx = -1;
|
||||
for (check_idx = 0; check_idx < array_length; check_idx++) {
|
||||
for (check_idx = 0; check_idx < array_length && NULL != info_array; check_idx++) {
|
||||
if (info_array[check_idx].unused)
|
||||
continue;
|
||||
if (info_array[check_idx].watch_fd != fd)
|
||||
continue;
|
||||
if (info_array[check_idx].closed) {
|
||||
/*
|
||||
* If the fd is known but closed,
|
||||
* immediately free it for re-use.
|
||||
*/
|
||||
info_array[check_idx].unused = true;
|
||||
info_array[check_idx].displayable = false;
|
||||
pv_freecontents_watchfd(&(info_array[check_idx]));
|
||||
continue;
|
||||
}
|
||||
found_idx = check_idx;
|
||||
break;
|
||||
}
|
||||
@@ -504,7 +522,7 @@ int pv_watchpid_scanfds(pvstate_t state, pid_t watch_pid, int watch_fd, int *arr
|
||||
* See if there's an empty slot we can re-use.
|
||||
*/
|
||||
use_idx = -1;
|
||||
for (check_idx = 0; check_idx < array_length; check_idx++) {
|
||||
for (check_idx = 0; check_idx < array_length && NULL != info_array; check_idx++) {
|
||||
if (info_array[check_idx].unused) {
|
||||
use_idx = check_idx;
|
||||
break;
|
||||
@@ -522,6 +540,10 @@ int pv_watchpid_scanfds(pvstate_t state, pid_t watch_pid, int watch_fd, int *arr
|
||||
use_idx = array_length - 1;
|
||||
}
|
||||
|
||||
/* At this point, the array should exist. */
|
||||
if (NULL == info_array)
|
||||
return 2;
|
||||
|
||||
debug("%s: %d => index %d", "found new fd", fd, use_idx);
|
||||
|
||||
changes_made = true;
|
||||
@@ -534,6 +556,7 @@ int pv_watchpid_scanfds(pvstate_t state, pid_t watch_pid, int watch_fd, int *arr
|
||||
pv_reset_watchfd(&(info_array[use_idx]));
|
||||
info_array[use_idx].watch_pid = watch_pid;
|
||||
info_array[use_idx].watch_fd = fd;
|
||||
info_array[use_idx].closed = false;
|
||||
info_array[use_idx].unused = false;
|
||||
info_array[use_idx].displayable = true;
|
||||
|
||||
@@ -627,7 +650,12 @@ void pv_watchpid_setname(pvstate_t state, pvwatchfd_t info)
|
||||
{
|
||||
size_t path_length, cwd_length;
|
||||
int max_display_length;
|
||||
char *file_fdpath = info->file_fdpath;
|
||||
char *file_fdpath;
|
||||
|
||||
if (NULL == info)
|
||||
return;
|
||||
|
||||
file_fdpath = info->file_fdpath;
|
||||
|
||||
memset(info->display_name, 0, PV_SIZEOF_DISPLAY_NAME);
|
||||
|
||||
|
||||
Executable
+89
@@ -0,0 +1,89 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Transfer a large chunk of data through pv using pipes, sending it in a
|
||||
# bursty fashion, and make sure some of it consists of blocks of null bytes.
|
||||
# Check data correctness afterwards, and if dd can produce a sparse file,
|
||||
# check that pv's output is also sparse.
|
||||
|
||||
# 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'}"
|
||||
true "${workFile3:?not set - call this from 'make check'}"
|
||||
|
||||
# generate some data, with a hole in the middle.
|
||||
dd if=/dev/urandom of="${workFile1}" bs=4096 count=640 2>/dev/null
|
||||
dd if=/dev/null of="${workFile1}" bs=4096 count=0 seek=1280 2>/dev/null
|
||||
dd if=/dev/urandom of="${workFile1}" bs=4096 count=1280 seek=1280 2>/dev/null
|
||||
|
||||
# check that sparse files are supported.
|
||||
cat < "${workFile1}" > "${workFile3}"
|
||||
inputBlocks="$(ls -1s "${workFile1}" | awk '{print $1}')"
|
||||
nonSparseBlocks="$(ls -1s "${workFile3}" | awk '{print $1}')"
|
||||
if test "${inputBlocks}" -eq "${nonSparseBlocks}"; then
|
||||
echo 'sparse files not supported'
|
||||
exit 77
|
||||
fi
|
||||
|
||||
inputChecksum=$(cksum "${workFile1}" | awk '{print $1}')
|
||||
|
||||
# read through pv and test afterwards
|
||||
(
|
||||
dd if="${workFile1}" bs=1 count=9000
|
||||
sleep 1
|
||||
dd if="${workFile1}" bs=1 skip=9000 count=1240
|
||||
sleep 1
|
||||
dd if="${workFile1}" bs=1024 skip=10 count=1014
|
||||
sleep 1
|
||||
dd if="${workFile1}" bs=1024 skip=1024 count=1024
|
||||
sleep 1
|
||||
dd if="${workFile1}" bs=1024 skip=2048
|
||||
) 2>/dev/null | "${testSubject}" -q -O -L 2M | cat > "${workFile2}"
|
||||
|
||||
outputChecksum=$(cksum "${workFile2}" | awk '{print $1}')
|
||||
|
||||
if ! test "${inputChecksum}" = "${outputChecksum}"; then
|
||||
echo "checksum mismatch with dd | pv | cat"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# same again but with one less pipe
|
||||
(
|
||||
dd if="${workFile1}" bs=1 count=9000
|
||||
sleep 1
|
||||
dd if="${workFile1}" bs=1 skip=9000 count=1240
|
||||
sleep 1
|
||||
dd if="${workFile1}" bs=1024 skip=10 count=1014
|
||||
sleep 1
|
||||
dd if="${workFile1}" bs=1024 skip=1024 count=1024
|
||||
sleep 1
|
||||
dd if="${workFile1}" bs=1024 skip=2048
|
||||
) 2>/dev/null | "${testSubject}" -q -O -L 2M > "${workFile2}"
|
||||
|
||||
outputChecksum=$(cksum "${workFile2}" | awk '{print $1}')
|
||||
|
||||
if ! test "${inputChecksum}" = "${outputChecksum}"; then
|
||||
echo "checksum mismatch with dd | pv > file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
outputBlocks="$(ls -1s "${workFile2}" | awk '{print $1}')"
|
||||
|
||||
# Note that we only check that the output has any holes at all (and that the
|
||||
# input had holes). We don't compare pv's output with dd's output directly,
|
||||
# because the exact number of holes might differ intermittently.
|
||||
|
||||
if test "${nonSparseBlocks}" -gt "${inputBlocks}" && ! test "${outputBlocks}" -lt "${nonSparseBlocks}"; then
|
||||
echo "output is not sparse"
|
||||
echo "input file:"
|
||||
ls -ls "${workFile1}"
|
||||
echo "output file:"
|
||||
ls -ls "${workFile2}"
|
||||
echo "input file without holes:"
|
||||
ls -ls "${workFile3}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user