From 36a9415469571fa972b6ff9004401aee393d28ad Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Mon, 6 Apr 2009 02:35:34 +0000 Subject: [PATCH] contrib: add "lar" - initial work on lua archive format --- contrib/lar/Makefile | 12 +++ contrib/lar/cli.c | 61 +++++++++++++++ contrib/lar/lar.c | 176 +++++++++++++++++++++++++++++++++++++++++++ contrib/lar/lar.h | 76 +++++++++++++++++++ contrib/lar/lar.pl | 50 ++++++++++++ 5 files changed, 375 insertions(+) create mode 100644 contrib/lar/Makefile create mode 100644 contrib/lar/cli.c create mode 100644 contrib/lar/lar.c create mode 100644 contrib/lar/lar.h create mode 100755 contrib/lar/lar.pl diff --git a/contrib/lar/Makefile b/contrib/lar/Makefile new file mode 100644 index 0000000000..64c323505d --- /dev/null +++ b/contrib/lar/Makefile @@ -0,0 +1,12 @@ +GCC := gcc +CFLAGS := -Wall +LDFLAGS := + +OBJ = cli.o lar.o +BIN = lar + +cli: $(OBJ) + $(GCC) $(CFLAGS) -o $(BIN) $(OBJ) $(LDFLAGS) + +clean: + rm -f $(OBJ) $(BIN) diff --git a/contrib/lar/cli.c b/contrib/lar/cli.c new file mode 100644 index 0000000000..026150e79e --- /dev/null +++ b/contrib/lar/cli.c @@ -0,0 +1,61 @@ +#include "lar.h" + +int do_print_member( lar_archive *ar, const char *name ) +{ + lar_member *member; + + if( (member = lar_open_member(ar, name)) != NULL ) + { + write(fileno(stdout), member->data, member->length); + lar_close_member(member); + } + else + LAR_DIE("Unable to locate archive member"); + + return 0; +} + +int do_print_index( lar_archive *ar ) +{ + lar_index *index = ar->index; + LAR_FNAME(filename); + + while(index) + { + lar_get_filename(ar, index, filename); + printf("%s\n", filename); + index = index->next; + } + + return 0; +} + +int main( int argc, const char* argv[] ) +{ + lar_archive *ar; + + if( argv[1] != NULL ) + { + if( (ar = lar_open(argv[1])) != NULL ) + { + if( argv[2] ) + return do_print_member(ar, argv[2]); + else + return do_print_index(ar); + + lar_close(ar); + } + else + { + LAR_DIE("Failed to open archive"); + } + } + else + { + printf("Usage: lar []\n"); + return 1; + } + + return 0; +} + diff --git a/contrib/lar/lar.c b/contrib/lar/lar.c new file mode 100644 index 0000000000..255bc01503 --- /dev/null +++ b/contrib/lar/lar.c @@ -0,0 +1,176 @@ +#include "lar.h" + +int lar_read32( int fd, uint32_t *val ) +{ + uint8_t buffer[5]; + + if( read(fd, buffer, 4) < 4 ) + LAR_DIE("Unexpected EOF while reading data"); + + buffer[4] = 0; + *val = ntohl(*((uint32_t *) buffer)); + + return 0; +} + +int lar_read16( int fd, uint16_t *val ) +{ + uint8_t buffer[3]; + + if( read(fd, buffer, 2) < 2 ) + LAR_DIE("Unexpected EOF while reading data"); + + buffer[2] = 0; + *val = ntohs(*((uint16_t *) buffer)); + + return 0; +} + +lar_index * lar_get_index( lar_archive *ar ) +{ + uint32_t i; + uint32_t idx_offset; + uint32_t idx_length; + lar_index *idx_map, *idx_ptr; + + if( lseek(ar->fd, -(sizeof(idx_offset)), SEEK_END) == -1 ) + LAR_DIE("Unable to seek to end of archive"); + + lar_read32(ar->fd, &idx_offset); + idx_length = ( ar->length - idx_offset - sizeof(idx_offset) ); + + if( lseek(ar->fd, idx_offset, SEEK_SET) == -1 ) + LAR_DIE("Unable to seek to archive index"); + + + idx_map = NULL; + + for( i = 0; i < idx_length; \ + i += (sizeof(lar_index) - sizeof(char)) + ) { + idx_ptr = (lar_index *)malloc(sizeof(lar_index)); + + lar_read32(ar->fd, &idx_ptr->noffset); + lar_read32(ar->fd, &idx_ptr->nlength); + lar_read32(ar->fd, &idx_ptr->foffset); + lar_read32(ar->fd, &idx_ptr->flength); + lar_read16(ar->fd, &idx_ptr->type); + lar_read16(ar->fd, &idx_ptr->flags); + + idx_ptr->next = idx_map; + idx_map = idx_ptr; + } + + return idx_map; +} + +uint32_t lar_get_filename( lar_archive *ar, + lar_index *idx_ptr, char *filename +) { + if( idx_ptr->nlength >= LAR_FNAME_BUFFER ) + LAR_DIE("Filename exceeds maximum allowed length"); + + if( lseek(ar->fd, idx_ptr->noffset, SEEK_SET) == -1 ) + LAR_DIE("Unexpected EOF while seeking filename"); + + if( read(ar->fd, filename, idx_ptr->nlength) < idx_ptr->nlength ) + LAR_DIE("Unexpected EOF while reading filename"); + + filename[idx_ptr->nlength] = 0; + + return idx_ptr->nlength; +} + +lar_member * lar_open_member( lar_archive *ar, const char *name ) +{ + lar_index *idx_ptr = ar->index; + lar_member *member; + char memberfile[LAR_FNAME_BUFFER]; + char *memberdata; + size_t pgsz = getpagesize(); + + while(idx_ptr) + { + lar_get_filename(ar, idx_ptr, memberfile); + + if( !strncmp(memberfile, name, idx_ptr->nlength) ) + { + memberdata = mmap( + 0, idx_ptr->flength + ( idx_ptr->foffset % pgsz ), + PROT_READ, MAP_PRIVATE, ar->fd, + idx_ptr->foffset - ( idx_ptr->foffset % pgsz ) + ); + + if( memberdata == MAP_FAILED ) + LAR_DIE("Failed to mmap() member data"); + + member = (lar_member *)malloc(sizeof(lar_member)); + member->type = idx_ptr->type; + member->flags = idx_ptr->flags; + member->length = idx_ptr->flength; + member->data = &memberdata[idx_ptr->foffset % pgsz]; + + member->mmap = memberdata; + member->mlen = idx_ptr->flength + ( idx_ptr->foffset % pgsz ); + + return member; + } + + idx_ptr = idx_ptr->next; + } + + return NULL; +} + +int lar_close_member( lar_member *member ) +{ + int stat = munmap(member->mmap, member->mlen); + free(member); + + return stat; +} + +lar_archive * lar_open( const char *filename ) +{ + int fd; + struct stat as; + lar_archive *ar; + + if( stat(filename, &as) == -1 ) + return NULL; + + if( !(as.st_mode & S_IFREG) ) + return NULL; + + if( (fd = open(filename, O_RDONLY)) != -1 ) + { + ar = (lar_archive *)malloc(sizeof(lar_archive)); + ar->fd = fd; + ar->length = as.st_size; + ar->index = lar_get_index(ar); + strncpy(ar->filename, filename, sizeof(ar->filename)); + + return ar; + } + + return NULL; +} + +int lar_close( lar_archive *ar ) +{ + lar_index *idx_head; + lar_index *idx_next; + + close(ar->fd); + + idx_head = ar->index; + do { + idx_next = idx_head->next; + free(idx_head); + } while( (idx_head = idx_next) != NULL ); + + free(ar); + + return 0; +} + diff --git a/contrib/lar/lar.h b/contrib/lar/lar.h new file mode 100644 index 0000000000..a4379f1eb9 --- /dev/null +++ b/contrib/lar/lar.h @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int errno; + +#define LAR_DIE(s) \ + do { \ + fprintf(stderr, "%s(%i): %s(): %s\n", \ + __FILE__, __LINE__, __FUNCTION__, s); \ + if( errno ) fprintf(stderr, "%s(%i): %s\n", \ + __FILE__, __LINE__, strerror(errno) ); \ + exit(1); \ + } while(0) + + +#define LAR_FNAME_BUFFER 1024 +#define LAR_FNAME(s) char s[LAR_FNAME_BUFFER] + + +struct lar_index_item { + uint32_t noffset; + uint32_t nlength; + uint32_t foffset; + uint32_t flength; + uint16_t type; + uint16_t flags; + struct lar_index_item *next; +}; + +struct lar_member_item { + uint16_t type; + uint16_t flags; + uint32_t length; + char *data; + char *mmap; + size_t mlen; +}; + +struct lar_archive_handle { + int fd; + off_t length; + char filename[LAR_FNAME_BUFFER]; + struct lar_index_item *index; +}; + +typedef struct lar_index_item lar_index; +typedef struct lar_member_item lar_member; +typedef struct lar_archive_handle lar_archive; + + +int lar_read32( int fd, uint32_t *val ); +int lar_read16( int fd, uint16_t *val ); + +lar_index * lar_get_index( lar_archive *ar ); + +uint32_t lar_get_filename( lar_archive *ar, + lar_index *idx_ptr, char *filename ); + +lar_member * lar_open_member( lar_archive *ar, const char *name ); + +int lar_close_member( lar_member *member ); + +lar_archive * lar_open( const char *filename ); + +int lar_close( lar_archive *ar ); + + diff --git a/contrib/lar/lar.pl b/contrib/lar/lar.pl new file mode 100755 index 0000000000..56e4897958 --- /dev/null +++ b/contrib/lar/lar.pl @@ -0,0 +1,50 @@ +#!/usr/bin/perl + +use strict; + +@ARGV || die "Usage: $0 ... \n"; + +my @index; +my $offset = 0; + +foreach my $file ( @ARGV ) +{ + if( -f $file && open F, "< $file" ) + { + warn sprintf "Member at 0x%08X\n", $offset; + push @index, [ ]; + + my $size = length $file; + + print $file; + print "\0" x ( $size % 4 ); + + $index[-1][0] = $offset; + $index[-1][1] = $size; + $index[-1][2] = $offset + $size + ( $size % 4 ); + + + $size = 0; + while( read F, my $buffer, 4096 ) { + $size += length $buffer; + print $buffer; + } + print "\0" x ( $size % 4 ); + + $index[-1][3] = $size; + $offset = $index[-1][2] + $size + ( $size % 4 ); + + close F; + } +} + + +foreach my $file ( @index ) +{ + warn sprintf "Index: 0x%08X 0x%08X 0x%08X 0x%08X\n", $file->[0], $file->[1], $file->[2], $file->[3]; + print pack "NNNNnn", $file->[0], $file->[1], $file->[2], $file->[3], 0x0000, 0x0000; +} + +warn sprintf "Index at 0x%08X, length 0x%08X\n", $offset, @index * 20; +print pack "N", $offset; + -- 2.30.2