diff --git a/Makefile b/Makefile index a940b48..4062e7f 100644 --- a/Makefile +++ b/Makefile @@ -1,26 +1,30 @@ MAKE=gmake -DEFS= +DEFS=-DFOXSATPLATFORM -DFOXSATFILE +#DEFS= -DFOXSATFILE SRCS= descriptor.c \ epg.c \ file.c \ huffman.c \ main.c \ - util.c + util.c \ + epgsql.c HDRS= descriptor.h \ epg.h \ lint.h \ - util.h + util.h \ + epgsql.h OBJS= $(SRCS:.c=.o) -CC=gcc +#CC=gcc #CC=mipsel-linux-gcc -CFLAGS=-g +CC=mips-linux-gcc +CFLAGS=-g -pthread INCS= -LIBS= +LIBS=-lsqlite3 -ldl #CFLAGS=-g -O3 -fno-strict-aliasing #WARN=-pedantic -Wall -Wnested-externs -Wpointer-arith -Werror -Wno-unused WARN=-pedantic -Wall -W -Wnested-externs -Wpointer-arith -Wno-long-long diff --git a/descriptor.c b/descriptor.c index 535e34c..1e38893 100644 --- a/descriptor.c +++ b/descriptor.c @@ -298,6 +298,8 @@ content_type(struct descriptor *d) return "Education/Science/Factual"; case 0xa: return "Leisure"; + case 0xf: + return "Drama"; default: return "Undefined"; } diff --git a/descriptor.h b/descriptor.h index f1d274b..f54a363 100644 --- a/descriptor.h +++ b/descriptor.h @@ -10,7 +10,11 @@ #define DS_PRIVATE_DATA_SPECIFIER 95 #define DS_CONTENT_IDENTIFIER 118 #define DS_FTA_CONTENT_MGMT 126 +#ifdef FOXSATPLATFORM +#define DS_USER_DEFINED 218 +#else #define DS_USER_DEFINED 137 +#endif #define PARSER_SHORT_EVENT 0 #define PARSER_USER_DEFINED 1 @@ -26,8 +30,13 @@ #pragma pack(1) struct crid { +#ifdef FOXSATPLATFORM + unsigned int type:6; + unsigned int location:2; +#else unsigned int location:2; unsigned int type:6; +#endif unsigned int cridlen; char *crid; unsigned int ref:16; @@ -45,8 +54,13 @@ struct descriptor { char *text; } d77; /* SHORT_EVENT */ struct { +#ifdef FOXSATPLATFORM + unsigned int reserved:4; + unsigned int stream_content:4; +#else unsigned int stream_content:4; unsigned int reserved:4; +#endif unsigned int type:8; unsigned int tag:8; char lang[3]; @@ -54,8 +68,13 @@ struct descriptor { unsigned int textlen; } d80; /* COMPONENT */ struct { +#ifdef FOXSATPLATFORM + unsigned int level1:4; + unsigned int level2:4; +#else unsigned int level2:4; unsigned int level1:4; +#endif unsigned int user:8; } d84; /* CONTENT */ struct { @@ -78,16 +97,29 @@ struct descriptor { unsigned int linkage_type:8; union { struct { +#ifdef FOXSATPLATFORM + unsigned int handover_type:4; + unsigned int reserved:3; + unsigned int origin_type:1; + unsigned int id:16; +#else unsigned int origin_type:1; unsigned int reserved:3; unsigned int handover_type:4; unsigned int id:16; +#endif } l8; struct { unsigned int event_id:16; +#ifdef FOXSATPLATFORM + unsigned int listed:1; + unsigned int simulcast:1; + unsigned int reserved:6; +#else unsigned int reserved:6; unsigned int simulcast:1; unsigned int listed:1; +#endif } ld; } l; } d74; /* DS_LINKAGE */ diff --git a/epg.c b/epg.c index 4a5df3d..92da3f1 100644 --- a/epg.c +++ b/epg.c @@ -177,7 +177,11 @@ parse(char *epgpath, /* Skip this service. */ epg->offset += s->total_length - 14; /* Skip padding bytes... */ +#ifdef FOXSATFILE + while ((epg->offset % 4) != 0) +#else while (epg->bin[epg->offset] == 'U') +#endif epg->offset++; continue; } @@ -332,12 +336,15 @@ parse(char *epgpath, if (dslist[i]) free_descriptor(dslist[i]); } - /* Skip CRC */ epg->offset += 4; /* Skip padding bytes... */ +#ifdef FOXSATFILE + while ((epg->offset % 4) != 0) +#else while (epg->bin[epg->offset] == 'U') +#endif epg->offset++; } diff --git a/epg.h b/epg.h index a365d54..dbdb559 100644 --- a/epg.h +++ b/epg.h @@ -5,7 +5,11 @@ #include -#define DEFAULT_EPG_FILE "/mnt/hd1/dvbepg/epg.dat" +#ifdef FOXSATFILE + #define DEFAULT_EPG_FILE "/mnt/hd2/fsatepg/epg.dat" +#else + #define DEFAULT_EPG_FILE "/mnt/hd1/dvbepg/epg.dat" +#endif struct epg { char fname[MAXPATHLEN + 1]; @@ -15,26 +19,50 @@ struct epg { uint32_t binsize; }; -#define SECTION_MAGIC "(Gq\x87\x00\x00\x00\x00\x02\x00\x00\x00\x00\x01" +#ifdef FOXSATFILE + #define SECTION_MAGIC "\x19\x77\x09\x29\xff\xff" +#else + #define SECTION_MAGIC "(Gq\x87\x00\x00\x00\x00\x02\x00\x00\x00\x00\x01" +#endif #pragma pack(1) + + struct section { +#ifdef FOXSATFILE + char magic[6]; +#else char magic[14]; +#endif unsigned int total_length:16; +#ifndef FOXSATFILE unsigned int magic2:32; +#endif unsigned int table_id:8; union { struct { +#ifdef FOXSATPLATFORM + unsigned int syntax_indicator:1; + unsigned int reserved:3; + unsigned int length:12; +#else unsigned int length:12; unsigned int reserved:3; unsigned int syntax_indicator:1; +#endif } u; unsigned int comp:16; } u1; unsigned int service_id:16; +#ifdef FOXSATPLATFORM + unsigned int reserved2:2; + unsigned int version_number:5; + unsigned int current_next_indicator:1; +#else unsigned int current_next_indicator:1; unsigned int version_number:5; unsigned int reserved2:2; +#endif unsigned int section_number:8; unsigned int last_section_number:8; unsigned int transport_stream_id:16; @@ -55,9 +83,15 @@ struct data { unsigned int dur_sec:8; union { struct { +#ifdef FOXSATPLATFORM + unsigned int running_status:3; + unsigned int free_CA_mode:1; + unsigned int descriptors_loop_length:12; +#else unsigned int descriptors_loop_length:12; unsigned int free_CA_mode:1; unsigned int running_status:3; +#endif } u; unsigned int comp:16; } u1; diff --git a/epgsql.c b/epgsql.c new file mode 100644 index 0000000..9097096 --- /dev/null +++ b/epgsql.c @@ -0,0 +1,176 @@ +#include +#include +#include +#include "epgsql.h" +#include +#include +#include + +#include +#include +#include +#include + +static int callback(void *NotUsed, int argc, char **argv, char **azColName){ + int i; + for(i=0; i Create it if it doesn't exist + Return the Success/Failure status of the Open command + and the pointer to the opened DB */ + int rc; + + rc = sqlite3_open_v2(DBFile, &*db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); + + if( rc != SQLITE_OK){ + fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(*db)); + sqlite3_close(*db); + exit(1); + } + return 0; +} + +int CloseDB(sqlite3 *db) { + /* Close the database and return the result */ + return sqlite3_close(db); +} + +int InitDB(char * InitScript, sqlite3 *db) { + /* Use the database initialisation script to initialise the DB + Script should create tables if they don't already exist + And delete any data that will be replaced */ + int fp; + char *zErrMsg = 0; + int rc; + char * SQLStatement; + uint32_t SQLStatementSize; + struct stat st; + + /* Get the size of the init file */ + if (stat(InitScript, &st) == -1) + { + fprintf(stderr, "Error getting size of DB Creation/Initialisation File : %s\n", InitScript); + sqlite3_close(db); + exit(1); + } + SQLStatementSize = st.st_size; + + if ((fp = open(InitScript, O_RDONLY, 0)) == -1) + { + fprintf(stderr, "Failed to open DB Creation/Initialisation File : %s\n", InitScript); + sqlite3_close(db); + exit(1); + } + + SQLStatement = (char *)mmap(NULL, SQLStatementSize, PROT_READ, MAP_SHARED, fp, 0); + if (SQLStatement == MAP_FAILED) + { + fprintf(stderr, "Failed to MMAP the DB Creation File : %s\n", InitScript); + fprintf(stderr, "SQLStatement : %s, Map_failed : %i\n", SQLStatement, MAP_FAILED); + + close(fp); + sqlite3_close(db); + exit(1); + } + + rc = sqlite3_exec(db, SQLStatement, 0, 0, &zErrMsg); + + munmap((void *)SQLStatement, SQLStatementSize); + if (fp > 0) + close(fp); + + if( rc!=SQLITE_OK ){ + fprintf(stderr, "SQL error executing DB Init script : %s\n", zErrMsg); + fprintf(stderr, "RC = %i\n", rc); + sqlite3_free(zErrMsg); + sqlite3_close(db); + exit(1); + } + return 0; +} + +int ExecSQLStatement(char *SQL, sqlite3 *db) +{ + int rc; + char *zErrMsg = 0; + + rc = sqlite3_exec(db, SQL, 0, 0, &zErrMsg); + + if( rc!=SQLITE_OK ){ + fprintf(stderr, "SQL error executing script : %s\n", zErrMsg); + fprintf(stderr, "RC : %i\n", rc); + fprintf(stderr, "SQL : %s\n", SQL); + sqlite3_free(zErrMsg); + return 1; + } + return 0; +} + +/*int GetFileTimestamp(sqlite3 *db, char *res)*/ +void GetFileTimestamp(unsigned int * TS) +{ + sqlite3_stmt *pStmt; + char sql[256]={0}; + int rc; + int i; + sqlite3 *db1; + int KeepGoing=1; + + *TS = 0; + + rc = sqlite3_open_v2("/opt/epg/epg.db", &db1, SQLITE_OPEN_READWRITE, 0); + if( rc ){ + fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db1)); + sqlite3_close(db1); + exit(1); + } + + + sprintf(sql, "select lastfileprocessed from epgtimestamp limit 1;"); + + if (sqlite3_prepare_v2(db1, sql, strlen(sql), &pStmt, NULL) != SQLITE_OK) { + fprintf(stderr, "Error Preparing Statement : %s\n", sqlite3_errmsg(db1)); + exit(1); + } + + while (KeepGoing==1) { + rc = sqlite3_step(pStmt); + + switch (rc) { + case SQLITE_ROW: + /* know it will be one column and one row (due to the query) so + stuff the result into the result string */ + for (i=0; i<(sqlite3_column_count(pStmt)); i++) + *TS = strtoul((char*)sqlite3_column_text(pStmt, i), NULL, 10); + break; + case SQLITE_DONE: + KeepGoing=0; + break; + case SQLITE_ERROR: + fprintf(stderr, "Error Executing Statement : %s\n", sqlite3_errmsg(db1)); + KeepGoing=0; + break; + case SQLITE_BUSY: + case SQLITE_LOCKED: + fprintf(stderr, "In waiting loop ... %i\n", rc); + break; + default: + fprintf(stderr, "Error Condition ... %i\n", rc); + fprintf(stderr, "Error Executing Statement : %s\n", sqlite3_errmsg(db1)); + KeepGoing=0; + break; + } + } + + sqlite3_finalize(pStmt); + sqlite3_close(db1); +} + + + diff --git a/epgsql.h b/epgsql.h new file mode 100644 index 0000000..07c9573 --- /dev/null +++ b/epgsql.h @@ -0,0 +1,10 @@ +#include + +static int callback(void *NotUsed, int argc, char **argv, char **azColName); +int OpenCreateDB(char * DBFile, sqlite3 **db); +int CloseDB(sqlite3 *db); +int InitDB(char * InitScript, sqlite3 *db); +int ExecSQLStatement(char *SQL, sqlite3 *db); +void GetFileTimestamp(unsigned int *); + + diff --git a/huffman.c b/huffman.c index 951df2e..a07689d 100644 --- a/huffman.c +++ b/huffman.c @@ -1,14 +1,6 @@ /* * Humax EPG Tool - * by af123, 2011 - 2018 - * - * These tables and the decompression code are derived from MythTV - * https://github.com/MythTV/mythtv/tree/master/mythtv/libs/libmythtv/mpeg - * freesat_tables.h and freesat_huffman.cpp - * - * MythTV is released as free open source software under version 2 or later - * of the GPL (GNU General Public License) a copy of which can be viewed at - * https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html + * by af123, 2011 */ #include @@ -22,6 +14,12 @@ #include "lint.h" +/* + * These tables and the decompression code are taken/derived from MythTV + * https://github.com/MythTV/mythtv/tree/master/mythtv/libs/libmythtv/mpeg + * freesat_tables.h and freesat_huffman.cpp + */ + struct fsattab { unsigned int value; short bits; diff --git a/main.c b/main.c index 0ed11d6..44439ad 100644 --- a/main.c +++ b/main.c @@ -15,16 +15,22 @@ #include #include #include "lint.h" +#include +#include "epgsql.h" +#include "sys/stat.h" +#include int debug = 0; -const char *version = "1.0.2"; +const char *version = "1.3"; unsigned long sysopts = 0; unsigned long filterflags = 0; int syntax() { - fprintf(stderr, "Humax EPG Tool v%s, by af123, 2011.\n\n", version); + fprintf(stderr, "Humax Foxsat EPG Tool v%s, by adrianf36, 2011-2016.\n", version); + fprintf(stderr, "based on the Humax (T2) EPG Tool from af123 v1.0.2, 2011.\n\n"); + fprintf(stderr, "Syntax: epg [options] [filters] ...\n\n"); fprintf(stderr, @@ -51,6 +57,11 @@ syntax() " Commands:\n" " dump Show a parsed summary of the EPG.\n" " dumpraw Show raw data from the EPG.\n" + " dumpsql Process the EPG file into a Sqlite Database\n" + " dumpsqlcont As 'dumpsql' but run continuously\n" + " Check for updated data every hour and process if necessary\n" + ); + fprintf(stderr, " now Show what is currently on.\n" " parse Parse the EPG, no output.\n" " search Search programme names for text.\n" @@ -62,7 +73,85 @@ syntax() } #define DECOMPRESS(str, len) \ - if (*(str) == 0x1f) uncompress_epg(&(str), &(len)) + if (str && *(str) == 0x1f) uncompress_epg(&(str), &(len)) + +unsigned int NeedToProcess (char * epgFile) +{ + struct stat epgstat; + unsigned int FileTS; + unsigned int DBTS; + FILE * fp; + + /* Get the timestamp of the epg file to be processed */ + if ((fp = fopen(epgFile, "r"))) { + if (!stat(epgFile, &epgstat)) + { + FileTS = (unsigned int) (epgstat.st_mtime); + } else { + fprintf(stderr, "Error getting epg file modified date\n"); + return 0; + } + } else { + fprintf(stderr, "Input file (%s) does not exist!\n", epgFile); + return 0; + } + + /* Get the timestamp of the last file processed from the DB */ + GetFileTimestamp(&DBTS); + +/* + printf("File Timestamp : %i\n", FileTS); + printf("DB Timestamp : %i\n", DBTS); +*/ + if (FileTS==DBTS) + return 0; + else + return FileTS; +} + +void SwapEPGFiles() +{ +/* + Having built the new EPG file as epgnew.db delete the old one + and replace it with the new one. Handle the case where the old + one can't be deleted because it's being accessed + + First thing make sure that the size of the new file looks sensible. + Expect this to be > 10MB ..... usually it's about 12MB +*/ + +struct stat epgstat; +off_t fsize; +FILE * fp; + + if ((fp = fopen("/opt/epg/epgnew.db", "r"))) { + if (!stat("/opt/epg/epgnew.db", &epgstat)) + { + fsize = epgstat.st_size; + if (fsize > (10 * 1024 * 1024)) { + while (remove("/opt/epg/epg.db") == -1) + { + sleep(5); + } + + while (rename("/opt/epg/epgnew.db", "/opt/epg/epg.db") != 0) + { + sleep(5); + } + } else { + /* epgnew.db is smaller than we expected and is probably incomplete. + Delete it and output a warning. + */ + fprintf(stderr, "Error. epgnew.db file size too small. Probably corrupt.\n"); + remove("/opt/epg/epgnew.db"); + } + } else { + fprintf(stderr, "Error getting epgnew.db file size\n"); + } + } else { + fprintf(stderr, "Can't open epgnew.db\n"); + } +} void pass(struct epg *epg __attribute__((unused)), @@ -99,6 +188,205 @@ dumpraw(struct epg *epg __attribute__((unused)), /* Strings should all be safe now the huffman module is in place... */ #define safeprintf printf +void EscapeChars(char ** InString, unsigned int *Len) +{ + /* Escape String for inserting into SQLite */ + /* Replace single quote ' with two single quotes '' */ + char * new; + unsigned int i,j; + int charcount=0; + char * originalstring; + + originalstring=*InString; + if (strchr(*InString, '\'')!=NULL) { + /* at least one ' character - process string */ + /* count them so we know how much space to allocate */ + for (i=0; i<*Len; i++) { + if (originalstring[i]==0x27) { + charcount++; + } + } + new = (char *) malloc(sizeof(char) * (*Len + charcount + 1)); + j=0; + for (i=0; i<*Len; i++) { + new[j++]=originalstring[i]; + if (originalstring[i]==0x27) + new[j++]=0x27; + } + new[j]='\0'; + + free(*InString); + *InString = new; + *Len = strlen(new); + } +} + +void +dumpsql(struct epg *epg __attribute__((unused)), + struct section *s, struct data *d, struct descriptor **ds, + void *var) +{ + time_t tm; + char SQLStatement[5000]; + sqlite3 * db = (sqlite3 *)var; + int rc; + + tm = mjd(d->start_date, d->start_hour, d->start_min, d->start_sec); + + if (ds[PARSER_SHORT_EVENT]) + { + struct descriptor *d77 = ds[PARSER_SHORT_EVENT]; + DECOMPRESS(d77->content.d77.name, d77->content.d77.namelen); + DECOMPRESS(d77->content.d77.text, d77->content.d77.textlen); + EscapeChars(&d77->content.d77.name, &d77->content.d77.namelen); + EscapeChars(&d77->content.d77.text, &d77->content.d77.textlen); + } + if (ds[PARSER_USER_DEFINED]) + { + struct descriptor *d = ds[PARSER_USER_DEFINED]; + DECOMPRESS(d->content.d137.warning, d->content.d137.warninglen); + EscapeChars(&d->content.d137.warning, &d->content.d137.warninglen); + } + + /* service_id, event_id, start, duration, encrypted, name, text + * warning, content code, content type, + * event CRID, series CRID, rec CRID + */ + sprintf(SQLStatement,"insert into epg (serviceid, eventid, starttime, duration, encrypted, name,"\ + "descr, warning, contentcode, contenttype, ECRID, SCRID, RCRID) values ("); + sprintf(SQLStatement, "%s%d,%d,%ld,%d,%d,", SQLStatement, + s->service_id, d->event_id, tm, + d->dur_hour * 3600 + d->dur_min * 60 + d->dur_sec, + d->u1.u.free_CA_mode); + if (ds[PARSER_SHORT_EVENT]) + { + struct descriptor *d77 = ds[PARSER_SHORT_EVENT]; + sprintf(SQLStatement,"%s'%.*s',", SQLStatement, d77->content.d77.namelen, d77->content.d77.name); + sprintf(SQLStatement,"%s'%.*s',", SQLStatement, d77->content.d77.textlen, d77->content.d77.text); + } + else + sprintf(SQLStatement,"%s'','',",SQLStatement); + + if (ds[PARSER_USER_DEFINED]) + { + struct descriptor *d137 = ds[PARSER_USER_DEFINED]; + EscapeChars(&d137->content.d137.warning, &d137->content.d137.warninglen); + sprintf(SQLStatement,"%s'%.*s',", SQLStatement, d137->content.d137.warninglen, d137->content.d137.warning); + } + else + sprintf(SQLStatement,"%s'',",SQLStatement); + + if (ds[PARSER_CONTENT]) + { + sprintf(SQLStatement,"%s%d,", SQLStatement, ds[PARSER_CONTENT]->content.d84.level1); + sprintf(SQLStatement,"%s'%s',", SQLStatement, content_type(ds[PARSER_CONTENT])); + } + else + sprintf(SQLStatement,"%s0,'',",SQLStatement); + + if (ds[PARSER_CRID_EVENT]) + { + struct descriptor *d = ds[PARSER_CRID_EVENT]; + EscapeChars(&d->content.d118.crids[0].crid, &d->content.d118.crids[0].cridlen); + sprintf(SQLStatement,"%s'%.*s',", SQLStatement, d->content.d118.crids[0].cridlen, + d->content.d118.crids[0].crid); + } + else + sprintf(SQLStatement,"%s'',",SQLStatement); + + if (ds[PARSER_CRID_SERIES]) + { + struct descriptor *d = ds[PARSER_CRID_SERIES]; + EscapeChars(&d->content.d118.crids[0].crid, &d->content.d118.crids[0].cridlen); + sprintf(SQLStatement,"%s'%.*s',", SQLStatement, d->content.d118.crids[0].cridlen, + d->content.d118.crids[0].crid); + } + else + sprintf(SQLStatement,"%s'',",SQLStatement); + + if (ds[PARSER_CRID_REC]) + { + struct descriptor *d = ds[PARSER_CRID_REC]; + EscapeChars(&d->content.d118.crids[0].crid, &d->content.d118.crids[0].cridlen); + sprintf(SQLStatement,"%s'%.*s'", SQLStatement, d->content.d118.crids[0].cridlen, + d->content.d118.crids[0].crid); + } + else + sprintf(SQLStatement,"%s''",SQLStatement); + + sprintf(SQLStatement,"%s)",SQLStatement); + rc = ExecSQLStatement(SQLStatement, db); + return; +} + +void dosqldump(char * epgpath,struct epgfilter *filter, int Continuous) +{ + sqlite3 * db; + int rc; + unsigned int FileTS; + char SQL [500] = {0}; + + if (Continuous==1) { + while (1) { + FileTS = NeedToProcess(epgpath); + if (FileTS !=0) { + /* Delete any old epgnew SQLite files before trying to open a new one */ + /* Don't worry about error handling - just need to make sure they're gone! */ + remove("/opt/epg/epgnew.db"); + remove("/opt/epg/epgnew.db-journal"); + rc = OpenCreateDB("/opt/epg/epgnew.db", &db); + + rc = ExecSQLStatement("pragma journal_mode = off;", db); + rc = ExecSQLStatement("pragma synchronous = off;", db); + + InitDB("/opt/epg/epgDBinit.sql", db); + + rc = ExecSQLStatement("BEGIN;", db); + + parse(epgpath, dumpsql, (void *)db, filter); + + rc = ExecSQLStatement("COMMIT;", db); + + sprintf(SQL, "replace into epgtimestamp (lastfileprocessed) values (%i);", FileTS); + rc = ExecSQLStatement("Delete from epgtimestamp;", db); + rc = ExecSQLStatement(SQL, db); + + if (db != NULL) CloseDB(db); + SwapEPGFiles(); + } + + sleep(3600); + } + } else { + + FileTS = NeedToProcess(epgpath); + + if (FileTS != 0) { + + /* Delete any old epgnew SQLite files before trying to open a new one */ + /* Don't worry about error handling - just need to make sure they're gone! */ + remove("/opt/epg/epgnew.db"); + remove("/opt/epg/epgnew.db-journal"); + rc = OpenCreateDB("/opt/epg/epgnew.db", &db); + + InitDB("/opt/epg/epgDBinit.sql", db); + + rc = ExecSQLStatement("BEGIN;", db); + + parse(epgpath, dumpsql, (void *)db, filter); + + rc = ExecSQLStatement("COMMIT;", db); + + sprintf(SQL, "replace into epgtimestamp (lastfileprocessed) values (%i);", FileTS); + rc = ExecSQLStatement("Delete from epgtimestamp;", db); + rc = ExecSQLStatement(SQL, db); + + if (db != NULL) CloseDB(db); + SwapEPGFiles(); + } + } +} + void dump(struct epg *epg __attribute__((unused)), struct section *s, struct data *d, struct descriptor **ds, @@ -453,6 +741,8 @@ nextopt: parse(epgpath, pass, NULL, filter); else if (!strcmp(argv[0], "dumpraw")) parse(epgpath, dumpraw, NULL, filter); + else if (!strcmp(argv[0], "dumpsql")) + dosqldump(epgpath, filter, 0); else if (!strcmp(argv[0], "now")) { time_t tm; @@ -465,9 +755,16 @@ nextopt: parse(epgpath, search, (void *)argv[1], filter); else if (!strcmp(argv[0], "searchall") && argc > 1) parse(epgpath, searchall, (void *)argv[1], filter); + else if (!strcmp(argv[0], "dumpsqlcont")) + { + dosqldump(epgpath, filter, 1); + + } else syntax(); return 0; } + + diff --git a/util.h b/util.h index 0fe6b2f..8752676 100644 --- a/util.h +++ b/util.h @@ -6,7 +6,11 @@ /* Works for modern dates, 1970 - 2038 */ #define MJD_TO_UNIX(xx) (((xx) - 40587) * 86400) -#define _swap16(v) ((((v) >> 8) & 0xff) | (((v) & 0xff) << 8)) +#ifdef FOXSATPLATFORM + #define _swap16(v) (v) +#else + #define _swap16(v) ((((v) >> 8) & 0xff) | (((v) & 0xff) << 8)) +#endif #define bcd(v) (((((v) >> 4) & 0xf) * 10) + ((v) & 0xf))