Projet Programmation système

Le but du projet est d'écrire une commande mytar permettant, à la manière de tar, d'archiver des fichiers. Elle n'implémentera pas toutes les fonctionnalités de la commande tar classique et utilisera un format de fichier archivé différent. Par ailleurs, il n'est pas demandé que la commande soit portable : il suffira qu'elle soit capable de désarchiver un fichier préalablement archivé sur la même machine.

Format des fichiers d'archive

Un fichier d'archive peut contenir des archives de fichiers ordinaires, de liens symboliques et de répertoires, concaténées l'une après l'autre :

Un fichier d'archive contenant quatre fichiers (fichiers ordinaires, liens symboliques ou répertoires) archivés.

Chaque archive de fichier est formatée de la manière suivante :

où chaque champ contient l'information suivante :

nom du champ type remarques contenu et signification
path_length size_t types entiers non-signés
définis dans <sys/types.h>
sert à stocker la longueur du champ path, incluant le caractère '\0' terminal
file_length off_t sert à stocker la longueur du champ file
mode mode_t permet de stocker les attributs du fichier
m_time time_t sert à stocker la date de dernière modification du fichier
a_time time_t sert à stocker la date de dernier accès au fichier
checksum char[32] sert à stocker l'empreinte md5 du fichier
path char[] chaîne de caractères (terminant par '\0') contient un chemin d'accès (relatif ou absolu) au fichier
file char[] ne termine pas nécessairement par '\0' contenu du fichier ; si path est un lien symbolique, il s'agit du contenu du lien lui-même et non du contenu de sa cible

La valeur de file_length est zéro pour les répertoires (et le champ file n'existe pas). La raison principale de la présence d'entrées distinctes pour les répertoires dans un fichier d'archive est de permettre la restauration des droits d'accès.

Le champ checksum offre une possibilité de vérification de l'intégrité des données. Il pourra éventuellement rester nul.

Fonctionnement général de la commande mytar

La commande mytar est invoquée de la manière suivante :

mytar options [path1] ... [pathn]

path1 ... pathn sont des chemins vers des fichiers ordinaires, des répertoires ou des liens symboliques.

La liste des options comprend :

Les modes -a, -c et -d nécessitent que la liste path1 ... pathn soit non vide.

Les différents modes sont les suivants :

La création d'une nouvelle archive (option -c) ; path1 ... pathn désignent alors les fichiers à archiver ; si certains sont des répertoires, toute la sous-arborescence correspondante doit être archivée ; par défaut, les liens symboliques sont ignorés.

La modification du contenu d'une archive, par ajout (option -a) ou suppression (option -d) de fichiers ; l'ajout se fait en fin d'archive, sans écrasement (l'archive peut donc contenir plusieurs versions d'un même fichier) ; la suppression (de fichiers ordinaires ou de sous-arborescences) peut nécessiter une réorganisation du fichier d'archive qui ne doit pas contenir de trous.

L'affichage du contenu d'une archive sur la sortie standard (option -l), sous forme d'une liste de chemins, chacun au format de ls -l ; si des chemins path1 ... pathn sont fournis, seules les lignes les concernant sont affichées (pour l'affichage des dates, consultez la fonction localtime).

L'extraction du contenu d'une archive (option -x), par défaut limiée aux fichiers ordinaires et aux répertoires ; cette extraction doit restaurer les droits d'accès et les dates de dernière modification et de dernier accès (consultez la fonction utime) ; si des chemins path1 ... pathn sont fournis, seuls ces fichiers (ou sous-arborescences) sont restaurés.
Par défaut, l'extraction écrase les fichiers ordinaires déjà présents sous le même nom dans l'arborescence ; en revanche, les répertoires préexistants sont conservés avec leurs attributs.

Exemple

L'image ci-dessous

présente un fragment de l'arborescence de fichiers : a, b, c sont des répertoires, et x, y, t, u, w des fichiers ordinaires.

La commande

mytar -c -f a.mtr a

exécutée depuis le répertoire contenant a construit l'archive a.mtr décrivant trois répertoires avec les chemins a, a/b, a/b/c et cinq fichiers ordinaires avec les chemins a/x, a/y, a/b/t, a/b/c/u, a/b/c/w.

La commande

mytar -x -f a.mtr a/b

reconstruit à partir de l'archive a.mtr l'arborescence de racine a/b.

La commande

mytar -d a/b -f a.mtr

supprime de l'archive a.mtr toute l'arborescence de racinee a/b.

Liste des options à implémenter

option signification ou action
-f fichier_archive fournit le chemin vers le fichier d'archive
-c création d'une archive
-a ajout de fichiers à la fin de l'archive
-d suppression de fichiers de l'archive
-l affichage du contenu de l'archive sur la sortie standard, au format de ls -l
-x extraction du contenu de l'archive
-k lors de l'extraction, indique que les fichiers existants ne doivent pas être remplacés ; un message d'avertissement doit être affiché (et l'extraction doit continuer)
-s les liens symboliques ne sont pas ignorés
-C rep indique que le répertoire rep devient la racine de l'arborescence archivée ; en mode création, cela signifie que les chemins path1 ... pathn, ainsi que les chemins écrits dans l'archive, sont relatifs à rep ; en mode extraction, cela signifie que l'archive doit être restaurée dans rep
-v permet la vérification de l'intégrité des données : en mode ajout ou création, l'empreinte md5 de chaque fichier ordinaire est calculée et copiée dans l'entête ; en mode extraction, l'empreinte de chaque fichier extrait est comparée avec le champ checksum dans l'archive, si celui-ci a été renseigné

Pour calculer l'empreinte md5 des fichiers, il vous est demandé de ne pas utiliser la bibliothèque <openssl/md5.h>, mais la commande md5 sans argument, qui écrit sur la sortie standard les 32 octets de l'empreinte md5 des données lues sur l'entrée standard. Il faudra donc créer un nouveau processus pour chaque calcul d'empreinte, dont les entrée et sortie standard seront redirigées de manière adéquate.

Toutes les opérations sur l'archive doivent être protégées par des verrous appropriés (au cas où plusieurs utilisateurs utilisent simultanément mytar pour la même archive).

Extensions possibles

La commande mytar est très limitée et loin de ce qu'on attend d'une commande d'archivage. Pour celles et ceux qui veulent aller plus loin, voici deux extensions possibles.

Ajout d'une option -z

Cette option doit pouvoir être combinée avec les modes -c, -l et -x. Elle indique que l'archive concernée est compressée -- son nom a alors le suffixe .mtr.gz. En mode création, l'archive est compressée avec la commande gzip une fois tous les fichiers traités. En mode affichage ou extraction, l'archive doit être décompressée avec gunzip avant d'être lue, sans que le fichier d'archive ne soit modifié : il faudra donc utiliser gunzip comme un filtre dont la sortie standard sera redirigée soit sur un fichier temporaire (dans /tmp), soit sur un tube.

Ajout d'une option -u

En mode ajout ou extraction, cette option fait ignorer les fichiers plus anciens : ne sont ajoutés à l'archive que les fichiers ayant une date de dernière modification plus récente que la (ou les) version(s) éventuellement présente(s) dans le fichier d'archive ; ne sont extraits que les fichiers ayant une date de dernière modification plus récente que le fichier éventuellement déjà présent dans l'arborescence.

Consignes générales

Toutes les opérations sur les fichiers doivent impérativement utiliser les fonctions d'entrée/sortie de bas niveau, à la seule exception des opérations d'entrée/sortie sur le terminal, pour lesquelles vous pouvez utiliser librement les fonctions d'entrée/sortie du C standard.

Il est interdit d'utiliser la fonction system dans votre projet.

Le projet doit être convenablement divisé en fonctions et en plusieurs fichiers sources, et accompagné d'un Makefile qui doit permettre la compilation de la commande avec un make.

La compilation de tous les fichiers sources doit être réalisée avec le compilateur gcc avec les options de pré-processeur CFLAGS = -Wall -pedantic -g sans aucun message d'avertissement. Il peut être nécessaire d'ajouter également l'option -std=c99 pour que votre code compile si vous utiliser le C standard de 1999.

De plus, il convient sans doute d'ajouter comme première ligne de chaque fichier source (avant tout include):

#define _POSIX_C_SOURCE 200112L

Une autre possibilité, au lieu d'ajouter cette ligne, consiste à passer cette constante à la compilation:

CFLAGS = -Wall -pedantic -std=c99 -D _POSIX_C_SOURCE=200112L

Par ailleurs, make cleanall doit supprimer tous les fichiers *.o et les exécutables.

Enfin, dans les fichiers sources, il faut au moins commenter

Et vérifier avec valgrind que votre programme n'a pas de fuites de mémoire. Cette vérification sera effectuée pendant les soutenances et les fuites de mémoire seront sanctionnées.

Modalités

Le projet sera réalisé en binôme ou monôme. La notation en tiendra compte.

La date limite de remise sera donnée ultérieurement.

Pour transmettre votre projet, vous devez créer un répertoire à votre (ou vos) nom(s) contenant les fichiers sources (*.c et *.h), le Makefile et un fichier alire.txt., contenant votre (ou vos) nom(s) puis la description de ce que vous avez réussi à faire et, éventuellement, de ce qui reste encore à faire par rapport au travail demandé. Ce répertoire doit être compressé sous forme xxx_yyy.tar.gzxxx et yyy sont vos noms. Ce fichier doit donc se désarchiver en un répertoire nommé xxx_yyy contenant votre projet. Le fichier d'archive avec votre projet est à déposer sur DiDEL.