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)
* 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
{
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
* *************************************************************************/
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;
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;
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
* *************************************************************************/
/* Open */
ret = fb_open2(dir, pos+1, decompress, compress);
+ fb_closedir(dir);
free(tmp);
return ret;
}
/* 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);
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);
#include <dirent.h>
#include <stdio.h>
+/* Bundle or Direct */
+typedef enum filebundle_handle_type
+{
+ FB_BUNDLE,
+ FB_DIRECT
+} fb_type;
+
/* File bundle entry type */
enum filebundle_type
{
const char *name;
union {
struct {
+ size_t count;
struct filebundle_entry *child;
} d;
struct {
/* 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;
/* 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
#include "htsmsg_json.h"
#include "settings.h"
#include "tvheadend.h"
+#include "filebundle.h"
static char *settingspath;
return settingspath ?: "No settings dir";
}
-
/**
*
*/
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) {
}
}
+/**
+ *
+ */
+static int
+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;
+
+ vsnprintf(tmp, sizeof(tmp), fmt, ap);
+ if (*tmp != '/' && prefix)
+ snprintf(dst, dstsize, "%s/%s", prefix, tmp);
+ else
+ strncpy(dst, tmp, dstsize);
+
+ while(*n) {
+ if(*n == ':' || *n == '?' || *n == '*' || *n > 127 || *n < 32)
+ *n = '_';
+ n++;
+ }
+}
/**
*
hts_settings_save(htsmsg_t *record, const char *pathfmt, ...)
{
char path[256];
- char fullpath[256];
- char fullpath2[256];
- int x, l, fd;
+ char tmppath[256];
+ int fd;
va_list ap;
- struct stat st;
htsbuf_queue_t hq;
htsbuf_data_t *hd;
- char *n;
int ok;
if(settingspath == NULL)
return;
+ /* Clean the 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;
- }
- path[x] = '/';
- }
- }
-
- snprintf(fullpath, sizeof(fullpath), "%s/%s.tmp", settingspath, path);
+ /* Create directories */
+ if (hts_settings_makedirs(path)) return;
- if((fd = tvh_open(fullpath, O_CREAT | O_TRUNC | O_RDWR, 0700)) < 0) {
+ /* 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",
- fullpath, strerror(errno));
+ 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",
- fullpath, strerror(errno));
+ tmppath, 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);
+
+ /* Move */
+ if(ok) {
+ rename(tmppath, path);
+
+ /* Delete tmp */
+ } else
+ unlink(tmppath);
}
/**
static htsmsg_t *
hts_settings_load_one(const char *filename)
{
- struct stat st;
- int fd;
+ ssize_t n;
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;
+ fb_file *fp;
+ htsmsg_t *r = NULL;
- n = read(fd, mem, st.st_size);
- close(fd);
- if(n == st.st_size)
+ /* 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);
- else
- r = NULL;
-
free(mem);
return r;
/**
*
*/
-static int
-hts_settings_buildpath(char *dst, size_t dstsize, const char *fmt, va_list ap)
-{
- 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);
- else
- strncpy(dst, tmp, dstsize);
-
- while(*n) {
- if(*n == ':' || *n == '?' || *n == '*' || *n > 127 || *n < 32)
- *n = '_';
- n++;
- }
- return 0;
-}
-
-/**
- *
- */
-htsmsg_t *
-hts_settings_load(const char *pathfmt, ...)
+static htsmsg_t *
+_hts_settings_load(const char *fullpath)
{
- char fullpath[256];
char child[256];
- va_list ap;
- struct stat st;
- struct dirent **namelist, *d;
+ struct filebundle_stat st;
+ fb_dirent **namelist, *d;
htsmsg_t *r, *c;
int n, i;
- va_start(ap, pathfmt);
- if(hts_settings_buildpath(fullpath, sizeof(fullpath), pathfmt, ap) < 0)
- return NULL;
-
- if(stat(fullpath, &st) != 0)
- return NULL;
+ /* Invalid */
+ if (fb_stat(fullpath, &st)) return NULL;
- if(S_ISDIR(st.st_mode)) {
+ /* Directory */
+ if (st.is_dir) {
- if((n = scandir(fullpath, &namelist, NULL, NULL)) < 0)
+ /* Get file list */
+ if((n = fb_scandir(fullpath, &namelist)) < 0)
return NULL;
-
- r = htsmsg_create_map();
+ /* Read files */
+ 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);
+ 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;
}
+/**
+ *
+ */
+htsmsg_t *
+hts_settings_load(const char *pathfmt, ...)
+{
+ htsmsg_t *ret = NULL;
+ char fullpath[256];
+ va_list ap;
+
+ /* Try normal path */
+ va_start(ap, pathfmt);
+ hts_settings_buildpath(fullpath, sizeof(fullpath),
+ pathfmt, ap, settingspath);
+ va_end(ap);
+ ret = _hts_settings_load(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 ret;
+}
+
/**
*
*/
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);
}
-
/**
*
*/
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);
}
-#!/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 <http://www.gnu.org/licenses/>.
+# Replacement for old mkbundle script that creates a full file heirarchy
#
-set -u # Fail on undefined vars
-
-READER="cat"
-SOURCE=
-DEPFILE=
-OUTPUT=
-PREFIX=
-COMPRESS=false
-usage()
-{
-cat << EOF
-usage: $0 options
-
-Generate a filebundle .c-file from a directory
-
-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
-}
-
-
-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
-
-
-if [[ -z $SOURCE ]] || [[ -z $OUTPUT ]] || [[ -z $PREFIX ]]; then
- usage
- exit 1
-fi
-
-FILES=`find "${SOURCE}" \( \( -name .svn -or -name *~ \) -and -prune \) -or -printf "%P "`
-
-echo >${OUTPUT} "// auto-generated by $0"
-
-for file in $FILES; do
-
- if [ -f ${SOURCE}/$file ]; then
-
- 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
-
-echo >>${OUTPUT} "#include <filebundle.h>"
-echo >>${OUTPUT} "static const struct filebundle_entry filebundle_entries[] = {"
-[[ -z $DEPFILE ]] || echo >${DEPFILE} -n "${OUTPUT}: "
-
-for file in $FILES; do
- [[ -z $DEPFILE ]] || echo >>${DEPFILE} -n "${SOURCE}/$file "
-
- 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} <<EOF
-
-static struct filebundle fb = {
- .entries = &filebundle_entries[0],
- .prefix = "${PREFIX}"
-};
-
-static void __attribute__((constructor)) filebundle_init(void)
-{
- extern struct filebundle *filebundles;
-
- fb.next = filebundles;
- filebundles = &fb;
-}
-
-EOF
\ No newline at end of file
+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, 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, ''
+
+# Create output
+def add_entry ( ents, path = "", name = "", idx = -1, next = -1 ):
+
+ # 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
+
+ # Add directory
+ if p >= 0:
+ if name:
+ output_dir(path, name, idx+1, p, c, 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
+++ /dev/null
-#!/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