Date: Wed, 20 Dec 2000 03:04:00 +1100 (EST) From: Bruce Evans <bde@zeta.org.au> To: Ian Dowse <iedowse@maths.tcd.ie> Cc: julian@FreeBSD.ORG, mckusick@mckusick.com, freebsd-fs@FreeBSD.ORG Subject: Re: creat(2) not setting mtime on existing 0-length file Message-ID: <Pine.BSF.4.21.0012200226530.289-100000@besplex.bde.org> In-Reply-To: <200012172252.aa18426@salmon.maths.tcd.ie>
next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 17 Dec 2000, Ian Dowse wrote: > I was trying to figure out why a very old piece of code we use here > had not been working as expected for ages. The code stores the time > of certain events in zero-length timestamp files using something like: > > close(creat(filename, 0666)); > > This is supposed to set the last-modified time on the file to the > current time, but I noticed that it has not been doing so for over > a year. This works as expected on FreeBSD 2.2.7, and on other > systems I tried, but FreeBSD 3.0 or later does not modify the mtime > if the file already exists and has zero size. > > I traced the problem back to r1.36 of src/sys/ufs/ffs/ffs_inode.c, > which includes the following changes to ffs_truncate(): > > @@ -171,6 +176,8 @@ > off_t osize; > > oip = VTOI(ovp); > + if (oip->i_size == length) > + return (0); > fs = oip->i_fs; > if (length < 0) > return (EINVAL); I fixed this a couple of years ago locally after NIST PCTS found the bug, but never got around to committing the fix. Some standards-related points: - creat(2) is implemented as open(..., ... O_TRUNC). - open(..., ... O_TRUNC) implemented by calling ffs_ftruncate() (via VOP_SETATTR()) with length = 0. - POSIX.1-1990 specifies that open(2) with the O_TRUNC flag set shall mark the times for update upon successful completion. - the Single Unix Spec (version 2, Copyright 1997) specifies that ftruncate(2) shall mark the times for update on successful completion if the file size changed. - POSIX.1-1996 specifies that ftruncate(2) shall mark the times for update on successful completion. Summary: the change gives bug for bug compatibility with the Single Unix Spec for ftruncate(), but breaks the POSIX spec for open() and ftruncate(). > @@ -197,6 +204,31 @@ > > A few lines down from this point is the fragment > > if (oip->i_size == length) { > oip->i_flag |= IN_CHANGE | IN_UPDATE; > return (UFS_UPDATE(ovp, 0)); > } > > so I think it is obvious that the code is not working as expected > since the condition here will never be true. The commit log message > gives no hints except that the patches were obtained from the > Whistle development tree. > > So Julian or Kirk, do you have any ideas as to why this change > might have been made in r1.36, or if this behaviour is desirable > or correct? A quick glance suggests that the problem can be resolved > by simply removing the offending lines as in the patch below. I originally thought that the change was to fix ftruncate(), since doing nothing for the nothing-to-do case is reasonable and is permitted by the Single Unix Spec, but that the implementation was wrong since it broke open(). Bruce To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-fs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0012200226530.289-100000>