Tidied up code so that local files should now work as well as bundles, also added the option to compress the data on the fly (if not already compressed bundle).
This commit is contained in:
parent
58209cd184
commit
d1e94d8a46
5 changed files with 144 additions and 92 deletions
4
Makefile
4
Makefile
|
@ -188,13 +188,13 @@ all: ${PROG}
|
|||
#
|
||||
#
|
||||
${PROG}: $(OBJS) $(ALLDEPS) support/dataroot/wd.c
|
||||
$(CC) -o $@ $(OBJS) support/dataroot/wd.c $(LDFLAGS) ${LDFLAGS_cfg}
|
||||
$(CC) -o $@ $(OBJS) $(CFLAGS_com) support/dataroot/wd.c $(LDFLAGS) ${LDFLAGS_cfg}
|
||||
|
||||
${PROG}.bundle: $(OBJS) $(BUNDLE_OBJS) $(ALLDEPS) support/dataroot/bundle.c
|
||||
$(CC) -o $@ $(OBJS) support/dataroot/bundle.c $(BUNDLE_OBJS) $(LDFLAGS) ${LDFLAGS_cfg}
|
||||
|
||||
${PROG}.datadir: $(OBJS) $(ALLDEPS) support/dataroot/datadir.c
|
||||
$(CC) -o $@ $(OBJS) -iquote${BUILDDIR} support/dataroot/datadir.c $(LDFLAGS) ${LDFLAGS_cfg}
|
||||
$(CC) -o $@ $(OBJS) $(CFLAGS_com) -iquote${BUILDDIR} support/dataroot/datadir.c $(LDFLAGS) ${LDFLAGS_cfg}
|
||||
|
||||
#
|
||||
#
|
||||
|
|
224
src/filebundle.c
224
src/filebundle.c
|
@ -28,14 +28,6 @@
|
|||
#include "filebundle.h"
|
||||
#include "tvheadend.h"
|
||||
|
||||
#ifdef TEST
|
||||
#define MIN(x,y) ((x<y)?x:y)
|
||||
static char *tvheadend_dataroot()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* **************************************************************************
|
||||
* Opaque data types
|
||||
* *************************************************************************/
|
||||
|
@ -70,18 +62,86 @@ typedef struct filebundle_file
|
|||
fb_type type;
|
||||
size_t size;
|
||||
int gzip;
|
||||
uint8_t *buf;
|
||||
size_t pos;
|
||||
union {
|
||||
struct {
|
||||
FILE *cur;
|
||||
FILE *cur;
|
||||
} d;
|
||||
struct {
|
||||
size_t cur;
|
||||
const filebundle_entry_t *root;
|
||||
uint8_t *buf;
|
||||
} b;
|
||||
};
|
||||
} fb_file;
|
||||
|
||||
/* **************************************************************************
|
||||
* Compression/Decompression
|
||||
* *************************************************************************/
|
||||
|
||||
static uint8_t *_fb_inflate ( const uint8_t *data, size_t size, size_t orig )
|
||||
{
|
||||
int err;
|
||||
z_stream zstr;
|
||||
uint8_t *bufin, *bufout;
|
||||
|
||||
/* Setup buffers */
|
||||
bufin = malloc(size);
|
||||
bufout = malloc(orig);
|
||||
memcpy(bufin, data, size);
|
||||
|
||||
/* Setup zlib */
|
||||
memset(&zstr, 0, sizeof(zstr));
|
||||
inflateInit2(&zstr, 31);
|
||||
zstr.avail_in = size;
|
||||
zstr.next_in = bufin;
|
||||
zstr.avail_out = orig;
|
||||
zstr.next_out = bufout;
|
||||
|
||||
/* Decompress */
|
||||
err = inflate(&zstr, Z_NO_FLUSH);
|
||||
if ( err != Z_STREAM_END || zstr.avail_out != 0 ) {
|
||||
free(bufout);
|
||||
bufout = NULL;
|
||||
}
|
||||
free(bufin);
|
||||
inflateEnd(&zstr);
|
||||
|
||||
return bufout;
|
||||
}
|
||||
|
||||
static uint8_t *_fb_deflate ( const uint8_t *data, size_t orig, size_t *size )
|
||||
{
|
||||
int err;
|
||||
z_stream zstr;
|
||||
uint8_t *bufin, *bufout;
|
||||
|
||||
/* Setup buffers */
|
||||
bufin = malloc(orig);
|
||||
bufout = malloc(orig);
|
||||
memcpy(bufin, data, orig);
|
||||
|
||||
/* Setup zlib */
|
||||
memset(&zstr, 0, sizeof(zstr));
|
||||
err = deflateInit2(&zstr, 9, Z_DEFLATED, 31, 9, Z_DEFAULT_STRATEGY);
|
||||
zstr.avail_in = orig;
|
||||
zstr.next_in = bufin;
|
||||
zstr.avail_out = orig;
|
||||
zstr.next_out = bufout;
|
||||
|
||||
/* Decompress */
|
||||
err = deflate(&zstr, Z_FINISH);
|
||||
if ( (err != Z_STREAM_END && err != Z_OK) || zstr.total_out == 0 ) {
|
||||
free(bufout);
|
||||
bufout = NULL;
|
||||
} else {
|
||||
*size = zstr.total_out;
|
||||
}
|
||||
free(bufin);
|
||||
deflateEnd(&zstr);
|
||||
|
||||
return bufout;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Directory processing
|
||||
* *************************************************************************/
|
||||
|
@ -125,7 +185,7 @@ fb_dir *fb_opendir ( const char *path )
|
|||
} else {
|
||||
DIR *dir;
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "%s%s%s", root, *root ? "" : "/", path);
|
||||
snprintf(buf, sizeof(buf), "%s/%s", root, path);
|
||||
if ((dir = opendir(buf))) {
|
||||
ret = calloc(1, sizeof(fb_dir));
|
||||
ret->type = FB_DIRECT;
|
||||
|
@ -185,10 +245,13 @@ fb_dirent *fb_readdir ( fb_dir *dir )
|
|||
// be passed in though and will be ignored if this is not the case
|
||||
// Note: compress will work on EITHER type (but will be ignored for already
|
||||
// compressed bundles)
|
||||
fb_file *fb_open2 ( const fb_dir *dir, const char *name, int decompress, int compress )
|
||||
fb_file *fb_open2
|
||||
( const fb_dir *dir, const char *name, int decompress, int compress )
|
||||
{
|
||||
assert(!decompress || !compress);
|
||||
fb_file *ret = NULL;
|
||||
|
||||
/* Bundle file */
|
||||
if (dir->type == FB_BUNDLE) {
|
||||
const filebundle_entry_t *fb = dir->b.root->d.child;
|
||||
while (fb) {
|
||||
|
@ -206,47 +269,56 @@ fb_file *fb_open2 ( const fb_dir *dir, const char *name, int decompress, int com
|
|||
if (fb->f.orig != -1 && decompress) {
|
||||
ret->gzip = 0;
|
||||
ret->size = fb->f.orig;
|
||||
int err;
|
||||
z_stream zstr;
|
||||
uint8_t *bufin, *bufout;
|
||||
|
||||
/* Setup buffers */
|
||||
bufin = malloc(fb->f.size);
|
||||
bufout = malloc(fb->f.orig);
|
||||
memcpy(bufin, fb->f.data, fb->f.size);
|
||||
|
||||
/* Setup zlib */
|
||||
zstr.zalloc = Z_NULL;
|
||||
zstr.zfree = 0;
|
||||
zstr.opaque = Z_NULL;
|
||||
zstr.avail_in = 0;
|
||||
zstr.next_in = Z_NULL;
|
||||
inflateInit2(&zstr, 31);
|
||||
zstr.avail_in = fb->f.size;
|
||||
zstr.next_in = bufin;
|
||||
zstr.avail_out = fb->f.orig;
|
||||
zstr.next_out = bufout;
|
||||
|
||||
/* Decompress */
|
||||
err = inflate(&zstr, Z_NO_FLUSH);
|
||||
if ( err == Z_STREAM_END && zstr.avail_out == 0 ) {
|
||||
ret->b.buf = bufout;
|
||||
|
||||
/* Error */
|
||||
} else {
|
||||
free(bufout);
|
||||
ret->buf = _fb_inflate(fb->f.data, fb->f.size, fb->f.orig);
|
||||
if (!ret->buf) {
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
/* Cleanup */
|
||||
free(bufin);
|
||||
inflateEnd(&zstr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Direct file */
|
||||
} else {
|
||||
|
||||
char path[512];
|
||||
snprintf(path, sizeof(path), "%s/%s", dir->d.root, name);
|
||||
FILE *fp = fopen(path, "r");
|
||||
if (fp) {
|
||||
struct stat st;
|
||||
lstat(path, &st);
|
||||
ret = calloc(1, sizeof(fb_file));
|
||||
ret->type = FB_DIRECT;
|
||||
ret->size = st.st_size;
|
||||
ret->gzip = 0;
|
||||
ret->d.cur = fp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Compress */
|
||||
if (ret && !ret->gzip && compress) {
|
||||
ret->gzip = 1;
|
||||
|
||||
/* Get data */
|
||||
if (ret->type == FB_BUNDLE) {
|
||||
const uint8_t *data;
|
||||
data = ret->b.root->f.data;
|
||||
ret->buf = _fb_deflate(data, ret->size, &ret->size);
|
||||
} else {
|
||||
uint8_t *data = malloc(ret->size);
|
||||
ssize_t c = fread(data, 1, ret->size, ret->d.cur);
|
||||
if (c == ret->size)
|
||||
ret->buf = _fb_deflate(data, ret->size, &ret->size);
|
||||
fclose(ret->d.cur);
|
||||
ret->d.cur = NULL;
|
||||
free(data);
|
||||
}
|
||||
|
||||
/* Cleanup */
|
||||
if (!ret->buf) {
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -261,7 +333,7 @@ fb_file *fb_open ( const char *path, int decompress, int compress )
|
|||
free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Find directory */
|
||||
*pos = '\0';
|
||||
dir = fb_opendir(tmp);
|
||||
|
@ -279,10 +351,10 @@ fb_file *fb_open ( const char *path, int decompress, int compress )
|
|||
/* Close file */
|
||||
void fb_close ( fb_file *fp )
|
||||
{
|
||||
if (fp->type == FB_DIRECT)
|
||||
if (fp->type == FB_DIRECT && fp->d.cur)
|
||||
fclose(fp->d.cur);
|
||||
else if (fp->b.buf)
|
||||
free(fp->b.buf);
|
||||
if (fp->buf)
|
||||
free(fp->buf);
|
||||
free(fp);
|
||||
}
|
||||
|
||||
|
@ -301,28 +373,25 @@ int fb_gzipped ( fb_file *fp )
|
|||
/* Check for EOF */
|
||||
int fb_eof ( fb_file *fp )
|
||||
{
|
||||
if (fp->type == FB_DIRECT) {
|
||||
return feof(fp->d.cur);
|
||||
} else {
|
||||
return fp->b.cur >= fp->size;
|
||||
}
|
||||
return fp->pos >= fp->size;
|
||||
}
|
||||
|
||||
/* Read some data */
|
||||
ssize_t fb_read ( fb_file *fp, void *buf, size_t count )
|
||||
{
|
||||
if (fp->type == FB_DIRECT) {
|
||||
return fread(buf, 1, count, fp->d.cur);
|
||||
} else if (fb_eof(fp)) {
|
||||
if (fb_eof(fp)) {
|
||||
return -1;
|
||||
} else if (fp->buf) {
|
||||
count = MIN(count, fp->size - fp->pos);
|
||||
memcpy(buf, fp->buf + fp->pos, count);
|
||||
fp->pos += count;
|
||||
} else if (fp->type == FB_DIRECT) {
|
||||
fp->pos += fread(buf, 1, count, fp->d.cur);
|
||||
return -1;
|
||||
} else if (fp->b.buf) {
|
||||
count = MIN(count, fp->b.root->f.orig - fp->b.cur);
|
||||
memcpy(buf, fp->b.buf + fp->b.cur, count);
|
||||
fp->b.cur += count;
|
||||
} else {
|
||||
count = MIN(count, fp->b.root->f.size - fp->b.cur);
|
||||
memcpy(buf, fp->b.root->f.data + fp->b.cur, count);
|
||||
fp->b.cur += count;
|
||||
count = MIN(count, fp->b.root->f.size - fp->pos);
|
||||
memcpy(buf, fp->b.root->f.data + fp->pos, count);
|
||||
fp->pos += count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -340,26 +409,3 @@ char *fb_gets ( fb_file *fp, void *buf, size_t count )
|
|||
((char*)buf)[c] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
int main ( int argc, char **argv )
|
||||
{
|
||||
uint8_t buf[100000];
|
||||
fb_dirent *de;
|
||||
fb_dir *d = fb_opendir(argv[1]);
|
||||
if (d) {
|
||||
while ((de = fb_readdir(d))) {
|
||||
printf("name = %s\n", de->name);
|
||||
fb_file *fp = fb_open2(d, de->name, 1, 0);
|
||||
printf("size = %lu\n", fb_size(fp));
|
||||
while (!fb_eof(fp)) {
|
||||
if (fb_gets(fp, buf, sizeof(buf)) == NULL)
|
||||
return 1;
|
||||
printf("LINE: %s", buf);
|
||||
}
|
||||
fb_close(fp);
|
||||
}
|
||||
fb_closedir(d);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -99,7 +99,6 @@ page_static_file(http_connection_t *hc, const char *remain, void *opaque)
|
|||
return HTTP_STATUS_BAD_REQUEST;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", base, remain);
|
||||
printf("path = %s\n", path);
|
||||
|
||||
postfix = strrchr(remain, '.');
|
||||
if(postfix != NULL) {
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#include "config.h"
|
||||
#include "filebundle.h"
|
||||
|
||||
filebundle_entry_t *filebundle_root = NULL;
|
||||
|
||||
const char *tvheadend_dataroot(void)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "filebundle.h"
|
||||
|
||||
filebundle_entry_t *filebundle_root = NULL;
|
||||
|
||||
const char *tvheadend_dataroot(void)
|
||||
{
|
||||
static char cwd[256] = { 0 };
|
||||
|
|
Loading…
Add table
Reference in a new issue