From f679cf91cf94363d10f99db5cbae872401ed5612 Mon Sep 17 00:00:00 2001 From: Dominik Riebeling Date: Thu, 30 Apr 2009 19:14:24 +0000 Subject: Bootloader installation for ipod and sansa: override the scanning with the device pointed to by the mountpoint. This allows selecting the correct player if two of the same brand are connected (FS#10096). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20832 a1c6a512-1295-4272-9138-f99709370657 --- rbutil/rbutilqt/base/autodetection.cpp | 115 ++++++++++++++++++------ rbutil/rbutilqt/base/autodetection.h | 1 + rbutil/rbutilqt/base/bootloaderinstallipod.cpp | 41 +++++++-- rbutil/rbutilqt/base/bootloaderinstallsansa.cpp | 100 ++++++++++----------- rbutil/rbutilqt/base/bootloaderinstallsansa.h | 1 + 5 files changed, 168 insertions(+), 90 deletions(-) (limited to 'rbutil') diff --git a/rbutil/rbutilqt/base/autodetection.cpp b/rbutil/rbutilqt/base/autodetection.cpp index ee42a8c09e..276c270499 100644 --- a/rbutil/rbutilqt/base/autodetection.cpp +++ b/rbutil/rbutilqt/base/autodetection.cpp @@ -238,6 +238,11 @@ QStringList Autodetection::mountpoints() return tempList; } + +/** resolve device name to mount point / drive letter + * @param device device name / disk number + * @return mount point / drive letter + */ QString Autodetection::resolveMountPoint(QString device) { qDebug() << "Autodetection::resolveMountPoint(QString)" << device; @@ -289,39 +294,97 @@ QString Autodetection::resolveMountPoint(QString device) QString result; unsigned int driveno = device.replace(QRegExp("^.*([0-9]+)"), "\\1").toInt(); - for(int letter = 'A'; letter <= 'Z'; letter++) { - DWORD written; - HANDLE h; - TCHAR uncpath[MAX_PATH]; - UCHAR buffer[0x400]; - PVOLUME_DISK_EXTENTS extents = (PVOLUME_DISK_EXTENTS)buffer; - - _stprintf(uncpath, _TEXT("\\\\.\\%c:"), letter); - h = CreateFile(uncpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - if(h == INVALID_HANDLE_VALUE) { - //qDebug() << "error getting extents for" << uncpath; - continue; + int letter; + for(letter = 'A'; letter <= 'Z'; letter++) { + if(resolveDevicename(QString(letter)).toUInt() == driveno) { + result = letter; + break; } - // get the extents - if(DeviceIoControl(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, - NULL, 0, extents, sizeof(buffer), &written, NULL)) { - for(unsigned int a = 0; a < extents->NumberOfDiskExtents; a++) { - qDebug() << "Disk:" << extents->Extents[a].DiskNumber; - if(extents->Extents[a].DiskNumber == driveno) { - result = letter; - qDebug("drive found for volume %i: %c", driveno, letter); - break; - } - } + } + qDebug() << "Autodetection::resolveMountPoint(QString)" << "->" << result; + if(!result.isEmpty()) + return result + ":/"; +#endif + return QString(""); +} + +/** Resolve mountpoint to devicename / disk number + * @param path mountpoint path / drive letter + * @return devicename / disk number + */ +QString Autodetection::resolveDevicename(QString path) +{ + qDebug() << __func__; +#if defined(Q_OS_LINUX) + FILE *mn = setmntent("/etc/mtab", "r"); + if(!mn) + return QString(""); + + struct mntent *ent; + while((ent = getmntent(mn))) { + if(QString(ent->mnt_dir).startsWith(path) + && QString(ent->mnt_type).contains("vfat", Qt::CaseInsensitive)) { + endmntent(mn); + return QString(ent->mnt_fsname); } + } + endmntent(mn); + +#endif +#if defined(Q_OS_MACX) + int num; + struct statfs *mntinf; + + num = getmntinfo(&mntinf, MNT_WAIT); + while(num--) { + if(QString(mntinf->f_mntonname).startsWith(path) + && QString(mntinf->f_fstypename).contains("vfat", Qt::CaseInsensitive)) + return QString(mntinf->f_mntfromname); + mntinf++; + } +#endif + +#if defined(Q_OS_OPENBSD) + int num; + struct statfs *mntinf; + + num = getmntinfo(&mntinf, MNT_WAIT); + while(num--) { + if(QString(mntinf->f_mntonname).startsWith(device) + && QString(mntinf->f_fstypename).contains("msdos", Qt::CaseInsensitive)) + return QString(mntinf->f_mntfromname); + mntinf++; + } +#endif +#if defined(Q_OS_WIN32) + DWORD written; + HANDLE h; + TCHAR uncpath[MAX_PATH]; + UCHAR buffer[0x400]; + PVOLUME_DISK_EXTENTS extents = (PVOLUME_DISK_EXTENTS)buffer; + + _stprintf(uncpath, _TEXT("\\\\.\\%c:"), path.toAscii().at(0)); + h = CreateFile(uncpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if(h == INVALID_HANDLE_VALUE) { + //qDebug() << "error getting extents for" << uncpath; + return ""; + } + // get the extents + if(DeviceIoControl(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, + NULL, 0, extents, sizeof(buffer), &written, NULL)) { + if(extents->NumberOfDiskExtents > 1) { + qDebug() << "volume spans multiple disks!"; + return ""; + } + //qDebug() << "Disk:" << extents->Extents[0].DiskNumber; + return QString("%1").arg(extents->Extents[0].DiskNumber); } - if(!result.isEmpty()) - return result + ":/"; #endif return QString(""); + } diff --git a/rbutil/rbutilqt/base/autodetection.h b/rbutil/rbutilqt/base/autodetection.h index 7e6386cd5f..cffab5bd4f 100644 --- a/rbutil/rbutilqt/base/autodetection.h +++ b/rbutil/rbutilqt/base/autodetection.h @@ -42,6 +42,7 @@ public: QString errdev(void) { return m_errdev; } QString incompatdev(void) { return m_incompat; } static QStringList mountpoints(void); + static QString resolveDevicename(QString path); private: QString resolveMountPoint(QString); diff --git a/rbutil/rbutilqt/base/bootloaderinstallipod.cpp b/rbutil/rbutilqt/base/bootloaderinstallipod.cpp index 82c64954a6..e4a70e0cd6 100644 --- a/rbutil/rbutilqt/base/bootloaderinstallipod.cpp +++ b/rbutil/rbutilqt/base/bootloaderinstallipod.cpp @@ -22,6 +22,7 @@ #include "bootloaderinstallipod.h" #include "../ipodpatcher/ipodpatcher.h" +#include "autodetection.h" BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent) @@ -36,7 +37,8 @@ BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent) BootloaderInstallIpod::~BootloaderInstallIpod() { - free(ipod_sectorbuf); + if(ipod_sectorbuf) + free(ipod_sectorbuf); } @@ -198,12 +200,15 @@ BootloaderInstallBase::BootloaderType BootloaderInstallIpod::installed(void) qDebug() << "BootloaderInstallIpod::installed(): BootloaderUnknown"; result = BootloaderUnknown; } - else if (ipod.ipod_directory[0].entryOffset == 0) { - qDebug() << "BootloaderInstallIpod::installed(): BootloaderOther"; - result = BootloaderOther; - } else { - qDebug() << "BootloaderInstallIpod::installed(): BootloaderRockbox"; + read_directory(&ipod); + if(ipod.ipod_directory[0].entryOffset == 0) { + qDebug() << "BootloaderInstallIpod::installed(): BootloaderOther"; + result = BootloaderOther; + } + else { + qDebug() << "BootloaderInstallIpod::installed(): BootloaderRockbox"; + } } ipod_close(&ipod); @@ -219,20 +224,38 @@ BootloaderInstallBase::Capabilities BootloaderInstallIpod::capabilities(void) bool BootloaderInstallIpod::ipodInitialize(struct ipod_t *ipod) { - ipod_scan(ipod); + if(!m_blfile.isEmpty()) { +#if defined(Q_OS_WIN32) + sprintf(ipod->diskname, "\\\\.\\PhysicalDrive%i", + Autodetection::resolveDevicename(m_blfile).toInt()); +#elif defined(Q_OS_MACX) + sprintf(ipod->diskname, + qPrintable(Autodetection::resolveDevicename(m_blfile) + .remove(QRegExp("s[0-9]+$")))); +#else + sprintf(ipod->diskname, + qPrintable(Autodetection::resolveDevicename(m_blfile) + .remove(QRegExp("[0-9]+$")))); +#endif + qDebug() << "ipodpatcher: overriding scan, using" << ipod->diskname; + } + else { + ipod_scan(ipod); + } if(ipod_open(ipod, 0) < 0) { emit logItem(tr("Could not open Ipod"), LOGERROR); return false; } if(read_partinfo(ipod, 0) < 0) { - emit logItem(tr("Could not read partition table"), LOGERROR); + emit logItem(tr("Error reading partition table - possibly not an Ipod"), LOGERROR); + ipod_close(ipod); return false; } if(ipod->pinfo[0].start == 0) { emit logItem(tr("No firmware partition on disk"), LOGERROR); - + ipod_close(ipod); return false; } return true; diff --git a/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp b/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp index 4679c2e9a8..aab298ce95 100644 --- a/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp +++ b/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp @@ -22,6 +22,7 @@ #include "bootloaderinstallsansa.h" #include "../sansapatcher/sansapatcher.h" +#include "autodetection.h" BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent) : BootloaderInstallBase(parent) @@ -36,7 +37,8 @@ BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent) BootloaderInstallSansa::~BootloaderInstallSansa() { - free(sansa_sectorbuf); + if(sansa_sectorbuf) + free(sansa_sectorbuf); } @@ -80,30 +82,12 @@ bool BootloaderInstallSansa::install(void) void BootloaderInstallSansa::installStage2(void) { struct sansa_t sansa; - sansa_scan(&sansa); emit logItem(tr("Installing Rockbox bootloader"), LOGINFO); QCoreApplication::processEvents(); - - if(sansa_open(&sansa, 0) < 0) { - emit logItem(tr("could not open Sansa"), LOGERROR); - emit done(true); - return; - } - - if(sansa_read_partinfo(&sansa, 0) < 0) - { - emit logItem(tr("could not read partitiontable"), LOGERROR); - emit done(true); - return; - } - - int i = is_sansa(&sansa); - if(i < 0) { - - emit logItem(tr("Disk is not a Sansa (Error: %1), aborting.").arg(i), LOGERROR); - emit done(true); - return; + if(!sansaInitialize(&sansa)) { + emit done(true); + return; } if(sansa.hasoldbootloader) { @@ -169,27 +153,7 @@ bool BootloaderInstallSansa::uninstall(void) emit logItem(tr("Uninstalling bootloader"), LOGINFO); QCoreApplication::processEvents(); - if(sansa_scan(&sansa) != 1) { - emit logItem(tr("Can't find Sansa"), LOGERROR); - emit done(true); - return false; - } - - if (sansa_open(&sansa, 0) < 0) { - emit logItem(tr("Could not open Sansa"), LOGERROR); - emit done(true); - return false; - } - - if (sansa_read_partinfo(&sansa,0) < 0) { - emit logItem(tr("Could not read partition table"), LOGERROR); - emit done(true); - return false; - } - - int i = is_sansa(&sansa); - if(i < 0) { - emit logItem(tr("Disk is not a Sansa (Error %1), aborting.").arg(i), LOGERROR); + if(!sansaInitialize(&sansa)) { emit done(true); return false; } @@ -235,18 +199,7 @@ BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void) struct sansa_t sansa; int num; - if(sansa_scan(&sansa) != 1) { - return BootloaderUnknown; - } - if (sansa_open(&sansa, 0) < 0) { - return BootloaderUnknown; - } - if (sansa_read_partinfo(&sansa,0) < 0) { - sansa_close(&sansa); - return BootloaderUnknown; - } - if(is_sansa(&sansa) < 0) { - sansa_close(&sansa); + if(!sansaInitialize(&sansa)) { return BootloaderUnknown; } if((num = sansa_list_images(&sansa)) == 2) { @@ -261,6 +214,43 @@ BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void) } +bool BootloaderInstallSansa::sansaInitialize(struct sansa_t *sansa) +{ + if(!m_blfile.isEmpty()) { +#if defined(Q_OS_WIN32) + sprintf(sansa->diskname, "\\\\.\\PhysicalDrive%i", + Autodetection::resolveDevicename(m_blfile).toInt()); +#else + sprintf(sansa->diskname, + qPrintable(Autodetection::resolveDevicename(m_blfile).remove(QRegExp("[0-9]+$")))); +#endif + qDebug() << "sansapatcher: overriding scan, using" << sansa->diskname; + } + else if(sansa_scan(sansa) != 1) { + emit logItem(tr("Can't find Sansa"), LOGERROR); + return false; + } + + if (sansa_open(sansa, 0) < 0) { + emit logItem(tr("Could not open Sansa"), LOGERROR); + return false; + } + + if (sansa_read_partinfo(sansa,0) < 0) { + emit logItem(tr("Could not read partition table"), LOGERROR); + sansa_close(sansa); + return false; + } + + int i = is_sansa(sansa); + if(i < 0) { + emit logItem(tr("Disk is not a Sansa (Error %1), aborting.").arg(i), LOGERROR); + sansa_close(sansa); + return false; + } + return true; +} + /** Get capabilities of subclass installer. */ diff --git a/rbutil/rbutilqt/base/bootloaderinstallsansa.h b/rbutil/rbutilqt/base/bootloaderinstallsansa.h index a3911057a0..29eaa6d603 100644 --- a/rbutil/rbutilqt/base/bootloaderinstallsansa.h +++ b/rbutil/rbutilqt/base/bootloaderinstallsansa.h @@ -38,6 +38,7 @@ class BootloaderInstallSansa : public BootloaderInstallBase Capabilities capabilities(void); private: + bool sansaInitialize(struct sansa_t *); private slots: void installStage2(void); -- cgit v1.2.3