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
|