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());
}
Exemple #2
0
/****************************************************
 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() */