Как получить размер файла с заданным именем и дескриптором родительского каталога или индексным узлом?

Я пишу небольшую утилиту для рекурсивного сканирования дерева каталогов и записи древовидной структуры с именами и размерами файлов. (Быстро настолько, насколько это возможно)

Возможно, я загнал себя в угол. Я могу получить содержимое каталога с помощью readdir(3) и работать с обычными файлами и каталогами отдельно.

Я не вижу, как получить размер файла обычного файла, кроме как с помощью вызовов openat(), fstat(), close().

Есть ли способ более точного получения размера файла при обработке записей каталога? Возможно, из номера инода?

Я ожидал, что это будет существовать: statat(int parentDirFD, const char * filename), так как у меня есть только имя файла, а не путь к файлу.

Кажется, в моем ядре нет поддержки O_PATH.

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

DIR* p_dir = ...;

int dir_fd = dirfd(p_dir);


size_t get_file_size(const char * filename_only, int dir_fd, DIR* pdir )
{
  //// this just strikes me as overly expensive:
  int fd = openat(dir_fd, filename_only, O_RDONLY );
  struct stat sb;
  fstat( fd, &sb );
  size_t file_size = sb.st_size;
  close(fd);
  //////

  return file_size;
}

person NoahR    schedule 04.08.2017    source источник
comment
Функция, которую вы ожидаете назвать statat, на самом деле называется fstatat. Требуется дополнительный аргумент флага, чтобы определить, имеет ли он lstat-подобное поведение в случае символической ссылки. спецификация POSIX справочная страница Linux   -  person    schedule 05.08.2017
comment
Боже мой. Вот оно! Думаю, я просто проглядел это, просматривая мою справочную веб-страницу goto fstat.   -  person NoahR    schedule 05.08.2017


Ответы (1)


Как только Wumpus Q. Wumbley дал ответ в комментариях, это оказалось совсем несложно. fstatat()

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

DIR* p_dir = ...;

int dir_fd = dirfd(p_dir);


size_t get_file_size(const char * filename_only, int dir_fd )
{
  struct stat sb;
  int fstatat_flags = 0; //| AT_SYMLINK_NOFOLLOW
  int stat_res = fstatat( dir_fd, filename_only, &sb, fstatat_flags );
  size_t file_size = sb.st_size;

  return file_size;
}
person NoahR    schedule 05.08.2017
comment
Из любопытства, вы обнаружили разницу в производительности в вашей системе между fstatatopenat + fdopendir, я полагаю) и передачей полных путей? Несколько лет назад я немного поработал над собой, надеясь сократить количество циклов и вспомнить, что результаты меня несколько не впечатлили. - person doynax; 05.08.2017