1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2007 by Dominik Wenger
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 ****************************************************************************/
21 #include "rockboxinfo.h"
23 #include "rbsettings.h"
24 #include "systeminfo.h"
35 #if defined(Q_OS_WIN32)
40 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
41 #include <sys/statvfs.h>
44 // recursive function to delete a dir with files
45 bool Utils::recursiveRmdir( const QString
&dirName
)
47 QString dirN
= dirName
;
49 // make list of entries in directory
50 QStringList list
= dir
.entryList(QDir::AllEntries
| QDir::NoDotAndDotDot
);
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
61 QFile::remove(curItem
); // ok, delete file
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
)
77 elems
= path
.split("/", QString::SkipEmptyParts
);
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.
83 realpath
= elems
.at(0) + "/";
89 for(int i
= start
; i
< elems
.size(); i
++) {
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
);
101 if(!realpath
.endsWith("/"))
108 qDebug() << "[Utils] resolving path" << path
<< "->" << 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
)
119 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
120 // the usage of statfs() is deprecated by the LSB so use statvfs().
124 ret
= statvfs(qPrintable(path
), &fs
);
127 size
= (qulonglong
)fs
.f_frsize
* (qulonglong
)fs
.f_bavail
;
129 #if defined(Q_OS_WIN32)
131 ULARGE_INTEGER freeAvailBytes
;
133 ret
= GetDiskFreeSpaceExW((LPCTSTR
)path
.utf16(), &freeAvailBytes
, NULL
, NULL
);
135 size
= freeAvailBytes
.QuadPart
;
137 qDebug() << "[Utils] Filesystem free:" << path
<< size
;
141 //! \brief searches for a Executable in the Environement Path
142 QString
Utils::findExecutable(QString name
)
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
);
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("");
160 qDebug() << "[Utils] executable:" << executable
;
161 if(QFileInfo(executable
).isExecutable())
163 return QDir::toNativeSeparators(executable
);
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
)
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>");
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
203 return tr("Problem detected:") + "<ul>" + text
+ "</ul>";
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.
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.
232 numa
.remove(QRegExp("\\D+.*$"));
233 numb
.remove(QRegExp("\\D+.*$"));
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.
247 // if numbers mismatch we have a decision.
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.
259 if(a
.contains(QRegExp("^[a-zA-Z]")))
261 if(b
.contains(QRegExp("^[a-zA-Z]")))
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.