From a8096d4ea8ee7c5eb03f5aa5bf92ab4d7c19334a Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Fri, 3 Aug 2012 12:30:32 +0100 Subject: [PATCH] Some updated to bundle/settings to integrate the two. Settings can now be seamlessly loaded from bundle/share/settings directory. This is useful to opentv module but may be useful elsewhere in the future. --- Makefile | 2 +- data/{ => conf}/epggrab/opentv/dict/skyeng | 0 data/{ => conf}/epggrab/opentv/dict/skyit | 0 data/{ => conf}/epggrab/opentv/genre/skyuk | 0 data/{ => conf}/epggrab/opentv/prov/ausat | 0 data/{ => conf}/epggrab/opentv/prov/skyit | 0 data/{ => conf}/epggrab/opentv/prov/skyuk | 0 src/filebundle.c | 96 ++++- src/filebundle.h | 24 +- src/settings.c | 396 ++++++++++----------- support/mkbundle | 252 +++++++------ support/mkbundle.py | 150 -------- 12 files changed, 432 insertions(+), 488 deletions(-) rename data/{ => conf}/epggrab/opentv/dict/skyeng (100%) rename data/{ => conf}/epggrab/opentv/dict/skyit (100%) rename data/{ => conf}/epggrab/opentv/genre/skyuk (100%) rename data/{ => conf}/epggrab/opentv/prov/ausat (100%) rename data/{ => conf}/epggrab/opentv/prov/skyit (100%) rename data/{ => conf}/epggrab/opentv/prov/skyuk (100%) delete mode 100755 support/mkbundle.py diff --git a/Makefile b/Makefile index 78aa0e79..29f17e3b 100644 --- a/Makefile +++ b/Makefile @@ -169,7 +169,7 @@ CFLAGS_com = -g -funsigned-char -O2 CFLAGS_com += -D_FILE_OFFSET_BITS=64 CFLAGS_com += -I${BUILDDIR} -I${CURDIR}/src -I${CURDIR} -MKBUNDLE = $(CURDIR)/support/mkbundle.py +MKBUNDLE = $(CURDIR)/support/mkbundle ifndef V ECHO = printf "$(1)\t\t%s\n" $(2) diff --git a/data/epggrab/opentv/dict/skyeng b/data/conf/epggrab/opentv/dict/skyeng similarity index 100% rename from data/epggrab/opentv/dict/skyeng rename to data/conf/epggrab/opentv/dict/skyeng diff --git a/data/epggrab/opentv/dict/skyit b/data/conf/epggrab/opentv/dict/skyit similarity index 100% rename from data/epggrab/opentv/dict/skyit rename to data/conf/epggrab/opentv/dict/skyit diff --git a/data/epggrab/opentv/genre/skyuk b/data/conf/epggrab/opentv/genre/skyuk similarity index 100% rename from data/epggrab/opentv/genre/skyuk rename to data/conf/epggrab/opentv/genre/skyuk diff --git a/data/epggrab/opentv/prov/ausat b/data/conf/epggrab/opentv/prov/ausat similarity index 100% rename from data/epggrab/opentv/prov/ausat rename to data/conf/epggrab/opentv/prov/ausat diff --git a/data/epggrab/opentv/prov/skyit b/data/conf/epggrab/opentv/prov/skyit similarity index 100% rename from data/epggrab/opentv/prov/skyit rename to data/conf/epggrab/opentv/prov/skyit diff --git a/data/epggrab/opentv/prov/skyuk b/data/conf/epggrab/opentv/prov/skyuk similarity index 100% rename from data/epggrab/opentv/prov/skyuk rename to data/conf/epggrab/opentv/prov/skyuk diff --git a/src/filebundle.c b/src/filebundle.c index a7cb2f63..b054e6df 100644 --- a/src/filebundle.c +++ b/src/filebundle.c @@ -32,13 +32,6 @@ * Opaque data types * *************************************************************************/ -/* Bundle or Direct */ -typedef enum filebundle_handle_type -{ - FB_BUNDLE, - FB_DIRECT -} fb_type; - /* File bundle dir handle */ typedef struct filebundle_dir { @@ -142,6 +135,42 @@ static uint8_t *_fb_deflate ( const uint8_t *data, size_t orig, size_t *size ) return bufout; } +/* ************************************************************************** + * Miscellanous + * *************************************************************************/ + +/* Get path stats */ +// TODO: this could do with being more efficient +int fb_stat ( const char *path, struct filebundle_stat *st ) +{ + int ret = 1; + fb_dir *dir; + fb_file *fp; + + if (*path == '/') { + struct stat _st; + if (!lstat(path, &_st)) { + st->type = FB_DIRECT; + st->is_dir = S_ISDIR(_st.st_mode) ? 1 : 0; + st->size = _st.st_size; + ret = 0; + } + } else if ((dir = fb_opendir(path))) { + st->type = dir->type; + st->is_dir = 1; + st->size = 0; + ret = 0; + fb_closedir(dir); + } else if ((fp = fb_open(path, 0, 0))) { + st->type = fp->type; + st->is_dir = 0; + st->size = fp->size; + ret = 0; + fb_close(fp); + } + return ret; +} + /* ************************************************************************** * Directory processing * *************************************************************************/ @@ -213,7 +242,7 @@ fb_dirent *fb_readdir ( fb_dir *dir ) fb_dirent *ret = NULL; if (dir->type == FB_BUNDLE) { if (dir->b.cur) { - dir->dirent.name = dir->b.cur->name; + strcpy(dir->dirent.name, dir->b.cur->name); dir->dirent.type = dir->b.cur->type; dir->b.cur = dir->b.cur->next; ret = &dir->dirent; @@ -225,7 +254,7 @@ fb_dirent *fb_readdir ( fb_dir *dir ) struct stat st; char buf[512]; snprintf(buf, sizeof(buf), "%s/%s", dir->d.root, de->d_name); - dir->dirent.name = de->d_name; + strcpy(dir->dirent.name, de->d_name); dir->dirent.type = FB_UNKNOWN; if (!lstat(buf, &st)) dir->dirent.type = S_ISDIR(st.st_mode) ? FB_DIR : FB_FILE; @@ -235,6 +264,50 @@ fb_dirent *fb_readdir ( fb_dir *dir ) return ret; } +/* Get entry list */ +int fb_scandir ( const char *path, fb_dirent ***list ) +{ + int i, ret = -1; + struct dirent **de; + struct filebundle_stat st; + if (fb_stat(path, &st)) return -1; + if (!st.is_dir) return -1; + + /* Direct */ + if (st.type == FB_DIRECT) { + if ((ret = scandir(path, &de, NULL, NULL)) != -1) { + if (ret == 0) return 0; + *list = malloc(sizeof(fb_dirent*)*ret); + for (i = 0; i < ret; i++) { + (*list)[i] = calloc(1, sizeof(fb_dirent)); + strcpy((*list)[i]->name, de[i]->d_name); + (*list)[i]->type = FB_DIRECT; + free(de[i]); + } + free(de); + } + + /* Bundle */ + } else { + fb_dir *dir; + if ((dir = fb_opendir(path))) { + const filebundle_entry_t *fb; + ret = dir->b.root->d.count; + fb = dir->b.root->d.child; + *list = malloc(ret * sizeof(fb_dirent)); + i = 0; + while (fb) { + (*list)[i] = calloc(1, sizeof(fb_dirent)); + strcpy((*list)[i]->name, fb->name); + fb = fb->next; + i++; + } + fb_closedir(dir); + } + } + return ret; +} + /* ************************************************************************** * Directory processing * *************************************************************************/ @@ -344,6 +417,7 @@ fb_file *fb_open ( const char *path, int decompress, int compress ) /* Open */ ret = fb_open2(dir, pos+1, decompress, compress); + fb_closedir(dir); free(tmp); return ret; } @@ -351,8 +425,9 @@ fb_file *fb_open ( const char *path, int decompress, int compress ) /* Close file */ void fb_close ( fb_file *fp ) { - if (fp->type == FB_DIRECT && fp->d.cur) + if (fp->type == FB_DIRECT && fp->d.cur) { fclose(fp->d.cur); + } if (fp->buf) free(fp->buf); free(fp); @@ -387,7 +462,6 @@ ssize_t fb_read ( fb_file *fp, void *buf, size_t count ) fp->pos += count; } else if (fp->type == FB_DIRECT) { fp->pos += fread(buf, 1, count, fp->d.cur); - return -1; } else { count = MIN(count, fp->b.root->f.size - fp->pos); memcpy(buf, fp->b.root->f.data + fp->pos, count); diff --git a/src/filebundle.h b/src/filebundle.h index 315bc3fb..d25ca833 100644 --- a/src/filebundle.h +++ b/src/filebundle.h @@ -24,6 +24,13 @@ #include #include +/* Bundle or Direct */ +typedef enum filebundle_handle_type +{ + FB_BUNDLE, + FB_DIRECT +} fb_type; + /* File bundle entry type */ enum filebundle_type { @@ -39,6 +46,7 @@ typedef struct filebundle_entry const char *name; union { struct { + size_t count; struct filebundle_entry *child; } d; struct { @@ -53,10 +61,18 @@ typedef struct filebundle_entry /* File bundle directory entry */ typedef struct filebundle_dirent { - const char *name; - enum filebundle_type type; + char name[256]; + enum filebundle_type type; } fb_dirent; +/* File bundle stat */ +struct filebundle_stat +{ + fb_type type; + uint8_t is_dir; + size_t size; +}; + /* Opaque types */ typedef struct filebundle_dir fb_dir; typedef struct filebundle_file fb_file; @@ -64,10 +80,14 @@ typedef struct filebundle_file fb_file; /* Root of bundle */ extern filebundle_entry_t *filebundle_root; +/* Miscellaneous */ +int fb_stat ( const char *path, struct filebundle_stat *st ); + /* Directory processing wrappers */ fb_dir *fb_opendir ( const char *path ); fb_dirent *fb_readdir ( fb_dir *fb ); void fb_closedir ( fb_dir *fb ); +int fb_scandir ( const char *path, fb_dirent ***list ); /* File processing wrappers */ // Note: all access is read-only diff --git a/src/settings.c b/src/settings.c index e2c54779..8f2088dc 100644 --- a/src/settings.c +++ b/src/settings.c @@ -31,6 +31,7 @@ #include "htsmsg_json.h" #include "settings.h" #include "tvheadend.h" +#include "filebundle.h" static char *settingspath; @@ -43,7 +44,6 @@ hts_settings_get_root(void) return settingspath ?: "No settings dir"; } - /** * */ @@ -56,17 +56,12 @@ hts_settings_init(const char *confpath) if(confpath != NULL) { settingspath = strdup(confpath); - } else { - - if(homedir != NULL) { - snprintf(buf, sizeof(buf), "%s/.hts", homedir); - if(stat(buf, &st) == 0 || mkdir(buf, 0700) == 0) { - - snprintf(buf, sizeof(buf), "%s/.hts/tvheadend", homedir); - - if(stat(buf, &st) == 0 || mkdir(buf, 0700) == 0) - settingspath = strdup(buf); - } + } else if(homedir != NULL) { + snprintf(buf, sizeof(buf), "%s/.hts", homedir); + if(stat(buf, &st) == 0 || mkdir(buf, 0700) == 0) { + snprintf(buf, sizeof(buf), "%s/.hts/tvheadend", homedir); + if(stat(buf, &st) == 0 || mkdir(buf, 0700) == 0) + settingspath = strdup(buf); } } if(settingspath == NULL) { @@ -82,139 +77,42 @@ hts_settings_init(const char *confpath) } } - -/** - * - */ -void -hts_settings_save(htsmsg_t *record, const char *pathfmt, ...) -{ - char path[256]; - char fullpath[256]; - char fullpath2[256]; - int x, l, fd; - va_list ap; - struct stat st; - htsbuf_queue_t hq; - htsbuf_data_t *hd; - char *n; - int ok; - - if(settingspath == NULL) - return; - - va_start(ap, pathfmt); - vsnprintf(path, sizeof(path), pathfmt, ap); - va_end(ap); - - n = path; - - while(*n) { - if(*n == ':' || *n == '?' || *n == '*' || *n > 127 || *n < 32) - *n = '_'; - n++; - } - - l = strlen(path); - - for(x = 0; x < l; x++) { - if(path[x] == '/') { - /* It's a directory here */ - - path[x] = 0; - snprintf(fullpath, sizeof(fullpath), "%s/%s", settingspath, path); - - if(stat(fullpath, &st) && mkdir(fullpath, 0700)) { - tvhlog(LOG_ALERT, "settings", "Unable to create dir \"%s\": %s", - fullpath, strerror(errno)); - return; - } - path[x] = '/'; - } - } - - snprintf(fullpath, sizeof(fullpath), "%s/%s.tmp", settingspath, path); - - if((fd = tvh_open(fullpath, O_CREAT | O_TRUNC | O_RDWR, 0700)) < 0) { - tvhlog(LOG_ALERT, "settings", "Unable to create \"%s\" - %s", - fullpath, strerror(errno)); - return; - } - - ok = 1; - - htsbuf_queue_init(&hq, 0); - htsmsg_json_serialize(record, &hq, 1); - - TAILQ_FOREACH(hd, &hq.hq_q, hd_link) - if(write(fd, hd->hd_data + hd->hd_data_off, hd->hd_data_len) != - hd->hd_data_len) { - tvhlog(LOG_ALERT, "settings", "Failed to write file \"%s\" - %s", - fullpath, strerror(errno)); - ok = 0; - break; - } - - close(fd); - - snprintf(fullpath2, sizeof(fullpath2), "%s/%s", settingspath, path); - - if(ok) - rename(fullpath, fullpath2); - else - unlink(fullpath); - - htsbuf_queue_flush(&hq); -} - -/** - * - */ -static htsmsg_t * -hts_settings_load_one(const char *filename) -{ - struct stat st; - int fd; - char *mem; - htsmsg_t *r; - int n; - - if(stat(filename, &st) < 0) - return NULL; - - if((fd = tvh_open(filename, O_RDONLY, 0)) < 0) - return NULL; - - mem = malloc(st.st_size + 1); - mem[st.st_size] = 0; - - n = read(fd, mem, st.st_size); - close(fd); - if(n == st.st_size) - r = htsmsg_json_deserialize(mem); - else - r = NULL; - - free(mem); - - return r; -} - /** * */ static int -hts_settings_buildpath(char *dst, size_t dstsize, const char *fmt, va_list ap) +hts_settings_makedirs ( char *path ) +{ + size_t x; + struct stat st; + size_t l = strlen(path); + for(x = 0; x < l; x++) { + if(path[x] == '/' && x != 0) { + path[x] = 0; + if(stat(path, &st) && mkdir(path, 0700)) { + tvhlog(LOG_ALERT, "settings", "Unable to create dir \"%s\": %s", + path, strerror(errno)); + return -1; + } + path[x] = '/'; + } + } + return 0; +} + +/** + * + */ +static void +hts_settings_buildpath + (char *dst, size_t dstsize, const char *fmt, va_list ap, const char *prefix) { char tmp[256]; char *n = dst; - if(settingspath == NULL) - return -1; - vsnprintf(tmp, sizeof(tmp), fmt, ap); - if (*tmp != '/') - snprintf(dst, dstsize, "%s/%s", settingspath, tmp); + if (*tmp != '/' && prefix) + snprintf(dst, dstsize, "%s/%s", prefix, tmp); else strncpy(dst, tmp, dstsize); @@ -223,7 +121,134 @@ hts_settings_buildpath(char *dst, size_t dstsize, const char *fmt, va_list ap) *n = '_'; n++; } - return 0; +} + +/** + * + */ +void +hts_settings_save(htsmsg_t *record, const char *pathfmt, ...) +{ + char path[256]; + char tmppath[256]; + int fd; + va_list ap; + htsbuf_queue_t hq; + htsbuf_data_t *hd; + int ok; + + if(settingspath == NULL) + return; + + /* Clean the path */ + va_start(ap, pathfmt); + hts_settings_buildpath(path, sizeof(path), pathfmt, ap, settingspath); + va_end(ap); + + /* Create directories */ + if (hts_settings_makedirs(path)) return; + + /* Create tmp file */ + snprintf(tmppath, sizeof(tmppath), "%s.tmp", path); + if((fd = tvh_open(tmppath, O_CREAT | O_TRUNC | O_RDWR, 0700)) < 0) { + tvhlog(LOG_ALERT, "settings", "Unable to create \"%s\" - %s", + tmppath, strerror(errno)); + return; + } + + /* Store data */ + ok = 1; + htsbuf_queue_init(&hq, 0); + htsmsg_json_serialize(record, &hq, 1); + TAILQ_FOREACH(hd, &hq.hq_q, hd_link) + if(write(fd, hd->hd_data + hd->hd_data_off, hd->hd_data_len) != + hd->hd_data_len) { + tvhlog(LOG_ALERT, "settings", "Failed to write file \"%s\" - %s", + tmppath, strerror(errno)); + ok = 0; + break; + } + close(fd); + htsbuf_queue_flush(&hq); + + /* Move */ + if(ok) { + rename(tmppath, path); + + /* Delete tmp */ + } else + unlink(tmppath); +} + +/** + * + */ +static htsmsg_t * +hts_settings_load_one(const char *filename) +{ + ssize_t n; + char *mem; + fb_file *fp; + htsmsg_t *r = NULL; + + /* Open */ + if (!(fp = fb_open(filename, 1, 0))) return NULL; + + /* Load data */ + mem = malloc(fb_size(fp)+1); + n = fb_read(fp, mem, fb_size(fp)); + if (n >= 0) mem[n] = 0; + fb_close(fp); + + /* Decode */ + if(n == fb_size(fp)) + r = htsmsg_json_deserialize(mem); + free(mem); + + return r; +} + +/** + * + */ +static htsmsg_t * +_hts_settings_load(const char *fullpath) +{ + char child[256]; + struct filebundle_stat st; + fb_dirent **namelist, *d; + htsmsg_t *r, *c; + int n, i; + + /* Invalid */ + if (fb_stat(fullpath, &st)) return NULL; + + /* Directory */ + if (st.is_dir) { + + /* Get file list */ + if((n = fb_scandir(fullpath, &namelist)) < 0) + return NULL; + + /* Read files */ + r = htsmsg_create_map(); + for(i = 0; i < n; i++) { + d = namelist[i]; + if(d->name[0] != '.') { + snprintf(child, sizeof(child), "%s/%s", fullpath, d->name); + if ((c = hts_settings_load_one(child))) + htsmsg_add_msg(r, d->name, c); + } + free(d); + } + free(namelist); + + /* File */ + } else { + r = hts_settings_load_one(fullpath); + } + + return r; } /** @@ -232,45 +257,27 @@ hts_settings_buildpath(char *dst, size_t dstsize, const char *fmt, va_list ap) htsmsg_t * hts_settings_load(const char *pathfmt, ...) { + htsmsg_t *ret = NULL; char fullpath[256]; - char child[256]; va_list ap; - struct stat st; - struct dirent **namelist, *d; - htsmsg_t *r, *c; - int n, i; + /* Try normal path */ va_start(ap, pathfmt); - if(hts_settings_buildpath(fullpath, sizeof(fullpath), pathfmt, ap) < 0) - return NULL; + hts_settings_buildpath(fullpath, sizeof(fullpath), + pathfmt, ap, settingspath); + va_end(ap); + ret = _hts_settings_load(fullpath); - if(stat(fullpath, &st) != 0) - return NULL; - - if(S_ISDIR(st.st_mode)) { - - if((n = scandir(fullpath, &namelist, NULL, NULL)) < 0) - return NULL; - - r = htsmsg_create_map(); - - for(i = 0; i < n; i++) { - d = namelist[i]; - if(d->d_name[0] != '.') { - snprintf(child, sizeof(child), "%s/%s", fullpath, d->d_name); - c = hts_settings_load_one(child); - if(c != NULL) - htsmsg_add_msg(r, d->d_name, c); - } - free(d); - } - free(namelist); - - } else { - r = hts_settings_load_one(fullpath); + /* Try bundle path */ + if (!ret && *pathfmt != '/') { + va_start(ap, pathfmt); + hts_settings_buildpath(fullpath, sizeof(fullpath), + pathfmt, ap, "data/conf"); + va_end(ap); + ret = _hts_settings_load(fullpath); } - - return r; + + return ret; } /** @@ -283,12 +290,12 @@ hts_settings_remove(const char *pathfmt, ...) va_list ap; va_start(ap, pathfmt); - if(hts_settings_buildpath(fullpath, sizeof(fullpath), pathfmt, ap) < 0) - return; + hts_settings_buildpath(fullpath, sizeof(fullpath), + pathfmt, ap, settingspath); + va_end(ap); unlink(fullpath); } - /** * */ @@ -296,48 +303,19 @@ int hts_settings_open_file(int for_write, const char *pathfmt, ...) { char path[256]; - char fullpath[256]; - int x, l; va_list ap; - struct stat st; - char *n; - - if(settingspath == NULL) - return -1; + /* Build path */ va_start(ap, pathfmt); - vsnprintf(path, sizeof(path), pathfmt, ap); + hts_settings_buildpath(path, sizeof(path), pathfmt, ap, settingspath); va_end(ap); - n = path; - - while(*n) { - if(*n == ':' || *n == '?' || *n == '*' || *n > 127 || *n < 32) - *n = '_'; - n++; - } - - l = strlen(path); - - for(x = 0; x < l; x++) { - if(path[x] == '/') { - /* It's a directory here */ - - path[x] = 0; - snprintf(fullpath, sizeof(fullpath), "%s/%s", settingspath, path); - - if(stat(fullpath, &st) && mkdir(fullpath, 0700)) { - tvhlog(LOG_ALERT, "settings", "Unable to create dir \"%s\": %s", - fullpath, strerror(errno)); - return -1; - } - path[x] = '/'; - } - } - - snprintf(fullpath, sizeof(fullpath), "%s/%s", settingspath, path); + /* Create directories */ + if (for_write) + if (hts_settings_makedirs(path)) return -1; + /* Open file */ int flags = for_write ? O_CREAT | O_TRUNC | O_WRONLY : O_RDONLY; - return tvh_open(fullpath, flags, 0700); + return tvh_open(path, flags, 0700); } diff --git a/support/mkbundle b/support/mkbundle index 2a7801bc..68741008 100755 --- a/support/mkbundle +++ b/support/mkbundle @@ -1,133 +1,155 @@ -#!/bin/bash +#!/usr/bin/env python # -# Filebundle generator -# Copyright (C) 2009 Andreas Ă–man -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Replacement for old mkbundle script that creates a full file heirarchy # -set -u # Fail on undefined vars +import os, sys, re +import gzip, cStringIO +from optparse import OptionParser -READER="cat" -SOURCE= -DEPFILE= -OUTPUT= -PREFIX= -COMPRESS=false -usage() -{ -cat << EOF -usage: $0 options +# Add reverse path split +def rsplit ( p ): + i = p.find(os.path.sep) + if i != -1: + return (p[:i], p[i+1:]) + else: + return (p, '') -Generate a filebundle .c-file from a directory +# Process command line +optp = OptionParser() +optp.add_option('-z', '--gzip', action='store_true', + help='Compress the files with gzip') +optp.add_option('-l', '--gzlevel', type='int', default=9, + help='Specify compression level if using gzip') +optp.add_option('-o', '--output', default=None, + help='Specify output file (default /dev/stdout)') +optp.add_option('-d', '--deps', default=None, + help='Specify deps file to update during run') +(opts, args) = optp.parse_args() -OPTIONS: - -h Show this message - -s Source path - -d Dependency file (for use with make) - -o Output file (.c file) - -z Compress individual files using gzip - -p Filebundle prefix -EOF -} +# Setup +outf = sys.stdout +if opts.output: + outf = open(opts.output, 'w') +depf = None +if opts.deps: + depf = open(opts.deps, 'w') + print >>depf, '%s: \\' % opts.output +# Build heirarchy +root = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..')) +ents = {} +for path in args: + for (p, ds, fs) in os.walk(path): + p = os.path.abspath(p) + n = p.replace(root+'/', '') + t = ents + while True: + (d,n) = rsplit(n) + if d not in t: + t[d] = {} + t = t[d] + if not n: break + for f in fs: + t[f] = None -while getopts "s:d:o:zhp:" OPTION -do - case $OPTION in - h) - usage - exit 1 - ;; - z) - READER="gzip -9" - COMPRESS=true - ;; - d) - DEPFILE="$OPTARG" - ;; - s) - SOURCE="$OPTARG" - ;; - o) - OUTPUT="$OPTARG" - ;; - p) - PREFIX="$OPTARG" - ;; - esac - done +# Output a file +def output_file ( path, name, idx, next = -1 ): + n = 'NULL' + if next >= 0: n = '&filebundle_entry_%06d' % next + p = os.path.join(root, path, name); + # Dep file + if depf: print >>depf, ' %s\\' % p -if [[ -z $SOURCE ]] || [[ -z $OUTPUT ]] || [[ -z $PREFIX ]]; then - usage - exit 1 -fi + # First the data + print >>outf, '// FILE : %s %s %d %d' % (path, name, idx, next) + print >>outf, 'static const uint8_t filebundle_data_%06d[] = {' % idx, + o = -1 + d = open(p, 'rb').read() + if opts.gzip: + o = len(d) + l = opts.gzlevel + t = cStringIO.StringIO() + if l < 0: l = 1 + if l > 9: l = 9 + z = gzip.GzipFile(filename=name, mode='w', compresslevel=l, fileobj=t) + z.write(d) + z.close() + d = t.getvalue() + t.close() + i = 0 + for b in d: + if not (i % 12): print >>outf, '\n ', + print >>outf, '0x%02x,' % ord(b), + i = i + 1 + print >>outf, '' + print >>outf, '};' + + print >>outf, 'static filebundle_entry_t filebundle_entry_%06d = {' % idx + print >>outf, ' .type = FB_FILE,' + print >>outf, ' .name = "%s",' % name + print >>outf, ' .next = %s,' % n + print >>outf, ' .f.size = %d,' % len(d) + print >>outf, ' .f.orig = %d,' % o + print >>outf, ' .f.data = filebundle_data_%06d,' % idx + print >>outf, '};' + print >>outf, '' -FILES=`find "${SOURCE}" \( \( -name .svn -or -name *~ \) -and -prune \) -or -printf "%P "` +# Output a directory +def output_dir ( path, name, idx, child, count, next = -1 ): + n = 'NULL' + if next >= 0: n = '&filebundle_entry_%06d' % next + print >>outf, '// DIR: %s %s %d %d %d %d'\ + % (path, name, idx, child, count, next) + print >>outf, 'static filebundle_entry_t filebundle_entry_%06d = {' % idx + print >>outf, ' .type = FB_DIR,' + print >>outf, ' .name = "%s",' % name + print >>outf, ' .next = %s,' % n + print >>outf, ' .d.count = %d,' % count + print >>outf, ' .d.child = &filebundle_entry_%06d,' % child + print >>outf, '};' + print >>outf, '' -echo >${OUTPUT} "// auto-generated by $0" +# Create output +def add_entry ( ents, path = "", name = "", idx = -1, next = -1 ): -for file in $FILES; do + # Add children + d = os.path.join(path, name) + p = -1 + c = 0 + for k in ents: + + # File + if not ents[k]: + output_file(d, k, idx+1, p) + p = idx = idx + 1 + c = c + 1 + + # Directory + else: + tmp = add_entry(ents[k], d, k, idx, p) + if tmp != idx: + p = idx = tmp + c = c + 1 - if [ -f ${SOURCE}/$file ]; then + # Add directory + if p >= 0: + if name: + output_dir(path, name, idx+1, p, c, next) + idx = idx + 1 - name=`echo $file | perl -pe s#[^a-z0-9A-Z]#_#g` - - echo >>${OUTPUT} "// ${SOURCE}/$file" - echo >>${OUTPUT} "static const unsigned char embedded_$name[]={" - $READER <${SOURCE}/$file | od -v -An -b | sed s/^\ */0/ | sed s/\ *$$/,/| sed s/\ /,\ 0/g|sed s/$/,/ >>${OUTPUT} - echo >>${OUTPUT} "};" - fi -done + return idx -echo >>${OUTPUT} "#include " -echo >>${OUTPUT} "static const struct filebundle_entry filebundle_entries[] = {" -[[ -z $DEPFILE ]] || echo >${DEPFILE} -n "${OUTPUT}: " +# Output header +print >>outf, '// Auto-generated - DO NOT EDIT' +print >>outf, '// COMMAND: [%s]' % (' '.join(sys.argv)) +print >>outf, '' +print >>outf, '#include "filebundle.h"' +print >>outf, '' -for file in $FILES; do - [[ -z $DEPFILE ]] || echo >>${DEPFILE} -n "${SOURCE}/$file " +# Output entries +idx = add_entry(ents) - if [ -f ${SOURCE}/$file ]; then - - if $COMPRESS; then - ORIGINAL_SIZE=`stat -c "%s" ${SOURCE}/$file` - else - ORIGINAL_SIZE="-1" - fi - - N=`echo $file | perl -pe s#[^a-z0-9A-Z]#_#g` - echo >>${OUTPUT} "{\"$file\", embedded_$N, sizeof(embedded_$N),${ORIGINAL_SIZE}}," - fi -done - -echo >>${OUTPUT} "{(void *)0, 0, 0, 0}};" -[[ -z $DEPFILE ]] || echo >>${DEPFILE} "" - -cat >>${OUTPUT} <>outf, 'filebundle_entry_t *filebundle_root = &filebundle_entry_%06d;' % idx diff --git a/support/mkbundle.py b/support/mkbundle.py deleted file mode 100755 index e1fb053e..00000000 --- a/support/mkbundle.py +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python -# -# Replacement for old mkbundle script that creates a full file heirarchy -# - -import os, sys, re -import gzip, cStringIO -from optparse import OptionParser - -# Add reverse path split -def rsplit ( p ): - i = p.find(os.path.sep) - if i != -1: - return (p[:i], p[i+1:]) - else: - return (p, '') - -# Process command line -optp = OptionParser() -optp.add_option('-z', '--gzip', action='store_true', - help='Compress the files with gzip') -optp.add_option('-l', '--gzlevel', type='int', default=9, - help='Specify compression level if using gzip') -optp.add_option('-o', '--output', default=None, - help='Specify output file (default /dev/stdout)') -optp.add_option('-d', '--deps', default=None, - help='Specify deps file to update during run') -(opts, args) = optp.parse_args() - -# Setup -outf = sys.stdout -if opts.output: - outf = open(opts.output, 'w') -depf = None -if opts.deps: - depf = open(opts.deps, 'w') - print >>depf, '%s: \\' % opts.output - -# Build heirarchy -root = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..')) -ents = {} -for path in args: - for (p, ds, fs) in os.walk(path): - p = os.path.abspath(p) - n = p.replace(root+'/', '') - t = ents - while True: - (d,n) = rsplit(n) - if d not in t: - t[d] = {} - t = t[d] - if not n: break - for f in fs: - t[f] = None - -# Output a file -def output_file ( path, name, idx, next = -1 ): - n = 'NULL' - if next >= 0: n = '&filebundle_entry_%06d' % next - p = os.path.join(root, path, name); - - # Dep file - if depf: print >>depf, ' %s\\' % p - - # First the data - print >>outf, '// FILE : %s %s %d %d' % (path, name, idx, next) - print >>outf, 'static const uint8_t filebundle_data_%06d[] = {' % idx, - o = -1 - d = open(p, 'rb').read() - if opts.gzip: - o = len(d) - l = opts.gzlevel - t = cStringIO.StringIO() - if l < 0: l = 1 - if l > 9: l = 9 - z = gzip.GzipFile(filename=name, mode='w', compresslevel=l, fileobj=t) - z.write(d) - z.close() - d = t.getvalue() - t.close() - i = 0 - for b in d: - if not (i % 12): print >>outf, '\n ', - print >>outf, '0x%02x,' % ord(b), - i = i + 1 - print >>outf, '' - print >>outf, '};' - - print >>outf, 'static filebundle_entry_t filebundle_entry_%06d = {' % idx - print >>outf, ' .type = FB_FILE,' - print >>outf, ' .name = "%s",' % name - print >>outf, ' .next = %s,' % n - print >>outf, ' .f.size = %d,' % len(d) - print >>outf, ' .f.orig = %d,' % o - print >>outf, ' .f.data = filebundle_data_%06d,' % idx - print >>outf, '};' - print >>outf, '' - -# Output a directory -def output_dir ( path, name, idx, child, next = -1 ): - n = 'NULL' - if next >= 0: n = '&filebundle_entry_%06d' % next - print >>outf, '// DIR: %s %s %d %d %d' % (path, name, idx, child, next) - print >>outf, 'static filebundle_entry_t filebundle_entry_%06d = {' % idx - print >>outf, ' .type = FB_DIR,' - print >>outf, ' .name = "%s",' % name - print >>outf, ' .next = %s,' % n - print >>outf, ' .d.child = &filebundle_entry_%06d,' % child - print >>outf, '};' - print >>outf, '' - -# Create output -def add_entry ( ents, path = "", name = "", idx = -1, next = -1 ): - - # Add children - d = os.path.join(path, name) - p = -1 - for k in ents: - - # File - if not ents[k]: - output_file(d, k, idx+1, p) - p = idx = idx + 1 - - # Directory - else: - tmp = add_entry(ents[k], d, k, idx, p) - if tmp != idx: - p = idx = tmp - - # Add directory - if p >= 0: - if name: - output_dir(path, name, idx+1, p, next) - idx = idx + 1 - - return idx - -# Output header -print >>outf, '// Auto-generated - DO NOT EDIT' -print >>outf, '// COMMAND: [%s]' % (' '.join(sys.argv)) -print >>outf, '' -print >>outf, '#include "filebundle.h"' -print >>outf, '' - -# Output entries -idx = add_entry(ents) - -# Output top link -print >>outf, 'filebundle_entry_t *filebundle_root = &filebundle_entry_%06d;' % idx