LINUX.ORG.RU

смещение volume deskriptor

 ,


0

1

здравствуйте вообщем нужно корректно научиться получать идентификатор тома cd диска в Linux чтоб он был такой же как и в windows я использую алгоритм

#include <stdio.h>

#define SEC_SIZE 2048
#define VD_N 16

unsigned cdid(unsigned char pvd[SEC_SIZE])
    {
    unsigned char part[4] = {0};
    int i;

    for(i = 0; i < SEC_SIZE; i += 4)
        {
        part[3] += pvd[i + 0];
        part[2] += pvd[i + 1];
        part[1] += pvd[i + 2];
        part[0] += pvd[i + 3];
        }

    return (part[3] << 24) + (part[2] << 16) + (part[1] << 8) + part[0];
    }

int main(int argc, char *argv[])
    {
    FILE *in;
    unsigned char buf[SEC_SIZE];

    if(argc != 2)
        {
        fprintf(stderr, "Call: cdid /dev/path\n");
        return 1;
        }

    /* Open device */
    in = fopen(argv[1], "rb");
    if(in == NULL)
        {
        perror(NULL);
        return 2;
        }

    /* Seek to primary volume descriptor */
    if(fseek(in, VD_N * SEC_SIZE, SEEK_SET) != 0)
        {
        perror(NULL);
        return 2;
        }

    /* Read descriptor */
    if(fread(buf, 1, SEC_SIZE, in) != SEC_SIZE)
        {
        perror(NULL);
        return 2;
        }

    /* Caclculate disc id */
    printf("%08X\n", cdid(buf));

    return 0;
    }


проблема в том что допустим:
1)берем пустой диск(сд болванку)
2)пишем на нее что-то
3)смотрим идентификатор тома вышеприведенной функцией
4)затем заходим в windows и смотрим командой dir идентификатор тома 
Они совпадают
5)потом еще дозаписываем какую нибудь информацию на диск
6)смотрим идентификатор тома вышеприведенной функцией(идентификатор тома остался  такой же)
7)смотрим идентификатор тома в windows он изменился
так вот идентификатор тома диска меняется после каждой дозаписи в windows
но как мне определить смещение в выше приведенной программе
чтобы каждый раз номера в windows и в программе совпадали...

Ответ на: комментарий от kold2015

Насколько я помню эти id чисто виндовое изобретение. Так что сходи на винфак, там должны более определённо сказать.

anonymous
()

Добавим поддержку сессий:

#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>

#define SEC_SIZE 2048
#define VD_N 16

unsigned cdid(unsigned char pvd[SEC_SIZE])
    {
    unsigned char part[4] = {0};
    int i;

    for(i = 0; i < SEC_SIZE; i += 4)
        {
        part[3] += pvd[i + 0];
        part[2] += pvd[i + 1];
        part[1] += pvd[i + 2];
        part[0] += pvd[i + 3];
        }

    return (part[3] << 24) + (part[2] << 16) + (part[1] << 8) + part[0];
    }

int main(int argc, char *argv[])
    {
    FILE *in;
    unsigned char buf[SEC_SIZE];
    struct cdrom_multisession msinfo;
    long session_start;

    if(argc != 2)
        {
        fprintf(stderr, "Call: cdid /dev/path\n");
        return 1;
        }

    /* Open device */
    in = fopen(argv[1], "rb");
    if(in == NULL)
        {
        perror(NULL);
        return 2;
        }

    /* Get session info */
    msinfo.addr_format = CDROM_LBA;
    if(ioctl(fileno(in), CDROMMULTISESSION, &msinfo) != 0)
        {
        fprintf(stderr, "WARNING: Can't get multisession info\n");
        perror(NULL);
        session_start = 0;
        }
    else
        session_start = msinfo.addr.lba;

    /* Seek to primary volume descriptor */
    if(fseek(in, (session_start + VD_N) * SEC_SIZE, SEEK_SET) != 0)
        {
        perror(NULL);
        return 2;
        }

    /* Read descriptor */
    if(fread(buf, 1, SEC_SIZE, in) != SEC_SIZE)
        {
        perror(NULL);
        return 2;
        }

    /* Caclculate disc id */
    printf("%08X\n", cdid(buf));

    return 0;
    }
cdslow ★★
()
Ответ на: комментарий от cdslow

вообщем ситуация такая: 1)на чистый CD-RW диск пишем что нибудь проверяем номера в windows dir командой и в Linux вышеприведенной функцией номера совпадают (после первой записи)

2)затем дозаписываем на диск что-нибудь и номера уже не совпадают программа выдает один номер, а windows команда dir выдает другой номер

что может быть?

kold2015
() автор топика

вместо этого говнокода наверняка есть готовая либа

smilessss ★★★★★
()
Ответ на: комментарий от kold2015

Добавил определение Joliet:

#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>
#include <string.h>

#define SEC_SIZE 2048
#define VD_N 16
#define VD_TYPE_SUPP 2
#define VD_TYPE_END 255
#define ESC_IDX 88
#define ESC_LEN 3
#define ESC_UCS2L1 "%/@"
#define ESC_UCS2L2 "%/C"
#define ESC_UCS2L3 "%/E"

unsigned cdid(unsigned char pvd[SEC_SIZE])
    {
    int i;
    unsigned char part[4] = {0};

    for(i = 0; i < SEC_SIZE; i += 4)
        {
        part[3] += pvd[i + 0];
        part[2] += pvd[i + 1];
        part[1] += pvd[i + 2];
        part[0] += pvd[i + 3];
        }

    return (part[3] << 24) + (part[2] << 16) + (part[1] << 8) + part[0];
    }

int main(int argc, char *argv[])
    {
    FILE *in;
    unsigned char buf[SEC_SIZE];
    struct cdrom_multisession msinfo;
    long session_start;
    unsigned id;

    if(argc != 2)
        {
        fprintf(stderr, "Call: cdid /dev/path\n");
        return 1;
        }

    /* Open device */
    in = fopen(argv[1], "rb");
    if(in == NULL)
        {
        perror(NULL);
        return 2;
        }

    /* Get session info */
    msinfo.addr_format = CDROM_LBA;
    if(ioctl(fileno(in), CDROMMULTISESSION, &msinfo) != 0)
        {
        fprintf(stderr, "WARNING: Can't get multisession info\n");
        perror(NULL);
        session_start = 0;
        }
    else
        session_start = msinfo.addr.lba;

    /* Seek to primary volume descriptor */
    if(fseek(in, (session_start + VD_N) * SEC_SIZE, SEEK_SET) != 0)
        {
        perror(NULL);
        return 2;
        }

    /* Read descriptor */
    if(fread(buf, 1, SEC_SIZE, in) != SEC_SIZE)
        {
        perror(NULL);
        return 2;
        }

    /* Caclculate disc id */
    id = cdid(buf);

    /* Search for Joliet extension */
    while(buf[0] != VD_TYPE_END)
        {
        /* Read descriptor */
        if(fread(buf, 1, SEC_SIZE, in) != SEC_SIZE)
            {
            perror(NULL);
            return 2;
            }

        if(buf[0] == VD_TYPE_SUPP
            && (memcmp(buf + ESC_IDX, ESC_UCS2L1, ESC_LEN) == 0
                || memcmp(buf + ESC_IDX, ESC_UCS2L2, ESC_LEN) == 0
                || memcmp(buf + ESC_IDX, ESC_UCS2L3, ESC_LEN) == 0)
            )
            {
            /* Joliet found */
            id = cdid(buf);
            }
        }

    printf("%08X\n", id);

    return 0;
    }

Следующая проблема будет, когда попадётся файловая система UDF, но с ней разбираться мне уже не охота.

cdslow ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.