Inizio trattazione statx
authorSimone Piccardi <piccardi@gnulinux.it>
Sun, 18 Aug 2019 14:53:21 +0000 (16:53 +0200)
committerSimone Piccardi <piccardi@gnulinux.it>
Sun, 18 Aug 2019 14:53:21 +0000 (16:53 +0200)
fileio.tex
listati/InitFile.c [new file with mode: 0644]
listati/statx.h [new file with mode: 0644]
sources/Gapil.h
sources/InitFile.c
sources/test_initfile.c

index d2522e1..a99960a 100644 (file)
@@ -1764,7 +1764,6 @@ specificata.\footnote{l'introduzione è avvenuta su proposta dello sviluppatore
 Essendo accomunate dalla stessa interfaccia le tratteremo insieme in questa
 sezione pur non essendo strettamente attinenti l'I/O su file.
 
-
 Benché queste funzioni non siano presenti negli standard tradizionali esse
 sono state adottate da altri sistemi unix-like come Solaris, i vari BSD, fino
 ad essere incluse in una recente revisione dello standard POSIX.1 (la
@@ -2136,7 +2135,7 @@ utilizzare invece la funzione di sistema \funcd{fstatat}, il cui prototipo è:
 \fhead{sys/stat.h}
 \fdecl{int fstatat(int dirfd, const char *pathname, struct stat *statbuf, int
   flags)} 
-\fdesc{Rimuove una voce da una directory.} 
+\fdesc{Legge le informazioni di un file.} 
 }
 
 {La funzione ritorna gli stessi valori e gli stessi codici di errore di
@@ -2231,7 +2230,6 @@ consentirebbe rendere accessibile all'interno di un \textit{choot} (vedi
 sez.~\ref{sec:file_chroot}) un qualunque file sia stato aperto fuori dallo
 stesso prima di entrarvi.
 
-
 % NOTE per la discussione sui problemi di sicurezza relativi a questa
 % funzionalità vedi http://lwn.net/Articles/562488/
 
@@ -2239,52 +2237,73 @@ Per questo motivo l'uso di \const{AT\_EMPTY\_PATH} richiede comunque privilegi
 amministrativi, anche se, quando è disponibile il filesystem \texttt{/proc}, è
 possibile usare \func{linkat} per creare un file da un qualunque file
 descriptor un processo abbia aperto, usandola con un codice analogo al
-seguente:\footnote{non esiste, al momento, una modalità per evitare i rischi
-  illustrati in precedenza se si sta usando il filesystem \textit{proc}.}
+seguente:\footnote{non esiste al momento, se si sta usando il filesystem
+  \textit{proc}, una modalità per evitare i rischi illustrati in precedenza.}
 \includecodesnip{listati/procfd_linkat.c}
-
-Questa modalità è anche quella con cui è possibile assegnare in un secondo
+e questa modalità è anche quella con cui è possibile assegnare in un secondo
 tempo il nome ad un file anonimo creato usando \func{open} con
 \const{O\_TMPFILE}; ma si deve tenere presente che per questi file la funzione
-ha un comportamento particolare. In generale infatti quando il file sorgente
-di \func{linkat} ha un numero di collegamenti nulli (cosa che avviene ad
-esempio quando si apre un file temporaneo e lo si cancella subito dopo oppure
-quando viene cancellato un file aperto in precedenza) la funzione non consente
-di ricollegarlo ad un altro file riassegnandogli un nuovo nome e fallisce
-sempre, qualunque siano i permessi del processo e che si usi questo approccio
-o \const{AT\_EMPTY\_PATH}, con un errore di \errval{ENOENT}.
-
-Questo non avviene se il file descriptor sorgente è stato ottenuto con
-\const{O\_TMPFILE} e la funzione ha successo, a meno che non si sia usato
-nell'apertura anche \const{O\_EXCL} per impedire questo specifico
-comportamento, e continuare ad ottenere l'errore di \errval{ENOENT}. In fig.
-
-Pertanto la modalità per creare in maniera sicura la versione iniziale di un
-file cui abbiamo accennato a pag.~\pageref{open_o_tmpfile_flag},
-
+ha un comportamento particolare.
+
+In generale infatti quando il file sorgente di \func{linkat} ha un numero di
+collegamenti nulli (cosa che avviene ad esempio quando si apre un file
+temporaneo e lo si cancella subito dopo oppure quando viene cancellato un file
+aperto in precedenza) la funzione non consente di ricollegarlo ad un altro
+file riassegnandogli un nuovo nome e fallisce sempre con un errore di
+\errval{ENOENT} qualunque siano i permessi del processo, e che si usi questo
+approccio o \const{AT\_EMPTY\_PATH}.  Ma questo non avviene se il file
+descriptor è stato ottenuto con \const{O\_TMPFILE}, in tal caso la funzione ha
+successo, a meno che non si sia usato nell'apertura anche \const{O\_EXCL} per
+impedire questo comportamento, e continuare ad ottenere \errval{ENOENT}.
+
+In fig.~\ref{fig:initfile} si è riportato il codice della funzione
+\func{InitFile}, che consente di creare in maniera sicura il contenuto
+iniziale di un file utilizzando \const{O\_TMPFILE} e \func{linkat}, come
+accennato a pag.~\pageref{open_o_tmpfile_flag}. La funzione richiede di
+indicare il file da creare usando la sintassi delle \textit{at-functions},
+specificando la directory in cui crearlo con il corrispondente file descriptor
+passato nell'argomento \texttt{dirfd} ed il pathname relativo ed essa passato
+l'argomento \texttt{file}; il contenuto iniziale del file deve essere fornito
+nel buffer \texttt{buf} di lunghezza \texttt{size}.
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{\codesamplewidth}
-    \includecodesample{listati/initfile.c}
+    \includecodesample{listati/InitFile.c}
   \end{minipage}
-  \caption{Esempio di codice creare in maniera sicura il contenuto iniziale di
-    un file.} 
+  \caption{Esempio di codice per creare in maniera sicura il contenuto
+    iniziale di un file.}
   \label{fig:initfile}
 \end{figure}
 
-
-
-
-
-
-% TODO: Trattare esempio di inzializzazione di file e successivo collegamento
-% con l'uso di O_TMPFILE e linkat, vedi man open
-
-
-
-% TODO manca prototipo di renameat2, introdotta nel 3.15, vedi
-% http://lwn.net/Articles/569134/ 
-
+La funzione come primo passo (\texttt{\small 6--10}) ottiene un file
+descriptor accessibile in lettura/scrittura invocando \func{openat} con il
+flag \const{O\_TMPFILE} per ottenere un file anonimo, facendo riferimento a
+quella che sarà la directory di destinazione in cui poi verrà collegato lo
+stesso passata dal chiamante in \texttt{dirfd}, usando ``\texttt{.}'' come
+\textit{pathname} relativo. Si noti come nella chiamata si impostino anche
+(per semplicità si è usato un valore fisso) i valori iniziali dei permessi del
+file (lettura e scrittura solo per il proprietario), e come dopo la chiamata
+si controlli la presenza di un eventuale errore, ritornandolo con un messaggio
+qualora avvenga.
+
+Il secondo passo (\texttt{\small 11--15}) è quello di chiamare la funzione
+\func{FullWrite} (che tratteremo in dettaglio in sez.~\ref{sec:sock_io_behav})
+per eseguire la scrittura del contenuto del buffer \texttt{buf} sul file
+anonimo ottenuto con \func{openat}; in sostanza la funzione scrive tutto il
+contenuto del buffer, iterando le scritture qualora non sia possibile eseguire
+tutto con una singola \func{write}, cosa che comunque per i file su disco in
+genere non avviene mai.
+
+Una volta completata con successo la scrittura l'ultimo passo (\texttt{\small
+  17--23}) è collegare il file anonimo con \func{linkat}, per questo però
+occorre utilizzare il \textit{pathname} ad esso associato sotto
+\texttt{/proc}, che viene ottenuto (\texttt{\small 16}) con una
+\func{snprintf} (vedi sez.~\ref{sec:file_formatted_io}) usando file descriptor
+restituito da \func{openat}. Con questo \textit{pathname} si può procedere
+(\texttt{\small 17}) a chiamare \func{linkat} per eseguire il collegamento, in
+cui occorre usare il flag \const{AT\_SYMLINK\_NOFOLLOW} come nell'esempio
+precedente.
 
 Altre due funzioni che utilizzano due \textit{pathname} (e due file
 descriptor) sono \funcd{renameat} e \funcd{renameat2}, corrispondenti alla
@@ -2333,15 +2352,13 @@ aggiuntivo \param{flags}; in questo caso \func{renameat} è totalmente
 equivalente all'utilizzo di \func{renamat2} con un valore nullo per
 \param{flags}.
 
-L'uso di \func{renameat} è identico a quello di \func{rename}, con le solite
-note relative alle estensioni delle \textit{at-functions}, applicate ad
-entrambi i \textit{pathname} passati come argomenti alla funzione. Con
-\func{renameat2} l'introduzione dell'argomento \func{flags} (i cui valori
-possibili sono riportati in tab.~\ref{tab:renameat2_flag_values}) ha permesso
-di aggiungere alcune funzionalità non previste al momento da nessuno standard,
-e specifiche di Linux. Si tenga conto che questa funzione di sistema non viene
-definita nella \acr{glibc} per cui deve essere chiamata utilizzando
-\func{syscall} come illustrato in sez.~\ref{sec:intro_syscall}.
+L'uso di \func{renameat} è identico a quello di \func{rename}, con la sintassi
+delle \textit{at-functions} applicabile ad entrambi i \textit{pathname} passati
+come argomenti alla funzione. Con \func{renameat2} l'introduzione
+dell'argomento \func{flags} (i cui valori possibili sono riportati in
+tab.~\ref{tab:renameat2_flag_values}) ha permesso di aggiungere alcune
+funzionalità specifiche di Linux non previste al momento da nessuno standard
+(la funzione è disponibile nelle \acr{glibc} a partire dalla versione 2.28).
 
 \begin{table}[htb]
   \centering
@@ -2370,13 +2387,12 @@ L'uso dell'argomento \param{flags} in questo caso non attiene alle
 funzionalità relative alla \textit{at-functions}, ma consente di estendere le
 funzionalità di \func{rename}. In particolare \func{renameat2} consente di
 eseguire uno scambio di nomi in maniera atomica usando il flag
-\constd{RENAME\_EXCHANGE}; quando viene specificato la funzione non solo
-rinomina \param{oldpath} in \param{newpath}, ma rinomina anche, senza dover
-effettuare un passaggio intermedio, \param{newpath} in \param{oldpath}. Quando
-si usa questo flag, entrambi i \textit{pathname} passati come argomenti alla
-funzione devono esistere, e non è possibile usare \const{RENAME\_NOREPLACE},
-non ci sono infine restrizioni sul tipo dei file (regolari, directory, link
-simbolici, ecc.) di cui si scambia il nome.
+\constd{RENAME\_EXCHANGE}; se specificato la funzione rinomina in un colpo
+solo \param{oldpath} in \param{newpath} e \param{newpath} in
+\param{oldpath}. Usando questo flag, entrambi i \textit{pathname} passati come
+argomenti devono esistere, e non è possibile usare \const{RENAME\_NOREPLACE},
+non ci sono infine restrizioni sul tipo di file (regolare, directory, link
+simbolici, dispositivo) di cui si scambia il nome.
 
 Il flag \constd{RENAME\_NOREPLACE} consente di richiedere la generazione di un
 errore nei casi in cui \func{rename} avrebbe causato una sovrascrittura della
@@ -2392,20 +2408,27 @@ Infine il flag \constd{RENAME\_WHITEOUT}, introdotto con il kernel 3.18,
 richiede un approfondimento specifico, in quanto attiene all'uso della
 funzione con dei filesystem di tipo \textit{overlay}/\textit{union}, dato che
 il flag ha senso solo quando applicato a file che stanno su questo tipo di
-filesystem. 
-
-Un \textit{overlay} o \texttt{union filesystem} è un filesystem speciale
-strutturato in livelli, in cui si rende scrivibile un filesystem accessibile
-in sola lettura, \textsl{sovrapponendogli} un filesystem scrivibile su cui
-vanno tutte le modifiche. Un tale tipo di filesystem serve ad esempio a
-rendere scrivibili i dati processati quando si fa partire una distribuzione
-\textit{Live} basata su CD o DVD, ad esempio usando una chiavetta o uno spazio
-disco aggiuntivo.
+filesystem.  Un \textit{overlay} o \textit{union filesystem} è un filesystem
+speciale strutturato in livelli, in cui si rende scrivibile un filesystem
+accessibile in sola lettura, \textsl{sovrapponendogli} un filesystem
+scrivibile su cui vanno tutte le modifiche. Un tale tipo di filesystem serve
+ad esempio a rendere scrivibili i dati processati quando si fa partire una
+distribuzione \textit{Live} basata su CD o DVD, ad esempio usando una
+chiavetta o uno spazio disco aggiuntivo.
 
 In questo caso quando si rinomina un file che sta nello strato in sola lettura
-quello che succede è questo viene copiato a destinazione sulla parte
-accessibile in scrittura, ma l'originale non può essere cancellato, per far si
-che esso non appaia più è possibile creare 
+questo viene copiato a destinazione sulla parte accessibile in scrittura, ma
+l'originale non può essere cancellato; per far si che esso non appaia più è
+possibile creare un oggetto speciale del filesystem, chiamato
+\textit{whiteout}, che serve a renderlo non più visibile. La funzione consente
+di creare questo oggetto, che in un filesystem ordinario verrebbe visto come
+un file di dispositivo con \textit{major minor} e \textit{minor number} nulli,
+in maniera atomica quando si rinomina un file.  Dato che l'uso di
+\const{RENAME\_WHITEOUT} comporta in sostanza la creazione di un file di
+dispositivo, l'operazione è privilegiata (occorre la \textit{capability}
+\texttt{CAP\_MKNOD}), inoltre occorre anche il supporto nel filesystem usato
+come supporto per la scrittura. Infine l'operazione non è compatibile con
+\const{RENAME\_EXCHANGE}.
 
 \itindend{overlay~filesytem}
 \itindend{union~filesytem}
@@ -2416,16 +2439,184 @@ che esso non appaia più è possibile creare
 % https://lwn.net/Articles/707602/ e
 % https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=a528d35e8bfcc521d7cb70aaf03e1bd296c8493f) 
 
+Benché non rientri nelle \textit{at-functions} previste nello standard
+POSIX.1-2008, tratteremo qui anche la funzione di sistema \funcd{statx},
+introdotta con il kernel 4.11 e disponibile dalle versione 2.28 della
+\acr{glibc}, il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{sys/types.h}
+\fhead{sys/stat.h}
+\fhead{unistd.h}
+\fhead{fcntl.h}
+\fdecl{int statx(int dirfd, const char *pathname, int flags, \\
+\phantom{int statx(}unsigned int mask, struct statx *statxbuf)} 
+\fdesc{Legge le informazioni di un file.} 
+}
+
+{La funzione ritorna gli stessi valori e gli stessi codici di errore di
+  \func{stat}, \func{fstat}, o \func{lstat} a seconda del valore di
+  \param{flags}, ed in più:
+  \begin{errlist}
+  \item[\errcode{EBADF}] \param{dirfd} non è un file descriptor valido.
+  \item[\errcode{EINVAL}] \param{flags} non ha un valore valido o \param{mask}
+    ha un valore riservato.
+  \item[\errcode{ENOTDIR}] \param{pathname} è un \textit{pathname} relativo,
+    ma \param{dirfd} fa riferimento ad un file.
+  \end{errlist}
+}  
+\end{funcproto}
+
+La funzione è una estensione specifica di Linux consente di leggere le
+informazioni di un file; ha la stessa sintassi di \func{fstatat} utilizzando
+con lo stesso significato gli argomenti \param{dirfd} e \param{pathname} ed i
+valori \const{AT\_EMPTY\_PATH}, \const{AT\_NO\_AUTOMOUNT} e
+\const{AT\_SYMLINK\_NOFOLLOW} per \param{flags}. Si può pertanto indicare il
+file di cui si vogliono ottenere i dati con un \textit{pathname} assoluto, con
+un \textit{pathname} relativo (sia alla directory corrente che a quella
+indicata da \param{dirfd}) o con un file descriptor ad esso associato.
+
+La funzione però consente di ottenere informazioni più dettagliate rispetto a
+quelle fornite dalle funzioni tradizionali come \func{stat} e \func{fstatat},
+ed è in grado di controllare le modalità con cui le ottiene nel caso un file
+sia posto su un filesystem remoto.  Per questo, oltre ai tre valori
+precedenti, l'argomento \param{flags} consente anche gli ulteriori valori
+elencati in tab.~\ref{tab:statx_flags_const}, con il significato ivi
+illustrato.
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Costante} & \textbf{Significato} \\
+    \hline
+    \hline
+    \constd{AT\_STATX\_SYNC\_AS\_STAT}& si comporta esattamente come
+                                        \func{stat}, in questo caso (il default
+                                        se non viene indicato niente) il
+                                        risultato dipende dal tipo di
+                                        filesystem.\\
+    \constd{AT\_STATX\_FORCE\_SYNC}& richiede che i valori degli attributi
+                                     richiesti siano, in caso di un filesystem
+                                     di rete, siano sincronizzati con il server
+                                     remoto, questo può forzare una scrittura
+                                     dei dati (in particolare i tempi del file)
+                                     verso lo stesso.\\
+    \constd{AT\_STATX\_DONT\_SYNC} & chiede di non sincronizzare nessun dato,
+                                     ritornando quanto presente nella cache,
+                                     questo significa che i dati potrebbero
+                                     essere non coerenti ed aggiornati, ma si
+                                     evita, in caso di filesystem di rete, la
+                                     necessità di contattare il server remoto.\\ 
+    \hline
+  \end{tabular}  
+  \caption{Valori specifici di \func{statx} per l'argomento \param{flags}.}
+  \label{tab:statx_flags_const}
+\end{table}
+
+La funzione restituisce le informazioni relative al file richiesto nella
+struttura \struct{statx} puntata dall'argomento \param{statxbuf}.  Inoltre
+data la quantità di informazioni che possono essere richieste, la funzione
+consente, con l'argomento \param{mask} di selezionare quelle volute, questa
+deve essere assegnata ad una maschera binaria dei valori illustrati in
+tab.~\ref{tab:statx_mask_const}.
+
+
+\begin{table}[htb]
+  \centering
+  \footnotesize
+  \begin{tabular}[c]{|l|l|}
+    \hline
+    \textbf{Costante} & \textbf{Significato} \\
+    \hline
+    \hline
+    \constd{STATX\_TYPE}  & Tipo del file (\texttt{stx\_mode \& S\_IFMT}).\\
+    \constd{STATX\_MODE}  & Permessi del file (\texttt{stx\_mode \&
+                            \tild{}S\_IFMT}).\\ 
+    \constd{STATX\_NLINK} & Numero di collegamenti (\textit{hard link},
+                            \texttt{stx\_nlink}).\\ 
+    \constd{STATX\_UID}   & Proprietario del file (per \ids{UID},
+                            \texttt{stx\_uid}).\\
+    \constd{STATX\_GID}   & Gruppo proprietario del file (per \ids{GID},
+                            \texttt{stx\_gid}).\\
+    \constd{STATX\_ATIME} & Tempo di ultimo accesso (\texttt{stx\_atime}).\\
+    \constd{STATX\_MTIME} & Tempo di ultima modifica (\texttt{stx\_mtime}).\\
+    \constd{STATX\_CTIME} & Tempo di ultimo cambiamento (\texttt{stx\_mtime}).\\
+    \constd{STATX\_INO}   & Numero di \textit{inode} (\texttt{stx\_ino}).\\
+    \constd{STATX\_SIZE}  & Dimensione del file (\texttt{stx\_size}).\\
+    \constd{STATX\_BLOCKS}& Numero di blocchi del file (\texttt{stx\_blocks}).\\
+    \constd{STATX\_BASIC\_STATS}& Tutte le informazioni precedenti.\\
+    \constd{STATX\_BTIME} & Tempo di creazione (\texttt{stx\_btime}).\\
+%    \constd{}& .\\
+    \constd{STATX\_ALL}   & Tutte le informazioni.\\
+    \hline
+  \end{tabular}
+  \caption{Le costanti per i valori dell'argomento \param{mask} di
+    \func{statx}.}
+  \label{tab:statx_mask_const}
+\end{table}
+
+Si tenga presente che il kernel accetta non richiede che \param{mask} contenga
+solo i flag di tab.~\ref{tab:statx_mask_const}, valori ulteriori in genere
+vengono usualmente ignorati ma non si può comunque indicare un valore
+qualunque in quanto alcuni bit sono riservati per future
+estensioni.\footnote{in particolare il bit \constd{STATX\_\_RESERVED} che se
+  usato causa il fallimento della funzione con un errore di \errval{EINVAL}.}
+Inoltre non è detto che tutte le informazioni richieste con \param{mask} siano
+disponibili, per questo il kernel restituisce in un opportuno campo della
+struttura \struct{statx}, \val{stx\_mask}, quali sono i dati effettivamente
+restituiti, che possono in alcuni casi essere anche di più di quelli richiesti
+(se l'informazione aggiuntiva è ottenuta senza costi ulteriori) per cui è
+normale che questo valore possa essere diverso da quanto richiesto.
+
+In particolare se un filesystem ha dei campi che non sono supportati o con
+valori che non hanno corrispondenza in un sistema unix-like, questi potranno
+essere restituiti con valori fittizi se disponibili (ad esempio gli \ids{UID}
+e \ids{GID} impostati in fase di montaggio per filesystem che non supportano
+gli utenti) ma il relativo bit in \val{stx\_mask} sarà comunque
+cancellato. Infine è possibile che campi diversi possano avere informazioni
+ottenute in momenti diversi per cui in caso di cambiamenti al file eseguiti in
+concorrenza a \func{statx} si possono ottenere campi con valori precedenti o
+posteriori il cambiamento.
+
+
+\begin{figure}[!htb]
+  \footnotesize
+  \centering
+  \begin{minipage}[c]{0.8\textwidth}
+    \includestruct{listati/statx.h}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \structd{statx} per la lettura delle informazioni dei 
+    file.}
+  \label{fig:file_statx_struct}
+\end{figure}
+
+
+Si è riportata in fig.~\ref{fig:file_statx_struct} la definizione della
+struttura \struct{statx} come presente in \headfile{sys/stat.h}.
+
 
 % TODO: manca prototipo e motivazione di fexecve, da trattare qui in quanto
 % inserita nello stesso standard e da usare con openat, vedi 
 % http://pubs.opengroup.org/onlinepubs/9699939699/toc.pdf
+
 % TODO manca prototipo di execveat, introdotta nel 3.19, vedi
 % https://lwn.net/Articles/626150/ cerca anche fexecve
+
 % TODO: manca prototipo e motivazione di execveat, vedi
 % http://man7.org/linux/man-pages/man2/execveat.2.html 
 
 
+Infine trattiamo qui altre due funzioni che non attengono che in maniera
+indiretta all'uso dei file, ma sono comunque legate alla stessa interfaccia
+delle \textit{at-functions} per quanto riguarda l'accesso ad un file.
+
+
+
+
+
 % TODO: trattare i nuovi AT_flags quando e se arriveranno, vedi
 % https://lwn.net/Articles/767547/ 
 
@@ -4807,9 +4998,9 @@ con uno dei valori \const{FSETLOCKING\_INTERNAL} o
 % LocalWords:  FIONREAD epoll FIOQSIZE side effects SAFE BYCALLER QUERY EACCES
 % LocalWords:  EBUSY OpenBSD syncfs futimes timespec only init ESRCH kill NTPL
 % LocalWords:  ENXIO  NONBLOCK WRONLY EPERM NOATIME ETXTBSY EWOULDBLOCK PGRP SZ
-% LocalWords:  EFAULT capabilities GETPIPE SETPIPE RESOURCE NFSv
-% LocalWords:  Documentation Urlich Drepper futimesat times
-% LocalWords:  futimens fs Tread TMPFILE EDQUOT extN Minix UDF XFS
+% LocalWords:  EFAULT capabilities GETPIPE SETPIPE RESOURCE NFSv InitFile stx
+% LocalWords:  Documentation Urlich Drepper futimesat times FullWrite major
+% LocalWords:  futimens fs Tread TMPFILE EDQUOT extN Minix UDF XFS mask
 % LocalWords:  shmem Btrfs ubifs tmpfile fchmod fchown fsetxattr fchdir PF
 % LocalWords:  fstatfs SIGTTIN EDESTADDRREQ datagram connect seal pag
 % LocalWords:  dirty execveat execve scandirat statx AUTOMOUNT automount DAC
diff --git a/listati/InitFile.c b/listati/InitFile.c
new file mode 100644 (file)
index 0000000..e7d010a
--- /dev/null
@@ -0,0 +1,24 @@
+ssize_t InitFile(int dirfd, const char *file, const char *buf, size_t size) 
+{
+    int fd, written, res;
+    char path[PATH_MAX];
+   
+    fd = openat(dirfd, ".", O_TMPFILE|O_RDWR, S_IRUSR|S_IWUSR);
+    if (fd < 0) {
+       perror("Cannot get temporary filedescritor");
+       return(fd);
+    }
+    written = FullWrite(fd, buf, size);
+    if (written < 0) {
+       perror("error writing on tmp file");
+       return(res);
+    }
+    snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd);
+    res = linkat(AT_FDCWD, path, dirfd, file, AT_SYMLINK_FOLLOW);
+    if (res < 0) {
+       perror("error linking the file");
+       return(res);
+    } else {
+       return written;
+    }
+}
diff --git a/listati/statx.h b/listati/statx.h
new file mode 100644 (file)
index 0000000..4eecfd6
--- /dev/null
@@ -0,0 +1,27 @@
+struct statx {
+    __u32 stx_mask;        /* Mask of bits indicating filled fields */
+    __u32 stx_blksize;     /* Block size for filesystem I/O */
+    __u64 stx_attributes;  /* Extra file attribute indicators */
+    __u32 stx_nlink;       /* Number of hard links */
+    __u32 stx_uid;         /* User ID of owner */
+    __u32 stx_gid;         /* Group ID of owner */
+    __u16 stx_mode;        /* File type and mode */
+    __u64 stx_ino;         /* Inode number */
+    __u64 stx_size;        /* Total size in bytes */
+    __u64 stx_blocks;      /* Number of 512B blocks allocated */
+    __u64 stx_attributes_mask; 
+                           /* Mask to show what's supported in stx_attributes */
+    /* The following fields are file timestamps */
+    struct statx_timestamp stx_atime;  /* Last access */
+    struct statx_timestamp stx_btime;  /* Creation */
+    struct statx_timestamp stx_ctime;  /* Last status change */
+    struct statx_timestamp stx_mtime;  /* Last modification */
+    /* If this file represents a device, then the next two
+       fields contain the ID of the device */
+    __u32 stx_rdev_major;  /* Major ID */
+    __u32 stx_rdev_minor;  /* Minor ID */
+    /* The next two fields contain the ID of the device
+       containing the filesystem where the file resides */
+    __u32 stx_dev_major;   /* Major ID */
+    __u32 stx_dev_minor;   /* Minor ID */
+};
index c5a702f..429fc6f 100644 (file)
@@ -113,7 +113,7 @@ size_t full_fwrite(FILE *file, void *buf, size_t count);
 /* Function dir_scan: simple scan for a directory. See dir_scan.c */
 int dir_scan(char * dirname, int(*compute)(struct dirent *));
 /* Function InitFile: secure create of a file with initial content */
-ssize_t InitFile(int dirfd, const char *file, const char *buf, size_t count);
+ssize_t InitFile(int dirfd, const char *file, const char *buf, size_t size);
 /* Function full_fread: to read from a standard file. See full_fread.c */
 /*
  * Shared memory handling functions. See SharedMem.c
index 307442a..a1e3e46 100644 (file)
@@ -37,9 +37,9 @@
 #include "Gapil.h"
 #include "macros.h"
 
-ssize_t InitFile(int dirfd, const char *file, const char *buf, size_t count
+ssize_t InitFile(int dirfd, const char *file, const char *buf, size_t size
 {
-    int fd, res;
+    int fd, written, res;
     char path[PATH_MAX];
    
     fd = openat(dirfd, ".", O_TMPFILE|O_RDWR, S_IRUSR|S_IWUSR);
@@ -47,18 +47,18 @@ ssize_t InitFile(int dirfd, const char *file, const char *buf, size_t count)
        perror("Cannot get temporary filedescritor");
        return(fd);
     }
-    res = FullWrite(fd, buf, count);
-    if (res < 0) {
+    written = FullWrite(fd, buf, size);
+    if (written < 0) {
        perror("error writing on tmp file");
        return(res);
     }
     snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd);
     res = linkat(AT_FDCWD, path, dirfd, file, AT_SYMLINK_FOLLOW);
     if (res < 0) {
-       perror("error writing on tmp file");
+       perror("error linking the file");
        return(res);
     } else {
-       return 0;
+       return written;
     }
 }
 
index 12dc028..afd6073 100644 (file)
@@ -99,6 +99,10 @@ int main(int argc, char *argv[])
     int newfd, res, count;
     count = strlen(argv[optind+1]);
     newfd = open(dir, O_PATH|O_RDWR);
+    if (newfd < 0) {
+       perror("Cannot open destination dir");
+       exit(1);
+    }
     res = InitFile(newfd, file, argv[optind+1], count);
     free(path);
     return 0;
@@ -107,8 +111,7 @@ int main(int argc, char *argv[])
  * routine to print usage info and exit
  */
 void usage(void) {
-    printf("Program test_initfile : test initfile  \n");
-    printf("Create a link to a tempfile or a link to -f indicated file");
+    printf("Program test_initfile : create a file with initial content  \n");
     printf("Usage:\n");
     printf("  test_initfile [-h] pathname 'test to be written on pathname' \n");
     printf("  -h          print this help\n");