Несовместимый gmtime в C при рекурсивном обходе каталогов

У меня есть программа на C, где я использую рекурсивную функцию, которая пересекает структуру каталогов. Требуется time_t переменная и создает из нее структуру gmtime.

Рекурсивная функция dir из Как рекурсивно перечислять каталоги в C на Linux?

void traversedir(time_t cutoff, const char* name, int indent)
{
    if (indent > 9)
        return;

    DIR* dir;
    struct dirent* entry;

    if (!(dir = opendir(name)))
        return;

    struct tm *t = gmtime(&cutoff);
    printf("%d-%d-%d %d:%d:%d (%lld)\n", (1900 + t->tm_year), (t->tm_mon + 1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, (long long) cutoff);
    sleep(1);  // only for debugging

    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR) {
            char path[1024];
            if (entry->d_name[0] == '.' && !isValidNumber(entry->d_name))
                continue;
            snprintf(path, sizeof(path), "%s/%s", name, entry->d_name);

            ...

            traversedir(cutoff, path, indent + 2);
        }
    }
    closedir(dir);
}

void imageCleanup()
{
    time_t cutoff = (time(NULL) - (86400 * 10));
    do {
        printf("Cutoff: %lld\n", (long long) cutoff);
        traversedir(cutoff, "/path/to/dir", 0);
        sleep(2);
        cutoff += 3600;
    } while (!available_storage() && cutoff < time(NULL));
}

Это вывод при запуске программы.

Cutoff: 1534245930
2018-8-14 11:25:30 (1534245930)
2018-8-24 11:25:31 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-24 11:25:33 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-14 11:25:35 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-24 11:25:38 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-24 11:25:43 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-24 11:25:52 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-24 11:25:54 (1534245930)
2018-8-14 11:25:55 (1534245930)
2018-8-24 11:25:56 (1534245930)
2018-8-14 11:25:30 (1534245930)
2018-8-24 11:25:58 (1534245930)

time_t что структура преобразуется из находится в скобках. Это последовательно 1534245930 или 14 августа 2018 11:25:30, что составляет минус десять дней на выполнение программы.

Вы можете видеть, что преобразование довольно противоречиво. Несколько раз секунды следуют за фактическим временем на момент выполнения. День меняется также несколько раз.

Кто-нибудь знает или имеет представление, что может вызвать это? Я попытался просто сделать простой цикл, который преобразует статический time_t без каких-либо проблем, так что я могу только предположить, что у него есть что-то

1 ответ

Решение

Прочитайте внимательно время (7) и gmtime (3).

Заметить, что gmtime не является реентерабельным, поскольку возвращает адрес некоторых статических данных. Ты хочешь gmtime_r (так как ваш traversedir функция является рекурсивной) и должна использовать локальную struct tm автоматическая переменная.

так

struct tm mytm;
struct tm *t = gmtime_r(&cutoff, &mytm);

затем t будет указывать на mytm в стеке вызовов (не для некоторых статических данных).

Вам также следует использовать strftime (3) (опять же, с достаточно большим буфером, объявленным как автоматическая переменная, или с некоторым выделенным буфером кучи).

Вас также могут заинтересовать nftw (3) и stat (2).

Читайте также Как отлаживать небольшие программы.

Другие вопросы по тегам