From owner-freebsd-fs Tue Dec 19 8: 3:56 2000 From owner-freebsd-fs@FreeBSD.ORG Tue Dec 19 08:03:53 2000 Return-Path: Delivered-To: freebsd-fs@freebsd.org Received: from mailman.zeta.org.au (mailman.zeta.org.au [203.26.10.16]) by hub.freebsd.org (Postfix) with ESMTP id 80DEF37B404; Tue, 19 Dec 2000 08:03:50 -0800 (PST) Received: from bde.zeta.org.au (bde.zeta.org.au [203.2.228.102]) by mailman.zeta.org.au (8.9.3/8.8.7) with ESMTP id DAA08214; Wed, 20 Dec 2000 03:03:33 +1100 Date: Wed, 20 Dec 2000 03:04:00 +1100 (EST) From: Bruce Evans X-Sender: bde@besplex.bde.org To: Ian Dowse Cc: julian@FreeBSD.ORG, mckusick@mckusick.com, freebsd-fs@FreeBSD.ORG Subject: Re: creat(2) not setting mtime on existing 0-length file In-Reply-To: <200012172252.aa18426@salmon.maths.tcd.ie> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-fs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org 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