Если ваша платформа имеет достаточную поддержку POSIX 2008, вы можете использовать функции fstatat()
и dirfd()
для хорошего эффекта. Это будет работать на текущих версиях BSD, macOS, Linux, AIX, HP-UX, Solaris - как минимум.
Этот код похож на код в вопросе, но он не пытается повторить способ декодирования типа файла и т. д. c.
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char **argv)
{
for (int i = 1; i < argc; i++)
{
const char *dir = argv[i];
DIR *dp = opendir(dir);
if (dp == 0)
{
fprintf(stderr, "%s: failed to open directory %s: %d %s\n",
argv[0], dir, errno, strerror(errno));
continue;
}
/* dirfd(): POSIX 2008 - OK on BSD, macOS, Linux, AIX, HP-UX, Solaris */
int fd = dirfd(dp);
struct dirent *file;
while ((file = readdir(dp)) != 0)
{
struct stat sb;
/* 0 argument could be AT_SYMLINK_NOFOLLOW */
if (fstatat(fd, file->d_name, &sb, 0) == 0)
{
/* Some of the conversion specifiers may be incorrect for some systems */
/* Inode number, size, time in particular */
printf("%10llu %5d %5d %7o %3d %9lld %10ld %10ld %10ld %s/%s\n",
sb.st_ino, sb.st_uid, sb.st_gid, sb.st_mode, sb.st_nlink, sb.st_size,
sb.st_mtime, sb.st_atime, sb.st_ctime, dir, file->d_name);
}
else
fprintf(stderr, "%s: failed to stat() %s/%s: %d %s\n",
argv[0], dir, file->d_name, errno, strerror(errno));
}
closedir(dp);
}
return 0;
}
Обратите внимание, что для этого вообще не нужно (и, следовательно, не) использовать chdir()
. Использование fstatat()
позволяет указать «интерпретировать имя файла относительно заданного каталога», где каталог идентифицируется дескриптором файла.
При наличии подходящего пакета сообщений об ошибках (поэтому название программы будет включается в ошибки автоматически), я бы упаковал тело l oop как функцию. Однако ссылки argv[0]
в сообщениях об ошибках делают это неудобным. Для отчетов об ошибках я бы использовал код, который доступен в моем репозитории SOQ (вопросы о переполнении стека) на GitHub в виде файлов stderr.c
и stderr.h
в подпункте src / libsoq -directory.
Пример вывода (от Ma c - номера инодов 10-ди git больше, чем в большинстве систем):
$ at67 bin ~/src/ule
4296808809 501 20 40755 33 1056 1577029162 1583165629 1577029162 bin/.
4296808746 501 20 40755 208 6656 1583164216 1583165629 1583164216 bin/..
4296811200 501 20 100755 1 1266 1515986057 1582224384 1582216636 bin/rfn
4296811205 501 20 100755 1 1266 1515986057 1583164235 1582216636 bin/rfn-c
4305347192 501 20 100755 1 246 1524096284 1582224384 1582216636 bin/soqvg
4297537255 501 20 100755 1 3813 1579639563 1582830967 1582216636 bin/pipe-rot
4296811199 501 20 100755 1 233 1515695843 1582224384 1582216636 bin/sow
4298720660 501 20 100755 1 627 1517875149 1582224384 1582216636 bin/so-getchar
4296811201 501 20 100755 1 218 1515695843 1582224384 1582216636 bin/ddpr
4296811210 501 20 100755 1 1266 1515986057 1582224384 1582216636 bin/rfn-pl
4296808811 501 20 100644 1 490 1510874880 1578595253 1510874880 bin/README.md
4296811204 501 20 100755 1 2278 1515695843 1582224384 1582216636 bin/fixin
4296811203 501 20 100755 1 2835 1576997332 1582224384 1582216636 bin/so-books
4296811196 501 20 100755 1 617 1515695843 1582224388 1582216636 bin/wso
4296811197 501 20 100755 1 85 1515695843 1583165629 1582216636 bin/so
4296808810 501 20 100644 1 92 1510874880 1579561480 1510874880 bin/.gitignore
4296811193 501 20 100755 1 200 1515695843 1582224388 1582216636 bin/posixcmd
4296811206 501 20 100755 1 1266 1515986057 1582224384 1582216636 bin/rfn-h
4451766334 501 20 100755 1 507 1576997332 1582224384 1582216636 bin/so-esql
4297012073 501 20 100755 1 937 1582216633 1583164235 1582216636 bin/sscce
4296811202 501 20 100755 1 522 1515695843 1582224384 1582216636 bin/so-late
4296811209 501 20 100755 1 1266 1515986057 1582224384 1582216636 bin/rfn-sql
4297507309 501 20 100755 1 848 1526264352 1582224384 1582216636 bin/so-stderr
4296811194 501 20 100755 1 206 1515695843 1582224388 1582216636 bin/posixfun
4342190418 501 20 100755 1 1227 1541833786 1582224384 1582216636 bin/so-quotes
4298078558 501 20 100755 1 722 1515695843 1582224384 1582216636 bin/soa
4296811198 501 20 100755 1 92 1515695843 1582224384 1582216636 bin/sops
4356366344 501 20 100755 1 454 1545845134 1582644937 1582216636 bin/so-reformat-c
4296811208 501 20 100755 1 1266 1515986057 1582224384 1582216636 bin/rfn-cpp
4298720661 501 20 100755 1 700 1576997332 1582224384 1582216636 bin/so-c-reserved
4296811207 501 20 100755 1 1266 1515986057 1582656633 1582216636 bin/rfn-sh
4296811195 501 20 100755 1 255 1515695843 1582224388 1582216636 bin/posixhdr
4451855327 501 20 100755 1 780 1577029658 1582224384 1582216636 bin/so-dotarrow
4296916142 501 20 40755 15 480 1574117045 1583165629 1574117045 /Users/jonathanleffler/src/ule/.
4296713088 501 20 40755 97 3104 1575746582 1583165539 1575746582 /Users/jonathanleffler/src/ule/..
4296917945 501 20 100444 1 7 1473056744 1578608259 1510993969 /Users/jonathanleffler/src/ule/ule-test-nnl
4296917947 501 20 100644 1 6148 1418098863 1578608259 1510994007 /Users/jonathanleffler/src/ule/.DS_Store
4296917957 501 20 100755 1 44824 1473056806 1578608437 1513032846 /Users/jonathanleffler/src/ule/ule-v1.4
4296917948 501 20 100444 1 15 1473056679 1578608259 1510993969 /Users/jonathanleffler/src/ule/ule-test-nul
4296917949 501 20 100640 1 43 1418023230 1578608259 1510993969 /Users/jonathanleffler/src/ule/ule-test-mix
4296917951 501 20 100644 1 745 1436058130 1578608259 1510993969 /Users/jonathanleffler/src/ule/ule.notes
4296917952 501 20 100640 1 33 1418023230 1578608259 1510993969 /Users/jonathanleffler/src/ule/ule-test-unx
4296917953 501 20 100640 1 33 1418023230 1578608259 1510993969 /Users/jonathanleffler/src/ule/ule-test-dos
4296917954 501 20 40755 11 352 1541802114 1578608839 1541802114 /Users/jonathanleffler/src/ule/RCS
4441180506 501 20 100444 1 6726 1574116649 1578608259 1574117045 /Users/jonathanleffler/src/ule/ule.c
4296917956 501 20 40755 3 96 1437532230 1578611808 1510994007 /Users/jonathanleffler/src/ule/ule.dSYM
4297282884 501 20 100755 1 60160 1513033250 1582552763 1513033250 /Users/jonathanleffler/src/ule/ule
4296917958 501 20 100640 1 30 1425237329 1578608259 1510993969 /Users/jonathanleffler/src/ule/ule-test-mac
$
Если ваша система не ' dirfd()
, но fstatat()
, вы можете использовать эти функции для открытия и закрытия каталога. (В ранней редакции приведенного выше кода использовался вариант этого кода, но он быстро запутывается при настройке, и dirfd()
делает все это ненужным.). Вы бы использовали dir_open(dir)
вместо dirfd(dp)
и добавили dir_close(fd)
до или после closedir(dp)
.
#include <fcntl.h>
#include <unistd.h>
int dir_open(const char *name)
{
return open(name, O_RDONLY | O_DIRECTORY);
}
int dir_close(int fd)
{
return close(fd);
}
Если ваша система имеет O_SEARCH
, используйте это вместо O_RDONLY
(O_SEARCH
недоступен в MacOS Mojave 10.14.6, например, где я проводил тестирование). Если ваша система не имеет O_DIRECTORY
, пропустите этот термин. Это лишь некоторые детали, которые усложняют настройку этого беспорядка.
В целом, если у вас есть fstatat()
, у вас, вероятно, тоже будет dirfd()
.