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
;
140 //! \brief searches for a Executable in the Environement Path
141 QString
Utils::findExecutable(QString name
)
145 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX) || defined(Q_OS_OPENBSD)
146 QStringList path
= QString(getenv("PATH")).split(":", QString::SkipEmptyParts
);
147 #elif defined(Q_OS_WIN)
148 QStringList path
= QString(getenv("PATH")).split(";", QString::SkipEmptyParts
);
150 qDebug() << "[Utils] system path:" << path
;
151 for(int i
= 0; i
< path
.size(); i
++)
153 QString executable
= QDir::fromNativeSeparators(path
.at(i
)) + "/" + name
;
154 #if defined(Q_OS_WIN)
155 executable
+= ".exe";
156 QStringList ex
= executable
.split("\"", QString::SkipEmptyParts
);
157 executable
= ex
.join("");
159 qDebug() << "[Utils] executable:" << executable
;
160 if(QFileInfo(executable
).isExecutable())
162 return QDir::toNativeSeparators(executable
);
169 /** @brief checks different Enviroment things. Ask if user wants to continue.
170 * @param permission if it should check for permission
171 * @return string with error messages if problems occurred, empty strings if none.
173 QString
Utils::checkEnvironment(bool permission
)
180 #if defined(Q_OS_WIN32)
181 if(System::userPermissions() != System::ADMIN
)
183 text
+= tr("<li>Permissions insufficient for bootloader "
184 "installation.\nAdministrator priviledges are necessary.</li>");
190 RockboxInfo
rbinfo(RbSettings::value(RbSettings::Mountpoint
).toString());
191 QString installed
= rbinfo
.target();
192 if(!installed
.isEmpty() && installed
!=
193 SystemInfo::value(SystemInfo::CurConfigureModel
).toString())
195 text
+= tr("<li>Target mismatch detected.\n"
196 "Installed target: %1, selected target: %2.</li>")
197 .arg(installed
, SystemInfo::value(SystemInfo::CurPlatformName
).toString());
198 // FIXME: replace installed by human-friendly name
202 return tr("Problem detected:") + "<ul>" + text
+ "</ul>";
206 /** @brief Compare two version strings.
207 * @param s1 first version string
208 * @param s2 second version string
209 * @return 0 if strings identical, 1 if second is newer, -1 if first.
211 int Utils::compareVersionStrings(QString s1
, QString s2
)
213 QString a
= s1
.trimmed();
214 QString b
= s2
.trimmed();
215 qDebug() << "[Utils] comparing version strings" << a
<< "and" << b
;
216 // if strings are identical return 0.
222 while(!a
.isEmpty() || !b
.isEmpty()) {
223 // trim all leading non-digits and non-dots (dots are removed afterwards)
224 a
.remove(QRegExp("^[^\\d\\.]*"));
225 b
.remove(QRegExp("^[^\\d\\.]*"));
227 // trim all trailing non-digits for conversion (QString::toInt()
228 // requires this). Copy strings first as replace() changes the string.
231 numa
.remove(QRegExp("\\D+.*$"));
232 numb
.remove(QRegExp("\\D+.*$"));
236 int vala
= numa
.toUInt(&ok1
);
237 int valb
= numb
.toUInt(&ok2
);
238 // if none of the numbers converted successfully we're at trailing garbage.
246 // if numbers mismatch we have a decision.
248 return (vala
> valb
) ? -1 : 1;
250 // trim leading digits.
251 a
.remove(QRegExp("^\\d*"));
252 b
.remove(QRegExp("^\\d*"));
254 // if number is immediately followed by a character consider it as
255 // version addon (like 1.2.3b). In this case compare characters too.
258 if(a
.contains(QRegExp("^[a-zA-Z]")))
260 if(b
.contains(QRegExp("^[a-zA-Z]")))
263 return (ltra
< ltrb
) ? 1 : -1;
264 // both are identical or no addon characters, ignore.
265 // remove modifiers and following dot.
266 a
.remove(QRegExp("^[a-zA-Z]*\\."));
267 b
.remove(QRegExp("^[a-zA-Z]*\\."));
270 // no differences found.