vdr  2.2.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 3.4 2013/10/11 09:38:07 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 
24 
26 {
27  delete current;
28  current = this;
29 }
30 
32 {
33  current = NULL;
34 }
35 
37 {
38  if (!current)
40  return current;
41 }
42 
44 {
45  delete current;
46 }
47 
48 int cVideoDirectory::FreeMB(int *UsedMB)
49 {
50  return FreeDiskSpaceMB(Name(), UsedMB);
51 }
52 
53 const char *cVideoDirectory::Name(void)
54 {
55  return name;
56 }
57 
58 void cVideoDirectory::SetName(const char *Name)
59 {
60  name = Name;
61 }
62 
63 bool cVideoDirectory::Register(const char *FileName)
64 {
65  // Incoming name must be in base video directory:
66  if (strstr(FileName, Name()) != FileName) {
67  esyslog("ERROR: %s not in %s", FileName, Name());
68  errno = ENOENT; // must set 'errno' - any ideas for a better value?
69  return false;
70  }
71  return true;
72 }
73 
74 bool cVideoDirectory::Rename(const char *OldName, const char *NewName)
75 {
76  dsyslog("renaming '%s' to '%s'", OldName, NewName);
77  if (rename(OldName, NewName) == -1) {
78  LOG_ERROR_STR(NewName);
79  return false;
80  }
81  return true;
82 }
83 
84 bool cVideoDirectory::Move(const char *FromName, const char *ToName)
85 {
86  dsyslog("moving '%s' to '%s'", FromName, ToName);
87  if (EntriesOnSameFileSystem(FromName, ToName)) {
88  if (rename(FromName, ToName) == -1) {
89  LOG_ERROR_STR(ToName);
90  return false;
91  }
92  }
93  else
94  return RecordingsHandler.Add(ruMove, FromName, ToName);
95  return true;
96 }
97 
98 bool cVideoDirectory::Remove(const char *Name)
99 {
100  return RemoveFileOrDir(Name);
101 }
102 
103 void cVideoDirectory::Cleanup(const char *IgnoreFiles[])
104 {
105  RemoveEmptyDirectories(Name(), false, IgnoreFiles);
106 }
107 
109 {
110  return EntriesOnSameFileSystem(this->Name(), Name);
111 }
112 
113 cUnbufferedFile *cVideoDirectory::OpenVideoFile(const char *FileName, int Flags)
114 {
115  if (Current()->Register(FileName))
116  return cUnbufferedFile::Create(FileName, Flags, DEFFILEMODE);
117  return NULL;
118 }
119 
120 bool cVideoDirectory::RenameVideoFile(const char *OldName, const char *NewName)
121 {
122  return Current()->Rename(OldName, NewName);
123 }
124 
125 bool cVideoDirectory::MoveVideoFile(const char *FromName, const char *ToName)
126 {
127  return Current()->Move(FromName, ToName);
128 }
129 
130 bool cVideoDirectory::RemoveVideoFile(const char *FileName)
131 {
132  return Current()->Remove(FileName);
133 }
134 
136 {
137  return Current()->FreeMB() >= SizeMB;
138 }
139 
141 {
142  int used = 0;
143  int free = Current()->FreeMB(&used);
144  int deleted = DeletedRecordings.TotalFileSizeMB();
145  if (deleted > used)
146  deleted = used; // let's not get beyond 100%
147  free += deleted;
148  used -= deleted;
149  if (FreeMB)
150  *FreeMB = free;
151  if (UsedMB)
152  *UsedMB = used;
153  return (free + used) ? used * 100 / (free + used) : 0;
154 }
155 
156 cString cVideoDirectory::PrefixVideoFileName(const char *FileName, char Prefix)
157 {
158  char PrefixedName[strlen(FileName) + 2];
159 
160  const char *p = FileName + strlen(FileName); // p points at the terminating 0
161  int n = 2;
162  while (p-- > FileName && n > 0) {
163  if (*p == '/') {
164  if (--n == 0) {
165  int l = p - FileName + 1;
166  strncpy(PrefixedName, FileName, l);
167  PrefixedName[l] = Prefix;
168  strcpy(PrefixedName + l + 1, p + 1);
169  return PrefixedName;
170  }
171  }
172  }
173  return NULL;
174 }
175 
176 void cVideoDirectory::RemoveEmptyVideoDirectories(const char *IgnoreFiles[])
177 {
178  Current()->Cleanup(IgnoreFiles);
179 }
180 
182 {
183  return Current()->Contains(FileName);
184 }
185 
186 // --- cVideoDiskUsage -------------------------------------------------------
187 
188 #define DISKSPACECHEK 5 // seconds between disk space checks
189 #define MB_PER_MINUTE 25.75 // this is just an estimate!
190 
191 int cVideoDiskUsage::state = 0;
196 
198 {
199  if (time(NULL) - lastChecked > DISKSPACECHEK) {
200  int FreeMB;
201  int UsedPercent = cVideoDirectory::VideoDiskSpace(&FreeMB);
202  if (FreeMB != freeMB) {
203  usedPercent = UsedPercent;
204  freeMB = FreeMB;
205  double MBperMinute = Recordings.MBperMinute();
206  if (MBperMinute <= 0)
207  MBperMinute = MB_PER_MINUTE;
208  freeMinutes = int(double(FreeMB) / MBperMinute);
209  state++;
210  }
211  lastChecked = time(NULL);
212  }
213  if (State != state) {
214  State = state;
215  return true;
216  }
217  return false;
218 }
219 
221 {
222  HasChanged(state);
223  return cString::sprintf("%s %d%% - %2d:%02d %s", tr("Disk"), usedPercent, freeMinutes / 60, freeMinutes % 60, tr("free"));
224 }
static bool RenameVideoFile(const char *OldName, const char *NewName)
Definition: videodir.c:120
static int usedPercent
Definition: videodir.h:90
int TotalFileSizeMB(void)
Definition: recording.c:1566
#define dsyslog(a...)
Definition: tools.h:36
virtual ~cVideoDirectory()
Definition: videodir.c:31
static cVideoDirectory * current
Definition: videodir.h:19
static cString String(void)
Returns a localized string of the form "Disk nn% - hh:mm free".
Definition: videodir.c:220
virtual bool Move(const char *FromName, const char *ToName)
Moves the directory FromName to the location ToName.
Definition: videodir.c:84
static cString name
Definition: videodir.h:18
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition: tools.c:1080
#define MB_PER_MINUTE
Definition: videodir.c:189
#define esyslog(a...)
Definition: tools.h:34
virtual bool Contains(const char *Name)
Checks whether the directory Name is on the same file system as the video directory.
Definition: videodir.c:108
#define LOG_ERROR_STR(s)
Definition: tools.h:39
static bool VideoFileSpaceAvailable(int SizeMB)
Definition: videodir.c:135
cUnbufferedFile is used for large files that are mainly written or read in a streaming manner...
Definition: tools.h:418
virtual bool Remove(const char *Name)
Removes the directory with the given Name and everything it contains.
Definition: videodir.c:98
static cUnbufferedFile * OpenVideoFile(const char *FileName, int Flags)
Definition: videodir.c:113
static cString PrefixVideoFileName(const char *FileName, char Prefix)
Definition: videodir.c:156
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:63
static const char * Name(void)
Definition: videodir.c:53
static void Destroy(void)
Definition: videodir.c:43
static void RemoveEmptyVideoDirectories(const char *IgnoreFiles[]=NULL)
Definition: videodir.c:176
virtual bool Rename(const char *OldName, const char *NewName)
Renames the directory OldName to NewName.
Definition: videodir.c:74
static void SetName(const char *Name)
Definition: videodir.c:58
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:197
virtual int FreeMB(int *UsedMB=NULL)
Returns the total amount (in MB) of free disk space for recording.
Definition: videodir.c:48
int FreeDiskSpaceMB(const char *Directory, int *UsedMB)
Definition: tools.c:410
static cVideoDirectory * Current(void)
Definition: videodir.c:36
cRecordingsHandler RecordingsHandler
Definition: recording.c:1910
cRecordings DeletedRecordings
static int freeMB
Definition: videodir.h:91
static int VideoDiskSpace(int *FreeMB=NULL, int *UsedMB=NULL)
Definition: videodir.c:140
static bool RemoveVideoFile(const char *FileName)
Definition: videodir.c:130
cVideoDirectory(void)
Definition: videodir.c:25
static int state
Definition: videodir.h:88
static bool MoveVideoFile(const char *FromName, const char *ToName)
Definition: videodir.c:125
#define tr(s)
Definition: i18n.h:85
cRecordings Recordings
Any access to Recordings that loops through the list of recordings needs to hold a thread lock on thi...
Definition: recording.c:1365
double MBperMinute(void)
Returns the average data rate (in MB/min) of all recordings, or -1 if this value is unknown...
Definition: recording.c:1578
bool EntriesOnSameFileSystem(const char *File1, const char *File2)
Checks whether the given files are on the same file system.
Definition: tools.c:395
static bool IsOnVideoDirectoryFileSystem(const char *FileName)
Definition: videodir.c:181
#define DISKSPACECHEK
Definition: videodir.c:188
bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis, const char *IgnoreFiles[])
Removes all empty directories under the given directory DirName.
Definition: tools.c:531
static cUnbufferedFile * Create(const char *FileName, int Flags, mode_t Mode=DEFFILEMODE)
Definition: tools.c:1883
bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks)
Definition: tools.c:473
virtual void Cleanup(const char *IgnoreFiles[]=NULL)
Recursively removes all empty directories under the video directory.
Definition: videodir.c:103
static int freeMinutes
Definition: videodir.h:92
static time_t lastChecked
Definition: videodir.h:89
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:1933
Definition: tools.h:168