annotate base/TempDirectory.cpp @ 104:40effd83ebcf

servlet name in the file xml \ user name and pwd are encoding
author benoitrigolleau
date Thu, 12 Jul 2007 15:06:41 +0000
parents 880dce3d7b00
children be6f263fa0ab
rev   line source
lbajardsilogic@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
lbajardsilogic@0 2
lbajardsilogic@0 3 /*
lbajardsilogic@0 4 Sonic Visualiser
lbajardsilogic@0 5 An audio file viewer and annotation editor.
lbajardsilogic@0 6 Centre for Digital Music, Queen Mary, University of London.
lbajardsilogic@0 7 This file copyright 2006 Chris Cannam.
lbajardsilogic@0 8
lbajardsilogic@0 9 This program is free software; you can redistribute it and/or
lbajardsilogic@0 10 modify it under the terms of the GNU General Public License as
lbajardsilogic@0 11 published by the Free Software Foundation; either version 2 of the
lbajardsilogic@0 12 License, or (at your option) any later version. See the file
lbajardsilogic@0 13 COPYING included with this distribution for more information.
lbajardsilogic@0 14 */
lbajardsilogic@0 15
lbajardsilogic@0 16 #include "TempDirectory.h"
lbajardsilogic@0 17 #include "system/System.h"
lbajardsilogic@0 18 #include "Exceptions.h"
lbajardsilogic@0 19
lbajardsilogic@0 20 #include <QDir>
lbajardsilogic@0 21 #include <QFile>
lbajardsilogic@0 22 #include <QMutexLocker>
lbajardsilogic@0 23 #include <QSettings>
lbajardsilogic@0 24
lbajardsilogic@0 25 #include <iostream>
lbajardsilogic@0 26 #include <cassert>
lbajardsilogic@0 27
lbajardsilogic@0 28 TempDirectory *
lbajardsilogic@0 29 TempDirectory::m_instance = new TempDirectory;
lbajardsilogic@0 30
lbajardsilogic@0 31 TempDirectory *
lbajardsilogic@0 32 TempDirectory::getInstance()
lbajardsilogic@0 33 {
lbajardsilogic@0 34 return m_instance;
lbajardsilogic@0 35 }
lbajardsilogic@0 36
lbajardsilogic@0 37 TempDirectory::TempDirectory() :
lbajardsilogic@0 38 m_tmpdir("")
lbajardsilogic@0 39 {
lbajardsilogic@0 40 }
lbajardsilogic@0 41
lbajardsilogic@0 42 TempDirectory::~TempDirectory()
lbajardsilogic@0 43 {
lbajardsilogic@0 44 std::cerr << "TempDirectory::~TempDirectory" << std::endl;
lbajardsilogic@0 45
lbajardsilogic@0 46 cleanup();
lbajardsilogic@0 47 }
lbajardsilogic@0 48
lbajardsilogic@0 49 void
lbajardsilogic@0 50 TempDirectory::cleanup()
lbajardsilogic@0 51 {
lbajardsilogic@0 52 cleanupDirectory("");
lbajardsilogic@0 53 }
lbajardsilogic@0 54
lbajardsilogic@12 55 QString
lbajardsilogic@12 56 TempDirectory::getDir()
lbajardsilogic@12 57 {
lbajardsilogic@12 58 QMutexLocker locker(&m_mutex);
lbajardsilogic@12 59
lbajardsilogic@12 60 QString svDirBase = ".easaier";
lbajardsilogic@12 61 QString svDir = QDir::home().filePath(svDirBase);
lbajardsilogic@12 62 if (!QFileInfo(svDir).exists()) {
lbajardsilogic@12 63 if (!QDir::home().mkdir(svDirBase)) {
lbajardsilogic@12 64 throw DirectoryCreationFailed(QString("%1 directory in $HOME")
lbajardsilogic@12 65 .arg(svDirBase));
lbajardsilogic@12 66 }
lbajardsilogic@12 67 } else if (!QFileInfo(svDir).isDir()) {
lbajardsilogic@12 68 throw DirectoryCreationFailed(QString("$HOME/%1 is not a directory")
lbajardsilogic@12 69 .arg(svDirBase));
lbajardsilogic@12 70 }
lbajardsilogic@12 71
lbajardsilogic@12 72 cleanupAbandonedDirectories(svDir);
lbajardsilogic@12 73
lbajardsilogic@12 74 return svDir;
lbajardsilogic@12 75 }
lbajardsilogic@12 76
lbajardsilogic@0 77 QString
lbajardsilogic@0 78 TempDirectory::getPath()
lbajardsilogic@0 79 {
lbajardsilogic@0 80 if (m_tmpdir != "") return m_tmpdir;
lbajardsilogic@0 81
lbajardsilogic@12 82 QString svDir = getDir();
lbajardsilogic@0 83
lbajardsilogic@0 84 return createTempDirectoryIn(svDir);
lbajardsilogic@0 85 }
lbajardsilogic@0 86
lbajardsilogic@0 87 QString
lbajardsilogic@12 88 TempDirectory::getConfigPath()
lbajardsilogic@12 89 {
lbajardsilogic@12 90 QString configPath = getDir();
lbajardsilogic@12 91 configPath.append("/config.xml");
lbajardsilogic@12 92
lbajardsilogic@12 93 return configPath;
lbajardsilogic@12 94 }
lbajardsilogic@12 95
lbajardsilogic@12 96 QString
lbajardsilogic@0 97 TempDirectory::createTempDirectoryIn(QString dir)
lbajardsilogic@0 98 {
lbajardsilogic@0 99 // Entered with mutex held.
lbajardsilogic@0 100
lbajardsilogic@0 101 QDir tempDirBase(dir);
lbajardsilogic@0 102
lbajardsilogic@0 103 // Generate a temporary directory. Qt4.1 doesn't seem to be able
lbajardsilogic@0 104 // to do this for us, and mkdtemp is not standard. This method is
lbajardsilogic@0 105 // based on the way glibc does mkdtemp.
lbajardsilogic@0 106
lbajardsilogic@0 107 static QString chars =
lbajardsilogic@0 108 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
lbajardsilogic@0 109
lbajardsilogic@0 110 QString suffix;
lbajardsilogic@0 111 int padlen = 6, attempts = 100;
lbajardsilogic@0 112 unsigned int r = time(0) ^ getpid();
lbajardsilogic@0 113
lbajardsilogic@0 114 for (int i = 0; i < padlen; ++i) {
lbajardsilogic@0 115 suffix += "X";
lbajardsilogic@0 116 }
lbajardsilogic@0 117
lbajardsilogic@0 118 for (int j = 0; j < attempts; ++j) {
lbajardsilogic@0 119
lbajardsilogic@0 120 unsigned int v = r;
lbajardsilogic@0 121
lbajardsilogic@0 122 for (int i = 0; i < padlen; ++i) {
lbajardsilogic@0 123 suffix[i] = chars[v % 62];
lbajardsilogic@0 124 v /= 62;
lbajardsilogic@0 125 }
lbajardsilogic@0 126
lbajardsilogic@0 127 QString candidate = QString("sv_%1").arg(suffix);
lbajardsilogic@0 128
lbajardsilogic@0 129 if (tempDirBase.mkpath(candidate)) {
lbajardsilogic@0 130 m_tmpdir = tempDirBase.filePath(candidate);
lbajardsilogic@0 131 break;
lbajardsilogic@0 132 }
lbajardsilogic@0 133
lbajardsilogic@0 134 r = r + 7777;
lbajardsilogic@0 135 }
lbajardsilogic@0 136
lbajardsilogic@0 137 if (m_tmpdir == "") {
lbajardsilogic@0 138 throw DirectoryCreationFailed(QString("temporary subdirectory in %1")
lbajardsilogic@0 139 .arg(tempDirBase.canonicalPath()));
lbajardsilogic@0 140 }
lbajardsilogic@0 141
lbajardsilogic@0 142 QString pidpath = QDir(m_tmpdir).filePath(QString("%1.pid").arg(getpid()));
lbajardsilogic@0 143 QFile pidfile(pidpath);
lbajardsilogic@0 144
lbajardsilogic@0 145 if (!pidfile.open(QIODevice::WriteOnly)) {
lbajardsilogic@0 146 throw DirectoryCreationFailed(QString("pid file creation in %1")
lbajardsilogic@0 147 .arg(m_tmpdir));
lbajardsilogic@0 148 } else {
lbajardsilogic@0 149 pidfile.close();
lbajardsilogic@0 150 }
lbajardsilogic@0 151
lbajardsilogic@0 152 return m_tmpdir;
lbajardsilogic@0 153 }
lbajardsilogic@0 154
lbajardsilogic@0 155 QString
lbajardsilogic@0 156 TempDirectory::getSubDirectoryPath(QString subdir)
lbajardsilogic@0 157 {
lbajardsilogic@0 158 QString tmpdirpath = getPath();
lbajardsilogic@0 159
lbajardsilogic@0 160 QMutexLocker locker(&m_mutex);
lbajardsilogic@0 161
lbajardsilogic@0 162 QDir tmpdir(tmpdirpath);
lbajardsilogic@0 163 QFileInfo fi(tmpdir.filePath(subdir));
lbajardsilogic@0 164
lbajardsilogic@0 165 if (!fi.exists()) {
lbajardsilogic@14 166 //if (!tmpdir.mkdir(subdir)) {
lbajardsilogic@14 167 if (!tmpdir.mkpath(subdir)) {
lbajardsilogic@0 168 throw DirectoryCreationFailed(fi.filePath());
lbajardsilogic@0 169 } else {
lbajardsilogic@0 170 return fi.filePath();
lbajardsilogic@0 171 }
lbajardsilogic@0 172 } else if (fi.isDir()) {
lbajardsilogic@0 173 return fi.filePath();
lbajardsilogic@0 174 } else {
lbajardsilogic@0 175 throw DirectoryCreationFailed(fi.filePath());
lbajardsilogic@0 176 }
lbajardsilogic@0 177 }
lbajardsilogic@0 178
lbajardsilogic@0 179 void
lbajardsilogic@0 180 TempDirectory::cleanupDirectory(QString tmpdir)
lbajardsilogic@0 181 {
lbajardsilogic@0 182 bool isRoot = false;
lbajardsilogic@0 183
lbajardsilogic@0 184 if (tmpdir == "") {
lbajardsilogic@0 185
lbajardsilogic@0 186 m_mutex.lock();
lbajardsilogic@0 187
lbajardsilogic@0 188 isRoot = true;
lbajardsilogic@0 189 tmpdir = m_tmpdir;
lbajardsilogic@0 190
lbajardsilogic@0 191 if (tmpdir == "") {
lbajardsilogic@0 192 m_mutex.unlock();
lbajardsilogic@0 193 return;
lbajardsilogic@0 194 }
lbajardsilogic@0 195 }
lbajardsilogic@0 196
lbajardsilogic@0 197 QDir dir(tmpdir);
lbajardsilogic@0 198 dir.setFilter(QDir::Dirs | QDir::Files);
lbajardsilogic@0 199
lbajardsilogic@0 200 for (unsigned int i = 0; i < dir.count(); ++i) {
lbajardsilogic@0 201
lbajardsilogic@0 202 if (dir[i] == "." || dir[i] == "..") continue;
lbajardsilogic@0 203 QFileInfo fi(dir.filePath(dir[i]));
lbajardsilogic@0 204
lbajardsilogic@0 205 if (fi.isDir()) {
lbajardsilogic@0 206 cleanupDirectory(fi.absoluteFilePath());
lbajardsilogic@0 207 } else {
lbajardsilogic@45 208 QFile tempFile(fi.absoluteFilePath());
lbajardsilogic@45 209 bool permit = tempFile.setPermissions(QFile::ReadOther | QFile::WriteOther);
lbajardsilogic@45 210 if (!permit)
lbajardsilogic@45 211 {
lbajardsilogic@45 212 std::cerr << "WARNING: TempDirectory::cleanup: "
lbajardsilogic@45 213 << "Permission denied \""
lbajardsilogic@45 214 << fi.absoluteFilePath().toStdString() << "\""
lbajardsilogic@45 215 << std::endl;
lbajardsilogic@45 216 }
lbajardsilogic@45 217 //if (!QFile(fi.absoluteFilePath()).remove())
lbajardsilogic@45 218 if (!tempFile.remove())
lbajardsilogic@45 219 {
lbajardsilogic@45 220 std::cerr << "WARNING: TempDirectory::cleanup: "
lbajardsilogic@0 221 << "Failed to unlink file \""
lbajardsilogic@0 222 << fi.absoluteFilePath().toStdString() << "\""
lbajardsilogic@0 223 << std::endl;
lbajardsilogic@0 224 }
lbajardsilogic@0 225 }
lbajardsilogic@0 226 }
lbajardsilogic@0 227
lbajardsilogic@0 228 QString dirname = dir.dirName();
lbajardsilogic@0 229 if (dirname != "") {
lbajardsilogic@0 230 if (!dir.cdUp()) {
lbajardsilogic@0 231 std::cerr << "WARNING: TempDirectory::cleanup: "
lbajardsilogic@0 232 << "Failed to cd to parent directory of "
lbajardsilogic@0 233 << tmpdir.toStdString() << std::endl;
lbajardsilogic@0 234 return;
lbajardsilogic@0 235 }
lbajardsilogic@0 236 if (!dir.rmdir(dirname)) {
lbajardsilogic@0 237 std::cerr << "WARNING: TempDirectory::cleanup: "
lbajardsilogic@0 238 << "Failed to remove directory "
lbajardsilogic@0 239 << dirname.toStdString() << std::endl;
lbajardsilogic@0 240 }
lbajardsilogic@0 241 }
lbajardsilogic@0 242
lbajardsilogic@0 243 if (isRoot) {
lbajardsilogic@0 244 m_tmpdir = "";
lbajardsilogic@0 245 m_mutex.unlock();
lbajardsilogic@0 246 }
lbajardsilogic@0 247 }
lbajardsilogic@0 248
lbajardsilogic@0 249 void
lbajardsilogic@0 250 TempDirectory::cleanupAbandonedDirectories(QString svDir)
lbajardsilogic@0 251 {
lbajardsilogic@0 252 QDir dir(svDir, "sv_*", QDir::Name, QDir::Dirs);
lbajardsilogic@0 253
lbajardsilogic@0 254 for (unsigned int i = 0; i < dir.count(); ++i) {
lbajardsilogic@0 255
lbajardsilogic@0 256 QDir subdir(dir.filePath(dir[i]), "*.pid", QDir::Name, QDir::Files);
lbajardsilogic@0 257
lbajardsilogic@0 258 for (unsigned int j = 0; j < subdir.count(); ++j) {
lbajardsilogic@0 259
lbajardsilogic@0 260 bool ok = false;
lbajardsilogic@0 261 int pid = QFileInfo(subdir[j]).baseName().toInt(&ok);
lbajardsilogic@0 262 if (!ok) continue;
lbajardsilogic@0 263
lbajardsilogic@0 264 if (GetProcessStatus(pid) == ProcessNotRunning) {
lbajardsilogic@0 265 std::cerr << "INFO: Found abandoned temporary directory from "
lbajardsilogic@41 266 << "an old Sound Access process\n(pid=" << pid
lbajardsilogic@0 267 << ", directory=\""
lbajardsilogic@0 268 << dir.filePath(dir[i]).toStdString()
lbajardsilogic@0 269 << "\"). Removing it..." << std::endl;
lbajardsilogic@0 270 cleanupDirectory(dir.filePath(dir[i]));
lbajardsilogic@0 271 std::cerr << "...done." << std::endl;
lbajardsilogic@0 272 break;
lbajardsilogic@0 273 }
lbajardsilogic@0 274 }
lbajardsilogic@0 275 }
lbajardsilogic@0 276 }
lbajardsilogic@0 277
lbajardsilogic@0 278
lbajardsilogic@0 279