void FilesystemWidget::ShowContextMenu(const QPoint&) { auto* selection = m_tree_view->selectionModel(); if (!selection->hasSelection()) return; auto* item = m_tree_model->itemFromIndex(selection->selectedIndexes()[0]); QMenu* menu = new QMenu(this); EntryType type = item->data(ENTRY_TYPE).value<EntryType>(); DiscIO::Partition partition = type == EntryType::Disc ? DiscIO::PARTITION_NONE : GetPartitionFromID(item->data(ENTRY_PARTITION).toInt()); QString path = item->data(ENTRY_NAME).toString(); const bool is_filesystem_root = (type == EntryType::Disc && m_volume->GetPartitions().empty()) || type == EntryType::Partition; if (type == EntryType::Dir || is_filesystem_root) { AddAction(menu, tr("Extract Files..."), this, [this, partition, path] { auto folder = SelectFolder(); if (!folder.isEmpty()) ExtractDirectory(partition, path, folder); }); } if (is_filesystem_root) { AddAction(menu, tr("Extract System Data..."), this, [this, partition] { auto folder = SelectFolder(); if (folder.isEmpty()) return; if (ExtractSystemData(partition, folder)) QMessageBox::information(nullptr, tr("Success"), tr("Successfully extracted system data.")); else QMessageBox::critical(nullptr, tr("Error"), tr("Failed to extract system data.")); }); } switch (type) { case EntryType::Disc: AddAction(menu, tr("Extract Entire Disc..."), this, [this, path] { auto folder = SelectFolder(); if (folder.isEmpty()) return; if (m_volume->GetPartitions().empty()) { ExtractPartition(DiscIO::PARTITION_NONE, folder); } else { for (DiscIO::Partition& p : m_volume->GetPartitions()) { if (const std::optional<u32> partition_type = m_volume->GetPartitionType(p)) { const std::string partition_name = DiscIO::DirectoryNameForPartitionType(*partition_type); ExtractPartition(p, folder + QChar(u'/') + QString::fromStdString(partition_name)); } } } }); break; case EntryType::Partition: AddAction(menu, tr("Extract Entire Partition..."), this, [this, partition] { auto folder = SelectFolder(); if (!folder.isEmpty()) ExtractPartition(partition, folder); }); if (m_volume->IsEncryptedAndHashed()) { menu->addSeparator(); AddAction(menu, tr("Check Partition Integrity"), this, [this, partition] { CheckIntegrity(partition); }); } break; case EntryType::File: AddAction(menu, tr("Extract File..."), this, [this, partition, path] { auto dest = QFileDialog::getSaveFileName(this, tr("Save File to")); if (!dest.isEmpty()) ExtractFile(partition, path, dest); }); break; case EntryType::Dir: // Handled above the switch statement break; } menu->exec(QCursor::pos()); }
/**************************************************** ReadMBR(): Read a master boot record (first 0x200 bytes). The MBR contains 446 bytes of assembly, and 4 partition tables. Start = offset for record Returns: 0=not MBR, 1=MBR ****************************************************/ int ReadMBR (int Fin, u_long MBRStart) { unsigned char MBR[0x200]; /* master boot record sector */ int i; /* extended partitions */ off_t Offset; /* partition descriptions */ int ActiveFlag,Type; int Head[2],Sec[2],Cyl[2]; u_long Start,Size; /* disk descriptions */ u_long SectorSize; u_long SectorPerCluster; u_long SectorPerCylinder; lseek(Fin,MBRStart,SEEK_SET); /* rewind file */ for(i=0; i<0x200; i++) { read(Fin,MBR+i,1); } /* check if it really is a MBR */ if ((MBR[0x1fe] != 0x55) || (MBR[0x1ff] != 0xaa)) { fprintf(stderr,"ERROR: No master boot record\n"); return(0); } /* 512 bytes per sector is pretty much standard. Apparently IBM's AS/400 systems use disks with 520 bytes/sector. MFM/RLL disks didn't have a native sector size. Some SCSI disks use 2048 bytes. But IDE uses 512. */ SectorSize = 512; SectorPerCluster = 0; /* does not matter for extraction */ SectorPerCylinder = 0; /* does not matter for extraction */ /* process each partition table */ for(i=446; i<510; i+=16) { /* 16 bytes describe each partition */ ActiveFlag=MBR[i]; /* 0x1BE */ Head[0]=MBR[i+1]; Sec[0]=(MBR[i+2] >> 2) & 0xcf; Cyl[0]=MBR[i+3] + (MBR[i+2] & 0x3)*16; Type=MBR[i+4]; Head[1]=MBR[i+5]; Sec[1]=(MBR[i+6] >> 2) & 0xcf; Cyl[1]=MBR[i+7] + (MBR[i+6] & 0x3)*16; /* Starting sector number, size of the sector */ Start=MBR[i+ 8] + MBR[i+ 9]*256 + MBR[i+10]*256*256 + MBR[i+11]*256*256*256; Size= MBR[i+12] + MBR[i+13]*256 + MBR[i+14]*256*256 + MBR[i+15]*256*256*256; if (Type != 0) /* Type 0 is unused */ { printf("Partition: (Active=%d,Type=%x)\n",ActiveFlag & 0x80,Type); printf(" HSC Start=%d,%d,%d\n",Head[0],Sec[0],Cyl[0]); printf(" HSC End =%d,%d,%d\n",Head[1],Sec[1],Cyl[1]); printf(" Sector: Start=%lu (%08lx) End=%lu (%08lx)\n", Start,Start,Start+Size,Start+Size); printf(" Byte: Logical start= %lu (%08lx)\n", MBRStart+(Start)*SectorSize, MBRStart+(Start)*SectorSize); printf(" Byte: Logical end = %lu (%08lx)\n", MBRStart+(Size+Start)*SectorSize, MBRStart+(Size+Start)*SectorSize); if (Start == 0) /* if it is a Linux kernel */ { ExtractKernel(Fin); break; } } /* check for extended partitions */ /** Types: http://www.win.tue.nl/~aeb/partitions/partition_types-1.html **/ switch(Type) { case 0x00: /* unused */ break; case 0x05: /* extended partition */ case 0x0f: /* Win95 extended partition */ Offset = lseek(Fin,0,SEEK_CUR); ReadMBR(Fin,MBRStart+(Start)*SectorSize); Offset = lseek(Fin,Offset,SEEK_CUR); break; case 0x06: /* FAT (DOS 3.3+) */ case 0x07: /* OS/2 HPFS, Windows NTFS, Advanced Unix */ case 0x0b: /* Win95 OSR2 FAT32 */ case 0x0c: /* Win95 OSR2 FAT32, LBA-mapped */ case 0x82: /* Linux swap */ case 0x83: /* Linux partition */ default: /* extract partition */ { long S,E; S=MBRStart+(Start)*SectorSize; E=MBRStart+(Size)*SectorSize; if (Verbose) fprintf(stderr,"Extracting type %02x: start=%04lx size=%lu\n",Type,S,E); ExtractPartition(Fin,S,E); } } } /* for MBR */ return(1); } /* ReadMBR() */