Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b4ec17ff9 | ||
|
|
cc9534fc7b | ||
|
|
c8762821fb | ||
|
|
272dacdd3a | ||
|
|
78548460b7 | ||
|
|
3eee7a1409 | ||
|
|
e446782c1f | ||
|
|
d8664ca4c1 | ||
|
|
d06374a0f1 | ||
|
|
9a9c117411 | ||
|
|
2255dcc2bf | ||
|
|
be4402c1ff | ||
|
|
4d46dbe545 | ||
|
|
3fdf8d5a69 | ||
|
|
7c0aea0b1e | ||
|
|
b4d6c5ed2a | ||
|
|
d8e0674da0 | ||
|
|
b0df2e53a8 | ||
|
|
94ffdaf60d | ||
|
|
376aa5a8fa | ||
|
|
7fcc7af07d | ||
|
|
03d42555e7 | ||
|
|
b8624035e0 | ||
|
|
41b223a757 | ||
|
|
03fb1dc673 | ||
|
|
e864eca78d | ||
|
|
ddafc2e897 | ||
|
|
bf3f76e02e | ||
|
|
4398cd8677 | ||
|
|
dbf55eff3c | ||
|
|
07f894f66c | ||
|
|
a9737ca05e | ||
|
|
0e1750835e | ||
|
|
965cc52815 | ||
|
|
08ee154c09 | ||
|
|
37cacf3da4 | ||
|
|
55f7f94a6f | ||
|
|
1e91713bb6 | ||
|
|
27f52cac6b | ||
|
|
b0a144fd54 | ||
|
|
bfa4a23751 | ||
|
|
7c6568865c |
+3
-4
@@ -4,7 +4,7 @@ dnl Copyright 2002-2008, 2010, 2012-2015, 2017, 2021, 2023 Andrew Wood
|
||||
dnl
|
||||
dnl License GPLv3+: GNU GPL version 3 or later; see `docs/COPYING'.
|
||||
|
||||
AC_INIT([pv], [1.8.0], [pv@ivarch.com], [pv], [https://www.ivarch.com/programs/pv.shtml])
|
||||
AC_INIT([pv], [1.8.5], [pv@ivarch.com], [pv], [https://www.ivarch.com/programs/pv.shtml])
|
||||
AC_CONFIG_SRCDIR([src/include/config.h.in])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([src/include/config.h])
|
||||
@@ -25,7 +25,7 @@ fi
|
||||
|
||||
dnl Items we can use if present, but can do without if not present.
|
||||
AC_CHECK_FUNCS([getopt_long])
|
||||
AC_CHECK_FUNCS([vsnprintf strlcat strtoul])
|
||||
AC_CHECK_FUNCS([vsnprintf strlcat strtoul memrchr])
|
||||
AC_CHECK_FUNCS([fdatasync])
|
||||
AC_CHECK_FUNCS([fpathconf sysconf posix_memalign posix_fadvise])
|
||||
AC_CHECK_FUNCS([nanosleep])
|
||||
@@ -103,10 +103,9 @@ yes
|
||||
|
||||
if test "$IPC_SUPPORT" = "yes"; then
|
||||
AC_CHECK_HEADERS([sys/ipc.h], [], [IPC_SUPPORT=no])
|
||||
AC_CHECK_HEADERS([sys/msg.h], [], [IPC_SUPPORT=no])
|
||||
AC_CHECK_HEADERS([sys/param.h])
|
||||
if test "$IPC_SUPPORT" = "yes"; then
|
||||
AC_CHECK_FUNCS([msgget], [], [IPC_SUPPORT=no])
|
||||
AC_CHECK_FUNCS([shmget], [], [IPC_SUPPORT=no])
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -87,5 +87,7 @@ is acknowledged and greatly appreciated:
|
||||
* [Wilhelm von Thiele](https://github.com/TurtleWilly) - assisted with OS X cleanups ([#73](https://codeberg.org/a-j-wood/pv/issues/73), [#74](https://codeberg.org/a-j-wood/pv/issues/74))
|
||||
* Matějů Miroslav, Ing. - suggested fix for ETA and elapsed time faults when suspending and resuming a machine ([#13](https://codeberg.org/a-j-wood/pv/issues/13))
|
||||
* Anthony DeRobertis - suggested the "`--error-skip-block`" option ([#37](https://codeberg.org/a-j-wood/pv/issues/37))
|
||||
* Benoit Pierre - provided patches for compilation without IPC support, without HAVE_STRUCT_STAT_ST_BLKSIZE, and on MacOS
|
||||
* [gustav-b](https://codeberg.org/gustav-b) - suggested percentage formatting correction ([#80](https://codeberg.org/a-j-wood/pv/issues/80))
|
||||
|
||||
---
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
### 1.8.5 - 19 November 2023
|
||||
|
||||
* fix: corrected percentage formatting so it doesn't jump from 2 to 3 characters wide at 100% ([#80](https://codeberg.org/a-j-wood/pv/issues/80))
|
||||
* fix: replaced "`--remote`" mechanism, using a temporary file instead of SysV IPC, so it can work reliably even when there are multiple PV instances
|
||||
* fix: corrected compilation failure when without IPC support
|
||||
* security: addressed all issues highlighted by the software auditing tools "`splint`" and "`flawfinder`" (see "`make analyse`") ([#77](https://codeberg.org/a-j-wood/pv/issues/77))
|
||||
* cleanup: compilation warnings fixed on non-IPC and MacOS systems
|
||||
|
||||
### 1.8.0 - 24 September 2023
|
||||
|
||||
#### Features
|
||||
|
||||
@@ -26,6 +26,5 @@ Things still to do. (#n) indicates the issue tracker number.
|
||||
* ([#56](https://codeberg.org/a-j-wood/pv/issues/56)) Support for backgrounding pv, and allowing it to be monitored separately ([jimbobmcgee](https://github.com/jimbobmcgee))
|
||||
* ([#67](https://codeberg.org/a-j-wood/pv/issues/67)) Wrap another process to monitor its stdin & stdout ([Alex Mason](https://github.com/axman6))
|
||||
* ([#76](https://codeberg.org/a-j-wood/pv/issues/76)) Provide a way to test translations without installing
|
||||
* ([#77](https://codeberg.org/a-j-wood/pv/issues/77)) Eliminate all warnings from "splint" and "flawfinder"
|
||||
|
||||
Any assistance would be appreciated.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH PV 1 "September 2023" Linux "User Manuals"
|
||||
.TH PV 1 "November 2023" Linux "User Manuals"
|
||||
.SH NAME
|
||||
pv \- monitor the progress of data through a pipe
|
||||
.SH SYNOPSIS
|
||||
@@ -689,13 +689,11 @@ before using
|
||||
.IP \(bu 3
|
||||
The
|
||||
.B -R
|
||||
option is not available on Cygwin without
|
||||
.B cygserver
|
||||
running (SYSV IPC is needed). To fix this, start
|
||||
.B cygserver
|
||||
before running the instance of
|
||||
.B pv
|
||||
you want, at runtime, to change the parameters of.
|
||||
option requires that either
|
||||
.B /run/user/<uid>/
|
||||
or
|
||||
.B $HOME/
|
||||
can be written to, for inter-process communication.
|
||||
.P
|
||||
If you find any other problems, please report them.
|
||||
|
||||
|
||||
+2
-4
@@ -517,10 +517,8 @@ The following problems are known to exist in **pv**:
|
||||
is needed to handle the terminal scrolling). To fix this, start
|
||||
**cygserver** before using **pv -c**.
|
||||
|
||||
- The **-R** option is not available on Cygwin without **cygserver**
|
||||
running (SYSV IPC is needed). To fix this, start **cygserver**
|
||||
before running the instance of **pv** you want, at runtime, to
|
||||
change the parameters of.
|
||||
- The **-R** option requires that either **/run/user/\<uid\>/** or
|
||||
**\$HOME/** can be written to, for inter-process communication.
|
||||
|
||||
If you find any other problems, please report them.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: pv@ivarch.com\n"
|
||||
"POT-Creation-Date: 2023-09-24 21:33+0100\n"
|
||||
"POT-Creation-Date: 2023-11-19 14:19+0000\n"
|
||||
"Language: de\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Date: 1999-06-01 15:18:29+0100\n"
|
||||
@@ -20,233 +20,233 @@ msgstr ""
|
||||
"nls/intl/textdomain.c src/nls/intl-cat/cat-compat.c src/nls/intl-gett/intl-"
|
||||
"compat.c\n"
|
||||
|
||||
#: src/main/help.c:283
|
||||
#: src/main/help.c:284
|
||||
msgid "show progress bar"
|
||||
msgstr "Fortschritts-Anzeige"
|
||||
|
||||
#: src/main/help.c:286
|
||||
#: src/main/help.c:287
|
||||
msgid "show elapsed time"
|
||||
msgstr "zeige die verstrichene Zeit an"
|
||||
|
||||
#: src/main/help.c:289
|
||||
#: src/main/help.c:290
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "zeige die erwartete Zeit bis zum Ende an"
|
||||
|
||||
#: src/main/help.c:292
|
||||
#: src/main/help.c:293
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "zeige die absolute geschätzte Zeit bis zur Fertigstellung"
|
||||
|
||||
#: src/main/help.c:295
|
||||
#: src/main/help.c:296
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "zeige die Datentransferrate an"
|
||||
|
||||
#: src/main/help.c:298
|
||||
#: src/main/help.c:299
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:300 src/main/help.c:328 src/main/help.c:340
|
||||
#: src/main/help.c:301 src/main/help.c:329 src/main/help.c:341
|
||||
msgid "SEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:301
|
||||
#: src/main/help.c:302
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:304
|
||||
#: src/main/help.c:305
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "zeige die Anzahl von Bytes, die transferiert worden sind"
|
||||
|
||||
#: src/main/help.c:307
|
||||
#: src/main/help.c:308
|
||||
msgid "show number of bits transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:310
|
||||
#: src/main/help.c:311
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "zeige, wie viel Prozent des Übertragungsbuffers in Benutzung sind"
|
||||
|
||||
#: src/main/help.c:312
|
||||
#: src/main/help.c:313
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:313
|
||||
#: src/main/help.c:314
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "NUM zeige die zuletzt geschriebenen NUM Bytes"
|
||||
|
||||
#: src/main/help.c:315
|
||||
#: src/main/help.c:316
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:316
|
||||
#: src/main/help.c:317
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "setze das Ausgabeformat auf FORMAT"
|
||||
|
||||
#: src/main/help.c:319
|
||||
#: src/main/help.c:320
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "Ausgabe von Prozent-Angaben statt visueller Darstellung"
|
||||
|
||||
#: src/main/help.c:322
|
||||
#: src/main/help.c:323
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "sämtliche Transferinformationen unterdrücken"
|
||||
|
||||
#: src/main/help.c:326
|
||||
#: src/main/help.c:327
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "keine Ausgabe bevor das erste Byte übertragen wurde"
|
||||
|
||||
#: src/main/help.c:329
|
||||
#: src/main/help.c:330
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "SEC nichts anzeigen, bis SEC Sekunden vergangen sind"
|
||||
|
||||
#: src/main/help.c:331
|
||||
#: src/main/help.c:332
|
||||
msgid "SIZE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:332
|
||||
#: src/main/help.c:333
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "setze erwartete Datenlänge auf SIZE Byte"
|
||||
|
||||
#: src/main/help.c:335
|
||||
#: src/main/help.c:336
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "zähle Zeilen anstelle von Bytes"
|
||||
|
||||
#: src/main/help.c:338
|
||||
#: src/main/help.c:339
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "Zeilen sind nullterminiert"
|
||||
|
||||
#: src/main/help.c:341
|
||||
#: src/main/help.c:342
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "aktualisiere Ausgabe nach SEC Sekunden Intervall"
|
||||
|
||||
#: src/main/help.c:343
|
||||
#: src/main/help.c:344
|
||||
msgid "WIDTH"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:344
|
||||
#: src/main/help.c:345
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "setze Terminal-Breite auf WIDTH Zeichen"
|
||||
|
||||
#: src/main/help.c:346
|
||||
#: src/main/help.c:347
|
||||
msgid "HEIGHT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:347
|
||||
#: src/main/help.c:348
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "setze Terminal-Höhe auf HEIGHT Zeichen"
|
||||
|
||||
#: src/main/help.c:349
|
||||
#: src/main/help.c:350
|
||||
msgid "NAME"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:350
|
||||
#: src/main/help.c:351
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "setze den NAMEn für visuelle Darstellung"
|
||||
|
||||
#: src/main/help.c:353
|
||||
#: src/main/help.c:354
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr ""
|
||||
"Ausgabe auch dann erzwingen, wenn der Fehlerausgabe-Kanal kein Terminal ist"
|
||||
|
||||
#: src/main/help.c:356
|
||||
#: src/main/help.c:357
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "benutze Escape-Sequenzen zur Cursor-Positionierung"
|
||||
|
||||
#: src/main/help.c:359
|
||||
#: src/main/help.c:360
|
||||
msgid "RATE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:360
|
||||
#: src/main/help.c:361
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "beschränke die Transferrate auf RATE Byte pro Sekunde"
|
||||
|
||||
#: src/main/help.c:362 src/main/help.c:371
|
||||
#: src/main/help.c:363 src/main/help.c:372
|
||||
msgid "BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:363
|
||||
#: src/main/help.c:364
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "BYTES benutze einen Puffer in der Größe von BYTES"
|
||||
|
||||
#: src/main/help.c:366
|
||||
#: src/main/help.c:367
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "anstelle von splice() immer read/write benutzen"
|
||||
|
||||
#: src/main/help.c:369
|
||||
#: src/main/help.c:370
|
||||
msgid "skip read errors in input"
|
||||
msgstr "Lesefehler in der Eingabe nicht beachten"
|
||||
|
||||
#: src/main/help.c:372
|
||||
#: src/main/help.c:373
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:375
|
||||
#: src/main/help.c:376
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "anhalten, nachdem --size Bytes übertragen wurden"
|
||||
|
||||
#: src/main/help.c:378
|
||||
#: src/main/help.c:379
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:381
|
||||
#: src/main/help.c:382
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:384
|
||||
#: src/main/help.c:385
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:387
|
||||
#: src/main/help.c:388
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:388
|
||||
#: src/main/help.c:389
|
||||
msgid "update settings of process PID"
|
||||
msgstr "Einstellungen der Prozess-PID updaten"
|
||||
|
||||
#: src/main/help.c:392 src/main/help.c:407
|
||||
#: src/main/help.c:393 src/main/help.c:408
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:393
|
||||
#: src/main/help.c:394
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "Prozess-ID in FILE speichern"
|
||||
|
||||
#: src/main/help.c:396
|
||||
#: src/main/help.c:397
|
||||
msgid "PID[:FD]"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:397
|
||||
#: src/main/help.c:398
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "die vom Prozess PID geöffnete Datei FD beobachten"
|
||||
|
||||
#: src/main/help.c:401
|
||||
#: src/main/help.c:402
|
||||
msgid "show this help and exit"
|
||||
msgstr "zeige diese Hilfe und beende"
|
||||
|
||||
#: src/main/help.c:404
|
||||
#: src/main/help.c:405
|
||||
msgid "show version information and exit"
|
||||
msgstr "zeige Versionsinformationen und beende"
|
||||
|
||||
#: src/main/help.c:408
|
||||
#: src/main/help.c:409
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:433
|
||||
#: src/main/help.c:434
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Syntax: %s [OPTION] [DATEI]..."
|
||||
|
||||
#: src/main/help.c:444
|
||||
#: src/main/help.c:445
|
||||
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:581
|
||||
#: src/main/help.c:582
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Bitte senden Sie Fehlerberichte an %s"
|
||||
|
||||
#: src/main/main.c:83
|
||||
#: src/main/main.c:74
|
||||
msgid "state allocation failed"
|
||||
msgstr "Zustandszuweisung fehlgeschlagen"
|
||||
|
||||
@@ -316,13 +316,13 @@ msgstr ""
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "Nicht verfügbar auf Systemen ohne /proc/self/fdinfo"
|
||||
|
||||
#: src/main/remote.c:242
|
||||
#: src/main/remote.c:295
|
||||
msgid "message not received"
|
||||
msgstr "Nachricht nicht empfangen"
|
||||
|
||||
#: src/main/remote.c:351
|
||||
msgid "IPC not supported on this system"
|
||||
msgstr "IPC wird auf diesem System nicht unterstützt"
|
||||
#: src/main/remote.c:422
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO wird auf diesem System nicht unterstützt"
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid "License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
@@ -356,39 +356,39 @@ msgstr "Sperrversuch fehlgeschlagen"
|
||||
msgid "failed to open terminal"
|
||||
msgstr "Terminal konnte nicht geöffnet werden"
|
||||
|
||||
#: src/pv/display.c:187
|
||||
#: src/pv/display.c:192
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:199
|
||||
#: src/pv/display.c:210
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:701 src/pv/transfer.c:894
|
||||
#: src/pv/display.c:746 src/pv/transfer.c:910
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "Puffer konnte nicht allokiert werden"
|
||||
|
||||
#: src/pv/display.c:763
|
||||
#: src/pv/display.c:845
|
||||
msgid "b"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:768 src/pv/transfer.c:584
|
||||
#: src/pv/display.c:848 src/pv/transfer.c:595
|
||||
msgid "B"
|
||||
msgstr "B"
|
||||
|
||||
#: src/pv/display.c:820 src/pv/display.c:833
|
||||
#: src/pv/display.c:890 src/pv/display.c:907
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
#: src/pv/display.c:895 src/pv/display.c:912
|
||||
msgid "/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
#: src/pv/display.c:895 src/pv/display.c:912
|
||||
msgid "B/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:875 src/pv/display.c:879 src/pv/display.c:938
|
||||
#: src/pv/display.c:940 src/pv/display.c:944 src/pv/display.c:1010
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
@@ -420,11 +420,11 @@ msgstr ""
|
||||
msgid "(stdin)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:541 src/pv/loop.c:595 src/pv/loop.c:637 src/pv/watchpid.c:73
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:94 src/pv/watchpid.c:102
|
||||
#: src/pv/watchpid.c:139 src/pv/watchpid.c:150 src/pv/watchpid.c:158
|
||||
#: src/pv/watchpid.c:169 src/pv/watchpid.c:255 src/pv/watchpid.c:263
|
||||
#: src/pv/watchpid.c:294 src/pv/watchpid.c:314
|
||||
#: src/pv/loop.c:570 src/pv/loop.c:621 src/pv/loop.c:662 src/pv/watchpid.c:99
|
||||
#: src/pv/watchpid.c:109 src/pv/watchpid.c:120 src/pv/watchpid.c:128
|
||||
#: src/pv/watchpid.c:165 src/pv/watchpid.c:184 src/pv/watchpid.c:192
|
||||
#: src/pv/watchpid.c:202 src/pv/watchpid.c:293 src/pv/watchpid.c:301
|
||||
#: src/pv/watchpid.c:377 src/pv/watchpid.c:398
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
@@ -432,51 +432,51 @@ msgstr ""
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:385 src/pv/state.c:395
|
||||
#: src/pv/state.c:386 src/pv/state.c:397
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:446
|
||||
#: src/pv/transfer.c:457
|
||||
msgid "read failed"
|
||||
msgstr "read-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:469
|
||||
#: src/pv/transfer.c:480
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "warnung: lesefehler erkannt"
|
||||
|
||||
#: src/pv/transfer.c:485
|
||||
#: src/pv/transfer.c:496
|
||||
msgid "file is not seekable"
|
||||
msgstr "datei ist nicht durchsuchbar"
|
||||
|
||||
#: src/pv/transfer.c:563
|
||||
#: src/pv/transfer.c:574
|
||||
msgid "failed to seek past error"
|
||||
msgstr "konnte den Fehler nicht überwinden"
|
||||
|
||||
#: src/pv/transfer.c:583
|
||||
#: src/pv/transfer.c:594
|
||||
msgid "skipped past read error"
|
||||
msgstr "über den Lesefehler hinaus verschoben"
|
||||
|
||||
#: src/pv/transfer.c:623
|
||||
#: src/pv/transfer.c:634
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:636
|
||||
#: src/pv/transfer.c:647
|
||||
msgid "failed to set alarm signal handler"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:759
|
||||
#: src/pv/transfer.c:774
|
||||
msgid "write failed"
|
||||
msgstr "write-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/transfer.c:985
|
||||
#: src/pv/transfer.c:1007
|
||||
msgid "select call failed"
|
||||
msgstr "select-Aufruf fehlgeschlagen"
|
||||
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:95 src/pv/watchpid.c:104
|
||||
#: src/pv/watchpid.c:150 src/pv/watchpid.c:159 src/pv/watchpid.c:171
|
||||
#: src/pv/watchpid.c:109 src/pv/watchpid.c:121 src/pv/watchpid.c:130
|
||||
#: src/pv/watchpid.c:184 src/pv/watchpid.c:193 src/pv/watchpid.c:204
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:104 src/pv/watchpid.c:171
|
||||
#: src/pv/watchpid.c:130 src/pv/watchpid.c:204
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "keine normale Datei oder Blockgerät"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: pv@ivarch.com\n"
|
||||
"POT-Creation-Date: 2023-09-24 21:33+0100\n"
|
||||
"POT-Creation-Date: 2023-11-19 14:19+0000\n"
|
||||
"Language: fr\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Date: 1999-06-01 15:18:29+0100\n"
|
||||
@@ -20,232 +20,232 @@ msgstr ""
|
||||
"nls/intl/textdomain.c src/nls/intl-cat/cat-compat.c src/nls/intl-gett/intl-"
|
||||
"compat.c\n"
|
||||
|
||||
#: src/main/help.c:283
|
||||
#: src/main/help.c:284
|
||||
msgid "show progress bar"
|
||||
msgstr "affiche la barre de progression"
|
||||
|
||||
#: src/main/help.c:286
|
||||
#: src/main/help.c:287
|
||||
msgid "show elapsed time"
|
||||
msgstr "affiche le temps écoulé"
|
||||
|
||||
#: src/main/help.c:289
|
||||
#: src/main/help.c:290
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "affiche l'heure approximative de l'achèvement de la tâche"
|
||||
|
||||
#: src/main/help.c:292
|
||||
#: src/main/help.c:293
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "affiche l'heure absolute de l'achèvement de la tâche"
|
||||
|
||||
#: src/main/help.c:295
|
||||
#: src/main/help.c:296
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "affiche le taux de tranfert des données"
|
||||
|
||||
#: src/main/help.c:298
|
||||
#: src/main/help.c:299
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "afficher le compteur de taux moyen de transfert de données"
|
||||
|
||||
#: src/main/help.c:300 src/main/help.c:328 src/main/help.c:340
|
||||
#: src/main/help.c:301 src/main/help.c:329 src/main/help.c:341
|
||||
msgid "SEC"
|
||||
msgstr "SEC"
|
||||
|
||||
#: src/main/help.c:301
|
||||
#: src/main/help.c:302
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:304
|
||||
#: src/main/help.c:305
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "affiche le nombre d'octets transférés"
|
||||
|
||||
#: src/main/help.c:307
|
||||
#: src/main/help.c:308
|
||||
msgid "show number of bits transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:310
|
||||
#: src/main/help.c:311
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "afficher le pourcentage de tampon de transfert utilisé"
|
||||
|
||||
#: src/main/help.c:312
|
||||
#: src/main/help.c:313
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:313
|
||||
#: src/main/help.c:314
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "affiche NUM octets pour la dernière fois écrits"
|
||||
|
||||
#: src/main/help.c:315
|
||||
#: src/main/help.c:316
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:316
|
||||
#: src/main/help.c:317
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "définir le format de sortie sur FORMAT"
|
||||
|
||||
#: src/main/help.c:319
|
||||
#: src/main/help.c:320
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "imprime en pourcentage, pas les informations visuelles"
|
||||
|
||||
#: src/main/help.c:322
|
||||
#: src/main/help.c:323
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "n'afficher aucune information de transfert"
|
||||
|
||||
#: src/main/help.c:326
|
||||
#: src/main/help.c:327
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "ne rien afficher avant qu'au moins un octet soit tranféré"
|
||||
|
||||
#: src/main/help.c:329
|
||||
#: src/main/help.c:330
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "n'afficher rien jusqu'à ce que SEC secondes se soient écoulées"
|
||||
|
||||
#: src/main/help.c:331
|
||||
#: src/main/help.c:332
|
||||
msgid "SIZE"
|
||||
msgstr "TAILLE"
|
||||
|
||||
#: src/main/help.c:332
|
||||
#: src/main/help.c:333
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "ajuste la taille estimée des données à TAILLE octets"
|
||||
|
||||
#: src/main/help.c:335
|
||||
#: src/main/help.c:336
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "compte les lignes au lieu des octets"
|
||||
|
||||
#: src/main/help.c:338
|
||||
#: src/main/help.c:339
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "les lignes sont terminées par un nul"
|
||||
|
||||
#: src/main/help.c:341
|
||||
#: src/main/help.c:342
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "mise-à-jour toute les SEC secondes"
|
||||
|
||||
#: src/main/help.c:343
|
||||
#: src/main/help.c:344
|
||||
msgid "WIDTH"
|
||||
msgstr "LARGEUR"
|
||||
|
||||
#: src/main/help.c:344
|
||||
#: src/main/help.c:345
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "présumer la largeur du terminal à LARGEUR caractères"
|
||||
|
||||
#: src/main/help.c:346
|
||||
#: src/main/help.c:347
|
||||
msgid "HEIGHT"
|
||||
msgstr "HAUTEUR"
|
||||
|
||||
#: src/main/help.c:347
|
||||
#: src/main/help.c:348
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "présumer la hauteur du terminal à HAUTEUR lignes"
|
||||
|
||||
#: src/main/help.c:349
|
||||
#: src/main/help.c:350
|
||||
msgid "NAME"
|
||||
msgstr "NOM"
|
||||
|
||||
#: src/main/help.c:350
|
||||
#: src/main/help.c:351
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "préfixer les informations visuelles avec NOM"
|
||||
|
||||
#: src/main/help.c:353
|
||||
#: src/main/help.c:354
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "imprime vers la sortie d'erreur même si ce n'est pas un terminal"
|
||||
|
||||
#: src/main/help.c:356
|
||||
#: src/main/help.c:357
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "utiliser les séquences d'échappements de positionnement de curseur"
|
||||
|
||||
#: src/main/help.c:359
|
||||
#: src/main/help.c:360
|
||||
msgid "RATE"
|
||||
msgstr "TAUX"
|
||||
|
||||
#: src/main/help.c:360
|
||||
#: src/main/help.c:361
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "limite le taux de transfer à TAUX octets par seconde"
|
||||
|
||||
#: src/main/help.c:362 src/main/help.c:371
|
||||
#: src/main/help.c:363 src/main/help.c:372
|
||||
msgid "BYTES"
|
||||
msgstr "OCTETS"
|
||||
|
||||
#: src/main/help.c:363
|
||||
#: src/main/help.c:364
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "Utiliser une mémoire tampon de OCTETS octets"
|
||||
|
||||
#: src/main/help.c:366
|
||||
#: src/main/help.c:367
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "n'utilisez jamais splice(), utilisez toujours read/write"
|
||||
|
||||
#: src/main/help.c:369
|
||||
#: src/main/help.c:370
|
||||
msgid "skip read errors in input"
|
||||
msgstr "ignorer les erreurs de lecture dans l'entrée"
|
||||
|
||||
#: src/main/help.c:372
|
||||
#: src/main/help.c:373
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:375
|
||||
#: src/main/help.c:376
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "arrêter après le transfert de --size octets"
|
||||
|
||||
#: src/main/help.c:378
|
||||
#: src/main/help.c:379
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:381
|
||||
#: src/main/help.c:382
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:384
|
||||
#: src/main/help.c:385
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:387
|
||||
#: src/main/help.c:388
|
||||
msgid "PID"
|
||||
msgstr "PID"
|
||||
|
||||
#: src/main/help.c:388
|
||||
#: src/main/help.c:389
|
||||
msgid "update settings of process PID"
|
||||
msgstr "mettre-à-jour la configuration du processus PID"
|
||||
|
||||
#: src/main/help.c:392 src/main/help.c:407
|
||||
#: src/main/help.c:393 src/main/help.c:408
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:393
|
||||
#: src/main/help.c:394
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "enregistrer l'ID de processus dans FILE"
|
||||
|
||||
#: src/main/help.c:396
|
||||
#: src/main/help.c:397
|
||||
msgid "PID[:FD]"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:397
|
||||
#: src/main/help.c:398
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "regarder le fichier FD ouvert par le processus PID"
|
||||
|
||||
#: src/main/help.c:401
|
||||
#: src/main/help.c:402
|
||||
msgid "show this help and exit"
|
||||
msgstr "afficher cette aide puis quitter"
|
||||
|
||||
#: src/main/help.c:404
|
||||
#: src/main/help.c:405
|
||||
msgid "show version information and exit"
|
||||
msgstr "afficher la version puis quitter"
|
||||
|
||||
#: src/main/help.c:408
|
||||
#: src/main/help.c:409
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:433
|
||||
#: src/main/help.c:434
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Utilisation : %s [OPTIONS] [FICHIER]..."
|
||||
|
||||
#: src/main/help.c:444
|
||||
#: src/main/help.c:445
|
||||
msgid ""
|
||||
"Concatenate FILE(s), or standard input, to standard output, with monitoring."
|
||||
msgstr ""
|
||||
"Concatène FICHIER(s), ou l'entrée standard, sur la sortie standard avec "
|
||||
"monitorage."
|
||||
|
||||
#: src/main/help.c:581
|
||||
#: src/main/help.c:582
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "SVP rapporter touts bogues à %s"
|
||||
|
||||
#: src/main/main.c:83
|
||||
#: src/main/main.c:74
|
||||
msgid "state allocation failed"
|
||||
msgstr "échec de l'allocation de mémoire de condition"
|
||||
|
||||
@@ -317,13 +317,13 @@ msgstr ""
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "non disponible sur les systèmes sans /proc/self/fdinfo"
|
||||
|
||||
#: src/main/remote.c:242
|
||||
#: src/main/remote.c:295
|
||||
msgid "message not received"
|
||||
msgstr "message non reçu"
|
||||
|
||||
#: src/main/remote.c:351
|
||||
msgid "IPC not supported on this system"
|
||||
msgstr "IPC non pris en charge sur ce système"
|
||||
#: src/main/remote.c:422
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO non pris en charge sur ce système"
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid "License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
@@ -357,39 +357,39 @@ msgstr "tentative de verrouillage échoué"
|
||||
msgid "failed to open terminal"
|
||||
msgstr "l'ouverture du terminal a échoué"
|
||||
|
||||
#: src/pv/display.c:187
|
||||
#: src/pv/display.c:192
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:199
|
||||
#: src/pv/display.c:210
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:701 src/pv/transfer.c:894
|
||||
#: src/pv/display.c:746 src/pv/transfer.c:910
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "l'allocation de mémoire tampon a échoué"
|
||||
|
||||
#: src/pv/display.c:763
|
||||
#: src/pv/display.c:845
|
||||
msgid "b"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:768 src/pv/transfer.c:584
|
||||
#: src/pv/display.c:848 src/pv/transfer.c:595
|
||||
msgid "B"
|
||||
msgstr "O"
|
||||
|
||||
#: src/pv/display.c:820 src/pv/display.c:833
|
||||
#: src/pv/display.c:890 src/pv/display.c:907
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
#: src/pv/display.c:895 src/pv/display.c:912
|
||||
msgid "/s"
|
||||
msgstr "/s"
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
#: src/pv/display.c:895 src/pv/display.c:912
|
||||
msgid "B/s"
|
||||
msgstr "O/s"
|
||||
|
||||
#: src/pv/display.c:875 src/pv/display.c:879 src/pv/display.c:938
|
||||
#: src/pv/display.c:940 src/pv/display.c:944 src/pv/display.c:1010
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
@@ -421,11 +421,11 @@ msgstr ""
|
||||
msgid "(stdin)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:541 src/pv/loop.c:595 src/pv/loop.c:637 src/pv/watchpid.c:73
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:94 src/pv/watchpid.c:102
|
||||
#: src/pv/watchpid.c:139 src/pv/watchpid.c:150 src/pv/watchpid.c:158
|
||||
#: src/pv/watchpid.c:169 src/pv/watchpid.c:255 src/pv/watchpid.c:263
|
||||
#: src/pv/watchpid.c:294 src/pv/watchpid.c:314
|
||||
#: src/pv/loop.c:570 src/pv/loop.c:621 src/pv/loop.c:662 src/pv/watchpid.c:99
|
||||
#: src/pv/watchpid.c:109 src/pv/watchpid.c:120 src/pv/watchpid.c:128
|
||||
#: src/pv/watchpid.c:165 src/pv/watchpid.c:184 src/pv/watchpid.c:192
|
||||
#: src/pv/watchpid.c:202 src/pv/watchpid.c:293 src/pv/watchpid.c:301
|
||||
#: src/pv/watchpid.c:377 src/pv/watchpid.c:398
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
@@ -433,51 +433,51 @@ msgstr ""
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:385 src/pv/state.c:395
|
||||
#: src/pv/state.c:386 src/pv/state.c:397
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:446
|
||||
#: src/pv/transfer.c:457
|
||||
msgid "read failed"
|
||||
msgstr "la lecture a échoué"
|
||||
|
||||
#: src/pv/transfer.c:469
|
||||
#: src/pv/transfer.c:480
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "avertissement: erreurs de lecture détectées"
|
||||
|
||||
#: src/pv/transfer.c:485
|
||||
#: src/pv/transfer.c:496
|
||||
msgid "file is not seekable"
|
||||
msgstr "ne peut pas se déplacer dans le fichier"
|
||||
|
||||
#: src/pv/transfer.c:563
|
||||
#: src/pv/transfer.c:574
|
||||
msgid "failed to seek past error"
|
||||
msgstr "n'a pas réussi à dépasser l'erreur"
|
||||
|
||||
#: src/pv/transfer.c:583
|
||||
#: src/pv/transfer.c:594
|
||||
msgid "skipped past read error"
|
||||
msgstr "erreur de lecture dépassée"
|
||||
|
||||
#: src/pv/transfer.c:623
|
||||
#: src/pv/transfer.c:634
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:636
|
||||
#: src/pv/transfer.c:647
|
||||
msgid "failed to set alarm signal handler"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:759
|
||||
#: src/pv/transfer.c:774
|
||||
msgid "write failed"
|
||||
msgstr "l'écriture a échoué"
|
||||
|
||||
#: src/pv/transfer.c:985
|
||||
#: src/pv/transfer.c:1007
|
||||
msgid "select call failed"
|
||||
msgstr "appel de sélection a échoué"
|
||||
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:95 src/pv/watchpid.c:104
|
||||
#: src/pv/watchpid.c:150 src/pv/watchpid.c:159 src/pv/watchpid.c:171
|
||||
#: src/pv/watchpid.c:109 src/pv/watchpid.c:121 src/pv/watchpid.c:130
|
||||
#: src/pv/watchpid.c:184 src/pv/watchpid.c:193 src/pv/watchpid.c:204
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:104 src/pv/watchpid.c:171
|
||||
#: src/pv/watchpid.c:130 src/pv/watchpid.c:204
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "pas un fichier ordinaire ou un périphérique de bloc"
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: pv@ivarch.com\n"
|
||||
"POT-Creation-Date: 2023-09-24 21:33+0100\n"
|
||||
"POT-Creation-Date: 2023-11-19 14:19+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"
|
||||
@@ -15,232 +15,232 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/main/help.c:283
|
||||
#: src/main/help.c:284
|
||||
msgid "show progress bar"
|
||||
msgstr "pokaż pasek postępu"
|
||||
|
||||
#: src/main/help.c:286
|
||||
#: src/main/help.c:287
|
||||
msgid "show elapsed time"
|
||||
msgstr "pokaż upływający czas"
|
||||
|
||||
#: src/main/help.c:289
|
||||
#: src/main/help.c:290
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "pokaż szacowany czas ukończenia"
|
||||
|
||||
#: src/main/help.c:292
|
||||
#: src/main/help.c:293
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:295
|
||||
#: src/main/help.c:296
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "pokaż licznik prędkości przesyłania"
|
||||
|
||||
#: src/main/help.c:298
|
||||
#: src/main/help.c:299
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:300 src/main/help.c:328 src/main/help.c:340
|
||||
#: src/main/help.c:301 src/main/help.c:329 src/main/help.c:341
|
||||
msgid "SEC"
|
||||
msgstr "WARTOŚĆ"
|
||||
|
||||
#: src/main/help.c:301
|
||||
#: src/main/help.c:302
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:304
|
||||
#: src/main/help.c:305
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "pokaż ilość przesłanych bajtów"
|
||||
|
||||
#: src/main/help.c:307
|
||||
#: src/main/help.c:308
|
||||
msgid "show number of bits transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:310
|
||||
#: src/main/help.c:311
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:312
|
||||
#: src/main/help.c:313
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:313
|
||||
#: src/main/help.c:314
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:315
|
||||
#: src/main/help.c:316
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:316
|
||||
#: src/main/help.c:317
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:319
|
||||
#: src/main/help.c:320
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "wświetl wyjście procentowo, bez graficznej prezentacji"
|
||||
|
||||
#: src/main/help.c:322
|
||||
#: src/main/help.c:323
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "nie wyświetlaj żadnych informacji o przesyłaniu"
|
||||
|
||||
#: src/main/help.c:326
|
||||
#: src/main/help.c:327
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "nie wyświetlaj nic aż do pierwszego przesłanego bajtu"
|
||||
|
||||
#: src/main/help.c:329
|
||||
#: src/main/help.c:330
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:331
|
||||
#: src/main/help.c:332
|
||||
msgid "SIZE"
|
||||
msgstr "WARTOŚĆ"
|
||||
|
||||
#: src/main/help.c:332
|
||||
#: src/main/help.c:333
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "ustaw oczekiwany rozmiar danych na WARTOŚĆ bajtów"
|
||||
|
||||
#: src/main/help.c:335
|
||||
#: src/main/help.c:336
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:338
|
||||
#: src/main/help.c:339
|
||||
msgid "lines are null-terminated"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:341
|
||||
#: src/main/help.c:342
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "aktualizuj co każde WARTOŚĆ sekund"
|
||||
|
||||
#: src/main/help.c:343
|
||||
#: src/main/help.c:344
|
||||
msgid "WIDTH"
|
||||
msgstr "WARTOŚĆ"
|
||||
|
||||
#: src/main/help.c:344
|
||||
#: src/main/help.c:345
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "przyjmij, że terminal ma szerokość WARTOŚĆ znaków"
|
||||
|
||||
#: src/main/help.c:346
|
||||
#: src/main/help.c:347
|
||||
msgid "HEIGHT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:347
|
||||
#: src/main/help.c:348
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "przyjmij, że terminal ma szerokość WARTOŚĆ znaków"
|
||||
|
||||
#: src/main/help.c:349
|
||||
#: src/main/help.c:350
|
||||
msgid "NAME"
|
||||
msgstr "NAZWA"
|
||||
|
||||
#: src/main/help.c:350
|
||||
#: src/main/help.c:351
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "poprzedź informacje prefiksem NAZWA"
|
||||
|
||||
#: src/main/help.c:353
|
||||
#: src/main/help.c:354
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "pokaż wyjście nawet gdy błędy nie są typu terminal"
|
||||
|
||||
#: src/main/help.c:356
|
||||
#: src/main/help.c:357
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "używaj sekwencji escape do pozycjonowania"
|
||||
|
||||
#: src/main/help.c:359
|
||||
#: src/main/help.c:360
|
||||
msgid "RATE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:360
|
||||
#: src/main/help.c:361
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "ogranicz przesyłane dane do RATE bajtów na sekundę"
|
||||
|
||||
#: src/main/help.c:362 src/main/help.c:371
|
||||
#: src/main/help.c:363 src/main/help.c:372
|
||||
msgid "BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:363
|
||||
#: src/main/help.c:364
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:366
|
||||
#: src/main/help.c:367
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:369
|
||||
#: src/main/help.c:370
|
||||
msgid "skip read errors in input"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:372
|
||||
#: src/main/help.c:373
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:375
|
||||
#: src/main/help.c:376
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:378
|
||||
#: src/main/help.c:379
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:381
|
||||
#: src/main/help.c:382
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:384
|
||||
#: src/main/help.c:385
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:387
|
||||
#: src/main/help.c:388
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:388
|
||||
#: src/main/help.c:389
|
||||
msgid "update settings of process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:392 src/main/help.c:407
|
||||
#: src/main/help.c:393 src/main/help.c:408
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:393
|
||||
#: src/main/help.c:394
|
||||
msgid "save process ID in FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:396
|
||||
#: src/main/help.c:397
|
||||
msgid "PID[:FD]"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:397
|
||||
#: src/main/help.c:398
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:401
|
||||
#: src/main/help.c:402
|
||||
msgid "show this help and exit"
|
||||
msgstr "wyświetl te informacje z pomocą i wyjdź"
|
||||
|
||||
#: src/main/help.c:404
|
||||
#: src/main/help.c:405
|
||||
msgid "show version information and exit"
|
||||
msgstr "wyświetl informacje o wersji i wyjdź"
|
||||
|
||||
#: src/main/help.c:408
|
||||
#: src/main/help.c:409
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:433
|
||||
#: src/main/help.c:434
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Sposób użycia: %s [OPCJA] [PLIK]..."
|
||||
|
||||
#: src/main/help.c:444
|
||||
#: src/main/help.c:445
|
||||
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:581
|
||||
#: src/main/help.c:582
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Proszę przesyłać zgłoszenia błędów do %s"
|
||||
|
||||
#: src/main/main.c:83
|
||||
#: src/main/main.c:74
|
||||
msgid "state allocation failed"
|
||||
msgstr ""
|
||||
|
||||
@@ -304,12 +304,12 @@ msgstr ""
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:242
|
||||
#: src/main/remote.c:295
|
||||
msgid "message not received"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/remote.c:351
|
||||
msgid "IPC not supported on this system"
|
||||
#: src/main/remote.c:422
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/version.c:28
|
||||
@@ -345,39 +345,39 @@ msgstr ""
|
||||
msgid "failed to open terminal"
|
||||
msgstr "nie udało się otworzyć terminala"
|
||||
|
||||
#: src/pv/display.c:187
|
||||
#: src/pv/display.c:192
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:199
|
||||
#: src/pv/display.c:210
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:701 src/pv/transfer.c:894
|
||||
#: src/pv/display.c:746 src/pv/transfer.c:910
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "nie udało się zaalokować bufora"
|
||||
|
||||
#: src/pv/display.c:763
|
||||
#: src/pv/display.c:845
|
||||
msgid "b"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:768 src/pv/transfer.c:584
|
||||
#: src/pv/display.c:848 src/pv/transfer.c:595
|
||||
msgid "B"
|
||||
msgstr "B"
|
||||
|
||||
#: src/pv/display.c:820 src/pv/display.c:833
|
||||
#: src/pv/display.c:890 src/pv/display.c:907
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
#: src/pv/display.c:895 src/pv/display.c:912
|
||||
msgid "/s"
|
||||
msgstr "/s"
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
#: src/pv/display.c:895 src/pv/display.c:912
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
#: src/pv/display.c:875 src/pv/display.c:879 src/pv/display.c:938
|
||||
#: src/pv/display.c:940 src/pv/display.c:944 src/pv/display.c:1010
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
@@ -410,11 +410,11 @@ msgstr ""
|
||||
msgid "(stdin)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:541 src/pv/loop.c:595 src/pv/loop.c:637 src/pv/watchpid.c:73
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:94 src/pv/watchpid.c:102
|
||||
#: src/pv/watchpid.c:139 src/pv/watchpid.c:150 src/pv/watchpid.c:158
|
||||
#: src/pv/watchpid.c:169 src/pv/watchpid.c:255 src/pv/watchpid.c:263
|
||||
#: src/pv/watchpid.c:294 src/pv/watchpid.c:314
|
||||
#: src/pv/loop.c:570 src/pv/loop.c:621 src/pv/loop.c:662 src/pv/watchpid.c:99
|
||||
#: src/pv/watchpid.c:109 src/pv/watchpid.c:120 src/pv/watchpid.c:128
|
||||
#: src/pv/watchpid.c:165 src/pv/watchpid.c:184 src/pv/watchpid.c:192
|
||||
#: src/pv/watchpid.c:202 src/pv/watchpid.c:293 src/pv/watchpid.c:301
|
||||
#: src/pv/watchpid.c:377 src/pv/watchpid.c:398
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
@@ -422,51 +422,51 @@ msgstr ""
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:385 src/pv/state.c:395
|
||||
#: src/pv/state.c:386 src/pv/state.c:397
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:446
|
||||
#: src/pv/transfer.c:457
|
||||
msgid "read failed"
|
||||
msgstr "błąd odczytu"
|
||||
|
||||
#: src/pv/transfer.c:469
|
||||
#: src/pv/transfer.c:480
|
||||
msgid "warning: read errors detected"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:485
|
||||
#: src/pv/transfer.c:496
|
||||
msgid "file is not seekable"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:563
|
||||
#: src/pv/transfer.c:574
|
||||
msgid "failed to seek past error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:583
|
||||
#: src/pv/transfer.c:594
|
||||
msgid "skipped past read error"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:623
|
||||
#: src/pv/transfer.c:634
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:636
|
||||
#: src/pv/transfer.c:647
|
||||
msgid "failed to set alarm signal handler"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:759
|
||||
#: src/pv/transfer.c:774
|
||||
msgid "write failed"
|
||||
msgstr "błąd zapisu"
|
||||
|
||||
#: src/pv/transfer.c:985
|
||||
#: src/pv/transfer.c:1007
|
||||
msgid "select call failed"
|
||||
msgstr "nie udało się wywołać funkcji select"
|
||||
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:95 src/pv/watchpid.c:104
|
||||
#: src/pv/watchpid.c:150 src/pv/watchpid.c:159 src/pv/watchpid.c:171
|
||||
#: src/pv/watchpid.c:109 src/pv/watchpid.c:121 src/pv/watchpid.c:130
|
||||
#: src/pv/watchpid.c:184 src/pv/watchpid.c:193 src/pv/watchpid.c:204
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:104 src/pv/watchpid.c:171
|
||||
#: src/pv/watchpid.c:130 src/pv/watchpid.c:204
|
||||
msgid "not a regular file or block device"
|
||||
msgstr ""
|
||||
|
||||
@@ -6,7 +6,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: pv@ivarch.com\n"
|
||||
"POT-Creation-Date: 2023-09-24 21:33+0100\n"
|
||||
"POT-Creation-Date: 2023-11-19 14:19+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"
|
||||
@@ -15,232 +15,232 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/main/help.c:283
|
||||
#: src/main/help.c:284
|
||||
msgid "show progress bar"
|
||||
msgstr "exibe barra de progressão"
|
||||
|
||||
#: src/main/help.c:286
|
||||
#: src/main/help.c:287
|
||||
msgid "show elapsed time"
|
||||
msgstr "exibe tempo passado"
|
||||
|
||||
#: src/main/help.c:289
|
||||
#: src/main/help.c:290
|
||||
msgid "show estimated time of arrival (completion)"
|
||||
msgstr "exibe o tempo estimado de término"
|
||||
|
||||
#: src/main/help.c:292
|
||||
#: src/main/help.c:293
|
||||
msgid "show absolute estimated time of arrival (completion)"
|
||||
msgstr "exibe o tempo absoluto estimado de término"
|
||||
|
||||
#: src/main/help.c:295
|
||||
#: src/main/help.c:296
|
||||
msgid "show data transfer rate counter"
|
||||
msgstr "exibe a taxa de transferência"
|
||||
|
||||
#: src/main/help.c:298
|
||||
#: src/main/help.c:299
|
||||
msgid "show data transfer average rate counter"
|
||||
msgstr "exibe o contador da taxa média de transferência de dados"
|
||||
|
||||
#: src/main/help.c:300 src/main/help.c:328 src/main/help.c:340
|
||||
#: src/main/help.c:301 src/main/help.c:329 src/main/help.c:341
|
||||
msgid "SEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:301
|
||||
#: src/main/help.c:302
|
||||
msgid "compute average rate over past SEC seconds (default 30s)"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:304
|
||||
#: src/main/help.c:305
|
||||
msgid "show number of bytes transferred"
|
||||
msgstr "exibe a quantidade de bytes transferidos"
|
||||
|
||||
#: src/main/help.c:307
|
||||
#: src/main/help.c:308
|
||||
msgid "show number of bits transferred"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:310
|
||||
#: src/main/help.c:311
|
||||
msgid "show percentage of transfer buffer in use"
|
||||
msgstr "exibe a porcentagem de buffer de transferência em uso"
|
||||
|
||||
#: src/main/help.c:312
|
||||
#: src/main/help.c:313
|
||||
msgid "NUM"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:313
|
||||
#: src/main/help.c:314
|
||||
msgid "show NUM bytes last written"
|
||||
msgstr "exibe NUM bytes gravados pela última vez"
|
||||
|
||||
#: src/main/help.c:315
|
||||
#: src/main/help.c:316
|
||||
msgid "FORMAT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:316
|
||||
#: src/main/help.c:317
|
||||
msgid "set output format to FORMAT"
|
||||
msgstr "definir o formato de saída para FORMAT"
|
||||
|
||||
#: src/main/help.c:319
|
||||
#: src/main/help.c:320
|
||||
msgid "output percentages, not visual information"
|
||||
msgstr "exibe apenas as porcentagens, sem informações visuais"
|
||||
|
||||
#: src/main/help.c:322
|
||||
#: src/main/help.c:323
|
||||
msgid "do not output any transfer information at all"
|
||||
msgstr "executa programa sem exibir quaisquer informações"
|
||||
|
||||
#: src/main/help.c:326
|
||||
#: src/main/help.c:327
|
||||
msgid "display nothing until first byte transferred"
|
||||
msgstr "não exibe nada até iniciar o processamento"
|
||||
|
||||
#: src/main/help.c:329
|
||||
#: src/main/help.c:330
|
||||
msgid "display nothing until SEC seconds have passed"
|
||||
msgstr "não exibir nada até que os segundos SEC tenham passado"
|
||||
|
||||
#: src/main/help.c:331
|
||||
#: src/main/help.c:332
|
||||
msgid "SIZE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:332
|
||||
#: src/main/help.c:333
|
||||
msgid "set estimated data size to SIZE bytes"
|
||||
msgstr "seta a quantidade estimada de dados em SIZE bytes"
|
||||
|
||||
#: src/main/help.c:335
|
||||
#: src/main/help.c:336
|
||||
msgid "count lines instead of bytes"
|
||||
msgstr "contar linhas em vez de bytes"
|
||||
|
||||
#: src/main/help.c:338
|
||||
#: src/main/help.c:339
|
||||
msgid "lines are null-terminated"
|
||||
msgstr "linhas são terminadas em nulo"
|
||||
|
||||
#: src/main/help.c:341
|
||||
#: src/main/help.c:342
|
||||
msgid "update every SEC seconds"
|
||||
msgstr "atualiza informações a cada SEC segundos"
|
||||
|
||||
#: src/main/help.c:343
|
||||
#: src/main/help.c:344
|
||||
msgid "WIDTH"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:344
|
||||
#: src/main/help.c:345
|
||||
msgid "assume terminal is WIDTH characters wide"
|
||||
msgstr "presuma que o terminal tem WIDTH caracteres de largura"
|
||||
|
||||
#: src/main/help.c:346
|
||||
#: src/main/help.c:347
|
||||
msgid "HEIGHT"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:347
|
||||
#: src/main/help.c:348
|
||||
msgid "assume terminal is HEIGHT rows high"
|
||||
msgstr "presuma que o terminal tem HEIGHT caracteres de altura"
|
||||
|
||||
#: src/main/help.c:349
|
||||
#: src/main/help.c:350
|
||||
msgid "NAME"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:350
|
||||
#: src/main/help.c:351
|
||||
msgid "prefix visual information with NAME"
|
||||
msgstr "exibe NAME antes das demais informações"
|
||||
|
||||
#: src/main/help.c:353
|
||||
#: src/main/help.c:354
|
||||
msgid "output even if standard error is not a terminal"
|
||||
msgstr "gera dados mesmo que a saída de erro seja redirecionada"
|
||||
|
||||
#: src/main/help.c:356
|
||||
#: src/main/help.c:357
|
||||
msgid "use cursor positioning escape sequences"
|
||||
msgstr "utiliza caracteres de escape para posicionar o cursor"
|
||||
|
||||
#: src/main/help.c:359
|
||||
#: src/main/help.c:360
|
||||
msgid "RATE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:360
|
||||
#: src/main/help.c:361
|
||||
msgid "limit transfer to RATE bytes per second"
|
||||
msgstr "limita a transferência a RATE bytes por segundo"
|
||||
|
||||
#: src/main/help.c:362 src/main/help.c:371
|
||||
#: src/main/help.c:363 src/main/help.c:372
|
||||
msgid "BYTES"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:363
|
||||
#: src/main/help.c:364
|
||||
msgid "use a buffer size of BYTES"
|
||||
msgstr "use um tamanho de buffer de BYTES"
|
||||
|
||||
#: src/main/help.c:366
|
||||
#: src/main/help.c:367
|
||||
msgid "never use splice(), always use read/write"
|
||||
msgstr "nunca use splice(), sempre use read/write"
|
||||
|
||||
#: src/main/help.c:369
|
||||
#: src/main/help.c:370
|
||||
msgid "skip read errors in input"
|
||||
msgstr "ignorar erros de leitura em entrada"
|
||||
|
||||
#: src/main/help.c:372
|
||||
#: src/main/help.c:373
|
||||
msgid "skip errors in BYTES blocks at a time"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:375
|
||||
#: src/main/help.c:376
|
||||
msgid "stop after --size bytes have been transferred"
|
||||
msgstr "parar após --size bytes terem sido transferidos"
|
||||
|
||||
#: src/main/help.c:378
|
||||
#: src/main/help.c:379
|
||||
msgid "flush cache to disk after every write"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:381
|
||||
#: src/main/help.c:382
|
||||
msgid "use direct I/O to bypass cache"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:384
|
||||
#: src/main/help.c:385
|
||||
msgid "discard input instead of writing to output"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:387
|
||||
#: src/main/help.c:388
|
||||
msgid "PID"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:388
|
||||
#: src/main/help.c:389
|
||||
msgid "update settings of process PID"
|
||||
msgstr "atualizar as configurações do processo PID"
|
||||
|
||||
#: src/main/help.c:392 src/main/help.c:407
|
||||
#: src/main/help.c:393 src/main/help.c:408
|
||||
msgid "FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:393
|
||||
#: src/main/help.c:394
|
||||
msgid "save process ID in FILE"
|
||||
msgstr "salvar ID do processo em FILE"
|
||||
|
||||
#: src/main/help.c:396
|
||||
#: src/main/help.c:397
|
||||
msgid "PID[:FD]"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:397
|
||||
#: src/main/help.c:398
|
||||
msgid "watch file FD opened by process PID"
|
||||
msgstr "assistir arquivo FD aberto pelo processo PID"
|
||||
|
||||
#: src/main/help.c:401
|
||||
#: src/main/help.c:402
|
||||
msgid "show this help and exit"
|
||||
msgstr "exibe esta tela de ajuda e termina"
|
||||
|
||||
#: src/main/help.c:404
|
||||
#: src/main/help.c:405
|
||||
msgid "show version information and exit"
|
||||
msgstr "exibe a versão e termina"
|
||||
|
||||
#: src/main/help.c:408
|
||||
#: src/main/help.c:409
|
||||
msgid "write debug logs to FILE"
|
||||
msgstr ""
|
||||
|
||||
#: src/main/help.c:433
|
||||
#: src/main/help.c:434
|
||||
#, c-format
|
||||
msgid "Usage: %s [OPTION] [FILE]..."
|
||||
msgstr "Uso: %s [OPÇÕES] [ARQUIVOS]..."
|
||||
|
||||
#: src/main/help.c:444
|
||||
#: src/main/help.c:445
|
||||
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:581
|
||||
#: src/main/help.c:582
|
||||
#, c-format
|
||||
msgid "Please report any bugs to: %s"
|
||||
msgstr "Por favor, reporte quaisquer defeitos para %s"
|
||||
|
||||
#: src/main/main.c:83
|
||||
#: src/main/main.c:74
|
||||
msgid "state allocation failed"
|
||||
msgstr "alocação de memória de status falhou"
|
||||
|
||||
@@ -308,13 +308,13 @@ msgstr "não pode transferir arquivos ao assistir descritores de arquivo"
|
||||
msgid "not available on systems without /proc/self/fdinfo"
|
||||
msgstr "não disponível em sistemas sem /proc/self/fdinfo"
|
||||
|
||||
#: src/main/remote.c:242
|
||||
#: src/main/remote.c:295
|
||||
msgid "message not received"
|
||||
msgstr "mensagem não recebida"
|
||||
|
||||
#: src/main/remote.c:351
|
||||
msgid "IPC not supported on this system"
|
||||
msgstr "IPC não suportado neste sistema"
|
||||
#: src/main/remote.c:422
|
||||
msgid "SA_SIGINFO not supported on this system"
|
||||
msgstr "SA_SIGINFO não suportado neste sistema"
|
||||
|
||||
#: src/main/version.c:28
|
||||
msgid "License: GPLv3+ <https://www.gnu.org/licenses/gpl-3.0.html>"
|
||||
@@ -348,39 +348,39 @@ msgstr "tentativa de bloqueio falhou"
|
||||
msgid "failed to open terminal"
|
||||
msgstr "erro abrindo o terminal"
|
||||
|
||||
#: src/pv/display.c:187
|
||||
#: src/pv/display.c:192
|
||||
msgid "yzafpnum kMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:199
|
||||
#: src/pv/display.c:210
|
||||
msgid "yzafpnum KMGTPEZY"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:701 src/pv/transfer.c:894
|
||||
#: src/pv/display.c:746 src/pv/transfer.c:910
|
||||
msgid "buffer allocation failed"
|
||||
msgstr "erro alocando o buffer"
|
||||
|
||||
#: src/pv/display.c:763
|
||||
#: src/pv/display.c:845
|
||||
msgid "b"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:768 src/pv/transfer.c:584
|
||||
#: src/pv/display.c:848 src/pv/transfer.c:595
|
||||
msgid "B"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:820 src/pv/display.c:833
|
||||
#: src/pv/display.c:890 src/pv/display.c:907
|
||||
msgid "b/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
#: src/pv/display.c:895 src/pv/display.c:912
|
||||
msgid "/s"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/display.c:824 src/pv/display.c:838
|
||||
#: src/pv/display.c:895 src/pv/display.c:912
|
||||
msgid "B/s"
|
||||
msgstr "B/s"
|
||||
|
||||
#: src/pv/display.c:875 src/pv/display.c:879 src/pv/display.c:938
|
||||
#: src/pv/display.c:940 src/pv/display.c:944 src/pv/display.c:1010
|
||||
msgid "ETA"
|
||||
msgstr "ETA"
|
||||
|
||||
@@ -412,11 +412,11 @@ msgstr ""
|
||||
msgid "(stdin)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/loop.c:541 src/pv/loop.c:595 src/pv/loop.c:637 src/pv/watchpid.c:73
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:94 src/pv/watchpid.c:102
|
||||
#: src/pv/watchpid.c:139 src/pv/watchpid.c:150 src/pv/watchpid.c:158
|
||||
#: src/pv/watchpid.c:169 src/pv/watchpid.c:255 src/pv/watchpid.c:263
|
||||
#: src/pv/watchpid.c:294 src/pv/watchpid.c:314
|
||||
#: src/pv/loop.c:570 src/pv/loop.c:621 src/pv/loop.c:662 src/pv/watchpid.c:99
|
||||
#: src/pv/watchpid.c:109 src/pv/watchpid.c:120 src/pv/watchpid.c:128
|
||||
#: src/pv/watchpid.c:165 src/pv/watchpid.c:184 src/pv/watchpid.c:192
|
||||
#: src/pv/watchpid.c:202 src/pv/watchpid.c:293 src/pv/watchpid.c:301
|
||||
#: src/pv/watchpid.c:377 src/pv/watchpid.c:398
|
||||
msgid "pid"
|
||||
msgstr ""
|
||||
|
||||
@@ -424,51 +424,51 @@ msgstr ""
|
||||
msgid "history structure allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/state.c:385 src/pv/state.c:395
|
||||
#: src/pv/state.c:386 src/pv/state.c:397
|
||||
msgid "file list allocation failed"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:446
|
||||
#: src/pv/transfer.c:457
|
||||
msgid "read failed"
|
||||
msgstr "erro de leitura"
|
||||
|
||||
#: src/pv/transfer.c:469
|
||||
#: src/pv/transfer.c:480
|
||||
msgid "warning: read errors detected"
|
||||
msgstr "aviso: erros de leitura detectados"
|
||||
|
||||
#: src/pv/transfer.c:485
|
||||
#: src/pv/transfer.c:496
|
||||
msgid "file is not seekable"
|
||||
msgstr "não pode mover dentro do arquivo"
|
||||
|
||||
#: src/pv/transfer.c:563
|
||||
#: src/pv/transfer.c:574
|
||||
msgid "failed to seek past error"
|
||||
msgstr "não pode ir além do erro"
|
||||
|
||||
#: src/pv/transfer.c:583
|
||||
#: src/pv/transfer.c:594
|
||||
msgid "skipped past read error"
|
||||
msgstr "ignorado erro de leitura"
|
||||
|
||||
#: src/pv/transfer.c:623
|
||||
#: src/pv/transfer.c:634
|
||||
msgid "no transfer buffer allocated"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:636
|
||||
#: src/pv/transfer.c:647
|
||||
msgid "failed to set alarm signal handler"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/transfer.c:759
|
||||
#: src/pv/transfer.c:774
|
||||
msgid "write failed"
|
||||
msgstr "erro de gravação"
|
||||
|
||||
#: src/pv/transfer.c:985
|
||||
#: src/pv/transfer.c:1007
|
||||
msgid "select call failed"
|
||||
msgstr "erro na chamada da função select"
|
||||
|
||||
#: src/pv/watchpid.c:83 src/pv/watchpid.c:95 src/pv/watchpid.c:104
|
||||
#: src/pv/watchpid.c:150 src/pv/watchpid.c:159 src/pv/watchpid.c:171
|
||||
#: src/pv/watchpid.c:109 src/pv/watchpid.c:121 src/pv/watchpid.c:130
|
||||
#: src/pv/watchpid.c:184 src/pv/watchpid.c:193 src/pv/watchpid.c:204
|
||||
msgid "fd"
|
||||
msgstr ""
|
||||
|
||||
#: src/pv/watchpid.c:104 src/pv/watchpid.c:171
|
||||
#: src/pv/watchpid.c:130 src/pv/watchpid.c:204
|
||||
msgid "not a regular file or block device"
|
||||
msgstr "não é um arquivo regular ou dispositivo de bloqueio"
|
||||
|
||||
@@ -79,15 +79,15 @@
|
||||
/* Define to 1 if you have the `memmove' function. */
|
||||
#undef HAVE_MEMMOVE
|
||||
|
||||
/* Define to 1 if you have the `memrchr' function. */
|
||||
#undef HAVE_MEMRCHR
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#undef HAVE_MEMSET
|
||||
|
||||
/* Define to 1 if you have the <minix/config.h> header file. */
|
||||
#undef HAVE_MINIX_CONFIG_H
|
||||
|
||||
/* Define to 1 if you have the `msgget' function. */
|
||||
#undef HAVE_MSGGET
|
||||
|
||||
/* Define to 1 if you have the `nanosleep' function. */
|
||||
#undef HAVE_NANOSLEEP
|
||||
|
||||
@@ -103,6 +103,9 @@
|
||||
/* Define to 1 if you have the `setlocale' function. */
|
||||
#undef HAVE_SETLOCALE
|
||||
|
||||
/* Define to 1 if you have the `shmget' function. */
|
||||
#undef HAVE_SHMGET
|
||||
|
||||
/* Define to 1 if you have the `splice' function. */
|
||||
#undef HAVE_SPLICE
|
||||
|
||||
@@ -157,9 +160,6 @@
|
||||
/* Define to 1 if you have the <sys/ipc.h> header file. */
|
||||
#undef HAVE_SYS_IPC_H
|
||||
|
||||
/* Define to 1 if you have the <sys/msg.h> header file. */
|
||||
#undef HAVE_SYS_MSG_H
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#undef HAVE_SYS_PARAM_H
|
||||
|
||||
|
||||
+192
-161
@@ -20,16 +20,25 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PV_DISPLAY_PROGRESS 1
|
||||
#define PV_DISPLAY_TIMER 2
|
||||
#define PV_DISPLAY_ETA 4
|
||||
#define PV_DISPLAY_RATE 8
|
||||
#define PV_DISPLAY_AVERAGERATE 16
|
||||
#define PV_DISPLAY_BYTES 32
|
||||
#define PV_DISPLAY_NAME 64
|
||||
#define PV_DISPLAY_BUFPERCENT 128
|
||||
#define PV_DISPLAY_OUTPUTBUF 256
|
||||
#define PV_DISPLAY_FINETA 512
|
||||
/*
|
||||
* Types of display component that make up an output string.
|
||||
*/
|
||||
typedef enum {
|
||||
PV_COMPONENT_STRING, /* fixed string */
|
||||
PV_COMPONENT_PROGRESS, /* progress bar, with percentage if known */
|
||||
PV_COMPONENT_BYTES, /* number of bytes transferred */
|
||||
PV_COMPONENT_TIMER, /* elapsed time */
|
||||
PV_COMPONENT_RATE, /* current transfer rate */
|
||||
PV_COMPONENT_AVERAGERATE, /* average transfer rate */
|
||||
PV_COMPONENT_ETA, /* estimated time remaining until completion */
|
||||
PV_COMPONENT_FINETA, /* estimated time of completion */
|
||||
PV_COMPONENT_NAME, /* name prefix */
|
||||
PV_COMPONENT_BUFPERCENT, /* percentage of buffer used */
|
||||
PV_COMPONENT_OUTPUTBUF, /* recent bytes in output buffer */
|
||||
PV_COMPONENT__MAX
|
||||
} pv_display_component;
|
||||
|
||||
#define PV_SIZEOF_COMPONENT_STR 1024 /* size of buffer for each component */
|
||||
|
||||
#define RATE_GRANULARITY 100000000 /* nsec between -L rate chunks */
|
||||
#define RATE_BURST_WINDOW 5 /* rate burst window (multiples of rate) */
|
||||
@@ -43,25 +52,9 @@ extern "C" {
|
||||
|
||||
#define MAXIMISE_BUFFER_FILL 1
|
||||
|
||||
|
||||
typedef struct pvhistory {
|
||||
off_t total_bytes;
|
||||
long double elapsed_sec;
|
||||
} pvhistory_t;
|
||||
|
||||
#define PV_SIZEOF_DEFAULT_FORMAT 512
|
||||
#define PV_SIZEOF_CWD 4096
|
||||
#define PV_SIZEOF_LASTOUTPUT_BUFFER 256
|
||||
#define PV_SIZEOF_STR_NAME 512
|
||||
#define PV_SIZEOF_STR_TRANSFERRED 128
|
||||
#define PV_SIZEOF_STR_BUFPERCENT 128
|
||||
#define PV_SIZEOF_STR_TIMER 128
|
||||
#define PV_SIZEOF_STR_RATE 128
|
||||
#define PV_SIZEOF_STR_AVERAGE_RATE 128
|
||||
#define PV_SIZEOF_STR_PROGRESS 1024
|
||||
#define PV_SIZEOF_STR_LASTOUTPUT 512
|
||||
#define PV_SIZEOF_STR_ETA 128
|
||||
#define PV_SIZEOF_STR_FINETA 128
|
||||
#define PV_FORMAT_ARRAY_MAX 100
|
||||
#define PV_SIZEOF_CRS_LOCK_FILE 1024
|
||||
|
||||
@@ -84,129 +77,161 @@ struct pvcursorstate_s {
|
||||
* Structure for holding PV internal state. Opaque outside the PV library.
|
||||
*/
|
||||
struct pvstate_s {
|
||||
/******************
|
||||
* Program status *
|
||||
******************/
|
||||
struct {
|
||||
/*@only@*/ char *program_name; /* program name for error reporting */
|
||||
char cwd[PV_SIZEOF_CWD]; /* current working directory for relative path */
|
||||
int current_input_file; /* index of current file being read */
|
||||
int exit_status; /* exit status to give (0=OK) */
|
||||
} status;
|
||||
|
||||
/***************
|
||||
* Input files *
|
||||
***************/
|
||||
unsigned int input_file_count; /* number of input files */
|
||||
/*@only@*/ /*@null@*/ char **input_files; /* input files */
|
||||
struct {
|
||||
unsigned int file_count; /* number of input files */
|
||||
/*@only@*/ /*@null@*/ char **filename; /* input filenames */
|
||||
} files;
|
||||
|
||||
/*******************
|
||||
* Program control *
|
||||
*******************/
|
||||
bool force; /* display even if not on terminal */
|
||||
bool cursor; /* use cursor positioning */
|
||||
bool numeric; /* numeric output only */
|
||||
bool wait; /* wait for data before display */
|
||||
bool linemode; /* count lines instead of bytes */
|
||||
bool bits; /* report bits instead of bytes */
|
||||
bool null_terminated_lines; /* lines are null-terminated */
|
||||
bool no_display; /* do nothing other than pipe data */
|
||||
unsigned int skip_errors; /* skip read errors counter */
|
||||
off_t error_skip_block; /* skip block size, 0 for adaptive */
|
||||
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 discard_input; /* write nothing to stdout */
|
||||
off_t rate_limit; /* rate limit, in bytes per second */
|
||||
size_t target_buffer_size; /* buffer size (0=default) */
|
||||
off_t size; /* total size of data */
|
||||
double interval; /* interval between updates */
|
||||
double delay_start; /* delay before first display */
|
||||
pid_t watch_pid; /* process to watch fds of */
|
||||
int watch_fd; /* fd to watch */
|
||||
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 */
|
||||
/*@only@*/ /*@null@*/ char *name; /* display name */
|
||||
char default_format[PV_SIZEOF_DEFAULT_FORMAT]; /* default format string */
|
||||
/*@only@*/ /*@null@*/ char *format_string; /* output format string */
|
||||
|
||||
/******************
|
||||
* Program status *
|
||||
******************/
|
||||
/*@only@*/ char *program_name; /* program name for error reporting */
|
||||
char cwd[PV_SIZEOF_CWD]; /* current working directory for relative path */
|
||||
int current_input_file; /* index of current file being read */
|
||||
int exit_status; /* exit status to give (0=OK) */
|
||||
struct {
|
||||
bool force; /* display even if not on terminal */
|
||||
bool cursor; /* use cursor positioning */
|
||||
bool numeric; /* numeric output only */
|
||||
bool wait; /* wait for data before display */
|
||||
bool linemode; /* count lines instead of bytes */
|
||||
bool bits; /* report bits instead of bytes */
|
||||
bool null_terminated_lines; /* lines are null-terminated */
|
||||
bool no_display; /* do nothing other than pipe data */
|
||||
unsigned int skip_errors; /* skip read errors counter */
|
||||
off_t error_skip_block; /* skip block size, 0 for adaptive */
|
||||
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 discard_input; /* write nothing to stdout */
|
||||
off_t rate_limit; /* rate limit, in bytes per second */
|
||||
size_t target_buffer_size; /* buffer size (0=default) */
|
||||
off_t size; /* total size of data */
|
||||
double interval; /* interval between updates */
|
||||
double delay_start; /* delay before first display */
|
||||
pid_t watch_pid; /* process to watch fds of */
|
||||
int watch_fd; /* fd to watch */
|
||||
unsigned int average_rate_window; /* time window in seconds for average rate calculations */
|
||||
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 */
|
||||
/*@only@*/ /*@null@*/ char *name; /* display name */
|
||||
char default_format[PV_SIZEOF_DEFAULT_FORMAT]; /* default format string */
|
||||
/*@only@*/ /*@null@*/ char *format_string; /* output format string */
|
||||
} control;
|
||||
|
||||
/*******************
|
||||
* Signal handling *
|
||||
*******************/
|
||||
int pv_sig_old_stderr; /* see pv_sig_ttou() */
|
||||
bool pv_tty_tostop_added; /* whether we had to set TOSTOP on the terminal */
|
||||
struct timespec pv_sig_tstp_time; /* see pv_sig_tstp() / __cont() */
|
||||
struct timespec pv_sig_toffset; /* total time spent stopped */
|
||||
volatile sig_atomic_t pv_sig_newsize; /* whether we need to get term size again */
|
||||
volatile sig_atomic_t pv_sig_abort; /* whether we need to abort right now */
|
||||
volatile sig_atomic_t reparse_display; /* whether to re-check format string */
|
||||
struct sigaction pv_sig_old_sigpipe;
|
||||
struct sigaction pv_sig_old_sigttou;
|
||||
struct sigaction pv_sig_old_sigtstp;
|
||||
struct sigaction pv_sig_old_sigcont;
|
||||
struct sigaction pv_sig_old_sigwinch;
|
||||
struct sigaction pv_sig_old_sigint;
|
||||
struct sigaction pv_sig_old_sighup;
|
||||
struct sigaction pv_sig_old_sigterm;
|
||||
struct {
|
||||
int old_stderr; /* see pv_sig_ttou() */
|
||||
bool pv_tty_tostop_added; /* whether we had to set TOSTOP on the terminal */
|
||||
struct timespec tstp_time; /* see pv_sig_tstp() / __cont() */
|
||||
struct timespec toffset; /* total time spent stopped */
|
||||
#ifdef SA_SIGINFO
|
||||
volatile sig_atomic_t rxusr2; /* whether SIGUSR2 was received */
|
||||
volatile pid_t sender; /* PID of sending process for SIGUSR2 */
|
||||
#endif
|
||||
/* old signal handlers to restore in pv_sig_fini(). */
|
||||
struct sigaction old_sigpipe;
|
||||
struct sigaction old_sigttou;
|
||||
struct sigaction old_sigtstp;
|
||||
struct sigaction old_sigcont;
|
||||
struct sigaction old_sigwinch;
|
||||
struct sigaction old_sigint;
|
||||
struct sigaction old_sighup;
|
||||
struct sigaction old_sigterm;
|
||||
#ifdef SA_SIGINFO
|
||||
struct sigaction old_sigusr2;
|
||||
#endif
|
||||
} signal;
|
||||
|
||||
/*******************
|
||||
* Transient flags *
|
||||
*******************/
|
||||
struct {
|
||||
volatile sig_atomic_t reparse_display; /* whether to re-check format string */
|
||||
volatile sig_atomic_t terminal_resized; /* whether we need to get term size again */
|
||||
volatile sig_atomic_t trigger_exit; /* whether we need to abort right now */
|
||||
} flag;
|
||||
|
||||
/*****************
|
||||
* Display state *
|
||||
*****************/
|
||||
long percentage;
|
||||
long double prev_elapsed_sec;
|
||||
long double prev_rate;
|
||||
long double prev_trans;
|
||||
|
||||
/* Keep track of progress over last intervals to compute current average rate. */
|
||||
/*@null@*/ pvhistory_t *history; /* state at previous intervals (circular buffer) */
|
||||
unsigned int history_len; /* total size */
|
||||
int history_interval; /* seconds between each history entry */
|
||||
int history_first;
|
||||
int history_last;
|
||||
long double current_avg_rate; /* current average rate over last history intervals */
|
||||
|
||||
off_t initial_offset;
|
||||
/*@only@*/ char *display_buffer;
|
||||
long display_buffer_size;
|
||||
size_t lastoutput_length; /* number of last-output bytes to show */
|
||||
char lastoutput_buffer[PV_SIZEOF_LASTOUTPUT_BUFFER];
|
||||
int prev_width; /* screen width last time we were called */
|
||||
int prev_length; /* length of last string we output */
|
||||
char str_name[PV_SIZEOF_STR_NAME];
|
||||
char str_transferred[PV_SIZEOF_STR_TRANSFERRED];
|
||||
char str_bufpercent[PV_SIZEOF_STR_BUFPERCENT];
|
||||
char str_timer[PV_SIZEOF_STR_TIMER];
|
||||
char str_rate[PV_SIZEOF_STR_RATE];
|
||||
char str_average_rate[PV_SIZEOF_STR_AVERAGE_RATE];
|
||||
char str_progress[PV_SIZEOF_STR_PROGRESS];
|
||||
char str_lastoutput[PV_SIZEOF_STR_LASTOUTPUT];
|
||||
char str_eta[PV_SIZEOF_STR_ETA];
|
||||
char str_fineta[PV_SIZEOF_STR_FINETA];
|
||||
unsigned long components_used; /* bitmask of components used */
|
||||
struct {
|
||||
const char *string;
|
||||
int length;
|
||||
} format[PV_FORMAT_ARRAY_MAX];
|
||||
bool display_visible; /* set once anything written to terminal */
|
||||
/*@only@*/ /*@null@*/ char *display_buffer; /* buffer for display string */
|
||||
size_t display_buffer_size; /* size allocated to display buffer */
|
||||
size_t display_string_len; /* length of string in display buffer */
|
||||
unsigned int prev_screen_width; /* screen width last time we were called */
|
||||
bool display_visible; /* set once anything written to terminal */
|
||||
|
||||
int percentage; /* transfer percentage completion */
|
||||
|
||||
long double prev_elapsed_sec; /* elapsed sec at which rate last calculated */
|
||||
long double prev_rate; /* last calculated instantaneous transfer rate */
|
||||
long double prev_trans; /* bytes transferred since last rate calculation */
|
||||
|
||||
/* Keep track of progress over last intervals to compute current average rate. */
|
||||
/*@null@*/ struct { /* state at previous intervals (circular buffer) */
|
||||
long double elapsed_sec; /* time since start of transfer */
|
||||
off_t total_bytes; /* amount transferred by that time */
|
||||
} *history;
|
||||
size_t history_len; /* total size of history array */
|
||||
int history_interval; /* seconds between each history entry */
|
||||
size_t history_first; /* index of oldest entry */
|
||||
size_t history_last; /* index of newest entry */
|
||||
long double current_avg_rate; /* current average rate over last history intervals */
|
||||
|
||||
off_t initial_offset; /* offset when first opened (when watching fds) */
|
||||
|
||||
size_t lastoutput_length; /* number of last-output bytes to show */
|
||||
char lastoutput_buffer[PV_SIZEOF_LASTOUTPUT_BUFFER];
|
||||
|
||||
size_t format_segment_count; /* number of format string segments */
|
||||
struct { /* format string broken into display components */
|
||||
pv_display_component type; /* type of display component */
|
||||
size_t str_start; /* for strings: start offset */
|
||||
size_t str_length; /* for strings: length */
|
||||
} format[PV_FORMAT_ARRAY_MAX];
|
||||
|
||||
struct { /* display components */
|
||||
bool required; /* true if included in format */
|
||||
char content[PV_SIZEOF_COMPONENT_STR]; /* string to display */
|
||||
size_t length; /* number of bytes in string */
|
||||
} component[PV_COMPONENT__MAX];
|
||||
|
||||
} display;
|
||||
|
||||
/********************
|
||||
* Cursor/IPC state *
|
||||
********************/
|
||||
struct {
|
||||
#ifdef HAVE_IPC
|
||||
int crs_shmid; /* ID of our shared memory segment */
|
||||
int crs_pvcount; /* number of `pv' processes in total */
|
||||
int crs_pvmax; /* highest number of `pv's seen */
|
||||
/*@keep@*/ /*@null@*/ struct pvcursorstate_s *crs_shared; /* data shared between instances */
|
||||
int crs_y_lastread; /* last value of _y_top seen */
|
||||
int crs_y_offset; /* our Y offset from this top position */
|
||||
int crs_needreinit; /* counter if we need to reinit cursor pos */
|
||||
bool crs_noipc; /* set if we can't use IPC */
|
||||
int shmid; /* ID of our shared memory segment */
|
||||
int pvcount; /* number of `pv' processes in total */
|
||||
int pvmax; /* highest number of `pv's seen */
|
||||
/*@keep@*/ /*@null@*/ struct pvcursorstate_s *shared; /* data shared between instances */
|
||||
int y_lastread; /* last value of _y_top seen */
|
||||
int y_offset; /* our Y offset from this top position */
|
||||
int needreinit; /* counter if we need to reinit cursor pos */
|
||||
bool noipc; /* set if we can't use IPC */
|
||||
#endif /* HAVE_IPC */
|
||||
int crs_lock_fd; /* fd of lockfile, -1 if none open */
|
||||
char crs_lock_file[PV_SIZEOF_CRS_LOCK_FILE];
|
||||
int crs_y_start; /* our initial Y coordinate */
|
||||
int lock_fd; /* fd of lockfile, -1 if none open */
|
||||
char lock_file[PV_SIZEOF_CRS_LOCK_FILE];
|
||||
int y_start; /* our initial Y coordinate */
|
||||
} cursor;
|
||||
|
||||
/*******************
|
||||
* Transfer state *
|
||||
@@ -216,7 +241,7 @@ struct pvstate_s {
|
||||
* to the output when splice() is not available.
|
||||
*
|
||||
* If buffer_size is smaller than pv__target_bufsize, then
|
||||
* pv_transfer will try to reallocate transfer_buffer to make
|
||||
* pv_transfer() will try to reallocate transfer_buffer to make
|
||||
* buffer_size equal to pv__target_bufsize.
|
||||
*
|
||||
* Data from the input files is read into the buffer; read_position
|
||||
@@ -226,40 +251,45 @@ struct pvstate_s {
|
||||
* is the offset in the buffer that we've written data up to. It
|
||||
* will always be less than or equal to read_position.
|
||||
*/
|
||||
/*@keep@*/ /*@null@*/ char *transfer_buffer; /* data transfer buffer */
|
||||
size_t buffer_size; /* size of buffer */
|
||||
size_t read_position; /* amount of data in buffer */
|
||||
size_t write_position; /* buffered data written */
|
||||
struct {
|
||||
/*@only@*/ /*@null@*/ char *transfer_buffer; /* data transfer buffer */
|
||||
size_t buffer_size; /* size of buffer */
|
||||
size_t read_position; /* amount of data in buffer */
|
||||
size_t write_position; /* buffered data written */
|
||||
|
||||
/*
|
||||
* While reading from a file descriptor we keep track of how many
|
||||
* times in a row we've seen errors (read_errors_in_a_row), and
|
||||
* whether or not we have put a warning on stderr about read errors
|
||||
* on this fd (read_error_warning_shown).
|
||||
*
|
||||
* Whenever the active file descriptor changes from
|
||||
* last_read_skip_fd, we reset read_errors_in_a_row to 0 and
|
||||
* read_error_warning_shown to false for the new file descriptor and
|
||||
* set last_read_skip_fd to the new fd number.
|
||||
*
|
||||
* This way, we're treating each input file separately.
|
||||
*/
|
||||
int last_read_skip_fd;
|
||||
off_t read_errors_in_a_row;
|
||||
bool read_error_warning_shown;
|
||||
/*
|
||||
* While reading from a file descriptor we keep track of how
|
||||
* many times in a row we've seen errors
|
||||
* (read_errors_in_a_row), and whether or not we have put a
|
||||
* warning on stderr about read errors on this fd
|
||||
* (read_error_warning_shown).
|
||||
*
|
||||
* Whenever the active file descriptor changes from
|
||||
* last_read_skip_fd, we reset read_errors_in_a_row to 0 and
|
||||
* read_error_warning_shown to false for the new file
|
||||
* descriptor and set last_read_skip_fd to the new fd
|
||||
* number.
|
||||
*
|
||||
* This way, we're treating each input file separately.
|
||||
*/
|
||||
int last_read_skip_fd;
|
||||
off_t read_errors_in_a_row;
|
||||
bool read_error_warning_shown;
|
||||
#ifdef HAVE_SPLICE
|
||||
/*
|
||||
* These variables are used to keep track of whether splice() was
|
||||
* used; splice_failed_fd is the file descriptor that splice() last
|
||||
* failed on, so that we don't keep trying to use it on an fd that
|
||||
* doesn't support it, and splice_used is set to true if splice()
|
||||
* was used this time within pv_transfer().
|
||||
*/
|
||||
int splice_failed_fd;
|
||||
bool splice_used;
|
||||
/*
|
||||
* These variables are used to keep track of whether
|
||||
* splice() was used; splice_failed_fd is the file
|
||||
* descriptor that splice() last failed on, so that we don't
|
||||
* keep trying to use it on an fd that doesn't support it,
|
||||
* and splice_used is set to true if splice() was used this
|
||||
* time within pv_transfer().
|
||||
*/
|
||||
int splice_failed_fd;
|
||||
bool splice_used;
|
||||
#endif
|
||||
ssize_t to_write; /* max to write this time around */
|
||||
ssize_t written; /* bytes sent to stdout this time */
|
||||
ssize_t to_write; /* max to write this time around */
|
||||
ssize_t written; /* bytes sent to stdout this time */
|
||||
} transfer;
|
||||
};
|
||||
|
||||
|
||||
@@ -278,6 +308,7 @@ struct pvwatchfd_s {
|
||||
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 */
|
||||
/*@null@*/ pvstate_t state; /* state object for flags and display */
|
||||
};
|
||||
typedef struct pvwatchfd_s *pvwatchfd_t;
|
||||
|
||||
@@ -308,9 +339,9 @@ void pv_remote_fini(pvstate_t);
|
||||
int pv_remote_set(pvstate_t);
|
||||
|
||||
int pv_watchfd_info(pvstate_t, pvwatchfd_t, bool);
|
||||
int pv_watchfd_changed(pvwatchfd_t);
|
||||
bool pv_watchfd_changed(pvwatchfd_t);
|
||||
off_t pv_watchfd_position(pvwatchfd_t);
|
||||
int pv_watchpid_scanfds(pvstate_t, pvstate_t, unsigned int, int *, pvwatchfd_t *, pvstate_t *, int *);
|
||||
int pv_watchpid_scanfds(pvstate_t, pid_t, int *, pvwatchfd_t *, int *);
|
||||
void pv_watchpid_setname(pvstate_t, pvwatchfd_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -87,6 +88,12 @@ extern size_t pv_strlcat(char *, const char *, size_t);
|
||||
*/
|
||||
/*@null@ */ /*@only@ */ extern char *pv_strdup(const char *);
|
||||
|
||||
/*
|
||||
* Return a pointer to the last matching character in the buffer, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
/*@null@ */ /*@temp@ */ extern void *pv_memrchr(const void *, int, size_t);
|
||||
|
||||
/*
|
||||
* Functions relating to elapsed time.
|
||||
*/
|
||||
@@ -200,6 +207,13 @@ extern off_t pv_calc_total_size(pvstate_t);
|
||||
*/
|
||||
extern void pv_sig_init(pvstate_t);
|
||||
|
||||
#ifdef SA_SIGINFO
|
||||
/*
|
||||
* Return true if SIGUSR2 has been received, and indicate the sender.
|
||||
*/
|
||||
extern bool pv_sigusr2_received(pvstate_t, pid_t *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enter the main transfer loop, transferring all input files to the output.
|
||||
*/
|
||||
|
||||
+3
-2
@@ -9,6 +9,7 @@
|
||||
#include "config.h"
|
||||
#include "pv.h"
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
@@ -383,11 +384,11 @@ void display_help(void)
|
||||
{ "-X", "--discard", NULL,
|
||||
N_("discard input instead of writing to output"),
|
||||
{ 0, 0, 0, 0} },
|
||||
#ifdef HAVE_IPC
|
||||
#ifdef SA_SIGINFO
|
||||
{ "-R", "--remote", N_("PID"),
|
||||
N_("update settings of process PID"),
|
||||
{ 0, 0, 0, 0} },
|
||||
#endif /* HAVE_IPC */
|
||||
#endif /* SA_SIGINFO */
|
||||
{ "", NULL, NULL, NULL, { 0, 0, 0, 0} },
|
||||
{ "-P", "--pidfile", N_("FILE"),
|
||||
N_("save process ID in FILE"),
|
||||
|
||||
+18
-10
@@ -24,7 +24,7 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
int pv_remote_set(opts_t);
|
||||
int pv_remote_set(opts_t, pvstate_t);
|
||||
void pv_remote_init(void);
|
||||
void pv_remote_fini(void);
|
||||
|
||||
@@ -60,15 +60,6 @@ int main(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* -R specified - send the message, then exit.
|
||||
*/
|
||||
if (opts->remote > 0) {
|
||||
retcode = pv_remote_set(opts);
|
||||
opts_free(opts);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate our internal state buffer.
|
||||
*/
|
||||
@@ -87,6 +78,23 @@ 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.
|
||||
*/
|
||||
|
||||
+185
-113
@@ -11,22 +11,20 @@
|
||||
#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 HAVE_IPC
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/msg.h>
|
||||
#endif /* HAVE_IPC */
|
||||
#ifdef SA_SIGINFO
|
||||
void pv_error(pvstate_t, char *, ...);
|
||||
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
struct remote_msg {
|
||||
long mtype;
|
||||
bool progress; /* progress bar flag */
|
||||
bool timer; /* timer flag */
|
||||
bool eta; /* ETA flag */
|
||||
@@ -53,67 +51,106 @@ struct remote_msg {
|
||||
* bounded to one less than their size so they are always \0 terminated.
|
||||
*/
|
||||
|
||||
static int remote__msgid = -1;
|
||||
|
||||
|
||||
/*
|
||||
* Return a key for use with msgget() which will be unique to the current
|
||||
* user.
|
||||
*
|
||||
* We can't just use ftok() because the queue needs to be user-specific
|
||||
* so that a user cannot send messages to another user's process, and we
|
||||
* can't easily find out the terminal a given process is connected to in a
|
||||
* cross-platform way.
|
||||
* 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.
|
||||
*/
|
||||
static key_t remote__genkey(void)
|
||||
static FILE *pv__control_file(char *filename, size_t bufsize, pid_t control_pid, bool sender)
|
||||
{
|
||||
uid_t uid;
|
||||
key_t key;
|
||||
int open_flags, open_mode, control_fd;
|
||||
FILE *control_fptr;
|
||||
|
||||
/*@-type@ *//* splint doesn't like uid_t */
|
||||
uid = geteuid();
|
||||
/*@+type@ */
|
||||
open_flags = O_RDONLY;
|
||||
#ifdef O_NOFOLLOW
|
||||
open_flags += O_NOFOLLOW;
|
||||
#endif
|
||||
if (sender)
|
||||
open_flags = O_WRONLY | O_CREAT | O_EXCL;
|
||||
|
||||
key = ftok("/tmp", (int) 'P') | uid;
|
||||
open_mode = 0644;
|
||||
|
||||
return key;
|
||||
(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;
|
||||
|
||||
(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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return a message queue ID that is unique to the current user and the
|
||||
* given process ID, or -1 on error.
|
||||
*/
|
||||
static int remote__msgget(void)
|
||||
{
|
||||
/* Catch SIGSYS in case msgget() raises it, so we get ENOSYS */
|
||||
/*@-unrecog@ *//* splint doesn't see SIGSYS */
|
||||
(void) signal(SIGSYS, SIG_IGN);
|
||||
/*@+unrecog@ */
|
||||
return msgget(remote__genkey(), IPC_CREAT | 0600);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the options of a remote process by setting up an IPC message queue,
|
||||
* sending a message containing the new options, and then waiting for the
|
||||
* message to be consumed by the remote process.
|
||||
* 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)
|
||||
int pv_remote_set(opts_t opts, pvstate_t state)
|
||||
{
|
||||
char control_filename[4096]; /* flawfinder: ignore */
|
||||
FILE *control_fptr;
|
||||
struct remote_msg msgbuf;
|
||||
struct msqid_ds qbuf;
|
||||
pid_t signal_sender;
|
||||
long timeout;
|
||||
int msgid;
|
||||
unsigned long initial_qnum;
|
||||
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) {
|
||||
fprintf(stderr, "%s: %u: %s\n", opts->program_name, opts->remote, strerror(errno));
|
||||
pv_error(state, "%u: %s", opts->remote, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -137,7 +174,6 @@ int pv_remote_set(opts_t opts)
|
||||
* Copy parameters into message buffer.
|
||||
*/
|
||||
memset(&msgbuf, 0, sizeof(msgbuf));
|
||||
msgbuf.mtype = (long) (opts->remote);
|
||||
msgbuf.progress = opts->progress;
|
||||
msgbuf.timer = opts->timer;
|
||||
msgbuf.eta = opts->eta;
|
||||
@@ -169,28 +205,56 @@ int pv_remote_set(opts_t opts)
|
||||
* terminated by memset() earlier.
|
||||
*/
|
||||
|
||||
msgid = remote__msgget();
|
||||
if (msgid < 0) {
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name, strerror(errno));
|
||||
/*
|
||||
* 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), getpid(), true);
|
||||
if (NULL == control_fptr) {
|
||||
pv_error(state, "%s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&qbuf, 0, sizeof(qbuf));
|
||||
if (msgctl(msgid, IPC_STAT, &qbuf) < 0) {
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name, strerror(errno));
|
||||
/*
|
||||
* Write the message buffer to the remote control file, and close
|
||||
* it.
|
||||
*/
|
||||
if (1 != fwrite(&msgbuf, sizeof(msgbuf), 1, control_fptr)) {
|
||||
pv_error(state, "%s", strerror(errno));
|
||||
(void) fclose(control_fptr);
|
||||
(void) remove(control_filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
initial_qnum = qbuf.msg_qnum;
|
||||
|
||||
if (msgsnd(msgid, &msgbuf, sizeof(msgbuf) - sizeof(long), 0) != 0) {
|
||||
fprintf(stderr, "%s: %s\n", opts->program_name, strerror(errno));
|
||||
if (0 != fclose(control_fptr)) {
|
||||
pv_error(state, "%s", strerror(errno));
|
||||
(void) remove(control_filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(state, "%u: %s", opts->remote, strerror(errno));
|
||||
(void) remove(control_filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
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) {
|
||||
while (timeout > 10000 && !received) {
|
||||
struct timeval tv;
|
||||
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
@@ -201,80 +265,91 @@ int pv_remote_set(opts_t opts)
|
||||
/*@+nullpass@ */
|
||||
timeout -= 10000;
|
||||
|
||||
/*
|
||||
* If we can't stat the queue, it must have been deleted.
|
||||
*/
|
||||
memset(&qbuf, 0, sizeof(qbuf));
|
||||
if (msgctl(msgid, IPC_STAT, &qbuf) < 0)
|
||||
break;
|
||||
|
||||
/*
|
||||
* If the message count is at or below the message count
|
||||
* before we sent our message, assume it was received.
|
||||
*/
|
||||
if (qbuf.msg_qnum <= initial_qnum) {
|
||||
return 0;
|
||||
if (pv_sigusr2_received(state, &signal_sender)) {
|
||||
if (signal_sender == opts->remote) {
|
||||
debug("%s", "message received");
|
||||
received = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Message not received - delete it.
|
||||
* Remove the remote control file.
|
||||
*/
|
||||
memset(&qbuf, 0, sizeof(qbuf));
|
||||
if (msgctl(msgid, IPC_STAT, &qbuf) >= 0) {
|
||||
(void) msgrcv(msgid, &msgbuf, sizeof(msgbuf) - sizeof(long), (long) (opts->remote), IPC_NOWAIT);
|
||||
/*
|
||||
* If this leaves nothing on the queue, remove the
|
||||
* queue, in case we created one for no reason.
|
||||
*/
|
||||
if (msgctl(msgid, IPC_STAT, &qbuf) >= 0) {
|
||||
if (qbuf.msg_qnum < 1)
|
||||
(void) msgctl(msgid, IPC_RMID, &qbuf);
|
||||
}
|
||||
if (0 != remove(control_filename)) {
|
||||
pv_error(state, "%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.
|
||||
*/
|
||||
fprintf(stderr, "%s: %u: %s\n", opts->program_name, opts->remote, _("message not received"));
|
||||
pv_error(state, "%u: %s", opts->remote, _("message not received"));
|
||||
return 1;
|
||||
/*@+mustfreefresh @ */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check for an IPC remote handling message and, if there is one, replace
|
||||
* the current process's options with those being passed in.
|
||||
* 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.
|
||||
*/
|
||||
void pv_remote_check(pvstate_t state)
|
||||
{
|
||||
pid_t signal_sender;
|
||||
char control_filename[4096]; /* flawfinder: ignore */
|
||||
FILE *control_fptr;
|
||||
struct remote_msg msgbuf;
|
||||
ssize_t got;
|
||||
|
||||
if (remote__msgid < 0)
|
||||
/* 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;
|
||||
|
||||
memset(&msgbuf, 0, sizeof(msgbuf));
|
||||
|
||||
got = msgrcv(remote__msgid, &msgbuf, sizeof(msgbuf) - sizeof(long), getpid(), IPC_NOWAIT);
|
||||
if (got < 0) {
|
||||
/*
|
||||
* If our queue had been deleted, re-create it.
|
||||
*/
|
||||
/*@-unrecog@ *//* splint doesn't see ENOMSG */
|
||||
if (errno != EAGAIN && errno != ENOMSG) {
|
||||
remote__msgid = remote__msgget();
|
||||
}
|
||||
/*@+unrecog@ */
|
||||
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(state, "%s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (got < 1)
|
||||
|
||||
/*
|
||||
* Read the message buffer from the remote control file, and close
|
||||
* it.
|
||||
*/
|
||||
if (1 != fread(&msgbuf, sizeof(msgbuf), 1, control_fptr)) {
|
||||
pv_error(state, "%s", strerror(errno));
|
||||
(void) fclose(control_fptr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 != fclose(control_fptr)) {
|
||||
pv_error(state, "%s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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");
|
||||
|
||||
@@ -313,7 +388,6 @@ void pv_remote_check(pvstate_t state)
|
||||
*/
|
||||
void pv_remote_init(void)
|
||||
{
|
||||
remote__msgid = remote__msgget();
|
||||
}
|
||||
|
||||
|
||||
@@ -322,23 +396,18 @@ void pv_remote_init(void)
|
||||
*/
|
||||
void pv_remote_fini(void)
|
||||
{
|
||||
if (remote__msgid >= 0) {
|
||||
struct msqid_ds qbuf;
|
||||
memset(&qbuf, 0, sizeof(qbuf));
|
||||
(void) msgctl(remote__msgid, IPC_RMID, &qbuf);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !HAVE_IPC */
|
||||
#else /* !SA_SIGINFO */
|
||||
|
||||
/*
|
||||
* Dummy stubs for remote control when we don't have IPC.
|
||||
* Dummy stubs for remote control when we don't have SA_SIGINFO.
|
||||
*/
|
||||
void pv_remote_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void pv_remote_check(pvstate_t state)
|
||||
void pv_remote_check( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -346,12 +415,15 @@ void pv_remote_fini(void)
|
||||
{
|
||||
}
|
||||
|
||||
int pv_remote_set(pvstate_t state)
|
||||
int pv_remote_set( /*@unused@ */
|
||||
__attribute__((unused)) opts_t opts, /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
{
|
||||
fprintf(stderr, "%s\n", _("IPC not supported on this system"));
|
||||
/*@-mustfreefresh@ *//* splint - see above */
|
||||
fprintf(stderr, "%s\n", _("SA_SIGINFO not supported on this system"));
|
||||
/*@+mustfreefresh@ */
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* HAVE_IPC */
|
||||
#endif /* SA_SIGINFO */
|
||||
|
||||
/* EOF */
|
||||
|
||||
+103
-104
@@ -79,18 +79,18 @@ static void pv_crs_open_lockfile(pvstate_t state, int fd)
|
||||
char *tmpdir;
|
||||
int openflags;
|
||||
|
||||
state->crs_lock_fd = -1;
|
||||
state->cursor.lock_fd = -1;
|
||||
|
||||
ttydev = ttyname(fd);
|
||||
if (!ttydev) {
|
||||
if (!state->force) {
|
||||
if (!state->control.force) {
|
||||
pv_error(state, "%s: %s", _("failed to get terminal name"), strerror(errno));
|
||||
}
|
||||
/*
|
||||
* If we don't know our terminal name, we can neither do IPC
|
||||
* nor make a lock file, so turn off cursor positioning.
|
||||
*/
|
||||
state->cursor = 0;
|
||||
state->control.cursor = 0;
|
||||
debug("%s", "ttyname failed - cursor positioning disabled");
|
||||
return;
|
||||
}
|
||||
@@ -104,8 +104,8 @@ static void pv_crs_open_lockfile(pvstate_t state, int fd)
|
||||
*/
|
||||
tmpdir = "/tmp";
|
||||
|
||||
memset(state->crs_lock_file, 0, PV_SIZEOF_CRS_LOCK_FILE);
|
||||
(void) pv_snprintf(state->crs_lock_file,
|
||||
memset(state->cursor.lock_file, 0, PV_SIZEOF_CRS_LOCK_FILE);
|
||||
(void) pv_snprintf(state->cursor.lock_file,
|
||||
PV_SIZEOF_CRS_LOCK_FILE, "%s/pv-%s-%i.lock", tmpdir, basename(ttydev), (int) geteuid());
|
||||
|
||||
/*
|
||||
@@ -117,7 +117,7 @@ static void pv_crs_open_lockfile(pvstate_t state, int fd)
|
||||
openflags = O_RDWR | O_CREAT;
|
||||
#endif
|
||||
|
||||
state->crs_lock_fd = open(state->crs_lock_file, openflags, 0600); /* flawfinder: ignore */
|
||||
state->cursor.lock_fd = open(state->cursor.lock_file, openflags, 0600); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* flawfinder rationale: we aren't truncating the lock file, we
|
||||
@@ -126,9 +126,9 @@ static void pv_crs_open_lockfile(pvstate_t state, int fd)
|
||||
* open() is as safe as we can make it.
|
||||
*/
|
||||
|
||||
if (state->crs_lock_fd < 0) {
|
||||
pv_error(state, "%s: %s: %s", state->crs_lock_file, _("failed to open lock file"), strerror(errno));
|
||||
state->cursor = 0;
|
||||
if (state->cursor.lock_fd < 0) {
|
||||
pv_error(state, "%s: %s: %s", state->cursor.lock_file, _("failed to open lock file"), strerror(errno));
|
||||
state->control.cursor = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -144,8 +144,8 @@ static void pv_crs_lock(pvstate_t state, int fd)
|
||||
int lock_fd;
|
||||
|
||||
lock_fd = fd;
|
||||
if (state->crs_lock_fd >= 0)
|
||||
lock_fd = state->crs_lock_fd;
|
||||
if (state->cursor.lock_fd >= 0)
|
||||
lock_fd = state->cursor.lock_fd;
|
||||
|
||||
memset(&lock, 0, sizeof(lock));
|
||||
lock.l_type = (short) F_WRLCK;
|
||||
@@ -154,10 +154,10 @@ static void pv_crs_lock(pvstate_t state, int fd)
|
||||
lock.l_len = 1;
|
||||
while (fcntl(lock_fd, F_SETLKW, &lock) < 0) {
|
||||
if (errno != EINTR) {
|
||||
if (state->crs_lock_fd == -2) {
|
||||
if (state->cursor.lock_fd == -2) {
|
||||
pv_crs_open_lockfile(state, fd);
|
||||
if (state->crs_lock_fd >= 0) {
|
||||
lock_fd = state->crs_lock_fd;
|
||||
if (state->cursor.lock_fd >= 0) {
|
||||
lock_fd = state->cursor.lock_fd;
|
||||
}
|
||||
} else {
|
||||
pv_error(state, "%s: %s", _("lock attempt failed"), strerror(errno));
|
||||
@@ -166,8 +166,8 @@ static void pv_crs_lock(pvstate_t state, int fd)
|
||||
}
|
||||
}
|
||||
|
||||
if (state->crs_lock_fd >= 0) {
|
||||
debug("%s: %s", state->crs_lock_file, "terminal lockfile acquired");
|
||||
if (state->cursor.lock_fd >= 0) {
|
||||
debug("%s: %s", state->cursor.lock_file, "terminal lockfile acquired");
|
||||
} else {
|
||||
debug("%s", "terminal lock acquired");
|
||||
}
|
||||
@@ -184,8 +184,8 @@ static void pv_crs_unlock(pvstate_t state, int fd)
|
||||
int lock_fd;
|
||||
|
||||
lock_fd = fd;
|
||||
if (state->crs_lock_fd >= 0)
|
||||
lock_fd = state->crs_lock_fd;
|
||||
if (state->cursor.lock_fd >= 0)
|
||||
lock_fd = state->cursor.lock_fd;
|
||||
|
||||
memset(&lock, 0, sizeof(lock));
|
||||
lock.l_type = (short) F_UNLCK;
|
||||
@@ -194,8 +194,8 @@ static void pv_crs_unlock(pvstate_t state, int fd)
|
||||
lock.l_len = 1;
|
||||
(void) fcntl(lock_fd, F_SETLK, &lock);
|
||||
|
||||
if (state->crs_lock_fd >= 0) {
|
||||
debug("%s: %s", state->crs_lock_file, "terminal lockfile released");
|
||||
if (state->cursor.lock_fd >= 0) {
|
||||
debug("%s: %s", state->cursor.lock_file, "terminal lockfile released");
|
||||
} else {
|
||||
debug("%s", "terminal lock released");
|
||||
}
|
||||
@@ -216,13 +216,13 @@ static void pv_crs_ipccount(pvstate_t state)
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
buf.shm_nattch = 0;
|
||||
|
||||
(void) shmctl(state->crs_shmid, IPC_STAT, &buf);
|
||||
state->crs_pvcount = (int) (buf.shm_nattch);
|
||||
(void) shmctl(state->cursor.shmid, IPC_STAT, &buf);
|
||||
state->cursor.pvcount = (int) (buf.shm_nattch);
|
||||
|
||||
if (state->crs_pvcount > state->crs_pvmax)
|
||||
state->crs_pvmax = state->crs_pvcount;
|
||||
if (state->cursor.pvcount > state->cursor.pvmax)
|
||||
state->cursor.pvmax = state->cursor.pvcount;
|
||||
|
||||
debug("%s: %d", "pvcount", state->crs_pvcount);
|
||||
debug("%s: %d", "pvcount", state->cursor.pvcount);
|
||||
}
|
||||
#endif /* HAVE_IPC */
|
||||
|
||||
@@ -334,13 +334,13 @@ static int pv_crs_ipcinit(pvstate_t state, char *ttyfile, int terminalfd)
|
||||
}
|
||||
|
||||
pv_crs_lock(state, terminalfd);
|
||||
if (!state->cursor) {
|
||||
if (!state->control.cursor) {
|
||||
debug("%s", "early return - cursor has been disabled");
|
||||
return 1;
|
||||
}
|
||||
|
||||
state->crs_shmid = shmget(key, sizeof(struct pvcursorstate_s), 0600 | IPC_CREAT);
|
||||
if (state->crs_shmid < 0) {
|
||||
state->cursor.shmid = shmget(key, sizeof(struct pvcursorstate_s), 0600 | IPC_CREAT);
|
||||
if (state->cursor.shmid < 0) {
|
||||
debug("%s: %s", "shmget failed", strerror(errno));
|
||||
pv_crs_unlock(state, terminalfd);
|
||||
return 1;
|
||||
@@ -348,7 +348,7 @@ static int pv_crs_ipcinit(pvstate_t state, char *ttyfile, int terminalfd)
|
||||
|
||||
/*@-nullpass@ */
|
||||
/* splint doesn't know shmaddr can be NULL */
|
||||
state->crs_shared = shmat(state->crs_shmid, NULL, 0);
|
||||
state->cursor.shared = shmat(state->cursor.shmid, NULL, 0);
|
||||
/*@+nullpass@ */
|
||||
|
||||
pv_crs_ipccount(state);
|
||||
@@ -359,26 +359,26 @@ static int pv_crs_ipcinit(pvstate_t state, char *ttyfile, int terminalfd)
|
||||
* current Y cursor co-ordinate and with an initial false value for
|
||||
* the TOSTOP-added flag.
|
||||
*/
|
||||
if (state->crs_pvcount < 2) {
|
||||
state->crs_y_start = pv_crs_get_ypos(terminalfd);
|
||||
state->crs_shared->y_topmost = state->crs_y_start;
|
||||
state->crs_shared->tty_tostop_added = false;
|
||||
state->crs_y_lastread = state->crs_y_start;
|
||||
if (state->cursor.pvcount < 2) {
|
||||
state->cursor.y_start = pv_crs_get_ypos(terminalfd);
|
||||
state->cursor.shared->y_topmost = state->cursor.y_start;
|
||||
state->cursor.shared->tty_tostop_added = false;
|
||||
state->cursor.y_lastread = state->cursor.y_start;
|
||||
debug("%s", "we are the first to attach");
|
||||
}
|
||||
|
||||
state->crs_y_offset = state->crs_pvcount - 1;
|
||||
if (state->crs_y_offset < 0)
|
||||
state->crs_y_offset = 0;
|
||||
state->cursor.y_offset = state->cursor.pvcount - 1;
|
||||
if (state->cursor.y_offset < 0)
|
||||
state->cursor.y_offset = 0;
|
||||
|
||||
/*
|
||||
* If anyone else had attached to the shared memory segment, we need
|
||||
* to read the top Y co-ordinate from it.
|
||||
*/
|
||||
if (state->crs_pvcount > 1) {
|
||||
state->crs_y_start = state->crs_shared->y_topmost;
|
||||
state->crs_y_lastread = state->crs_y_start;
|
||||
debug("%s: %d", "not the first to attach - got top y", state->crs_y_start);
|
||||
if (state->cursor.pvcount > 1) {
|
||||
state->cursor.y_start = state->cursor.shared->y_topmost;
|
||||
state->cursor.y_lastread = state->cursor.y_start;
|
||||
debug("%s: %d", "not the first to attach - got top y", state->cursor.y_start);
|
||||
}
|
||||
|
||||
pv_crs_unlock(state, terminalfd);
|
||||
@@ -396,10 +396,10 @@ void pv_crs_init(pvstate_t state)
|
||||
char *ttyfile;
|
||||
int terminalfd;
|
||||
|
||||
state->crs_lock_fd = -2;
|
||||
state->crs_lock_file[0] = '\0';
|
||||
state->cursor.lock_fd = -2;
|
||||
state->cursor.lock_file[0] = '\0';
|
||||
|
||||
if (!state->cursor)
|
||||
if (!state->control.cursor)
|
||||
return;
|
||||
|
||||
debug("%s", "init");
|
||||
@@ -407,7 +407,7 @@ void pv_crs_init(pvstate_t state)
|
||||
ttyfile = ttyname(STDERR_FILENO);
|
||||
if (NULL == ttyfile) {
|
||||
debug("%s: %s", "disabling cursor positioning because ttyname failed", strerror(errno));
|
||||
state->cursor = false;
|
||||
state->control.cursor = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -422,22 +422,22 @@ void pv_crs_init(pvstate_t state)
|
||||
|
||||
if (terminalfd < 0) {
|
||||
pv_error(state, "%s: %s: %s", _("failed to open terminal"), ttyfile, strerror(errno));
|
||||
state->cursor = false;
|
||||
state->control.cursor = false;
|
||||
return;
|
||||
}
|
||||
#ifdef HAVE_IPC
|
||||
if (pv_crs_ipcinit(state, ttyfile, terminalfd) != 0) {
|
||||
debug("%s", "ipcinit failed, setting noipc flag");
|
||||
state->crs_noipc = true;
|
||||
state->cursor.noipc = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have already set the terminal TOSTOP attribute, set the
|
||||
* flag in shared memory to let the other instances know.
|
||||
*/
|
||||
if ((!state->crs_noipc) && state->pv_tty_tostop_added && (NULL != state->crs_shared)) {
|
||||
if ((!state->cursor.noipc) && state->signal.pv_tty_tostop_added && (NULL != state->cursor.shared)) {
|
||||
debug("%s", "propagating local pv_tty_tostop_added true value to shared flag");
|
||||
state->crs_shared->tty_tostop_added = true;
|
||||
state->cursor.shared->tty_tostop_added = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -445,7 +445,7 @@ void pv_crs_init(pvstate_t state)
|
||||
* co-ordinate. If we are using IPC, then the pv_crs_ipcinit()
|
||||
* function takes care of this in a more multi-process-friendly way.
|
||||
*/
|
||||
if (state->crs_noipc) {
|
||||
if (state->cursor.noipc) {
|
||||
#else /* ! HAVE_IPC */
|
||||
if (1) {
|
||||
#endif /* HAVE_IPC */
|
||||
@@ -453,18 +453,18 @@ void pv_crs_init(pvstate_t state)
|
||||
* Get current cursor position + 1.
|
||||
*/
|
||||
pv_crs_lock(state, terminalfd);
|
||||
state->crs_y_start = pv_crs_get_ypos(terminalfd);
|
||||
state->cursor.y_start = pv_crs_get_ypos(terminalfd);
|
||||
/*
|
||||
* Move down a line while the terminal is locked, so that
|
||||
* other processes in the pipeline will get a different
|
||||
* initial ypos.
|
||||
*/
|
||||
if (state->crs_y_start > 0)
|
||||
if (state->cursor.y_start > 0)
|
||||
pv_write_retry(STDERR_FILENO, "\n", 1);
|
||||
pv_crs_unlock(state, terminalfd);
|
||||
|
||||
if (state->crs_y_start < 1)
|
||||
state->cursor = 0;
|
||||
if (state->cursor.y_start < 1)
|
||||
state->control.cursor = 0;
|
||||
}
|
||||
|
||||
(void) close(terminalfd);
|
||||
@@ -477,9 +477,9 @@ void pv_crs_init(pvstate_t state)
|
||||
*/
|
||||
void pv_crs_needreinit(pvstate_t state)
|
||||
{
|
||||
state->crs_needreinit += 2;
|
||||
if (state->crs_needreinit > 3)
|
||||
state->crs_needreinit = 3;
|
||||
state->cursor.needreinit += 2;
|
||||
if (state->cursor.needreinit > 3)
|
||||
state->cursor.needreinit = 3;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -495,23 +495,23 @@ static void pv_crs_reinit(pvstate_t state)
|
||||
|
||||
pv_crs_lock(state, STDERR_FILENO);
|
||||
|
||||
state->crs_needreinit--;
|
||||
if (state->crs_y_offset < 1)
|
||||
state->crs_needreinit = 0;
|
||||
state->cursor.needreinit--;
|
||||
if (state->cursor.y_offset < 1)
|
||||
state->cursor.needreinit = 0;
|
||||
|
||||
if (state->crs_needreinit > 0) {
|
||||
if (state->cursor.needreinit > 0) {
|
||||
pv_crs_unlock(state, STDERR_FILENO);
|
||||
return;
|
||||
}
|
||||
|
||||
debug("%s", "reinit full");
|
||||
|
||||
state->crs_y_start = pv_crs_get_ypos(STDERR_FILENO);
|
||||
state->cursor.y_start = pv_crs_get_ypos(STDERR_FILENO);
|
||||
|
||||
if ((state->crs_y_offset < 1) && (NULL != state->crs_shared)) {
|
||||
state->crs_shared->y_topmost = state->crs_y_start;
|
||||
if ((state->cursor.y_offset < 1) && (NULL != state->cursor.shared)) {
|
||||
state->cursor.shared->y_topmost = state->cursor.y_start;
|
||||
}
|
||||
state->crs_y_lastread = state->crs_y_start;
|
||||
state->cursor.y_lastread = state->cursor.y_start;
|
||||
|
||||
pv_crs_unlock(state, STDERR_FILENO);
|
||||
}
|
||||
@@ -539,24 +539,24 @@ void pv_crs_update(pvstate_t state, const char *output_line)
|
||||
/* flawfinder - output_line is explictly expected to be \0-terminated. */
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
if (!state->crs_noipc) {
|
||||
if (state->crs_needreinit > 0)
|
||||
if (!state->cursor.noipc) {
|
||||
if (state->cursor.needreinit > 0)
|
||||
pv_crs_reinit(state);
|
||||
|
||||
pv_crs_ipccount(state);
|
||||
if (NULL != state->crs_shared) {
|
||||
if (state->crs_y_lastread != state->crs_shared->y_topmost) {
|
||||
state->crs_y_start = state->crs_shared->y_topmost;
|
||||
state->crs_y_lastread = state->crs_y_start;
|
||||
if (NULL != state->cursor.shared) {
|
||||
if (state->cursor.y_lastread != state->cursor.shared->y_topmost) {
|
||||
state->cursor.y_start = state->cursor.shared->y_topmost;
|
||||
state->cursor.y_lastread = state->cursor.y_start;
|
||||
}
|
||||
}
|
||||
|
||||
if (state->crs_needreinit > 0)
|
||||
if (state->cursor.needreinit > 0)
|
||||
return;
|
||||
}
|
||||
#endif /* HAVE_IPC */
|
||||
|
||||
y = state->crs_y_start;
|
||||
y = state->cursor.y_start;
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
/*
|
||||
@@ -565,27 +565,27 @@ void pv_crs_update(pvstate_t state, const char *output_line)
|
||||
* scroll the screen (only if we're the first `pv'), and then move
|
||||
* our initial Y co-ordinate up.
|
||||
*/
|
||||
if (((state->crs_y_start + state->crs_pvmax) > (int) (state->height))
|
||||
&& (!state->crs_noipc)
|
||||
if (((state->cursor.y_start + state->cursor.pvmax) > (int) (state->control.height))
|
||||
&& (!state->cursor.noipc)
|
||||
) {
|
||||
int offs;
|
||||
|
||||
offs = ((state->crs_y_start + state->crs_pvmax) - state->height);
|
||||
offs = ((state->cursor.y_start + state->cursor.pvmax) - state->control.height);
|
||||
|
||||
state->crs_y_start -= offs;
|
||||
if (state->crs_y_start < 1)
|
||||
state->crs_y_start = 1;
|
||||
state->cursor.y_start -= offs;
|
||||
if (state->cursor.y_start < 1)
|
||||
state->cursor.y_start = 1;
|
||||
|
||||
debug("%s: %d", "scroll offset", offs);
|
||||
|
||||
/*
|
||||
* Scroll the screen if we're the first `pv'.
|
||||
*/
|
||||
if (0 == state->crs_y_offset) {
|
||||
if (0 == state->cursor.y_offset) {
|
||||
pv_crs_lock(state, STDERR_FILENO);
|
||||
|
||||
memset(cup_cmd, 0, sizeof(cup_cmd));
|
||||
(void) pv_snprintf(cup_cmd, sizeof(cup_cmd), "\033[%u;1H", state->height);
|
||||
(void) pv_snprintf(cup_cmd, sizeof(cup_cmd), "\033[%u;1H", state->control.height);
|
||||
cup_cmd_length = strlen(cup_cmd); /* flawfinder: ignore */
|
||||
pv_write_retry(STDERR_FILENO, cup_cmd, cup_cmd_length);
|
||||
for (; offs > 0; offs--) {
|
||||
@@ -598,8 +598,8 @@ void pv_crs_update(pvstate_t state, const char *output_line)
|
||||
}
|
||||
}
|
||||
|
||||
if (!state->crs_noipc)
|
||||
y = state->crs_y_start + state->crs_y_offset;
|
||||
if (!state->cursor.noipc)
|
||||
y = state->cursor.y_start + state->cursor.y_offset;
|
||||
#endif /* HAVE_IPC */
|
||||
|
||||
/*
|
||||
@@ -636,23 +636,20 @@ void pv_crs_fini(pvstate_t state)
|
||||
{
|
||||
char cup_cmd[32]; /* flawfinder: ignore */
|
||||
unsigned int y;
|
||||
struct shmid_ds shm_buf;
|
||||
|
||||
/* flawfinder - "cup_cmd" is zeroed, and only written by pv_snprintf() */
|
||||
|
||||
memset(&shm_buf, 0, sizeof(shm_buf));
|
||||
|
||||
debug("%s", "fini");
|
||||
|
||||
y = (unsigned int) (state->crs_y_start);
|
||||
y = (unsigned int) (state->cursor.y_start);
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
if ((state->crs_pvmax > 0) && (!state->crs_noipc))
|
||||
y += state->crs_pvmax - 1;
|
||||
if ((state->cursor.pvmax > 0) && (!state->cursor.noipc))
|
||||
y += state->cursor.pvmax - 1;
|
||||
#endif /* HAVE_IPC */
|
||||
|
||||
if (y > state->height)
|
||||
y = state->height;
|
||||
if (y > state->control.height)
|
||||
y = state->control.height;
|
||||
|
||||
/*
|
||||
* Absolute bounds check.
|
||||
@@ -668,44 +665,46 @@ void pv_crs_fini(pvstate_t state)
|
||||
pv_write_retry(STDERR_FILENO, cup_cmd, strlen(cup_cmd)); /* flawfinder: ignore */
|
||||
/* flawfinder - pv_snprintf() always \0-terminates (see above). */
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
/*
|
||||
* If any other "pv -c" instances have set the terminal TOSTOP
|
||||
* attribute, set our local flag so pv_sig_fini() will know about
|
||||
* it.
|
||||
*/
|
||||
if ((!state->crs_noipc) && (NULL != state->crs_shared) && state->crs_shared->tty_tostop_added) {
|
||||
if (!state->pv_tty_tostop_added) {
|
||||
if ((!state->cursor.noipc) && (NULL != state->cursor.shared) && state->cursor.shared->tty_tostop_added) {
|
||||
if (!state->signal.pv_tty_tostop_added) {
|
||||
debug("%s", "propagating shared tty_tostop_added true value to local flag");
|
||||
state->pv_tty_tostop_added = true;
|
||||
state->signal.pv_tty_tostop_added = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_IPC
|
||||
pv_crs_ipccount(state);
|
||||
if (NULL != state->crs_shared) {
|
||||
(void) shmdt(state->crs_shared);
|
||||
if (NULL != state->cursor.shared) {
|
||||
(void) shmdt(state->cursor.shared);
|
||||
}
|
||||
state->crs_shared = NULL;
|
||||
state->cursor.shared = NULL;
|
||||
|
||||
/*
|
||||
* If we are the last instance detaching from the shared memory,
|
||||
* delete it so it's not left lying around.
|
||||
*/
|
||||
if (state->crs_pvcount < 2)
|
||||
(void) shmctl(state->crs_shmid, IPC_RMID, &shm_buf);
|
||||
if (state->cursor.pvcount < 2) {
|
||||
struct shmid_ds shm_buf;
|
||||
memset(&shm_buf, 0, sizeof(shm_buf));
|
||||
(void) shmctl(state->cursor.shmid, IPC_RMID, &shm_buf);
|
||||
}
|
||||
|
||||
#endif /* HAVE_IPC */
|
||||
|
||||
pv_crs_unlock(state, STDERR_FILENO);
|
||||
|
||||
if (state->crs_lock_fd >= 0) {
|
||||
(void) close(state->crs_lock_fd);
|
||||
if (state->cursor.lock_fd >= 0) {
|
||||
(void) close(state->cursor.lock_fd);
|
||||
/*
|
||||
* We can get away with removing this on exit because all
|
||||
* the other PVs will be finishing at the same sort of time.
|
||||
*/
|
||||
(void) remove(state->crs_lock_file);
|
||||
(void) remove(state->cursor.lock_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+627
-443
File diff suppressed because it is too large
Load Diff
+44
-44
@@ -45,25 +45,25 @@ static off_t pv_calc_total_bytes(pvstate_t state)
|
||||
/*
|
||||
* No files specified - check stdin.
|
||||
*/
|
||||
if ((state->input_file_count < 1) || (NULL == state->input_files)) {
|
||||
if ((state->files.file_count < 1) || (NULL == state->files.filename)) {
|
||||
if (0 == fstat(STDIN_FILENO, &sb))
|
||||
total = sb.st_size;
|
||||
return total;
|
||||
}
|
||||
|
||||
for (file_idx = 0; file_idx < state->input_file_count; file_idx++) {
|
||||
for (file_idx = 0; file_idx < state->files.file_count; file_idx++) {
|
||||
int rc;
|
||||
|
||||
if (0 == strcmp(state->input_files[file_idx], "-")) {
|
||||
if (0 == strcmp(state->files.filename[file_idx], "-")) {
|
||||
rc = fstat(STDIN_FILENO, &sb);
|
||||
if (rc != 0) {
|
||||
total = 0;
|
||||
return total;
|
||||
}
|
||||
} else {
|
||||
rc = stat(state->input_files[file_idx], &sb);
|
||||
rc = stat(state->files.filename[file_idx], &sb);
|
||||
if (0 == rc) {
|
||||
rc = access(state->input_files[file_idx], R_OK); /* flawfinder: ignore */
|
||||
rc = access(state->files.filename[file_idx], R_OK); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: we're not really
|
||||
* using access() to do permissions checks,
|
||||
@@ -79,7 +79,7 @@ static off_t pv_calc_total_bytes(pvstate_t state)
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
debug("%s: %s", state->input_files[file_idx], strerror(errno));
|
||||
debug("%s: %s", state->files.filename[file_idx], strerror(errno));
|
||||
total = 0;
|
||||
return total;
|
||||
}
|
||||
@@ -91,7 +91,7 @@ static off_t pv_calc_total_bytes(pvstate_t state)
|
||||
* Get the size of block devices by opening
|
||||
* them and seeking to the end.
|
||||
*/
|
||||
if (0 == strcmp(state->input_files[file_idx], "-")) {
|
||||
if (0 == strcmp(state->files.filename[file_idx], "-")) {
|
||||
fd = open("/dev/stdin", O_RDONLY); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: "/dev/stdin" may be
|
||||
@@ -101,7 +101,7 @@ static off_t pv_calc_total_bytes(pvstate_t state)
|
||||
* be under the control of someone else.
|
||||
*/
|
||||
} else {
|
||||
fd = open(state->input_files[file_idx], O_RDONLY); /* flawfinder: ignore */
|
||||
fd = open(state->files.filename[file_idx], O_RDONLY); /* flawfinder: ignore */
|
||||
/* flawfinder - see last open() below. */
|
||||
}
|
||||
if (fd >= 0) {
|
||||
@@ -146,7 +146,7 @@ static off_t pv_calc_total_bytes(pvstate_t state)
|
||||
if (lseek(STDOUT_FILENO, 0, SEEK_SET) != 0) {
|
||||
pv_error(state, "%s: %s: %s", "(stdout)",
|
||||
_("failed to seek to start of output"), strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
state->status.exit_status |= 2;
|
||||
}
|
||||
/*
|
||||
* If we worked out a size, then set the
|
||||
@@ -155,7 +155,7 @@ static off_t pv_calc_total_bytes(pvstate_t state)
|
||||
* device.
|
||||
*/
|
||||
if (total > 0) {
|
||||
state->stop_at_size = true;
|
||||
state->control.stop_at_size = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,11 +182,11 @@ static off_t pv_calc_total_lines(pvstate_t state)
|
||||
|
||||
total = 0;
|
||||
|
||||
for (file_idx = 0; file_idx < state->input_file_count && NULL != state->input_files; file_idx++) {
|
||||
for (file_idx = 0; file_idx < state->files.file_count && NULL != state->files.filename; file_idx++) {
|
||||
int fd = -1;
|
||||
int rc = 0;
|
||||
|
||||
if (0 == strcmp(state->input_files[file_idx], "-")) {
|
||||
if (0 == strcmp(state->files.filename[file_idx], "-")) {
|
||||
rc = fstat(STDIN_FILENO, &sb);
|
||||
if ((rc != 0) || (!S_ISREG(sb.st_mode))) {
|
||||
total = 0;
|
||||
@@ -194,17 +194,17 @@ static off_t pv_calc_total_lines(pvstate_t state)
|
||||
}
|
||||
fd = dup(STDIN_FILENO);
|
||||
} else {
|
||||
rc = stat(state->input_files[file_idx], &sb);
|
||||
rc = stat(state->files.filename[file_idx], &sb);
|
||||
if ((rc != 0) || (!S_ISREG(sb.st_mode))) {
|
||||
total = 0;
|
||||
return total;
|
||||
}
|
||||
fd = open(state->input_files[file_idx], O_RDONLY); /* flawfinder: ignore */
|
||||
fd = open(state->files.filename[file_idx], O_RDONLY); /* flawfinder: ignore */
|
||||
/* flawfinder - see last open() below. */
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
debug("%s: %s", state->input_files[file_idx], strerror(errno));
|
||||
debug("%s: %s", state->files.filename[file_idx], strerror(errno));
|
||||
total = 0;
|
||||
return total;
|
||||
}
|
||||
@@ -227,14 +227,14 @@ static off_t pv_calc_total_lines(pvstate_t state)
|
||||
* OK.
|
||||
*/
|
||||
if (numread < 0) {
|
||||
pv_error(state, "%s: %s", state->input_files[file_idx], strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
pv_error(state, "%s: %s", state->files.filename[file_idx], strerror(errno));
|
||||
state->status.exit_status |= 2;
|
||||
break;
|
||||
} else if (0 == numread) {
|
||||
break;
|
||||
}
|
||||
for (buf_idx = 0; buf_idx < numread; buf_idx++) {
|
||||
if (state->null_terminated_lines) {
|
||||
if (state->control.null_terminated_lines) {
|
||||
if ('\0' == scanbuf[buf_idx])
|
||||
total++;
|
||||
} else {
|
||||
@@ -245,8 +245,8 @@ static off_t pv_calc_total_lines(pvstate_t state)
|
||||
}
|
||||
|
||||
if (0 != lseek(fd, 0, SEEK_SET)) {
|
||||
pv_error(state, "%s: %s", state->input_files[file_idx], strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
pv_error(state, "%s: %s", state->files.filename[file_idx], strerror(errno));
|
||||
state->status.exit_status |= 2;
|
||||
}
|
||||
|
||||
(void) close(fd);
|
||||
@@ -259,13 +259,13 @@ static off_t pv_calc_total_lines(pvstate_t state)
|
||||
/*
|
||||
* Work out the total size of all data by adding up the sizes of all input
|
||||
* files, using either pv_calc_total_bytes() or pv_calc_total_lines()
|
||||
* depending on whether state->linemode is true.
|
||||
* depending on whether state->control.linemode is true.
|
||||
*
|
||||
* Returns the total size, or 0 if it is unknown.
|
||||
*/
|
||||
off_t pv_calc_total_size(pvstate_t state)
|
||||
{
|
||||
if (state->linemode) {
|
||||
if (state->control.linemode) {
|
||||
return pv_calc_total_lines(state);
|
||||
} else {
|
||||
return pv_calc_total_bytes(state);
|
||||
@@ -279,7 +279,7 @@ off_t pv_calc_total_size(pvstate_t state)
|
||||
* error). It is an error if the next input file is the same as the file
|
||||
* stdout is pointing to.
|
||||
*
|
||||
* Updates state->current_input_file in the process.
|
||||
* Updates state->status.current_input_file in the process.
|
||||
*/
|
||||
int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
{
|
||||
@@ -291,21 +291,21 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
if (oldfd >= 0) {
|
||||
if (0 != close(oldfd)) {
|
||||
pv_error(state, "%s: %s", _("failed to close file"), strerror(errno));
|
||||
state->exit_status |= 8;
|
||||
state->status.exit_status |= 8;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (filenum >= state->input_file_count) {
|
||||
debug("%s: %d >= %d", "filenum too large", filenum, state->input_file_count);
|
||||
state->exit_status |= 8;
|
||||
if (filenum >= state->files.file_count) {
|
||||
debug("%s: %d >= %d", "filenum too large", filenum, state->files.file_count);
|
||||
state->status.exit_status |= 8;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((NULL == state->input_files) || (0 == strcmp(state->input_files[filenum], "-"))) {
|
||||
if ((NULL == state->files.filename) || (0 == strcmp(state->files.filename[filenum], "-"))) {
|
||||
fd = STDIN_FILENO;
|
||||
} else {
|
||||
fd = open(state->input_files[filenum], O_RDONLY); /* flawfinder: ignore */
|
||||
fd = open(state->files.filename[filenum], O_RDONLY); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder rationale: the input file list is under the
|
||||
* control of the operator by its nature, so we can't refuse
|
||||
@@ -313,24 +313,24 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
*/
|
||||
if (fd < 0) {
|
||||
pv_error(state, "%s: %s: %s",
|
||||
_("failed to read file"), state->input_files[filenum], strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
_("failed to read file"), state->files.filename[filenum], strerror(errno));
|
||||
state->status.exit_status |= 2;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != fstat(fd, &isb)) {
|
||||
pv_error(state, "%s: %s: %s", _("failed to stat file"),
|
||||
NULL == state->input_files ? "-" : state->input_files[filenum], strerror(errno));
|
||||
NULL == state->files.filename ? "-" : state->files.filename[filenum], strerror(errno));
|
||||
(void) close(fd);
|
||||
state->exit_status |= 2;
|
||||
state->status.exit_status |= 2;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 != fstat(STDOUT_FILENO, &osb)) {
|
||||
pv_error(state, "%s: %s", _("failed to stat output file"), strerror(errno));
|
||||
(void) close(fd);
|
||||
state->exit_status |= 2;
|
||||
state->status.exit_status |= 2;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -351,18 +351,18 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
|
||||
if (input_file_is_stdout) {
|
||||
pv_error(state, "%s: %s", _("input file is output file"),
|
||||
NULL == state->input_files ? "-" : state->input_files[filenum]);
|
||||
NULL == state->files.filename ? "-" : state->files.filename[filenum]);
|
||||
(void) close(fd);
|
||||
state->exit_status |= 4;
|
||||
state->status.exit_status |= 4;
|
||||
return -1;
|
||||
}
|
||||
|
||||
state->current_input_file = filenum;
|
||||
state->status.current_input_file = filenum;
|
||||
#ifdef O_DIRECT
|
||||
/*
|
||||
* Set or clear O_DIRECT on the file descriptor.
|
||||
*/
|
||||
if (0 != fcntl(fd, F_SETFL, (state->direct_io ? O_DIRECT : 0) | fcntl(fd, F_GETFL))) {
|
||||
if (0 != fcntl(fd, F_SETFL, (state->control.direct_io ? O_DIRECT : 0) | fcntl(fd, F_GETFL))) {
|
||||
/*@-compdef@ */
|
||||
/*
|
||||
* splint - passed or returned storage is undefined - but at
|
||||
@@ -400,7 +400,7 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
/*@-statictrans@ */
|
||||
/*
|
||||
* Here we are doing bad things with regards to whether the returned
|
||||
* string is an allocated string from the state->input_files array,
|
||||
* string is an allocated string from the state->files.filename array,
|
||||
* a constant string, or a returned string from gettext(), but it
|
||||
* has no impact. We explicitly document, above, that the returned
|
||||
* string expires with the state, and hence switch off the
|
||||
@@ -418,15 +418,15 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
if (NULL == str_stdin)
|
||||
str_stdin = "(stdin)";
|
||||
|
||||
if (state->current_input_file < 0)
|
||||
if (state->status.current_input_file < 0)
|
||||
return str_none;
|
||||
if ((unsigned int) (state->current_input_file) >= state->input_file_count)
|
||||
if ((unsigned int) (state->status.current_input_file) >= state->files.file_count)
|
||||
return str_none;
|
||||
|
||||
if (NULL == state->input_files) {
|
||||
if (NULL == state->files.filename) {
|
||||
input_file_name = NULL;
|
||||
} else {
|
||||
input_file_name = state->input_files[state->current_input_file];
|
||||
input_file_name = state->files.filename[state->status.current_input_file];
|
||||
}
|
||||
if (NULL == input_file_name)
|
||||
return str_none;
|
||||
@@ -437,7 +437,7 @@ int pv_next_file(pvstate_t state, unsigned int filenum, int oldfd)
|
||||
return input_file_name;
|
||||
/*@+compdef@ */
|
||||
/*
|
||||
* splint warns about state->input_files being undefined, but we
|
||||
* splint warns about state->files.filename being undefined, but we
|
||||
* know it's been populated fully by the time this function is
|
||||
* called.
|
||||
*/
|
||||
|
||||
+173
-137
@@ -41,7 +41,6 @@ int pv_main_loop(pvstate_t state)
|
||||
struct timespec start_time, next_update, next_ratecheck, cur_time;
|
||||
struct timespec init_time, next_remotecheck, transfer_elapsed;
|
||||
long double elapsed_seconds;
|
||||
struct stat sb;
|
||||
int fd;
|
||||
unsigned int file_idx;
|
||||
|
||||
@@ -70,7 +69,7 @@ int pv_main_loop(pvstate_t state)
|
||||
total_written = 0;
|
||||
lineswritten = 0;
|
||||
transferred_since_last = 0;
|
||||
state->initial_offset = 0;
|
||||
state->display.initial_offset = 0;
|
||||
|
||||
memset(&cur_time, 0, sizeof(cur_time));
|
||||
memset(&start_time, 0, sizeof(start_time));
|
||||
@@ -85,11 +84,11 @@ int pv_main_loop(pvstate_t state)
|
||||
pv_elapsedtime_copy(&next_ratecheck, &cur_time);
|
||||
pv_elapsedtime_copy(&next_remotecheck, &cur_time);
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
if ((state->delay_start > 0)
|
||||
&& (state->delay_start > state->interval)) {
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->delay_start));
|
||||
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->interval));
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval));
|
||||
}
|
||||
|
||||
target = 0;
|
||||
@@ -100,7 +99,7 @@ int pv_main_loop(pvstate_t state)
|
||||
* Open the first readable input file.
|
||||
*/
|
||||
fd = -1;
|
||||
while (fd < 0 && file_idx < state->input_file_count) {
|
||||
while (fd < 0 && file_idx < state->files.file_count) {
|
||||
fd = pv_next_file(state, file_idx, -1);
|
||||
if (fd < 0)
|
||||
file_idx++;
|
||||
@@ -110,9 +109,9 @@ int pv_main_loop(pvstate_t state)
|
||||
* Exit early if there was no readable input file.
|
||||
*/
|
||||
if (fd < 0) {
|
||||
if (state->cursor)
|
||||
if (state->control.cursor)
|
||||
pv_crs_fini(state);
|
||||
return state->exit_status;
|
||||
return state->status.exit_status;
|
||||
}
|
||||
#if HAVE_POSIX_FADVISE
|
||||
/* Advise the OS that we will only be reading sequentially. */
|
||||
@@ -123,10 +122,11 @@ int pv_main_loop(pvstate_t state)
|
||||
/*
|
||||
* Set or clear O_DIRECT on the output.
|
||||
*/
|
||||
if (0 != fcntl(STDOUT_FILENO, F_SETFL, (state->direct_io ? O_DIRECT : 0) | fcntl(STDOUT_FILENO, F_GETFL))) {
|
||||
if (0 !=
|
||||
fcntl(STDOUT_FILENO, F_SETFL, (state->control.direct_io ? O_DIRECT : 0) | fcntl(STDOUT_FILENO, F_GETFL))) {
|
||||
debug("%s: %s", "fcntl", strerror(errno));
|
||||
}
|
||||
state->direct_io_changed = false;
|
||||
state->control.direct_io_changed = false;
|
||||
#endif /* O_DIRECT */
|
||||
|
||||
#if HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||
@@ -134,17 +134,22 @@ int pv_main_loop(pvstate_t state)
|
||||
* Set target buffer size if the initial file's block size can be
|
||||
* read and we weren't given a target buffer size.
|
||||
*/
|
||||
if ((0 == fstat(fd, &sb)) && (0 == state->target_buffer_size)) {
|
||||
size_t sz;
|
||||
sz = (size_t) (sb.st_blksize * 32);
|
||||
if (sz > BUFFER_SIZE_MAX)
|
||||
sz = BUFFER_SIZE_MAX;
|
||||
state->target_buffer_size = sz;
|
||||
if (0 == state->control.target_buffer_size) {
|
||||
struct stat sb;
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
if (0 == fstat(fd, &sb)) {
|
||||
size_t sz;
|
||||
sz = (size_t) (sb.st_blksize * 32);
|
||||
if (sz > BUFFER_SIZE_MAX) {
|
||||
sz = BUFFER_SIZE_MAX;
|
||||
}
|
||||
state->control.target_buffer_size = sz;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (0 == state->target_buffer_size)
|
||||
state->target_buffer_size = BUFFER_SIZE;
|
||||
if (0 == state->control.target_buffer_size)
|
||||
state->control.target_buffer_size = BUFFER_SIZE;
|
||||
|
||||
while ((!(eof_in && eof_out)) || (!final_update)) {
|
||||
|
||||
@@ -158,17 +163,17 @@ int pv_main_loop(pvstate_t state)
|
||||
pv_elapsedtime_add_nsec(&next_remotecheck, REMOTE_INTERVAL);
|
||||
}
|
||||
|
||||
if (1 == state->pv_sig_abort)
|
||||
if (1 == state->flag.trigger_exit)
|
||||
break;
|
||||
|
||||
if (state->rate_limit > 0) {
|
||||
if (state->control.rate_limit > 0) {
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
if (pv_elapsedtime_compare(&cur_time, &next_ratecheck) > 0) {
|
||||
target +=
|
||||
((long double) (state->rate_limit)) / (long double) (1000000000.0 /
|
||||
(long
|
||||
double) (RATE_GRANULARITY));
|
||||
long double burst_max = ((long double) (state->rate_limit * RATE_BURST_WINDOW));
|
||||
((long double) (state->control.rate_limit)) / (long double) (1000000000.0 /
|
||||
(long double)
|
||||
(RATE_GRANULARITY));
|
||||
long double burst_max = ((long double) (state->control.rate_limit * RATE_BURST_WINDOW));
|
||||
if (target > burst_max) {
|
||||
target = burst_max;
|
||||
}
|
||||
@@ -181,11 +186,11 @@ int pv_main_loop(pvstate_t state)
|
||||
* If we have to stop at "size" bytes, make sure we don't
|
||||
* try to write more than we're allowed to.
|
||||
*/
|
||||
if ((0 < state->size) && (state->stop_at_size)) {
|
||||
if ((state->size < (total_written + cansend))
|
||||
if ((0 < state->control.size) && (state->control.stop_at_size)) {
|
||||
if ((state->control.size < (total_written + cansend))
|
||||
|| ((0 == cansend)
|
||||
&& (0 == state->rate_limit))) {
|
||||
cansend = state->size - total_written;
|
||||
&& (0 == state->control.rate_limit))) {
|
||||
cansend = state->control.size - total_written;
|
||||
if (0 >= cansend) {
|
||||
eof_in = true;
|
||||
eof_out = true;
|
||||
@@ -193,7 +198,7 @@ int pv_main_loop(pvstate_t state)
|
||||
}
|
||||
}
|
||||
|
||||
if ((0 < state->size) && (state->stop_at_size)
|
||||
if ((0 < state->control.size) && (state->control.stop_at_size)
|
||||
&& (0 >= cansend) && eof_in && eof_out) {
|
||||
written = 0;
|
||||
} else {
|
||||
@@ -202,27 +207,27 @@ int pv_main_loop(pvstate_t state)
|
||||
|
||||
/* End on write error. */
|
||||
if (written < 0) {
|
||||
if (state->cursor)
|
||||
if (state->control.cursor)
|
||||
pv_crs_fini(state);
|
||||
return state->exit_status;
|
||||
return state->status.exit_status;
|
||||
}
|
||||
|
||||
if (state->linemode) {
|
||||
if (state->control.linemode) {
|
||||
transferred_since_last += lineswritten;
|
||||
total_written += lineswritten;
|
||||
if (state->rate_limit > 0)
|
||||
if (state->control.rate_limit > 0)
|
||||
target -= lineswritten;
|
||||
} else {
|
||||
transferred_since_last += written;
|
||||
total_written += written;
|
||||
if (state->rate_limit > 0)
|
||||
if (state->control.rate_limit > 0)
|
||||
target -= written;
|
||||
}
|
||||
|
||||
/*
|
||||
* EOF, and files remain - advance to the next file.
|
||||
*/
|
||||
while (eof_in && eof_out && file_idx < (state->input_file_count - 1)) {
|
||||
while (eof_in && eof_out && file_idx < (state->files.file_count - 1)) {
|
||||
file_idx++;
|
||||
fd = pv_next_file(state, file_idx, fd);
|
||||
if (fd >= 0) {
|
||||
@@ -237,14 +242,14 @@ int pv_main_loop(pvstate_t state)
|
||||
/* If full EOF, final update, and force a display updaate. */
|
||||
if (eof_in && eof_out) {
|
||||
final_update = true;
|
||||
if ((state->display_visible)
|
||||
|| (state->delay_start < 0.001)) {
|
||||
if ((state->display.display_visible)
|
||||
|| (state->control.delay_start < 0.001)) {
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
}
|
||||
}
|
||||
|
||||
/* Just go round the loop again if there's no display. */
|
||||
if (state->no_display)
|
||||
if (state->control.no_display)
|
||||
continue;
|
||||
|
||||
/*
|
||||
@@ -253,9 +258,9 @@ int pv_main_loop(pvstate_t state)
|
||||
* we then count time as if we started when the first byte
|
||||
* was received.
|
||||
*/
|
||||
if (state->wait) {
|
||||
if (state->control.wait) {
|
||||
/* Restart the loop if nothing written yet. */
|
||||
if (state->linemode) {
|
||||
if (state->control.linemode) {
|
||||
if (lineswritten < 1)
|
||||
continue;
|
||||
} else {
|
||||
@@ -263,7 +268,7 @@ int pv_main_loop(pvstate_t state)
|
||||
continue;
|
||||
}
|
||||
|
||||
state->wait = 0;
|
||||
state->control.wait = 0;
|
||||
|
||||
/*
|
||||
* Reset the timer offset counter now that data
|
||||
@@ -277,7 +282,7 @@ int pv_main_loop(pvstate_t state)
|
||||
*/
|
||||
pv_sig_nopause();
|
||||
pv_elapsedtime_read(&start_time);
|
||||
pv_elapsedtime_zero(&(state->pv_sig_toffset));
|
||||
pv_elapsedtime_zero(&(state->signal.toffset));
|
||||
pv_sig_allowpause();
|
||||
|
||||
/*
|
||||
@@ -285,7 +290,7 @@ int pv_main_loop(pvstate_t state)
|
||||
* not immediately.
|
||||
*/
|
||||
pv_elapsedtime_copy(&next_update, &start_time);
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
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. */
|
||||
@@ -293,7 +298,7 @@ int pv_main_loop(pvstate_t state)
|
||||
continue;
|
||||
}
|
||||
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
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)
|
||||
@@ -304,7 +309,7 @@ int pv_main_loop(pvstate_t state)
|
||||
* started, plus the total time we spent stopped.
|
||||
*/
|
||||
memset(&init_time, 0, sizeof(init_time));
|
||||
pv_elapsedtime_add(&init_time, &start_time, &(state->pv_sig_toffset));
|
||||
pv_elapsedtime_add(&init_time, &start_time, &(state->signal.toffset));
|
||||
|
||||
/*
|
||||
* Now get the effective elapsed transfer time - current
|
||||
@@ -319,19 +324,19 @@ int pv_main_loop(pvstate_t state)
|
||||
transferred_since_last = -1;
|
||||
|
||||
/* Resize the display, if a resize signal was received. */
|
||||
if (1 == state->pv_sig_newsize) {
|
||||
if (1 == state->flag.terminal_resized) {
|
||||
unsigned int new_width, new_height;
|
||||
|
||||
state->pv_sig_newsize = 0;
|
||||
state->flag.terminal_resized = 0;
|
||||
|
||||
new_width = state->width;
|
||||
new_height = state->height;
|
||||
new_width = state->control.width;
|
||||
new_height = state->control.height;
|
||||
pv_screensize(&new_width, &new_height);
|
||||
|
||||
if (!state->width_set_manually)
|
||||
state->width = new_width;
|
||||
if (!state->height_set_manually)
|
||||
state->height = new_height;
|
||||
if (!state->control.width_set_manually)
|
||||
state->control.width = new_width;
|
||||
if (!state->control.height_set_manually)
|
||||
state->control.height = new_height;
|
||||
}
|
||||
|
||||
pv_display(state, elapsed_seconds, transferred_since_last, total_written);
|
||||
@@ -339,27 +344,27 @@ int pv_main_loop(pvstate_t state)
|
||||
transferred_since_last = 0;
|
||||
}
|
||||
|
||||
if (state->cursor) {
|
||||
if (state->control.cursor) {
|
||||
pv_crs_fini(state);
|
||||
} else {
|
||||
if ((!state->numeric) && (!state->no_display)
|
||||
&& (state->display_visible))
|
||||
if ((!state->control.numeric) && (!state->control.no_display)
|
||||
&& (state->display.display_visible))
|
||||
pv_write_retry(STDERR_FILENO, "\n", 1);
|
||||
}
|
||||
|
||||
if (1 == state->pv_sig_abort)
|
||||
state->exit_status |= 32;
|
||||
if (1 == state->flag.trigger_exit)
|
||||
state->status.exit_status |= 32;
|
||||
|
||||
if (fd >= 0)
|
||||
(void) close(fd);
|
||||
|
||||
return state->exit_status;
|
||||
return state->status.exit_status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Watch the progress of file descriptor state->watch_fd in process
|
||||
* state->watch_pid and show details about the transfer on standard error
|
||||
* Watch the progress of file descriptor state->control.watch_fd in process
|
||||
* state->control.watch_pid and show details about the transfer on standard error
|
||||
* according to the given options.
|
||||
*
|
||||
* Returns nonzero on error.
|
||||
@@ -375,28 +380,32 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
int rc;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.watch_pid = state->watch_pid;
|
||||
info.watch_fd = state->watch_fd;
|
||||
info.watch_pid = state->control.watch_pid;
|
||||
info.watch_fd = state->control.watch_fd;
|
||||
rc = pv_watchfd_info(state, &info, false);
|
||||
if (0 != rc) {
|
||||
state->exit_status |= 2;
|
||||
return state->exit_status;
|
||||
state->status.exit_status |= 2;
|
||||
/*@-compdestroy@ */
|
||||
return state->status.exit_status;
|
||||
/*@+compdestroy@ */
|
||||
/* splint: no leak of info.state as it is unused so far. */
|
||||
}
|
||||
|
||||
/*
|
||||
* Use a size if one was passed, otherwise use the total size
|
||||
* calculated.
|
||||
*/
|
||||
if (0 >= state->size)
|
||||
state->size = info.size;
|
||||
if (0 >= state->control.size)
|
||||
state->control.size = info.size;
|
||||
|
||||
if (state->size < 1) {
|
||||
if (state->control.size < 1) {
|
||||
char *fmt;
|
||||
while (NULL != (fmt = strstr(state->default_format, "%e"))) {
|
||||
while (NULL != (fmt = strstr(state->control.default_format, "%e"))) {
|
||||
debug("%s", "zero size - removing ETA");
|
||||
/* strlen-1 here to include trailing NUL */
|
||||
memmove(fmt, fmt + 2, strlen(fmt) - 1);
|
||||
state->reparse_display = 1;
|
||||
/* strlen-1 here to include trailing \0 */
|
||||
memmove(fmt, fmt + 2, strlen(fmt) - 1); /* flawfinder: ignore */
|
||||
/* flawfinder: default_format is always \0 terminated */
|
||||
state->flag.reparse_display = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,7 +419,7 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
pv_elapsedtime_copy(&(info.start_time), &cur_time);
|
||||
pv_elapsedtime_copy(&next_remotecheck, &cur_time);
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval));
|
||||
|
||||
ended = false;
|
||||
total_written = 0;
|
||||
@@ -426,7 +435,7 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
pv_elapsedtime_add_nsec(&next_remotecheck, REMOTE_INTERVAL);
|
||||
}
|
||||
|
||||
if (1 == state->pv_sig_abort)
|
||||
if (1 == state->flag.trigger_exit)
|
||||
break;
|
||||
|
||||
position_now = pv_watchfd_position(&info);
|
||||
@@ -437,7 +446,7 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
transferred_since_last += position_now - total_written;
|
||||
total_written = position_now;
|
||||
if (first_check) {
|
||||
state->initial_offset = position_now;
|
||||
state->display.initial_offset = position_now;
|
||||
first_check = false;
|
||||
}
|
||||
}
|
||||
@@ -458,7 +467,7 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
continue;
|
||||
}
|
||||
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
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)
|
||||
@@ -468,7 +477,7 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
* Calculate the effective start time: the time we actually
|
||||
* started, plus the total time we spent stopped.
|
||||
*/
|
||||
pv_elapsedtime_add(&init_time, &(info.start_time), &(state->pv_sig_toffset));
|
||||
pv_elapsedtime_add(&init_time, &(info.start_time), &(state->signal.toffset));
|
||||
|
||||
/*
|
||||
* Now get the effective elapsed transfer time - current
|
||||
@@ -482,19 +491,19 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
transferred_since_last = -1;
|
||||
|
||||
/* Resize the display, if a resize signal was received. */
|
||||
if (1 == state->pv_sig_newsize) {
|
||||
if (1 == state->flag.terminal_resized) {
|
||||
unsigned int new_width, new_height;
|
||||
|
||||
state->pv_sig_newsize = 0;
|
||||
state->flag.terminal_resized = 0;
|
||||
|
||||
new_width = state->width;
|
||||
new_height = state->height;
|
||||
new_width = state->control.width;
|
||||
new_height = state->control.height;
|
||||
pv_screensize(&new_width, &new_height);
|
||||
|
||||
if (!state->width_set_manually)
|
||||
state->width = new_width;
|
||||
if (!state->height_set_manually)
|
||||
state->height = new_height;
|
||||
if (!state->control.width_set_manually)
|
||||
state->control.width = new_width;
|
||||
if (!state->control.height_set_manually)
|
||||
state->control.height = new_height;
|
||||
}
|
||||
|
||||
pv_display(state, elapsed_seconds, transferred_since_last, total_written);
|
||||
@@ -502,30 +511,44 @@ int pv_watchfd_loop(pvstate_t state)
|
||||
transferred_since_last = 0;
|
||||
}
|
||||
|
||||
if (!state->numeric)
|
||||
if (!state->control.numeric)
|
||||
pv_write_retry(STDERR_FILENO, "\n", 1);
|
||||
|
||||
if (1 == state->pv_sig_abort)
|
||||
state->exit_status |= 32;
|
||||
if (1 == state->flag.trigger_exit)
|
||||
state->status.exit_status |= 32;
|
||||
|
||||
return state->exit_status;
|
||||
/*
|
||||
* Free the state structure specific to this file descriptor.
|
||||
* Uunused so far - this is so that in future we could watch
|
||||
* multiple file descriptors similar to pv_watchpid_loop().
|
||||
*/
|
||||
if (NULL != info.state) {
|
||||
pv_state_free(info.state);
|
||||
info.state = NULL;
|
||||
}
|
||||
|
||||
/*@-compdestroy@ */
|
||||
return state->status.exit_status;
|
||||
/*@+compdestroy@ */
|
||||
/* splint: no leak of info.state as we just freed it above. */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Watch the progress of all file descriptors in process state->watch_pid
|
||||
* Watch the progress of all file descriptors in process state->control.watch_pid
|
||||
* and show details about the transfers on standard error according to the
|
||||
* given options.
|
||||
*
|
||||
* Replaces format_string in "state" so that starts with "%N " if it doesn't
|
||||
* already do so.
|
||||
*
|
||||
* Returns nonzero on error.
|
||||
*/
|
||||
int pv_watchpid_loop(pvstate_t state)
|
||||
{
|
||||
struct pvstate_s state_copy;
|
||||
const char *original_format_string;
|
||||
char new_format_string[512];
|
||||
char new_format_string[512]; /* flawfinder: ignore */
|
||||
struct pvwatchfd_s *info_array = NULL;
|
||||
struct pvstate_s *state_array = NULL;
|
||||
int array_length = 0;
|
||||
int fd_to_idx[FD_SETSIZE];
|
||||
struct timespec next_update, cur_time;
|
||||
@@ -533,37 +556,40 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
int prev_displayed_lines, blank_lines;
|
||||
bool first_pass = true;
|
||||
|
||||
/*
|
||||
* flawfinder rationale (new_format_string): zeroed with memset(),
|
||||
* only written to with pv_snprintf() which checks boundaries, and
|
||||
* explicitly terminated with \0.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Make sure the process exists first, so we can give an error if
|
||||
* it's not there at the start.
|
||||
*/
|
||||
if (kill(state->watch_pid, 0) != 0) {
|
||||
pv_error(state, "%s %u: %s", _("pid"), state->watch_pid, strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
if (kill(state->control.watch_pid, 0) != 0) {
|
||||
pv_error(state, "%s %u: %s", _("pid"), state->control.watch_pid, strerror(errno));
|
||||
state->status.exit_status |= 2;
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a copy of our state, ready to change in preparation for
|
||||
* duplication.
|
||||
*/
|
||||
memcpy(&state_copy, state, sizeof(state_copy));
|
||||
|
||||
/*
|
||||
* Make sure there's a format string, and then insert %N into it if
|
||||
* it's not present.
|
||||
*/
|
||||
original_format_string = state->format_string ? state->format_string : state->default_format;
|
||||
original_format_string =
|
||||
NULL != state->control.format_string ? state->control.format_string : state->control.default_format;
|
||||
memset(new_format_string, 0, sizeof(new_format_string));
|
||||
if (NULL == strstr(original_format_string, "%N")) {
|
||||
if (NULL == original_format_string) {
|
||||
(void) pv_snprintf(new_format_string, sizeof(new_format_string), "%%N");
|
||||
} else if (NULL == strstr(original_format_string, "%N")) {
|
||||
(void) pv_snprintf(new_format_string, sizeof(new_format_string), "%%N %s", original_format_string);
|
||||
} else {
|
||||
(void) pv_snprintf(new_format_string, sizeof(new_format_string), "%s", original_format_string);
|
||||
}
|
||||
new_format_string[sizeof(new_format_string) - 1] = '\0';
|
||||
state_copy.format_string = NULL;
|
||||
(void) pv_snprintf(state_copy.default_format, PV_SIZEOF_DEFAULT_FORMAT, "%.510s", new_format_string);
|
||||
state_copy.default_format[PV_SIZEOF_DEFAULT_FORMAT - 1] = '\0';
|
||||
if (NULL != state->control.format_string)
|
||||
free(state->control.format_string);
|
||||
state->control.format_string = pv_strdup(new_format_string);
|
||||
|
||||
/*
|
||||
* Get things ready for the main loop.
|
||||
@@ -574,7 +600,7 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
pv_elapsedtime_copy(&next_update, &cur_time);
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->control.interval));
|
||||
|
||||
for (idx = 0; idx < FD_SETSIZE; idx++) {
|
||||
fd_to_idx[idx] = -1;
|
||||
@@ -585,19 +611,17 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
while (true) {
|
||||
int rc, fd, displayed_lines;
|
||||
|
||||
if (1 == state->pv_sig_abort)
|
||||
if (1 == state->flag.trigger_exit)
|
||||
break;
|
||||
|
||||
pv_elapsedtime_read(&cur_time);
|
||||
|
||||
if (kill(state->watch_pid, 0) != 0) {
|
||||
if (kill(state->control.watch_pid, 0) != 0) {
|
||||
if (first_pass) {
|
||||
pv_error(state, "%s %u: %s", _("pid"), state->watch_pid, strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
pv_error(state, "%s %u: %s", _("pid"), state->control.watch_pid, strerror(errno));
|
||||
state->status.exit_status |= 2;
|
||||
if (NULL != info_array)
|
||||
free(info_array);
|
||||
if (NULL != state_array)
|
||||
free(state_array);
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
@@ -612,34 +636,33 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
continue;
|
||||
}
|
||||
|
||||
pv_elapsedtime_add_nsec(&next_update, (long long) (1000000000.0 * state->interval));
|
||||
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. */
|
||||
if (1 == state->pv_sig_newsize) {
|
||||
state->pv_sig_newsize = 0;
|
||||
pv_screensize(&(state->width), &(state->height));
|
||||
for (idx = 0; idx < array_length; idx++) {
|
||||
state_array[idx].width = state->width;
|
||||
state_array[idx].height = state->height;
|
||||
if (1 == state->flag.terminal_resized) {
|
||||
state->flag.terminal_resized = 0;
|
||||
pv_screensize(&(state->control.width), &(state->control.height));
|
||||
for (idx = 0; NULL != info_array && idx < array_length; idx++) {
|
||||
if (NULL == info_array[idx].state)
|
||||
continue;
|
||||
info_array[idx].state->control.width = state->control.width;
|
||||
info_array[idx].state->control.height = state->control.height;
|
||||
pv_watchpid_setname(state, &(info_array[idx]));
|
||||
state_array[idx].reparse_display = 1;
|
||||
info_array[idx].state->flag.reparse_display = 1;
|
||||
}
|
||||
}
|
||||
|
||||
rc = pv_watchpid_scanfds(state, &state_copy,
|
||||
state->watch_pid, &array_length, &info_array, &state_array, fd_to_idx);
|
||||
rc = pv_watchpid_scanfds(state, state->control.watch_pid, &array_length, &info_array, fd_to_idx);
|
||||
if (rc != 0) {
|
||||
if (first_pass) {
|
||||
pv_error(state, "%s %u: %s", _("pid"), state->watch_pid, strerror(errno));
|
||||
state->exit_status |= 2;
|
||||
pv_error(state, "%s %u: %s", _("pid"), state->control.watch_pid, strerror(errno));
|
||||
state->status.exit_status |= 2;
|
||||
if (NULL != info_array)
|
||||
free(info_array);
|
||||
if (NULL != state_array)
|
||||
free(state_array);
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
@@ -648,12 +671,12 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
first_pass = false;
|
||||
displayed_lines = 0;
|
||||
|
||||
for (fd = 0; fd < FD_SETSIZE; fd++) {
|
||||
for (fd = 0; fd < FD_SETSIZE && NULL != info_array; fd++) {
|
||||
off_t position_now, transferred_since_last;
|
||||
struct timespec init_time, transfer_elapsed;
|
||||
long double elapsed_seconds;
|
||||
|
||||
if (displayed_lines >= (int) (state->height))
|
||||
if (displayed_lines >= (int) (state->control.height))
|
||||
break;
|
||||
|
||||
idx = fd_to_idx[fd];
|
||||
@@ -674,6 +697,11 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NULL == info_array[idx].state) {
|
||||
debug("%s %d: %s", "fd", fd, "null state - skipping");
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Displayable fd - display, or remove if changed
|
||||
*/
|
||||
@@ -697,7 +725,7 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
* Calculate the effective start time: the time we actually
|
||||
* started, plus the total time we spent stopped.
|
||||
*/
|
||||
pv_elapsedtime_add(&init_time, &(info_array[idx].start_time), &(state->pv_sig_toffset));
|
||||
pv_elapsedtime_add(&init_time, &(info_array[idx].start_time), &(state->signal.toffset));
|
||||
|
||||
/*
|
||||
* Now get the effective elapsed transfer time - current
|
||||
@@ -715,7 +743,7 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
debug("%s %d [%d]: %Lf / %Ld / %Ld", "fd", fd, idx, elapsed_seconds, transferred_since_last,
|
||||
position_now);
|
||||
|
||||
pv_display(&(state_array[idx]), elapsed_seconds, transferred_since_last, position_now);
|
||||
pv_display(info_array[idx].state, elapsed_seconds, transferred_since_last, position_now);
|
||||
displayed_lines++;
|
||||
}
|
||||
|
||||
@@ -733,7 +761,7 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
unsigned int x;
|
||||
if (displayed_lines > 0)
|
||||
pv_write_retry(STDERR_FILENO, "\n", 1);
|
||||
for (x = 0; x < state->width; x++)
|
||||
for (x = 0; x < state->control.width; x++)
|
||||
pv_write_retry(STDERR_FILENO, " ", 1);
|
||||
pv_write_retry(STDERR_FILENO, "\r", 1);
|
||||
blank_lines--;
|
||||
@@ -754,7 +782,7 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
blank_lines = prev_displayed_lines;
|
||||
while (blank_lines > 0) {
|
||||
unsigned int x;
|
||||
for (x = 0; x < state->width; x++)
|
||||
for (x = 0; x < state->control.width; x++)
|
||||
pv_write_retry(STDERR_FILENO, " ", 1);
|
||||
pv_write_retry(STDERR_FILENO, "\r", 1);
|
||||
blank_lines--;
|
||||
@@ -766,10 +794,18 @@ int pv_watchpid_loop(pvstate_t state)
|
||||
prev_displayed_lines--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the per-fd state.
|
||||
*/
|
||||
for (idx = 0; NULL != info_array && idx < array_length; idx++) {
|
||||
if (NULL == info_array[idx].state)
|
||||
continue;
|
||||
pv_state_free(info_array[idx].state);
|
||||
info_array[idx].state = NULL;
|
||||
}
|
||||
|
||||
if (NULL != info_array)
|
||||
free(info_array);
|
||||
if (NULL != state_array)
|
||||
free(state_array);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+100
-44
@@ -45,7 +45,7 @@ static void pv_sig_ensure_tty_tostop()
|
||||
if (0 == (terminal_attributes.c_lflag & TOSTOP)) {
|
||||
terminal_attributes.c_lflag |= TOSTOP;
|
||||
if (0 == tcsetattr(STDERR_FILENO, TCSANOW, &terminal_attributes)) {
|
||||
pv_sig_state->pv_tty_tostop_added = true;
|
||||
pv_sig_state->signal.pv_tty_tostop_added = true;
|
||||
debug("%s", "set terminal TOSTOP attribute");
|
||||
} else {
|
||||
debug("%s: %s", "failed to set terminal TOSTOP attribute", strerror(errno));
|
||||
@@ -55,8 +55,9 @@ static void pv_sig_ensure_tty_tostop()
|
||||
* In "-c" mode with IPC, make all "pv -c" instances aware
|
||||
* that we set TOSTOP, so the last one can clear it on exit.
|
||||
*/
|
||||
if (pv_sig_state->cursor && (NULL != pv_sig_state->crs_shared) && (!pv_sig_state->crs_noipc)) {
|
||||
pv_sig_state->crs_shared->tty_tostop_added = true;
|
||||
if (pv_sig_state->control.cursor && (NULL != pv_sig_state->cursor.shared)
|
||||
&& (!pv_sig_state->cursor.noipc)) {
|
||||
pv_sig_state->cursor.shared->tty_tostop_added = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -92,8 +93,8 @@ static void pv_sig_ttou( /*@unused@ */ __attribute__((unused))
|
||||
* stderr while backgrounded.
|
||||
*/
|
||||
|
||||
if (-1 == pv_sig_state->pv_sig_old_stderr)
|
||||
pv_sig_state->pv_sig_old_stderr = dup(STDERR_FILENO);
|
||||
if (-1 == pv_sig_state->signal.old_stderr)
|
||||
pv_sig_state->signal.old_stderr = dup(STDERR_FILENO);
|
||||
|
||||
if (dup2(fd, STDERR_FILENO) < 0) {
|
||||
debug("%s: %s", "failed to replace stderr", strerror(errno));
|
||||
@@ -114,7 +115,7 @@ static void pv_sig_tstp( /*@unused@ */ __attribute__((unused))
|
||||
{
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
pv_elapsedtime_read(&(pv_sig_state->pv_sig_tstp_time));
|
||||
pv_elapsedtime_read(&(pv_sig_state->signal.tstp_time));
|
||||
if (0 != raise(SIGSTOP)) {
|
||||
debug("%s: %s", "raise", strerror(errno));
|
||||
}
|
||||
@@ -135,13 +136,13 @@ static void pv_sig_cont( /*@unused@ */ __attribute__((unused))
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
|
||||
pv_sig_state->pv_sig_newsize = 1;
|
||||
pv_sig_state->flag.terminal_resized = 1;
|
||||
|
||||
/*
|
||||
* 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->pv_sig_tstp_time.tv_sec) {
|
||||
if (0 != pv_sig_state->signal.tstp_time.tv_sec) {
|
||||
|
||||
memset(¤t_time, 0, sizeof(current_time));
|
||||
memset(&time_spent_stopped, 0, sizeof(time_spent_stopped));
|
||||
@@ -149,27 +150,27 @@ 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->pv_sig_tstp_time));
|
||||
pv_elapsedtime_subtract(&time_spent_stopped, ¤t_time, &(pv_sig_state->signal.tstp_time));
|
||||
|
||||
/* add time spent stopped the total stopped-time count */
|
||||
pv_elapsedtime_add(&(pv_sig_state->pv_sig_toffset), &(pv_sig_state->pv_sig_toffset),
|
||||
pv_elapsedtime_add(&(pv_sig_state->signal.toffset), &(pv_sig_state->signal.toffset),
|
||||
&time_spent_stopped);
|
||||
|
||||
/* reset the SIGTSTP receipt time */
|
||||
pv_elapsedtime_zero(&(pv_sig_state->pv_sig_tstp_time));
|
||||
pv_elapsedtime_zero(&(pv_sig_state->signal.tstp_time));
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the old stderr, if we had replaced it.
|
||||
*/
|
||||
if (pv_sig_state->pv_sig_old_stderr != -1) {
|
||||
if (dup2(pv_sig_state->pv_sig_old_stderr, STDERR_FILENO) < 0) {
|
||||
if (pv_sig_state->signal.old_stderr != -1) {
|
||||
if (dup2(pv_sig_state->signal.old_stderr, STDERR_FILENO) < 0) {
|
||||
debug("%s: %s", "failed to restore old stderr", strerror(errno));
|
||||
}
|
||||
if (0 != close(pv_sig_state->pv_sig_old_stderr)) {
|
||||
if (0 != close(pv_sig_state->signal.old_stderr)) {
|
||||
debug("%s: %s", "failed to close duplicate old stderr", strerror(errno));
|
||||
}
|
||||
pv_sig_state->pv_sig_old_stderr = -1;
|
||||
pv_sig_state->signal.old_stderr = -1;
|
||||
}
|
||||
|
||||
pv_sig_ensure_tty_tostop();
|
||||
@@ -189,7 +190,7 @@ static void pv_sig_winch( /*@unused@ */ __attribute__((unused))
|
||||
{
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
pv_sig_state->pv_sig_newsize = 1;
|
||||
pv_sig_state->flag.terminal_resized = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -202,10 +203,47 @@ static void pv_sig_term( /*@unused@ */ __attribute__((unused))
|
||||
{
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
pv_sig_state->pv_sig_abort = 1;
|
||||
pv_sig_state->flag.trigger_exit = 1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef SA_SIGINFO
|
||||
/*
|
||||
* Handle a SIGUSR2 by setting a flag to say we received it, after recording
|
||||
* the sending PID.
|
||||
*/
|
||||
static void pv_sig_usr2( /*@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.rxusr2 = 1;
|
||||
pv_sig_state->signal.sender = info->si_pid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return true if a SIGUSR2 signal has been received since the last time
|
||||
* this function was called, populating *pid with the sending PID if so.
|
||||
*/
|
||||
bool pv_sigusr2_received(pvstate_t state, pid_t * pid)
|
||||
{
|
||||
if (NULL == state)
|
||||
return false;
|
||||
if (0 == state->signal.rxusr2)
|
||||
return false;
|
||||
if (NULL != pid)
|
||||
*pid = state->signal.sender;
|
||||
state->signal.rxusr2 = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Initialise signal handling.
|
||||
*/
|
||||
@@ -224,9 +262,9 @@ void pv_sig_init(pvstate_t state)
|
||||
|
||||
pv_sig_state = state;
|
||||
|
||||
pv_sig_state->pv_sig_old_stderr = -1;
|
||||
pv_elapsedtime_zero(&(pv_sig_state->pv_sig_tstp_time));
|
||||
pv_elapsedtime_zero(&(pv_sig_state->pv_sig_toffset));
|
||||
pv_sig_state->signal.old_stderr = -1;
|
||||
pv_elapsedtime_zero(&(pv_sig_state->signal.tstp_time));
|
||||
pv_elapsedtime_zero(&(pv_sig_state->signal.toffset));
|
||||
|
||||
/*
|
||||
* Note that we cast all sigemptyset() and sigaction() return values
|
||||
@@ -241,7 +279,7 @@ void pv_sig_init(pvstate_t state)
|
||||
sa.sa_handler = SIG_IGN;
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
(void) sigaction(SIGPIPE, &sa, &(pv_sig_state->pv_sig_old_sigpipe));
|
||||
(void) sigaction(SIGPIPE, &sa, &(pv_sig_state->signal.old_sigpipe));
|
||||
|
||||
/*
|
||||
* Handle SIGTTOU by continuing with output switched off, so that we
|
||||
@@ -250,7 +288,7 @@ void pv_sig_init(pvstate_t state)
|
||||
sa.sa_handler = pv_sig_ttou;
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
(void) sigaction(SIGTTOU, &sa, &(pv_sig_state->pv_sig_old_sigttou));
|
||||
(void) sigaction(SIGTTOU, &sa, &(pv_sig_state->signal.old_sigttou));
|
||||
|
||||
/*
|
||||
* Handle SIGTSTP by storing the time the signal happened for later
|
||||
@@ -259,7 +297,7 @@ void pv_sig_init(pvstate_t state)
|
||||
sa.sa_handler = pv_sig_tstp;
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
(void) sigaction(SIGTSTP, &sa, &(pv_sig_state->pv_sig_old_sigtstp));
|
||||
(void) sigaction(SIGTSTP, &sa, &(pv_sig_state->signal.old_sigtstp));
|
||||
|
||||
/*
|
||||
* Handle SIGCONT by adding the elapsed time since the last SIGTSTP
|
||||
@@ -269,7 +307,7 @@ void pv_sig_init(pvstate_t state)
|
||||
sa.sa_handler = pv_sig_cont;
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
(void) sigaction(SIGCONT, &sa, &(pv_sig_state->pv_sig_old_sigcont));
|
||||
(void) sigaction(SIGCONT, &sa, &(pv_sig_state->signal.old_sigcont));
|
||||
|
||||
/*
|
||||
* Handle SIGWINCH by setting a flag to let the main loop know it
|
||||
@@ -279,7 +317,7 @@ void pv_sig_init(pvstate_t state)
|
||||
sa.sa_handler = pv_sig_winch;
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
(void) sigaction(SIGWINCH, &sa, &(pv_sig_state->pv_sig_old_sigwinch));
|
||||
(void) sigaction(SIGWINCH, &sa, &(pv_sig_state->signal.old_sigwinch));
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -289,17 +327,32 @@ void pv_sig_init(pvstate_t state)
|
||||
sa.sa_handler = pv_sig_term;
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
(void) sigaction(SIGINT, &sa, &(pv_sig_state->pv_sig_old_sigint));
|
||||
(void) sigaction(SIGINT, &sa, &(pv_sig_state->signal.old_sigint));
|
||||
|
||||
sa.sa_handler = pv_sig_term;
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
(void) sigaction(SIGHUP, &sa, &(pv_sig_state->pv_sig_old_sighup));
|
||||
(void) sigaction(SIGHUP, &sa, &(pv_sig_state->signal.old_sighup));
|
||||
|
||||
sa.sa_handler = pv_sig_term;
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
sa.sa_flags = 0;
|
||||
(void) sigaction(SIGTERM, &sa, &(pv_sig_state->pv_sig_old_sigterm));
|
||||
(void) sigaction(SIGTERM, &sa, &(pv_sig_state->signal.old_sigterm));
|
||||
|
||||
#ifdef SA_SIGINFO
|
||||
/*
|
||||
* Handle SIGUSR2 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_usr2;
|
||||
(void) sigemptyset(&(sa.sa_mask));
|
||||
/*@-unrecog@ *//* splint doesn't know about SA_SIGINFO */
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
/*@+unrecog@ */
|
||||
(void) sigaction(SIGUSR2, &sa, &(pv_sig_state->signal.old_sigusr2));
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ensure that the TOSTOP terminal attribute is set, so that a
|
||||
@@ -323,20 +376,23 @@ void pv_sig_fini( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
if (NULL == pv_sig_state)
|
||||
return;
|
||||
|
||||
(void) sigaction(SIGPIPE, &(pv_sig_state->pv_sig_old_sigpipe), NULL);
|
||||
(void) sigaction(SIGTTOU, &(pv_sig_state->pv_sig_old_sigttou), NULL);
|
||||
(void) sigaction(SIGTSTP, &(pv_sig_state->pv_sig_old_sigtstp), NULL);
|
||||
(void) sigaction(SIGCONT, &(pv_sig_state->pv_sig_old_sigcont), NULL);
|
||||
(void) sigaction(SIGPIPE, &(pv_sig_state->signal.old_sigpipe), NULL);
|
||||
(void) sigaction(SIGTTOU, &(pv_sig_state->signal.old_sigttou), NULL);
|
||||
(void) sigaction(SIGTSTP, &(pv_sig_state->signal.old_sigtstp), NULL);
|
||||
(void) sigaction(SIGCONT, &(pv_sig_state->signal.old_sigcont), NULL);
|
||||
#ifdef SIGWINCH
|
||||
(void) sigaction(SIGWINCH, &(pv_sig_state->pv_sig_old_sigwinch), NULL);
|
||||
(void) sigaction(SIGWINCH, &(pv_sig_state->signal.old_sigwinch), NULL);
|
||||
#endif
|
||||
(void) sigaction(SIGINT, &(pv_sig_state->signal.old_sigint), NULL);
|
||||
(void) sigaction(SIGHUP, &(pv_sig_state->signal.old_sighup), NULL);
|
||||
(void) sigaction(SIGTERM, &(pv_sig_state->signal.old_sigterm), NULL);
|
||||
#ifdef SA_SIGINFO
|
||||
(void) sigaction(SIGUSR2, &(pv_sig_state->signal.old_sigusr2), NULL);
|
||||
#endif
|
||||
(void) sigaction(SIGINT, &(pv_sig_state->pv_sig_old_sigint), NULL);
|
||||
(void) sigaction(SIGHUP, &(pv_sig_state->pv_sig_old_sighup), NULL);
|
||||
(void) sigaction(SIGTERM, &(pv_sig_state->pv_sig_old_sigterm), NULL);
|
||||
|
||||
need_to_clear_tostop = pv_sig_state->pv_tty_tostop_added;
|
||||
need_to_clear_tostop = pv_sig_state->signal.pv_tty_tostop_added;
|
||||
|
||||
if (pv_sig_state->cursor) {
|
||||
if (pv_sig_state->control.cursor) {
|
||||
#ifdef HAVE_IPC
|
||||
/*
|
||||
* We won't clear TOSTOP if other "pv -c" instances
|
||||
@@ -345,7 +401,7 @@ void pv_sig_fini( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
* TODO: we need a better way to determine if we're the last
|
||||
* "pv" left.
|
||||
*/
|
||||
if (pv_sig_state->cursor && pv_sig_state->crs_pvcount > 1) {
|
||||
if (pv_sig_state->control.cursor && pv_sig_state->cursor.pvcount > 1) {
|
||||
need_to_clear_tostop = false;
|
||||
}
|
||||
#else /* !HAVE_IPC */
|
||||
@@ -375,7 +431,7 @@ void pv_sig_fini( /*@unused@ */ __attribute__((unused)) pvstate_t state)
|
||||
}
|
||||
}
|
||||
|
||||
pv_sig_state->pv_tty_tostop_added = false;
|
||||
pv_sig_state->signal.pv_tty_tostop_added = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,18 +496,18 @@ void pv_sig_checkbg(void)
|
||||
|
||||
next_check = time(NULL) + 1;
|
||||
|
||||
if (-1 == pv_sig_state->pv_sig_old_stderr)
|
||||
if (-1 == pv_sig_state->signal.old_stderr)
|
||||
return;
|
||||
|
||||
if (dup2(pv_sig_state->pv_sig_old_stderr, STDERR_FILENO) < 0) {
|
||||
if (dup2(pv_sig_state->signal.old_stderr, STDERR_FILENO) < 0) {
|
||||
debug("%s: %s", "failed to restore old stderr", strerror(errno));
|
||||
}
|
||||
|
||||
if (0 != close(pv_sig_state->pv_sig_old_stderr)) {
|
||||
if (0 != close(pv_sig_state->signal.old_stderr)) {
|
||||
debug("%s: %s", "failed to close duplicate old stderr", strerror(errno));
|
||||
}
|
||||
|
||||
pv_sig_state->pv_sig_old_stderr = -1;
|
||||
pv_sig_state->signal.old_stderr = -1;
|
||||
|
||||
pv_sig_ensure_tty_tostop();
|
||||
#ifdef HAVE_IPC
|
||||
|
||||
+112
-110
@@ -20,26 +20,26 @@
|
||||
/* alloc / realloc history buffer */
|
||||
static void pv_alloc_history(pvstate_t state)
|
||||
{
|
||||
if (NULL != state->history)
|
||||
free(state->history);
|
||||
state->history = NULL;
|
||||
if (NULL != state->display.history)
|
||||
free(state->display.history);
|
||||
state->display.history = NULL;
|
||||
|
||||
state->history = calloc((size_t) (state->history_len), sizeof(state->history[0]));
|
||||
if (NULL == state->history) {
|
||||
state->display.history = calloc((size_t) (state->display.history_len), sizeof(state->display.history[0]));
|
||||
if (NULL == state->display.history) {
|
||||
/*@-mustfreefresh@ */
|
||||
/*
|
||||
* splint note: the gettext calls made by _() cause memory
|
||||
* leak warnings, but in this case it's unavoidable, and
|
||||
* mitigated by the fact we only translate each string once.
|
||||
*/
|
||||
fprintf(stderr, "%s: %s: %s\n", state->program_name,
|
||||
fprintf(stderr, "%s: %s: %s\n", state->status.program_name,
|
||||
_("history structure allocation failed"), strerror(errno));
|
||||
/*@+mustfreefresh@ */
|
||||
return;
|
||||
}
|
||||
|
||||
state->history_first = state->history_last = 0;
|
||||
state->history[0].elapsed_sec = 0.0; /* to be safe, memset() not recommended for doubles */
|
||||
state->display.history_first = state->display.history_last = 0;
|
||||
state->display.history[0].elapsed_sec = 0.0; /* to be safe, memset() not recommended for doubles */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -55,44 +55,44 @@ pvstate_t pv_state_alloc(const char *program_name)
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
/* splint 3.1.2 thinks this is required for some reason. */
|
||||
if (NULL != state->program_name) {
|
||||
free(state->program_name);
|
||||
if (NULL != state->status.program_name) {
|
||||
free(state->status.program_name);
|
||||
}
|
||||
|
||||
state->program_name = pv_strdup(program_name);
|
||||
if (NULL == state->program_name) {
|
||||
state->status.program_name = pv_strdup(program_name);
|
||||
if (NULL == state->status.program_name) {
|
||||
free(state);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state->watch_pid = 0;
|
||||
state->watch_fd = -1;
|
||||
state->control.watch_pid = 0;
|
||||
state->control.watch_fd = -1;
|
||||
#ifdef HAVE_IPC
|
||||
state->crs_shmid = -1;
|
||||
state->crs_pvcount = 1;
|
||||
state->cursor.shmid = -1;
|
||||
state->cursor.pvcount = 1;
|
||||
#endif /* HAVE_IPC */
|
||||
state->crs_lock_fd = -1;
|
||||
state->cursor.lock_fd = -1;
|
||||
|
||||
state->reparse_display = 1;
|
||||
state->current_input_file = -1;
|
||||
state->flag.reparse_display = 1;
|
||||
state->status.current_input_file = -1;
|
||||
#ifdef HAVE_SPLICE
|
||||
state->splice_failed_fd = -1;
|
||||
state->transfer.splice_failed_fd = -1;
|
||||
#endif /* HAVE_SPLICE */
|
||||
state->display_visible = false;
|
||||
state->display.display_visible = false;
|
||||
|
||||
/*
|
||||
* Get the current working directory, if possible, as a base for
|
||||
* showing relative filenames with --watchfd.
|
||||
*/
|
||||
if (NULL == getcwd(state->cwd, PV_SIZEOF_CWD - 1)) {
|
||||
if (NULL == getcwd(state->status.cwd, PV_SIZEOF_CWD - 1)) {
|
||||
/* failed - will always show full path */
|
||||
state->cwd[0] = '\0';
|
||||
state->status.cwd[0] = '\0';
|
||||
}
|
||||
if ('\0' == state->cwd[1]) {
|
||||
if ('\0' == state->status.cwd[1]) {
|
||||
/* CWD is root directory - always show full path */
|
||||
state->cwd[0] = '\0';
|
||||
state->status.cwd[0] = '\0';
|
||||
}
|
||||
state->cwd[PV_SIZEOF_CWD - 1] = '\0';
|
||||
state->status.cwd[PV_SIZEOF_CWD - 1] = '\0';
|
||||
|
||||
return state;
|
||||
}
|
||||
@@ -106,45 +106,45 @@ void pv_state_free(pvstate_t state)
|
||||
if (0 == state)
|
||||
return;
|
||||
|
||||
if (NULL != state->program_name)
|
||||
free(state->program_name);
|
||||
state->program_name = NULL;
|
||||
if (NULL != state->status.program_name)
|
||||
free(state->status.program_name);
|
||||
state->status.program_name = NULL;
|
||||
|
||||
if (NULL != state->display_buffer)
|
||||
free(state->display_buffer);
|
||||
state->display_buffer = NULL;
|
||||
if (NULL != state->display.display_buffer)
|
||||
free(state->display.display_buffer);
|
||||
state->display.display_buffer = NULL;
|
||||
|
||||
if (NULL != state->name) {
|
||||
free(state->name);
|
||||
state->name = NULL;
|
||||
if (NULL != state->control.name) {
|
||||
free(state->control.name);
|
||||
state->control.name = NULL;
|
||||
}
|
||||
|
||||
if (NULL != state->format_string) {
|
||||
free(state->format_string);
|
||||
state->format_string = NULL;
|
||||
if (NULL != state->control.format_string) {
|
||||
free(state->control.format_string);
|
||||
state->control.format_string = NULL;
|
||||
}
|
||||
|
||||
/*@-keeptrans@ */
|
||||
if (NULL != state->transfer_buffer)
|
||||
free(state->transfer_buffer);
|
||||
state->transfer_buffer = NULL;
|
||||
if (NULL != state->transfer.transfer_buffer)
|
||||
free(state->transfer.transfer_buffer);
|
||||
state->transfer.transfer_buffer = NULL;
|
||||
/*@+keeptrans@ */
|
||||
/* splint - explicitly freeing this structure, so free() here is OK. */
|
||||
|
||||
if (NULL != state->history)
|
||||
free(state->history);
|
||||
state->history = NULL;
|
||||
if (NULL != state->display.history)
|
||||
free(state->display.history);
|
||||
state->display.history = NULL;
|
||||
|
||||
if (NULL != state->input_files) {
|
||||
if (NULL != state->files.filename) {
|
||||
unsigned int file_idx;
|
||||
for (file_idx = 0; file_idx < state->input_file_count; file_idx++) {
|
||||
for (file_idx = 0; file_idx < state->files.file_count; file_idx++) {
|
||||
/*@-unqualifiedtrans@ */
|
||||
free(state->input_files[file_idx]);
|
||||
free(state->files.filename[file_idx]);
|
||||
/*@+unqualifiedtrans@ */
|
||||
/* splint: see similar code below. */
|
||||
}
|
||||
free(state->input_files);
|
||||
state->input_files = NULL;
|
||||
free(state->files.filename);
|
||||
state->files.filename = NULL;
|
||||
}
|
||||
|
||||
free(state);
|
||||
@@ -160,12 +160,12 @@ void pv_state_set_format(pvstate_t state, bool progress, bool timer, bool eta, b
|
||||
const char *name)
|
||||
{
|
||||
#define PV_ADDFORMAT(x,y) if (x) { \
|
||||
if (state->default_format[0] != '\0') \
|
||||
(void) pv_strlcat(state->default_format, " ", sizeof(state->default_format)); \
|
||||
(void) pv_strlcat(state->default_format, y, sizeof(state->default_format)); \
|
||||
if (state->control.default_format[0] != '\0') \
|
||||
(void) pv_strlcat(state->control.default_format, " ", sizeof(state->control.default_format)); \
|
||||
(void) pv_strlcat(state->control.default_format, y, sizeof(state->control.default_format)); \
|
||||
}
|
||||
|
||||
state->default_format[0] = '\0';
|
||||
state->control.default_format[0] = '\0';
|
||||
PV_ADDFORMAT(name, "%N");
|
||||
PV_ADDFORMAT(bytes, "%b");
|
||||
PV_ADDFORMAT(bufpercent, "%T");
|
||||
@@ -187,171 +187,172 @@ void pv_state_set_format(pvstate_t state, bool progress, bool timer, bool eta, b
|
||||
*/
|
||||
}
|
||||
|
||||
if (NULL != state->name) {
|
||||
free(state->name);
|
||||
state->name = NULL;
|
||||
if (NULL != state->control.name) {
|
||||
free(state->control.name);
|
||||
state->control.name = NULL;
|
||||
}
|
||||
|
||||
if (NULL != name)
|
||||
state->name = pv_strdup(name);
|
||||
state->control.name = pv_strdup(name);
|
||||
|
||||
state->reparse_display = 1;
|
||||
state->flag.reparse_display = 1;
|
||||
}
|
||||
|
||||
|
||||
void pv_state_force_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->force = val;
|
||||
state->control.force = val;
|
||||
}
|
||||
|
||||
void pv_state_cursor_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->cursor = val;
|
||||
state->control.cursor = val;
|
||||
}
|
||||
|
||||
void pv_state_numeric_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->numeric = val;
|
||||
state->control.numeric = val;
|
||||
}
|
||||
|
||||
void pv_state_wait_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->wait = val;
|
||||
state->control.wait = val;
|
||||
}
|
||||
|
||||
void pv_state_delay_start_set(pvstate_t state, double val)
|
||||
{
|
||||
state->delay_start = val;
|
||||
state->control.delay_start = val;
|
||||
}
|
||||
|
||||
void pv_state_linemode_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->linemode = val;
|
||||
state->control.linemode = val;
|
||||
}
|
||||
|
||||
void pv_state_bits_set(pvstate_t state, bool bits)
|
||||
{
|
||||
state->bits = bits;
|
||||
state->control.bits = bits;
|
||||
}
|
||||
|
||||
void pv_state_null_terminated_lines_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->null_terminated_lines = val;
|
||||
state->control.null_terminated_lines = val;
|
||||
}
|
||||
|
||||
void pv_state_no_display_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->no_display = val;
|
||||
state->control.no_display = val;
|
||||
}
|
||||
|
||||
void pv_state_skip_errors_set(pvstate_t state, unsigned int val)
|
||||
{
|
||||
state->skip_errors = val;
|
||||
state->control.skip_errors = val;
|
||||
}
|
||||
|
||||
void pv_state_error_skip_block_set(pvstate_t state, off_t val)
|
||||
{
|
||||
state->error_skip_block = val;
|
||||
state->control.error_skip_block = val;
|
||||
}
|
||||
|
||||
void pv_state_stop_at_size_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->stop_at_size = val;
|
||||
state->control.stop_at_size = val;
|
||||
}
|
||||
|
||||
void pv_state_sync_after_write_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->sync_after_write = val;
|
||||
state->control.sync_after_write = val;
|
||||
}
|
||||
|
||||
void pv_state_direct_io_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->direct_io = val;
|
||||
state->direct_io_changed = true;
|
||||
state->control.direct_io = val;
|
||||
state->control.direct_io_changed = true;
|
||||
}
|
||||
|
||||
void pv_state_discard_input_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->discard_input = val;
|
||||
state->control.discard_input = val;
|
||||
}
|
||||
|
||||
void pv_state_rate_limit_set(pvstate_t state, off_t val)
|
||||
{
|
||||
state->rate_limit = val;
|
||||
state->control.rate_limit = val;
|
||||
}
|
||||
|
||||
void pv_state_target_buffer_size_set(pvstate_t state, size_t val)
|
||||
{
|
||||
state->target_buffer_size = val;
|
||||
state->control.target_buffer_size = val;
|
||||
}
|
||||
|
||||
void pv_state_no_splice_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->no_splice = val;
|
||||
state->control.no_splice = val;
|
||||
}
|
||||
|
||||
void pv_state_size_set(pvstate_t state, off_t val)
|
||||
{
|
||||
state->size = val;
|
||||
state->control.size = val;
|
||||
}
|
||||
|
||||
void pv_state_interval_set(pvstate_t state, double val)
|
||||
{
|
||||
state->interval = val;
|
||||
state->control.interval = val;
|
||||
}
|
||||
|
||||
void pv_state_width_set(pvstate_t state, unsigned int val, bool was_set_manually)
|
||||
{
|
||||
state->width = val;
|
||||
state->width_set_manually = was_set_manually;
|
||||
state->control.width = val;
|
||||
state->control.width_set_manually = was_set_manually;
|
||||
}
|
||||
|
||||
void pv_state_height_set(pvstate_t state, unsigned int val, bool was_set_manually)
|
||||
{
|
||||
state->height = val;
|
||||
state->height_set_manually = was_set_manually;
|
||||
state->control.height = val;
|
||||
state->control.height_set_manually = was_set_manually;
|
||||
}
|
||||
|
||||
void pv_state_name_set(pvstate_t state, /*@null@ */ const char *val)
|
||||
{
|
||||
if (NULL != state->name) {
|
||||
free(state->name);
|
||||
state->name = NULL;
|
||||
if (NULL != state->control.name) {
|
||||
free(state->control.name);
|
||||
state->control.name = NULL;
|
||||
}
|
||||
if (NULL != val)
|
||||
state->name = pv_strdup(val);
|
||||
state->control.name = pv_strdup(val);
|
||||
}
|
||||
|
||||
void pv_state_format_string_set(pvstate_t state, /*@null@ */ const char *val)
|
||||
{
|
||||
if (NULL != state->format_string) {
|
||||
free(state->format_string);
|
||||
state->format_string = NULL;
|
||||
if (NULL != state->control.format_string) {
|
||||
free(state->control.format_string);
|
||||
state->control.format_string = NULL;
|
||||
}
|
||||
if (NULL != val)
|
||||
state->format_string = pv_strdup(val);
|
||||
state->control.format_string = pv_strdup(val);
|
||||
}
|
||||
|
||||
void pv_state_watch_pid_set(pvstate_t state, pid_t val)
|
||||
{
|
||||
state->watch_pid = val;
|
||||
state->control.watch_pid = val;
|
||||
}
|
||||
|
||||
void pv_state_watch_fd_set(pvstate_t state, int val)
|
||||
{
|
||||
state->watch_fd = val;
|
||||
state->control.watch_fd = val;
|
||||
}
|
||||
|
||||
void pv_state_average_rate_window_set(pvstate_t state, unsigned int val)
|
||||
{
|
||||
if (val < 1)
|
||||
val = 1;
|
||||
state->control.average_rate_window = val;
|
||||
if (val >= 20) {
|
||||
state->history_len = val / 5 + 1;
|
||||
state->history_interval = 5;
|
||||
state->display.history_len = (size_t) (val / 5 + 1);
|
||||
state->display.history_interval = 5;
|
||||
} else {
|
||||
state->history_len = val + 1;
|
||||
state->history_interval = 1;
|
||||
state->display.history_len = (size_t) (val + 1);
|
||||
state->display.history_interval = 1;
|
||||
}
|
||||
pv_alloc_history(state);
|
||||
}
|
||||
@@ -364,10 +365,10 @@ void pv_state_inputfiles(pvstate_t state, unsigned int input_file_count, const c
|
||||
{
|
||||
unsigned int file_idx;
|
||||
|
||||
if (NULL != state->input_files) {
|
||||
for (file_idx = 0; file_idx < state->input_file_count; file_idx++) {
|
||||
if (NULL != state->files.filename) {
|
||||
for (file_idx = 0; file_idx < state->files.file_count; file_idx++) {
|
||||
/*@-unqualifiedtrans@ */
|
||||
free(state->input_files[file_idx]);
|
||||
free(state->files.filename[file_idx]);
|
||||
/*@+unqualifiedtrans@ */
|
||||
/*
|
||||
* TODO: find a way to tell splint the array
|
||||
@@ -375,29 +376,30 @@ void pv_state_inputfiles(pvstate_t state, unsigned int input_file_count, const c
|
||||
* array itself.
|
||||
*/
|
||||
}
|
||||
free(state->input_files);
|
||||
state->input_files = NULL;
|
||||
state->input_file_count = 0;
|
||||
free(state->files.filename);
|
||||
state->files.filename = NULL;
|
||||
state->files.file_count = 0;
|
||||
}
|
||||
state->input_files = calloc((size_t) (input_file_count + 1), sizeof(char *));
|
||||
if (NULL == state->input_files) {
|
||||
state->files.filename = calloc((size_t) (input_file_count + 1), sizeof(char *));
|
||||
if (NULL == state->files.filename) {
|
||||
/*@-mustfreefresh@ *//* see similar _() issue above */
|
||||
fprintf(stderr, "%s: %s: %s\n", state->program_name, _("file list allocation failed"), strerror(errno));
|
||||
fprintf(stderr, "%s: %s: %s\n", state->status.program_name, _("file list allocation failed"),
|
||||
strerror(errno));
|
||||
/*@+mustfreefresh@ */
|
||||
return;
|
||||
}
|
||||
for (file_idx = 0; file_idx < input_file_count; file_idx++) {
|
||||
/*@-nullstate@ */
|
||||
state->input_files[file_idx] = pv_strdup(input_files[file_idx]);
|
||||
if (NULL == state->input_files[file_idx]) {
|
||||
state->files.filename[file_idx] = pv_strdup(input_files[file_idx]);
|
||||
if (NULL == state->files.filename[file_idx]) {
|
||||
/*@-mustfreefresh@ *//* see similar _() issue above */
|
||||
fprintf(stderr, "%s: %s: %s\n", state->program_name,
|
||||
fprintf(stderr, "%s: %s: %s\n", state->status.program_name,
|
||||
_("file list allocation failed"), strerror(errno));
|
||||
/*@+mustfreefresh@ */
|
||||
return;
|
||||
}
|
||||
}
|
||||
state->input_file_count = input_file_count;
|
||||
state->files.file_count = input_file_count;
|
||||
}
|
||||
|
||||
/*@+nullstate@*/
|
||||
|
||||
@@ -151,4 +151,33 @@ char *pv_strdup(const char *original)
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a pointer to the last matching character in the buffer, or NULL if
|
||||
* not found.
|
||||
*/
|
||||
/*@null@ */
|
||||
/*@temp@ */
|
||||
void *pv_memrchr(const void *buffer, int match, size_t length)
|
||||
{
|
||||
#ifdef HAVE_MEMRCHR
|
||||
/*@-unrecog @ *//* splint doesn't know of memrchr() */
|
||||
return memrchr(buffer, match, length);
|
||||
/*@+unrecog @ */
|
||||
#else
|
||||
unsigned char *ptr;
|
||||
|
||||
if (length < 1)
|
||||
return NULL;
|
||||
|
||||
ptr = ((unsigned char *) buffer) + length - 1;
|
||||
while (ptr >= (unsigned char *) buffer) {
|
||||
if ((int) (ptr[0]) == match)
|
||||
return (void *) ptr;
|
||||
ptr--;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
+170
-155
@@ -129,7 +129,14 @@ static ssize_t pv__transfer_read_repeated(int fd, void *buf, size_t count)
|
||||
struct timespec cur_time, transfer_elapsed;
|
||||
long double elapsed_seconds;
|
||||
|
||||
nread = read(fd, buf, (size_t) (count > MAX_READ_AT_ONCE ? MAX_READ_AT_ONCE : count));
|
||||
nread = read(fd, buf, (size_t) (count > MAX_READ_AT_ONCE ? MAX_READ_AT_ONCE : count)); /* flawfinder: ignore */
|
||||
|
||||
/*
|
||||
* flawfinder rationale: reads stop after "count" bytes, and
|
||||
* we handle negative and zero results from read(), so it is
|
||||
* bounded to the buffer size the caller told us to use.
|
||||
*/
|
||||
|
||||
if (nread < 0)
|
||||
return nread;
|
||||
|
||||
@@ -286,21 +293,21 @@ static ssize_t pv__transfer_write_repeated(int fd, void *buf, size_t count, bool
|
||||
* returns 1.
|
||||
*
|
||||
* At most, the number of bytes read will be the number of bytes remaining
|
||||
* in the input buffer. If state->rate_limit is >0, and/or "allowed" is >0,
|
||||
* in the input buffer. If state->control.rate_limit is >0, and/or "allowed" is >0,
|
||||
* then the maximum number of bytes read will be the number remaining unused
|
||||
* in the input buffer or the value of "allowed", whichever is smaller.
|
||||
*
|
||||
* If splice() was successfully used, sets state->splice_used to true; if it
|
||||
* failed, then state->splice_failed_fd is updated to the current fd so
|
||||
* If splice() was successfully used, sets state->transfer.splice_used to true; if it
|
||||
* failed, then state->transfer.splice_failed_fd is updated to the current fd so
|
||||
* splice() won't be tried again until the next input file.
|
||||
*
|
||||
* Updates state->read_position by the number of bytes read, unless splice()
|
||||
* Updates state->transfer.read_position by the number of bytes read, unless splice()
|
||||
* was used, in which case it does not since there's nothing in the buffer
|
||||
* (and it also adds the bytes to state->written since they've been written
|
||||
* (and it also adds the bytes to state->transfer.written since they've been written
|
||||
* to the output).
|
||||
*
|
||||
* On read error, updates state->exit_status, and if allowed by
|
||||
* state->skip_errors, tries to skip past the problem.
|
||||
* On read error, updates state->status.exit_status, and if allowed by
|
||||
* state->control.skip_errors, tries to skip past the problem.
|
||||
*
|
||||
* If the end of the input file is reached or the error is unrecoverable,
|
||||
* sets *eof_in to true. If all data in the buffer has been written at this
|
||||
@@ -317,18 +324,18 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou
|
||||
#endif /* HAVE_SPLICE */
|
||||
|
||||
do_not_skip_errors = false;
|
||||
if (0 == state->skip_errors)
|
||||
if (0 == state->control.skip_errors)
|
||||
do_not_skip_errors = true;
|
||||
|
||||
bytes_can_read = state->buffer_size - state->read_position;
|
||||
bytes_can_read = state->transfer.buffer_size - state->transfer.read_position;
|
||||
nread = 0;
|
||||
|
||||
#ifdef HAVE_SPLICE
|
||||
state->splice_used = false;
|
||||
if ((!state->linemode) && (!state->no_splice)
|
||||
&& (fd != state->splice_failed_fd)
|
||||
&& (0 == state->to_write)) {
|
||||
if (state->rate_limit > 0 || allowed != 0) {
|
||||
state->transfer.splice_used = false;
|
||||
if ((!state->control.linemode) && (!state->control.no_splice)
|
||||
&& (fd != state->transfer.splice_failed_fd)
|
||||
&& (0 == state->transfer.to_write)) {
|
||||
if (state->control.rate_limit > 0 || allowed != 0) {
|
||||
bytes_to_splice = (size_t) allowed;
|
||||
} else {
|
||||
bytes_to_splice = bytes_can_read;
|
||||
@@ -341,18 +348,18 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou
|
||||
/*@+type@ */
|
||||
/*@+nullpass@ */
|
||||
|
||||
state->splice_used = true;
|
||||
state->transfer.splice_used = true;
|
||||
if ((nread < 0) && (EINVAL == errno)) {
|
||||
debug("%s %d: %s", "fd", fd, "splice failed with EINVAL - disabling");
|
||||
state->splice_failed_fd = fd;
|
||||
state->splice_used = false;
|
||||
state->transfer.splice_failed_fd = fd;
|
||||
state->transfer.splice_used = false;
|
||||
/*
|
||||
* Fall through to read() below.
|
||||
*/
|
||||
} else if (nread > 0) {
|
||||
state->written = nread;
|
||||
state->transfer.written = nread;
|
||||
#ifdef HAVE_FDATASYNC
|
||||
if (state->sync_after_write) {
|
||||
if (state->control.sync_after_write) {
|
||||
/*
|
||||
* Ignore non IO errors, such as EBADFD (bad file
|
||||
* descriptor), EINVAL (non syncable fd, such as a
|
||||
@@ -373,14 +380,18 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou
|
||||
/* nothing read yet - do nothing */
|
||||
} else {
|
||||
/* EOF might not really be EOF, it seems */
|
||||
state->splice_used = false;
|
||||
state->transfer.splice_used = false;
|
||||
}
|
||||
}
|
||||
if (!state->splice_used) {
|
||||
nread = pv__transfer_read_repeated(fd, state->transfer_buffer + state->read_position, bytes_can_read);
|
||||
if (!state->transfer.splice_used) {
|
||||
nread =
|
||||
pv__transfer_read_repeated(fd, state->transfer.transfer_buffer + state->transfer.read_position,
|
||||
bytes_can_read);
|
||||
}
|
||||
#else
|
||||
nread = pv__transfer_read_repeated(fd, state->transfer_buffer + state->read_position, bytes_can_read);
|
||||
nread =
|
||||
pv__transfer_read_repeated(fd, state->transfer.transfer_buffer + state->transfer.read_position,
|
||||
bytes_can_read);
|
||||
#endif /* HAVE_SPLICE */
|
||||
|
||||
|
||||
@@ -392,7 +403,7 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou
|
||||
* move on to the next input file.
|
||||
*/
|
||||
*eof_in = true;
|
||||
if (state->write_position >= state->read_position)
|
||||
if (state->transfer.write_position >= state->transfer.read_position)
|
||||
*eof_out = true;
|
||||
return 1;
|
||||
} else if (nread > 0) {
|
||||
@@ -401,16 +412,16 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou
|
||||
* the error counter and update our record of how much data
|
||||
* we've got in the buffer.
|
||||
*/
|
||||
state->read_errors_in_a_row = 0;
|
||||
state->transfer.read_errors_in_a_row = 0;
|
||||
#ifdef HAVE_SPLICE
|
||||
/*
|
||||
* If we used splice(), there isn't any more data in the
|
||||
* buffer than there was before.
|
||||
*/
|
||||
if (!state->splice_used)
|
||||
state->read_position += nread;
|
||||
if (!state->transfer.splice_used)
|
||||
state->transfer.read_position += nread;
|
||||
#else
|
||||
state->read_position += nread;
|
||||
state->transfer.read_position += nread;
|
||||
#endif /* HAVE_SPLICE */
|
||||
return 1;
|
||||
}
|
||||
@@ -434,8 +445,8 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou
|
||||
* exit status, regardless of whether we're skipping errors, and
|
||||
* increment the error counter.
|
||||
*/
|
||||
state->exit_status |= 16;
|
||||
state->read_errors_in_a_row++;
|
||||
state->status.exit_status |= 16;
|
||||
state->transfer.read_errors_in_a_row++;
|
||||
|
||||
/*
|
||||
* If we aren't skipping errors, show the error and pretend we
|
||||
@@ -452,7 +463,7 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou
|
||||
* TODO: investigate and fix the reason for this.
|
||||
*/
|
||||
*eof_in = true;
|
||||
if (state->write_position >= state->read_position) {
|
||||
if (state->transfer.write_position >= state->transfer.read_position) {
|
||||
*eof_out = true;
|
||||
}
|
||||
return 1;
|
||||
@@ -464,13 +475,13 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou
|
||||
|
||||
amount_skipped = -1;
|
||||
|
||||
if (!state->read_error_warning_shown) {
|
||||
if (!state->transfer.read_error_warning_shown) {
|
||||
/*@-compdef@ */
|
||||
pv_error(state, "%s: %s: %s", pv_current_file_name(state), _("warning: read errors detected"),
|
||||
strerror(errno));
|
||||
/*@+compdef@ */
|
||||
/* splint - see previous pv_current_file_name() call. */
|
||||
state->read_error_warning_shown = true;
|
||||
state->transfer.read_error_warning_shown = true;
|
||||
}
|
||||
|
||||
orig_offset = (off_t) lseek(fd, 0, SEEK_CUR);
|
||||
@@ -486,7 +497,7 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou
|
||||
/*@+compdef@ */
|
||||
/* splint - see previous pv_current_file_name() calls. */
|
||||
*eof_in = true;
|
||||
if (state->write_position >= state->read_position) {
|
||||
if (state->transfer.write_position >= state->transfer.read_position) {
|
||||
*eof_out = true;
|
||||
}
|
||||
return 1;
|
||||
@@ -497,13 +508,13 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou
|
||||
* otherwise start small and ramp up based on the number of errors
|
||||
* in a row.
|
||||
*/
|
||||
if (state->error_skip_block > 0) {
|
||||
amount_to_skip = state->error_skip_block;
|
||||
if (state->control.error_skip_block > 0) {
|
||||
amount_to_skip = state->control.error_skip_block;
|
||||
} else {
|
||||
if (state->read_errors_in_a_row < 10) {
|
||||
amount_to_skip = (off_t) (state->read_errors_in_a_row < 5 ? 1 : 2);
|
||||
} else if (state->read_errors_in_a_row < 20) {
|
||||
unsigned int shift_by = (unsigned int) (state->read_errors_in_a_row - 10);
|
||||
if (state->transfer.read_errors_in_a_row < 10) {
|
||||
amount_to_skip = (off_t) (state->transfer.read_errors_in_a_row < 5 ? 1 : 2);
|
||||
} else if (state->transfer.read_errors_in_a_row < 20) {
|
||||
unsigned int shift_by = (unsigned int) (state->transfer.read_errors_in_a_row - 10);
|
||||
amount_to_skip = (off_t) (1 << shift_by);
|
||||
} else {
|
||||
amount_to_skip = 512;
|
||||
@@ -574,9 +585,9 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou
|
||||
* of the transfer buffer, and update the buffer position.
|
||||
*/
|
||||
if (amount_skipped > 0) {
|
||||
memset(state->transfer_buffer + state->read_position, 0, (size_t) amount_skipped);
|
||||
state->read_position += amount_skipped;
|
||||
if (state->skip_errors < 2) {
|
||||
memset(state->transfer.transfer_buffer + state->transfer.read_position, 0, (size_t) amount_skipped);
|
||||
state->transfer.read_position += amount_skipped;
|
||||
if (state->control.skip_errors < 2) {
|
||||
/*@-compdef@ */
|
||||
pv_error(state, "%s: %s: %ld - %ld (%ld %s)",
|
||||
pv_current_file_name(state),
|
||||
@@ -590,7 +601,7 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou
|
||||
* Failed to skip - mark file as ended.
|
||||
*/
|
||||
*eof_in = true;
|
||||
if (state->write_position >= state->read_position) {
|
||||
if (state->transfer.write_position >= state->transfer.read_position) {
|
||||
*eof_out = true;
|
||||
}
|
||||
}
|
||||
@@ -600,47 +611,48 @@ static int pv__transfer_read(pvstate_t state, int fd, bool *eof_in, bool *eof_ou
|
||||
|
||||
|
||||
/*
|
||||
* Write state->to_write bytes of data from the transfer buffer to stdout.
|
||||
* Write state->transfer.to_write bytes of data from the transfer buffer to stdout.
|
||||
* Returns zero if there was a transient error and we need to return 0 from
|
||||
* pv_transfer, otherwise returns 1.
|
||||
*
|
||||
* Updates state->write_position by moving it on by the number of bytes
|
||||
* written; adds the number of bytes written to state->written; sets
|
||||
* Updates state->transfer.write_position by moving it on by the number of bytes
|
||||
* written; adds the number of bytes written to state->transfer.written; sets
|
||||
* *eof_out to true, on stdout EOF, or when the write position catches up
|
||||
* with the read position AND *eof_in is true (meaning we've reached the end
|
||||
* of data).
|
||||
*
|
||||
* On error, sets *eof_out to true, sets state->written to -1, and updates
|
||||
* state->exit_status.
|
||||
* On error, sets *eof_out to true, sets state->transfer.written to -1, and updates
|
||||
* state->status.exit_status.
|
||||
*
|
||||
* If state->discard_input is true, does not actually write anything.
|
||||
* If state->control.discard_input is true, does not actually write anything.
|
||||
*/
|
||||
static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long *lineswritten)
|
||||
{
|
||||
ssize_t nwritten;
|
||||
|
||||
if (NULL == state->transfer_buffer) {
|
||||
if (NULL == state->transfer.transfer_buffer) {
|
||||
pv_error(state, "%s", _("no transfer buffer allocated"));
|
||||
state->exit_status |= 64;
|
||||
state->status.exit_status |= 64;
|
||||
*eof_out = true;
|
||||
state->written = -1;
|
||||
state->transfer.written = -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
nwritten = 0;
|
||||
|
||||
if (state->discard_input) {
|
||||
nwritten = state->to_write;
|
||||
} else if (state->to_write > 0) {
|
||||
if (state->control.discard_input) {
|
||||
nwritten = state->transfer.to_write;
|
||||
} else if (state->transfer.to_write > 0) {
|
||||
if (signal(SIGALRM, SIG_IGN) == SIG_ERR) {
|
||||
pv_error(state, "%s: %s", _("failed to set alarm signal handler"), strerror(errno));
|
||||
} else {
|
||||
(void) alarm(1);
|
||||
}
|
||||
nwritten = pv__transfer_write_repeated(STDOUT_FILENO,
|
||||
state->transfer_buffer +
|
||||
state->write_position, (size_t) (state->to_write),
|
||||
state->sync_after_write);
|
||||
state->transfer.transfer_buffer +
|
||||
state->transfer.write_position,
|
||||
(size_t) (state->transfer.to_write),
|
||||
state->control.sync_after_write);
|
||||
(void) alarm(0);
|
||||
}
|
||||
|
||||
@@ -654,66 +666,69 @@ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long
|
||||
/*
|
||||
* Write returned >0 - data successfully written.
|
||||
*/
|
||||
if ((state->linemode) && (lineswritten != NULL)) {
|
||||
/*
|
||||
* Guillaume Marcais: use strchr to count \n
|
||||
*/
|
||||
char save;
|
||||
if ((state->control.linemode) && (lineswritten != NULL)) {
|
||||
char separator;
|
||||
char *ptr;
|
||||
long lines = 0;
|
||||
|
||||
save = state->transfer_buffer[state->write_position + nwritten];
|
||||
state->transfer_buffer[state->write_position + nwritten] = '\0';
|
||||
ptr = (char *) (state->transfer_buffer + state->write_position - 1);
|
||||
|
||||
if (state->null_terminated_lines) {
|
||||
for (ptr++;
|
||||
ptr -
|
||||
(char *) state->transfer_buffer -
|
||||
state->write_position < (size_t) nwritten; ptr++) {
|
||||
if (*ptr == '\0')
|
||||
++lines;
|
||||
}
|
||||
if (state->control.null_terminated_lines) {
|
||||
separator = '\0';
|
||||
} else {
|
||||
while ((ptr = strchr((char *) (ptr + 1), '\n')))
|
||||
separator = '\n';
|
||||
}
|
||||
|
||||
ptr = (char *) (state->transfer.transfer_buffer + state->transfer.write_position - 1);
|
||||
for (ptr++;
|
||||
ptr - (char *) state->transfer.transfer_buffer - state->transfer.write_position <
|
||||
(size_t) nwritten; ptr++) {
|
||||
if (*ptr == separator)
|
||||
++lines;
|
||||
}
|
||||
|
||||
*lineswritten += lines;
|
||||
state->transfer_buffer[state->write_position + nwritten] = save;
|
||||
}
|
||||
|
||||
state->write_position += nwritten;
|
||||
state->written += nwritten;
|
||||
state->transfer.write_position += nwritten;
|
||||
state->transfer.written += nwritten;
|
||||
|
||||
/*
|
||||
* If we're monitoring the output, update our copy of the
|
||||
* last few bytes we've written.
|
||||
*/
|
||||
if (((state->components_used & PV_DISPLAY_OUTPUTBUF) != 0)
|
||||
&& (nwritten > 0)) {
|
||||
if (state->display.component[PV_COMPONENT_OUTPUTBUF].required && (nwritten > 0)) {
|
||||
size_t new_portion_length, old_portion_length;
|
||||
|
||||
new_portion_length = (size_t) nwritten;
|
||||
if (new_portion_length > state->lastoutput_length)
|
||||
new_portion_length = state->lastoutput_length;
|
||||
if (new_portion_length > state->display.lastoutput_length)
|
||||
new_portion_length = state->display.lastoutput_length;
|
||||
|
||||
old_portion_length = state->lastoutput_length - new_portion_length;
|
||||
old_portion_length = state->display.lastoutput_length - new_portion_length;
|
||||
|
||||
/*
|
||||
* Make room for the new portion.
|
||||
*/
|
||||
if (old_portion_length > 0) {
|
||||
memmove(state->lastoutput_buffer,
|
||||
state->lastoutput_buffer + new_portion_length, old_portion_length);
|
||||
memmove(state->display.lastoutput_buffer,
|
||||
state->display.lastoutput_buffer + new_portion_length, old_portion_length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the new data in.
|
||||
*/
|
||||
memcpy(state->lastoutput_buffer +
|
||||
memcpy(state->display.lastoutput_buffer + /* flawfinder: ignore */
|
||||
old_portion_length,
|
||||
state->transfer_buffer + state->write_position - new_portion_length, new_portion_length);
|
||||
state->transfer.transfer_buffer + state->transfer.write_position - new_portion_length,
|
||||
new_portion_length);
|
||||
/*
|
||||
* flawfinder rationale: calculations above ensure
|
||||
* that old_portion_length + new_portion_length is
|
||||
* always <= lastoutput_length, and
|
||||
* lastoutput_length is guaranteed by
|
||||
* pv__format_init() to be no more than
|
||||
* PV_SIZEOF_LASTOUTPUT_BUFFER, which is the size of
|
||||
* lastoutput_buffer, so the memcpy() will always
|
||||
* fit into the buffer.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -722,9 +737,9 @@ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long
|
||||
* EOF, set eof_out as well to indicate that we've written
|
||||
* everything for this input file.
|
||||
*/
|
||||
if (state->write_position >= state->read_position) {
|
||||
state->write_position = 0;
|
||||
state->read_position = 0;
|
||||
if (state->transfer.write_position >= state->transfer.read_position) {
|
||||
state->transfer.write_position = 0;
|
||||
state->transfer.read_position = 0;
|
||||
if (*eof_in)
|
||||
*eof_out = true;
|
||||
}
|
||||
@@ -757,9 +772,9 @@ static int pv__transfer_write(pvstate_t state, bool *eof_in, bool *eof_out, long
|
||||
}
|
||||
|
||||
pv_error(state, "%s: %s", _("write failed"), strerror(errno));
|
||||
state->exit_status |= 16;
|
||||
state->status.exit_status |= 16;
|
||||
*eof_out = true;
|
||||
state->written = -1;
|
||||
state->transfer.written = -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -832,13 +847,13 @@ static char *pv__allocate_aligned_buffer(int fd, size_t target_size)
|
||||
|
||||
/*
|
||||
* Transfer some data from "fd" to standard output, timing out after 9/100
|
||||
* of a second. If state->rate_limit is >0, and/or "allowed" is >0, only up
|
||||
* of a second. If state->control.rate_limit is >0, and/or "allowed" is >0, only up
|
||||
* to "allowed" bytes can be written. The variables that "eof_in" and
|
||||
* "eof_out" point to are used to flag that we've finished reading and
|
||||
* writing respectively.
|
||||
*
|
||||
* Returns the number of bytes written, or negative on error (in which case
|
||||
* state->exit_status is updated). In line mode, the number of lines written
|
||||
* state->status.exit_status is updated). In line mode, the number of lines written
|
||||
* will be put into *lineswritten.
|
||||
*/
|
||||
ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t allowed, long *lineswritten)
|
||||
@@ -855,9 +870,9 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t
|
||||
* Set or clear O_DIRECT on the input and output file descriptors,
|
||||
* if the setting has changed.
|
||||
*/
|
||||
if (state->direct_io_changed) {
|
||||
if (state->control.direct_io_changed) {
|
||||
if (!(*eof_in)) {
|
||||
if (0 != fcntl(fd, F_SETFL, (state->direct_io ? O_DIRECT : 0) | fcntl(fd, F_GETFL))) {
|
||||
if (0 != fcntl(fd, F_SETFL, (state->control.direct_io ? O_DIRECT : 0) | fcntl(fd, F_GETFL))) {
|
||||
/*@-compdef@ */
|
||||
debug("%s: %s: %s", pv_current_file_name(state), "fcntl", strerror(errno));
|
||||
/*@+compdef@ */
|
||||
@@ -866,11 +881,11 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t
|
||||
}
|
||||
if (!(*eof_out)) {
|
||||
if (0 != fcntl(STDOUT_FILENO, F_SETFL,
|
||||
(state->direct_io ? O_DIRECT : 0) | fcntl(STDOUT_FILENO, F_GETFL))) {
|
||||
(state->control.direct_io ? O_DIRECT : 0) | fcntl(STDOUT_FILENO, F_GETFL))) {
|
||||
debug("%s: %s: %s", "(stdout)", "fcntl", strerror(errno));
|
||||
}
|
||||
}
|
||||
state->direct_io_changed = false;
|
||||
state->control.direct_io_changed = false;
|
||||
}
|
||||
#endif /* O_DIRECT */
|
||||
|
||||
@@ -878,24 +893,25 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t
|
||||
* Reinitialise the error skipping variables if the file descriptor
|
||||
* has changed since the last time we were called.
|
||||
*/
|
||||
if (fd != state->last_read_skip_fd) {
|
||||
state->last_read_skip_fd = fd;
|
||||
state->read_errors_in_a_row = 0;
|
||||
state->read_error_warning_shown = false;
|
||||
if (fd != state->transfer.last_read_skip_fd) {
|
||||
state->transfer.last_read_skip_fd = fd;
|
||||
state->transfer.read_errors_in_a_row = 0;
|
||||
state->transfer.read_error_warning_shown = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new buffer, aligned appropriately for the input file
|
||||
* (important if using O_DIRECT).
|
||||
*/
|
||||
if (NULL == state->transfer_buffer) {
|
||||
state->transfer_buffer = pv__allocate_aligned_buffer(fd, state->target_buffer_size + 32);
|
||||
if (NULL == state->transfer_buffer) {
|
||||
if (NULL == state->transfer.transfer_buffer) {
|
||||
state->transfer.transfer_buffer =
|
||||
pv__allocate_aligned_buffer(fd, state->control.target_buffer_size + 32);
|
||||
if (NULL == state->transfer.transfer_buffer) {
|
||||
pv_error(state, "%s: %s", _("buffer allocation failed"), strerror(errno));
|
||||
state->exit_status |= 64;
|
||||
state->status.exit_status |= 64;
|
||||
return -1;
|
||||
}
|
||||
state->buffer_size = state->target_buffer_size;
|
||||
state->transfer.buffer_size = state->control.target_buffer_size;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -905,31 +921,37 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t
|
||||
* memory) because the buffer may need to be aligned for O_DIRECT,
|
||||
* and we can't realloc() an aligned buffer.
|
||||
*/
|
||||
if (state->buffer_size < state->target_buffer_size) {
|
||||
if (state->transfer.buffer_size < state->control.target_buffer_size) {
|
||||
char *newptr;
|
||||
newptr = pv__allocate_aligned_buffer(fd, state->target_buffer_size + 32);
|
||||
newptr = pv__allocate_aligned_buffer(fd, state->control.target_buffer_size + 32);
|
||||
if (NULL == newptr) {
|
||||
/*
|
||||
* Reset target if realloc failed so we don't keep
|
||||
* trying to realloc over and over.
|
||||
*/
|
||||
debug("realloc: %s", strerror(errno));
|
||||
state->target_buffer_size = state->buffer_size;
|
||||
state->control.target_buffer_size = state->transfer.buffer_size;
|
||||
} else {
|
||||
debug("%s: %ld", "buffer resized", state->buffer_size);
|
||||
debug("%s: %ld", "buffer resized", state->transfer.buffer_size);
|
||||
/*
|
||||
* Copy the old buffer contents into the new buffer,
|
||||
* and free the old one.
|
||||
*/
|
||||
if (state->buffer_size > 0)
|
||||
memcpy(newptr, state->transfer_buffer, state->buffer_size);
|
||||
free(state->transfer_buffer);
|
||||
state->transfer_buffer = newptr;
|
||||
state->buffer_size = state->target_buffer_size;
|
||||
if (state->transfer.buffer_size > 0) {
|
||||
memcpy(newptr, state->transfer.transfer_buffer, state->transfer.buffer_size); /* flawfinder: ignore */
|
||||
}
|
||||
/*
|
||||
* flawfinder rationale: number of bytes copied is
|
||||
* definitely always smaller than the new buffer
|
||||
* size.
|
||||
*/
|
||||
free(state->transfer.transfer_buffer);
|
||||
state->transfer.transfer_buffer = newptr;
|
||||
state->transfer.buffer_size = state->control.target_buffer_size;
|
||||
}
|
||||
}
|
||||
|
||||
if ((state->linemode) && (lineswritten != NULL))
|
||||
if ((state->control.linemode) && (lineswritten != NULL))
|
||||
*lineswritten = 0;
|
||||
|
||||
if ((*eof_in) && (*eof_out))
|
||||
@@ -942,7 +964,7 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t
|
||||
* If the input file is not at EOF and there's room in the buffer,
|
||||
* look for incoming data from it.
|
||||
*/
|
||||
if ((!(*eof_in)) && (state->read_position < state->buffer_size)) {
|
||||
if ((!(*eof_in)) && (state->transfer.read_position < state->transfer.buffer_size)) {
|
||||
check_read_fd = fd;
|
||||
}
|
||||
|
||||
@@ -952,10 +974,10 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t
|
||||
* is >0, then this puts an upper limit on how much we're allowed to
|
||||
* write.
|
||||
*/
|
||||
state->to_write = (ssize_t) (state->read_position - state->write_position);
|
||||
if ((state->rate_limit > 0) || (allowed > 0)) {
|
||||
if ((off_t) (state->to_write) > allowed) {
|
||||
state->to_write = (ssize_t) allowed;
|
||||
state->transfer.to_write = (ssize_t) (state->transfer.read_position - state->transfer.write_position);
|
||||
if ((state->control.rate_limit > 0) || (allowed > 0)) {
|
||||
if ((off_t) (state->transfer.to_write) > allowed) {
|
||||
state->transfer.to_write = (ssize_t) allowed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -963,7 +985,7 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t
|
||||
* If we don't think we've finished writing and there's anything
|
||||
* we're allowed to write, look for the stdout becoming writable.
|
||||
*/
|
||||
if ((!(*eof_out)) && (state->to_write > 0)) {
|
||||
if ((!(*eof_out)) && (state->transfer.to_write > 0)) {
|
||||
check_write_fd = STDOUT_FILENO;
|
||||
}
|
||||
|
||||
@@ -987,18 +1009,18 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t
|
||||
/*@+compdef@ */
|
||||
/* splint - see previous pv_current_file_name() calls. */
|
||||
|
||||
state->exit_status |= 16;
|
||||
state->status.exit_status |= 16;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
state->written = 0;
|
||||
state->transfer.written = 0;
|
||||
|
||||
/*
|
||||
* If there is data to read, try to read some in. Return early if
|
||||
* there was a transient read error.
|
||||
*
|
||||
* NB this can update state->written because of splice().
|
||||
* NB this can update state->transfer.written because of splice().
|
||||
*/
|
||||
if (ready_to_read) {
|
||||
if (pv__transfer_read(state, fd, eof_in, eof_out, allowed) == 0)
|
||||
@@ -1009,23 +1031,15 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t
|
||||
* In line mode, only write up to and including the last newline,
|
||||
* so that we're writing output line-by-line.
|
||||
*/
|
||||
if ((state->to_write > 0) && (state->linemode) && !(state->null_terminated_lines)) {
|
||||
/*
|
||||
* Guillaume Marcais: use strrchr to find last \n
|
||||
*/
|
||||
char save;
|
||||
if ((state->transfer.to_write > 0) && (state->control.linemode) && !(state->control.null_terminated_lines)) {
|
||||
char *start;
|
||||
char *end;
|
||||
|
||||
save = state->transfer_buffer[state->write_position + state->to_write];
|
||||
state->transfer_buffer[state->write_position + state->to_write] = '\0';
|
||||
start = (char *) (state->transfer.transfer_buffer + state->transfer.write_position);
|
||||
end = pv_memrchr(start, (int) '\n', (size_t) (state->transfer.to_write));
|
||||
|
||||
start = (char *) (state->transfer_buffer + state->write_position);
|
||||
end = strrchr(start, '\n');
|
||||
state->transfer_buffer[state->write_position + state->to_write] = save;
|
||||
|
||||
if (end != NULL) {
|
||||
state->to_write = (end - start) + 1;
|
||||
if (NULL != end) {
|
||||
state->transfer.to_write = (ssize_t) ((end - start) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1036,10 +1050,10 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t
|
||||
*/
|
||||
if (ready_to_write
|
||||
#ifdef HAVE_SPLICE
|
||||
&& (!state->splice_used)
|
||||
&& (!state->transfer.splice_used)
|
||||
#endif /* HAVE_SPLICE */
|
||||
&& (state->read_position > state->write_position)
|
||||
&& (state->to_write > 0)
|
||||
&& (state->transfer.read_position > state->transfer.write_position)
|
||||
&& (state->transfer.to_write > 0)
|
||||
&& (NULL != lineswritten)) {
|
||||
if (pv__transfer_write(state, eof_in, eof_out, lineswritten) == 0)
|
||||
return 0;
|
||||
@@ -1049,21 +1063,22 @@ ssize_t pv_transfer(pvstate_t state, int fd, bool *eof_in, bool *eof_out, off_t
|
||||
* Rotate the written bytes out of the buffer so that it can be
|
||||
* filled up completely by the next read.
|
||||
*/
|
||||
if (state->write_position > 0) {
|
||||
if (state->write_position < state->read_position) {
|
||||
memmove(state->transfer_buffer,
|
||||
state->transfer_buffer +
|
||||
state->write_position, state->read_position - state->write_position);
|
||||
state->read_position -= state->write_position;
|
||||
state->write_position = 0;
|
||||
if (state->transfer.write_position > 0) {
|
||||
if (state->transfer.write_position < state->transfer.read_position) {
|
||||
memmove(state->transfer.transfer_buffer,
|
||||
state->transfer.transfer_buffer +
|
||||
state->transfer.write_position,
|
||||
state->transfer.read_position - state->transfer.write_position);
|
||||
state->transfer.read_position -= state->transfer.write_position;
|
||||
state->transfer.write_position = 0;
|
||||
} else {
|
||||
state->write_position = 0;
|
||||
state->read_position = 0;
|
||||
state->transfer.write_position = 0;
|
||||
state->transfer.read_position = 0;
|
||||
}
|
||||
}
|
||||
#endif /* MAXIMISE_BUFFER_FILL */
|
||||
|
||||
return state->written;
|
||||
return state->transfer.written;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
+222
-85
@@ -31,7 +31,16 @@
|
||||
#include <sys/proc_info.h>
|
||||
#endif
|
||||
|
||||
int filesize(pvwatchfd_t info)
|
||||
/*@-type@*/
|
||||
/* splint has trouble with off_t and mode_t. */
|
||||
|
||||
/*
|
||||
* Set info->size to the size of the file info->file_fdpath points to,
|
||||
* assuming that info->sb_fd has been populated by stat(), or to 0 if the
|
||||
* file size could not be determined or the file was opened in write mode;
|
||||
* returns false if the file was not a block device or regular file.
|
||||
*/
|
||||
static bool filesize(pvwatchfd_t info)
|
||||
{
|
||||
if (S_ISBLK(info->sb_fd.st_mode)) {
|
||||
int fd;
|
||||
@@ -40,10 +49,25 @@ int filesize(pvwatchfd_t info)
|
||||
* Get the size of block devices by opening
|
||||
* them and seeking to the end.
|
||||
*/
|
||||
fd = open(info->file_fdpath, O_RDONLY);
|
||||
fd = open(info->file_fdpath, O_RDONLY); /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder: redirection check below; risk is minimal as
|
||||
* we are not actually reading any data here.
|
||||
*/
|
||||
if (fd >= 0) {
|
||||
info->size = lseek(fd, 0, SEEK_END);
|
||||
close(fd);
|
||||
/*
|
||||
* TOCTOU mitigation: check it's still a block
|
||||
* device before trying to seek to the end.
|
||||
* Otherwise treat it as unreadable and set the size
|
||||
* to 0.
|
||||
*/
|
||||
struct stat check_fd_sb;
|
||||
memset(&check_fd_sb, 0, sizeof(check_fd_sb));
|
||||
info->size = 0;
|
||||
if (0 == fstat(fd, &check_fd_sb) && S_ISBLK(check_fd_sb.st_mode)) {
|
||||
info->size = lseek(fd, 0, SEEK_END);
|
||||
}
|
||||
(void) close(fd);
|
||||
} else {
|
||||
info->size = 0;
|
||||
}
|
||||
@@ -52,12 +76,14 @@ int filesize(pvwatchfd_t info)
|
||||
info->size = info->sb_fd.st_size;
|
||||
}
|
||||
} else {
|
||||
return 4;
|
||||
return false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*@+type@*/
|
||||
|
||||
#ifdef __APPLE__
|
||||
int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
{
|
||||
@@ -96,7 +122,7 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (filesize(info) != 0) {
|
||||
if (!filesize(info)) {
|
||||
if (!automatic)
|
||||
pv_error(state, "%s %u: %s %d: %s: %s",
|
||||
_("pid"),
|
||||
@@ -144,7 +170,15 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
(void) pv_snprintf(info->file_fd, PV_SIZEOF_FILE_FD, "/proc/%u/fd/%d", info->watch_pid, info->watch_fd);
|
||||
|
||||
memset(info->file_fdpath, 0, PV_SIZEOF_FILE_FDPATH);
|
||||
if (readlink(info->file_fd, info->file_fdpath, PV_SIZEOF_FILE_FDPATH - 1) < 0) {
|
||||
if (readlink(info->file_fd, info->file_fdpath, PV_SIZEOF_FILE_FDPATH - 1) < 0) { /* flawfinder: ignore */
|
||||
/*
|
||||
* flawfinder: memset() has put \0 at the end already, and
|
||||
* we tell readlink() to use 1 byte less than the buffer
|
||||
* length, so \0 termination is assured. There is no
|
||||
* mitigation for the risk of the link changing while we
|
||||
* read it, but we are only reading from the destination,
|
||||
* and then only if it's a block device - see filesize().
|
||||
*/
|
||||
if (!automatic)
|
||||
pv_error(state, "%s %u: %s %d: %s",
|
||||
_("pid"), info->watch_pid, _("fd"), info->watch_fd, strerror(errno));
|
||||
@@ -162,14 +196,13 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
|
||||
info->size = 0;
|
||||
|
||||
int ret = filesize(info);
|
||||
if (ret != 0) {
|
||||
if (!filesize(info)) {
|
||||
if (!automatic)
|
||||
pv_error(state, "%s %u: %s %d: %s: %s",
|
||||
_("pid"),
|
||||
info->watch_pid,
|
||||
_("fd"), info->watch_fd, info->file_fdpath, _("not a regular file or block device"));
|
||||
return ret;
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -177,32 +210,35 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
int pv_watchfd_changed(pvwatchfd_t info)
|
||||
bool pv_watchfd_changed(pvwatchfd_t info)
|
||||
{
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* Return nonzero if the given file descriptor has changed in some way since
|
||||
* we started looking at it (i.e. changed destination or permissions).
|
||||
* Return true if the given file descriptor has changed in some way since
|
||||
* we started looking at it (i.e. changed destination or permissions).
|
||||
*/
|
||||
int pv_watchfd_changed(pvwatchfd_t info)
|
||||
bool pv_watchfd_changed(pvwatchfd_t info)
|
||||
{
|
||||
struct stat sb_fd, sb_fd_link;
|
||||
|
||||
memset(&sb_fd, 0, sizeof(sb_fd));
|
||||
memset(&sb_fd_link, 0, sizeof(sb_fd_link));
|
||||
|
||||
if ((0 == stat(info->file_fd, &sb_fd))
|
||||
&& (0 == lstat(info->file_fd, &sb_fd_link))) {
|
||||
if ((sb_fd.st_dev != info->sb_fd.st_dev)
|
||||
|| (sb_fd.st_ino != info->sb_fd.st_ino)
|
||||
|| (sb_fd_link.st_mode != info->sb_fd_link.st_mode)
|
||||
) {
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -214,7 +250,6 @@ int pv_watchfd_changed(pvwatchfd_t info)
|
||||
off_t pv_watchfd_position(pvwatchfd_t info)
|
||||
{
|
||||
off_t position;
|
||||
unsigned long long pos_long;
|
||||
#ifdef __APPLE__
|
||||
struct vnode_fdinfowithpath vnodeInfo = { };
|
||||
int32_t proc_fd = (int32_t) info->watch_fd;
|
||||
@@ -228,19 +263,22 @@ off_t pv_watchfd_position(pvwatchfd_t info)
|
||||
|
||||
position = (off_t) vnodeInfo.pfi.fi_offset;
|
||||
#else
|
||||
long long pos_long;
|
||||
FILE *fptr;
|
||||
|
||||
if (pv_watchfd_changed(info))
|
||||
return -1;
|
||||
|
||||
fptr = fopen(info->file_fdinfo, "r");
|
||||
fptr = fopen(info->file_fdinfo, "r"); /* flawfinder: ignore */
|
||||
/* flawfinder: trusted location (/proc). */
|
||||
if (NULL == fptr)
|
||||
return -1;
|
||||
pos_long = -1;
|
||||
position = -1;
|
||||
if (1 == fscanf(fptr, "pos: %llu", &pos_long))
|
||||
if (1 == fscanf(fptr, "pos: %lld", &pos_long)) {
|
||||
position = (off_t) pos_long;
|
||||
fclose(fptr);
|
||||
}
|
||||
(void) fclose(fptr);
|
||||
#endif
|
||||
|
||||
return position;
|
||||
@@ -270,6 +308,54 @@ static int pidfds(pvstate_t state, unsigned int pid, struct proc_fdinfo **fds, i
|
||||
}
|
||||
#endif
|
||||
|
||||
/*@-compdestroy @ */
|
||||
/*@-usereleased @ */
|
||||
/*@-compdef @ */
|
||||
|
||||
/*
|
||||
* splint: extending or creating entries and then zeroing them makes splint
|
||||
* believe that data previously there may refer to pointers that are now
|
||||
* lost - but these are newly added array entries so there is no loss.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extend the info array by one, returning false on error.
|
||||
*/
|
||||
static bool extend_info_array(int *array_length_ptr, pvwatchfd_t * info_array_ptr)
|
||||
{
|
||||
int array_length = 0;
|
||||
struct pvwatchfd_s *info_array = NULL;
|
||||
struct pvwatchfd_s *new_info_array;
|
||||
|
||||
array_length = *array_length_ptr;
|
||||
info_array = *info_array_ptr;
|
||||
|
||||
array_length++;
|
||||
|
||||
if (NULL == info_array) {
|
||||
new_info_array = malloc(array_length * sizeof(*info_array));
|
||||
if (NULL != new_info_array)
|
||||
memset(new_info_array, 0, array_length * sizeof(*info_array));
|
||||
} else {
|
||||
new_info_array = realloc(info_array, array_length * sizeof(*info_array));
|
||||
if (NULL != new_info_array)
|
||||
memset(&(new_info_array[array_length - 1]), 0, sizeof(*info_array));
|
||||
}
|
||||
|
||||
if (NULL == new_info_array) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*info_array_ptr = new_info_array;
|
||||
*array_length_ptr = array_length;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*@+compdestroy @ */
|
||||
/*@+usereleased @ */
|
||||
/*@+compdef @ */
|
||||
|
||||
|
||||
/*
|
||||
* Scan the given process and update the arrays with any new file
|
||||
* descriptors.
|
||||
@@ -277,14 +363,11 @@ static int pidfds(pvstate_t state, unsigned int pid, struct proc_fdinfo **fds, i
|
||||
* Returns 0 on success, 1 if the process no longer exists or could not be
|
||||
* read, or 2 for a memory allocation error.
|
||||
*/
|
||||
int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
unsigned int watch_pid, int *array_length_ptr,
|
||||
pvwatchfd_t * info_array_ptr, pvstate_t * state_array_ptr, int *fd_to_idx)
|
||||
int pv_watchpid_scanfds(pvstate_t state,
|
||||
pid_t watch_pid, int *array_length_ptr, pvwatchfd_t * info_array_ptr, int *fd_to_idx)
|
||||
{
|
||||
char fd_dir[512] = { 0, };
|
||||
int array_length = 0;
|
||||
struct pvwatchfd_s *info_array = NULL;
|
||||
struct pvstate_s *state_array = NULL;
|
||||
|
||||
#ifdef __APPLE__
|
||||
struct proc_fdinfo *fd_infos = NULL;
|
||||
@@ -295,9 +378,11 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
char fd_dir[512]; /* flawfinder: ignore - zeroed, bounded with pv_snprintf(). */
|
||||
DIR *dptr;
|
||||
struct dirent *d;
|
||||
|
||||
memset(fd_dir, 0, sizeof(fd_dir));
|
||||
(void) pv_snprintf(fd_dir, sizeof(fd_dir), "/proc/%u/fd", watch_pid);
|
||||
|
||||
dptr = opendir(fd_dir);
|
||||
@@ -307,7 +392,6 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
|
||||
array_length = *array_length_ptr;
|
||||
info_array = *info_array_ptr;
|
||||
state_array = *state_array_ptr;
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (fd_infos_count < 1) {
|
||||
@@ -320,6 +404,7 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
#endif
|
||||
int fd, check_idx, use_idx, rc;
|
||||
off_t position_now;
|
||||
const char *use_format_string;
|
||||
|
||||
fd = -1;
|
||||
#ifdef __APPLE__
|
||||
@@ -350,42 +435,14 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
}
|
||||
|
||||
/*
|
||||
* If there's no empty slot, extend the arrays.
|
||||
* If there's no empty slot, extend the array.
|
||||
*/
|
||||
if (use_idx < 0) {
|
||||
struct pvwatchfd_s *new_info_array;
|
||||
struct pvstate_s *new_state_array;
|
||||
|
||||
array_length++;
|
||||
if (!extend_info_array(array_length_ptr, info_array_ptr))
|
||||
return 2;
|
||||
array_length = *array_length_ptr;
|
||||
info_array = *info_array_ptr;
|
||||
use_idx = array_length - 1;
|
||||
|
||||
if (NULL == info_array) {
|
||||
new_info_array = malloc(array_length * sizeof(*info_array));
|
||||
} else {
|
||||
new_info_array = realloc(info_array, array_length * sizeof(*info_array));
|
||||
}
|
||||
if (NULL == new_info_array)
|
||||
return 2;
|
||||
info_array = new_info_array;
|
||||
*info_array_ptr = info_array;
|
||||
info_array[use_idx].watch_pid = 0;
|
||||
|
||||
if (NULL == state_array) {
|
||||
new_state_array = malloc(array_length * sizeof(*state_array));
|
||||
} else {
|
||||
new_state_array = realloc(state_array, array_length * sizeof(*state_array));
|
||||
}
|
||||
if (NULL == new_state_array)
|
||||
return 2;
|
||||
state_array = new_state_array;
|
||||
*state_array_ptr = state_array;
|
||||
|
||||
*array_length_ptr = array_length;
|
||||
|
||||
for (check_idx = 0; check_idx < array_length; check_idx++) {
|
||||
state_array[check_idx].name = info_array[check_idx].display_name;
|
||||
state_array[check_idx].reparse_display = 1;
|
||||
}
|
||||
}
|
||||
|
||||
debug("%s: %d => index %d", "found new fd", fd, use_idx);
|
||||
@@ -393,24 +450,77 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
/*
|
||||
* Initialise the details of this new entry.
|
||||
*/
|
||||
memcpy(&(state_array[use_idx]), pristine, sizeof(*pristine));
|
||||
memset(&(info_array[use_idx]), 0, sizeof(info_array[use_idx]));
|
||||
|
||||
info_array[use_idx].watch_pid = watch_pid;
|
||||
info_array[use_idx].watch_fd = fd;
|
||||
|
||||
/* Allocate new display state. */
|
||||
/*@-mustfreeonly@ *//* splint - this is not a leak, this is a new entry. */
|
||||
info_array[use_idx].state = pv_state_alloc(state->status.program_name);
|
||||
/*@+mustfreeonly@ */
|
||||
if (NULL == info_array[use_idx].state)
|
||||
return 2;
|
||||
|
||||
/* Copy the main status.cwd value to the new state. */
|
||||
memcpy(&(info_array[use_idx].state->status.cwd), &(state->status.cwd), sizeof(state->status.cwd)); /* flawfinder: ignore */
|
||||
/* flawfinder: bounded to destination object size. */
|
||||
|
||||
/*
|
||||
* Copy over all the control values, blanking out the
|
||||
* dynamically allocated strings, and setting the default
|
||||
* format (fixed buffer) to the required format string
|
||||
* instead of allocating a new dynamic format string for the
|
||||
* copy (so there's less dynamic allocation going on).
|
||||
*/
|
||||
memcpy(&(info_array[use_idx].state->control), &(state->control), sizeof(state->control)); /* flawfinder: ignore */
|
||||
/* flawfinder: bounded to destination object size. */
|
||||
/*@-mustfreeonly@ *//* splint - this is not a leak, this is a new entry. */
|
||||
info_array[use_idx].state->control.name = NULL;
|
||||
info_array[use_idx].state->control.format_string = NULL;
|
||||
/*@+mustfreeonly@ */
|
||||
info_array[use_idx].state->control.default_format[0] = '\0';
|
||||
use_format_string =
|
||||
NULL != state->control.format_string ? state->control.format_string : state->control.default_format;
|
||||
if (NULL != use_format_string)
|
||||
(void) pv_snprintf(info_array[use_idx].state->control.default_format, PV_SIZEOF_DEFAULT_FORMAT,
|
||||
"%.510s", use_format_string);
|
||||
|
||||
/*
|
||||
* Copy over all the display values, blanking out the
|
||||
* dynamically allocated parts as above; then set the
|
||||
* average rate window so that a new history buffer is
|
||||
* allocated for this state.
|
||||
*/
|
||||
memcpy(&(info_array[use_idx].state->display), &(state->display), sizeof(state->display)); /* flawfinder: ignore */
|
||||
/* flawfinder: bounded to destination object size. */
|
||||
/*@-mustfreeonly@ *//* splint - this is not a leak, this is a new entry. */
|
||||
info_array[use_idx].state->display.display_buffer = NULL;
|
||||
info_array[use_idx].state->display.display_buffer_size = 0;
|
||||
info_array[use_idx].state->display.history = NULL;
|
||||
info_array[use_idx].state->display.history_len = 0;
|
||||
/*@+mustfreeonly@ */
|
||||
pv_state_average_rate_window_set(info_array[use_idx].state, state->control.average_rate_window);
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (fd_infos[i].proc_fdtype != PROX_FDTYPE_VNODE) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* Retrieve the details of this file descriptor. */
|
||||
rc = pv_watchfd_info(state, &(info_array[use_idx]), true);
|
||||
|
||||
/*
|
||||
* Lookup failed - mark this slot as being free for re-use.
|
||||
*/
|
||||
if ((rc != 0) && (rc != 4)) {
|
||||
info_array[use_idx].watch_pid = 0;
|
||||
debug("%s %d: %s: %d", "fd", fd, "lookup failed - marking slot for re-use", use_idx);
|
||||
info_array[use_idx].watch_pid = 0;
|
||||
if (NULL != info_array[use_idx].state)
|
||||
pv_state_free(info_array[use_idx].state);
|
||||
/*@-mustfreeonly@ *//* not a leak - we've just free()d it. */
|
||||
info_array[use_idx].state = NULL;
|
||||
/*@+mustfreeonly@ */
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -425,31 +535,56 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
info_array[use_idx].watch_fd = -1;
|
||||
}
|
||||
|
||||
state_array[use_idx].size = info_array[use_idx].size;
|
||||
if (state_array[use_idx].size < 1) {
|
||||
char *fmt;
|
||||
while (NULL != (fmt = strstr(state_array[use_idx].default_format, "%e"))) {
|
||||
debug("%s", "zero size - removing ETA");
|
||||
/* strlen-1 here to include trailing NUL */
|
||||
memmove(fmt, fmt + 2, strlen(fmt) - 1);
|
||||
state_array[use_idx].reparse_display = 1;
|
||||
}
|
||||
/* NULL check on the state - skip if not usable. */
|
||||
if (NULL == info_array[use_idx].state) {
|
||||
debug("%s %d: %s", "fd", fd, "state is NULL - marking as not displayable");
|
||||
info_array[use_idx].watch_fd = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
state_array[use_idx].name = info_array[use_idx].display_name;
|
||||
/*
|
||||
* Set the displayed size appropriately; if the size is 0,
|
||||
* or not known, remove %e and %I from the state's default
|
||||
* format string so that neither estimated time remaining
|
||||
* nor estimated time of completion are displayed.
|
||||
*/
|
||||
info_array[use_idx].state->control.size = info_array[use_idx].size;
|
||||
if (info_array[use_idx].state->control.size < 1) {
|
||||
char *fmt;
|
||||
while (NULL != (fmt = strstr(info_array[use_idx].state->control.default_format, "%e"))) {
|
||||
debug("%s", "zero size - removing estimated time remaining");
|
||||
/* strlen-1 here to include trailing \0 */
|
||||
memmove(fmt, fmt + 2, strlen(fmt) - 1); /* flawfinder: ignore */
|
||||
info_array[use_idx].state->flag.reparse_display = 1;
|
||||
}
|
||||
while (NULL != (fmt = strstr(info_array[use_idx].state->control.default_format, "%I"))) {
|
||||
debug("%s", "zero size - removing estimated completion time");
|
||||
/* strlen-1 here to include trailing \0 */
|
||||
memmove(fmt, fmt + 2, strlen(fmt) - 1); /* flawfinder: ignore */
|
||||
info_array[use_idx].state->flag.reparse_display = 1;
|
||||
}
|
||||
/* flawfinder: default_format is always \0-terminated. */
|
||||
}
|
||||
|
||||
/* Set the info display_name appropriately. */
|
||||
pv_watchpid_setname(state, &(info_array[use_idx]));
|
||||
|
||||
state_array[use_idx].reparse_display = 1;
|
||||
/* Carry the display_name through to the display state, and reparse. */
|
||||
pv_state_name_set(info_array[use_idx].state, info_array[use_idx].display_name);
|
||||
info_array[use_idx].state->flag.reparse_display = 1;
|
||||
|
||||
pv_elapsedtime_read(&(info_array[use_idx].start_time));
|
||||
|
||||
state_array[use_idx].initial_offset = 0;
|
||||
/*
|
||||
* Set the starting position (and initial offset, for the
|
||||
* display), if known, so that ETA and so on are calculated
|
||||
* correctly.
|
||||
*/
|
||||
info_array[use_idx].state->display.initial_offset = 0;
|
||||
info_array[use_idx].position = 0;
|
||||
|
||||
position_now = pv_watchfd_position(&(info_array[use_idx]));
|
||||
if (position_now >= 0) {
|
||||
state_array[use_idx].initial_offset = position_now;
|
||||
info_array[use_idx].state->display.initial_offset = position_now;
|
||||
info_array[use_idx].position = position_now;
|
||||
}
|
||||
}
|
||||
@@ -458,7 +593,7 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
#ifdef __APPLE__
|
||||
free(fd_infos);
|
||||
#else
|
||||
closedir(dptr);
|
||||
(void) closedir(dptr);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
@@ -474,22 +609,24 @@ int pv_watchpid_scanfds(pvstate_t state, pvstate_t pristine,
|
||||
*/
|
||||
void pv_watchpid_setname(pvstate_t state, pvwatchfd_t info)
|
||||
{
|
||||
int path_length, cwd_length, max_display_length;
|
||||
size_t path_length, cwd_length;
|
||||
int max_display_length;
|
||||
char *file_fdpath = info->file_fdpath;
|
||||
|
||||
memset(info->display_name, 0, PV_SIZEOF_DISPLAY_NAME);
|
||||
|
||||
path_length = strlen(info->file_fdpath);
|
||||
cwd_length = strlen(state->cwd);
|
||||
path_length = strlen(info->file_fdpath); /* flawfinder: ignore */
|
||||
cwd_length = strlen(state->status.cwd); /* flawfinder: ignore */
|
||||
/* flawfinder: both strings are always \0 terminated. */
|
||||
if (cwd_length > 0 && path_length > cwd_length) {
|
||||
if (0 == strncmp(info->file_fdpath, state->cwd, cwd_length)) {
|
||||
if (0 == strncmp(info->file_fdpath, state->status.cwd, cwd_length)) {
|
||||
file_fdpath += cwd_length + 1;
|
||||
path_length -= cwd_length + 1;
|
||||
}
|
||||
}
|
||||
|
||||
max_display_length = (state->width / 2) - 6;
|
||||
if (max_display_length >= path_length) {
|
||||
max_display_length = (int) (state->control.width / 2) - 6;
|
||||
if (max_display_length >= (int) path_length) {
|
||||
(void) pv_snprintf(info->display_name,
|
||||
PV_SIZEOF_DISPLAY_NAME, "%4d:%.498s", info->watch_fd, file_fdpath);
|
||||
} else {
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
# Dummy assignments for "shellcheck".
|
||||
testSubject="${testSubject:-false}"; workFile1="${workFile1:-.tmp1}"; workFile2="${workFile2:-.tmp2}"; workFile3="${workFile3:-.tmp3}"; workFile4="${workFile4:-.tmp4}"
|
||||
|
||||
# Do nothing if IPC is not supported.
|
||||
# Do nothing if it is not supported.
|
||||
if ! "${testSubject}" -h 2>/dev/null | grep -Eq "^ -R,"; then
|
||||
echo "IPC is not supported on this platform"
|
||||
echo "Not supported on this platform"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
# Dummy assignments for "shellcheck".
|
||||
sourcePath="${sourcePath:-.}"; testSubject="${testSubject:-false}"; workFile1="${workFile1:-.tmp1}"; workFile2="${workFile2:-.tmp2}"; workFile3="${workFile3:-.tmp3}"; workFile4="${workFile4:-.tmp4}"
|
||||
|
||||
# Do nothing if IPC is not supported.
|
||||
# Do nothing if it is not supported.
|
||||
if ! "${testSubject}" -h 2>/dev/null | grep -Eq "^ -R,"; then
|
||||
echo "IPC is not supported on this platform"
|
||||
echo "Not supported on this platform"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
# Dummy assignments for "shellcheck".
|
||||
sourcePath="${sourcePath:-.}"; testSubject="${testSubject:-false}"; workFile1="${workFile1:-.tmp1}"; workFile2="${workFile2:-.tmp2}"; workFile3="${workFile3:-.tmp3}"; workFile4="${workFile4:-.tmp4}"
|
||||
|
||||
# Do nothing if IPC is not supported.
|
||||
# Do nothing if it is not supported.
|
||||
if ! "${testSubject}" -h 2>/dev/null | grep -Eq "^ -R,"; then
|
||||
echo "IPC is not supported on this platform"
|
||||
echo "Not supported on this platform"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
# Dummy assignments for "shellcheck".
|
||||
testSubject="${testSubject:-false}"; workFile1="${workFile1:-.tmp1}"; workFile2="${workFile2:-.tmp2}"; workFile3="${workFile3:-.tmp3}"; workFile4="${workFile4:-.tmp4}"
|
||||
|
||||
# Do nothing if IPC is not supported.
|
||||
# Do nothing if it is not supported.
|
||||
if ! "${testSubject}" -h 2>/dev/null | grep -Eq "^ -R,"; then
|
||||
echo "IPC is not supported on this platform"
|
||||
echo "Not supported on this platform"
|
||||
exit 77
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user