pacat: Write to stream only in frame-sized chunks
authorAhmed S. Darwish <darwish.07@gmail.com>
Tue, 20 Dec 2016 09:07:31 +0000 (09:07 +0000)
committerTanu Kaskinen <tanuk@iki.fi>
Tue, 20 Dec 2016 17:59:08 +0000 (19:59 +0200)
commitf7b8df50c71acd9f06faa7182aeba08458b89a86
treeb01318f8292693ca29e7e75c44aa80bc79942d9d
parent65958ca83312c2ada0848878567735bc03d49e8b
pacat: Write to stream only in frame-sized chunks

Current pacat code reads whatever available from STDIN and writes
it directly to the playback stream. A minimal buffer is created
for each read operation; no further reads are then allowed unless
earlier read buffer has been fully consumed by a stream write.

While quite simple, this model breaks upon the new requirements of
writing only frame-aligned data to the stream (commits #1 and #2).
The kernel read syscall can return a length much smaller than the
frame-aligned size requested, leading to invalid unaligned writes.

This can easily be reproduced by choosing a starved STDIN backend:

  pacat /dev/random    pa_stream_write() failed: EINVAL
  echo 1234 | pacat    pa_stream_write() failed: EINVAL

or by playing an incomplete WAV file in raw, non-paplay, mode.

So guard against such incomplete kernel reads by writing only in
frame-aligned sizes, while caching any trailing partial frame for
subsequent writes.

Other operation modes are not affected. Non-raw paplay playback is
handled by libsndfile, ensuring complete reads, and recording mode
just writes to the STDOUT fd without any special needs.

CommitReference #1: 22827a5e1e62
CommitReference #2: 150ace90f380
BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=98475
BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=77595
Suggested-by: David Henningsson <diwic@ubuntu.com>
Signed-off-by: Ahmed S. Darwish <darwish.07@gmail.com>
src/utils/pacat.c