/* fichier filtre_simple.c
créé par Yann GUIDON (whygee@f-cpu.org)
version Fri Aug  5 07:23:20 CEST 2005

 fonction :
   prend un fichier, tourne en rond puis le réécrit

 compilation :
   gcc -Wall -DBUFFER_SIZE=taille_en_octets\
     -DCHARGE=un_nombre -o filtre_simple filtre_simple.c

 invocation :
   filtre_simple nom_du_fichier_src nom_dest charge
*/

#define _FILE_OFFSET_BITS 64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>  /* open() */
#include <errno.h>  /* perror() */
#include <stdio.h>  /* printf() */
#include <stdlib.h> /* malloc(), strtol() */
#include <unistd.h> /* exit(), read() */

/* permet de moduler la charge CPU */
#ifndef CHARGE
#define CHARGE (4)
#endif

#ifndef BUFFER_SIZE
#define BUFFER_SIZE (32*1024)
#endif

char *buffer;

int main (int argc, char *argv[]) {
  unsigned long int i;
  int charge=CHARGE, j, fd_in, fd_out;
  ssize_t t=0;

  if (argc < 3) {
    printf("Erreur d'argument\n\
 Spécifier un nom de fichier source et un\
 nom de fichier destination.\n");
    exit(EXIT_FAILURE);
  }

  fd_in = open(argv[1], O_RDONLY);
  if (fd_in == -1) {
    perror("Erreur à l'ouverture de la source");
    exit(EXIT_FAILURE);
  }

  fd_out = open(argv[2], O_WRONLY|O_CREAT);
  if (fd_out == -1) {
    perror("Erreur à l'ouverture du destinataire");
    exit(EXIT_FAILURE);
  }

  if (argc > 3) {
    charge=strtol(argv[3], NULL,10);
    if (charge < 0) {
      printf("Erreur d'argument : charge invalide ?\n");
      exit(EXIT_FAILURE);
    }
  }

  buffer=malloc(BUFFER_SIZE);
  if (buffer == NULL) {
    perror("Erreur de malloc() ");
    exit(EXIT_FAILURE);
  }

  while ( (t = read(fd_in, buffer, BUFFER_SIZE)) >0 ) {

/* ne fait absolument rien mais grille du temps CPU */
    for (j=0; j<charge; j++)
      for (i=0; i<t; i++)
        buffer[i]^=j;

    write(fd_out, buffer, t);
  }

  if (t < 0) {
    perror("Erreur de lecture ");
    exit(EXIT_FAILURE);
  }

  exit(EXIT_SUCCESS);
}
