QSysInfo: Expand Linux distribution detection
Expand Linux distribution detection to /etc/redhat-release and /etc/debian_version to follow what /usr/bin/lsb_release script does. If /usr/bin/lsb_release fails to extract the distribution information from /etc/lsb-release, it then checks /etc/redhat-release and, as a last fallback, /etc/debian_version. Some Red Hat distributions have a /etc/lsb-release file that does not provide the values we are looking for (DISTRIB_ID, DISTRIB_RELEASE and DISTRIB_DESCRIPTION). If both productType or productVersion are empty after reading /etc/lsb-release, readEtcLsbRelease() will return false, allowing further parsing of /etc/redhat-release. This scenario mimics what the /usr/bin/lsb_release script does if /etc/lsb-release does not contains enough information. The productType and productVersion returned by QSysInfo after reading /etc/redhat-release match the distributor id and release information returned by the /usr/bin/lsb_release script. For Debian Linux distributions where /etc/os-release, /etc/lsb-release and /etc/redhat-release are not available nor usable, the /usr/bin/lsb_release script also checks for the /etc/debian_version file. In this case, we also enable parsing of /etc/debian_version to retrieve a fallback productVersion, the productType being set to Debian. Change-Id: Ia20d513d78be8a8ee8c0410d0aaa052fde81a41d Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
This commit is contained in:
parent
78a1090821
commit
6c20a01cb9
@ -2120,9 +2120,9 @@ const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion()
|
||||
# define USE_ETC_OS_RELEASE
|
||||
struct QUnixOSVersion
|
||||
{
|
||||
// from /etc/os-release older /etc/lsb-release
|
||||
QString productType; // $ID $DISTRIB_ID
|
||||
QString productVersion; // $VERSION_ID $DISTRIB_RELEASE
|
||||
// from /etc/os-release older /etc/lsb-release // redhat /etc/redhat-release // debian /etc/debian_version
|
||||
QString productType; // $ID $DISTRIB_ID // single line file containing: // Debian
|
||||
QString productVersion; // $VERSION_ID $DISTRIB_RELEASE // <Vendor_ID release Version_ID> // single line file <Release_ID/sid>
|
||||
QString prettyName; // $PRETTY_NAME $DISTRIB_DESCRIPTION
|
||||
};
|
||||
|
||||
@ -2134,24 +2134,32 @@ static QString unquote(const char *begin, const char *end)
|
||||
}
|
||||
return QString::fromLatin1(begin, end - begin);
|
||||
}
|
||||
|
||||
static bool readEtcFile(QUnixOSVersion &v, const char *filename,
|
||||
const QByteArray &idKey, const QByteArray &versionKey, const QByteArray &prettyNameKey)
|
||||
static QByteArray getEtcFileContent(const char *filename)
|
||||
{
|
||||
// we're avoiding QFile here
|
||||
int fd = qt_safe_open(filename, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return false;
|
||||
return QByteArray();
|
||||
|
||||
QT_STATBUF sbuf;
|
||||
if (QT_FSTAT(fd, &sbuf) == -1) {
|
||||
qt_safe_close(fd);
|
||||
return false;
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
|
||||
buffer.resize(qt_safe_read(fd, buffer.data(), sbuf.st_size));
|
||||
qt_safe_close(fd);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static bool readEtcFile(QUnixOSVersion &v, const char *filename,
|
||||
const QByteArray &idKey, const QByteArray &versionKey, const QByteArray &prettyNameKey)
|
||||
{
|
||||
|
||||
QByteArray buffer = getEtcFileContent(filename);
|
||||
if (buffer.isEmpty())
|
||||
return false;
|
||||
|
||||
const char *ptr = buffer.constData();
|
||||
const char *end = buffer.constEnd();
|
||||
@ -2215,14 +2223,72 @@ static bool readEtcLsbRelease(QUnixOSVersion &v)
|
||||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
// some distributions have a /etc/lsb-release file that does not provide the values
|
||||
// we are looking for, i.e. DISTRIB_ID, DISTRIB_RELEASE and DISTRIB_DESCRIPTION.
|
||||
// Assuming that neither DISTRIB_ID nor DISTRIB_RELEASE were found, or contained valid values,
|
||||
// returning false for readEtcLsbRelease will allow further /etc/<lowercasename>-release parsing.
|
||||
return ok && !(v.productType.isEmpty() && v.productVersion.isEmpty());
|
||||
}
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
static QByteArray getEtcFileFirstLine(const char *fileName)
|
||||
{
|
||||
QByteArray buffer = getEtcFileContent(fileName);
|
||||
if (buffer.isEmpty())
|
||||
return QByteArray();
|
||||
|
||||
const char *ptr = buffer.constData();
|
||||
int eol = buffer.indexOf("\n");
|
||||
return QByteArray(ptr, eol).trimmed();
|
||||
}
|
||||
|
||||
static bool readEtcRedHatRelease(QUnixOSVersion &v)
|
||||
{
|
||||
// /etc/redhat-release analysed should be a one line file
|
||||
// the format of its content is <Vendor_ID release Version>
|
||||
// i.e. "Red Hat Enterprise Linux Workstation release 6.5 (Santiago)"
|
||||
QByteArray line = getEtcFileFirstLine("/etc/redhat-release");
|
||||
if (line.isEmpty())
|
||||
return false;
|
||||
|
||||
v.prettyName = QString::fromLatin1(line);
|
||||
|
||||
const char keyword[] = "release ";
|
||||
int releaseIndex = line.indexOf(keyword);
|
||||
v.productType = QString::fromLatin1(line.mid(0, releaseIndex)).remove(QLatin1Char(' '));
|
||||
int spaceIndex = line.indexOf(' ', releaseIndex + strlen(keyword));
|
||||
v.productVersion = QString::fromLatin1(line.mid(releaseIndex + strlen(keyword), spaceIndex > -1 ? spaceIndex - releaseIndex - strlen(keyword) : -1));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readEtcDebianVersion(QUnixOSVersion &v)
|
||||
{
|
||||
// /etc/debian_version analysed should be a one line file
|
||||
// the format of its content is <Release_ID/sid>
|
||||
// i.e. "jessie/sid"
|
||||
QByteArray line = getEtcFileFirstLine("/etc/debian_version");
|
||||
if (line.isEmpty())
|
||||
return false;
|
||||
|
||||
v.productType = QStringLiteral("Debian");
|
||||
v.productVersion = QString::fromLatin1(line);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool findUnixOsVersion(QUnixOSVersion &v)
|
||||
{
|
||||
if (readEtcOsRelease(v))
|
||||
return true;
|
||||
return readEtcLsbRelease(v);
|
||||
if (readEtcLsbRelease(v))
|
||||
return true;
|
||||
#if defined(Q_OS_LINUX)
|
||||
if (readEtcRedHatRelease(v))
|
||||
return true;
|
||||
if (readEtcDebianVersion(v))
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
# endif // USE_ETC_OS_RELEASE
|
||||
#endif // Q_OS_UNIX
|
||||
|
Loading…
x
Reference in New Issue
Block a user