Skip to content

Commit

Permalink
Fix skipping in stream inputs.
Browse files Browse the repository at this point in the history
The existing test was piping input from a file, not an IPC pipe,
so wasn't a proper test. Fix the test and make skipping in pipes
work.
  • Loading branch information
fragglet committed Mar 16, 2013
1 parent b1ef312 commit 16ba398
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 9 deletions.
6 changes: 4 additions & 2 deletions lib/lha_basic_reader.c
Expand Up @@ -75,8 +75,10 @@ LHAFileHeader *lha_basic_reader_next_file(LHABasicReader *reader)
lha_file_header_free(reader->curr_file);
reader->curr_file = NULL;

lha_input_stream_skip(reader->stream,
reader->curr_file_remaining);
if (!lha_input_stream_skip(reader->stream,
reader->curr_file_remaining)) {
reader->eof = 1;
}
}

if (reader->eof) {
Expand Down
49 changes: 45 additions & 4 deletions lib/lha_input_stream.c
Expand Up @@ -22,6 +22,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>

#include "lha_arch.h"
#include "lha_input_stream.h"
Expand Down Expand Up @@ -293,11 +294,51 @@ static int file_source_read(void *handle, void *buf, size_t buf_len)
return (int) bytes_read;
}

// "Fallback" skip for file source that uses fread(), for unseekable
// streams.

static int file_source_skip_fallback(FILE *handle, size_t bytes)
{
uint8_t data[32];
unsigned int len;
int result;

while (bytes > 0) {
if (bytes > sizeof(data)) {
len = sizeof(data);
} else {
len = bytes;
}

result = fread(data, 1, len, handle);

if (result != (int) len) {
return 0;
}

bytes -= len;
}

return 1;
}

// Seek forward in a FILE * input stream.

static int file_source_seek(void *handle, size_t bytes)
static int file_source_skip(void *handle, size_t bytes)
{
return fseek(handle, (long) bytes, SEEK_CUR);
int result;

result = fseek(handle, (long) bytes, SEEK_CUR);

if (result < 0) {
if (errno == EBADF || errno == ESPIPE) {
return file_source_skip_fallback(handle, bytes);
} else {
return 0;
}
}

return 1;
}

// Close a FILE * input stream.
Expand All @@ -312,15 +353,15 @@ static void file_source_close(void *handle)

static const LHAInputStreamType file_source_owned = {
file_source_read,
file_source_seek,
file_source_skip,
file_source_close
};

// "Unowned" file source - the stream is owned by the calling code.

static const LHAInputStreamType file_source_unowned = {
file_source_read,
file_source_seek,
file_source_skip,
NULL
};

Expand Down
2 changes: 1 addition & 1 deletion lib/public/lha_reader.h
Expand Up @@ -49,7 +49,7 @@ typedef struct _LHAReader LHAReader;
* Policy for extracting directories.
*
* When extracting a directory, some of the metadata associated with
* it need to be set after the contents of the directory have been
* it needs to be set after the contents of the directory have been
* extracted. This includes the modification time (which would
* otherwise be reset to the current time) and the permissions (which
* can affect the ability to extract files into the directory).
Expand Down
8 changes: 6 additions & 2 deletions test/test-extract
Expand Up @@ -250,8 +250,12 @@ test_stdin_extract() {

make_sandboxes

lha_check_output "$expected_file" e - \
< $(test_arc_file "$archive_file")
# This is *not* a useless use of cat. If a < pipe was used,
# the input would come from a file handle, not a pipe. Using
# cat forces the data to come from a pipe.

cat $(test_arc_file "$archive_file") | \
lha_check_output "$expected_file" e -

check_extracted_files "$archive_file"

Expand Down

0 comments on commit 16ba398

Please sign in to comment.