1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #include "remotelinuxcheckforfreediskspaceservice.h"
27 
28 #include <ssh/sshremoteprocessrunner.h>
29 #include <utils/fileutils.h>
30 
31 namespace RemoteLinux {
32 namespace Internal {
33 class RemoteLinuxCheckForFreeDiskSpaceServicePrivate
34 {
35 public:
36     QString pathToCheck;
37     quint64 requiredSpaceInBytes;
38     QSsh::SshRemoteProcessRunner *processRunner;
39 };
40 } // namespace Internal
41 
RemoteLinuxCheckForFreeDiskSpaceService(QObject * parent)42 RemoteLinuxCheckForFreeDiskSpaceService::RemoteLinuxCheckForFreeDiskSpaceService(QObject *parent)
43         : AbstractRemoteLinuxDeployService(parent),
44           d(new Internal::RemoteLinuxCheckForFreeDiskSpaceServicePrivate)
45 {
46     d->processRunner = nullptr;
47     d->requiredSpaceInBytes = 0;
48 }
49 
~RemoteLinuxCheckForFreeDiskSpaceService()50 RemoteLinuxCheckForFreeDiskSpaceService::~RemoteLinuxCheckForFreeDiskSpaceService()
51 {
52     cleanup();
53     delete d;
54 }
55 
setPathToCheck(const QString & path)56 void RemoteLinuxCheckForFreeDiskSpaceService::setPathToCheck(const QString &path)
57 {
58     d->pathToCheck = path;
59 }
60 
setRequiredSpaceInBytes(quint64 sizeInBytes)61 void RemoteLinuxCheckForFreeDiskSpaceService::setRequiredSpaceInBytes(quint64 sizeInBytes)
62 {
63     d->requiredSpaceInBytes = sizeInBytes;
64 }
65 
handleStdErr()66 void RemoteLinuxCheckForFreeDiskSpaceService::handleStdErr()
67 {
68     emit stdErrData(QString::fromUtf8(d->processRunner->readAllStandardError()));
69 }
70 
handleProcessFinished()71 void RemoteLinuxCheckForFreeDiskSpaceService::handleProcessFinished()
72 {
73     if (!d->processRunner->processErrorString().isEmpty()) {
74         emit errorMessage(tr("Remote process failed: %1")
75                           .arg(d->processRunner->processErrorString()));
76         stopDeployment();
77         return;
78 
79     }
80 
81     bool isNumber;
82     QByteArray processOutput = d->processRunner->readAllStandardOutput();
83     processOutput.chop(1); // newline
84     quint64 freeSpace = processOutput.toULongLong(&isNumber);
85     quint64 requiredSpaceInMegaBytes = d->requiredSpaceInBytes / (1024 * 1024);
86     if (!isNumber) {
87         emit errorMessage(tr("Unexpected output from remote process: \"%1\"")
88                 .arg(QString::fromUtf8(processOutput)));
89         stopDeployment();
90         return;
91     }
92 
93     freeSpace /= 1024; // convert kilobyte to megabyte
94     if (freeSpace < requiredSpaceInMegaBytes) {
95         emit errorMessage(tr("The remote file system has only %n megabytes of free space, "
96                 "but %1 megabytes are required.", nullptr, freeSpace).arg(requiredSpaceInMegaBytes));
97         stopDeployment();
98         return;
99     }
100 
101     emit progressMessage(tr("The remote file system has %n megabytes of free space, going ahead.",
102                             nullptr, freeSpace));
103     stopDeployment();
104 }
105 
isDeploymentPossible() const106 CheckResult RemoteLinuxCheckForFreeDiskSpaceService::isDeploymentPossible() const
107 {
108     if (!d->pathToCheck.startsWith(QLatin1Char('/'))) {
109         return CheckResult::failure(
110            tr("Cannot check for free disk space: \"%1\" is not an absolute path.")
111                     .arg(d->pathToCheck));
112     }
113 
114     return AbstractRemoteLinuxDeployService::isDeploymentPossible();
115 }
116 
doDeploy()117 void RemoteLinuxCheckForFreeDiskSpaceService::doDeploy()
118 {
119     d->processRunner = new QSsh::SshRemoteProcessRunner;
120     connect(d->processRunner, &QSsh::SshRemoteProcessRunner::processClosed,
121             this, &RemoteLinuxCheckForFreeDiskSpaceService::handleProcessFinished);
122     connect(d->processRunner, &QSsh::SshRemoteProcessRunner::readyReadStandardError,
123             this, &RemoteLinuxCheckForFreeDiskSpaceService::handleStdErr);
124     const QString command = QString::fromLatin1("df -k %1 |tail -n 1 |sed 's/  */ /g' "
125             "|cut -d ' ' -f 4").arg(d->pathToCheck);
126     d->processRunner->run(command, deviceConfiguration()->sshParameters());
127 }
128 
stopDeployment()129 void RemoteLinuxCheckForFreeDiskSpaceService::stopDeployment()
130 {
131     cleanup();
132     handleDeploymentDone();
133 }
134 
cleanup()135 void RemoteLinuxCheckForFreeDiskSpaceService::cleanup()
136 {
137     if (d->processRunner) {
138         disconnect(d->processRunner, nullptr, this, nullptr);
139         d->processRunner->cancel();
140         delete d->processRunner;
141         d->processRunner = nullptr;
142     }
143 }
144 
145 } // namespace RemoteLinux
146