aboutsummaryrefslogtreecommitdiff
path: root/squashfs-tools
AgeCommit message (Collapse)Author
2013-02-21pseudo: Use MEM_ERROR() for out of space handling.Phillip Lougher
Replace all hand crafted BAD_ERROR() messages with MEM_ERROR() which does the same thing. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-02-21mksquashfs: Use MEM_ERROR() for out of space handling.Phillip Lougher
Replace all hand crafted BAD_ERROR() messages with MEM_ERROR() which does the same thing. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-02-21action: Use MEM_ERROR() for out of space handling.Phillip Lougher
Replace all hand crafted BAD_ERROR() messages with MEM_ERROR() which does the same thing. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-02-21error: add MEM_ERROR() macroPhillip Lougher
Add a new MEM_ERROR() macro that prints out of space with the function it occurred in, and then aborts mksquashfs, restoring the original filesystem if appending. This macro allows "Out of memory" handling to be regularised accross Mksquashfs, rather than at present where every out of memory error has a different and hand crafted error message. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-02-14mksquashfs: Rewrite write failure error message in writer threadPhillip Lougher
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>
2013-02-14mksquashfs: Rewrite write failure error message in write_destination()Phillip Lougher
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>
2013-02-14mksquashfs: flag lseek error in write_destination as probable out of spacePhillip Lougher
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>
2013-02-14mksquashfs: flag lseek error in writer as probable out of spacePhillip Lougher
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>
2013-02-11mksquashfs: improve out of space in output filesystem handlingPhillip Lougher
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>
2013-02-06mksquashfs: Improve writer lseek error messagePhillip Lougher
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-02-06mksquashfs: Improve lseek error messagesPhillip Lougher
Add description to determine which function the lseek error occurred in, and add the offset the lseek was trying to seek to. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-02-03unsquashfs: add support for displaying compression optionsPhillip Lougher
Add support to display the compression options used to compress the filesystem in -stat. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-02-02unsquashfs: fix error statementPhillip Lougher
Forgot to update error message when function was renamed. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-02-01unsquashfs: fix read_directory_table() parameterPhillip Lougher
sBlk.s.fragment_table_start isn't the end of the directory table, it instead points to the fragment_index_table, in which the first index of that points to the end of the directory table. The only exception to that is where fragments == 0, where fragment_table_start does represent the end of the directory table. The upshot of this is that for years Unsquashfs has been reading and decompressing the directory_table and the table after it. Not a major bug, but a waste of memory all the same. It has shown up now because of the additional sanity checks when reading metadata blocks that have been added recently, where all metadata blocks in the directory table bar the last one should be SQUASHFS_METADATA_SIZE in size. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-28unsquashfs: bring uncompress_directory_table() into linePhillip Lougher
with the other filesystem table reading functions. In particular, rename to read_directory_table() and return errors as FALSE rather than exiting inside the function. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-28unsquashfs: bring uncompress_inode_table() into linePhillip Lougher
with the other filesystem table reading functions. In particular, rename to read_inode_table() and return errors as FALSE rather than exiting inside the function. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-28unsquashfs: harden inode/directory table reading against corrupted filesystemsPhillip Lougher
Harden inode and directory table reading, checking against unexpected metadata block length, ensuring no buffer overflow/underflow occurs. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-28unsquash-4.c: harden uid/gid and fragment table reading against corrupted dataPhillip Lougher
Harden uid/gid and fragment table reading, checking against unexpected metadata block length, ensuring no buffer overflow/underflow occurs. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-28unsquash-3: harden fragment table reading against corrupted filesystemsPhillip Lougher
Harden fragment table reading, checking against unexpected metadata block length, ensuring no buffer overflow/underflow occurs. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-28unsquash-2: harden fragment table reading against corrupted filesystemsPhillip Lougher
Harden fragment table reading, checking against unexpected metadata block length, ensuring no buffer overflow/underflow occurs. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-28read_xattrs: harden xattr data reading against corrupted filesystemsPhillip Lougher
Harden xattr data reading, checking against unexpected metadata block length, ensuring no buffer overflow/underflow occurs. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-25unsquashfs: prevent buffer {over|under}flow in read_block() with corrupted ↵Phillip Lougher
filesystems Prevent buffer overflow and underflow in read_block() with corrupted filesystems. Overflow is easy to understand, read_block() is called to read the next metadata block pointed to by <start>... Often the buffer passed in is large enough to hold the expected return bytes, which can be less than SQUASHFS_METADATA_SIZE. For example filesystem tables are compressed in SQUASHFS_METADATA_SIZEd chunks, the last compressed chunk will normally be smaller than SQUASHFS_METADATA_SIZE, so when read_block() is called, the passed buffer is only large enough to hold the expected size. Underflow is rather more subtle, when read_block() is called, it is expected that the returned block will fill the expected amount of bytes in the filesystem table (stored as an array). If the returned block is smaller than expected, then there will be uninitialised data in the filesystem table which will cause unexpected behaviour later. Fix both cases by passing in an additional parameter <expected> which contains the expected number of bytes in the metadata block. Refuse to read blocks which are larger than expected to avoid buffer overflow and also return error if the block proves to be smaller than expected, to avoid using unitialised data. For the callers where the expected number of bytes is unknown support <expected> containing 0, in which case the metadata block is checked to ensure it doesn't overflow a SQUASHFS_METADATA_SIZEd buffer. Callers of read_block() with <expected> == 0 are expected to pass in a SQUASHFS_METADATA_SIZEd buffer. For instance with compressor specific options data, the correct length is only known by the compressor specific code, and this is later called to check the length. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-24read_fs: reformat scan_inode_table() tidying codePhillip Lougher
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-23read_fs: Further harden scan_inode_table() against corrupted filesystemsPhillip Lougher
Add a lot more sanity checks to the data read from the filesystem. Also ensure we do not try to access beyond the malloced buffer holding the data. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-23codec_wrappers: rename block_size in uncompress() to outsizePhillip Lougher
Rename block_size parameter in uncompress() call to outsize, as it now holds the size of the output buffer, which can be less than block_size. Also in the wrappers where the uncompressed length is available in the header, don't bother calling the codec if outsize is too small. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-22read_fs: When reading directory pass expected number of bytes to read_block()Phillip Lougher
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-22read_fs: check the root inode block is found in scan_inode_table()Phillip Lougher
Further hardening of read_fs. If the filesystem is corrupted we may get the situation where in the inode_table metatadata block scan we fail to find the metadata block containing the root inode. In this case *root_inode_block will be used unitialised. Add code to check against the small possibility this happens. In the majority of cases if the filesystem is corrupted we will fail to read a metadata block in the block scan, and so we will never get to this place in the code, however, it could happen and so it needs to be guarded against. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-22read_fs: check metadata blocks are expected size in scan_inode_table()Phillip Lougher
Note we can't use expected in read_block() here because at the time of calling read_block() we don't know what the expected size is. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-22read_fs: When reading lookup_table pass expected number of bytes to read_block()Phillip Lougher
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-22read_fs: When reading fragment_table pass expected number of bytes to ↵Phillip Lougher
read_block() Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-22read_fs: When reading id_table pass expected number of bytes to read_block()Phillip Lougher
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-22read_fs: prevent buffer {over|under}flow in read_block() with corrupted ↵Phillip Lougher
filesystems Prevent buffer overflow and underflow in read_block() with corrupted filesystems. Overflow is easy to understand, read_block() is called to read the next metadata block pointed to by <start>... Often the buffer passed in is large enough to hold the expected return bytes, which can be less than SQUASHFS_METADATA_SIZE. For example filesystem tables are compressed in SQUASHFS_METADATA_SIZEd chunks, the last compressed chunk will normally be smaller than SQUASHFS_METADATA_SIZE, so when read_block() is called, the passed buffer is only large enough to hold the expected size. Underflow is rather more subtle, when read_block() is called, it is expected that the returned block will fill the expected amount of bytes in the filesystem table (stored as an array). If the returned block is smaller than expected, then there will be uninitialised data in the filesystem table which will cause unexpected behaviour later. Fix both cases by passing in an additional parameter <expected> which contains the expected number of bytes in the metadata block. Refuse to read blocks which are larger than expected to avoid buffer overflow and also return error if the block proves to be smaller than expected, to avoid using unitialised data. For the callers where the expected number of bytes is unknown support <expected> containing 0, in which case the metadata block is checked to ensure it doesn't overflow a SQUASHFS_METADATA_SIZEd buffer. Callers of read_block() with <expected> == 0 are expected to pass in a SQUASHFS_METADATA_SIZEd buffer. For instance with compressor specific options data, the correct length is only known by the compressor specific code, and this is later called to check the length. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-17mksquashfs: Get rid of unused defs in squashfs_xattr_{entry|val} structsPhillip Lougher
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-13mksquashfs: ensure buffer_list is always initialised in write_file_blocks_dup()Phillip Lougher
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-13mksquashfs: ensure block_list is always initialised in write_file_blocks_dup()Phillip Lougher
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-13mksquashfs: ensure block_list is always initialised in write_file_blocks()Phillip Lougher
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-13action: fix memory leak in move_dir()Phillip Lougher
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-13mksquashfs: optimise subpathname() calling in dir_scan1()Phillip Lougher
Small optimisation - subpath is only needed if there are exclude actions specified, or if the dir_ent is a directory. In other cases don't calculate subpath as it is not needed. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-09mksquashfs: rewrite some ugly code in scan1_opendir()Phillip Lougher
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-09mksquashfs: Move strdupping of filename/subpath to scan1_opendir()Phillip Lougher
This simplifies the logic, eliminating the need to strdup on the recursive call to dir_scan1(), and eliminating the need to free them on recursive dir_scan1() failure. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-09mksquashfs: eliminate redundant labelPhillip Lougher
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-09mksquashfs: optimise excluded() when dealing with non-anchored excludesPhillip Lougher
Non anchored excludes (specified with the "... name" syntax to exclude files matching name in any directory) are implemented with the "stickypath" path variable. This is an exclude specification which "sticks" as it is present in every directory. This was previously implemented by adding the stickypath to each new set of paths returned from the excluded() function, as obviously, we want stickypath to be present in the next sub-directory. However, this has the undesirable effect that the new paths variable "new" is always returned holding at least one entry (the stickypath). This partially breaks the original design intention of excluded() where by putting the exclude specifications only in the directories where they are applicable, for the majority of the time dir_scan1() will have an empty set of paths to check for exclude matches, thus eliminating the overhead of exclude matching. Fix this by not implementing stickypaths as an entry added to the new set of paths returned from excluded(), instead explictly match against stickypath if it exists. This slightly complicates excluded() requiring a new helper function excluded_match() split out of excluded(), but the benefit is the new variable in the majority of cases now gets returned empty (NULL) for stickypaths which was the original intention. Also get rid of init_subdir() and instead initialise new in add_subdir() when first called. This not only eliminates code (so the overall changes are 15 lines shorter than before despite the addition of the new excluded_match() helper function) but it also means "new" is never allocated in the event we don't get any matches. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-07mksquashfs: fix "new" variable leak in dir_scan1()Phillip Lougher
Fix leak in dir_scan1() where new returned by excluded() was not freed. Normally new will be null unless exclude files and wildcards have been used. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-07mksquashfs: Wrap line longer than 80 charsPhillip Lougher
Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2013-01-04action: add quoted string and back slash handling to lexical analyserPhillip Lougher
Add the ability to parse strings quoted with ", and also add the ability to backslash "special characters" that would normally be treated as end of string. Quoted and non quoted strings can be specified multiply and the strings will be concatenated together. String examples "Hello World" Hello\ World This" is a "string "So"\ is\ "this" "This \" is too" etc. Also switch to using an internal buffer (increased as necessary) to return strings from the lexical analyser, rather than dynamically allocating each string returned. This reduces unnecessary overhead (mostly strings returned from the lexical analyser are discarded without being stored, the ones that are stored can be explicitly copied when necessary), and it fixes a memory leak in the parser as returned strings are not freed. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2012-12-31pseudo: Get rid of ERROR statements in child process in exec_file()Phillip Lougher
ERROR() since commit 738570df60f65c10cd7fde4134f3af1e005b671a calls progressbar_error() to synchronise with the progress bar output, however, this function uses pthread mutexes which are meaningless/ useless in a child process. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2012-12-31action: Get rid of ERROR statements in child process in file() testPhillip Lougher
ERROR() since commit 738570df60f65c10cd7fde4134f3af1e005b671a calls progressbar_error() to synchronise with the progress bar output, however, this function uses pthread mutexes which are meaningless/ useless in a child process. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2012-12-30action: implement exec() test optionPhillip Lougher
Exec() adds the ability to run a command, with the result of the test being the exit status of the command; if the command returns a valid exit status (0), exec() returns TRUE, otherwise on a bad exit status exec() returns FALSE. Three environment variables hold: - NAME: name of file - PATHNAME: pathname of file relative to squashfs root - SOURCE_PATHNAME: the pathname of the file in the source directory Currently only a single argument (without spaces) can be entered as a command, this is because the actions parser currently lacks the ability to have arguments with spaces in them (either argument quoted with '"', or spaces blackslashed with '\')! Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2012-12-30xz_wrapper: Add comments describing how compression option functions workPhillip Lougher
XZ is the only compression algorithm using the "new" compression option framework. Add some comments on the functions that describe how the functions work, and how they interact with the overall compression options framework. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
2012-12-30pseudo: Improve parse error messages in read_pseudo_def()Phillip Lougher
Plus add checking for trailing characters Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>