write(2)

NOME
write - Scrive su un descrittore di file

LIBRERIA
Libreria C standard (libc, -lc)

SINTASSI
#include <unistd.h>

ssize_t write(int fd, const void buf[.count], size_t count);

DESCRIZIONE
write() scrive fino a count byte dal buffer che inizia da buf nel file a cui fa riferimento il descrittore di file fd.

Il numero di byte scritti potrebbe essere meno di count se, per esempio, non c'è spazio sufficiente sul supporto fisico sottostante, o se si raggiunge il limite della risorsa RLIMIT_FSIZE (vedere setrlimit(2)), o se la chiamata è stata interrotta da un handler di segnale dopo che ha scritto meno di count byte (vedere anche pipe(7)).

Per un file che si può spostare (cioè un file a cui si può applicare lseek(2), per esempio un file regolare), la scrittura viene eseguita all'offset del file, e l'offset del file viene incrementato dal numero di byte effettivamente scritti. Se il file è stato aperto da open(2) con O_APPEND, l'offset del file viene prima impostato alla fine del file, e poi scritto. La regolazione dell'offset del file e l'operazione di scrittura vengono eseguite come un'operazione atomica.

POSIX richiede che una chiamata read(2) avvenuta dopo l'esecuzione di una chiamata write() restituisca i nuovi dati. Notare che non tutti i filesystem sono conformi a POSIX.

Secondo POSIX.1, se count è maggiore di SSIZE_MAX, il risultato è definito dall'implementazione; vedi NOTE per il limite superiore in Linux.

VALORE RESTITUITO
Se è andato tutto bene, la funzione restituisce il numero di byte scritti. In caso di errore viene restituito -1, e errno viene impostato per indicare l'errore.

Si noti che una chiamata write() andata a buon fine può trasferire meno di count byte. Tali scritture parziali possono avvenire per diverse ragioni; per esempio, perché lo spazio sul dispositivo del disco era insufficiente per scrivere tutti i byte richiesti, o perché una chiamata write() bloccata su un socket, una pipe, o simili è stata interrotta da un gestore di segnale dopo che aveva trasferito alcuni byte, ma prima di aver trasferito tutti quelli richiesti. Nel caso di un write parziale, il chiamante può fare un'altra chiamata a write() per trasferire i byte rimanenti. La chiamata successiva o trasferisce ulteriori byte o può determinare un errore (e.g., se il disco ora è pieno).

Se count è zero, e fd fa riferimento ad un file regolare, write() può restituire uno stato di insuccesso se viene rilevato uno degli errori descritti più avanti. Se non vengono rilevati errori, o se non la rilevazione degli errori non è eseguita, restituisce 0 senza causare altri effetti. Se count è zero e fd fa riferimento ad un file diverso da uno regolare, i risultati non sono specificati.

ERRORI

EAGAIN
    Il descrittore di file fd fa riferimento a un file diverso da un socket ed è stato marcato come non bloccante (O_NONBLOCK), e la scrittura si bloccherebbe. Vedi open(2) per ulteriori dettagli sull'opzione O_NONBLOCK.

EAGAIN o EWOULDBLOCK
    Il descrittore di file fd fa riferimento a un diverso da un socket ed è stato marcato come non bloccante (O_NONBLOCK), e la scrittura si bloccherebbe. POSIX.1-2001 consente che venga restituito uno qualsiasi dei due errori per questo caso, e non richiede che queste costanti abbiano lo stesso valore, per cui un'applicazione portabile dovrebbe verificare entrambe le possibilità.

EBADF
    fd non è un decrittore di file valido o non è aperto in scrittura.

EDESTADDRREQ
    fd fa riferimento a un socket a datagrammi per il quale un indirizzo dello stesso livello non è stato impostato usando connect(2).

EDQUOT
    La quota utente di blocchi del disco sul filesystem contenente il file a cui fd fa riferimento è esaurita.

EFAULT
    I bufè al di fuori del proprio spazio di indirizzamento accessibile.

EFBIG
    È stato fatto un tentativo di scrivere un file che supera la massima dimensione del file definita dall'implementazione o il limite di dimensione del file del processo, o di scrivere ad una posizione oltre il massimo offset consentito.

EINTR
    La chiamata è stata interrotta da un segnale prima che sia stato scritto qualunque dato; vedere signal(7).

EINVAL
    fd è attaccato a un oggetto su cui non si può scrivere; o il file è stato aperto con l'opzione O_DIRECT, e l'indirizzo specificato in buf, o il valore specificato in count, o l'offset del file non è correttamente allineato.

EIO EIO Un errore I/O di basso livello è accaduto mentre si modificava l'inode. Quest'errore può riguardare il "write-back" di dati scritti da un precedente write(), che può essere stato eseguito usando un altro descrittore di file che serviva per accedere allo stesso file. A partire da Linux 4.13, gli errori derivanti da write-back si presentano con la speranza che possano essere riportati da successive richieste di write(), e verranno riportati da un successivo fsync(2) (che siano stati riportati o no anche da write()). Un'altra causa di EIO su filesystem collegati in rete è quando un lock consigliato (advisory lock) era già stato scaricato sul descrittore di file e questo lock è stato perso. Si veda la sezione Lost locks di fcntl(2) per ulteriori dettagli.

ENOSPC
    Il dispositivo contenente il file a cui fa riferimento fd non ha spazio per i dati.

EPERM
    L'operazione è stata impedita da una restrizione sul file; vedi fcntl(2).

EPIPE
    fd è connesso a una pipe o un socket la cui lettura è chiusa. Quando ciò accade il processo di scrittura riceverà anche un segnale SIGPIPE. (Quindi il valore restituito in scrittura è visto solo se il programma intercetta, blocca o ignora questo segnale).

Possono accadere altri errori, in funzione dell'oggetto connesso a fd.

CONFORME A
POSIX.1-2008.

STORIA
SVr4, 4.3BSD, POSIX.1-2001.

Sotto SVr4 una scrittura può essere interrotta e restituire EINTR in qualsiasi punto, non solo prima che venga scritto un dato.

NOTE
Un ritorno con successo da write() non dà alcuna garanzia che i dati siano stati trasferiti sul disco. Su alcuni filesystem, compreso NFS, esso non garantisce che questo spazio sia stato riservato per i dati in modo corretto. In questo caso, alcuni errori potrebbero essere differiti fino a un futuro write(), fsync(2), o anche close(2). Il solo modo per essere sicuri è di chiamare fsync(2) dopo che si è eseguita la scrittura di tutti i propri dati.

Se una scrittura con write() viene interrotta da un handler di segnale prima che venga scritto qualunque byte, la chiamata fallisce con l'errore EINTR; se viene interrotta dopo aver scritto almeno un byte, la chiamata ha successo e restituisce il numero di byte scritti.

Su Linux, write() (e chiamate di sistema simili) trasferiranno al massimo 0x7ffff000 (2,147,479,552) byte, restituendo il numero di byte effettivamente trasferiti. (Questo è vero sia sui sistemi a 32 bit sia su quelli a 64 bit)

Un valore di errore restituito mentre si esegue una chiamata write() usando I/O diretto non significa che l'intera scrittura non abbia avuto successo. Possono venir scritti dati parziali e i dati all'offset del file sul quale è stata tentata la chiamata write() dovrebbe essere considerata incongruente.

BUG
Secondo POSIX.1-2008/SUSv4 Section XSI 2.9.7 ("Thread Interactions with Regular File Operations"):

    Tutte le seguenti funzioni devono essere atomiche l'una rispetto all'altra nei risultati specificati in POSIX.1-2008 quando esse operano su file regolari o su collegamenti simbolici: ...

Tra le API elencate successivamente ci sono write() e writev(2). E tra i risultati che dovrebbero essere atomici attraverso i thread (e i processi) ci sono gli aggiornamenti dell'offset dei file. Tuttavia, sulle versioni di Linux precedenti alla 3.14 non era così: se due processi che condividono un descrittore di file aperto (vedi open(2)) effettuano un write() (o writev(2)) allo stesso tempo, le operazioni I/O non erano atomiche rispetto all'offset del file, col risultato che i blocchi di dati in uscita dai due processi potrebbero (non correttamente) sovrapporsi. Questo problema è stato risolto in Linux 3.14.

VEDERE ANCHE
close(2), fcntl(2), fsync(2), ioctl(2), lseek(2), open(2), pwrite(2), read(2), select(2), writev(2), fwrite(3)

TRADUZIONE
La traduzione italiana di questa pagina di manuale è stata creata da Goffredo Baroncelli <kreijack@usa.net>, Giulio Daprelà <giulio@pluto.it>, Elisabetta Galli <lab@kkk.it>, Marco Curreli <marcocurreli@tiscali.it> e Giuseppe Sacco <eppesuig@debian.org>

Questa traduzione è documentazione libera; leggere la GNU General Public License Versione 3 (https://www.gnu.org/licenses/gpl-3.0.html) o successiva per le condizioni di copyright. Non ci assumiamo alcuna responsabilità.

Per segnalare errori nella traduzione di questa pagina di manuale inviare un messaggio a pluto-ildp@lists.pluto.it.