RFC: futimens(2) and utimensat(2)
Bruce Evans
brde at optusnet.com.au
Wed Feb 29 13:08:43 UTC 2012
On Wed, 29 Feb 2012, Sergey Kandaurov wrote:
> On 29 February 2012 10:40, Xin Li <delphij at delphij.net> wrote:
>>
>> These are required by IEEE Std 1003.1-2008. Patchset at:
>>
>> http://people.freebsd.org/~delphij/for_review/utimens.diff
I didn't look at this because it wasn't in the mail :-).
> This is the older version last time discussed with jilles.
> It misses man page update and compat32 parts (both were
> done since then except missing ERROR section in utimes(2).
> e.g. my compat32 version is just as yours :)).
> I started to commit my version (you can see r227447) but
> failed due to missing ERROR section, my lack of english to
> rewrite utimes(2) man page, and too complicated and wrong
> ERROR section in the existing utimes(2).
>
> http://plukky.net/~pluknet/patches/utimes.2008.3.diff
>
> It is pretty similar to your except I done getutimens() a bit different.
> I had to introduce such complication to pass all tests.
> Take note on private flags UTIMENS_NULL and UTIMENS_EXIT.
>
> Index: sys/kern/vfs_syscalls.c
> ===================================================================
> --- sys/kern/vfs_syscalls.c (revision 220831)
> +++ sys/kern/vfs_syscalls.c (working copy)
> ...
> static int
> +getutimens(usrtsp, tspseg, tsp, retflags)
> + const struct timespec *usrtsp;
> + enum uio_seg tspseg;
> + struct timespec *tsp;
> + int *retflags;
Should probably not use K&R function definitions in new code.
> +{
> + int error;
> + struct timespec tsnow;
Structs should be sorted before scalars (and pointers).
> +
> + vfs_timestamp(&tsnow);
Not used in all paths.
> + *retflags = 0;
Not used in all paths?
> + if (usrtsp == NULL) {
> + tsp[0] = tsnow;
> + tsp[1] = tsnow;
> + *retflags |= UTIMENS_NULL;
> + return (0);
> + }
> + if (tspseg == UIO_SYSSPACE) {
> + tsp[0] = usrtsp[0];
> + tsp[1] = usrtsp[1];
> + } else if ((error = copyin(usrtsp, tsp, sizeof(*tsp) * 2)) != 0)
> + return (error);
Indentation.
> +
Extra blank line. Many more of these below.
> + if (tsp[0].tv_nsec == UTIME_OMIT && tsp[1].tv_nsec == UTIME_OMIT)
> + *retflags |= UTIMENS_EXIT;
> + if (tsp[0].tv_nsec == UTIME_NOW && tsp[1].tv_nsec == UTIME_NOW)
> + *retflags |= UTIMENS_NULL;
> +
> + if (tsp[0].tv_nsec == UTIME_OMIT)
> + tsp[0].tv_sec = VNOVAL;
tsp[0].tv_nsec is not initialized (except it is UTIME_OMIT, which might
be the same as VNOVAL). The patch seems to be missing the header part
that defines UTIME_OMIT). Most setattr vnops are sloppy about checking
both tv_sec and tv_nsec, but VATTR_NULL() sets both to VNOVAL for
setattrs that don't request a time change. More care is actually
required in the opposite direction -- getattr defaults va_birthtime.
tv_sec.tv_nsec to -1.0, so that when a getattr doesn't understand
birthime it comes back back unchanged as -1.0 which gives the error
value (time_t)-1. All attributes for getattr should be defaulted like
this so that all file systems don't have to know about them, but only
va_birthtime, va_fsid and va_rdev are (all the others default to stack
garbage).
> + else if (tsp[0].tv_nsec == UTIME_NOW)
> + tsp[0] = tsnow;
> + else if (tsp[0].tv_nsec < 0 || tsp[0].tv_nsec >= 1000000000L)
> + return (EINVAL);
> +
> + if (tsp[1].tv_nsec == UTIME_OMIT)
> + tsp[1].tv_sec = VNOVAL;
> + else if (tsp[1].tv_nsec == UTIME_NOW)
> + tsp[1] = tsnow;
> + else if (tsp[1].tv_nsec < 0 || tsp[1].tv_nsec >= 1000000000L)
> + return (EINVAL);
Is it possible to extend this API to support birthtimes (and with more
security control, ctimes)? Encoding more in tv_nsec should do it.
Certain magic values in tsp[1].tv_nsec would indicate that there are
more than 2 entries in tsp[]. An extra copyin is needed to read the
extra entries (after reading tsp[1] to see if there are more). Better
add this before the ABI solidifies.
This would have worked for utimes() too, with with magic in tsp[1].tv_usec,
but this seems unnecessary now.
Bruce
More information about the freebsd-arch
mailing list