Mercurial > hg > svcore
comparison 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 |
comparison
equal
deleted
inserted
replaced
80:8739096929dd | 81:f277a171749d |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2006 Chris Cannam. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #include "TempDirectory.h" | |
17 | |
18 #include <QDir> | |
19 #include <QFile> | |
20 #include <QMutexLocker> | |
21 | |
22 #include <iostream> | |
23 #include <cassert> | |
24 | |
25 TempDirectory * | |
26 TempDirectory::m_instance = new TempDirectory; | |
27 | |
28 TempDirectory * | |
29 TempDirectory::instance() | |
30 { | |
31 return m_instance; | |
32 } | |
33 | |
34 TempDirectory::DirectoryCreationFailed::DirectoryCreationFailed(QString directory) throw() : | |
35 m_directory(directory) | |
36 { | |
37 std::cerr << "ERROR: Directory creation failed for directory: " | |
38 << directory.toLocal8Bit().data() << std::endl; | |
39 } | |
40 | |
41 const char * | |
42 TempDirectory::DirectoryCreationFailed::what() const throw() | |
43 { | |
44 return QString("Directory creation failed for \"%1\"") | |
45 .arg(m_directory).toLocal8Bit().data(); | |
46 } | |
47 | |
48 TempDirectory::TempDirectory() : | |
49 m_tmpdir("") | |
50 { | |
51 } | |
52 | |
53 TempDirectory::~TempDirectory() | |
54 { | |
55 std::cerr << "TempDirectory::~TempDirectory" << std::endl; | |
56 | |
57 cleanup(); | |
58 } | |
59 | |
60 void | |
61 TempDirectory::cleanup() | |
62 { | |
63 cleanupDirectory(""); | |
64 } | |
65 | |
66 QString | |
67 TempDirectory::getPath() | |
68 { | |
69 QMutexLocker locker(&m_mutex); | |
70 | |
71 if (m_tmpdir != "") return m_tmpdir; | |
72 | |
73 QDir systemTempDir = QDir::temp(); | |
74 | |
75 // Generate a temporary directory. Qt4.1 doesn't seem to be able | |
76 // to do this for us, and mkdtemp is not standard. This method is | |
77 // based on the way glibc does mkdtemp. | |
78 | |
79 static QString chars = | |
80 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; | |
81 | |
82 QString suffix; | |
83 int padlen = 6, attempts = 100; | |
84 unsigned int r = time(0) ^ getpid(); | |
85 | |
86 for (int i = 0; i < padlen; ++i) { | |
87 suffix += "X"; | |
88 } | |
89 | |
90 for (int j = 0; j < attempts; ++j) { | |
91 | |
92 unsigned int v = r; | |
93 | |
94 for (int i = 0; i < padlen; ++i) { | |
95 suffix[i] = chars[v % 62]; | |
96 v /= 62; | |
97 } | |
98 | |
99 QString candidate = QString("sv_%1").arg(suffix); | |
100 | |
101 if (QDir::temp().mkpath(candidate)) { | |
102 m_tmpdir = systemTempDir.filePath(candidate); | |
103 break; | |
104 } | |
105 | |
106 r = r + 7777; | |
107 } | |
108 | |
109 if (m_tmpdir == "") { | |
110 throw DirectoryCreationFailed(QString("temporary subdirectory in %1") | |
111 .arg(systemTempDir.canonicalPath())); | |
112 } | |
113 | |
114 return m_tmpdir; | |
115 } | |
116 | |
117 QString | |
118 TempDirectory::getSubDirectoryPath(QString subdir) | |
119 { | |
120 QString tmpdirpath = getPath(); | |
121 | |
122 QMutexLocker locker(&m_mutex); | |
123 | |
124 QDir tmpdir(tmpdirpath); | |
125 QFileInfo fi(tmpdir.filePath(subdir)); | |
126 | |
127 if (!fi.exists()) { | |
128 if (!tmpdir.mkdir(subdir)) { | |
129 throw DirectoryCreationFailed(fi.filePath()); | |
130 } else { | |
131 return fi.filePath(); | |
132 } | |
133 } else if (fi.isDir()) { | |
134 return fi.filePath(); | |
135 } else { | |
136 throw DirectoryCreationFailed(fi.filePath()); | |
137 } | |
138 } | |
139 | |
140 void | |
141 TempDirectory::cleanupDirectory(QString tmpdir) | |
142 { | |
143 bool isRoot = false; | |
144 | |
145 if (tmpdir == "") { | |
146 | |
147 m_mutex.lock(); | |
148 | |
149 isRoot = true; | |
150 tmpdir = m_tmpdir; | |
151 | |
152 if (tmpdir == "") { | |
153 m_mutex.unlock(); | |
154 return; | |
155 } | |
156 } | |
157 | |
158 QDir dir(tmpdir); | |
159 dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); | |
160 | |
161 for (unsigned int i = 0; i < dir.count(); ++i) { | |
162 | |
163 QFileInfo fi(dir.filePath(dir[i])); | |
164 | |
165 if (fi.isDir()) { | |
166 cleanupDirectory(fi.absoluteFilePath()); | |
167 } else { | |
168 if (!QFile(fi.absoluteFilePath()).remove()) { | |
169 std::cerr << "WARNING: TempDirectory::cleanup: " | |
170 << "Failed to unlink file \"" | |
171 << fi.absoluteFilePath().toStdString() << "\"" | |
172 << std::endl; | |
173 } | |
174 } | |
175 } | |
176 | |
177 QString dirname = dir.dirName(); | |
178 if (dirname != "") { | |
179 if (!dir.cdUp()) { | |
180 std::cerr << "WARNING: TempDirectory::cleanup: " | |
181 << "Failed to cd to parent directory of " | |
182 << tmpdir.toStdString() << std::endl; | |
183 return; | |
184 } | |
185 if (!dir.rmdir(dirname)) { | |
186 std::cerr << "WARNING: TempDirectory::cleanup: " | |
187 << "Failed to remove directory " | |
188 << dirname.toStdString() << std::endl; | |
189 } | |
190 } | |
191 | |
192 if (isRoot) { | |
193 m_tmpdir = ""; | |
194 m_mutex.unlock(); | |
195 } | |
196 } |