vdr  2.7.6
videodir.c
Go to the documentation of this file.
1 /*
2  * videodir.c: Functions to maintain the video directory
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: videodir.c 5.2 2021/12/24 10:56:47 kls Exp $
8  */
9 
10 #include "videodir.h"
11 #include <ctype.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/stat.h>
18 #include <unistd.h>
19 #include "recording.h"
20 #include "tools.h"
21 
25 
27 {
28  mutex.Lock();
29  delete current;
30  current = this;
31  mutex.Unlock();
32 }
33 
35 {
36  mutex.Lock();
37  current = NULL;
38  mutex.Unlock();
39 }
40 
42 {
43  mutex.Lock();
44  if (!current)
45  new cVideoDirectory;
46  mutex.Unlock();
47  return current;
48 }
49 
51 {
52  delete current;
53 }
54 
55 int cVideoDirectory::FreeMB(int *UsedMB)
56 {
57  return FreeDiskSpaceMB(Name(), UsedMB);
58 }
59 
60 const char *cVideoDirectory::Name(void)
61 {
62  return name;
63 }
64 
65 void cVideoDirectory::SetName(const char *Name)
66 {
67  name = Name;
68 }
69 
70 bool cVideoDirectory::Register(const char *FileName)
71 {
72  // Incoming name must be in base video directory:
73  if (strstr(FileName, Name()) != FileName) {
74  esyslog("ERROR: %s not in %s", FileName, Name());
75  errno = ENOENT; // must set 'errno' - any ideas for a better value?
76  return false;
77  }
78  return true;
79 }
80 
81 bool cVideoDirectory::Rename(const char *OldName, const char *NewName)
82 {
83  dsyslog("renaming '%s' to '%s'", OldName, NewName);
84  if (rename(OldName, NewName) == -1) {
85  LOG_ERROR_STR(NewName);
86  return false;
87  }
88  return true;
89 }
90 
91 bool cVideoDirectory::Move(const char *FromName, const char *ToName)
92 {
93  dsyslog("moving '%s' to '%s'", FromName, ToName);
94  if (EntriesOnSameFileSystem(FromName, ToName)) {
95  if (rename(FromName, ToName) == -1) {
96  LOG_ERROR_STR(ToName);
97  return false;
98  }
99  // detect whether it's a real recording move inside same file system or a recording rename
100  if (strcmp(strgetbefore(FromName, '/', 2), strgetbefore(ToName, '/', 2)))
102  else
104  }
105  else
106  return RecordingsHandler.Add(ruMove, FromName, ToName);
107  return true;
108 }
109 
110 bool cVideoDirectory::Remove(const char *Name)
111 {
112  return RemoveFileOrDir(Name);
113 }
114 
115 void cVideoDirectory::Cleanup(const char *IgnoreFiles[])
116 {
117  RemoveEmptyDirectories(Name(), false, IgnoreFiles);
118 }
119 
120 bool cVideoDirectory::Contains(const char *Name)
121 {
122  return EntriesOnSameFileSystem(this->Name(), Name);
123 }
124 
125 cUnbufferedFile *cVideoDirectory::OpenVideoFile(const char *FileName, int Flags)
126 {
127  if (Current()->Register(FileName))
128  return cUnbufferedFile::Create(FileName, Flags, DEFFILEMODE);
129  return NULL;
130 }
131 
132 bool cVideoDirectory::RenameVideoFile(const char *OldName, const char *NewName)
133 {
134  return Current()->Rename(OldName, NewName);
135 }
136 
137 bool cVideoDirectory::MoveVideoFile(const char *FromName, const char *ToName)
138 {
139  return Current()->Move(FromName, ToName);
140 }
141 
142 bool cVideoDirectory::RemoveVideoFile(const char *FileName)
143 {
144  return Current()->Remove(FileName);
145 }
146 
148 {
149  return Current()->FreeMB() >= SizeMB;
150 }
151 
152 int cVideoDirectory::VideoDiskSpace(int *FreeMB, int *UsedMB)
153 {
154  int used = 0;
155  int free = Current()->FreeMB(&used);
157  int deleted = DeletedRecordings->TotalFileSizeMB();
158  if (deleted > used)
159  deleted = used; // let's not get beyond 100%
160  free += deleted;
161  used -= deleted;
162  if (FreeMB)
163  *FreeMB = free;
164  if (UsedMB)
165  *UsedMB = used;
166  return (free + used) ? round(double(used) * 100 / (free + used)) : 0;
167 }
168 
169 cString cVideoDirectory::PrefixVideoFileName(const char *FileName, char Prefix)
170 {
171  char PrefixedName[strlen(FileName) + 2];
172 
173  const char *p = FileName + strlen(FileName); // p points at the terminating 0
174  int n = 2;
175  while (p-- > FileName && n > 0) {
176  if (*p == '/') {
177  if (--n == 0) {
178  int l = p - FileName + 1;
179  strncpy(PrefixedName, FileName, l);
180  PrefixedName[l] = Prefix;
181  strcpy(PrefixedName + l + 1, p + 1);
182  return PrefixedName;
183  }
184  }
185  }
186  return NULL;
187 }
188 
189 void cVideoDirectory::RemoveEmptyVideoDirectories(const char *IgnoreFiles[])
190 {
191  Current()->Cleanup(IgnoreFiles);
192 }
193 
195 {
196  return Current()->Contains(FileName);
197 }
198 
199 // --- cVideoDiskUsage -------------------------------------------------------
200 
201 #define DISKSPACECHEK 5 // seconds between disk space checks
202 #define MB_PER_MINUTE 25.75 // this is just an estimate!
203 
204 int cVideoDiskUsage::state = 0;
209 
211 {
212  if (time(NULL) - lastChecked > DISKSPACECHEK) {
213  int FreeMB;
215  if (FreeMB != freeMB) {
217  freeMB = FreeMB;
219  double MBperMinute = Recordings->MBperMinute();
220  if (MBperMinute <= 0)
221  MBperMinute = MB_PER_MINUTE;
222  freeMinutes = int(double(FreeMB) / MBperMinute);
223  state++;
224  }
225  lastChecked = time(NULL);
226  }
227  if (State != state) {
228  State = state;
229  return true;
230  }
231  return false;
232 }
233 
235 {
236  HasChanged(state);
237  return cString::sprintf("%s %d%% - %2d:%02d %s", tr("Disk"), usedPercent, freeMinutes / 60, freeMinutes % 60, tr("free"));
238 }
Definition: thread.h:67
void Lock(void)
Definition: thread.c:223
void Unlock(void)
Definition: thread.c:229
static void InvokeCommand(const char *State, const char *RecordingFileName, const char *SourceFileName=NULL)
Definition: recording.c:2512
bool Add(int Usage, const char *FileNameSrc, const char *FileNameDst=NULL)
Adds the given FileNameSrc to the recordings handler for (later) processing.
Definition: recording.c:2175
Definition: tools.h:178
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition: tools.c:1195
cUnbufferedFile is used for large files that are mainly written or read in a streaming manner,...
Definition: tools.h:494
static cUnbufferedFile * Create(const char *FileName, int Flags, mode_t Mode=DEFFILEMODE)
Definition: tools.c:1987
virtual int FreeMB(int *UsedMB=NULL)
Returns the total amount (in MB) of free disk space for recording.
Definition: videodir.c:55
virtual bool Contains(const char *Name)
Checks whether the directory Name is on the same file system as the video directory.
Definition: videodir.c:120
static cString PrefixVideoFileName(const char *FileName, char Prefix)
Definition: videodir.c:169
static void Destroy(void)
Definition: videodir.c:50
static void RemoveEmptyVideoDirectories(const char *IgnoreFiles[]=NULL)
Definition: videodir.c:189
static bool IsOnVideoDirectoryFileSystem(const char *FileName)
Definition: videodir.c:194
cVideoDirectory(void)
Definition: videodir.c:26
static cVideoDirectory * current
Definition: videodir.h:20
static const char * Name(void)
Definition: videodir.c:60
static cMutex mutex
Definition: videodir.h:18
static cUnbufferedFile * OpenVideoFile(const char *FileName, int Flags)
Definition: videodir.c:125
static bool VideoFileSpaceAvailable(int SizeMB)
Definition: videodir.c:147
static bool MoveVideoFile(const char *FromName, const char *ToName)
Definition: videodir.c:137
virtual bool Move(const char *FromName, const char *ToName)
Moves the directory FromName to the location ToName.
Definition: videodir.c:91
static int VideoDiskSpace(int *FreeMB=NULL, int *UsedMB=NULL)
Definition: videodir.c:152
virtual bool Rename(const char *OldName, const char *NewName)
Renames the directory OldName to NewName.
Definition: videodir.c:81
virtual void Cleanup(const char *IgnoreFiles[]=NULL)
Recursively removes all empty directories under the video directory.
Definition: videodir.c:115
virtual bool Register(const char *FileName)
By default VDR assumes that the video directory consists of one large volume, on which it can store i...
Definition: videodir.c:70
virtual bool Remove(const char *Name)
Removes the directory with the given Name and everything it contains.
Definition: videodir.c:110
virtual ~cVideoDirectory()
Definition: videodir.c:34
static void SetName(const char *Name)
Definition: videodir.c:65
static cVideoDirectory * Current(void)
Definition: videodir.c:41
static bool RenameVideoFile(const char *OldName, const char *NewName)
Definition: videodir.c:132
static bool RemoveVideoFile(const char *FileName)
Definition: videodir.c:142
static cString name
Definition: videodir.h:19
static int state
Definition: videodir.h:89
static int freeMB
Definition: videodir.h:92
static int FreeMB(void)
Returns the amount of free space on the video disk in MB.
Definition: videodir.h:115
static int freeMinutes
Definition: videodir.h:93
static bool HasChanged(int &State)
Returns true if the usage of the video disk space has changed since the last call to this function wi...
Definition: videodir.c:210
static time_t lastChecked
Definition: videodir.h:90
static cString String(void)
Returns a localized string of the form "Disk nn% - hh:mm free".
Definition: videodir.c:234
static int usedPercent
Definition: videodir.h:91
static int UsedPercent(void)
Returns the used space of the video disk in percent.
Definition: videodir.h:112
#define tr(s)
Definition: i18n.h:85
cRecordingsHandler RecordingsHandler
Definition: recording.c:2123
@ ruMove
Definition: recording.h:35
#define LOCK_RECORDINGS_READ
Definition: recording.h:329
#define RUC_RENAMEDRECORDING
Definition: recording.h:460
#define RUC_MOVEDRECORDING
Definition: recording.h:461
#define LOCK_DELETEDRECORDINGS_READ
Definition: recording.h:331
int FreeDiskSpaceMB(const char *Directory, int *UsedMB)
Definition: tools.c:472
bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis, const char *IgnoreFiles[])
Removes all empty directories under the given directory DirName.
Definition: tools.c:593
bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks)
Definition: tools.c:535
bool EntriesOnSameFileSystem(const char *File1, const char *File2)
Checks whether the given files are on the same file system.
Definition: tools.c:457
cString strgetbefore(const char *s, char c, int n)
Definition: tools.c:211
#define LOG_ERROR_STR(s)
Definition: tools.h:40
#define dsyslog(a...)
Definition: tools.h:37
#define esyslog(a...)
Definition: tools.h:35
#define DISKSPACECHEK
Definition: videodir.c:201
#define MB_PER_MINUTE
Definition: videodir.c:202