From 2160777d2f26a7e00c3dc003bf52bf9d40d885c7 Mon Sep 17 00:00:00 2001 From: liljencrantz Date: Sat, 27 Oct 2007 04:42:32 +1000 Subject: [PATCH] Implement non-clobbering file io. Use the >? operator for this for now. darcs-hash:20071026184232-75c98-11edcbc7548c8ad3a2d4b648cb7ae18067569f02.gz --- exec.c | 34 ++++++++++++++++++++++++++-------- highlight.c | 12 +++++++++++- parser.c | 9 +++++++++ tokenizer.c | 6 ++++++ tokenizer.h | 1 + 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/exec.c b/exec.c index 660d5dab1..dbda6cbb0 100644 --- a/exec.c +++ b/exec.c @@ -52,10 +52,17 @@ file descriptor redirection error message */ #define FD_ERROR _( L"An error occurred while redirecting file descriptor %d" ) + /** file redirection error message */ #define FILE_ERROR _( L"An error occurred while redirecting file '%ls'" ) + +/** + file redirection clobbering error message +*/ +#define NOCLOB_ERROR _( L"The file '%ls' already exists" ) + /** fork error message */ @@ -113,10 +120,10 @@ void exec_close( int fd ) if( n == fd ) { al_set_long( open_fds, - i, - al_get_long( open_fds, al_get_count( open_fds ) -1 ) ); + i, + al_get_long( open_fds, al_get_count( open_fds ) -1 ) ); al_truncate( open_fds, - al_get_count( open_fds ) -1 ); + al_get_count( open_fds ) -1 ); break; } } @@ -288,13 +295,24 @@ static int handle_child_io( io_data_t *io ) case IO_FILE: { if( (tmp=wopen( io->param1.filename, - io->param2.flags, OPEN_MASK ) )==-1 ) + io->param2.flags, OPEN_MASK ) )==-1 ) { - debug( 1, - FILE_ERROR, - io->param1.filename ); + if( ( io->param2.flags & O_EXCL ) && + ( errno ==EEXIST ) ) + { + debug( 1, + NOCLOB_ERROR, + io->param1.filename ); + } + else + { + debug( 1, + FILE_ERROR, + io->param1.filename ); + + wperror( L"open" ); + } - wperror( L"open" ); return -1; } else if( tmp != io->fd) diff --git a/highlight.c b/highlight.c index 603d75b90..8a5f75120 100644 --- a/highlight.c +++ b/highlight.c @@ -757,6 +757,7 @@ void highlight_shell( wchar_t * buff, break; } + case TOK_REDIRECT_NOCLOB: case TOK_REDIRECT_OUT: case TOK_REDIRECT_IN: case TOK_REDIRECT_APPEND: @@ -825,7 +826,7 @@ void highlight_shell( wchar_t * buff, if it exists. */ if( last_type == TOK_REDIRECT_IN || - last_type == TOK_REDIRECT_APPEND ) + last_type == TOK_REDIRECT_APPEND ) { if( wstat( target, &buff ) == -1 ) { @@ -834,6 +835,15 @@ void highlight_shell( wchar_t * buff, al_push( error, wcsdupcat( L"File \'", target, L"\' does not exist" ) ); } } + if( last_type == TOK_REDIRECT_NOCLOB ) + { + if( wstat( target, &buff ) != -1 ) + { + color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR; + if( error ) + al_push( error, wcsdupcat( L"File \'", target, L"\' exists" ) ); + } + } } break; } diff --git a/parser.c b/parser.c index a699219e3..916dd79b7 100644 --- a/parser.c +++ b/parser.c @@ -1462,6 +1462,7 @@ static void parse_job_argument_list( process_t *p, case TOK_REDIRECT_IN: case TOK_REDIRECT_APPEND: case TOK_REDIRECT_FD: + case TOK_REDIRECT_NOCLOB: { int type = tok_last_type( tok ); io_data_t *new_io; @@ -1557,6 +1558,12 @@ static void parse_job_argument_list( process_t *p, new_io->param1.filename = target; break; + case TOK_REDIRECT_NOCLOB: + new_io->io_mode = IO_FILE; + new_io->param2.flags = O_CREAT | O_EXCL | O_WRONLY; + new_io->param1.filename = target; + break; + case TOK_REDIRECT_IN: new_io->io_mode = IO_FILE; new_io->param2.flags = O_RDONLY; @@ -2121,6 +2128,7 @@ static int parse_job( process_t *p, break; case TOK_REDIRECT_OUT: + case TOK_REDIRECT_NOCLOB: case TOK_REDIRECT_APPEND: case TOK_REDIRECT_IN: case TOK_REDIRECT_FD: @@ -3324,6 +3332,7 @@ int parser_test( const wchar_t * buff, case TOK_REDIRECT_IN: case TOK_REDIRECT_APPEND: case TOK_REDIRECT_FD: + case TOK_REDIRECT_NOCLOB: { if( !had_cmd ) { diff --git a/tokenizer.c b/tokenizer.c index 0551bb176..edefc070c 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -69,6 +69,7 @@ static const wchar_t *tok_desc[] = N_( L"Append output to file" ), N_( L"Redirect input to file" ), N_( L"Redirect to file descriptor" ), + N_( L"Redirect output to file if file does not exist" ), N_( L"Run job in background" ), N_( L"Comment" ) } @@ -473,6 +474,11 @@ static void read_redirect( tokenizer *tok, int fd ) tok->buff++; tok->last_type = TOK_REDIRECT_FD; } + else if( *tok->buff == L'?' ) + { + tok->buff++; + tok->last_type = TOK_REDIRECT_NOCLOB; + } else { tok->last_type = TOK_REDIRECT_OUT + mode; diff --git a/tokenizer.h b/tokenizer.h index bced30e5e..3954cc481 100644 --- a/tokenizer.h +++ b/tokenizer.h @@ -26,6 +26,7 @@ enum token_type TOK_REDIRECT_APPEND,/**< redirection append token */ TOK_REDIRECT_IN,/**< input redirection token */ TOK_REDIRECT_FD,/**< redirection to new fd token */ + TOK_REDIRECT_NOCLOB, /**