Как написать из ФАЙЛА * на ФД? - PullRequest
0 голосов
/ 06 марта 2019

Я хотел бы скопировать содержимое файла FILE* (библиотека *.so) в дескриптор файла, который я передам другой функции.Я прочитал о fileno(), но, похоже, он не работает должным образом.Кто-нибудь может дать мне хитрость, чтобы сделать это?

Вот мой код:

int takeFromDisk(char *file){
    int shm_fd;
    shm_fd = open_ramfs(); // Give me a file descriptor to memory
    printf("[+] File Descriptor Shared Memory created!\n");

    FILE *fichier = fopen(file, "r");


    fclose(fichier);
    return(shm_fd);
}

И функция, которую я использую для получения моего файлового дескриптора:

int open_ramfs(void) {
    int shm_fd;

    //If we have a kernel < 3.17
    // We need to use the less fancy way
    if (kernel_version() == 0) {
        shm_fd = shm_open(SHM_NAME, O_RDWR | O_CREAT, S_IRWXU);
        if (shm_fd < 0) { //Something went wrong :(
            fprintf(stderr, "[-] Could not open file descriptor\n");
            exit(-1);
        }
    }
    // If we have a kernel >= 3.17
    // We can use the funky style
    else {
        shm_fd = memfd_create(SHM_NAME, 1);
        if (shm_fd < 0) { //Something went wrong :(
            fprintf(stderr, "[- Could not open file descriptor\n");
            exit(-1);
        }
    }
    return shm_fd;
}

И код, который я пробовал:

int c;
while ((c = fgetc(fichier)) != EOF)
{
  write(shm_fd, &c, sizeof(c));
}

1 Ответ

2 голосов
/ 06 марта 2019

Проблема с кодом, который вы пробовали, связана с арифметикой указателей.

  • fgetc возвращает прочитанный байт как значение, которое вы сохраняете в c.Пока все хорошо.
  • write немного более гибок, чем fgetc - он может записывать более одного байта за раз (аналогично fread).Таким образом, вы не можете просто передать ему одно целочисленное значение, как вы пытались это сделать - ему нужен указатель в ячейку памяти с байтом, который вы хотите записать.&c - указатель на память, используемую c - но подождите, это еще не все ...
  • fgetc возвращает байт, который он читает в int.На всех современных платформах int больше, чем один байт, так что переменная c на самом деле больше, чем байт (большинство систем, с которыми вы столкнетесь, имеют 4 байта в int, чтоэто также то, что ваш sizeof будет производить, так что в итоге вы получите файл, завышенный в 4 раза.К сожалению, платформы отличаются тем, где именно тот байт, о котором вы заботитесь, находится в памяти для этой переменной.На многих платформах использование &c будет работать, но не на всех.
  • Лучшим подходом является выделение буфера фиксированного размера, тогда вы можете прочитать в него с помощью fread и записать его в другой FDиспользуя write, примерно так (я пропустил обработку ошибок и другие детали):
#define BUFSIZE 4096
char buf[BUFSIZE];
while (1) {
    size_t num_read = fread(&buf, 1, BUFSIZE, fichier);
    if (num_read == 0) break;
    write(shm_fd, &buf, num_read);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...