From 37a6a271bf72e247047f1e4e9cf457e895d57dce Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 30 Nov 2008 06:56:27 +0000 Subject: * login/utmp_file.c (file_writable): New variable. (setutent_file): Don't try to open file for writing. (pututline_file): Before writing, make descriptor writable if necessary. --- login/utmp_file.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 9 deletions(-) (limited to 'login') diff --git a/login/utmp_file.c b/login/utmp_file.c index 9033f72a4e..fb5840242e 100644 --- a/login/utmp_file.c +++ b/login/utmp_file.c @@ -36,6 +36,7 @@ /* Descriptor for the file and position. */ static int file_fd = -1; +static bool file_writable; static off64_t file_offset; /* Cache for the last read entry. */ @@ -138,7 +139,6 @@ setutent_file (void) if (file_fd < 0) { const char *file_name; - int result; file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name); @@ -147,14 +147,10 @@ setutent_file (void) #else # define O_flags O_LARGEFILE #endif - file_fd = open_not_cancel_2 (file_name, O_RDWR | O_flags); + file_writable = false; + file_fd = open_not_cancel_2 (file_name, O_RDONLY | O_flags); if (file_fd == -1) - { - /* Hhm, read-write access did not work. Try read-only. */ - file_fd = open_not_cancel_2 (file_name, O_RDONLY | O_flags); - if (file_fd == -1) - return 0; - } + return 0; #ifndef __ASSUME_O_CLOEXEC # ifdef O_CLOEXEC @@ -162,7 +158,7 @@ setutent_file (void) # endif { /* We have to make sure the file is `closed on exec'. */ - result = fcntl_not_cancel (file_fd, F_GETFD, 0); + int result = fcntl_not_cancel (file_fd, F_GETFD, 0); if (result >= 0) { # ifdef O_CLOEXEC @@ -404,6 +400,52 @@ pututline_file (const struct utmp *data) assert (file_fd >= 0); + if (! file_writable) + { + /* We must make the file descriptor writable before going on. */ + const char *file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name); + + int new_fd = open_not_cancel_2 (file_name, O_RDWR | O_flags); + if (new_fd == -1) + return NULL; + +#ifndef __ASSUME_O_CLOEXEC +# ifdef O_CLOEXEC + if (__have_o_cloexec <= 0) +# endif + { + /* We have to make sure the file is `closed on exec'. */ + int result = fcntl_not_cancel (file_fd, F_GETFD, 0); + if (result >= 0) + { +# ifdef O_CLOEXEC + if (__have_o_cloexec == 0) + __have_o_cloexec = (result & FD_CLOEXEC) ? 1 : -1; + + if (__have_o_cloexec < 0) +# endif + result = fcntl_not_cancel (file_fd, F_SETFD, + result | FD_CLOEXEC); + } + + if (result == -1) + { + close_not_cancel_no_status (file_fd); + return NULL; + } + } +#endif + + if (__lseek64 (new_fd, __lseek64 (file_fd, 0, SEEK_CUR), SEEK_SET) == -1 + || dup2 (new_fd, file_fd) < 0) + { + close_not_cancel_no_status (new_fd); + return NULL; + } + close_not_cancel_no_status (new_fd); + file_writable = true; + } + /* Find the correct place to insert the data. */ if (file_offset > 0 && ( -- cgit v1.2.3