mksquashfs: improve out of space in output filesystem handling

There has been a long term problem with out of space handling
in mksquashfs, dating back to the parallelisation of mksquashfs
in 2006. The writer thread discovers out of space when writing
the filesystem, but, it cannot tell the main thread to abort, as
there is no "back channel" to the main thread.  Adding a back
channel wasn't an attractive option because checking of this
by the main thread would limit parallelisation, and I was keen on
maxmising parallelism.  In the end I implemented a workaround where
the writer() thread flaged the error, ignored further write requests,
and at the end of the filesystem creation when the main thread had to
synchronise with the writer thread, it passed an error flag back,
which would cause the main thread to abort then.

This workaround was determined to be "good enough" for the first
release of "parallel mksquashfs" when as usual due to work commitments
I needed to finish the difficult and complex task of parallelising
Mksquashfs by a fixed deadline.  This was encouraged by the view that
nobody knowingly creates Squashfs filesystems on a device insufficiently
large, and if it does prove too small, it is likely to be towards the
end of filesystem creation, and so no-one would notice Mksquashfs running
on until the end of the filesystem creation....  So it proved to be,
no-one raised issues about the out of space handling, and although
the out of space handling was never entirely forgotten about, it
was never re-visited as there was always something more important to
deal with, and the years went by ...

Fast-forward to 2013, and I get some emails about "Lseek failure" on
the destination device.  Although it's not been conclusively proved
because the reporter has not got back to me, it is almost certainly
a subtle case of the "out of space" handling.  The reporter is confused
as there's been no "out of space" error reported, and I was confused for
a while until I realised the "out of space" error has likely scrolled off the
screen - the source filesystem is huge, the destination filesystem is far
too small, and by the time the "Lseek error" is reported the out of space
error is long gone.  The "Lseek error" is a symptom of the earlier
"out of space" error where the writer thread has ceased to write
data to the output filesystem - when the main thread finds a "potential"
duplicate file alread stored in the filesystem, it reads the original
file out of the filesystem for a byte-by-byte compare, but the file
doesn't exist as it would have been written after the "out of space"
error, and on a block device this will result in an "Lseek error".

So, the out of space handling finally causes an issue seven years
afterwards.

Revisiting the problem the solution is obvious, have the writer thread
send a signal to the main process, the main process on receipt of the
signal aborts and restores the filesystem if it is appending.  In fact
the infrastructure already exists to deal with the user hitting ^C twice.

This commit fixes that.  The next commit will fix a subtle edge condition
with the writer thread where it may experience Lseek error before
hitting Out of Space on block devices.  This is already handled, but it is
not flagged as an Out of Space error.  This could be the Lseek error reported
but it is unlikely, as the Lseek error is reported as immediately
terminating Mksquashfs, if the writer thread experienced Lseek Mksquashfs
would in fact continue.

Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
mksquashfs: flag lseek error in writer as probable out of space

If the writer thread hits "lseek error" it is probably because the
destination file is out of space, this is especially true if the
destination is a block device, but could conceivably happen on some
(non Linux?) filesystems too if they don't implement holes.  This
is because lseeking to the write position could be beyond the end
of the available destination file end, and hence fail before
attempting to write.

Recent correspondence with users shows that "Lseek error" is
meaningless, and so augment the error message with an "Out of
Space" error which is presumbly something they will understand.

Note we can't use BAD_ERROR here because it will cause mksquashfs to
immediately exit, and we instead want to signal the the main thread to
exit.

Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
mksquashfs: flag lseek error in write_destination as probable out of space

If the main thread hits "lseek error" when writing the metadata
in write_destination() it is probably because the
destination file is out of space, this is especially true if the
destination is a block device, but could conceivably happen on some
(non Linux?) filesystems too if they don't implement holes.  This
is because lseeking to the write position could be beyond the end
of the available destination file end, and hence fail before
attempting to write.

Recent correspondence with users shows that "Lseek error" is
meaningless, and so augment the error message with an "Out of
Space" error which is presumbly something they will understand.

Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
mksquashfs: Rewrite write failure error message in write_destination()

Write_bytes() already prints an error message if write() fails,
so this error message is largely redundant.

So replace with a more user friendly error message that says
we're aborting due to failure to write the filesystem image.

Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
mksquashfs: Rewrite write failure error message in writer thread

Write_bytes() already prints an error message if write() fails,
so this error message is largely redundant.

So replace with a more user friendly error message that says
we're aborting due to failure to write the filesystem image.

Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>