open() fails to update st_mtime when used with O_TRUNC and 0 byte files
open() fails to update st_mtime when used with O_TRUNC and 0 byte files
- Subject: open() fails to update st_mtime when used with O_TRUNC and 0 byte files
- From: "Mike Frysinger" <email@hidden>
- Date: Tue, 12 Jun 2007 15:57:25 -0400
i was tracking down a bug in the Linux kernel build system which seems
to be caused by a bug in Darwin. the kernel build system creates a
bunch of 0 byte files and then uses open(O_TRUNC) on them in order to
update the st_mtime field (which triggers make to recreate some object
files). on my mac mini, this all falls apart.
according to POSIX:
http://www.opengroup.org/onlinepubs/009695399/functions/open.html
If O_TRUNC is set and the file did previously exist, upon successful
completion, open() shall mark for update the st_ctime and st_mtime
fields of the file.
Darwin appears to update st_ctime properly, but not st_mtime.
the machine i'm testing on:
$ uname -a
Darwin Blackfin-Linux-Mac-Mini.local 8.9.0 Darwin Kernel Version
8.9.0: Thu Feb 22 20:54:07 PST 2007; root:xnu-792.17.14~1/RELEASE_PPC
Power Macintosh powerpc
but it was first noticed on one of the new Interl based macbooks
the filesystem is default OS X HFS+ with case sensitivity enabled
the attached test code should show the issue clearly
-mike
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
void timestest(size_t num_bytes)
{
const char *tempfile = "MOO_MOO";
struct stat st1, st2;
int fd, ret;
/* punt the file and then create a 0 byte file and get its times */
printf("getting first times ...\n");
unlink(tempfile);
fd = open(tempfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
assert(fd >= 0);
if (num_bytes)
write(fd, tempfile, num_bytes);
close(fd);
ret = stat(tempfile, &st1);
assert(ret == 0);
/* sleep a little to make there is a difference in the times */
printf("sleeping for three seconds ...\n");
sleep(3);
/* open the file again and grab the new file times */
printf("getting second times ...\n");
fd = open(tempfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
assert(fd >= 0);
close(fd);
ret = stat(tempfile, &st2);
assert(ret == 0);
unlink(tempfile);
/* each of these should be different (except for atime if you
* mount your filesystem with atime turned off)
*/
#define comp(member) (st1.member == st2.member ? "same" : "diff")
printf("the following times should all be different\n(atime can be the same if you have filesystem mounted noatime)\n");
printf("atime: %lu vs %lu (%s)\n"
"mtime: %lu vs %lu (%s)\n"
"ctime: %lu vs %lu (%s)\n",
st1.st_atime, st2.st_atime, comp(st_atime),
st1.st_mtime, st2.st_mtime, comp(st_mtime),
st1.st_ctime, st2.st_ctime, comp(st_ctime));
printf("\n");
}
int main(int argc, char *argv[])
{
printf("testing truncation with a 0 byte file\n");
timestest(0);
printf("testing truncation with a 4 byte file\n");
timestest(4);
return 0;
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden