13#include <QtCore/QDirIterator>
14#include <QtCore/QFileInfo>
15#include <QtCore/QProcessEnvironment>
56Sandbox *Sandbox::s_activeInstance = 0;
59 : m_defaultConstructed(true), m_usage(UseDirectly), m_scopes(ThisProcess),
60 m_sandboxPath(QProcessEnvironment::systemEnvironment().value(
"SSU_SANDBOX_DIR")),
64 qFatal(
"%s: Failed to activate", Q_FUNC_INFO);
68Sandbox::Sandbox(
const QString &sandboxPath, Usage usage, Scopes scopes)
69 : m_defaultConstructed(false), m_usage(usage), m_scopes(scopes),
70 m_sandboxPath(sandboxPath), m_prepared(false)
72 Q_ASSERT(!sandboxPath.isEmpty());
81 if (!m_tempDir.isEmpty() && QFileInfo(m_tempDir).exists()) {
82 if (!QDir(m_tempDir).removeRecursively()) {
83 qWarning(
"%s: Failed to remove temporary directory", Q_FUNC_INFO);
88bool Sandbox::isActive()
const
90 return s_activeInstance ==
this;
93bool Sandbox::activate()
95 Q_ASSERT_X(s_activeInstance == 0, Q_FUNC_INFO,
"Only one instance can be active!");
101 if (m_scopes & ChildProcesses) {
102 setenv(
"SSU_SANDBOX_DIR", qPrintable(m_workingSandboxDir.path()), 1);
105 s_activeInstance =
this;
109void Sandbox::deactivate()
111 Q_ASSERT(isActive());
113 if (m_scopes & ChildProcesses) {
114 unsetenv(
"SSU_SANDBOX_DIR");
117 s_activeInstance = 0;
120QDir Sandbox::effectiveRootDir()
122 return s_activeInstance != 0 && s_activeInstance->m_scopes & ThisProcess
123 ? s_activeInstance->m_workingSandboxDir
127QString Sandbox::map(
const QString &fileName)
129 return effectiveRootDir().filePath(
130 QDir::root().relativeFilePath(
131 QFileInfo(fileName).absoluteFilePath()));
134QString Sandbox::map(
const QString &pathName,
const QString &fileName)
136 return effectiveRootDir().filePath(
137 QDir::root().relativeFilePath(
138 QFileInfo(pathName + fileName).absoluteFilePath()));
147 const QStringList &filterNames,
bool recurse)
149 Q_ASSERT(!isActive());
150 Q_ASSERT(!directory.isEmpty());
156 const QString sandboxedDirectory = m_workingSandboxDir.filePath(
157 QDir::root().relativeFilePath(
158 QFileInfo(directory).absoluteFilePath()));
160 if (!QFileInfo(directory).exists()) {
162 qDebug(
"%s: Directory does not exist - an empty one will be created instead of copied: '%s'",
163 Q_FUNC_INFO, qPrintable(directory));
164 }
else if (!QFileInfo(directory).isDir()) {
165 qWarning(
"%s: Is not a directory: '%s'", Q_FUNC_INFO, qPrintable(directory));
169 if (!QFileInfo(sandboxedDirectory).exists()) {
170 if (!QDir().mkpath(sandboxedDirectory)) {
171 qWarning(
"%s: Failed to create sandbox directory '%s'", Q_FUNC_INFO,
172 qPrintable(sandboxedDirectory));
175 }
else if (!QFileInfo(sandboxedDirectory).isDir()) {
176 qWarning(
"%s: Failed to create sandbox directory '%s': Is not a directory", Q_FUNC_INFO,
177 qPrintable(sandboxedDirectory));
181 if (filters == QDir::NoFilter) {
182 filters = QDir::AllEntries;
185 filters |= QDir::NoDotAndDotDot;
187 foreach (
const QFileInfo &worldEntryInfo, QDir(directory).entryInfoList(filterNames, filters)) {
189 const QFileInfo sandboxEntryInfo(QDir(sandboxedDirectory).filePath(worldEntryInfo.fileName()));
191 if (worldEntryInfo.isDir()) {
192 if (!sandboxEntryInfo.exists()) {
193 if (!QDir(sandboxedDirectory).mkdir(worldEntryInfo.fileName())) {
194 qWarning(
"%s: Failed to create overlay directory '%s/%s'", Q_FUNC_INFO,
195 qPrintable(sandboxedDirectory), qPrintable(worldEntryInfo.fileName()));
198 }
else if (!sandboxEntryInfo.isDir()) {
199 qWarning(
"%s: Failed to create sandboxed copy '%s': Is not a directory", Q_FUNC_INFO,
200 qPrintable(sandboxEntryInfo.filePath()));
205 if (!
addWorldFiles(worldEntryInfo.absoluteFilePath(), filters, filterNames,
true)) {
210 if (!sandboxEntryInfo.exists()) {
211 if (!QFile(worldEntryInfo.filePath()).copy(sandboxEntryInfo.filePath())) {
212 qWarning(
"%s: Failed to copy file into sandbox '%s'", Q_FUNC_INFO,
213 qPrintable(worldEntryInfo.filePath()));
216 }
else if (sandboxEntryInfo.isDir()) {
217 qWarning(
"%s: Failed to create sandboxed copy '%s': Is a directory", Q_FUNC_INFO,
218 qPrintable(sandboxEntryInfo.filePath()));
227bool Sandbox::addWorldFile(
const QString &file)
230 QStringList() << QFileInfo(file).fileName());
233bool Sandbox::prepare()
235 Q_ASSERT(m_defaultConstructed || !m_sandboxPath.isEmpty());
241 if (m_sandboxPath.isEmpty()) {
245 if (!QFileInfo(m_sandboxPath).exists()) {
246 qWarning(
"%s: Invalid sandboxPath: No such file or directory", qPrintable(m_sandboxPath));
250 if (!QFileInfo(m_sandboxPath).isDir()) {
251 qWarning(
"%s: Invalid sandboxPath: Not a directory", qPrintable(m_sandboxPath));
255 if (m_usage == UseAsSkeleton) {
256 if (m_tempDir = createTmpDir(
"ssu-sandbox.%1"), m_tempDir.isEmpty()) {
257 qWarning(
"%s: Failed to create sandbox directory", Q_FUNC_INFO);
261 const QString sandboxCopyPath = QDir(m_tempDir).filePath(
"configroot");
263 if (!copyDir(m_sandboxPath, sandboxCopyPath)) {
264 qWarning(
"%s: Failed to copy sandbox directory", Q_FUNC_INFO);
268 m_workingSandboxDir = QDir(sandboxCopyPath);
270 m_workingSandboxDir = QDir(m_sandboxPath);
277QString Sandbox::createTmpDir(
const QString &nameTemplate)
279 const int REASONABLE_REPEAT_COUNT = 10;
281 for (
int i = 0; i < REASONABLE_REPEAT_COUNT; ++i) {
285 path = QDir::temp().filePath(nameTemplate.arg(++suffix));
286 }
while (QFileInfo(path).exists());
288 if (QDir().mkpath(path)) {
293 qWarning(
"%s: Failed to create temporary directory", Q_FUNC_INFO);
297bool Sandbox::copyDir(
const QString &directory,
const QString &newName)
299 const QDir sourceRoot(directory);
300 const QDir destinationRoot(newName);
302 QDirIterator it(directory, QDir::AllEntries | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
303 while (it.hasNext()) {
306 const QFileInfo destination = QFileInfo(destinationRoot.filePath(
307 sourceRoot.relativeFilePath(it.filePath())));
309 if (it.fileInfo().isDir()) {
310 if (!QDir().mkpath(destination.absoluteFilePath())) {
311 qWarning(
"%s: Failed to mkpath '%s'", Q_FUNC_INFO, qPrintable(destination.absolutePath()));
314 }
else if (it.fileInfo().isFile()) {
315 if (!QDir().mkpath(destination.absolutePath())) {
316 qWarning(
"%s: Failed to mkpath '%s'", Q_FUNC_INFO, qPrintable(destination.absolutePath()));
320 if (!QFile::copy(it.fileInfo().absoluteFilePath(), destination.absoluteFilePath())) {
321 qWarning(
"%s: Failed to copy file '%s'", Q_FUNC_INFO, qPrintable(it.filePath()));
325 qWarning(
"%s: Cannot copy other than regular files: '%s'", Q_FUNC_INFO,
326 qPrintable(it.filePath()));
Helps to redirect file operations into sandbox directory.
bool addWorldFiles(const QString &directory, QDir::Filters filters=QDir::NoFilter, const QStringList &filterNames=QStringList(), bool recurse=true)