diff --git a/HISTORY b/HISTORY index 83f31aca..a1cb40c6 100644 --- a/HISTORY +++ b/HISTORY @@ -7235,7 +7235,7 @@ Video Disk Recorder Revision History function in order to make use of this new feature. See, for instance, the function cSkinClassicDisplayMenu::SetButtons() in skinclassic.c for details. -2012-09-29: Version 1.7.31 +2012-09-30: Version 1.7.31 - If regenerating an index file fails and no data is written to the file, VDR now reports this error and removes the empty index file. @@ -7264,3 +7264,10 @@ Video Disk Recorder Revision History - Fixed sorting folders before recordings in case of UTF-8 (thanks to Sören Moch). - Reactivated stripping control characters from EPG texts and adapted it to UTF-8. - Added missing decrementing of 'len' in libsi/si.c's String::decodeText() functions. +- When checking whether a video directory is empty, file names that start with a + dot ('.') are no longer automatically ignored and implicitly removed if the directory + contains no other files. Instead, RemoveEmptyDirectories() now has an additional + parameter that can be given a list of files that shall be ignored when considering + whether a directory is empty. This allows users to continue to use files such as + ".keep" to prevent a directory from being deleted when it is empty. Currently the + only file name that is ignored is ".sort". diff --git a/recording.c b/recording.c index dc77a84c..1eeb82d0 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.c 2.63 2012/09/29 10:04:55 kls Exp $ + * $Id: recording.c 2.64 2012/09/30 13:05:14 kls Exp $ */ #include "recording.h" @@ -107,8 +107,10 @@ void cRemoveDeletedRecordingsThread::Action(void) } r = DeletedRecordings.Next(r); } - if (deleted) - RemoveEmptyVideoDirectories(); + if (deleted) { + const char *IgnoreFiles[] = { SORTMODEFILE, NULL }; + RemoveEmptyVideoDirectories(IgnoreFiles); + } } } diff --git a/tools.c b/tools.c index 3d9c513c..26c325b6 100644 --- a/tools.c +++ b/tools.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.c 2.25 2012/08/21 10:34:37 kls Exp $ + * $Id: tools.c 2.26 2012/09/30 13:04:14 kls Exp $ */ #include "tools.h" @@ -285,6 +285,18 @@ int64_t StrToNum(const char *s) return n; } +bool StrInArray(const char *a[], const char *s) +{ + if (a) { + while (*a) { + if (strcmp(*a, s) == 0) + return true; + a++; + } + } + return false; +} + cString AddDirectory(const char *DirName, const char *FileName) { return cString::sprintf("%s/%s", DirName && *DirName ? DirName : ".", FileName); @@ -433,9 +445,9 @@ bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks) return true; } -bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis) +bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis, const char *IgnoreFiles[]) { - bool HasDotFiles = false; + bool HasIgnoredFiles = false; cReadDir d(DirName); if (d.Ok()) { bool empty = true; @@ -446,11 +458,11 @@ bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis) struct stat st; if (stat(buffer, &st) == 0) { if (S_ISDIR(st.st_mode)) { - if (!RemoveEmptyDirectories(buffer, true)) + if (!RemoveEmptyDirectories(buffer, true, IgnoreFiles)) empty = false; } - else if (*e->d_name == '.') // "dot files" don't count - HasDotFiles = true; + else if (RemoveThis && IgnoreFiles && StrInArray(IgnoreFiles, e->d_name)) + HasIgnoredFiles = true; else empty = false; } @@ -461,21 +473,18 @@ bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis) } } if (RemoveThis && empty) { - if (HasDotFiles) { - cReadDir d(DirName); - if (d.Ok()) { - struct dirent *e; - while ((e = d.Next()) != NULL) { - if (*e->d_name == '.') { // for safety - should always be true - cString buffer = AddDirectory(DirName, e->d_name); - dsyslog("removing %s", *buffer); - if (remove(buffer) < 0) { - LOG_ERROR_STR(*buffer); - return false; - } + if (HasIgnoredFiles) { + while (*IgnoreFiles) { + cString buffer = AddDirectory(DirName, *IgnoreFiles); + if (access(buffer, F_OK) == 0) { + dsyslog("removing %s", *buffer); + if (remove(buffer) < 0) { + LOG_ERROR_STR(*buffer); + return false; } } - } + IgnoreFiles++; + } } dsyslog("removing %s", DirName); if (remove(DirName) < 0) { diff --git a/tools.h b/tools.h index b73448d3..3e546a17 100644 --- a/tools.h +++ b/tools.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.h 2.21 2012/05/20 13:58:06 kls Exp $ + * $Id: tools.h 2.22 2012/09/30 11:02:21 kls Exp $ */ #ifndef __TOOLS_H @@ -213,6 +213,9 @@ int64_t StrToNum(const char *s); ///< K, M, G or T to abbreviate Kilo-, Mega-, Giga- or Terabyte, respectively ///< (based on 1024). Everything after the first non-numeric character is ///< silently ignored, as are any characters other than the ones mentioned here. +bool StrInArray(const char *a[], const char *s); + ///< Returns true if the string s is equal to one of the strings pointed + ///< to by the (NULL terminated) array a. cString itoa(int n); cString AddDirectory(const char *DirName, const char *FileName); bool EntriesOnSameFileSystem(const char *File1, const char *File2); @@ -220,7 +223,12 @@ int FreeDiskSpaceMB(const char *Directory, int *UsedMB = NULL); bool DirectoryOk(const char *DirName, bool LogErrors = false); bool MakeDirs(const char *FileName, bool IsDirectory = false); bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks = false); -bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis = false); +bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis = false, const char *IgnoreFiles[] = NULL); + ///< Removes all empty directories under the given directory DirName. + ///< If RemoveThis is true, DirName will also be removed if it is empty. + ///< IgnoreFiles can be set to an array of file names that will be ignored when + ///< considering whether a directory is empty. If IgnoreFiles is given, the array + ///< must end with a NULL pointer. int DirSizeMB(const char *DirName); ///< returns the total size of the files in the given directory, or -1 in case of an error char *ReadLink(const char *FileName); ///< returns a new string allocated on the heap, which the caller must delete (or NULL in case of an error) bool SpinUpDisk(const char *FileName); diff --git a/videodir.c b/videodir.c index c64a5c65..d39ab051 100644 --- a/videodir.c +++ b/videodir.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: videodir.c 2.3 2012/09/01 10:57:44 kls Exp $ + * $Id: videodir.c 2.4 2012/09/30 12:06:33 kls Exp $ */ #include "videodir.h" @@ -229,11 +229,11 @@ cString PrefixVideoFileName(const char *FileName, char Prefix) return NULL; } -void RemoveEmptyVideoDirectories(void) +void RemoveEmptyVideoDirectories(const char *IgnoreFiles[]) { cVideoDirectory Dir; do { - RemoveEmptyDirectories(Dir.Name()); + RemoveEmptyDirectories(Dir.Name(), false, IgnoreFiles); } while (Dir.Next()); } diff --git a/videodir.h b/videodir.h index 40d7b058..a25ac319 100644 --- a/videodir.h +++ b/videodir.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: videodir.h 2.2 2012/09/01 10:57:07 kls Exp $ + * $Id: videodir.h 2.3 2012/09/30 11:01:15 kls Exp $ */ #ifndef __VIDEODIR_H @@ -23,7 +23,7 @@ bool RemoveVideoFile(const char *FileName); bool VideoFileSpaceAvailable(int SizeMB); int VideoDiskSpace(int *FreeMB = NULL, int *UsedMB = NULL); // returns the used disk space in percent cString PrefixVideoFileName(const char *FileName, char Prefix); -void RemoveEmptyVideoDirectories(void); +void RemoveEmptyVideoDirectories(const char *IgnoreFiles[] = NULL); bool IsOnVideoDirectoryFileSystem(const char *FileName); class cVideoDiskUsage {