diff options
Diffstat (limited to 'lib/base')
| -rw-r--r-- | lib/base/.gitignore | 1 | ||||
| -rw-r--r-- | lib/base/Makefile.am | 58 | ||||
| -rw-r--r-- | lib/base/console.h | 1 | ||||
| -rw-r--r-- | lib/base/eenv.cpp.in | 117 | ||||
| -rw-r--r-- | lib/base/eenv.h | 16 | ||||
| -rw-r--r-- | lib/base/encoding.cpp | 7 | ||||
| -rw-r--r-- | lib/base/etpm.cpp | 172 | ||||
| -rw-r--r-- | lib/base/etpm.h | 44 | ||||
| -rw-r--r-- | lib/base/filepush.cpp | 60 | ||||
| -rw-r--r-- | lib/base/filepush.h | 12 | ||||
| -rw-r--r-- | lib/base/itssource.h | 19 | ||||
| -rw-r--r-- | lib/base/rawfile.cpp | 27 | ||||
| -rw-r--r-- | lib/base/rawfile.h | 15 |
13 files changed, 489 insertions, 60 deletions
diff --git a/lib/base/.gitignore b/lib/base/.gitignore new file mode 100644 index 00000000..aa9ae18f --- /dev/null +++ b/lib/base/.gitignore @@ -0,0 +1 @@ +eenv.cpp diff --git a/lib/base/Makefile.am b/lib/base/Makefile.am index 6ea9d03f..d76dfc9e 100644 --- a/lib/base/Makefile.am +++ b/lib/base/Makefile.am @@ -1,12 +1,56 @@ -INCLUDES = \ - -I$(top_srcdir)/include +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/include \ + -include Python.h \ + -include $(top_builddir)/enigma2_config.h noinst_LIBRARIES = libenigma_base.a libenigma_base_a_SOURCES = \ - buffer.cpp ebase.cpp eerror.cpp elock.cpp \ - init.cpp message.cpp thread.cpp \ - smartptr.cpp estring.cpp connection.cpp \ - filepush.cpp encoding.cpp console.cpp rawfile.cpp \ - nconfig.cpp ioprio.cpp + buffer.cpp \ + connection.cpp \ + console.cpp \ + ebase.cpp \ + eenv.cpp \ + eerror.cpp \ + elock.cpp \ + encoding.cpp \ + estring.cpp \ + etpm.cpp \ + filepush.cpp \ + init.cpp \ + ioprio.cpp \ + message.cpp \ + nconfig.cpp \ + rawfile.cpp \ + smartptr.cpp \ + thread.cpp +EXTRA_DIST = \ + eenv.cpp.in + +baseincludedir = $(pkgincludedir)/lib/base +baseinclude_HEADERS = \ + buffer.h \ + console.h \ + ebase.h \ + eenv.h \ + eerror.h \ + elock.h \ + encoding.h \ + eptrlist.h \ + estring.h \ + etpm.h \ + filepush.h \ + i18n.h \ + itssource.h \ + init.h \ + init_num.h \ + ioprio.h \ + message.h \ + nconfig.h \ + object.h \ + rawfile.h \ + ringbuffer.h \ + smartptr.h \ + thread.h diff --git a/lib/base/console.h b/lib/base/console.h index e730b40e..60540da0 100644 --- a/lib/base/console.h +++ b/lib/base/console.h @@ -1,7 +1,6 @@ #ifndef __LIB_BASE_CONSOLE_H__ #define __LIB_BASE_CONSOLE_H__ -#include "Python.h" #include <string> #include <lib/base/ebase.h> #include <lib/python/connections.h> diff --git a/lib/base/eenv.cpp.in b/lib/base/eenv.cpp.in new file mode 100644 index 00000000..52c42147 --- /dev/null +++ b/lib/base/eenv.cpp.in @@ -0,0 +1,117 @@ +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <wordexp.h> +#include <lib/base/eenv.h> +#include <lib/base/eerror.h> + +bool eEnv::initialized = false; + +void eEnv::initialize() +{ + static const struct { + std::string name; + std::string value; + } cfgenv[] = { + { "prefix", "@prefix@" }, + { "exec_prefix", "@exec_prefix@" }, + { "bindir", "@bindir@" }, + { "sbindir", "@sbindir@" }, + { "libexecdir", "@libexecdir@" }, + { "datarootdir", "@datarootdir@" }, + { "datadir", "@datadir@" }, + { "sysconfdir", "@sysconfdir@" }, + { "sharedstatedir", "@sharedstatedir@" }, + { "localstatedir", "@localstatedir@" }, + { "libdir", "@libdir@" }, + { "localedir", "@localedir@" }, + }; + size_t i; + + // 1st pass, as generated by configure. + // Variables set by the user will not be overwritten. + for (i = 0; i < (sizeof(cfgenv) / sizeof(*cfgenv)); i++) { + eDebug("setenv('%s', '%s', 0)", cfgenv[i].name.c_str(), cfgenv[i].value.c_str()); + setenv(cfgenv[i].name.c_str(), cfgenv[i].value.c_str(), 0); + } + + // 2nd pass: Resolve directories. + for (i = 0; i < (sizeof(cfgenv) / sizeof(*cfgenv)); i++) { + std::string dest; + eEnv::resolveVar(dest, "${" + cfgenv[i].name + "}"); + eDebug("setenv('%s', '%s', 1)", cfgenv[i].name.c_str(), dest.c_str()); + setenv(cfgenv[i].name.c_str(), dest.c_str(), 1); + } +} + +int eEnv::resolveVar(std::string &dest, const char *src) +{ + size_t i = 0; + int ret; + wordexp_t p; + + ret = wordexp(src, &p, WRDE_NOCMD | WRDE_UNDEF); + if (ret != 0) { + switch (ret) { + case WRDE_BADCHAR: + eDebug("%s: bad character", __func__); + break; + case WRDE_BADVAL: + eDebug("%s: bad value", __func__); + break; + case WRDE_CMDSUB: + eDebug("%s: invalid command substitution", __func__); + break; + case WRDE_NOSPACE: + eDebug("%s: out of memory", __func__); + break; + case WRDE_SYNTAX: + eDebug("%s: syntax error", __func__); + break; + default: + eDebug("%s: unknown error", __func__); + break; + } + + return -1; + } + + while (i < p.we_wordc) { + if (strchr(p.we_wordv[i], '$')) { + ret = eEnv::resolveVar(dest, p.we_wordv[i]); + if (ret < 0) + break; + } else { + dest.append(p.we_wordv[i]); + } + + if (++i < p.we_wordc) + dest.append(" "); + } + + wordfree(&p); + return ret; +} + +int eEnv::resolveVar(std::string &dest, const std::string &src) +{ + return eEnv::resolveVar(dest, src.c_str()); +} + +std::string eEnv::resolve(const std::string &src) +{ + std::string dest; + + if (!initialized) { + eEnv::initialize(); + initialized = true; + } + + eDebug("%s: resolve %s", __func__, src.c_str()); + + eEnv::resolveVar(dest, src); + + eDebug("%s: -> %s", __func__, dest.c_str()); + + return dest; +} diff --git a/lib/base/eenv.h b/lib/base/eenv.h new file mode 100644 index 00000000..3d149f5e --- /dev/null +++ b/lib/base/eenv.h @@ -0,0 +1,16 @@ +#ifndef __lib_base_paths_h +#define __lib_base_paths_h + +#include <string> + +class eEnv { +private: + static bool initialized; + static void initialize(); + static int resolveVar(std::string &dest, const char *src); + static int resolveVar(std::string &dest, const std::string &src); +public: + static std::string resolve(const std::string &path); +}; + +#endif diff --git a/lib/base/encoding.cpp b/lib/base/encoding.cpp index 8b4b592b..361acce5 100644 --- a/lib/base/encoding.cpp +++ b/lib/base/encoding.cpp @@ -2,6 +2,7 @@ #include <cstdlib> #include <lib/base/encoding.h> #include <lib/base/eerror.h> +#include <lib/base/eenv.h> eDVBTextEncodingHandler encodingHandler; // the one and only instance @@ -17,8 +18,8 @@ inline char toupper(char c) eDVBTextEncodingHandler::eDVBTextEncodingHandler() { - const char * file=DATADIR "/enigma2/encoding.conf"; - FILE *f = fopen(file, "rt"); + std::string file = eEnv::resolve("${datadir}/enigma2/encoding.conf"); + FILE *f = fopen(file.c_str(), "rt"); if (f) { char *line = (char*) malloc(256); @@ -61,7 +62,7 @@ eDVBTextEncodingHandler::eDVBTextEncodingHandler() free(line); } else - eDebug("[eDVBTextEncodingHandler] couldn't open %s !", file); + eDebug("[eDVBTextEncodingHandler] couldn't open %s !", file.c_str()); } void eDVBTextEncodingHandler::getTransponderDefaultMapping(int tsidonid, int &table) diff --git a/lib/base/etpm.cpp b/lib/base/etpm.cpp new file mode 100644 index 00000000..9a443e0a --- /dev/null +++ b/lib/base/etpm.cpp @@ -0,0 +1,172 @@ +#include <sys/socket.h> +#include <fcntl.h> +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/un.h> +#include <unistd.h> +#include <openssl/bn.h> +#include <openssl/sha.h> +#include <lib/base/eerror.h> + +#include "etpm.h" + +eTPM::eTPM() +{ + struct sockaddr_un addr; + unsigned char buf[8]; + unsigned int tag; + size_t len; + unsigned char *val; + + level2_cert_read = level3_cert_read = false; + + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, TPMD_SOCKET); + + fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (fd < 0) + { + eDebug("[eTPM] socket error"); + return; + } + + if (connect(fd, (const struct sockaddr *)&addr, SUN_LEN(&addr)) < 0) + { + eDebug("[eTPM] connect error"); + return; + } + + buf[0] = TPMD_DT_LEVEL2_CERT; + buf[1] = TPMD_DT_LEVEL3_CERT; + if (!send_cmd(TPMD_CMD_GET_DATA, buf, 2)) + { + return; + } + + val = (unsigned char*)recv_cmd(&tag, &len); + if (val == NULL) + { + return; + } + + parse_data(val, len); + free(val); +} + +eTPM::~eTPM() +{ + +} + +bool eTPM::send_cmd(enum tpmd_cmd cmd, const void *data, size_t len) +{ + unsigned char buf[len + 4]; + + buf[0] = (cmd >> 8) & 0xff; + buf[1] = (cmd >> 0) & 0xff; + buf[2] = (len >> 8) & 0xff; + buf[3] = (len >> 0) & 0xff; + memcpy(&buf[4], data, len); + + if (write(fd, buf, sizeof(buf)) != (ssize_t)sizeof(buf)) + { + fprintf(stderr, "%s: incomplete write\n", __func__); + return false; + } + + return true; +} + +void* eTPM::recv_cmd(unsigned int *tag, size_t *len) +{ + unsigned char buf[4]; + void *val; + + if (read(fd, buf, 4) != 4) + { + fprintf(stderr, "%s: incomplete read\n", __func__); + return NULL; + } + + *tag = (buf[0] << 8) | buf[1]; + *len = (buf[2] << 8) | buf[3]; + + val = malloc(*len); + if (val == NULL) + return NULL; + + ssize_t rd = read(fd, val, *len); + if (rd < 0) + { + perror("eTPM::recv_cmd read"); + free(val); + } + else if ((size_t)rd != *len) { + fprintf(stderr, "%s: incomplete read\n", __func__); + free(val); + return NULL; + } + + return val; +} + +void eTPM::parse_data(const unsigned char *data, size_t datalen) +{ + unsigned int i; + unsigned int tag; + unsigned int len; + const unsigned char *val; + + for (i = 0; i < datalen; i += len) { + tag = data[i++]; + len = data[i++]; + val = &data[i]; + + switch (tag) { + case TPMD_DT_LEVEL2_CERT: + if (len != 210) + break; + memcpy(level2_cert, val, 210); + level2_cert_read = true; + break; + case TPMD_DT_LEVEL3_CERT: + if (len != 210) + break; + memcpy(level3_cert, val, 210); + level3_cert_read = true; + break; + } + } +} + +std::string eTPM::getCert(cert_type type) +{ + if (type == TPMD_DT_LEVEL2_CERT && level2_cert_read) + return std::string((char*)level2_cert, 210); + else if (type == TPMD_DT_LEVEL3_CERT && level3_cert_read) + return std::string((char*)level3_cert, 210); + return ""; +} + +std::string eTPM::challenge(std::string rnd) +{ + if (rnd.length() == 8) + { + if (!send_cmd(TPMD_CMD_COMPUTE_SIGNATURE, rnd.c_str(), 8)) + return ""; + + unsigned int tag; + size_t len; + unsigned char *val = (unsigned char*)recv_cmd(&tag, &len); + + if (tag != TPMD_CMD_COMPUTE_SIGNATURE) + return ""; + + std::string ret((char*)val, len); + free(val); + return ret; + } + return ""; +} diff --git a/lib/base/etpm.h b/lib/base/etpm.h new file mode 100644 index 00000000..c9e52140 --- /dev/null +++ b/lib/base/etpm.h @@ -0,0 +1,44 @@ +#ifndef __lib_base_etpm_h +#define __lib_base_etpm_h + +#ifndef SWIG +#define TPMD_SOCKET "/var/run/tpmd_socket" +#endif + +#include <string> + +class eTPM +{ +#ifndef SWIG + int fd; + unsigned char level2_cert[210]; + unsigned char level3_cert[210]; + bool level2_cert_read; + bool level3_cert_read; + + enum tpmd_cmd { + TPMD_CMD_RESERVED = 0x0000, + TPMD_CMD_GET_DATA = 0x0001, + TPMD_CMD_APDU = 0x0002, + TPMD_CMD_COMPUTE_SIGNATURE = 0x0003, + TPMD_CMD_APP_CERT = 0x0004, + }; + + bool send_cmd(enum tpmd_cmd cmd, const void *data, size_t len); + void *recv_cmd(unsigned int *tag, size_t *len); + void parse_data(const unsigned char *data, size_t datalen); + +#endif +public: + eTPM(); + ~eTPM(); + + enum cert_type { + TPMD_DT_LEVEL2_CERT = 0x04, + TPMD_DT_LEVEL3_CERT = 0x05 + }; + std::string getCert(cert_type type); + std::string challenge(std::string rnd); +}; + +#endif // __lib_base_etpm_h diff --git a/lib/base/filepush.cpp b/lib/base/filepush.cpp index 91f24ba0..e3e2a13a 100644 --- a/lib/base/filepush.cpp +++ b/lib/base/filepush.cpp @@ -29,7 +29,7 @@ void eFilePushThread::thread() { setIoPrio(prio_class, prio); - off_t dest_pos = 0, source_pos = 0; + off_t dest_pos = 0; size_t bytes_read = 0; off_t current_span_offset = 0; @@ -46,9 +46,7 @@ void eFilePushThread::thread() sigaction(SIGUSR1, &act, 0); hasStarted(); - - source_pos = m_raw_source.lseek(0, SEEK_CUR); - + /* m_stop must be evaluated after each syscall. */ while (!m_stop) { @@ -137,14 +135,12 @@ void eFilePushThread::thread() if (m_sg && !current_span_remaining) { - m_sg->getNextSourceSpan(source_pos, bytes_read, current_span_offset, current_span_remaining); + m_sg->getNextSourceSpan(m_current_position, bytes_read, current_span_offset, current_span_remaining); ASSERT(!(current_span_remaining % m_blocksize)); - - if (source_pos != current_span_offset) - source_pos = m_raw_source.lseek(current_span_offset, SEEK_SET); + m_current_position = current_span_offset; bytes_read = 0; } - + size_t maxread = sizeof(m_buffer); /* if we have a source span, don't read past the end */ @@ -157,9 +153,9 @@ void eFilePushThread::thread() m_buf_start = 0; m_filter_end = 0; m_buf_end = 0; - + if (maxread) - m_buf_end = m_raw_source.read(m_buffer, maxread); + m_buf_end = m_source->read(m_current_position, m_buffer, maxread); if (m_buf_end < 0) { @@ -177,10 +173,7 @@ void eFilePushThread::thread() /* a read might be mis-aligned in case of a short read. */ int d = m_buf_end % m_blocksize; if (d) - { - m_raw_source.lseek(-d, SEEK_CUR); m_buf_end -= d; - } if (m_buf_end == 0) { @@ -216,18 +209,10 @@ void eFilePushThread::thread() sleep(1); continue; } -#if 0 - eDebug("FILEPUSH: end-of-file! (currently unhandled)"); - if (!m_raw_source.lseek(0, SEEK_SET)) - { - eDebug("(looping)"); - continue; - } -#endif break; } else { - source_pos += m_buf_end; + m_current_position += m_buf_end; bytes_read += m_buf_end; if (m_sg) current_span_remaining -= m_buf_end; @@ -239,20 +224,30 @@ void eFilePushThread::thread() eDebug("FILEPUSH THREAD STOP"); } -void eFilePushThread::start(int fd_source, int fd_dest) +void eFilePushThread::start(int fd, int fd_dest) { - m_raw_source.setfd(fd_source); - m_fd_dest = fd_dest; - resume(); + eRawFile *f = new eRawFile(); + ePtr<iTsSource> source = f; + f->setfd(fd); + start(source, fd_dest); } -int eFilePushThread::start(const char *filename, int fd_dest) +int eFilePushThread::start(const char *file, int fd_dest) { - if (m_raw_source.open(filename) < 0) + eRawFile *f = new eRawFile(); + ePtr<iTsSource> source = f; + if (f->open(file) < 0) return -1; + start(source, fd_dest); + return 0; +} + +void eFilePushThread::start(ePtr<iTsSource> &source, int fd_dest) +{ + m_source = source; m_fd_dest = fd_dest; + m_current_position = 0; resume(); - return 0; } void eFilePushThread::stop() @@ -273,11 +268,6 @@ void eFilePushThread::pause() stop(); } -void eFilePushThread::seek(int whence, off_t where) -{ - m_raw_source.lseek(where, whence); -} - void eFilePushThread::resume() { m_stop = 0; diff --git a/lib/base/filepush.h b/lib/base/filepush.h index 71ee9979..a4457f67 100644 --- a/lib/base/filepush.h +++ b/lib/base/filepush.h @@ -24,9 +24,10 @@ public: void stop(); void start(int sourcefd, int destfd); int start(const char *filename, int destfd); - + + void start(ePtr<iTsSource> &source, int destfd); + void pause(); - void seek(int whence, off_t where); void resume(); /* flushes the internal readbuffer */ @@ -57,11 +58,12 @@ private: int m_send_pvr_commit; int m_stream_mode; int m_blocksize; + off_t m_current_position; + + ePtr<iTsSource> m_source; - eRawFile m_raw_source; - eFixedMessagePump<int> m_messagepump; - + void recvEvent(const int &evt); }; diff --git a/lib/base/itssource.h b/lib/base/itssource.h new file mode 100644 index 00000000..91167ff5 --- /dev/null +++ b/lib/base/itssource.h @@ -0,0 +1,19 @@ +#ifndef __lib_base_idatasource_h +#define __lib_base_idatasource_h + +#include <lib/base/object.h> + +class iTsSource: public iObject +{ +public: + /* NOTE: should only be used to get current position or filelength */ + virtual off_t lseek(off_t offset, int whence)=0; + + /* NOTE: you must be able to handle short reads! */ + virtual ssize_t read(off_t offset, void *buf, size_t count)=0; /* NOTE: this is what you in normal case have to use!! */ + + virtual off_t length()=0; + virtual int valid()=0; +}; + +#endif diff --git a/lib/base/rawfile.cpp b/lib/base/rawfile.cpp index c7e11feb..3a09e07e 100644 --- a/lib/base/rawfile.cpp +++ b/lib/base/rawfile.cpp @@ -4,7 +4,10 @@ #include <lib/base/rawfile.h> #include <lib/base/eerror.h> +DEFINE_REF(eRawFile); + eRawFile::eRawFile() + :m_lock(false) { m_fd = -1; m_file = 0; @@ -53,6 +56,13 @@ void eRawFile::setfd(int fd) off_t eRawFile::lseek(off_t offset, int whence) { + eSingleLocker l(m_lock); + m_current_offset = lseek_internal(offset, whence); + return m_current_offset; +} + +off_t eRawFile::lseek_internal(off_t offset, int whence) +{ // eDebug("lseek: %lld, %d", offset, whence); /* if there is only one file, use the native lseek - the file could be growing! */ if (m_nrfiles < 2) @@ -61,7 +71,8 @@ off_t eRawFile::lseek(off_t offset, int whence) return ::lseek(m_fd, offset, whence); else { - ::fseeko(m_file, offset, whence); + if (::fseeko(m_file, offset, whence) < 0) + perror("fseeko"); return ::ftello(m_file); } } @@ -100,11 +111,19 @@ int eRawFile::close() } } -ssize_t eRawFile::read(void *buf, size_t count) +ssize_t eRawFile::read(off_t offset, void *buf, size_t count) { -// eDebug("read: %p, %d", buf, count); + eSingleLocker l(m_lock); + + if (offset != m_current_offset) + { + m_current_offset = lseek_internal(offset, SEEK_SET); + if (m_current_offset < 0) + return m_current_offset; + } + switchOffset(m_current_offset); - + if (m_nrfiles >= 2) { if (m_current_offset + count > m_totallength) diff --git a/lib/base/rawfile.h b/lib/base/rawfile.h index a1c73d6a..7b736a33 100644 --- a/lib/base/rawfile.h +++ b/lib/base/rawfile.h @@ -2,24 +2,27 @@ #define __lib_base_rawfile_h #include <string> +#include <lib/base/itssource.h> -class eRawFile +class eRawFile: public iTsSource { + DECLARE_REF(eRawFile); + eSingleLock m_lock; public: eRawFile(); ~eRawFile(); - int open(const char *filename, int cached = 0); void setfd(int fd); - off_t lseek(off_t offset, int whence); int close(); - ssize_t read(void *buf, size_t count); /* NOTE: you must be able to handle short reads! */ + + // iTsSource + off_t lseek(off_t offset, int whence); + ssize_t read(off_t offset, void *buf, size_t count); off_t length(); int valid(); private: int m_fd; /* for uncached */ FILE *m_file; /* for cached */ - int m_cached; std::string m_basename; off_t m_splitsize, m_totallength, m_current_offset, m_base_offset, m_last_offset; @@ -27,6 +30,8 @@ private: void scan(); int m_current_file; int switchOffset(off_t off); + + off_t lseek_internal(off_t offset, int whence); FILE *openFileCached(int nr); int openFileUncached(int nr); }; |
