Log filesystem free value to system trace.
[maemo-rb.git] / rbutil / rbutilqt / base / utils.cpp
blob1452ada330711001bc5313f22085daffe907c5f5
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2007 by Dominik Wenger
10 * $Id$
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include "utils.h"
21 #include "rockboxinfo.h"
22 #include "system.h"
23 #include "rbsettings.h"
24 #include "systeminfo.h"
26 #ifdef UNICODE
27 #define _UNICODE
28 #endif
30 #include <QtCore>
31 #include <QDebug>
32 #include <cstdlib>
33 #include <stdio.h>
35 #if defined(Q_OS_WIN32)
36 #include <windows.h>
37 #include <tchar.h>
38 #include <winioctl.h>
39 #endif
40 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
41 #include <sys/statvfs.h>
42 #endif
44 // recursive function to delete a dir with files
45 bool Utils::recursiveRmdir( const QString &dirName )
47 QString dirN = dirName;
48 QDir dir(dirN);
49 // make list of entries in directory
50 QStringList list = dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
51 QFileInfo fileInfo;
52 QString curItem, lstAt;
53 for(int i = 0; i < list.size(); i++){ // loop through all items of list
54 QString name = list.at(i);
55 curItem = dirN + "/" + name;
56 fileInfo.setFile(curItem);
57 if(fileInfo.isDir()) // is directory
58 recursiveRmdir(curItem); // call recRmdir() recursively for
59 // deleting subdirectory
60 else // is file
61 QFile::remove(curItem); // ok, delete file
63 dir.cdUp();
64 return dir.rmdir(dirN); // delete empty dir and return if (now empty)
65 // dir-removing was successfull
69 //! @brief resolves the given path, ignoring case.
70 //! @param path absolute path to resolve.
71 //! @return returns exact casing of path, empty string if path not found.
72 QString Utils::resolvePathCase(QString path)
74 QStringList elems;
75 QString realpath;
77 elems = path.split("/", QString::SkipEmptyParts);
78 int start;
79 #if defined(Q_OS_WIN32)
80 // on windows we must make sure to start with the first entry (i.e. the
81 // drive letter) instead of a single / to make resolving work.
82 start = 1;
83 realpath = elems.at(0) + "/";
84 #else
85 start = 0;
86 realpath = "/";
87 #endif
89 for(int i = start; i < elems.size(); i++) {
90 QStringList direlems
91 = QDir(realpath).entryList(QDir::AllEntries|QDir::Hidden|QDir::System);
92 if(direlems.contains(elems.at(i), Qt::CaseInsensitive)) {
93 // need to filter using QRegExp as QStringList::filter(QString)
94 // matches any substring
95 QString expr = QString("^" + elems.at(i) + "$");
96 QRegExp rx = QRegExp(expr, Qt::CaseInsensitive);
97 QStringList a = direlems.filter(rx);
99 if(a.size() != 1)
100 return QString("");
101 if(!realpath.endsWith("/"))
102 realpath += "/";
103 realpath += a.at(0);
105 else
106 return QString("");
108 qDebug() << "[Utils] resolving path" << path << "->" << realpath;
109 return realpath;
113 //! @brief figure the free disk space on a filesystem
114 //! @param path path on the filesystem to check
115 //! @return size in bytes
116 qulonglong Utils::filesystemFree(QString path)
118 qlonglong size = 0;
119 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
120 // the usage of statfs() is deprecated by the LSB so use statvfs().
121 struct statvfs fs;
122 int ret;
124 ret = statvfs(qPrintable(path), &fs);
126 if(ret == 0)
127 size = (qulonglong)fs.f_frsize * (qulonglong)fs.f_bavail;
128 #endif
129 #if defined(Q_OS_WIN32)
130 BOOL ret;
131 ULARGE_INTEGER freeAvailBytes;
133 ret = GetDiskFreeSpaceExW((LPCTSTR)path.utf16(), &freeAvailBytes, NULL, NULL);
134 if(ret)
135 size = freeAvailBytes.QuadPart;
136 #endif
137 qDebug() << "[Utils] Filesystem free:" << path << size;
138 return size;
141 //! \brief searches for a Executable in the Environement Path
142 QString Utils::findExecutable(QString name)
144 QString exepath;
145 //try autodetect tts
146 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX) || defined(Q_OS_OPENBSD)
147 QStringList path = QString(getenv("PATH")).split(":", QString::SkipEmptyParts);
148 #elif defined(Q_OS_WIN)
149 QStringList path = QString(getenv("PATH")).split(";", QString::SkipEmptyParts);
150 #endif
151 qDebug() << "[Utils] system path:" << path;
152 for(int i = 0; i < path.size(); i++)
154 QString executable = QDir::fromNativeSeparators(path.at(i)) + "/" + name;
155 #if defined(Q_OS_WIN)
156 executable += ".exe";
157 QStringList ex = executable.split("\"", QString::SkipEmptyParts);
158 executable = ex.join("");
159 #endif
160 qDebug() << "[Utils] executable:" << executable;
161 if(QFileInfo(executable).isExecutable())
163 return QDir::toNativeSeparators(executable);
166 return "";
170 /** @brief checks different Enviroment things. Ask if user wants to continue.
171 * @param permission if it should check for permission
172 * @return string with error messages if problems occurred, empty strings if none.
174 QString Utils::checkEnvironment(bool permission)
176 QString text = "";
178 // check permission
179 if(permission)
181 #if defined(Q_OS_WIN32)
182 if(System::userPermissions() != System::ADMIN)
184 text += tr("<li>Permissions insufficient for bootloader "
185 "installation.\nAdministrator priviledges are necessary.</li>");
187 #endif
190 // Check TargetId
191 RockboxInfo rbinfo(RbSettings::value(RbSettings::Mountpoint).toString());
192 QString installed = rbinfo.target();
193 if(!installed.isEmpty() && installed !=
194 SystemInfo::value(SystemInfo::CurConfigureModel).toString())
196 text += tr("<li>Target mismatch detected.\n"
197 "Installed target: %1, selected target: %2.</li>")
198 .arg(installed, SystemInfo::value(SystemInfo::CurPlatformName).toString());
199 // FIXME: replace installed by human-friendly name
202 if(!text.isEmpty())
203 return tr("Problem detected:") + "<ul>" + text + "</ul>";
204 else
205 return text;
207 /** @brief Compare two version strings.
208 * @param s1 first version string
209 * @param s2 second version string
210 * @return 0 if strings identical, 1 if second is newer, -1 if first.
212 int Utils::compareVersionStrings(QString s1, QString s2)
214 QString a = s1.trimmed();
215 QString b = s2.trimmed();
216 qDebug() << "[Utils] comparing version strings" << a << "and" << b;
217 // if strings are identical return 0.
218 if(a.isEmpty())
219 return 1;
220 if(b.isEmpty())
221 return -1;
223 while(!a.isEmpty() || !b.isEmpty()) {
224 // trim all leading non-digits and non-dots (dots are removed afterwards)
225 a.remove(QRegExp("^[^\\d\\.]*"));
226 b.remove(QRegExp("^[^\\d\\.]*"));
228 // trim all trailing non-digits for conversion (QString::toInt()
229 // requires this). Copy strings first as replace() changes the string.
230 QString numa = a;
231 QString numb = b;
232 numa.remove(QRegExp("\\D+.*$"));
233 numb.remove(QRegExp("\\D+.*$"));
235 // convert to number
236 bool ok1, ok2;
237 int vala = numa.toUInt(&ok1);
238 int valb = numb.toUInt(&ok2);
239 // if none of the numbers converted successfully we're at trailing garbage.
240 if(!ok1 && !ok2)
241 break;
242 if(!ok1)
243 return 1;
244 if(!ok2)
245 return -1;
247 // if numbers mismatch we have a decision.
248 if(vala != valb)
249 return (vala > valb) ? -1 : 1;
251 // trim leading digits.
252 a.remove(QRegExp("^\\d*"));
253 b.remove(QRegExp("^\\d*"));
255 // if number is immediately followed by a character consider it as
256 // version addon (like 1.2.3b). In this case compare characters too.
257 QChar ltra;
258 QChar ltrb;
259 if(a.contains(QRegExp("^[a-zA-Z]")))
260 ltra = a.at(0);
261 if(b.contains(QRegExp("^[a-zA-Z]")))
262 ltrb = b.at(0);
263 if(ltra != ltrb)
264 return (ltra < ltrb) ? 1 : -1;
265 // both are identical or no addon characters, ignore.
266 // remove modifiers and following dot.
267 a.remove(QRegExp("^[a-zA-Z]*\\."));
268 b.remove(QRegExp("^[a-zA-Z]*\\."));
271 // no differences found.
272 return 0;