写入文件,st_mtime不会更改

问题描述:

我有一个程序要检查文件是否已被修改。注册失败,事实上,尽管文件已更改,st_mtime还没有!此外,外部统计也证实了这一点。写入文件,st_mtime不会更改

我相信st_mtime 应该变化,因为统计(2)说

领域st_mtime是通过文件的修改改变,例如,通过用mknod(2),截断(2),UTIME(2)和写(2)(大于零字节)。

这里有一点C代码,说明此事:

#include <assert.h> 
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 


void touch(const char *fn, const char *contents) 
{ 
    FILE *fp; 
    assert(fp = fopen(fn, "w")); 
    fprintf(fp, contents); 
    fclose(fp); 
} 


int main(int argc, char *argv[]) 
{ 
    struct stat st; 
    char path[] = "/tmp/foo"; 
    time_t m1, m2; 
    unsigned int t; 

    touch(path, "hello\n"); 
    assert(!stat(path, &st)); 
    m1 = st.st_mtime; 

    touch(path, "hello, world!\n"); 
    t = sleep(2); 
    assert(!stat(path, &st)); 
    m2 = st.st_mtime; 

    printf("Sleep remaining: %lu\n", t); 
    printf("Elapsed modtime=%lu\n", m2 - m1); 
} 

这里的东西提供给打坏,以确认它不只是在C程序中的缓存:

$,而真正;做stat/tmp/foo | grep修改;睡眠1;完成

有什么建议发生了什么? FWIW,这是可鉴定的系统上运行:

[email protected]:src $ uname -a 
Linux london 2.6.32-37-generiC#81-Ubuntu SMP Fri Dec 2 20:32:42 UTC 2011 x86_64 GNU/Linux 
[email protected]:src $ 
+0

你如何改变你检查文件?在分析代码之前,可能需要考虑该步骤中的错误。 – Sim 2012-01-05 20:54:31

+0

touch()函数进行更改。它只是“echo $ 1>/tmp/foo”的C等价物。 – jma 2012-01-05 20:55:22

+0

从shell中查看文件,我确认它具有来自第二次更改的内容,但是从第一次更改了modtime! – jma 2012-01-05 21:00:04

首先,我强烈建议您不要在assert之内使用带副作用的语句。我明白这很方便,如果代码永远不会生产,它并不重要,但它不是很好的形式。特别是,如果您定义了NDEBUG,则assert会转换为noop,但条件的代码永远不会执行。

现在,问题很可能是您在拨打touch后调用sleep调用,而不是调用它们。更改此:

touch(path, "hello\n"); 
assert(!stat(path, &st)); 
m1 = st.st_mtime; 

touch(path, "hello, world!\n"); 
t = sleep(2); 
assert(!stat(path, &st)); 
m2 = st.st_mtime; 

touch(path, "hello\n"); 
int rv = stat(path, &st); 
assert(!rv); 
m1 = st.st_mtime; 

t = sleep(2); 

touch(path, "hello, world!\n"); 
int rv = stat(path, &st); 
assert(!rv); 
m2 = st.st_mtime; 
+0

恩,是的,我是个白痴。感谢您指出我显而易见的......这是一些相当复杂的代码的一个人为的例子,我清楚地校对了我认为我写的东西。 – jma 2012-01-05 21:04:59

+1

而现实生活中的代码复杂得多,也有同样的错误。我比我敢于梦想的更一致。 – jma 2012-01-05 21:07:47

切勿使用上的功能assert有副作用!

始终做到这一点:

FILE * fp; 
fp = fopen(...); 

assert(fp != NULL); 

包含assert()自发布消失构建整条生产线。

+0

同意,谢谢。在这个抛弃的例子中,它的意思是在这个例子中排除不良的返回值。 – jma 2012-01-05 21:06:12