Consignes

Pour ce TP, vous devrez rendre un petit rapport au format texte. Ce fichier README n'est pas un compte-rendu "classique". Vous devez produire un document synthétique du style "fiche de révision" contenant un résumé des notions et concepts que vous aurez explorés pendant le TP.

L'objectif est que vous produisiez une synthèse contenant les choses qui peuvent vous servir, par exemple pour l'examen !

Il n'est pas nécessaire de connaitre tous les détails par cœur, mais les techniques utilisées pour les 2 premiers tiers du TP sont au programme de l'examen.

Ce fichier contiendra obligatoirement une entête avec :

Liens utiles

Objectifs du TP

L'objectif de ce TP est de se familiariser avec le concept de fichier et la manière dont il sont gérés par le système d'exploitation.

1. Préliminaires

Si vous travaillez sur votre ordinateur, vous pourrez avoir des besoins d'utilitaires qui ne sont pas installés par défaut. Vous pouvez les installez avec

$ sudo apt install xxd xli gpicview feh imagemagick eog gimp

1.1. Chemins absolus

Chaque fichiers ou répertoire est uniquement identifié par son chemin absolu :

Dans le shell, il est possible d'afficher le répertoire de travail avec la commande

$ pwd

(pwd sont les initiales de "print working directory".)

Donnez, dans votre rapport, le chemin absolu correspondant :

  1. à votre répertoire personnel,

  2. au fichier de votre rapport.

Chaque processus a son propre répertoire de travail. Le répertoire de travail d'un processus Python est accessible avec os.getcwd(). Créez un programme Python contenant uniquement les lignes suivantes :

import os

print(os.getcwd())
  1. On peut exécuter un programme Python depuis un shell avec

    $ python3 CHEMIN_FICHIER_PYTHON

    Lorsqu'on exécute le programme ci dessus dans un shell, à quoi correspond le répertoire de travail ?

  2. La fonction pour changer le répertoire de travail d'un programme Python est os.chdir(CHEMIN). Testez cette fonction et cherchez un exemple d'application.

1.2. Motifs, retour sur la commande "find"

Les motifs shell standards sont

bash signification
* joker (plusieurs caractères, éventuellement zéro)
? joker (1 caractère)
[...] caractère parmi ...
[!...] caractère sauf ...
\? \* caractères ? *

Les jokers "?" et "*" ont une restriction : il ne peuvent pas correspondre au "." initial des fichiers cachés.

La commande find s'utilise dans le shell :

$ find RÉPERTOIRE CONDITIONS
  1. Donnez une commande qui affiche les noms de tous les fichiers PDF contenu dans le répertoire /usr/share. Vous devrez utiliser find pour pouvoir lister même les fichiers contenus dans des sous-répertoires...

  2. Donnez une commande qui permet de lister tous les fichiers contenus dans des sous-répertoire de /usr/bin dont l'extension est un unique chiffre pair. (Par exemple, sur ma machine, /usr/bin/tclsh8.6 doit être listé, mais ni /usr/bin/perl5.32.1 ni /usr/bin/m4 ne doivent être listés.)

  3. Comment pouvez-vous compter le nombre de tels fichiers facilement ?

2. Fichiers textes

2.1. ASCII

Chaque caractère ASCII est codé par un octet, ou plus précisément, par les 7 bits de poids faible d'un octet.

La commande

$ xxd -b FICHIER

permet d'afficher la représentation binaire d'un fichier.

Remarque : chaque ligne du résultat de xxd commence par le numéro (en hexadécimal) du premier octet de la ligne :

00000000: ...    # cette ligne commence à l'octet 0
00000010: ...    # cette ligne commence à l'octet 16 (10 en hexadécimal)
00000020: ...    # cette ligne commence à l'octet 32 (20 en hexadécimal)

Chaque octet du fichier est représenté dans la suite de la ligne par 8 bits (en mode binaire) ou 2 chiffres en hexadécimal (en mode hexadécimal).

Téléchargez les deux fichiers petit_fichier1.ascii et petit_fichier2.ascii.

  1. Vous pouvez télécharger des fichiers directement depuis la ligne de commandes avec wget:

    $ wget URL
  2. Ouvrez les deux fichiers (sans les modifier) avec un éditeur de texte (ligne de commande : nano, ou graphique : gedit). Les deux fichiers sont ils identiques ?

  3. Regardez la représentation binaire des deux fichiers (avec xxd -b) : à quoi correspond la différence observée ? (table des caractères ASCII)

2.2. Autres caractères

Les caractères accentués n'existent pas en ASCII. Ils sont codés :

Ouvrez, dans deux onglets différents de votre navigateur web, les fichiers petit_fichier.codage1 et petit_fichier.codage2. Ils contiennent la chaine "Étoile" codée avec 2 encodages différents : UTF-8 et ISO-8859-1. (Firefox utilisera un encodage par défaut, et un des fichiers risque de ne pas s'afficher correctement.)

  1. Telechargez les 2 fichiers et utilisez xxd pour trouver quel fichier est codé en UTF-8.

  2. Donnez le codage en binaire de la lettre "É"

    • en UTF-8,

    • en ISO-8859-1.

3. Fichiers binaires

Les fichiers binaires sont constitués d'octets arbitraires. Le fichier lac.image contient une image binaire.

Téléchargez le fichier lac.image.

  1. Que se passe t'il si vous affichez les 100 premiers / 100 derniers octets dans le terminal avec les commandes head -c100 et tail -c100 ?

  2. Que se passe t'il si vous affichez l'intégralité du fichier dans le terminal avec la commande cat ?

  3. Que se passe t'il si vous affichez le fichier avec la commande xli, display, eog ou gimp ? (Ces programmes sont des visualisateurs d'images, ou, pour le dernier, un logiciel d'édition d'images.)

Si l'affichage de votre terminal est corrompu par des octets non imprimables:

␉▒⎽␤: 2␌ : ␌⎺└└▒┼␍␊ ␋┼├⎼⎺┤┴▒␉┌␊
⎻␤≤┴␊@└▒┤-59-14:·/Ti┌i␌␤▒⎼±␊└␊┼├⎽$
⎻␤≤┴␊@└▒┤-59-14:·/Ti┌i␌␤▒⎼±␊└␊┼├⎽$ ⎼␊⎽␊├

il est possible de lancer la commande reset pour réinitialiser l'affichage :

$ reset

Note : il est possible que les caractères que vous tapez au clavier (la commande "reset") ne soient pas affichés correctement. Ce n'est pas gênant. Dans mon cas, "reset" s'est affiché comme "⎼␊⎽␊├"

  1. En utilisant la commande

    $ xxd -g1 lac.image

    sauvegardez la représentation (en hexadécimal) du fichier lac.image dans un fichier lac.hexa. Vous devrez pour ceci rediriger l'affichage de la commande dans un fichier grâce à l'opérateur ">".

  2. Ouvrez le fichiers lac.hexa dans un éditeur de texte (nano ou gedit). Les premières lignes ressemblent à

    00000000: 50 36 0a 35 30 30 20 33 35 33 0a 32 35 35 0a 97  P6.500 353.255..
    00000010: c1 e6 80 b6 e2 7e b6 e4 78 b3 e1 79 b3 e1 7f b6  .....~..x..y....
    00000020: e2 86 b6 e2 8c b7 e1 8c b7 e1 8c ba e2 85 b8 e2  ................
    00000030: 7e b6 e1 7c b6 e4 7c b6 e4 79 b6 e4 77 b4 e2 77  ~..|..|..y..w..w
    00000040: b3 e4 77 b4 e5 77 b4 e4 78 b5 e2 77 b5 e2 77 b5  ..w..w..x..w..w.

    Modifiez, sur la première ligne, l'octet 6 en remplaçant

    00000000: 50 36 0a 35 30 30 20 33 35 33 0a 32 35 35 0a 97  P6.500 353.255..

    par

    ..................... 30 32 20 ..........................

    et sauvegardez le fichier.

    Les symboles . dans la ligne précédente représentent des caractères qu'il ne faut pas modifier. Autrement dit, vous de devez modifier qu'un seul octet sur la ligne : l'octet n°6 qui passe de la valeur 30 à la valeur 32.

  3. Reconvertissez le fichier modifié lac.hexa en binaire grâce à la commande xxd -r lac.hexa. Sauvegardez le résultat dans un nouveau fichier lac2.image grâce à une redirection ">" et visualisez le résultat avec xli, display, eog ou gimp.

    Qu'en pensez-vous ?

    Proposez une explication ?

  1. En repartant du fichier lac.hexa d'origine, modifiez maintenant l'octet 12 en remplaçant

    00000000: 50 36 0a 35 30 30 20 33 35 33 0a 32 35 35 0a 97  P6.500 353.255..

    par

    ....................................... 0a 30 35 ........
  2. Reconvertissez le fichier modifié lac.hexa en binaire grâce à la commande xxd -r lac.hexa. Sauvegardez le résultat dans un nouveau fichier lac3.image grâce à une redirection ">" et visualisez le résultat avec xli, display, eog ou gimp.

    Qu'en pensez-vous ?

  1. En repartant du fichier lac.hexa d'origine, modifiez maintenant l'octet 2 en remplaçant

    00000000: 50 36 0a 35 30 30 20 33 35 33 0a 32 35 35 0a 97  P6.500 353.255..

    par

    ......... 50 35 0a ......................................
  2. Reconvertissez le fichier modifié lac.hexa en binaire dans un nouveau fichier lac4.image et visualisez le résultat avec xli, display, eog ou gimp.

    Qu'en pensez-vous ?

  1. En repartant du fichier lac.hexa d'origine, modifiez maintenant l'octet 2 en remplaçant

    00000000: 50 36 0a 35 30 30 20 33 35 33 0a 32 35 35 0a 97  P6.500 353.255..

    par

    ......... 50 38 0a ......................................
  2. Reconvertissez le fichier modifié lac.hexa dans un nouveau fichier lac5.image et visualisez le résultat avec xli, display, eog ou gimp.

    Qu'en pensez-vous ?

  1. En repartant du fichier lac.hexa d'origine, modifiez maintenant la ligne 5 en remplaçant

    00000040: b3 e4 77 b4 e5 77 b4 e4 78 b5 e2 77 b5 e2 77 b5

    par

    00000040: b3 e4 ff 00 00 ff 00 00 ff 00 00 ff 00 00 77 b5
  2. Reconvertissez le fichier modifié lac.hexa dans un nouveau fichier lac6.image et visualisez le résultat avec xli, display, eog ou gimp.

    Qu'en pensez-vous ?

À faire à la fin du TP, si vous avez le temps

Reportez vous à la description des formats PPM et expliquez les modifications qui ont été faites sur les images.

Commande "file"

Comme le montrait le fichier lac.image, l'extension d'un fichier n'est pas forcément représentative du type réel du fichier.

La commande

$ file FICHIER1 ... FICHIERn

essaie de "deviner" le type des fichiers en regardant les premiers octets.

Utilisez la commande file pour donner le type des fichiers

4. Métadonnées

4.1. Affichage des méta-données

Les méta-données d'un fichier sont obtenues en ajoutant l'option "-l" à la commande ls:

$ ls -l
...
-rw-r--r--  1 hyvernat hyvernat 10016 avril  3 07:42 enseignement.php
...

Chaque ligne du résultat se décompose comme suit :

-rw-r--r--  1 hyvernat hyvernat 10016 avril  3 07:42 enseignement.php
----------  - -------- -------- ----- -------------- ----------------
    |       |     |        |      |          |              |
    |       |     |        |      |          |              +----->  nom du fichier
    |       |     |        |      |          |
    |       |     |        |      |          +----->  date de modification
    |       |     |        |      |
    |       |     |        |      +----->  taille (en octets)
    |       |     |        |
    |       |     |        +----->  groupe propriétaire
    |       |     |
    |       |     +----->  utilisateur propriétaire
    |       |
    |       +-----> nombre de liens physiques (que vous pouvez ignorer)
    |
    +-----> droits d'accès
  1. Vérifiez que vous êtes bien "propriétaire" de vos fichiers. Quel est votre "nom" pour l'ordinateur ?

  2. À quel groupe appartiennent les fichiers que vous créez ?

L'administrateur peut modifier le propriétaire d'un fichier avec la commande

$ chown PROPRIÉTAIRE FICHIER1 ... FICHIERn

4.2. Droit d'accès

Parmi les métadonnées importantes d'un fichier se trouvent les droits d'accès. Les droits d'accès Unix sont divisés en trois sous-parties :

  1. droits d'accès pour l'utilisateur propriétaire du fichier,

  2. droits d'accès pour le groupe propriétaire du fichier (un groupe regroupe plusieurs utilisateurs),

  3. droits d'accès pour le reste du monde.

Il y a 3 types de droits d'accès :

  1. droit de lecture ("Read") pour les accès en lecture,

  2. droit d'écriture ("Write") pour les accès en écriture,

  3. droit d'exécution ("eXecute") pour l'exécution du fichier.

Nous allons ignorer le droit d'exécution pour ce TP...

La manière utilisée pour vous donner accès à vos fichiers (CIFS : "Common Internet File System") ne supporte pas le droit d'accès "exécution" sur les fichiers. Tous les fichiers et répertoires de votre répertoire personnels sont automatiquement exécutable pour tout le monde. Vous pouvez observer des fichiers sans droit "eXecute" dans le répertoire "/tmp/".

Les droits d'accès des groupes sont également gérés de manière particulière. Nous n'allons pas nous en occuper...

Si vous travaillez sur les ordinateurs fixes de l'université, il est important de travailler dans le répertoire "/tmp/" pour eviter des surprises liées au systeme CIFS, pour toutes les questions restantes.

Ces droits sont affichés dans les premières colonnes du résultat et sont donnés par des codes:

- rw- r-- r--
| ||| ||| |||
| ||| ||| ||+-----> 'x' lorsque le monde a le droit d'exécution
| ||| ||| ||        '-' sinon
| ||| ||| ||
| ||| ||| |+-----> 'w' lorsque le monde a le droit d'écriture
| ||| ||| |        '-' sinon
| ||| ||| |
| ||| ||| +-----> 'r' lorsque le monde a le droit de lecture
| ||| |||         '-' sinon
| ||| |||
| ||| |||
| ||| ||+-----> 'x' lorsque le groupe a le droit d'exécution
| ||| ||        '-' sinon
| ||| ||
| ||| |+-----> 'w' lorsque le groupe a le droit d'écriture
| ||| |        '-' sinon
| ||| |
| ||| +-----> 'r' lorsque le groupe a le droit de lecture
| |||         '-' sinon
| |||
| |||
| ||+-----> 'x' lorsque le propriétaire a le droit d'exécution
| ||	    '-' sinon
| ||
| |+-----> 'w' lorsque le propriétaire a le droit d'écriture
| |	   '-' sinon
| |
| +-----> 'r' lorsque le propriétaire a le droit de lecture
|	  '-' sinon
|
+-----> '-' pour les fichiers
        'd' pour les répertoires
        (autre symboles pour d'autres type de fichiers)

La commande pour modifier les droits d'accès d'un fichier / répertoire est la suivante :

$ chmod MODE FICHIER1 ... FICHIERn

Vous pouvez consulter la description complète du mode en faisant

$ man chmod

Voici quelques exemples :

  1. Créez un fichiers test.txt contenant la chaine "Bonjour".

  2. Notez ses droits d'accès, et vérifiez que vous pouvez modifier le fichier.

  3. Enlevez le droit d'écriture (pour le propriétaire) sur ce fichier :

    • pouvez vous le visualiser ?

    • Pouvez vous le modifier ?

    • Pouvez vous le supprimer ?

  4. Supprimez et re-créez le fichiers test.txt contenant la chaine "Bonjour". Vous aurez ainsi un fichier avec les droits par defaut. Enlevez son droit de lecture (pour le propriétaire)

    • pouvez vous le visualiser ?

    • Pouvez vous le modifier ?

    • Pouvez vous le supprimer ?

  5. Résumez vos résultats sous forme d'un tableau

    droits fichier  |  visualisation   |  modification    |  suppression     |
                -w  |  (pas) possible  |  (pas) possible  |  (pas) possible  |
                r-  |  (pas) possible  |  (pas) possible  |  (pas) possible  |

    Essayez d'expliquer les résultats surprenants.

  6. À votre avis, que se passe t'il si personne n'a aucun droit sur un fichier (ni lecture, ni écriture) ?

Les répertoires ont également les droits d'accès "Read" et "Write".

  1. Créez quatre répertoires D--, Dr-, D-w et Drw, contenant chacun un fichier test.txt avec la ligne "coucou".

  2. Changez les droits d'accès aux répertoires (sans changer ceux des fichiers) pour avoir les droits suivant pour le propriétaire :

    • D-- : ni lecture ni écriture,

    • Dr- : lecture, pas écriture,

    • D-w : pas lecture, écriture,

    • Drw : lecture et écriture.

    Lorsque vous donner un répertoire à ls, c'est le contenu du répertoire qui est listé. Pour obtenir les droits d'accès sur un répertoire, vous pouvez faire

    $ ls -ld REPERTOIRE

    L'option -d indique à ls qu'il ne doit pas regarder le contenu des répertoires.

  3. Précisez, pour chacun des répertoires, si les opérations suivantes sont possibles :

    • modification d'un fichier,

    • suppression d'un fichier,

    • création d'un fichier,

    • changement des droits d'accès d'un fichier,

    • changement des droits d'accès du dossier lui même,

    • lister les fichiers contenus dans le répertoire (avec ls)

    • se déplacer dans le répertoire (avec cd)

  4. Résumez vos résultats sous forme d'un tableau

    droits dossier | modif | rm | création | chmod fichier | chmod dossier | ls | cd |
                -- |       |    |          |               |               |    |    |
                r- |       |    |          |               |               |    |    |
                -w |       |    |          |               |               |    |    |
                rw |       |    |          |               |               |    |    |

    Essayez d'expliquer les résultats surprenants.

  5. (BONUS) : testez les mêmes opérations sur un répertoire avec les droits de lecture et d'écriture, mais sans le droit x.

5. Un peu de technique

5.1. Les deux tailles d'un fichier

La commande

$ ls -l

affiche les méta-données des fichiers, dont en particulier la taille (en octets) des données.

La commande

$ ls -s

affiche la taille occupée par les fichiers, en kibioctets.

Cette taille est différente de la précédente car chaque bloc occupé partiellement par le fichier est compté comme utilisé.

Dans les deux cas, il est conseillé d'ajouter l'option -h pour que les tailles soient affichées en utilisant les unités standards (k, M, G etc.)

$ ls -lh
...
$ ls -sh
...

Vous pouvez également avoir les deux tailles directement avec

$ ls -lsh

Créez un fichier vide avec la commande

$ touch FICHIER

(Attention, si le fichier existe, cette commande change simplement sa date de modification !)

Et un petit fichier contenant "Spock" avec la commande

$ echo "Spock" > FICHIER
  1. Quelle est la taille, en octets, des deux fichiers ?

  2. Quelle est la place occupé sur le disque par ces deux fichiers ?

Exécutez les commandes suivantes :

$ echo "Hello" > fichier_mysterieux
$ truncate -s 16M fichier_mysterieux
$ echo "world" >> fichier_mysterieux
  1. Quelles sont les tailles de fichier_mysterieux ?

  2. Qu'affiche la commande cat fichier_mysterieux ?

  3. Quel est le contenu exact de fichier_mysterieux ?

  4. Cherchez et expliquez ce que vous constatez.

5.2. Des fichiers "virtuels"

Le concept de "fichier" dans le monde Unix est beaucoup plus général que les fichiers habituels. Un "fichier" est une abstraction pour quelque chose dans laquelle on peut, en général:

  1. La commande xxd peut prendre un argument -l NB pour afficher (en binaire) au plus NB octets d'un fichier. Affichez les 64 premiers octets du "fichier" /dev/zero.

  2. Quelle est la taille de /dev/zero ? Est-ce que cela est compatible avec ce que vous avez observé au point précédent ?

  3. À votre avis, comment le système gère t'il les lectures dans /dev/zero ?

  1. Affichez les 64 premiers octets du "fichier" /dev/random.

  2. Affichez les 64 premiers octets du "fichier" /dev/random.

  3. Affichez les 64 premiers octets du "fichier" /dev/random.

  4. Que constatez vous ?

  5. À votre avis, comment le système gère t'il les lectures dans /dev/random ?

  6. Essayer de deviner ce qui se passera si on lance

    $ cat /dev/random

    Si vous avez lancé la commande, souvenez-vous (mission 20 du TP2 que la combinaison de touche Control-c permet de stopper la commande en cours. Il est cependant possible que vous deviez relancer votre terminal...

  1. Si on redirige la sortie standard dans /dev/null :

    $ ls > /dev/null

    rien n'est affiché, et tout est envoyé dans le "fichier" /dev/null

  2. Affichez, par exemple avec

    $ cat /dev/null

    le contenu de /dev/null après la redirection du point précédent.

    Que constatez vous ?

  3. À votre avis, comment le système gère t'il les écritures dans /dev/null ?

  1. Que se passe t'il si on redirige la sortie standard dans /dev/full :

    $ ls > /dev/full
  2. La commande echo "" n'affiche rien. Comment expliquez vous le résultat de

    $ echo "" > /dev/full