Dup

Dup è un programma C il cui obiettivo è mostrare l’utilizzo delle funzione dup.

 1#include <stdio.h>
 2#include <stdlib.h>
 3#include <fcntl.h>
 4#include <unistd.h>
 5
 6#define FILE_NAME "log.txt"
 7#define STDOUT 1
 8
 9#define abort(msg) do{printf(msg);exit(1);}while(0)
10
11
12int main() {
13    int ofd;
14
15    /* opend output file and check errors */
16    ofd=open(FILE_NAME,O_WRONLY|O_CREAT|O_TRUNC,0660);
17    if (ofd == -1) abort("output creation error\n");
18
19    close(STDOUT);  /* close standard output */
20    ofd = dup(ofd); /* duplicate file descriptor */
21    if (ofd == -1) abort("dup failed\n");
22
23    execlp("ls","ls",NULL); /* run 'ls' */
24}

In UNIX esistono 3 file descriptor principali:

  • 0: standard input;

  • 1: standard output;

  • 2: standard error.

Secondo lo standard POSIX (stdin), questi canali (o stream) sono predefiniti ed aperti implicitamente. I descrittori referenziano quindi a specifici canali, ma l’associazione può essere cambiata dinamicamente. Ad esempio, la funzione dup associa ad un canale (più precisamente alla file description) già esistente un nuovo descrittore. Il canale viene individuato a partire dal file descriptor passato come parametro. Il nuovo descrittore viene invece scelto prendendo il primo disponibile.

Il codice in questione utilizza queste primitive per ridirezionare lo standard output di un eseguibile (in questo caso il comando ls) su file regolare. Lo scopo viene raggiunto in pochi semplici passi:

  1. crea ed apre il file destinazione ottenendo il file descriptor ofd (riga 16);

  2. chiude lo stream di standard output (riga 19), rendendo 1 il primo file descriptor disponibile (0 è impegnato per lo standard input);

  3. invoca dup passando ofd come parametro (riga 20);

  4. sostituisce il programma del processo corrente tramite chiamata exec (riga 23).

Il comando ls stampa su standard output (file descriptor 1), il quale è stato direzionato sul file di log piuttosto che il terminale.

Osservazione

L’ultimo parametro è della open è passato in base otto (ogni cifra è compresa tra 0 e 7). Questo è identificato dal fatto che la costante comincia per 0. Essendo 8 valori rappresentabili con soli 3 bit, ogni cifra in base 8 corrisponde esattamente a 3 bit. Focalizzandoci solo sul literal 0660, questo è un intero (per l’esattezza un mode_t) la cui rappresentazione binaria è:

User

Group

Other

r

w

x

r

w

x

r

w

x

1

1

0

1

1

0

0

0

0

6

6

0

Ulteriori dettagli possono essere trovati a questo link: Microsoft C docs.

Domanda

Come è possibile esprimere i medesimi permessi utilizzando una rappresentazione decimale o esadecimale? e utilizzando le macro definite in sys/stat.h?

Riferimenti