Exercice 1

Créer un fichier dans votre répertoire de travail. Écrivez ensuite un programme qui ouvre ce fichier et affichez la valeur (de l’index) du descripteur associé. Cette valeur est-elle conforme à vos attentes? Que se passe t-il si vous exécuter la commande close(STDIN_FILENO) avant l’appel de open?

Exercice 2

Écrivez un programme qui redirige tous ses printf dans un fichier output.txt plutôt que sur sa sortie standard. sans modifier les appels à printf dans le programme.

Exercice 3

Écrire une commande mycat qui écrive caractère par caractère le contenu de son entrée standard sur sa sortie standard. Pour effectuer les entrées-sorties on utilisera le couple de fonctions read / write. Testez votre programme en lui faisant afficher le code source, comme ceci :

$ ./mycat < mycat.c

Modifiez votre programme pour lire/écrire N caractères à la fois (en définissant une constante dans le source).

Exercice 4

Écrire deux commandes pour lire et enregistrer un entier de 32 bits non signé à une position donnée d’un fichier donné. Les deux commandes auront les prototypes suivants:

enregister-entier fichier position valeur
lire-entier fichier position
  1. Tester ces commandes en utilisant un fichier membre d’un répertoire de votre compte.

  2. Utiliser la commande hexdump pour visualiser le contenu du fichier.

  3. Que constate-t-on si l’on cherche lire / écrire après la fin du fichier?

Exercice 5

Écrire la commande reverse input-file-name output-file-name qui écrit le miroir du premier fichier dans le second. On utilisera la fonction lseek() pour déterminer la taille du fichier source.

Exercice 6

On dispose d’une commande ecrire dont le programme source est listé ci-dessous :

int main(int argc, char *argv[]) {
  int i, fd; 
  if(argc != 2) {
    fprintf(stderr , "Usage: %s <position_depart>\n", argv[0]);
    exit (1);
  }
  fd = open("fich", O_WRONLY | O_CREAT, 0666);
  for (i = atoi(argv[1]); i < 10; i += 2) {
    lseek(fd , i*sizeof(int), SEEK_SET);
    write(fd, &i, sizeof(int));
    sleep (1);
  }
  close(fd) ;
  return 0 ;
}

1. Décrivez précisément le contenu du fichier fich après l’exécution de la commande shell suivante :

$ ecrire 0

2. Même question lorsque l’on exécute consécutivement ces deux commandes :

$ ecrire 0 
$ ecrire 1 

3. Que se passe-t-il si l’on exécute les deux commandes ecrire 0 et ecrire 1 en parallèle (en les lançant simultanément dans deux terminaux) ? Que pouvez-vous dire à propos du fichier fich ?

Exercice 7

Interpréter les résultats produit par l’exécution du code suivant :

int main() {
  printf("hello ");
  write(1, "world", 5);
  return 1;
}
  1. Que se passe-t-il si l’on remplace la première chaîne par “hello\” ? Tester aussi lors d’une redirection dans un fichier.

  2. Que se passe-t-il si l’on remplace la sortie standard par la sortie standard d’erreur ?

  3. Proposer une clarification du code.

Exercice 8

Écrire la commande mycat-avec-buffer qui fonctionne sur le même principe que la commande précédente mycat, mais en utilisant les fonctions fread / fwrite. Comparer les temps de duplication d’un gros fichiers entre mycat et mycat-avec-buffer en utilisant la commande unix time pour mesurer le temps d’exécution de chaque programme. Vous pouvez utiliser la commande dd if=/dev/zero of=/tmp/toto count=10000 pour créer un fichier /tmp/toto de 10 000 blocs de 512 octets chacun (tous nuls).