Laboratoire 14 - Appel système mmap

Sommaire

Remarque: n’oubliez pas, lors de l’utilisation d’appels systèmes, de traiter les cas d’erreurs.

mmap

  1. Le programme memcat qui prend en argument le fichier à projeter et en affiche le contenu.
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.h>

int main(int argc, char **argv){
  if(argc != 2){
    printf("usage : %s nom_fichier\n", argv[0]);
    return 1;
  }

  int fd, resWrite;
  struct stat stat;
  char *buf;

  fd = open(argv[1], O_RDONLY);
  if(fd == -1){
    perror("open");
    return 1;
  }
  if(fstat(fd, &stat) == -1){
    perror("stat");
    return 1;
  }
  buf = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0);
  if(buf == (char *)MAP_FAILED){
    perror("mmap");
    return 1;
  }
  close(fd);

  resWrite=write(1, buf, stat.st_size);
  if(resWrite == -1){
    perror("write");
    return 1;
  }
  munmap(buf, stat.st_size);

  return 0;

}
  1. Le programme memtac qui prend en argument le fichier à projeter et en affiche le contenu dans l’ordre inverse.
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.h>

int main(int argc, char **argv){
  if(argc != 2){
    printf("usage : %s nom_fichier\n", argv[0]);
    return 1;
  }

  int fd;
  struct stat stat;
  char *buf=NULL, *adresse_debut=NULL, *adresse_fin=NULL;

  fd = open(argv[1], O_RDONLY);
  if(fd == -1){
    perror("open");
    return 1;
  }
  if(fstat(fd, &stat) == -1){
    perror("stat");
    return 1;
  }
  buf = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0);
  if(buf == (char *)MAP_FAILED){
    perror("mmap");
    return 1;
  }
  close(fd);

  if(stat.st_size != 1) {
    adresse_fin = buf + stat.st_size;
    for(int i=stat.st_size-2; i>=0; i--){
      if(buf[i] == '\n' ){
        adresse_debut = buf + i + 1;
        write(1, adresse_debut, adresse_fin-adresse_debut);
        adresse_fin = adresse_debut;
      }else if(i == 0){
        adresse_debut = buf;
        write(1, adresse_debut, adresse_fin-adresse_debut);
      }
    }
  }

  munmap(buf, stat.st_size);

  return 0;
}
  1. Le programme memcount qui affiche le nombre de fois où un certain motif fourni en argument est présent dans le fichier.
#define _GNU_SOURCE
#include <string.h>
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.h>


int main(int argc, char **argv){
  if(argc != 3){
    printf("usage : %s nom_fichier motif\n", argv[0]);
    return 1;
  }

  int fd, compteur=0, taille;
  struct stat stat;
  char *buf=NULL, *adresse_occurence=NULL, *pointeur_buf=NULL;

  fd = open(argv[1], O_RDONLY);
  if(fd == -1){
    perror("open");
    return 1;
  }
  if(fstat(fd, &stat) == -1){
    perror("stat");
    return 1;
  }
  buf = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0);
  if(buf == (char *)MAP_FAILED){
    perror("mmap");
    return 1;
  }
  close(fd);

  taille = stat.st_size;
  pointeur_buf = buf ;

  while((adresse_occurence = memmem(pointeur_buf, taille, argv[2], strlen(argv[2]))) ){
    pointeur_buf = adresse_occurence+strlen(argv[2]);
    taille = stat.st_size - (pointeur_buf - buf);
    compteur++;
  }

  printf("Total : %d occurences\n", compteur);

  munmap(buf, stat.st_size);

  return 0;
}
  1. Le programme memgrep qui affiche, dans l’ordre inverse, toutes les lignes où le motif recherché est présent.
#define _GNU_SOURCE
#include <string.h>
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/mman.h>


int main(int argc, char **argv){
  if(argc != 3){
    printf("usage : %s nom_fichier motif\n", argv[0]);
    return 1;
  }

  int fd, taille;
  struct stat stat;
  char *buf=NULL, *adresse_occurence=NULL, *pointeur_buf=NULL;

  fd = open(argv[1], O_RDONLY);
  if(fd == -1){
    perror("open");
    return 1;
  }
  if(fstat(fd, &stat) == -1){
    perror("stat");
    return 1;
  }
  buf = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0);
  if(buf == (char *)MAP_FAILED){
    perror("mmap");
    return 1;
  }
  close(fd);

  taille = stat.st_size;
  pointeur_buf = buf ;
  char* adresse_debut, *adresse_fin;

  // Pour chaque instance de la chaine, on trouve le début et la fin de la ligne pour l'afficher
  while((adresse_occurence = memmem(pointeur_buf, taille, argv[2], strlen(argv[2]))) ){

	adresse_debut = memrchr(buf, '\n', adresse_occurence-buf);
	if (adresse_debut == NULL) { //si c'est la première ligne
		adresse_debut = buf;
	} else {
		adresse_debut++;//après le retour de ligne
	}

	adresse_fin = memchr(adresse_occurence, '\n', taille);
	if (adresse_fin == NULL) { //si c'est la dernière ligne du fichier
		adresse_fin = buf + taille;
	}
	write(1, adresse_debut, adresse_fin-adresse_debut+1);

	// on continue la recherche à partir de la ligne suivante pour éviter d'afficher plusieurs fois une ligne qui contient plus qu'une instance de la chaine recherchée
    pointeur_buf = adresse_fin+1;
    taille = stat.st_size - (pointeur_buf - buf);
  }

  munmap(buf, stat.st_size);

  return 0;
}