MythTV  master
mythcoreutil.cpp
Go to the documentation of this file.
1 
2 #include "mythcoreutil.h"
3 
4 // POSIX
5 #include <unistd.h>
6 #include <fcntl.h>
7 
8 // System specific C headers
9 #include "compat.h"
10 
11 #ifdef linux
12 #include <sys/vfs.h>
13 #include <sys/sysinfo.h>
14 #endif
15 
16 #if CONFIG_DARWIN
17 #include <mach/mach.h>
18 #endif
19 
20 #ifdef BSD
21 #include <sys/mount.h> // for struct statfs
22 #include <sys/sysctl.h>
23 #endif
24 
25 // Qt headers
26 #include <QByteArray>
27 #include <QStringList>
28 #include <QFile>
29 
30 // libmythbase headers
31 #include "mythcorecontext.h"
32 #include "mythlogging.h"
33 #include "unzip2.h"
34 
35 #include "version.h"
36 #include "mythversion.h"
37 
43 int64_t getDiskSpace(const QString &file_on_disk,
44  int64_t &total, int64_t &used)
45 {
46  struct statfs statbuf {};
47  int64_t freespace = -1;
48  QByteArray cstr = file_on_disk.toLocal8Bit();
49 
50  total = used = -1;
51 
52  // there are cases where statfs will return 0 (good), but f_blocks and
53  // others are invalid and set to 0 (such as when an automounted directory
54  // is not mounted but still visible because --ghost was used),
55  // so check to make sure we can have a total size > 0
56  if ((statfs(cstr.constData(), &statbuf) == 0) &&
57  (statbuf.f_blocks > 0) &&
58  (statbuf.f_bsize > 0))
59  {
60  total = statbuf.f_blocks;
61  total *= statbuf.f_bsize;
62  total = total >> 10;
63 
64  freespace = statbuf.f_bavail;
65  freespace *= statbuf.f_bsize;
66  freespace = freespace >> 10;
67 
68  used = total - freespace;
69  }
70 
71  return freespace;
72 }
73 
74 bool extractZIP(QString &zipFile, const QString &outDir)
75 {
76  UnZip unzip(zipFile);
77  return unzip.extractFile(outDir);
78 }
79 
80 bool gzipFile(const QString &inFilename, const QString &gzipFilename)
81 {
82  QFile infile(inFilename);
83  QFile outfile(gzipFilename);
84 
85  if (!infile.open(QIODevice::ReadOnly))
86  {
87  LOG(VB_GENERAL, LOG_ERR, QString("gzipFile(): Error opening file for reading '%1'").arg(inFilename));
88  return false;
89  }
90 
91  if (!outfile.open(QIODevice::WriteOnly))
92  {
93  LOG(VB_GENERAL, LOG_ERR, QString("gzipFile(): Error opening file for writing '%1'").arg(gzipFilename));
94  infile.close();
95  return false;
96  }
97 
98  QByteArray uncompressedData = infile.readAll();
99  QByteArray compressedData = gzipCompress(uncompressedData);
100 
101  if (!outfile.write(compressedData))
102  {
103  LOG(VB_GENERAL, LOG_ERR, QString("gzipFile(): Error while writing to '%1'").arg(gzipFilename));
104  infile.close();
105  outfile.close();
106  return false;
107  }
108 
109  infile.close();
110  outfile.close();
111 
112  return true;
113 }
114 
115 bool gunzipFile(const QString &gzipFilename, const QString &outFilename)
116 {
117  QFile infile(gzipFilename);
118  QFile outfile(outFilename);
119 
120  if (!infile.open(QIODevice::ReadOnly))
121  {
122  LOG(VB_GENERAL, LOG_ERR, QString("gunzipFile(): Error opening file for reading '%1'").arg(gzipFilename));
123  return false;
124  }
125 
126  if (!outfile.open(QIODevice::WriteOnly))
127  {
128  LOG(VB_GENERAL, LOG_ERR, QString("gunzipFile(): Error opening file for writing '%1'").arg(outFilename));
129  infile.close();
130  return false;
131  }
132 
133  QByteArray compressedData = infile.readAll();
134  QByteArray uncompressedData = gzipUncompress(compressedData);
135 
136  if (outfile.write(uncompressedData) < uncompressedData.size())
137  {
138  LOG(VB_GENERAL, LOG_ERR, QString("gunzipFile(): Error while writing to '%1'").arg(outFilename));
139  infile.close();
140  outfile.close();
141  return false;
142  }
143 
144  infile.close();
145  outfile.close();
146 
147  return true;
148 }
149 
150 QByteArray gzipCompress(const QByteArray& data)
151 {
152  if (data.length() == 0)
153  return QByteArray();
154 
155  std::array <char,1024> out {};
156 
157  // allocate inflate state
158  z_stream strm {};
159 
160  strm.zalloc = Z_NULL;
161  strm.zfree = Z_NULL;
162  strm.opaque = Z_NULL;
163  strm.avail_in = data.length();
164  strm.next_in = (Bytef*)(data.data());
165 
166  int ret = deflateInit2(&strm,
167  Z_DEFAULT_COMPRESSION,
168  Z_DEFLATED,
169  15 + 16,
170  8,
171  Z_DEFAULT_STRATEGY ); // gzip encoding
172  if (ret != Z_OK)
173  return QByteArray();
174 
175  QByteArray result;
176 
177  // run deflate()
178  do
179  {
180  strm.avail_out = out.size();
181  strm.next_out = (Bytef*)(out.data());
182 
183  ret = deflate(&strm, Z_FINISH);
184 
185  Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
186 
187  switch (ret)
188  {
189  case Z_NEED_DICT:
190  case Z_DATA_ERROR:
191  case Z_MEM_ERROR:
192  (void)deflateEnd(&strm);
193  return QByteArray();
194  }
195 
196  result.append(out.data(), out.size() - strm.avail_out);
197  }
198  while (strm.avail_out == 0);
199 
200  // clean up and return
201 
202  deflateEnd(&strm);
203 
204  return result;
205 }
206 
207 QByteArray gzipUncompress(const QByteArray &data)
208 {
209  if (data.length() == 0)
210  return QByteArray();
211 
212  std::array<char,1024> out {};
213 
214  // allocate inflate state
215  z_stream strm;
216  strm.total_in = 0;
217  strm.total_out = 0;
218  strm.zalloc = Z_NULL;
219  strm.zfree = Z_NULL;
220  strm.opaque = Z_NULL;
221  strm.avail_in = data.length();
222  strm.next_in = (Bytef*)(data.data());
223 
224  int ret = inflateInit2(&strm, 15 + 16);
225 
226  if (ret != Z_OK)
227  return QByteArray();
228 
229  QByteArray result;
230 
231  do
232  {
233  strm.avail_out = out.size();
234  strm.next_out = (Bytef*)out.data();
235  ret = inflate(&strm, Z_NO_FLUSH);
236 
237  Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
238 
239  switch (ret)
240  {
241  case Z_NEED_DICT:
242  case Z_DATA_ERROR:
243  case Z_MEM_ERROR:
244  (void) deflateEnd(&strm);
245  return QByteArray();
246  }
247 
248  result.append(out.data(), out.size() - strm.avail_out);
249  }
250  while (strm.avail_out == 0);
251 
252  (void) inflateEnd(& strm);
253 
254  return result;
255 }
256 
257 static QString downloadRemoteFile(const QString &cmd, const QString &url,
258  const QString &storageGroup,
259  const QString &filename)
260 {
261  QStringList strlist(cmd);
262  strlist << url;
263  strlist << storageGroup;
264  strlist << filename;
265 
266  bool ok = gCoreContext->SendReceiveStringList(strlist);
267 
268  if (!ok || strlist.size() < 2 || strlist[0] != "OK")
269  {
270  LOG(VB_GENERAL, LOG_ERR,
271  "downloadRemoteFile(): " + cmd + " returned ERROR!");
272  return QString();
273  }
274 
275  return strlist[1];
276 }
277 
278 QString RemoteDownloadFile(const QString &url,
279  const QString &storageGroup,
280  const QString &filename)
281 {
282  return downloadRemoteFile("DOWNLOAD_FILE", url, storageGroup, filename);
283 }
284 
285 QString RemoteDownloadFileNow(const QString &url,
286  const QString &storageGroup,
287  const QString &filename)
288 {
289  return downloadRemoteFile("DOWNLOAD_FILE_NOW", url, storageGroup, filename);
290 }
291 
292 const char *GetMythSourceVersion()
293 {
294  return MYTH_SOURCE_VERSION;
295 }
296 
297 const char *GetMythSourcePath()
298 {
299  return MYTH_SOURCE_PATH;
300 }
301 
302 /* vim: set expandtab tabstop=4 shiftwidth=4: */
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:1395
getDiskSpace
int64_t getDiskSpace(const QString &file_on_disk, int64_t &total, int64_t &used)
Definition: mythcoreutil.cpp:43
downloadRemoteFile
static QString downloadRemoteFile(const QString &cmd, const QString &url, const QString &storageGroup, const QString &filename)
Definition: mythcoreutil.cpp:257
extractZIP
bool extractZIP(QString &zipFile, const QString &outDir)
Definition: mythcoreutil.cpp:74
RemoteDownloadFileNow
QString RemoteDownloadFileNow(const QString &url, const QString &storageGroup, const QString &filename)
Definition: mythcoreutil.cpp:285
mythcoreutil.h
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
gzipCompress
QByteArray gzipCompress(const QByteArray &data)
Definition: mythcoreutil.cpp:150
Z_NULL
#define Z_NULL
Definition: unzip2.h:23
unzip2.h
mythversion.h
mythlogging.h
statfs
int statfs(const char *path, struct statfs *buffer)
Definition: compat.h:180
compat.h
gzipFile
bool gzipFile(const QString &inFilename, const QString &gzipFilename)
Definition: mythcoreutil.cpp:80
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
GetMythSourcePath
const char * GetMythSourcePath()
Definition: mythcoreutil.cpp:297
UnZip::extractFile
bool extractFile(const QString &outDir)
Definition: unzip2.cpp:255
mythcorecontext.h
statfs::f_blocks
long f_blocks
Definition: compat.h:171
gunzipFile
bool gunzipFile(const QString &gzipFilename, const QString &outFilename)
Definition: mythcoreutil.cpp:115
statfs
Definition: compat.h:168
statfs::f_bsize
long f_bsize
Definition: compat.h:170
UnZip
Definition: unzip2.h:32
statfs::f_bavail
long f_bavail
Definition: compat.h:173
GetMythSourceVersion
const char * GetMythSourceVersion()
Definition: mythcoreutil.cpp:292
gzipUncompress
QByteArray gzipUncompress(const QByteArray &data)
Definition: mythcoreutil.cpp:207
build_compdb.filename
filename
Definition: build_compdb.py:21
RemoteDownloadFile
QString RemoteDownloadFile(const QString &url, const QString &storageGroup, const QString &filename)
Definition: mythcoreutil.cpp:278