Mercurial > hg > svcore
diff base/TempDirectory.cpp @ 81:f277a171749d
* Pull out temporary directory management into its own class
* Make sure playback plugins get a default sample path in their original
play parameters configuration
* Save play parameters to .sv file (we aren't reloading yet though)
author | Chris Cannam |
---|---|
date | Tue, 25 Apr 2006 22:14:43 +0000 |
parents | |
children | bf42d8d63885 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/base/TempDirectory.cpp Tue Apr 25 22:14:43 2006 +0000 @@ -0,0 +1,196 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006 Chris Cannam. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "TempDirectory.h" + +#include <QDir> +#include <QFile> +#include <QMutexLocker> + +#include <iostream> +#include <cassert> + +TempDirectory * +TempDirectory::m_instance = new TempDirectory; + +TempDirectory * +TempDirectory::instance() +{ + return m_instance; +} + +TempDirectory::DirectoryCreationFailed::DirectoryCreationFailed(QString directory) throw() : + m_directory(directory) +{ + std::cerr << "ERROR: Directory creation failed for directory: " + << directory.toLocal8Bit().data() << std::endl; +} + +const char * +TempDirectory::DirectoryCreationFailed::what() const throw() +{ + return QString("Directory creation failed for \"%1\"") + .arg(m_directory).toLocal8Bit().data(); +} + +TempDirectory::TempDirectory() : + m_tmpdir("") +{ +} + +TempDirectory::~TempDirectory() +{ + std::cerr << "TempDirectory::~TempDirectory" << std::endl; + + cleanup(); +} + +void +TempDirectory::cleanup() +{ + cleanupDirectory(""); +} + +QString +TempDirectory::getPath() +{ + QMutexLocker locker(&m_mutex); + + if (m_tmpdir != "") return m_tmpdir; + + QDir systemTempDir = QDir::temp(); + + // Generate a temporary directory. Qt4.1 doesn't seem to be able + // to do this for us, and mkdtemp is not standard. This method is + // based on the way glibc does mkdtemp. + + static QString chars = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + + QString suffix; + int padlen = 6, attempts = 100; + unsigned int r = time(0) ^ getpid(); + + for (int i = 0; i < padlen; ++i) { + suffix += "X"; + } + + for (int j = 0; j < attempts; ++j) { + + unsigned int v = r; + + for (int i = 0; i < padlen; ++i) { + suffix[i] = chars[v % 62]; + v /= 62; + } + + QString candidate = QString("sv_%1").arg(suffix); + + if (QDir::temp().mkpath(candidate)) { + m_tmpdir = systemTempDir.filePath(candidate); + break; + } + + r = r + 7777; + } + + if (m_tmpdir == "") { + throw DirectoryCreationFailed(QString("temporary subdirectory in %1") + .arg(systemTempDir.canonicalPath())); + } + + return m_tmpdir; +} + +QString +TempDirectory::getSubDirectoryPath(QString subdir) +{ + QString tmpdirpath = getPath(); + + QMutexLocker locker(&m_mutex); + + QDir tmpdir(tmpdirpath); + QFileInfo fi(tmpdir.filePath(subdir)); + + if (!fi.exists()) { + if (!tmpdir.mkdir(subdir)) { + throw DirectoryCreationFailed(fi.filePath()); + } else { + return fi.filePath(); + } + } else if (fi.isDir()) { + return fi.filePath(); + } else { + throw DirectoryCreationFailed(fi.filePath()); + } +} + +void +TempDirectory::cleanupDirectory(QString tmpdir) +{ + bool isRoot = false; + + if (tmpdir == "") { + + m_mutex.lock(); + + isRoot = true; + tmpdir = m_tmpdir; + + if (tmpdir == "") { + m_mutex.unlock(); + return; + } + } + + QDir dir(tmpdir); + dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); + + for (unsigned int i = 0; i < dir.count(); ++i) { + + QFileInfo fi(dir.filePath(dir[i])); + + if (fi.isDir()) { + cleanupDirectory(fi.absoluteFilePath()); + } else { + if (!QFile(fi.absoluteFilePath()).remove()) { + std::cerr << "WARNING: TempDirectory::cleanup: " + << "Failed to unlink file \"" + << fi.absoluteFilePath().toStdString() << "\"" + << std::endl; + } + } + } + + QString dirname = dir.dirName(); + if (dirname != "") { + if (!dir.cdUp()) { + std::cerr << "WARNING: TempDirectory::cleanup: " + << "Failed to cd to parent directory of " + << tmpdir.toStdString() << std::endl; + return; + } + if (!dir.rmdir(dirname)) { + std::cerr << "WARNING: TempDirectory::cleanup: " + << "Failed to remove directory " + << dirname.toStdString() << std::endl; + } + } + + if (isRoot) { + m_tmpdir = ""; + m_mutex.unlock(); + } +}