MythTV  master
filesysteminfo.cpp
Go to the documentation of this file.
1 #include <unistd.h>
2 #include <cstdlib>
3 #include "compat.h"
4 
5 #include <QtGlobal>
6 
7 #ifdef __linux__
8 #include <sys/vfs.h>
9 #include <sys/sysinfo.h>
10 #endif
11 
12 #ifdef Q_OS_DARWIN
13 #include <mach/mach.h>
14 #endif
15 
16 #ifdef BSD
17 #include <sys/param.h>
18 #include <sys/mount.h> // for struct statfs
19 #endif
20 
21 #include <QList>
22 #include <QString>
23 #include <QStringList>
24 #include <utility>
25 
26 #include "filesysteminfo.h"
27 #include "mythcoreutil.h"
28 
29 // for deserialization
30 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
31 #define NEXT_STR() do { if (it == listend) \
32  { \
33  LOG(VB_GENERAL, LOG_ALERT, listerror); \
34  clear(); \
35  return false; \
36  } \
37  ts = *it++; } while (false)
38 
40 {
41  FileSystemInfo::clone(other);
42 }
43 
44 FileSystemInfo::FileSystemInfo(QString hostname, QString path, bool local,
45  int fsid, int groupid, int blksize, int64_t total, int64_t used) :
46  m_hostname(std::move(hostname)), m_path(std::move(path)), m_local(local), m_fsid(fsid),
47  m_grpid(groupid), m_blksize(blksize), m_total(total), m_used(used)
48 {
49 }
50 
51 FileSystemInfo::FileSystemInfo(QStringList::const_iterator &it,
52  const QStringList::const_iterator& end)
53 {
54  FromStringList(it, end);
55 }
56 
57 FileSystemInfo::FileSystemInfo(const QStringList &slist)
58 {
59  FromStringList(slist);
60 }
61 
63 {
64  m_hostname = other.m_hostname;
65  m_path = other.m_path;
66  m_local = other.m_local;
67  m_fsid = other.m_fsid;
68  m_grpid = other.m_grpid;
69  m_blksize = other.m_blksize;
70  m_total = other.m_total;
71  m_used = other.m_used;
72  m_weight = other.m_weight;
73 }
74 
76 {
77  if (this == &other)
78  return *this;
79 
80  clone(other);
81  return *this;
82 }
83 
85 {
86  m_hostname = "";
87  m_path = "";
88  m_local = false;
89  m_fsid = -1;
90  m_grpid = -1;
91  m_blksize = 4096;
92  m_total = 0;
93  m_used = 0;
94  m_weight = 0;
95 }
96 
97 bool FileSystemInfo::ToStringList(QStringList &list) const
98 {
99  list << m_hostname;
100  list << m_path;
101  list << QString::number(m_local);
102  list << QString::number(m_fsid);
103  list << QString::number(m_grpid);
104  list << QString::number(m_blksize);
105  list << QString::number(m_total);
106  list << QString::number(m_used);
107 
108  return true;
109 }
110 
111 bool FileSystemInfo::FromStringList(const QStringList &slist)
112 {
113  QStringList::const_iterator it = slist.constBegin();
114  return FromStringList(it, slist.constEnd());
115 }
116 
117 bool FileSystemInfo::FromStringList(QStringList::const_iterator &it,
118  const QStringList::const_iterator& listend)
119 {
120  QString listerror = "FileSystemInfo: FromStringList, not enough items in list.";
121  QString ts;
122 
123  NEXT_STR(); m_hostname = ts;
124  NEXT_STR(); m_path = ts;
125  NEXT_STR(); m_local = ts.toLongLong();
126  NEXT_STR(); m_fsid = ts.toLongLong();
127  NEXT_STR(); m_grpid = ts.toLongLong();
128  NEXT_STR(); m_blksize = ts.toLongLong();
129  NEXT_STR(); m_total = ts.toLongLong();
130  NEXT_STR(); m_used = ts.toLongLong();
131 
132  m_weight = 0;
133 
134  return true;
135 }
136 
137 QList<FileSystemInfo> FileSystemInfo::RemoteGetInfo(MythSocket *sock)
138 {
139  FileSystemInfo fsInfo;
140  QList<FileSystemInfo> fsInfos;
141  QStringList strlist(QString("QUERY_FREE_SPACE_LIST"));
142 
143  bool sent = false;
144 
145  if (sock)
146  sent = sock->SendReceiveStringList(strlist);
147  else
148  sent = gCoreContext->SendReceiveStringList(strlist);
149 
150  if (sent)
151  {
152  int numdisks = strlist.size()/NUMDISKINFOLINES;
153 
154  QStringList::const_iterator it = strlist.cbegin();
155  for (int i = 0; i < numdisks; i++)
156  {
157  fsInfo.FromStringList(it, strlist.cend());
158  fsInfos.append(fsInfo);
159  }
160  }
161 
162  return fsInfos;
163 }
164 
165 void FileSystemInfo::Consolidate(QList<FileSystemInfo> &disks,
166  bool merge, int64_t fuzz)
167 {
168  int newid = 0;
169 
170  for (auto it1 = disks.begin(); it1 != disks.end(); ++it1)
171  {
172  if (it1->getFSysID() == -1)
173  {
174  it1->setFSysID(newid++);
175  if (merge)
176  it1->setPath(it1->getHostname().section(".", 0, 0)
177  + ":" + it1->getPath());
178  }
179 
180  for (auto it2 = it1+1; it2 != disks.end(); ++it2)
181  {
182  if (it2->getFSysID() != -1) // disk has already been matched
183  continue;
184 
185  int bSize = std::max(32, std::max(it1->getBlockSize(), it2->getBlockSize())
186  / 1024);
187  int64_t diffSize = it1->getTotalSpace() - it2->getTotalSpace();
188  int64_t diffUsed = it1->getUsedSpace() - it2->getUsedSpace();
189 
190  if (diffSize < 0)
191  diffSize = 0 - diffSize;
192  if (diffUsed < 0)
193  diffUsed = 0 - diffUsed;
194 
195  if ((diffSize <= bSize) && (diffUsed <= fuzz))
196  {
197  it2->setFSysID(it1->getFSysID());
198 
199  if (merge)
200  {
201  if (!it1->getHostname().contains(it2->getHostname()))
202  it1->setHostname(it1->getHostname()
203  + "," + it2->getHostname());
204  it1->setPath(it1->getPath() + ","
205  + it2->getHostname().section(".", 0, 0) + ":"
206  + it2->getPath());
207  disks.erase(it2);
208  it2 = it1;
209  }
210  }
211  }
212  }
213 }
214 
216 {
217  int64_t total = -1;
218  int64_t used = -1;
219  getDiskSpace(getPath().toLatin1().constData(), total, used);
220  setTotalSpace(total);
221  setUsedSpace(used);
222 }
223 
225 {
226  struct statfs statbuf {};
227 
228  if (statfs(getPath().toLocal8Bit().constData(), &statbuf) == 0)
229  {
230 #ifdef Q_OS_DARWIN
231  char *fstypename = statbuf.f_fstypename;
232  if ((!strcmp(fstypename, "nfs")) || // NFS|FTP
233  (!strcmp(fstypename, "afpfs")) || // AppleShare
234  (!strcmp(fstypename, "smbfs"))) // SMB
235  setLocal(false);
236 #elif defined(__linux__)
237  long fstype = statbuf.f_type;
238  if ((fstype == 0x6969) || // NFS
239  (fstype == 0x517B) || // SMB
240  (fstype == (long)0xFF534D42)) // CIFS
241  setLocal(false);
242 #endif
243  setBlockSize(statbuf.f_bsize);
244  }
245 }
filesysteminfo.h
FileSystemInfo::setUsedSpace
void setUsedSpace(int64_t size)
Definition: filesysteminfo.h:54
FileSystemInfo::m_total
int64_t m_total
Definition: filesysteminfo.h:76
FileSystemInfo::m_fsid
int m_fsid
Definition: filesysteminfo.h:73
FileSystemInfo::m_path
QString m_path
Definition: filesysteminfo.h:71
MythCoreContext::SendReceiveStringList
bool SendReceiveStringList(QStringList &strlist, bool quickTimeout=false, bool block=true)
Send a message to the backend and wait for a response.
Definition: mythcorecontext.cpp:1371
getDiskSpace
int64_t getDiskSpace(const QString &file_on_disk, int64_t &total, int64_t &used)
Definition: mythcoreutil.cpp:33
FileSystemInfo::FromStringList
bool FromStringList(const QStringList &slist)
Definition: filesysteminfo.cpp:111
FileSystemInfo::getPath
QString getPath(void) const
Definition: filesysteminfo.h:34
FileSystemInfo::Consolidate
static void Consolidate(QList< FileSystemInfo > &disks, bool merge=true, int64_t fuzz=14000)
Definition: filesysteminfo.cpp:165
mythcoreutil.h
FileSystemInfo::ToStringList
bool ToStringList(QStringList &slist) const
Definition: filesysteminfo.cpp:97
FileSystemInfo::FileSystemInfo
FileSystemInfo()=default
MythSocket
Class for communcating between myth backends and frontends.
Definition: mythsocket.h:25
FileSystemInfo::setTotalSpace
void setTotalSpace(int64_t size)
Definition: filesysteminfo.h:53
NUMDISKINFOLINES
static constexpr int8_t NUMDISKINFOLINES
Definition: filesysteminfo.h:3
FileSystemInfo::RemoteGetInfo
static QList< FileSystemInfo > RemoteGetInfo(MythSocket *sock=nullptr)
Definition: filesysteminfo.cpp:137
FileSystemInfo::m_hostname
QString m_hostname
Definition: filesysteminfo.h:70
FileSystemInfo::setLocal
void setLocal(bool local=true)
Definition: filesysteminfo.h:49
statfs
int statfs(const char *path, struct statfs *buffer)
Definition: compat.h:105
compat.h
FileSystemInfo::m_local
bool m_local
Definition: filesysteminfo.h:72
FileSystemInfo::clone
virtual void clone(const FileSystemInfo &other)
Definition: filesysteminfo.cpp:62
NEXT_STR
#define NEXT_STR()
Definition: filesysteminfo.cpp:31
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
FileSystemInfo::PopulateFSProp
void PopulateFSProp(void)
Definition: filesysteminfo.cpp:224
FileSystemInfo::PopulateDiskSpace
void PopulateDiskSpace(void)
Definition: filesysteminfo.cpp:215
FileSystemInfo::m_weight
int m_weight
Definition: filesysteminfo.h:78
statfs
Definition: compat.h:93
FileSystemInfo
Definition: filesysteminfo.h:15
std
Definition: mythchrono.h:23
FileSystemInfo::m_blksize
int m_blksize
Definition: filesysteminfo.h:75
statfs::f_bsize
long f_bsize
Definition: compat.h:95
FileSystemInfo::setBlockSize
void setBlockSize(int size)
Definition: filesysteminfo.h:52
FileSystemInfo::m_used
int64_t m_used
Definition: filesysteminfo.h:77
musicbrainzngs.caa.hostname
string hostname
Definition: caa.py:17
FileSystemInfo::m_grpid
int m_grpid
Definition: filesysteminfo.h:74
FileSystemInfo::clear
void clear(void)
Definition: filesysteminfo.cpp:84
MythSocket::SendReceiveStringList
bool SendReceiveStringList(QStringList &list, uint min_reply_length=0, std::chrono::milliseconds timeoutMS=kLongTimeout)
Definition: mythsocket.cpp:326
FileSystemInfo::operator=
FileSystemInfo & operator=(const FileSystemInfo &other)
Definition: filesysteminfo.cpp:75