QT C++ Создание ISO-образа

237
12 декабря 2021, 00:50

Появилась задача создать простую программу для создания ISO-образов с компакт-диска на C++. Однако, в дебрях интернета несколько запутался и не смог найти какой-то вменяемый пример или библиотеку.

Находил информацию, что использовать надо:

  • IMAPI2 Windows API для работы с дисками
  • libcdio

Но примеров создания образов или вменяемого описания так и не нашел.

Подскажите в какую сторону копать?

Answer 1

Я думаю, примеров нету, потому что задача создания образа ISO фактически сводится к задаче побайтового копирования данных с устройства в файл. Подробнее это обсуждалось здесь: Склонировать диск (в т.ч системный) в ISO

IMAPI тут не нужен, достаточно обычных файловых API. Основная сложность состоит в том, чтобы реализовать чтение с устройства в конкретной ОС.

Реализация под Windows:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
const unsigned int SECTOR_SIZE = 2048; //размер сектора для CD
#ifdef _WIN32
#include <Windows.h>
void GetDiskMetrics(const char* disk, unsigned int* pBlockSize, uint64_t* pTotalSize){
    char path[MAX_PATH]="";
    strcpy(path,disk);
    strcat(path,":\\"); 
    unsigned long  dwSectorsPerCluster, dwBytesPerSector, dwNumberOfFreeClusters, dwTotalNumberOfClusters;
    unsigned int  blocksize;
    uint64_t totalsize;
    //найдем размер сектора и объем данных на диске
    int res = GetDiskFreeSpaceA(path, &dwSectorsPerCluster, &dwBytesPerSector,
                &dwNumberOfFreeClusters, &dwTotalNumberOfClusters);
    //вычислим размер блока, кратный размеру сектора, и общий объем данных в байтах
    if (res){
        blocksize = dwBytesPerSector * 20;
        totalsize = dwSectorsPerCluster * dwBytesPerSector * (uint64_t)dwTotalNumberOfClusters;
    }
    else{
        printf("GetDiskFreeSpace error %d", GetLastError());
        blocksize = SECTOR_SIZE * 20;
        totalsize = 4700307456; //DVD
    }
    *pBlockSize = blocksize;
    *pTotalSize = totalsize;
}
bool OpenDevice(const char* disk, void** phFile){
    char path[MAX_PATH]=""; 
    sprintf(path,"\\\\.\\%s:",disk); //формат имени файла для открытия тома
    //открываем том для прямого доступа на чтение
    HANDLE handle = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
            NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (handle == INVALID_HANDLE_VALUE) {
        fprintf(stderr,"CreateFileA error %d", GetLastError());  
        return false;
    }
    else {
        *phFile = handle;
        return true;
    }
}
bool ReadDevice(void* hFile, void* lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead){
    BOOL res = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, NULL);
    if (res == FALSE){
        fprintf(stderr,"ReadFile error %d", GetLastError());
        return false;
    }
    else return true;
}
void CloseDevice(void* hFile){
    CloseHandle(hFile);
}
#endif
void CreateISO(const char* disk, const char* outfile){      
    char* buf;
    unsigned long dwRead = 0;
    uint64_t count = 0;     
    unsigned int  blocksize;
    uint64_t totalsize; 
    GetDiskMetrics(disk,&blocksize,&totalsize);
    buf = (char*)malloc(blocksize);     
    //открываем том для прямого доступа на чтение    
    void* handle=NULL;
    bool res = OpenDevice(disk,&handle);
    if (res == false)  goto End;    
    //открываем файл для записи
    FILE* target = fopen(outfile,"wb");
    while (true){
        dwRead = 0;
        memset(buf,0,blocksize);
        //считаем блок данных
        res = ReadDevice(handle,buf, blocksize, &dwRead);
        if (res == false) goto End;
        if (dwRead == 0) break; //конец считывания
        count += dwRead;
        printf(" Creating image: %5.1f%% [%10.2f KB / %10.2f KB]\r",
               (count * 100.0f / totalsize),
               (count / 1024.0f),
               (totalsize / 1024.0f));
        //запишем блок в файл
        fwrite(buf,dwRead,1,target);                    
     }
     End: CloseDevice(handle);
          fclose(target);
          free(buf);
          printf("\n");
}
int main(int argc, char **argv)
{
    CreateISO("K", "c:\\distr\\image.iso");
    getchar();
    return 0;
}

Чтобы заставить это работать под другими ОС, вам нужно будет реализовать функции, расположенные в блоке #ifdef _WIN32.

READ ALSO
Библиотека mpich

Библиотека mpich

такая проблема, есть программа, которая реализуется сортировку методом двухпутевого слияния, нужно при помощи библиотеки mpich реализовать...

217
Инициализация поля класса указателем С++

Инициализация поля класса указателем С++

Как можно организовать передачу указателя в поле класса так, чтобы в дальнейшем можно было его использовать для модификации переданного...

123
Не выводит текст в файл

Не выводит текст в файл

Когда я нажимаю на кнопку считает, а в файл нечего не записывается искал много способов записи в файл, ругался на все кроме этогоcli c++

245
C++ Вывод только положительного результата

C++ Вывод только положительного результата

Всем привет! Подскажите нужно создать матрицу такого вида: 4 - размер матрицы;

268