Skip site navigation (1)Skip section navigation (2)
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>