diff options
author | Rolf Ahrenberg <Rolf.Ahrenberg@sci.fi> | 2011-02-10 13:14:03 +0200 |
---|---|---|
committer | Dieter Hametner <dh (plus) vdr (at) gekrumbel (dot) de> | 2011-02-10 22:41:13 +0100 |
commit | 23562a42a5a5d776330b42823fe844493b574830 (patch) | |
tree | defa4a6843b930d7eaf37eef0428514c3bfc63dd /tools.cpp | |
parent | cbe61b644bffc891c339d74fffaaf2cc482720ea (diff) | |
download | vdr-plugin-live-23562a42a5a5d776330b42823fe844493b574830.tar.gz vdr-plugin-live-23562a42a5a5d776330b42823fe844493b574830.tar.bz2 |
Added support for renaming/moving recordings and for deleting multiple recordings at once.
Diffstat (limited to 'tools.cpp')
-rw-r--r-- | tools.cpp | 169 |
1 files changed, 169 insertions, 0 deletions
@@ -5,6 +5,7 @@ #include <tnt/htmlescostream.h> #include <tnt/httprequest.h> #include <tnt/httpreply.h> +#include <vdr/recording.h> #include "exception.h" #include "live.h" #include "setup.h" @@ -312,5 +313,173 @@ namespace vdrlive { return decoded; } + std::string FileSystemExchangeChars(std::string const & s, bool ToFileSystem) + { + char *str = strdup(s.c_str()); + str = ExchangeChars(str, ToFileSystem); + std::string data = str; + if (str) { + free(str); + } + return data; + } + + bool MoveDirectory(std::string const & sourceDir, std::string const & targetDir) + { + const char* delim = "/"; + std::string source = sourceDir; + std::string target = targetDir; + + // add missing directory delimiters + if (source.compare(source.size() - 1, 1, delim) != 0) { + source += "/"; + } + if (target.compare(target.size() - 1, 1, delim) != 0) { + target += "/"; + } + + if (source != target) { + // validate target directory + if (target.find(source) != std::string::npos) { + esyslog("[LIVE]: cannot move under sub-directory\n"); + return false; + } + RemoveFileOrDir(target.c_str()); + if (!MakeDirs(target.c_str(), true)) { + esyslog("[LIVE]: cannot create directory %s", target.c_str()); + return false; + } + + struct stat st1, st2; + stat(source.c_str(), &st1); + stat(target.c_str(),&st2); + if (st1.st_dev == st2.st_dev) { + if (!RenameVideoFile(source.c_str(), target.c_str())) { + esyslog("[LIVE]: rename failed from %s to %s", source.c_str(), target.c_str()); + return false; + } + } + else { + int required = DirSizeMB(source.c_str()); + int available = FreeDiskSpaceMB(target.c_str()); + + // validate free space + if (required < available) { + cReadDir d(source.c_str()); + struct dirent *e; + bool success = true; + + // allocate copying buffer + const int len = 1024 * 1024; + char *buffer = MALLOC(char, len); + if (!buffer) { + esyslog("[LIVE]: cannot allocate renaming buffer"); + return false; + } + + // loop through all files, but skip all subdirectories + while ((e = d.Next()) != NULL) { + // skip generic entries + if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..") && strcmp(e->d_name, "lost+found")) { + string sourceFile = source + e->d_name; + string targetFile = target + e->d_name; + + // copy only regular files + if (!stat(sourceFile.c_str(), &st1) && S_ISREG(st1.st_mode)) { + int r = -1, w = -1; + cUnbufferedFile *inputFile = cUnbufferedFile::Create(sourceFile.c_str(), O_RDONLY | O_LARGEFILE); + cUnbufferedFile *outputFile = cUnbufferedFile::Create(targetFile.c_str(), O_RDWR | O_CREAT | O_LARGEFILE); + + // validate files + if (!inputFile || !outputFile) { + esyslog("[LIVE]: cannot open file %s or %s", sourceFile.c_str(), targetFile.c_str()); + success = false; + break; + } + + // do actual copy + dsyslog("[LIVE]: copying %s to %s", sourceFile.c_str(), targetFile.c_str()); + do { + r = inputFile->Read(buffer, len); + if (r > 0) + w = outputFile->Write(buffer, r); + else + w = 0; + } while (r > 0 && w > 0); + DELETENULL(inputFile); + DELETENULL(outputFile); + + // validate result + if (r < 0 || w < 0) { + success = false; + break; + } + } + } + } + + // release allocated buffer + free(buffer); + + // delete all created target files and directories + if (!success) { + size_t found = target.find_last_of(delim); + if (found != std::string::npos) { + target = target.substr(0, found); + } + if (!RemoveFileOrDir(target.c_str(), true)) { + esyslog("[LIVE]: cannot remove target %s", target.c_str()); + } + found = target.find_last_of(delim); + if (found != std::string::npos) { + target = target.substr(0, found); + } + if (!RemoveEmptyDirectories(target.c_str(), true)) { + esyslog("[LIVE]: cannot remove target directory %s", target.c_str()); + } + esyslog("[LIVE]: copying failed"); + return false; + } + else if (!RemoveFileOrDir(source.c_str(), true)) { // delete source files + esyslog("[LIVE]: cannot remove source directory %s", source.c_str()); + return false; + } + + // delete all empty source directories + size_t found = source.find_last_of(delim); + if (found != std::string::npos) { + source = source.substr(0, found); + while (source != VideoDirectory) { + found = source.find_last_of(delim); + if (found == std::string::npos) + break; + source = source.substr(0, found); + if (!RemoveEmptyDirectories(source.c_str(), true)) + break; + } + } + } + else { + esyslog("[LIVE]: renaming requires %dMB - only %dMB available", required, available); + // delete all created empty target directories + size_t found = target.find_last_of(delim); + if (found != std::string::npos) { + target = target.substr(0, found); + while (target != VideoDirectory) { + found = target.find_last_of(delim); + if (found == std::string::npos) + break; + target = target.substr(0, found); + if (!RemoveEmptyDirectories(target.c_str(), true)) + break; + } + } + return false; + } + } + } + + return true; + } } // namespace vdrlive |