записать файл, st_mtime не меняется - PullRequest
1 голос
/ 06 января 2012

У меня есть программа, которая хочет проверить, был ли файл изменен. Regtest не проходит, и, действительно, несмотря на изменение файла, st_mtime не имеет! Более того, внешняя статистика подтверждает то же самое.

Я считаю, что st_mtime должно измениться, потому что stat (2) говорит:

Поле st_mtime изменяется при модификации файла, например, с помощью mknod (2), truncate (2), utime (2) и write (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);
}

Вот что предложить bash, чтобы подтвердить, что это не просто кеширование в программе C:

$ пока верно; делать stat / tmp / foo | grep Modify; сон 1; сделано

Есть предложения, что происходит? Кстати, это работает в системе, идентифицированной таким образом:

jeff@london: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
jeff@london:src $ 

Ответы [ 2 ]

4 голосов
/ 06 января 2012

Прежде всего, я настоятельно рекомендую вам не использовать утверждения с побочными эффектами в течение assert с. Я понимаю, что это удобно, и если код никогда не будет запущен в производство, это на самом деле не имеет значения, но это не очень хорошая форма. В частности, если вы когда-либо определите NDEBUG, assert s преобразуются в noop, код для условия никогда не выполняется.

Теперь проблема, скорее всего, заключается в том, что вы ставите вызов sleep после обоих вызовов touch, а не между ними. Изменить это:

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;
1 голос
/ 06 января 2012

Никогда не используйте assert для функций с побочными эффектами!

Всегда делайте так:

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

assert(fp != NULL);

Вся строка, содержащая assert(), исчезает из сборок релиза.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...