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