aboutsummaryrefslogtreecommitdiff
path: root/login
diff options
context:
space:
mode:
authorMiles Bader <miles@gnu.org>1996-07-01 19:19:08 +0000
committerMiles Bader <miles@gnu.org>1996-07-01 19:19:08 +0000
commite81bd562d57209c6c9297962046716ace78bfb30 (patch)
tree4586df9a058706a9fab0bd3e6a3d282cf46a6807 /login
parent4bbb963eb40bc42a509d20358cefdbff7fb0889a (diff)
downloadglibc-e81bd562d57209c6c9297962046716ace78bfb30.zip
glibc-e81bd562d57209c6c9297962046716ace78bfb30.tar.gz
glibc-e81bd562d57209c6c9297962046716ace78bfb30.tar.bz2
(pututline_r): If not located after any entry don't use UTMP_DATA->ubuf, and seek to the end before adding. Lock the file before stating.
Diffstat (limited to 'login')
-rw-r--r--login/pututline_r.c60
1 files changed, 35 insertions, 25 deletions
diff --git a/login/pututline_r.c b/login/pututline_r.c
index 62fc83b..4fffbb7 100644
--- a/login/pututline_r.c
+++ b/login/pututline_r.c
@@ -60,7 +60,8 @@ pututline_r (const struct utmp *id, struct utmp_data *utmp_data)
#if _HAVE_UT_TYPE - 0
/* Seek position to write. */
- if (utmp_data->ubuf.ut_type != id->ut_type)
+ if (utmp_data->loc_utmp >= sizeof (utmp)
+ && utmp_data->ubuf.ut_type != id->ut_type)
{
/* We must not overwrite the data in UTMP_DATA. */
struct utmp_data *data_tmp = alloca (sizeof (*data_tmp));
@@ -82,16 +83,6 @@ pututline_r (const struct utmp *id, struct utmp_data *utmp_data)
}
#endif
- /* Find out how large the file is. */
- if (fstat (utmp_data->ut_fd, &st) < 0)
- return -1;
-
- /* Position file correctly. */
- if (utmp_data->loc_utmp <= st.st_size
- && lseek (utmp_data->ut_fd, utmp_data->loc_utmp - sizeof (struct utmp),
- SEEK_SET) < 0)
- return -1;
-
/* Try to lock the file. */
if (flock (utmp_data->ut_fd, LOCK_EX | LOCK_NB) < 0 && errno != ENOSYS)
{
@@ -102,20 +93,39 @@ pututline_r (const struct utmp *id, struct utmp_data *utmp_data)
(void) flock (utmp_data->ut_fd, LOCK_EX | LOCK_NB);
}
- /* Write the new data. */
- if (write (utmp_data->ut_fd, id, sizeof (struct utmp))
- != sizeof (struct utmp))
- {
- /* If we appended a new record this is only partially written.
- Remove it. */
- if (utmp_data->loc_utmp > st.st_size)
- {
- (void) ftruncate (utmp_data->ut_fd, st.st_size);
- utmp_data->loc_utmp = st.st_size;
- }
-
- result = -1;
- }
+ /* Find out how large the file is. */
+ result = fstat (utmp_data->ut_fd, &st);
+
+ if (result == 0)
+ /* Position file correctly. */
+ if (utmp_data->loc_utmp < sizeof (struct utmp))
+ /* Not located at any valid entry. Add at the end. */
+ {
+ result = lseek (utmp_data->ut_fd, 0L, SEEK_END);
+ if (result == 0)
+ /* Where we'll be if the write succeeds. */
+ utmp_data->loc_utmp = st.st_size + sizeof (struct utmp);
+ }
+ else if (utmp_data->loc_utmp <= st.st_size)
+ result =
+ lseek (utmp_data->ut_fd, utmp_data->loc_utmp - sizeof (struct utmp),
+ SEEK_SET);
+
+ if (result == 0)
+ /* Write the new data. */
+ if (write (utmp_data->ut_fd, id, sizeof (struct utmp))
+ != sizeof (struct utmp))
+ {
+ /* If we appended a new record this is only partially written.
+ Remove it. */
+ if (utmp_data->loc_utmp > st.st_size)
+ {
+ (void) ftruncate (utmp_data->ut_fd, st.st_size);
+ utmp_data->loc_utmp = st.st_size;
+ }
+
+ result = -1;
+ }
/* And unlock the file. */
(void) flock (utmp_data->ut_fd, LOCK_UN);