menu
  Home  ==>  articles  ==>  colibri_utilities  ==>  iso_cd_extractor   

Iso CD Extractor - John COLIBRI.


1 - Introduction

De nombreux logiciels sont proposés sur le Web sous forme de fichier "ISO". Il s'agit d'un paquet de données ayant un format particulier. Ce format est adapté aux lecteurs de CD ROM, et nous ne pouvons donc pas afficher le contenu de ces fichiers dans l'Explorateur Windows. Il faut alors
  • soit placer ces fichiers sur un disque vierge
  • soit extraire le contenu du fichier .ISO et les copier dans un répertoire classique
N'étant pas arrivé à copier un fichier .ISO téléchargé, j'ai cherché un programme pour analyser ce fichier et suis tombé sur http://isolib.xenome.info/. Ce site propose un projet permettant l'analyse, l'extraction de fichiers, et à terme, l'écriture de CD. Le programme est aussi sur SourceForge. Notre projet est un descendant direct de ce projet (tIsoLib).

Nous allons ici:

  • présenter le format des fichiers .ISO
  • afficher la liste des répertoires et des fichiers
  • extraire les fichiers dans un répertoire Windows.

2 - Format ISO

Format général

Les données placées sur un CD ROM peuvent être organisées selon plusieurs formats: des formats pour la musique, pour les films, pour les données informatiques etc.

Ce qui nous intéresse ici, c'est le format des données informatiques. Plusieurs tentatives de normalisation ont été entreprises, et plusieurs formats, tels ISO 9660, High Sierra, Joliet etc ont été publiés.

Nous analyserons le format ISO 9660, qui serait similaire à High Sierra.

Un CD ROM ISO est organisé de la façon suivante:

  • les données sont groupées par paquets de 2048 ou 2336 octets
  • la structure est la suivante
    • les 16 premiers secteurs sont inutilisés
    • à partir du secteur 16 sont situés des descripteurs de volume
    • vient une table des chemins
    • puis nous trouvons le répertoire principal
    • ce répertoire principal indique où se trouvent
      • les fichiers contenus dans le répertoire principal
      • les sous-répertoire qui contiennent d'autres fichiers
Globalement nous avons donc:

Et:

  • les descripteurs vont être détaillés ci-dessous. Ils permettent essentiellement de savoir où se trouve le "master dir"
  • la table des chemins ne sera pas utilisée ici
  • le "master dir" est le répertoire global. Il a la même structure que les sous-répertoires: il contient des entrées pour des sous-répertoires ou des fichiers:
    • chaque sous-répertoire contient donc aussi des entrées de sous-répertoires ou de fichiers
    • les entrées de fichiers permettent de localiser les fichiers

Les Descripteurs

Chaque CD contient 2 descripteurs ou plus:
  • il y a deux descripteurs principaux:
    • le descripteur primaire est le plus important. C'est lui qui nous donne accès à la table des matière principale
    • le descripteur final sert à indiquer la fin des descripteurs
  • entre les deux, 0 ou plusieurs descripteurs optionnels
    • le descripteur de partition
    • le descripteur de boot
    Suivant l'operating system destinataire (Linux, Mac etc) il y aura plusieurs de ces descripteurs.
    Comme il ne nous servent pas à récupérer nos données, nous ne nous en occuperons pas ici
La détection du type de CD se fait en vérifiant que les octets situés à 16* 2048 + 1 sont bien "CDOO1". Il s'agit alors bien du format "YellowBook, mode 1".

Les secteurs de descripteurs contiennent en position 0 un octet qui définit le type de descripteur. Il suffit donc de lire le secteur jusqu'à ce que nous tombions sur le secteur de "fin de descripteurs".

Le descripteur primaire qui a la signature $01 est défini par le type Delphi suivant:

 t_primary_descriptorpacked record
                         StandardIdentifierarray[0..4] of Char;
                         VolumeDescriptorVersionByte;
                         unusedByte;
                         SystemIdentifierarray[0..31] of Char;
                         VolumeIdentifierarray[0..31] of Char;
                         Unused2array[0..7] of Byte;

                         VolumeSpaceSizeTBothEndianDWord;
                         Unused3array[0..31] of Byte;
                         VolumeSetSizeTBothEndianWord;
                         VolumeSequenceNumberTBothEndianWord;
                         LogicalBlockSizeTBothEndianWord;
                         PathTableSizeTBothEndianDWord;
                         LocationOfTypeLPathTableLongWord;
                         LocationOfOptionalTypeLPathTableLongWord;
                         LocationOfTypeMPathTableLongWord;
                         LocationOfOptionalTypeMPathTableLongWord;

                         RootDirectoryTRootDirectoryRecord// <===

                         VolumeSetIdentifierarray[0..127] of Char;
                         PublisherIdentifierarray[0..127] of Char;
                         DataPreparerIdentifierarray[0..127] of Char;
                         ApplicationIdentifierarray[0..127] of Char;
                         CopyrightFileIdentifierarray[0..36] of Char;
                         AbstractFileIdentifierarray[0..36] of Char;
                         BibliographicFileIdentifierarray[0..36] of Char;
                         VolumeCreationDateAndTimeTVolumeDateTime;
                         VolumeModificationDateAndTimeTVolumeDateTime;
                         VolumeExpirationDateAndTimeTVolumeDateTime;
                         VolumeEffectiveDateAndTimeTVolumeDateTime;
                         FileStructureVersionByte;
                         ReservedForFutureStandardizationByte;

                         // -- the remaining bytes
                         ApplicationUsearray[0..511] of Byte;
                         ReservedForFutureStandardization2array[0..652] of Byte;
                       end// t_primary_descriptor

Et:

  • StandardIdentifier est la signature "CD001" citée plus haut
  • RootDirectory est un sous enregistrement qui indique où se trouve le répertoire principal:

     TRootDirectoryRecordpacked record
                             LengthOfDirectoryRecordByte;
                             ExtendedAttributeRecordLengthByte;
                             LocationOfExtentTBothEndianDWord;
                             DataLengthTBothEndianDWord;
                             RecordingDateAndTimeTDirectoryDateTime;
                             FileFlagsByte;
                             FileUnitSizeByte;
                             InterleaveGapSizeByte;
                             VolumeSequenceNumberTBothEndianWord;
                             LengthOfFileIdentifierByte// = 1
                             FileIdentifierByte// = 0
                           end// TRootDirectoryRecord

    et:

    • LocationOfExtent est le numéro de secteur du répertoire principal
    • DataLength nous donne le nombre d'octets de ce répertoire. En divisant par 2048 nous obtenons le nombre de secteurs qu'il utilise.

Le Format d'une entrée

Les répertoires sont composés d'entrées.

Chaque entrée a le format suivant:

 t_directory_entrypacked record
                      LengthOfDirectoryRecordByte;
                      ExtendedAttributeRecordLengthByte;
                      LocationOfExtentTBothEndianDWord;
                      DataLengthTBothEndianDWord;
                      RecordingDateAndTimeTDirectoryDateTime;
                      FileFlagsByte;
                      FileUnitSizeByte;
                      InterleaveGapSizeByte;
                      VolumeSequenceNumberTBothEndianWord;
                      LengthOfFileIdentifierByte;

                      // -- followed by FileIdentifier and padding bytes
                    end// t_directory_entry

Plusieurs facteurs compliquent l'analyse des entrées:

  • chaque entrée a une partie fixe (tailles, indicateurs divers) et un nom de taille variable situé après la partie fixe
  • une entrée ne peut pas chevaucher deux secteurs
  • une entrée peut contenir un nom de taille 0, mais tout de même être suivie par d'autres entrées valides
Les champs qui nous intéressent sont alors:
  • LengthOfFileIdentifier: le nombre d'octets utilisés par le nom
  • FileFlags: détermine le type d'entrée. Essentiellement le bit 1 qui est à 0 pour un fichier, à 1 pour un sous-répertoire
  • LocationOfExtent: le numéro de secteur des données (le sous-répertoire ou le fichier)
  • DataLength: le nombre d'octets utiles

3 - Le Programme

Organisation

Nous avons utilisé les fichiers suivants:
  • u_iso_definitions qui contient les définitions des descripteurs et des entrées
  • u_c_iso_file_read qui:
    • détecte le type de fichier .ISO (en lisant les octets de signature)
    • contient un tFileStream permettant de lire le fichier .ISO secteur par secteur
  • un structure arborescente récursive pour stocker:
    • pour les répertoires:
      • leur nom
      • la liste de leurs sous-répertoires
      • la liste de leurs fichiers
    • pour les fichiers:
      • leur nom
      • leur numéro de secteur et leur taille
    Nous avons ici utilisé notre classique encapsulation de tStringList (cf u_c_tstringlist). La définition est la suivante:

     c_iso_file// one file
                 Class(c_basic_object)
                   // -- m_name: the file+ extension name
                   m_iso_sector_numberInteger;
                   m_iso_sizeInteger;

                   Constructor create_iso_file(p_nameString;
                       p_iso_sector_numberp_iso_sizeInteger);
                   function f_display_fileString;
                   function f_c_selfc_iso_file;
                   Destructor DestroyOverride;
                 end// c_iso_file

     c_iso_path// -- recursive structure containing the iso directories
                 Class(c_basic_object)
                   // -- m_name: the full path
                   m_segmentString;
                   m_c_parent_pathc_iso_path;

                   m_c_file_listtStringList;
                   m_c_sub_path_listtStringList;

                   Constructor create_iso_path(p_namep_segmentString;
                       p_c_parent_pathc_iso_path);
                   function f_c_selfc_iso_path;

                   function f_file_countInteger;
                   function f_c_file(p_file_indexInteger): c_iso_file;
                   function f_index_of_file(p_file_nameString): Integer;
                   function f_c_find_by_file(p_file_nameString): c_iso_file;
                   procedure add_file(p_file_nameStringp_c_filec_iso_file);
                   function f_c_add_file(p_file_nameString;
                        p_iso_sector_numberp_iso_sizeInteger): c_iso_file;
                   procedure display_file_list;

                   function f_sub_path_countInteger;
                   function f_c_sub_path(p_sub_path_indexInteger): c_iso_path;
                   function f_c_find_sub_path_by_name(p_sub_path_nameString): c_iso_path;
                   procedure add_sub_path(p_sub_path_nameStringp_c_sub_pathc_iso_path);
                   function f_c_add_sub_path(p_sub_path_namep_segmentString): c_iso_path;
                   function f_c_get_or_add_sub_path(p_sub_path_namep_segmentString): c_iso_path;
                   procedure display_sub_path_list;

                   procedure display_path_and_file;

                   Destructor DestroyOverride;
                 end// c_iso_path

  • l'arborescence est construite par une classe c_analyze_iso_file qui lit le fichier et place les cellules en fonction du contenu du fichier
Le programme principal:
  • contient une tDirectoryListBox associé à une tFileListBox qui permettent la sélection du fichier .ISO et le lancement de la construction de l'arbre
  • le bouton display_path_file visualise l'arborescence de façon indentée (avec la position des fichiers et leur taille)
  • le bouton build_tree_view_ permet de visualiser la structure dans un tTreeView
  • le bouton extract_iso_ copie tous les fichier du fichier .ISO dans un répertoire de votre choix



4 - Utilisation

Pour utiliser le programme:
   récupérez sur le Web le fichier .ISO qui vous intéresse
   téléchargez le .ZIP
   décompactez-le dans n'importe quel répertoire
   exécutez-le
   sélectionnez à l'aide de la tDirectoryListBox le chemin
   cliquez dans la tFileListBox le fichier que vous souhaitez analyser / décompacter
   le programme construit l'arborescence en mémoire
   pour visualiser le contenu du .ISO
  • cliquez sur display_path_file pour lister les répertoires et fichiers
  • cliquez sur build_tree_view_ pour construire le tTreeView qui sera visible dans l'onglet directory_
   pour extraire les fichiers et les placer dans une arborescence Windows
  • créez le répertoire avec l'Explorateur Windows
  • changez le nom k_save_path dans le fichiers (sinon le répertoire "c:\prog\essais_util\util\_cd_iso\_data\" sera créé et utilisé)
  • cliquez extract_iso_. Attendez quelques secondes que les fichiers soient copiés

5 - Améliorations

Améliorations

Ce programme a été crée pour nous permettre de décompacter un .ISO que nous avions téléchargé. Il n'a pas été testé sur d'autres fichiers.

Le programme pourrait être amélioré:

  • en lisant directement depuis le lecteur, ou en gravant des fichiers sur le CD
  • en testant et en ajoutant le traitement des autres formats (JOLIET etc)

Je recherche

D'après certains messages sur le Web, XP contiendrait des API, "mal documentées" (c'est peu dire), permettant d'écrire des CD en utilisant les DLL (NERO ou autre). Si quelqu'un a des informations, et quelques lignes de programmes, elles sont les bienvenues. Graver mes CD de sauvegarde est toujours une galère. Il faut en effet:
  • extraire les fichiers manuellement
  • vérifier approximativement que la taille ne dépasse pas la capacité du CD
  • lancer une mystérieux .EXE qui grave, ou qui envoie des messages sibyllins s'il n'y arrive pas
Or tout le travail de préparation peut être avantageusement effectué en Delphi, en utilisant des procédure inverses de celles présentées ici pour la lecture. Si on connaît les primitives d'écriture, la gravure des secteurs préparés devrait alors être un jeu d'enfant.

Si on connaît les primitives d'écriture...


6 - Télécharger le source

Nous avons placé le projet dans un .ZIP qui comprend:
  • le .DPR, la forme principale
  • les unités citées ici
  • nos utilitaires habituels d'affichage, de log etc
Ce .ZIP est auto suffisant.

Il contient des chemins RELATIFS. Par conséquent:

  • créez un répertoire n'importe où sur votre machine
  • placez le .ZIP dans ce répertoire
  • dézippez et les sous-répertoires nécessaires seront créés
  • compilez et exécutez
Au niveau sécurité:
  • les .ZIP:
    • ne modifient pas votre PC (pas de changement de la Base de Registre, d'écrasement de DLL ou autre .BAT). Aucune modification de répertoire ou de contenu de répertoire ailleurs que dans celui où vous dézippez
    • ne contiennent aucun programme qui s'exécuterait à la décompression (.EXE, .BAT, .SCR ou autre .VXD) ou qui seraient lancés plus tard (reboot)
    • passez-les à l'antivirus avant décompression si vous êtes inquiets.
  • les programmes ne changent pas la base de registre et ne modifient aucun autre répertoire de votre machine
  • pour supprimer le projet, effacez simplement le répertoire.
Voici le .ZIP:

Comme d'habitude:
  • nous vous remercions de nous signaler toute erreur, inexactitude ou problème de téléchargement en envoyant un e-mail à jcolibri@jcolibri.com. Les corrections qui en résulteront pourront aider les prochains lecteurs
  • tous vos commentaires, remarques, questions, critiques, suggestion d'article, ou mentions d'autres sources sur le même sujet seront de même les bienvenus à jcolibri@jcolibri.com.
  • plus simplement, vous pouvez taper (anonymement ou en fournissant votre e-mail pour une réponse) vos commentaires ci-dessus et nous les envoyer en cliquant "envoyer" :
    Nom :
    E-mail :
    Commentaires * :
     

  • et si vous avez apprécié cet article, faites connaître notre site, ajoutez un lien dans vos listes de liens ou citez-nous dans vos blogs ou réponses sur les messageries. C'est très simple: plus nous aurons de visiteurs et de références Google, plus nous écrirons d'articles.

7 - Conclusion

Ce projet permet d'analyser le contenu d'un fichier .ISO et d'en extraire les fichiers dans un répertoire Windows


8 - Références

  • http://isolib.xenome.info/ (ou SourceForge)
    Le projet Delphi dont nous sommes paris

9 - L'auteur

John COLIBRI est passionné par le développement Delphi et les applications de Bases de Données. Il a écrit de nombreux livres et articles, et partage son temps entre le développement de projets (nouveaux projets, maintenance, audit, migration BDE, migration Xe_n, refactoring) pour ses clients, le conseil (composants, architecture, test) et la formation. Son site contient des articles avec code source, ainsi que le programme et le calendrier des stages de formation Delphi, base de données, programmation objet, Services Web, Tcp/Ip et UML qu'il anime personellement tous les mois, à Paris, en province ou sur site client.
Créé: may-04. Maj: aou-15  148 articles, 471 sources .ZIP, 2.021 figures
Contact : John COLIBRI - Tel: 01.42.83.69.36 / 06.87.88.23.91 - email:jcolibri@jcolibri.com
Copyright © J.Colibri   http://www.jcolibri.com - 2001 - 2015
Retour:  Home  Articles  Formations  Développement Delphi  Livres  Pascalissime  Liens  Download
l'Institut Pascal

John COLIBRI

+ Home
  + articles_avec_sources
    + bases_de_donnees
    + web_internet_sockets
    + prog_objet_composants
    + office_com_automation
    + colibri_utilities
      – difference_textuelle
      – iso_cd_extractor
      – find_uses
      – interprete_expression
      – file_byte_frequency
    + uml_design_patterns
    + graphique
    + delphi
    + outils
    + firemonkey
    + vcl_rtl
    + colibri_helpers
    + colibri_skelettons
  + formations
  + developpement_delphi
  + présentations
  + pascalissime
  + livres
  + entre_nous
  – télécharger

contacts
plan_du_site
– chercher :

RSS feed  
Blog

Prestataire Delphi réalisation de projets Delphi, création de composants, migration Delphi - Tél 01.42.83.69.36