Added 'IgnoreFiles' to RemoveEmptyDirectories()

This commit is contained in:
Klaus Schmidinger 2012-09-30 13:05:14 +02:00
parent 3cc12a401a
commit f1000d75c0
6 changed files with 56 additions and 30 deletions

View File

@ -7235,7 +7235,7 @@ Video Disk Recorder Revision History
function in order to make use of this new feature. See, for instance, the function function in order to make use of this new feature. See, for instance, the function
cSkinClassicDisplayMenu::SetButtons() in skinclassic.c for details. 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 - 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. 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). - 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. - 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. - 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".

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "recording.h"
@ -107,8 +107,10 @@ void cRemoveDeletedRecordingsThread::Action(void)
} }
r = DeletedRecordings.Next(r); r = DeletedRecordings.Next(r);
} }
if (deleted) if (deleted) {
RemoveEmptyVideoDirectories(); const char *IgnoreFiles[] = { SORTMODEFILE, NULL };
RemoveEmptyVideoDirectories(IgnoreFiles);
}
} }
} }

47
tools.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "tools.h"
@ -285,6 +285,18 @@ int64_t StrToNum(const char *s)
return n; 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) cString AddDirectory(const char *DirName, const char *FileName)
{ {
return cString::sprintf("%s/%s", DirName && *DirName ? DirName : ".", FileName); return cString::sprintf("%s/%s", DirName && *DirName ? DirName : ".", FileName);
@ -433,9 +445,9 @@ bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks)
return true; 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); cReadDir d(DirName);
if (d.Ok()) { if (d.Ok()) {
bool empty = true; bool empty = true;
@ -446,11 +458,11 @@ bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis)
struct stat st; struct stat st;
if (stat(buffer, &st) == 0) { if (stat(buffer, &st) == 0) {
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
if (!RemoveEmptyDirectories(buffer, true)) if (!RemoveEmptyDirectories(buffer, true, IgnoreFiles))
empty = false; empty = false;
} }
else if (*e->d_name == '.') // "dot files" don't count else if (RemoveThis && IgnoreFiles && StrInArray(IgnoreFiles, e->d_name))
HasDotFiles = true; HasIgnoredFiles = true;
else else
empty = false; empty = false;
} }
@ -461,21 +473,18 @@ bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis)
} }
} }
if (RemoveThis && empty) { if (RemoveThis && empty) {
if (HasDotFiles) { if (HasIgnoredFiles) {
cReadDir d(DirName); while (*IgnoreFiles) {
if (d.Ok()) { cString buffer = AddDirectory(DirName, *IgnoreFiles);
struct dirent *e; if (access(buffer, F_OK) == 0) {
while ((e = d.Next()) != NULL) { dsyslog("removing %s", *buffer);
if (*e->d_name == '.') { // for safety - should always be true if (remove(buffer) < 0) {
cString buffer = AddDirectory(DirName, e->d_name); LOG_ERROR_STR(*buffer);
dsyslog("removing %s", *buffer); return false;
if (remove(buffer) < 0) {
LOG_ERROR_STR(*buffer);
return false;
}
} }
} }
} IgnoreFiles++;
}
} }
dsyslog("removing %s", DirName); dsyslog("removing %s", DirName);
if (remove(DirName) < 0) { if (remove(DirName) < 0) {

12
tools.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #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 ///< K, M, G or T to abbreviate Kilo-, Mega-, Giga- or Terabyte, respectively
///< (based on 1024). Everything after the first non-numeric character is ///< (based on 1024). Everything after the first non-numeric character is
///< silently ignored, as are any characters other than the ones mentioned here. ///< 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 itoa(int n);
cString AddDirectory(const char *DirName, const char *FileName); cString AddDirectory(const char *DirName, const char *FileName);
bool EntriesOnSameFileSystem(const char *File1, const char *File2); 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 DirectoryOk(const char *DirName, bool LogErrors = false);
bool MakeDirs(const char *FileName, bool IsDirectory = false); bool MakeDirs(const char *FileName, bool IsDirectory = false);
bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks = 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 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) 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); bool SpinUpDisk(const char *FileName);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "videodir.h"
@ -229,11 +229,11 @@ cString PrefixVideoFileName(const char *FileName, char Prefix)
return NULL; return NULL;
} }
void RemoveEmptyVideoDirectories(void) void RemoveEmptyVideoDirectories(const char *IgnoreFiles[])
{ {
cVideoDirectory Dir; cVideoDirectory Dir;
do { do {
RemoveEmptyDirectories(Dir.Name()); RemoveEmptyDirectories(Dir.Name(), false, IgnoreFiles);
} while (Dir.Next()); } while (Dir.Next());
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __VIDEODIR_H
@ -23,7 +23,7 @@ bool RemoveVideoFile(const char *FileName);
bool VideoFileSpaceAvailable(int SizeMB); bool VideoFileSpaceAvailable(int SizeMB);
int VideoDiskSpace(int *FreeMB = NULL, int *UsedMB = NULL); // returns the used disk space in percent int VideoDiskSpace(int *FreeMB = NULL, int *UsedMB = NULL); // returns the used disk space in percent
cString PrefixVideoFileName(const char *FileName, char Prefix); cString PrefixVideoFileName(const char *FileName, char Prefix);
void RemoveEmptyVideoDirectories(void); void RemoveEmptyVideoDirectories(const char *IgnoreFiles[] = NULL);
bool IsOnVideoDirectoryFileSystem(const char *FileName); bool IsOnVideoDirectoryFileSystem(const char *FileName);
class cVideoDiskUsage { class cVideoDiskUsage {