Несовместимый 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).
Читайте также Как отлаживать небольшие программы.