1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-20 11:11:24 +00:00

Normalize the tv_usec part of the utimes(2) arguments to ensure

that a file's atime and mtime are only set to correct fractional
second values (0-999999000ns with the current interface).
Prior to this change users could create files with values outside
that range.  Moreover, on 32-bit machines tv_usec offsets larger than
4.3s would result in an unnormalized AND wrong timestamp value,
due to overflow.

MFC after:	1 week
This commit is contained in:
Diomidis Spinellis 2006-01-03 21:58:21 +00:00
parent 2f7a934c4f
commit 51339e8593
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=154003
2 changed files with 48 additions and 6 deletions

View File

@ -2712,6 +2712,25 @@ fchown(td, uap)
return (error);
}
/*
* Normalize the tv_usec value of t within the allowed range.
*/
static struct timeval
normalize_timeval(const struct timeval *t)
{
struct timeval n;
if (t->tv_usec >= 0 && t->tv_usec < 1000000)
return *t;
n.tv_sec = t->tv_sec + t->tv_usec / 1000000;
n.tv_usec = t->tv_usec % 1000000;
if (n.tv_usec < 0) {
n.tv_sec--;
n.tv_usec += 1000000;
}
return n;
}
/*
* Common implementation code for utimes(), lutimes(), and futimes().
*/
@ -2721,7 +2740,7 @@ getutimes(usrtvp, tvpseg, tsp)
enum uio_seg tvpseg;
struct timespec *tsp;
{
struct timeval tv[2];
struct timeval tv[2], tvn;
const struct timeval *tvp;
int error;
@ -2738,8 +2757,10 @@ getutimes(usrtvp, tvpseg, tsp)
tvp = tv;
}
TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
tvn = normalize_timeval(&tvp[0]);
TIMEVAL_TO_TIMESPEC(&tvn, &tsp[0]);
tvn = normalize_timeval(&tvp[1]);
TIMEVAL_TO_TIMESPEC(&tvn, &tsp[1]);
}
return (0);
}

View File

@ -2712,6 +2712,25 @@ fchown(td, uap)
return (error);
}
/*
* Normalize the tv_usec value of t within the allowed range.
*/
static struct timeval
normalize_timeval(const struct timeval *t)
{
struct timeval n;
if (t->tv_usec >= 0 && t->tv_usec < 1000000)
return *t;
n.tv_sec = t->tv_sec + t->tv_usec / 1000000;
n.tv_usec = t->tv_usec % 1000000;
if (n.tv_usec < 0) {
n.tv_sec--;
n.tv_usec += 1000000;
}
return n;
}
/*
* Common implementation code for utimes(), lutimes(), and futimes().
*/
@ -2721,7 +2740,7 @@ getutimes(usrtvp, tvpseg, tsp)
enum uio_seg tvpseg;
struct timespec *tsp;
{
struct timeval tv[2];
struct timeval tv[2], tvn;
const struct timeval *tvp;
int error;
@ -2738,8 +2757,10 @@ getutimes(usrtvp, tvpseg, tsp)
tvp = tv;
}
TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]);
TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]);
tvn = normalize_timeval(&tvp[0]);
TIMEVAL_TO_TIMESPEC(&tvn, &tsp[0]);
tvn = normalize_timeval(&tvp[1]);
TIMEVAL_TO_TIMESPEC(&tvn, &tsp[1]);
}
return (0);
}