IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

API, COM et SDKs Delphi Discussion :

[D7][astuce][experimentale]generer un fichier de 50 Go et ecrire a la fin en notime [FAQ]


Sujet :

API, COM et SDKs Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    160
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 160
    Par défaut [D7][astuce][experimentale]generer un fichier de 50 Go et ecrire a la fin en notime
    Bonjour, comme certains le savent, je travaille en ce momment sur des très gros fichiers.

    Au fait pardon Shai le troll pour mon manque de répondant alors que tu voulais me donner un coup de main, mais je n'ai plus une seconde à moi. J'apprecie ton aide quand meme!

    Ca fait un moment que je tourne en rond pour savoir comment creer par exemple un fichier disons d'un Terra octet (LoL pas encore essayé) vide (enfin plein de 00).

    Et pouvoir ecrire instantannément à la fin du fichier.

    Le but étant de cloner des HDD en backward... (du coup je travaille aussi sur les commandes ATA mais c'est une autre histoire)

    Alors voilà une astuce...
    Encore au stade experimentale.
    Donc si vous ne savez pas ce que vous faites, gafffffee.

    Mais ca peut servir a d'autres. (he he he y'en a ici qui sont sur le meme projet que moi hein thunderlord?)

    Et heuuu... C'est un peut "dirty", vu que j'ai calculé certains IOCTL code à la main...

    Bref... Proof of concept.

    Passons en avant premiere à la creation d'un fichier de 50 Go, remplit de 0x00 avec un petit message à la fin. A aller lire avec winhex ou autre pour s'en persuader.

    Et tout ca en pif paf pouf ... No time!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    procedure TForm1.Button1Click(Sender: TObject);
    const
    NTFS_IOCTLCODE_SET_SPARSE=$900C4;//Le controle code du SET_SPARSE
    var
    h : Thandle; //handle sur le fichier
    Filesize : LARGE_INTEGER; // structure INT64
    Filename : string;
    Buffer :array[0..4] of byte;
    BytesReturned: DWORD;
    begin
    Filename := 'C:\BIGFILE.TMP';//notre fichier sur le disque
     
    //ouai je sais on aurait pu faire une boucle mais bon...
    //la demo n'est pas là...
    //Donc le buffer qu'on veut ecrire à la fin du gros fichier...
    Buffer[0]:=115; //s
    Buffer[1]:=97;  //a
    buffer[2]:=108; //l
    buffer[3]:=117; //u
    buffer[4]:=116; //t
     
    // Un bon vieux create FILE
    // pour la création du fichier ou un overwrite si'l existe
     
    h := CreateFile(pchar(Filename),GENERIC_WRITE,FILE_SHARE_WRITE, nil,CREATE_ALWAYS,0,0);
     
    //Premiere astuce on demande au filesystem
    //de na pas inscrire les bytes à 00 dans le fichier lui meme mais de définir
    //dans la mft l'endroit ou ils sont.
    //on va donc travailler avec ce qu'on nomme un sparse file
    DeviceIoControl(h, NTFS_IOCTLCODE_SET_SPARSE, nil, 0, nil, 0, BytesReturned, nil);//compression des 00
     
    Filesize.QuadPart := 50000000000; //he he he on va reserver 50 Go!
     
    setfilepointer(h,Filesize.LowPart,@Filesize.HighPart,FILE_BEGIN); // se place a l'octet Filesize.QuadPart
    SetEndOfFile (h); // Deuxieme astuce alloue l'espace disque on est donc à la fin de notre
                      //gros fichier!
     
    fileseek (h,-6,1);//mets le pointeur ou on veut (c'est a dire 6 Bytes avant la position actuelle)
    FileWrite(h,buffer,sizeof(buffer));//on ecrit notre buffer à la fin
    setfilepointer(h,0,nil,FILE_BEGIN); //et on revient au début
    CloseHandle(h); //c'est fini
    beep;//juste pour nous prevenir parce que ca va vite
     
    //y'a plus qu'a ouvrir avec winhex le fichier et taaaddddaaa un fichier de 50 Go
    //remplit de 0 juste avec salut à la fin
    //tadaaa
    end;

    Bon je ne sais pas si c'est la seule methode...
    En tout cas c'est la seule que j'ai trouvé qui ne prenne pas des plombes.

    Vos avis sont les bienvenus.

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    160
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 160
    Par défaut
    Du reste... Si vous avez une autre methode je suis preneur.

    Creer un fichier vide (la taille operationnelle pour mon projet est de 400 Go)
    Et pouvoir ecrire à la fin sans que ca prenne 2 heures.

    Merci de me faire savoir comment vous vous y prendriez.

  3. #3
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par défaut
    Bon, pour la manipulation de tel fichier, c'est surprenant de le faire sur Windows ... mais effectivement, faire un seek en dehors du fichier, permet de créer un fichier de la taille équivalente mais tu peu faire un code plus simple

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure TFrmTestFichier.BtnBigTextBuildTextPrepareSizeClick(Sender: TObject);
    var
      FS: TFileStream;
    begin
      FS := TFileStream.Create(EdPathFileBigText.Text, fmCreate);
      try
        // Ici ton DeviceIoControl
        FS.Size := 53687091200; // 50 * 1024 * 1024 * 1024; // ça c'est 50Go informatique !
      finally
        FS.Free();
      end;
    end;
    je n'ai pas vu de différence de performances pour le temps de création pour 512Mo, j'ai testé avec 40Go, c'est instantané, les API win sont SetFilePointer et SetEndOfFile mais après le gros problème est l'écriture à la fin, qui prend énormément de temps car si le fichier semble créé, en fait dès la première écriture, il corrige sa FAT et donc réécrit VRAIEMENT le fichier ...

    ce qui revient à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    procedure CreateZeroFillFile(const FileName: string; NewSize: Int64);
    var
      FileHandle: THandle;
    begin
      FileHandle := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
      try
        SetFilePointer(FileHandle, Int64Rec(NewSize).Lo, @Int64Rec(NewSize).Hi, FILE_BEGIN);
        // Ici ton DeviceIoControl
        SetEndOfFile(FileHandle);
      finally
        CloseHandle(FileHandle);
      end;
    end;
    Je vais voir ce DeviceIoControl, mais je n'ai même pas le constantes de base de window nt4 dans l'aide de D7 donc pas NTFS_IOCTLCODE_SET_SPARSE, en tout cas, cela semble être la seule méthode pour créer un VRAI fichier vide ... mais il faudrait TOUJOURS le manipuler de cette façon (parse truc), il doit gérer un fichier par fragment, et tous les fragments manquants sont des zéros ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    160
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 160
    Par défaut
    ben en fait le IOCTLCODE doit s'appeller FSCTL_SET_SPARSE dans la msdn.

    Bon ok pour les vrais 50 GO informatique...
    Moi c'était des Go à la louche

    J'en ai un peu bavé pour ce IO_CTLCODE... Faut le dénicher...

    Mais cette idée d'utiliser les possibilités du filesystem m'est venue après la lecture d'un livre sur l'analyse forensic du systeme NTFS (donc a mon tour de te taquiner... Il ne remet pas sa FAT à jour puisqu'il n'y a que la mft qui tienne en ntfs )

    Bref ce livre (en anglais et donc pour ce que j'ai comprit) explique que si l'attribut "sparse" est "on" sur un fichier dans NTFS, les suites de 0x00 ne sont pas écrites sur le disque.

    A la place, l'adresse de début et de fin (en secteurs amha mais je suis en train de reverser tout ca donc je serais plus prolyxe sur le sujet plus tard), bref a la place disais-je, on enregistre les endroits ou sont censé se trouver des 0x00 dans la mft.


    exemple

    un fichier qui aurait cette forme

    ||bloc data 1|| ... bloc de 0x00... ||bloc de data 2||

    sur un fichier normal, serait repésenté par ceci sur un fichier sparse

    ||bloc data 1||bloc de data 2||

    Et dans la mft on dirait grosso mode "insere a tel endroit "n" 0x00"
    ce qui déclanche dans windows un "special run" (dans le texte) lorsqu'on lit ou ecrit le fichier.

    C'est ce qui permet en fait d'écrire à la fin (ou on veut du reste) en un rien de temps. (le gros pb (comme tu l'as soulevé) n'etant pas de reserver virtuellement l'espace mais d'aller ecrire dedans)

    Le fichier est bien créé, il est bien remplit de 0x00 mais ne grossit de fait sur le disque qu'au fur et à mesure que des bytes sont ecrits.

    Attention toutefois à la vilaine blague.

    Ce fichier est bien réel.

    De ce fait, un fichier d'un terra octet tient environ un mega octet d'espace réél sur le disque.

    MAIS WARNING! Ne vous avisez pas de le déplacer sur une autre partition! Car la copie perdrait sans doute (en phase d'experimentation) sont attribut sparse... Et c'est bien un Toctet de 0x00 qui seraient copiés!

    Ce serait long.
    De plus vous etes livrés a vous meme.
    Lorsque vous imposez un mode de fonctionnement au file system via un driver, vous travaillez sans filet.

    Si vous finissez par dépasser la capcité de votre hdd, vous risquez de planter votre systeme.

    Bref moi je dispose au boulot de 15 T octet, donc je peux experimenter.

    Pour supprimer ce fichier mieux vaux le shift+suppr que la corbeille pour des raisons similaires (on désaloue juste la place dans la mft)

    Voilà ou j'en suis. Pour cette partie du projet.

    Je me passionne dorénavant pour le FileSystem.

    Je ne suis pas étonné que ca t'interesse shai, je te sens assez curieux et passionné pour ce genre de chose.

  5. #5
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 089
    Par défaut
    Hum, oui, je suis passionné par tout ce qui concerne le bas niveau, et malheureusement c'est pas au taf que peut m'éclater à ce sujet (je n'ai plus d'ordi à la maison, DD mort , et mon ordi est tellement vieux que faut que je rachète tout, ça me gonfle rien d'en parler ...) ... et le forum ici, grouille parfois de sujet tout à fait intéressant, qui ont l'air insignifiant mais dont la résolution amène de grand délire

    Sinon très intéressant ce système de comptage de zéro, sous linux, le système de fichier est différent, il gère ses fragments différement, ... sinon, juste comme ça, peut-être que prendre le problème à l'envers, au lieu de chercher dans windows, tu fais ton propre "système de fichier", en gros dans ton fichier, tu gères à la main le blocs et leur position dans un fichier, ensuite, une routine nocturne (un moment où cela ne se verra pas pour l'utilisateur, tu provoque la vraie écriture, et tant pis si cela occupe 1 To )
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

Discussions similaires

  1. [WAR]generer un fichier WAR
    Par inseaiste dans le forum ANT
    Réponses: 22
    Dernier message: 19/10/2009, 15h28
  2. [MySQL] generer un fichier html a partir de php en interne sur serve
    Par NoobX dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 11/10/2005, 14h01
  3. Comment générer des fichiers html ?
    Par keke33 dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 04/06/2004, 16h28
  4. Comment generer un fichier war dans java
    Par relivio dans le forum ANT
    Réponses: 4
    Dernier message: 12/03/2004, 13h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo