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 "unzip.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(const QString &zipFile, const QString &outDir)
75 {
76  UnZip uz;
77  UnZip::ErrorCode ec = uz.openArchive(zipFile);
78 
79  if (ec != UnZip::Ok)
80  {
81  LOG(VB_GENERAL, LOG_ERR,
82  QString("extractZIP(): Unable to open ZIP file %1")
83  .arg(zipFile));
84  return false;
85  }
86 
87  ec = uz.extractAll(outDir);
88 
89  if (ec != UnZip::Ok)
90  {
91  LOG(VB_GENERAL, LOG_ERR,
92  QString("extractZIP(): Error extracting ZIP file %1")
93  .arg(zipFile));
94  return false;
95  }
96 
97  uz.closeArchive();
98 
99  return true;
100 }
101 
102 bool gzipFile(const QString &inFilename, const QString &gzipFilename)
103 {
104  QFile infile(inFilename);
105  QFile outfile(gzipFilename);
106 
107  if (!infile.open(QIODevice::ReadOnly))
108  {
109  LOG(VB_GENERAL, LOG_ERR, QString("gzipFile(): Error opening file for reading '%1'").arg(inFilename));
110  return false;
111  }
112 
113  if (!outfile.open(QIODevice::WriteOnly))
114  {
115  LOG(VB_GENERAL, LOG_ERR, QString("gzipFile(): Error opening file for writing '%1'").arg(gzipFilename));
116  infile.close();
117  return false;
118  }
119 
120  QByteArray uncompressedData = infile.readAll();
121  QByteArray compressedData = gzipCompress(uncompressedData);
122 
123  if (!outfile.write(compressedData))
124  {
125  LOG(VB_GENERAL, LOG_ERR, QString("gzipFile(): Error while writing to '%1'").arg(gzipFilename));
126  infile.close();
127  outfile.close();
128  return false;
129  }
130 
131  infile.close();
132  outfile.close();
133 
134  return true;
135 }
136 
137 bool gunzipFile(const QString &gzipFilename, const QString &outFilename)
138 {
139  QFile infile(gzipFilename);
140  QFile outfile(outFilename);
141 
142  if (!infile.open(QIODevice::ReadOnly))
143  {
144  LOG(VB_GENERAL, LOG_ERR, QString("gunzipFile(): Error opening file for reading '%1'").arg(gzipFilename));
145  return false;
146  }
147 
148  if (!outfile.open(QIODevice::WriteOnly))
149  {
150  LOG(VB_GENERAL, LOG_ERR, QString("gunzipFile(): Error opening file for writing '%1'").arg(outFilename));
151  infile.close();
152  return false;
153  }
154 
155  QByteArray compressedData = infile.readAll();
156  QByteArray uncompressedData = gzipUncompress(compressedData);
157 
158  if (outfile.write(uncompressedData) < uncompressedData.size())
159  {
160  LOG(VB_GENERAL, LOG_ERR, QString("gunzipFile(): Error while writing to '%1'").arg(outFilename));
161  infile.close();
162  outfile.close();
163  return false;
164  }
165 
166  infile.close();
167  outfile.close();
168 
169  return true;
170 }
171 
172 QByteArray gzipCompress(const QByteArray& data)
173 {
174  if (data.length() == 0)
175  return QByteArray();
176 
177  std::array <char,1024> out {};
178 
179  // allocate inflate state
180  z_stream strm;
181 
182  strm.zalloc = Z_NULL;
183  strm.zfree = Z_NULL;
184  strm.opaque = Z_NULL;
185  strm.avail_in = data.length();
186  strm.next_in = (Bytef*)(data.data());
187 
188  int ret = deflateInit2(&strm,
189  Z_DEFAULT_COMPRESSION,
190  Z_DEFLATED,
191  15 + 16,
192  8,
193  Z_DEFAULT_STRATEGY ); // gzip encoding
194  if (ret != Z_OK)
195  return QByteArray();
196 
197  QByteArray result;
198 
199  // run deflate()
200  do
201  {
202  strm.avail_out = out.size();
203  strm.next_out = (Bytef*)(out.data());
204 
205  ret = deflate(&strm, Z_FINISH);
206 
207  Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
208 
209  switch (ret)
210  {
211  case Z_NEED_DICT:
212  case Z_DATA_ERROR:
213  case Z_MEM_ERROR:
214  (void)deflateEnd(&strm);
215  return QByteArray();
216  }
217 
218  result.append(out.data(), out.size() - strm.avail_out);
219  }
220  while (strm.avail_out == 0);
221 
222  // clean up and return
223 
224  deflateEnd(&strm);
225 
226  return result;
227 }
228 
229 QByteArray gzipUncompress(const QByteArray &data)
230 {
231  if (data.length() == 0)
232  return QByteArray();
233 
234  std::array<char,1024> out {};
235 
236  // allocate inflate state
237  z_stream strm;
238 
239  strm.zalloc = Z_NULL;
240  strm.zfree = Z_NULL;
241  strm.opaque = Z_NULL;
242  strm.avail_in = data.length();
243  strm.next_in = (Bytef*)(data.data());
244 
245  int ret = inflateInit2(&strm, 15 + 16);
246 
247  if (ret != Z_OK)
248  return QByteArray();
249 
250  QByteArray result;
251 
252  do
253  {
254  strm.avail_out = out.size();
255  strm.next_out = (Bytef*)out.data();
256  ret = inflate(&strm, Z_NO_FLUSH);
257 
258  Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
259 
260  switch (ret)
261  {
262  case Z_NEED_DICT:
263  case Z_DATA_ERROR:
264  case Z_MEM_ERROR:
265  (void) deflateEnd(&strm);
266  return QByteArray();
267  }
268 
269  result.append(out.data(), out.size() - strm.avail_out);
270  }
271  while (strm.avail_out == 0);
272 
273  (void) inflateEnd(& strm);
274 
275  return result;
276 }
277 
278 static QString downloadRemoteFile(const QString &cmd, const QString &url,
279  const QString &storageGroup,
280  const QString &filename)
281 {
282  QStringList strlist(cmd);
283  strlist << url;
284  strlist << storageGroup;
285  strlist << filename;
286 
287  bool ok = gCoreContext->SendReceiveStringList(strlist);
288 
289  if (!ok || strlist.size() < 2 || strlist[0] != "OK")
290  {
291  LOG(VB_GENERAL, LOG_ERR,
292  "downloadRemoteFile(): " + cmd + " returned ERROR!");
293  return QString();
294  }
295 
296  return strlist[1];
297 }
298 
299 QString RemoteDownloadFile(const QString &url,
300  const QString &storageGroup,
301  const QString &filename)
302 {
303  return downloadRemoteFile("DOWNLOAD_FILE", url, storageGroup, filename);
304 }
305 
306 QString RemoteDownloadFileNow(const QString &url,
307  const QString &storageGroup,
308  const QString &filename)
309 {
310  return downloadRemoteFile("DOWNLOAD_FILE_NOW", url, storageGroup, filename);
311 }
312 
313 const char *GetMythSourceVersion()
314 {
315  return MYTH_SOURCE_VERSION;
316 }
317 
318 const char *GetMythSourcePath()
319 {
320  return MYTH_SOURCE_PATH;
321 }
322 
323 /* 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:1380
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:278
RemoteDownloadFileNow
QString RemoteDownloadFileNow(const QString &url, const QString &storageGroup, const QString &filename)
Definition: mythcoreutil.cpp:306
mythcoreutil.h
arg
arg(title).arg(filename).arg(doDelete))
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
UnZip::openArchive
ErrorCode openArchive(const QString &filename)
Definition: unzip.cpp:228
unzip.h
UnZip::extractAll
ErrorCode extractAll(const QString &dirname, ExtractionOptions options=ExtractPaths)
Definition: unzip.cpp:363
gzipCompress
QByteArray gzipCompress(const QByteArray &data)
Definition: mythcoreutil.cpp:172
UnZip::closeArchive
void closeArchive()
Definition: unzip.cpp:264
mythversion.h
mythlogging.h
statfs
int statfs(const char *path, struct statfs *buffer)
Definition: compat.h:179
compat.h
gzipFile
bool gzipFile(const QString &inFilename, const QString &gzipFilename)
Definition: mythcoreutil.cpp:102
UnZip::ErrorCode
ErrorCode
Definition: unzip.h:53
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:637
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
GetMythSourcePath
const char * GetMythSourcePath()
Definition: mythcoreutil.cpp:318
Z_NULL
#define Z_NULL
Definition: unzip.h:37
mythcorecontext.h
statfs::f_blocks
long f_blocks
Definition: compat.h:170
gunzipFile
bool gunzipFile(const QString &gzipFilename, const QString &outFilename)
Definition: mythcoreutil.cpp:137
statfs
Definition: compat.h:167
statfs::f_bsize
long f_bsize
Definition: compat.h:169
UnZip
PKZip 2.0 file decompression. Compatibility with later versions is not ensured as they may use unsupp...
Definition: unzip.h:50
UnZip::Ok
@ Ok
Definition: unzip.h:54
statfs::f_bavail
long f_bavail
Definition: compat.h:172
GetMythSourceVersion
const char * GetMythSourceVersion()
Definition: mythcoreutil.cpp:313
extractZIP
bool extractZIP(const QString &zipFile, const QString &outDir)
Definition: mythcoreutil.cpp:74
gzipUncompress
QByteArray gzipUncompress(const QByteArray &data)
Definition: mythcoreutil.cpp:229
RemoteDownloadFile
QString RemoteDownloadFile(const QString &url, const QString &storageGroup, const QString &filename)
Definition: mythcoreutil.cpp:299