1 votes

Compilation pour l'accès aux fichiers en 64 bits

J'ai examiné un certain nombre de réponses concernant la compilation du code pour qu'il puisse lire/écrire des fichiers au-delà du maximum de 4 Go autorisé par les décalages de fichiers de 32 bits. Je n'ai pas de chance avec les solutions "simples" que je trouve.

L'essentiel est que j'ai Ubuntu Server 11.10 sur un petit ordinateur portable (architecture Intel 32 bits). J'essaie de lire un fichier unicode qui fait 343868522737 octets (0x50102940f1). La machine Ubuntu continue de penser qu'il est beaucoup plus petit (0x102940f1), ce qui s'avère être seulement les 32 bits inférieurs d'un vrai fichier de taille 64 bits.

J'ai écrit un petit programme que j'ai compilé sur MacOS et sur Ubuntu. Le Mac semble se comporter correctement, mais pas la boîte Ubuntu.

Le petit programme se trouve ci-dessous. Bien que j'aie commenté un bloc de code, cela n'est vraiment nécessaire que pour le Mac. L'environnement Ubuntu compilera les deux blocs de code sans problème - et générera exactement la même réponse pour les deux blocs.

// Necessary for Ubuntu build?
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
//#include <features.h>
// finish Ubuntu

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>

// Ubuntu version
off64_t fileMaxLen(FILE* fin) {
    off64_t fmaxlen = 0;
    if( (fin!=NULL) && (fseeko64(fin,0,SEEK_END) == 0) ) {
        fmaxlen = ftello64(fin);
        fprintf(stdout,"fileMaxLen(): file length is: %#lx \n",(long unsigned int)fmaxlen);
        fseeko64(fin,0,SEEK_SET);
    }
}

// Mac OS version
//off_t fileMaxLen(FILE* fin) {
//    off_t fmaxlen = 0;
//    if( (fin!=NULL) && (fseeko(fin,0,SEEK_END) == 0) ) {
//        fmaxlen = ftello(fin);
//        fprintf(stdout,"fileMaxLen(): file length is: %#lx \n",(long unsigned int)fmaxlen);
//        fseeko(fin,0,SEEK_SET);
//    }
//}

main(int argc, char* argv[]) {
    char fname[255];
    char *locale;
    FILE* f = NULL;

    locale = setlocale(LC_ALL, "");

    if( argc>=2 ) {
        // get the file for segmenting
        memset(fname, '\0', 255);
        sprintf(fname,"%s",argv[1]);
        fprintf(stdout,"Opening: %s\n",fname);
        f = fopen(fname,"r");
        fileMaxLen(f);
        fprintf(stdout,"Done!\n");
    } else {
        fprintf(stdout,"Need a filename\n");
    }
}

Enregistrez l'extrait sous le nom de file_test.c, la compilation est alors très simple.

gcc fichier_test.c

Exécutez ensuite le fichier a.out

Avez-vous des suggestions pour que ce code reconnaisse les fichiers au-delà de cette limite de 32 bits ? Pour l'instant, je ne sais plus où j'en suis.

3voto

John Points 9

Según cette , la taille de long unsigned int sous Unix 32 bits est de 4 octets - se peut-il que la valeur soit coupée là où vous cassez fmaxlen en (long unsigned int) ?

1voto

Mark S. Rasmussen Points 13313

Vous trouverez la documentation sur les macros qui contrôlent ce comportement à l'adresse suivante man feature_test_macros .

D'après cette documentation, vous n'avez qu'à définir _FILE_OFFSET_BITS à 64 . Cela devrait permettre de redéfinir off_t et des fonctions telles que fseeko , ftello vers des versions sûres en 64 bits (c'est un non-op sur les systèmes 64 bits, et redirige les symboles vers le fichier 64 sur les systèmes 32 bits). Cette méthode est préférable à l'utilisation de l'option 64 directement les fonctions suffixées.

Et comme l'a dit Sergey, le fait de lancer le off_t jusqu'à une valeur de long unsigned int perdra des informations sur les systèmes 32 bits. Je ne pense pas qu'il existe une norme printf code de format pour off_t Il est donc préférable d'envoyer la valeur à unsigned long long int et en utilisant le %#llx comme code de format. Cela devrait permettre d'éviter les avertissements sur les deux tailles de mots et de ne pas perdre d'informations.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X