utime misusage

Guy Harris guy at rlgvax.UUCP
Fri Nov 30 17:43:16 AEST 1984

> 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

More information about the Comp.lang.c mailing list