# TP2 : Fichiers

#### Ex1 
Écrire deux versions d'un programme qui copie "octet par octet" un fichier source dans un fichier destination :
		
```
./copy infile outfile
```

en utilisant : 

  1. les appels systèmes linux : `open`, `read`, `write`, `close`.
  2. les fonctions E/S standards (sdtio) : `fopen`, `fread`, `fwrite`, `fclose`.

Testez vos deux programmes  sur un fichier volumineux (utilisez la commande `dd` le pseudo fichier `dev/urandom` pour
générer un contenu aléatoire) et expliquez pourquoi le deuxième programme est beaucoup plus rapide que le
premier.

```
dd if=/dev/urandom of=test.data bs=1M count=8
```

Remarques : 
- pour être  dans les mêmes conditions, il faut être sur que le fichier à copier n'est pas en cache en mémoire. Générez un nouveau fichier de même taille, ou utilisez le programme [fadvise.c](./src/fadvise.c) qui permet de vider les blocs du cache pour un fichier quelconque.
- utilisez `strace` pour tracer les appels systèmes de vos deux programmes.

#### Ex2
Écrire un programme qui copie un fichier en utilisant `mmap`.

#### Ex3
Compilez et exécutez Le programme [coherence.c](./src/coherence.c). Qu'est ce que cela montre ?

#### Ex4
Écrire en C une commande qui prend en argument 2 noms de fichiers, et qui
détermine si les deux fichiers  ont le même contenu. 

- Votre commande renverra le code de retour 0 (fichiers	identiques) ou
 1 (fichiers différents). Vous testerez d'abord la taille des deux fichiers, et si nécessaire leur 
 contenu.
- Utilisez un buffer pour limiter les accès aux fichiers. 

Fonctions et macro utiles :

```c
int open(const char *pathname, int flags, ...
                  /* mode_t mode */ );
int stat(const char *restrict pathname,
                struct stat *restrict statbuf);
off_t lseek(int fd, off_t offset, int whence);
ssize_t read(int fd, void buf[.count], size_t count);
int memcmp(const void s1[.n], const void s2[.n], size_t n);
int close(int fd);
```


#### Ex5
Le but est d'écrire en C un programme qui efface un fichier du disque de telle manière que le contenu effacé ne soit pas
récupérable. Pour des raisons physiques, on procédera de la manière suivante :
- Si l'inode correspondant au fichier à effacer a plusieurs références, on efface juste l'entrée du répertoire correspondant.
- Sinon, on  réécrit les blocs de données :
  - une première passe avec `0xff` pour  tous les octets.
  - une deuxième passe avec des valeurs aléatoires (on utilisera le pseudo-fichier `/dev/urandom`)
  - enfin, avant d'effacer le fichier, on le renomera de manière aléatoire.

Toutes les E/S devront utilisées un cache.


Fonctions utiles :

```c
#include <sys/stat.h>
int stat(const char *restrict pathname,
         struct stat *restrict statbuf);

#include <fcntl.h>
int open(const char *pathname, int flags, ...
        /* mode_t mode */ );

#include <unistd.h>

ssize_t read(int fd, void buf[.count], size_t count);
ssize_t write(int fd, const void buf[.count], size_t count);
int unlink(const char *pathname);
int close(int fd);


#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
```

#### Ex6
Le but est d'écrire une version simplifiée de la commande `ls -al`.

```bash
$./myls /
drwxr-xr-x  18 root root       4096 07	sept.	12:48 ..
drwxr-xr-x   6 root root       4096 03	nov.	09:40 srv
drwxr-xr-x  10 root root       4096 24	sept.	21:07 usr
dr-xr-xr-x 301 root root          0 18	sept.	07:10 proc
drwxr-xr-x 312 root root     258048 12	sept.	09:46 lib
drwxrwxrwt  25 root root       2140 27	sept.	13:02 tmp
drwxr-xr-x  18 root root       4096 07	sept.	12:48 .
drwxr-xr-x   5 root root       1024 07	sept.	12:57 boot
drwxr-xr-x  32 root root        760 27	sept.	09:57 run
drwxr-xr-x  11 root root       4096 25	juil.	18:14 opt
drwxr-x---  32 root root       4096 25	sept.	13:49 root
drwxr-xr-x 122 root root      12288 27	sept.	09:57 etc
drwxr-xr-x   4 root root       4096 10	déc.	08:27 home
drwxr-xr-x   6 root root     151552 24	sept.	21:07 bin
drwxr-xr-x   6 root root     151552 24	sept.	21:07 sbin
drwxr-xr-x  23 root root       3580 27	sept.	09:57 dev
drwxr-xr-x  10 root root       4096 13	sept.	13:33 media
drwxr-xr-x  15 root root       4096 18	sept.	07:10 var
drwxr-xr-x 312 root root     258048 12	sept.	09:46 lib64
dr-xr-xr-x  13 root root          0 18	sept.	07:10 sys
drwx------   2 root root      16384 02	sept.	11:30 lost+found
-rw-r--r--   1 root root       2333 28	juin	20:49 fonts.conf
drwxr-xr-x   2 root root       4096 02	sept.	11:40 mnt
```

 - pour parcourir les entrées du repertoire passé en argument :
   ```c
   #include <sys/types.h>
   #include <dirent.h>
   
   DIR *opendir(const char *name);
   ```
 
   ```c
   #include <dirent.h>

   struct dirent *readdir(DIR *dirp);
   struct dirent {
              ino_t          d_ino;       /* Inode number */
              off_t          d_off;       /* Not an offset; see below */
              unsigned short d_reclen;    /* Length of this record */
              unsigned char  d_type;      /* Type of file; not supported
                                             by all filesystem types */
              char           d_name[256]; /* Null-terminated filename */
          };
   ```

 - les autres informations sont accessibles grâce à la fonction :

   ```c
   #include <sys/types.h>
   #include <sys/stat.h>
   #include <unistd.h>

   int stat(const char *pathname, struct stat *statbuf);

   struct stat {
              dev_t     st_dev;         /* ID of device containing file */
              ino_t     st_ino;         /* Inode number */
              mode_t    st_mode;        /* File type and mode */
              nlink_t   st_nlink;       /* Number of hard links */
              uid_t     st_uid;         /* User ID of owner */
              gid_t     st_gid;         /* Group ID of owner */
              dev_t     st_rdev;        /* Device ID (if special file) */
              off_t     st_size;        /* Total size, in bytes */
              blksize_t st_blksize;     /* Block size for filesystem I/O */
              blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */

              /* Since Linux 2.6, the kernel supports nanosecond
                 precision for the following timestamp fields.
                 For the details before Linux 2.6, see NOTES. */

              struct timespec st_atim;  /* Time of last access */
              struct timespec st_mtim;  /* Time of last modification */
              struct timespec st_ctim;  /* Time of last status change */

          #define st_atime st_atim.tv_sec      /* Backward compatibility */
          #define st_mtime st_mtim.tv_sec
          #define st_ctime st_ctim.tv_sec
          };
   ```

	Faire `man 7 inode`.
