77#include <sys/types.h>
88#include <ctype.h>
99#include "file.h"
10+ #include "line.h"
1011#include "const.h"
1112#include "status.h"
1213#include "error.h"
2122static struct file g_infile ;
2223static struct file g_outfile ;
2324static struct file g_tmpfile ;
25+ static struct file g_dupfile ;
2426
2527
2628/** Ensure that infile and outfile don't point to the same
2729 * file on filesystem, by comparing device & inode.
2830 */
29- static void check_files (const char * infile_name , const char * outfile_name )
31+ static void check_files_difer (
32+ const char * infile_name ,
33+ const char * outfile_name )
3034{
3135 struct stat infile_info ;
3236 struct stat outfile_info ;
@@ -62,6 +66,7 @@ static void close_all(void)
6266{
6367 close_file (& g_infile );
6468 close_file (& g_outfile );
69+ close_file (& g_dupfile );
6570
6671 if (FILE_ISSET (& g_tmpfile ))
6772 {
@@ -175,19 +180,24 @@ static void copy_file(int dst_fd, int src_fd, bool send_status)
175180 * - Registers cleanup functions with atexit()
176181 * - returned file has `addr` attribute mapped in memory
177182 */
178- void init_file ( const char * infile_name , const char * outfile_name )
183+ void init_files ( void )
179184{
180185 struct file * file ;
181186
182- check_files ( infile_name , outfile_name );
187+ check_files_difer ( g_conf . infile_name , g_conf . outfile_name );
183188
184189 memset (& g_infile , -1 , sizeof (g_infile ));
185- memset (& g_outfile , -1 , sizeof (g_infile ));
186- memset (& g_tmpfile , -1 , sizeof (g_infile ));
190+ memset (& g_outfile , -1 , sizeof (g_outfile ));
191+ memset (& g_tmpfile , -1 , sizeof (g_tmpfile ));
192+ memset (& g_dupfile , -1 , sizeof (g_dupfile ));
187193
188194 atexit (close_all );
189- open_file (& g_infile , infile_name , O_RDONLY );
190- open_file (& g_outfile , outfile_name , O_TRUNC | O_CREAT | O_RDWR );
195+ open_file (& g_infile , g_conf .infile_name , O_RDONLY );
196+ open_file (& g_outfile , g_conf .outfile_name , O_TRUNC | O_CREAT | O_RDWR );
197+
198+ if (g_conf .dupfile_name != NULL ) {
199+ open_file (& g_dupfile , g_conf .dupfile_name , O_TRUNC | O_CREAT | O_RDWR );
200+ }
191201
192202 if (S_ISREG (g_outfile .info .st_mode ))
193203 file = & g_outfile ;
@@ -230,7 +240,7 @@ void init_file(const char *infile_name, const char *outfile_name)
230240 * - truncate file with new size.
231241 * - Call close_all() for cleanout.
232242 */
233- void destroy_file (void )
243+ void cleanup_files (void )
234244{
235245 struct file * file ;
236246
@@ -252,3 +262,19 @@ void destroy_file(void)
252262
253263 close_all ();
254264}
265+
266+ /** Write a duplicate to dupfile_name (must be atomic)
267+ */
268+ void log_duplicate (char * line_ptr , int line_sz )
269+ {
270+ ssize_t n ;
271+ char buf [MAX_MAX_LINE_SIZE + 1 ];
272+ memcpy (buf , line_ptr , line_sz );
273+ buf [line_sz ] = '\n' ;
274+ do {
275+ n = write (g_dupfile .fd , buf , line_sz + 1 );
276+ } while (n == -1 && errno == EINTR );
277+ if (n == -1 ) {
278+ error ("log_duplicate() -> write(): %s" , ERRNO );
279+ }
280+ }
0 commit comments