[net.bugs.usg] utime misusage

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (11/28/84)

The following UNIX System V Release 2.0 commands have erroneous use
of utime(2) in their source code.  On some systems, this can cause
files to have their dates set to funny values (like 31-Dec-1969).

	cpio	file	pack	tar	unpack

The fix is obvious; just follow directions given in UTIME(2).

Recipients of the BRL UNIX System V emulation for 4.2BSD should fix
this and install corrected versions of these commands.

gam@amdahl.UUCP (Gordon A. Moffett) (11/29/84)

> = Doug Gwyn
>
> The following UNIX System V Release 2.0 commands have erroneous use
> of utime(2) in their source code.  On some systems, this can cause
> files to have their dates set to funny values (like 31-Dec-1969).
> 
> 	cpio	file	pack	tar	unpack

The instances you refer to are of the form:

        char *filename;
        struct stat st;
        ...
        utime(filename, &st.st_atime);

Despite its rather inelegant appearance, why should this fail?

The second argument of utime(2) is expected to be the address of
this kind of struct:

        struct utimbuf { time_t actime, modtime; } ubuf;

Using the address of the st_atime field of a stat(2) struct would
provide these values correctly, because the word following st_atime in
the structure is st_mtime (the mod. time).  Here's a picture:

 &st.st_atime -----> st_atime      &ubuf -----> actime
                     st_mtime                   modtime

So is this really a bug, or is your C compiler acting strangely?
-- 
Gordon A. Moffett		...!{ihnp4,hplabs,amd,sun}!amdahl!gam

37 22'50" N / 122 59'12" W	[ This is just me talking. ]

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (11/30/84)

> Using the address of the st_atime field of a stat(2) struct would
> provide these values correctly, because the word following st_atime in
> the structure is st_mtime (the mod. time).

Wrong.  Not only is this not promised, but on 4.2BSD it is not true.

guy@rlgvax.UUCP (Guy Harris) (11/30/84)

> The instances you refer to are of the form:
> 
>         char *filename;
>         struct stat st;
>         ...
>         utime(filename, &st.st_atime);
> 
> Despite its rather inelegant appearance, why should this fail?
> 
> The second argument of utime(2) is expected to be the address of
> this kind of struct:
> 
>         struct utimbuf { time_t actime, modtime; } ubuf;
> 
> Using the address of the st_atime field of a stat(2) struct would
> provide these values correctly, because the word following st_atime in
> the structure is st_mtime (the mod. time).

WRONG!  FALSE!  INCORRECT!  Show me where in STAT(2) it states that those
fields are contiguous.  The V7 manual did, but the S3 and S5 manuals
*go out of their way* to state that they say *nothing* about what the
"stat" structure looks like.  They give the fields in a different order
than they appear in the structure, and say before it "The contents of
the structure pointed to by 'buf' *include* the following members:".
Clearly, they did *not* want to commit to the precise shape of the structure
forever, world without end, amen.  The 4.2BSD manual is similar, for a
very good reason; they *did* change the structure around, adding several
new fields, including reserved fields for giving access/modification/change
time down to microsecond "resolution" (probably not the correct word, as
the clock may not give microsecond resolution, but the value is in microseconds
even if the minimum step is greater than 1).  These were stuck, for perfectly
good reasons, after their corresponding 1-second-resolution times.  As
such, the word following "st_atime" is *not* "st_mtime".

The S5 emulation under 4.2BSD doesn't bother redoing the "stat" structure,
because there's simply no point in it.  It would require searching a separate
include directory for "stat.h", and would preclude the standard I/O package
from using the blocksize of the filesystem on which a file resides as the
buffer size for that file (which makes things run faster - I don't know if
the S5 standard I/O library in Doug's emulation does this, but the one we
run here, and will run on the Power 6/32 (also known as the Sperry 7000/40
or some such) and the Power 5/30, does this).

Code written the wrong way won't pass "lint" (the S5R2 "lint" library
says the second argument to "utime" is a pointer to a structure containing
two elements of type "time_t"); why not silence "lint" and insure that your
program will run on systems that don't use the V7 "stat" structure at the
same time?

The programmers who wrote that code used implicit knowledge about the internals
of a UNIX data structure that they had no business using, if they were working
from the S3/S5 manuals (they may have been working from manuals which did give
the format of the stat structure, and which gave the second argument to "utime"
as a pointer to an array of two times, both of which the V7 manual did).  Using
implicit knowledge about a system is a great way to get royally screwed when a
new version comes out.  That's why the Berkeley "directory library" is
also a good idea; it doesn't depend on the implementation details of
directories, and makes it easier to move your program to systems (like 4.2BSD,
or VMS, or...) that don't handle directories in the same way (they may not
have the same directory format, or they may not even permit you to open
a directory like a plain file and read it!).  Versions exist both for the
V6/V7/4.1BSD/S3/S5 directory structure and for the 4.2BSD directory structure.

	Guy Harris
	{seismo,ihnp4,allegra}!rlgvax!guy

henry@utzoo.UUCP (Henry Spencer) (11/30/84)

> The instances you refer to are of the form:
> 
>         char *filename;
>         struct stat st;
>         ...
>         utime(filename, &st.st_atime);
> 
> Despite its rather inelegant appearance, why should this fail?
> 
> The second argument of utime(2) is expected to be the address of
> this kind of struct:
> 
>         struct utimbuf { time_t actime, modtime; } ubuf;
> 
> Using the address of the st_atime field of a stat(2) struct would
> provide these values correctly, because the word following st_atime in
> the structure is st_mtime (the mod. time).  Here's a picture:
> 
>  &st.st_atime -----> st_atime      &ubuf -----> actime
>                      st_mtime                   modtime
> 
> So is this really a bug, or is your C compiler acting strangely?

It's really a bug.  You are assuming that the st_atime + st_mtime fragment
of "struct stat" is laid out in memory the same way as a "struct utimbuf".
This is a compiler-dependent and system-dependent assumption, albeit one
that is often true on reasonable machines.
-- 
				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,linus,decvax}!utzoo!henry

gam@amdahl.UUCP (Gordon A. Moffett) (12/03/84)

>   = Guy Harris {seismo,ihnp4,allegra}!rlgvax!guy
> > = me

> > The second argument of utime(2) is expected to be the address of
> > this kind of struct:
> > 
> >         struct utimbuf { time_t actime, modtime; } ubuf;
> > 
> > Using the address of the st_atime field of a stat(2) struct would
> > provide these values correctly, because the word following st_atime in
> > the structure is st_mtime (the mod. time).
> 
> WRONG!  FALSE!  INCORRECT!  Show me where in STAT(2) it states that those
> fields are contiguous.  The V7 manual did, but the S3 and S5 manuals
> *go out of their way* to state that they say *nothing* about what the
> "stat" structure looks like.  They give the fields in a different order
> than they appear in the structure, and say before it "The contents of
> the structure pointed to by 'buf' *include* the following members:".
> Clearly, they did *not* want to commit to the precise shape of the structure
> forever, world without end, amen....

Quite right, sorry, my mistake.  Never mind.
-- 
Gordon A. Moffett		...!{ihnp4,hplabs,amd,sun}!amdahl!gam

37 22'50" N / 122 59'12" W	[ This is just me talking. ]