vdr 2.7.2
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
40
42{
43 mutex.Lock();
44 if (!current)
46 mutex.Unlock();
47 return current;
48}
49
51{
52 delete current;
53}
54
56{
57 return FreeDiskSpaceMB(Name(), UsedMB);
58}
59
60const char *cVideoDirectory::Name(void)
61{
62 return name;
63}
64
65void cVideoDirectory::SetName(const char *Name)
66{
67 name = Name;
68}
69
70bool 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
81bool 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
91bool 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
110bool cVideoDirectory::Remove(const char *Name)
111{
112 return RemoveFileOrDir(Name);
113}
114
115void cVideoDirectory::Cleanup(const char *IgnoreFiles[])
116{
117 RemoveEmptyDirectories(Name(), false, IgnoreFiles);
118}
119
120bool cVideoDirectory::Contains(const char *Name)
121{
122 return EntriesOnSameFileSystem(this->Name(), Name);
123}
124
125cUnbufferedFile *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
132bool cVideoDirectory::RenameVideoFile(const char *OldName, const char *NewName)
133{
134 return Current()->Rename(OldName, NewName);
135}
136
137bool cVideoDirectory::MoveVideoFile(const char *FromName, const char *ToName)
138{
139 return Current()->Move(FromName, ToName);
140}
141
142bool cVideoDirectory::RemoveVideoFile(const char *FileName)
143{
144 return Current()->Remove(FileName);
145}
146
148{
149 return Current()->FreeMB() >= SizeMB;
150}
151
152int 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
169cString 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
189void 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
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{
237 return cString::sprintf("%s %d%% - %2d:%02d %s", tr("Disk"), usedPercent, freeMinutes / 60, freeMinutes % 60, tr("free"));
238}
void Lock(void)
Definition thread.c:222
void Unlock(void)
Definition thread.c:228
static void InvokeCommand(const char *State, const char *RecordingFileName, const char *SourceFileName=NULL)
Definition recording.c:2495
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:2158
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition tools.c:1188
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:1978
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:2106
@ ruMove
Definition recording.h:35
#define LOCK_RECORDINGS_READ
Definition recording.h:327
#define RUC_RENAMEDRECORDING
Definition recording.h:458
#define RUC_MOVEDRECORDING
Definition recording.h:459
#define LOCK_DELETEDRECORDINGS_READ
Definition recording.h:329
int FreeDiskSpaceMB(const char *Directory, int *UsedMB)
Definition tools.c:469
bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis, const char *IgnoreFiles[])
Removes all empty directories under the given directory DirName.
Definition tools.c:590
bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks)
Definition tools.c:532
bool EntriesOnSameFileSystem(const char *File1, const char *File2)
Checks whether the given files are on the same file system.
Definition tools.c:454
cString strgetbefore(const char *s, char c, int n)
Definition tools.c:208
#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