Как в C правильно форматировать время?

Есть вот такой кусок кода:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

void listdir(const char *name, int indent)
{
    DIR *dir;
    struct dirent *entry;
    struct stat buff;


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

    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR) {
            //char path[1024];

            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0){
                continue;
              }
              //
              stat(entry->d_name, &buff);

              time_t times = buff.st_ctim.tv_sec;

              printf("%s %s", entry->d_name, ctime(&times)); //

              listdir(entry->d_name, indent + 1);



        }
    }
    closedir(dir);
}

int main(void) {
    listdir(".", 0);
    return 0;
}

При выполнении выдает время ctime не корректно, все идет с 1970 года. Получается так: Thu Jan 1 05:03:14 1970 Проблема в форматировании времени?


Ответы (1 шт):

Автор решения: avp

Видимо у вас какая-то наведенная ошибка, поскольку вы не обходите дерево оглавлений, но рекурсивно вызываете listdir() и не проверяете результата вызова stat().

У меня

avp@avp-xubu2:~/hashcode$ uname -a
Linux avp-xubu2 5.4.0-84-generic #94-Ubuntu SMP Thu Aug 26 20:27:37 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
avp@avp-xubu2:~/hashcode$ 

ваш код с минимальными изменениями (пара chdir() для обхода дерева) вполне успешно работает.

void listdir(const char *name, int indent)
{
    DIR *dir;
    struct dirent *entry;
    struct stat buff;


    if (!(dir = opendir(name))){
      perror(name);
      return;
    }
    chdir(name); // думаю, тут можно и не проверять результат, т.к. предыдущий `opendir()` успешно прошел

    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR) {
            //char path[1024];

            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0){
                continue;
              }
              //
              stat(entry->d_name, &buff);

              time_t times = buff.st_mtim.tv_sec; //buff.st_ctim.tv_sec;

              printf("%s %s", entry->d_name, ctime(&times)); //

              listdir(entry->d_name, indent + 1);



        }
    }
    closedir(dir);
    chdir("..");
}

Для соответствия формата времени тому, что выводит ls -l я заменил st_ctim (в manpage это "Time of last status change") на st_mtim ("Time of last modification").

→ Ссылка