From nobody@FreeBSD.org  Sat Apr 28 19:13:15 2007
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 0F58A16A401
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 28 Apr 2007 19:13:15 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [69.147.83.33])
	by mx1.freebsd.org (Postfix) with ESMTP id EAB1113C46E
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 28 Apr 2007 19:13:14 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.13.1/8.13.1) with ESMTP id l3SJDESU048397
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 28 Apr 2007 19:13:14 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.13.1/8.13.1/Submit) id l3SJ8Dxl047438;
	Sat, 28 Apr 2007 19:08:13 GMT
	(envelope-from nobody)
Message-Id: <200704281908.l3SJ8Dxl047438@www.freebsd.org>
Date: Sat, 28 Apr 2007 19:08:13 GMT
From: Jan Schaumann<jschauma@netmeister.org>
To: freebsd-gnats-submit@FreeBSD.org
Subject: touch(1)ing a directory and failing yields return code 0
X-Send-Pr-Version: www-3.0

>Number:         112211
>Category:       misc
>Synopsis:       touch(1)ing a directory and failing yields return code 0
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Apr 28 19:20:03 GMT 2007
>Closed-Date:    Sat Apr 28 20:38:24 GMT 2007
>Last-Modified:  Sat Apr 28 20:40:09 GMT 2007
>Originator:     Jan Schaumann
>Release:        
>Organization:
>Environment:
>Description:
When using touch(1) on a directory that I can't update the timestamp on (say, if the filesystem is mounted read-only), it will return 0 as the return value, even though it failed.

The reason this happens is in touch.c#225:

    /* Try reading/writing. */
    if (!S_ISLNK(sb.st_mode) && !S_ISDIR(sb.st_mode) &&
        rw(*argv, &sb, fflag))
            rval = 1;
    else
            warn("%s", *argv);

At this point, it tries to update the timestamp using utimes(2), which
failed, so it would continue to try to update it by reading and writing
the file.

However, since the file in question is a directory, it doesn't try this
and simply warns instead of setting the return value to 1.

>How-To-Repeat:
$ mkdir foo
$ touch foo/bar
$ mount -u -o ro /
$ touch foo/bar
touch: foo/bar: Read-only file system
$ echo $?
1
$ touch foo
touch: foo: Read-only file system
$ echo $?
0
$


>Fix:
See NetBSD's touch(1):

                /* Try reading/writing. */
                if (!S_ISLNK(sb.st_mode) && rw(*argv, &sb, fflag))
                        rval = 1;


This still is slightly suboptimal, since the error message will be

$ touch foo
touch: foo: Is a directory
$ echo $?
1
$ 

But that's better than returning 0.
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: linimon 
State-Changed-When: Sat Apr 28 20:38:00 UTC 2007 
State-Changed-Why:  
Duplicate of bin/112213.

http://www.freebsd.org/cgi/query-pr.cgi?pr=112211 
>Unformatted:
