diff options
author | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2008-12-10 16:39:54 +0000 |
---|---|---|
committer | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2008-12-10 16:39:54 +0000 |
commit | 0f1e140e796f55cf5f07d39707f3e88d335f4ff1 (patch) | |
tree | e44d49e4cb8da17389d4ffa57e784f7ee91d3381 /libc/login/utmp_file.c | |
parent | 8acd6170c246b159d26f05d85fa256746391d3d7 (diff) | |
download | eglibc2-0f1e140e796f55cf5f07d39707f3e88d335f4ff1.tar.gz |
Merge changes between r7357 and r7510 from /fsf/trunk.
git-svn-id: svn://svn.eglibc.org/trunk@7511 7b3dc134-2b1b-0410-93df-9e9f96275f8d
Diffstat (limited to 'libc/login/utmp_file.c')
-rw-r--r-- | libc/login/utmp_file.c | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/libc/login/utmp_file.c b/libc/login/utmp_file.c index 9033f72a4..fb5840242 100644 --- a/libc/login/utmp_file.c +++ b/libc/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 && ( |