Revisione di open(2) e documentazione O_PATH (inizio).
authorSimone Piccardi <piccardi@gnulinux.it>
Thu, 27 Sep 2018 00:42:46 +0000 (02:42 +0200)
committerSimone Piccardi <piccardi@gnulinux.it>
Thu, 27 Sep 2018 00:42:46 +0000 (02:42 +0200)
fileio.tex

index 3d16c07..2008e7a 100644 (file)
@@ -162,8 +162,8 @@ aspetta di dover scrivere i dati in uscita. Il terzo è lo \textit{standard
 \itindend{file~descriptor} 
 
 
-Benché questa sia soltanto una convenzione, essa è seguita dalla gran parte
-delle applicazioni, e non aderirvi potrebbe portare a problemi di
+Benché questa sia alla fine soltanto una convenzione, essa è seguita dalla
+totalità delle applicazioni, e non aderirvi potrebbe portare a problemi di
 interoperabilità.  Nel caso della shell tutti questi file sono associati al
 terminale di controllo, e corrispondono quindi alla lettura della tastiera per
 l'ingresso e alla scrittura sul terminale per l'uscita.  Lo standard POSIX.1
@@ -248,17 +248,29 @@ corrispondente,\footnote{è \func{open} che alloca \kstruct{file}, la inserisce
     \const{O\_CREAT} e \const{O\_EXCL}.
   \item[\errcode{EINTR}] la funzione era bloccata ed è stata interrotta da un
     segnale (vedi sez.~\ref{sec:sig_gen_beha}).
-  \item[\errcode{EISDIR}] \param{pathname} indica una directory e si è tentato
-    l'accesso in scrittura o in lettura/scrittura.
-  \item[\errcode{EFBIG}] il file è troppo grande per essere aperto (lo
-    standard richiederebbe \errval{EOVERFLOW}).
+  \item[\errcode{EINVAL}] si è usato \const{O\_CREAT} indicando un pathname
+    con caratteri non supportati dal filesystem sottostante o si è richiesto
+    \const{O\_TMPFILE} senza indicare \const{O\_WRONLY} o \const{O\_RDWR} o si
+    è usato \const{O\_DIRECT} per un filesystem che non lo supporta.
+  \item[\errcode{EISDIR}] \param{pathname} indica una directory e o si è
+    tentato un accesso che prevede la scrittura o si è usato
+    \const{O\_TMPFILE} con accesso che prevede la scrittura ma il kernel non
+    supporta la funzionalità.
+  \item[\errcode{EFBIG}] il file è troppo grande per essere aperto, in genere
+    dovuto al fatto che si è compilata una applicazione a 32 bit senza
+    abilitare il supporto per le dimesioni a 64 bit; questo è il valore
+    restituito fino al kernel 2.6.23, coi successivi viene restituito
+    \errcode{EOVERFLOW} come richiesto da POSIX.1.
   \item[\errcode{ELOOP}] si sono incontrati troppi collegamenti simbolici nel
     risolvere \param{pathname} o si è indicato \const{O\_NOFOLLOW} e
-    \param{pathname} è un collegamento simbolico.
+    \param{pathname} è un collegamento simbolico (e non si è usato
+    \const{O\_PATH}).
   \item[\errcode{ENODEV}] \param{pathname} si riferisce a un file di
     dispositivo che non esiste.
   \item[\errcode{ENOENT}] \param{pathname} non esiste e non si è richiesto
-    \const{O\_CREAT}, o non esiste un suo componente. 
+    \const{O\_CREAT}, o non esiste un suo componente, o si riferisce ad una
+    directory inesistente, si è usato \const{O\_TMPFILE} con accesso che
+    prevede la scrittura ma il kernel non supporta la funzionalità.
   \item[\errcode{ENOTDIR}] si è specificato \const{O\_DIRECTORY} e
     \param{pathname} non è una directory.
   \item[\errcode{ENXIO}] si sono impostati \const{O\_NONBLOCK} o
@@ -272,7 +284,7 @@ corrispondente,\footnote{è \func{open} che alloca \kstruct{file}, la inserisce
   \item[\errcode{EWOULDBLOCK}] la funzione si sarebbe bloccata ma si è
     richiesto \const{O\_NONBLOCK}.
   \end{errlist}
-  ed inoltre \errval{EACCES}, \errval{EFAULT}, \errval{EMFILE},
+  ed inoltre \errval{EACCES}, \errval{EDQUOT}, \errval{EFAULT}, \errval{EMFILE},
   \errval{ENAMETOOLONG}, \errval{ENFILE}, \errval{ENOMEM}, \errval{ENOSPC},
   \errval{EROFS}, nel loro significato generico.}
 \end{funcproto}
@@ -281,7 +293,9 @@ La funzione apre il file indicato da \param{pathname} nella modalità indicata
 da \param{flags}. Essa può essere invocata in due modi diversi, specificando
 opzionalmente un terzo argomento \param{mode}. Qualora il file non esista e
 venga creato, questo argomento consente di indicare quali permessi dovranno
-essergli assegnati. I valori possibili sono gli stessi già visti in
+essergli assegnati.\footnote{questo è possibile solo se si è usato in
+  \param{flags} uno fra \const{O\_CREATE} e \const{O\_TMPFILE}, in tutti gli
+  altri casi sarà ignorato.} I valori possibili sono gli stessi già visti in
 sez.~\ref{sec:file_perm_overview} e possono essere specificati come OR binario
 delle costanti descritte in tab.~\ref{tab:file_bit_perm}. Questi permessi sono
 comunque filtrati dal valore della \textit{umask} (vedi
@@ -396,51 +410,62 @@ sez.~\ref{sec:file_fcntl_ioctl}).
       \textbf{Flag} & \textbf{Significato} \\
       \hline
       \hline
-      \constd{O\_CREAT} &   Se il file non esiste verrà creato, con le regole
-                            di titolarità del file viste in
-                            sez.~\ref{sec:file_ownership_management}. Se si
-                            imposta questo flag l'argomento \param{mode} deve
-                            essere sempre specificato.\\  
-      \constd{O\_DIRECTORY}&Se \param{pathname} non è una directory la
-                            chiamata fallisce. Questo flag, introdotto con il
-                            kernel 2.1.126, è specifico di Linux e
-                            serve ad evitare dei possibili
-                            \itindex{Denial~of~Service~(DoS)}
-                            \textit{DoS}\footnotemark quando \func{opendir} 
-                            viene chiamata su una \textit{fifo} o su un dispositivo
-                            associato ad una unità a nastri. Non viene
-                            usato al di fuori dell'implementazione di
-                            \func{opendir}, ed è utilizzabile soltanto se si è
-                            definita la macro \macro{\_GNU\_SOURCE}.\\
-      \constd{O\_EXCL}    & Deve essere usato in congiunzione con
-                            \const{O\_CREAT} ed in tal caso impone che il file
-                            indicato da \param{pathname} non sia già esistente
-                            (altrimenti causa il fallimento della chiamata con
-                            un errore di \errcode{EEXIST}).\\
-      \constd{O\_LARGEFILE}&Viene usato sui sistemi a 32 bit per richiedere
-                            l'apertura di file molto grandi, la cui
-                            dimensione non è rappresentabile con la versione a
-                            32 bit del tipo \type{off\_t}, utilizzando
-                            l'interfaccia alternativa abilitata con la
-                            macro \macro{\_LARGEFILE64\_SOURCE}. Come
-                            illustrato in sez.~\ref{sec:intro_gcc_glibc_std} è
-                            sempre preferibile usare la conversione automatica
-                            delle funzioni che si attiva assegnando a $64$ la
-                            macro \macro{\_FILE\_OFFSET\_BITS}, e non usare mai
-                            questo flag.\\
-      \constd{O\_NOCTTY}  & Se \param{pathname} si riferisce ad un dispositivo
-                            di terminale, questo non diventerà il terminale di
-                            controllo, anche se il processo non ne ha ancora
-                            uno (si veda sez.~\ref{sec:sess_ctrl_term}).\\ 
+      \constd{O\_CREAT}  & Se il file non esiste verrà creato, con le regole
+                           di titolarità del file viste in
+                           sez.~\ref{sec:file_ownership_management}. Se si
+                           imposta questo flag l'argomento \param{mode} deve
+                           essere sempre specificato.\\  
+      \constd{O\_DIRECTORY}& Se \param{pathname} non è una directory la
+                             chiamata fallisce. Questo flag, introdotto con il
+                             kernel 2.1.126, è specifico di Linux e
+                             serve ad evitare dei possibili
+                             \itindex{Denial~of~Service~(DoS)}
+                             \textit{DoS}\footnotemark quando \func{opendir} 
+                             viene chiamata su una \textit{fifo} o su un
+                             dispositivo associato ad una unità a nastri. Non
+                             viene usato al di fuori dell'implementazione di
+                             \func{opendir}, ed è utilizzabile soltanto se si è
+                             definita la macro \macro{\_GNU\_SOURCE}.\\
+      \constd{O\_EXCL}   & Deve essere usato in congiunzione con
+                           \const{O\_CREAT} ed in tal caso impone che il file
+                           indicato da \param{pathname} non sia già esistente
+                           (altrimenti causa il fallimento della chiamata con
+                           un errore di \errcode{EEXIST}).\\
+      \constd{O\_LARGEFILE}& Viene usato sui sistemi a 32 bit per richiedere
+                             l'apertura di file molto grandi, la cui
+                             dimensione non è rappresentabile con la versione a
+                             32 bit del tipo \type{off\_t}, utilizzando
+                             l'interfaccia alternativa abilitata con la
+                             macro \macro{\_LARGEFILE64\_SOURCE}. Come
+                             illustrato in sez.~\ref{sec:intro_gcc_glibc_std} è
+                             sempre preferibile usare la conversione automatica
+                             delle funzioni che si attiva assegnando a $64$ la
+                             macro \macro{\_FILE\_OFFSET\_BITS}, e non usare mai
+                             questo flag.\\
+      \constd{O\_NOCTTY} & Se \param{pathname} si riferisce ad un dispositivo
+                           di terminale, questo non diventerà il terminale di
+                           controllo, anche se il processo non ne ha ancora
+                           uno (si veda sez.~\ref{sec:sess_ctrl_term}).\\ 
       \constd{O\_NOFOLLOW}& Se \param{pathname} è un collegamento simbolico
                             la chiamata fallisce. Questa è un'estensione BSD
                             aggiunta in Linux a partire dal kernel
                             2.1.126, ed utilizzabile soltanto se si è definita
                             la macro \macro{\_GNU\_SOURCE}.\\ 
-      \constd{O\_TRUNC}   & Se usato su un file di dati aperto in scrittura,
-                            ne tronca la lunghezza a zero; con un terminale o
-                            una \textit{fifo} viene ignorato, negli altri casi il
-                            comportamento non è specificato.\\ 
+      \const{O\_PATH}    & Ottiene un file descriptor io cui uso è limitato
+                           all'indicare una posizione sul filesystem o
+                           eseguire operazioni che operano solo a livello del
+                           file descriptor (e non di accesso al contenuto del
+                           file). Introdotto con il kernel 2.6.39, è specifico
+                           di Linux.\\ 
+      \const{O\_TMPFILE} & Consente di creare un file temporaneo anonimo, non
+                           visibile con un pathname sul filesystem, ma
+                           leggibile e scrivibile all'iterno del processo.
+                           Introdotto con il kernel 3.11, è specifico di
+                           Linux.\\ 
+      \constd{O\_TRUNC}  & Se usato su un file di dati aperto in scrittura,
+                           ne tronca la lunghezza a zero; con un terminale o
+                           una \textit{fifo} viene ignorato, negli altri casi
+                           il comportamento non è specificato.\\ 
       \hline
     \end{tabular}
     \caption{Le costanti che identificano le \textit{modalità di apertura} di
@@ -448,12 +473,6 @@ sez.~\ref{sec:file_fcntl_ioctl}).
   \label{tab:open_time_flag}
 \end{table}
 
-
-% TODO: aggiungere O_TMPFILE per la creazione di file temporanei senza che
-% questi appaiano sul filesystem, introdotto con il 3.11, vedi:
-% https://lwn.net/Articles/556512/, http://kernelnewbies.org/Linux_3.11
-% https://lwn.net/Articles/558598/ http://lwn.net/Articles/619146/
-
 \footnotetext{acronimo di \itindex{Denial~of~Service~(DoS)} \textit{Denial of
     Service}, si chiamano così attacchi miranti ad impedire un servizio
   causando una qualche forma di carico eccessivo per il sistema, che resta
@@ -467,28 +486,67 @@ Si è riportato in tab.~\ref{tab:open_time_flag} l'elenco dei flag delle
   esistono con Linux.}  Uno di questi, \const{O\_EXCL}, ha senso solo se usato
 in combinazione a \const{O\_CREAT} quando si vuole creare un nuovo file per
 assicurarsi che questo non esista di già, e lo si usa spesso per creare i
-cosiddetti ``\textsl{file di lock}'' (vedi sez.~\ref{sec:ipc_file_lock}). Si
-tenga presente che questa opzione è supportata su NFS solo a partire da NFSv3
-e con il kernel 2.6, nelle versioni precedenti la funzionalità viene emulata
-controllando prima l'esistenza del file per cui usarla per creare un file di
-lock potrebbe dar luogo a una \textit{race condition}.\footnote{un file
-  potrebbe venir creato fra il controllo la successiva apertura con
-  \const{O\_CREAT}, la cosa si può risolvere comunque creando un file con un
-  nome univoco ed usando la funzione \func{link} per creare il file di lock,
-  (vedi sez.~\ref{sec:ipc_file_lock}).}
+cosiddetti ``\textsl{file di lock}'' (vedi sez.~\ref{sec:ipc_file_lock}).
+
+Si tenga presente che questa opzione è supportata su NFS solo a partire da
+NFSv3 e con il kernel 2.6, nelle versioni precedenti la funzionalità viene
+emulata controllando prima l'esistenza del file per cui usarla per creare un
+file di lock potrebbe dar luogo a una \textit{race condition}, in tal caso
+infatto un file potrebbe venir creato fra il controllo la successiva apertura
+con \const{O\_CREAT}; la cosa si può risolvere comunque creando un file con un
+nome univoco ed usando la funzione \func{link} per creare il file di lock,
+(vedi sez.~\ref{sec:ipc_file_lock}).
 
 Se si usa \const{O\_EXCL} senza \const{O\_CREAT} il comportamento è
-indefinito.  Nella creazione di un file con \const{O\_CREAT} occorre sempre
-specificare l'argomento di \param{mode}, che altrimenti è ignorato. Si tenga
-presente che indipendentemente dai permessi che si possono assegnare, che in
-seguito potrebbero non consentire lettura o scrittura, quando il file viene
-aperto l'accesso viene garantito secondo quanto richiesto con i flag di
+indefinito, escluso il caso in cui viene usato con uno dei due nuovi flag
+\const{O\_PATH} o \const{O\_TMPFILE} su cui torneremo a breve.  Nella
+creazione di un file con \const{O\_CREAT} occorre sempre specificare
+l'argomento di \param{mode}, che altrimenti è ignorato. Si tenga presente che
+indipendentemente dai permessi che si possono assegnare, che in seguito
+potrebbero non consentire lettura o scrittura, quando il file viene aperto
+l'accesso viene garantito secondo quanto richiesto con i flag di
 tab.~\ref{tab:open_access_mode_flag}.  Quando viene creato un nuovo file
 \const{O\_CREAT} con tutti e tre i tempi del file di
 tab.~\ref{tab:file_file_times} vengono impostati al tempo corrente. Se invece
 si tronca il file con \const{O\_TRUNC} verranno impostati soltanto il
 \textit{modification time} e lo \textit{status change time}.
 
+Dei flag illustrati in tab.~\ref{tab:open_time_flag} due, specifici di Linux
+ed introdotti solo con i kernel più recenti, meritano un approfondimento. Il
+primo di questi è \constd{O\_PATH}, che viene usato per limitare l'uso del
+file descriptor restituito da \func{open} o all'identificazione di una
+posizione sul filesystem (ad uso delle \textit{at-functions} che tratteremo in
+sez.~\ref{sec:file_openat}) o a operazioni che riguardano solo il file
+descriptor; le sole funzioni con cui sarà possibile usare il file descriptor
+sono:
+
+\begin{itemize*}
+\item \func{close}
+\item \func{fchdir}, se il file descriptore fa riferimento a una directory
+  (dal kernel 3.5).
+\item \func{fstat} (dal kernel 3.6).  
+\item \func{fstatfs} (dal kernel 3.12).
+\item le funzioni che duplicano il file descriptor (vedi
+  sez.~\ref{sec:file_dup})
+\item 
+
+\end{itemize*}
+
+In realtà infatti usando \constd{O\_PATH} il file non viene effettivamente
+aperto, per cui ogni tentativo di usare il file descriptor così ottenuto con
+funzioni che operano effettivamente sul file (come ad esempio \func{read},
+\func{write}, \func{fchown}, \func{fchmod}, \func{ioctl}, ecc.) fallirano con
+un errore di \errval{EBADF} come se questo non fosse un file descriptor
+valido.
+
+
+
+% TODO: aggiungere O_TMPFILE per la creazione di file temporanei senza che
+% questi appaiano sul filesystem, introdotto con il 3.11, vedi:
+% https://lwn.net/Articles/556512/, http://kernelnewbies.org/Linux_3.11
+% https://lwn.net/Articles/558598/ http://lwn.net/Articles/619146/
+
+
 \begin{table}[!htb]
   \centering
   \footnotesize
@@ -512,10 +570,10 @@ si tronca il file con \const{O\_TRUNC} verranno impostati soltanto il
                            tutte le volte che il file è pronto per le
                            operazioni di lettura o scrittura. Questo flag si
                            può usare solo terminali, pseudo-terminali e socket
-                           e, a partire dal kernel 2.6, anche sulle \textit{fifo}. Per
-                           un bug dell'implementazione non è opportuno usarlo
-                           in fase di apertura del file, deve
-                           invece essere attivato successivamente con
+                           e, a partire dal kernel 2.6, anche sulle
+                           \textit{fifo}. Per un bug dell'implementazione non
+                           è opportuno usarlo in fase di apertura del file,
+                           deve invece essere attivato successivamente con
                            \func{fcntl}.\\
       \constd{O\_CLOEXEC}& Attiva la modalità di \textit{close-on-exec} (vedi
                            sez.~\ref{sec:proc_exec}) sul file. Il flag è 
@@ -540,19 +598,19 @@ si tronca il file con \const{O\_TRUNC} verranno impostati soltanto il
                            montaggio. Introdotto con il kernel 2.6.8 ed 
                            utilizzabile soltanto se si è definita la 
                            macro \macro{\_GNU\_SOURCE}.\\ 
-      \constd{O\_NONBLOCK}&Apre il file in \textsl{modalità non bloccante} per
-                           le operazioni di I/O (vedi
-                           sez.~\ref{sec:file_noblocking}). Questo significa
-                           il fallimento delle successive operazioni di
-                           lettura o scrittura qualora il file non sia pronto
-                           per la loro esecuzione immediata, invece del 
-                           blocco delle stesse in attesa di una successiva
-                           possibilità di esecuzione come avviene
-                           normalmente. Questa modalità ha senso solo per le
-                           \textit{fifo}, vedi sez.~\ref{sec:ipc_named_pipe}), o quando
-                           si vuole aprire un file di dispositivo per eseguire
-                           una \func{ioctl} (vedi
-                           sez.~\ref{sec:file_fcntl_ioctl}).\\ 
+      \constd{O\_NONBLOCK}& Apre il file in \textsl{modalità non bloccante} per
+                            le operazioni di I/O (vedi
+                            sez.~\ref{sec:file_noblocking}). Questo significa
+                            il fallimento delle successive operazioni di
+                            lettura o scrittura qualora il file non sia pronto
+                            per la loro esecuzione immediata, invece del 
+                            blocco delle stesse in attesa di una successiva
+                            possibilità di esecuzione come avviene
+                            normalmente. Questa modalità ha senso solo per le
+                            \textit{fifo}, vedi sez.~\ref{sec:ipc_named_pipe}),
+                            o quando si vuole aprire un file di dispositivo
+                            per eseguire una \func{ioctl} (vedi
+                            sez.~\ref{sec:file_fcntl_ioctl}).\\ 
       \constd{O\_NDELAY} & In Linux è un sinonimo di \const{O\_NONBLOCK}, ma
                            origina da SVr4, dove però causava il ritorno da
                            una \func{read} con un valore nullo e non con un