vdr  2.4.0
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 4.1 2015/08/11 13:39:59 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  }
100  else
101  return RecordingsHandler.Add(ruMove, FromName, ToName);
102  return true;
103 }
104 
105 bool cVideoDirectory::Remove(const char *Name)
106 {
107  return RemoveFileOrDir(Name);
108 }
109 
110 void cVideoDirectory::Cleanup(const char *IgnoreFiles[])
111 {
112  RemoveEmptyDirectories(Name(), false, IgnoreFiles);
113 }
114 
115 bool cVideoDirectory::Contains(const char *Name)
116 {
117  return EntriesOnSameFileSystem(this->Name(), Name);
118 }
119 
120 cUnbufferedFile *cVideoDirectory::OpenVideoFile(const char *FileName, int Flags)
121 {
122  if (Current()->Register(FileName))
123  return cUnbufferedFile::Create(FileName, Flags, DEFFILEMODE);
124  return NULL;
125 }
126 
127 bool cVideoDirectory::RenameVideoFile(const char *OldName, const char *NewName)
128 {
129  return Current()->Rename(OldName, NewName);
130 }
131 
132 bool cVideoDirectory::MoveVideoFile(const char *FromName, const char *ToName)
133 {
134  return Current()->Move(FromName, ToName);
135 }
136 
137 bool cVideoDirectory::RemoveVideoFile(const char *FileName)
138 {
139  return Current()->Remove(FileName);
140 }
141 
143 {
144  return Current()->FreeMB() >= SizeMB;
145 }
146 
147 int cVideoDirectory::VideoDiskSpace(int *FreeMB, int *UsedMB)
148 {
149  int used = 0;
150  int free = Current()->FreeMB(&used);
152  int deleted = DeletedRecordings->TotalFileSizeMB();
153  if (deleted > used)
154  deleted = used; // let's not get beyond 100%
155  free += deleted;
156  used -= deleted;
157  if (FreeMB)
158  *FreeMB = free;
159  if (UsedMB)
160  *UsedMB = used;
161  return (free + used) ? used * 100 / (free + used) : 0;
162 }
163 
164 cString cVideoDirectory::PrefixVideoFileName(const char *FileName, char Prefix)
165 {
166  char PrefixedName[strlen(FileName) + 2];
167 
168  const char *p = FileName + strlen(FileName); // p points at the terminating 0
169  int n = 2;
170  while (p-- > FileName && n > 0) {
171  if (*p == '/') {
172  if (--n == 0) {
173  int l = p - FileName + 1;
174  strncpy(PrefixedName, FileName, l);
175  PrefixedName[l] = Prefix;
176  strcpy(PrefixedName + l + 1, p + 1);
177  return PrefixedName;
178  }
179  }
180  }
181  return NULL;
182 }
183 
184 void cVideoDirectory::RemoveEmptyVideoDirectories(const char *IgnoreFiles[])
185 {
186  Current()->Cleanup(IgnoreFiles);
187 }
188 
190 {
191  return Current()->Contains(FileName);
192 }
193 
194 // --- cVideoDiskUsage -------------------------------------------------------
195 
196 #define DISKSPACECHEK 5 // seconds between disk space checks
197 #define MB_PER_MINUTE 25.75 // this is just an estimate!
198 
199 int cVideoDiskUsage::state = 0;
204 
206 {
207  if (time(NULL) - lastChecked > DISKSPACECHEK) {
208  int FreeMB;
210  if (FreeMB != freeMB) {
212  freeMB = FreeMB;
214  double MBperMinute = Recordings->MBperMinute();
215  if (MBperMinute <= 0)
216  MBperMinute = MB_PER_MINUTE;
217  freeMinutes = int(double(FreeMB) / MBperMinute);
218  state++;
219  }
220  lastChecked = time(NULL);
221  }
222  if (State != state) {
223  State = state;
224  return true;
225  }
226  return false;
227 }
228 
230 {
231  HasChanged(state);
232  return cString::sprintf("%s %d%% - %2d:%02d %s", tr("Disk"), usedPercent, freeMinutes / 60, freeMinutes % 60, tr("free"));
233 }
static bool RenameVideoFile(const char *OldName, const char *NewName)
Definition: videodir.c:127
static int usedPercent
Definition: videodir.h:91
void Lock(void)
Definition: thread.c:222
#define dsyslog(a...)
Definition: tools.h:37
virtual ~cVideoDirectory()
Definition: videodir.c:34
static cVideoDirectory * current
Definition: videodir.h:20
static cString String(void)
Returns a localized string of the form "Disk nn% - hh:mm free".
Definition: videodir.c:229
virtual bool Move(const char *FromName, const char *ToName)
Moves the directory FromName to the location ToName.
Definition: videodir.c:91
static cString name
Definition: videodir.h:19
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition: tools.c:1127
#define MB_PER_MINUTE
Definition: videodir.c:197
#define esyslog(a...)
Definition: tools.h:35
virtual bool Contains(const char *Name)
Checks whether the directory Name is on the same file system as the video directory.
Definition: videodir.c:115
#define LOG_ERROR_STR(s)
Definition: tools.h:40
static bool VideoFileSpaceAvailable(int SizeMB)
Definition: videodir.c:142
cUnbufferedFile is used for large files that are mainly written or read in a streaming manner...
Definition: tools.h:457
virtual bool Remove(const char *Name)
Removes the directory with the given Name and everything it contains.
Definition: videodir.c:105
static cUnbufferedFile * OpenVideoFile(const char *FileName, int Flags)
Definition: videodir.c:120
static cString PrefixVideoFileName(const char *FileName, char Prefix)
Definition: videodir.c:164
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
static const char * Name(void)
Definition: videodir.c:60
static void Destroy(void)
Definition: videodir.c:50
static void RemoveEmptyVideoDirectories(const char *IgnoreFiles[]=NULL)
Definition: videodir.c:184
virtual bool Rename(const char *OldName, const char *NewName)
Renames the directory OldName to NewName.
Definition: videodir.c:81
static void SetName(const char *Name)
Definition: videodir.c:65
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:205
virtual int FreeMB(int *UsedMB=NULL)
Returns the total amount (in MB) of free disk space for recording.
Definition: videodir.c:55
int FreeDiskSpaceMB(const char *Directory, int *UsedMB)
Definition: tools.c:446
Definition: thread.h:67
static cVideoDirectory * Current(void)
Definition: videodir.c:41
cRecordingsHandler RecordingsHandler
Definition: recording.c:1961
static cMutex mutex
Definition: videodir.h:18
static int freeMB
Definition: videodir.h:92
static int VideoDiskSpace(int *FreeMB=NULL, int *UsedMB=NULL)
Definition: videodir.c:147
static bool RemoveVideoFile(const char *FileName)
Definition: videodir.c:137
#define LOCK_DELETEDRECORDINGS_READ
Definition: recording.h:308
cVideoDirectory(void)
Definition: videodir.c:26
static int state
Definition: videodir.h:89
static bool MoveVideoFile(const char *FromName, const char *ToName)
Definition: videodir.c:132
#define LOCK_RECORDINGS_READ
Definition: recording.h:306
#define tr(s)
Definition: i18n.h:85
bool EntriesOnSameFileSystem(const char *File1, const char *File2)
Checks whether the given files are on the same file system.
Definition: tools.c:431
static bool IsOnVideoDirectoryFileSystem(const char *FileName)
Definition: videodir.c:189
#define DISKSPACECHEK
Definition: videodir.c:196
bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis, const char *IgnoreFiles[])
Removes all empty directories under the given directory DirName.
Definition: tools.c:567
static cUnbufferedFile * Create(const char *FileName, int Flags, mode_t Mode=DEFFILEMODE)
Definition: tools.c:1966
bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks)
Definition: tools.c:509
virtual void Cleanup(const char *IgnoreFiles[]=NULL)
Recursively removes all empty directories under the video directory.
Definition: videodir.c:110
static int freeMinutes
Definition: videodir.h:93
static time_t lastChecked
Definition: videodir.h:90
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:2013
Definition: tools.h:176
static int FreeMB(void)
Returns the amount of free space on the video disk in MB.
Definition: videodir.h:115
void Unlock(void)
Definition: thread.c:228
static int UsedPercent(void)
Returns the used space of the video disk in percent.
Definition: videodir.h:112