Limit filesize for Timeshift on eMMC (<2GBytes)
[vuplus_dvbapp] / lib / base / filepush.cpp
index 91f24ba..5de9ef2 100644 (file)
@@ -1,12 +1,24 @@
 #include <lib/base/filepush.h>
 #include <lib/base/eerror.h>
+#include <lib/base/nconfig.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#include <sys/vfs.h>
+#if 0
+#include <dirent.h>
+#else
+#include <sys/types.h>
+#endif
 
 #define PVR_COMMIT 1
 
+#define MAJORSD_       8
+#define MAJORMMCBLK    179
+#define LIMIT_FILESIZE_NOHDD   2*1024*1024*1024LL      // 2GBytes
+
 //FILE *f = fopen("/log.ts", "wb");
+static bool g_is_diskfull = false;
 
 eFilePushThread::eFilePushThread(int io_prio_class, int io_prio_level, int blocksize)
        :prio_class(io_prio_class), prio(io_prio_level), m_messagepump(eApp, 0)
@@ -19,6 +31,7 @@ eFilePushThread::eFilePushThread(int io_prio_class, int io_prio_level, int block
        flush();
        enablePVRCommit(0);
        CONNECT(m_messagepump.recv_msg, eFilePushThread::recvEvent);
+       m_hdd_connected = false;
 }
 
 static void signal_handler(int x)
@@ -29,7 +42,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;
@@ -37,6 +50,39 @@ void eFilePushThread::thread()
        
        size_t written_since_last_sync = 0;
 
+       std::string tspath;
+       if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1) {
+               eDebug("could not query ts path from config");
+       }
+       tspath.append("/");
+
+#if 0
+       DIR *tsdir_info;
+       struct dirent *tsdir_entry;
+       tsdir_info = opendir("/sys/block");
+       if (tsdir_info != NULL) {
+               m_hdd_connected = false;
+               while (tsdir_entry = readdir(tsdir_info)) {
+                       if (strncmp(tsdir_entry->d_name, "sd", 2) == 0) {
+                               eDebug("HDD found: %s", tsdir_entry->d_name);
+                               m_hdd_connected = true;
+                               break;
+                       }
+               }
+       }
+#else
+       struct stat tspath_st;
+       if (stat(tspath.c_str(), &tspath_st) == 0) {
+               if (major(tspath_st.st_dev) == MAJORSD_) {
+                       eDebug("Timeshift location on HDD!");
+                       m_hdd_connected = true;
+               } else if (major(tspath_st.st_dev) == MAJORMMCBLK) {
+                       eDebug("Timeshift location on eMMC!");
+                       m_hdd_connected = false;
+               }
+       }
+#endif
+
        eDebug("FILEPUSH THREAD START");
        
                /* we set the signal to not restart syscalls, so we can detect our signal. */
@@ -46,9 +92,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)
        {
@@ -108,10 +152,19 @@ void eFilePushThread::thread()
 //                     eDebug("wrote %d bytes", w);
                        if (w <= 0)
                        {
-                               if (errno == EINTR || errno == EAGAIN || errno == EBUSY)
+                               if (w < 0 && (errno == EINTR || errno == EAGAIN || errno == EBUSY))
                                        continue;
                                eDebug("eFilePushThread WRITE ERROR");
                                sendEvent(evtWriteError);
+
+                               struct statfs fs;
+                               if (statfs(tspath.c_str(), &fs) < 0) {
+                                       eDebug("statfs failed!");
+                               }
+                               if ((off_t)fs.f_bavail < 1) {
+                                       eDebug("not enough diskspace for timeshift!");
+                                       g_is_diskfull = true;
+                               }
                                break;
                                // ... we would stop the thread
                        }
@@ -133,18 +186,29 @@ void eFilePushThread::thread()
                        continue;
                }
 
+               if (!m_hdd_connected) {
+                       struct stat limit_filesize;
+                       if (fstat(m_fd_dest, &limit_filesize) == 0) {
+                               if (limit_filesize.st_size > LIMIT_FILESIZE_NOHDD) {
+                                       eDebug("eFilePushThread %lld > %lld LIMIT FILESIZE", limit_filesize.st_size, LIMIT_FILESIZE_NOHDD);
+                                       sendEvent(evtWriteError);
+
+                                       g_is_diskfull = true;
+                                       break;
+                               }
+                       }
+               }
+
                        /* now fill our buffer. */
                        
                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 +221,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 +241,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,43 +277,50 @@ 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;
                }
 //             printf("FILEPUSH: read %d bytes\n", m_buf_end);
+
+               if (g_is_diskfull) {
+                       sendEvent(evtUser+3);
+                       g_is_diskfull = false;
+               }
        }
        fdatasync(m_fd_dest);
 
        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 +341,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;