Я пишу программу командной строки Linux, которая вернет размер каталога. Программа работает так, как ожидалось, за исключением случаев, когда речь идет конкретно о корневых каталогах. Я знаю, что многие файлы в корневом каталоге не имеют размеров, потому что это специальные файлы, используемые для представления системной информации (например, /proc/) или что-то вроде /dev/null/, поэтому я использовал std::filesystem::directory_options::skip_permission_denied
в своем цикле for, чтобы пропустить проблемы с разрешениями и Я использовал несколько блоков try/catch для перехвата исключений.
Однако даже при этом исключение отказа в разрешении все равно выдается. См. следующий код:
byte_size_and_num_files find_recursive(const std::filesystem::path& path)
{
byte_size_and_num_files bsnf;
std::filesystem::path pa;
try
{
for(const auto& p: std::filesystem::recursive_directory_iterator(path, std::filesystem::directory_options::skip_permission_denied))
{
pa = p.path();
if (std::filesystem::exists(p) && !std::filesystem::is_directory(p))
{
try
{
if(std::filesystem::is_regular_file(pa))
{
bsnf.size += std::filesystem::file_size(p);
bsnf.files++;
}
else
std::cout << "SKIPPED: size is not determinable: " << pa << "\n";
}
catch(std::filesystem::filesystem_error& e)
{
std::cout << "SKIPPED: size is not determinable: " << pa << "\n";
}
catch(std::bad_alloc)
{
std::cout << "Allocation error. Exiting..." << "\n";
byte_size_and_num_files err;
return err;
}
}
}
}
catch(std::filesystem::filesystem_error& e)
{
std::cout << "Unable to access file or path " << pa <<": " << e.what() << "\n";
}
catch(std::bad_alloc)
{
std::cout << "Allocation error. Exiting..." << "\n";
byte_size_and_num_files err;
return err;
}
return bsnf;
}
Выход:
...
SKIPPED: size is not determinable: "/lib/systemd/system/motd.service"
SKIPPED: size is not determinable: "/lib/systemd/system/mountall-bootclean.service"
SKIPPED: size is not determinable: "/lib/systemd/system/mountall.service"
SKIPPED: size is not determinable: "/lib/systemd/system/mountdevsubfs.service"
SKIPPED: size is not determinable: "/lib/systemd/system/mountkernfs.service"
SKIPPED: size is not determinable: "/lib/systemd/system/mountnfs-bootclean.service"
SKIPPED: size is not determinable: "/lib/systemd/system/mountnfs.service"
SKIPPED: size is not determinable: "/lib/systemd/system/rc.service"
SKIPPED: size is not determinable: "/lib/systemd/system/rcS.service"
SKIPPED: size is not determinable: "/lib/systemd/system/reboot.service"
SKIPPED: size is not determinable: "/lib/systemd/system/rmnologin.service"
SKIPPED: size is not determinable: "/lib/systemd/system/sendsigs.service"
SKIPPED: size is not determinable: "/lib/systemd/system/single.service"
SKIPPED: size is not determinable: "/lib/systemd/system/stop-bootlogd-single.service"
SKIPPED: size is not determinable: "/lib/systemd/system/stop-bootlogd.service"
SKIPPED: size is not determinable: "/lib/systemd/system/umountfs.service"
SKIPPED: size is not determinable: "/lib/systemd/system/umountnfs.service"
SKIPPED: size is not determinable: "/lib/systemd/system/umountroot.service"
SKIPPED: size is not determinable: "/lib/systemd/system/x11-common.service"
SKIPPED: size is not determinable: "/lib/systemd/system/lvm2.service"
Unable to access file or path "/proc/1/task/1/cwd": filesystem error: status: Permission denied [/proc/1/task/1/cwd]
/ is 262172.00 gigabytes with 143839 files.
Что дает? Его четкий отказ в разрешении всегда следует пропускать, но он все равно выдается. Ясно также, что файлы, размер которых невозможно определить, также пропускаются, но создается впечатление, что найдены и используются файлы неправильных размеров (262172,00 ГБ, конечно, не правильно). Это происходит ТОЛЬКО при переходе через корневой каталог, а не через какой-либо другой каталог, например домашний.
Может ли это быть ошибкой реализации?
РЕДАКТИРОВАТЬ: некоторая отладка выявила важную информацию. Похоже, что /dev/pts/ специально портит размеры файлов. Я не понимаю, почему файлы в этом каталоге не пропускаются, так как они не являются обычными файлами, поэтому их следует пропускать. Я предполагаю, что std::filesystem неправильно идентифицирует их как обычные файлы.
Кроме того, std::filesystem::directory_options::skip_permission_denied работает для каждого отдельного файла, кроме /proc/1/task/1/cwd. Я не уверен, почему именно этот файл не пропущен.
РЕДАКТИРОВАТЬ 2 Я отследил каталоги преступников, которые нарушают std::filesystem. Есть три,
/dev/
/proc/
/var/cache/
/dev/ по какой-то причине испортит размеры файлов, я думаю, std::filesystem считает эти обычные файлы, поэтому, когда вы пытаетесь получить размеры файлов, вы получаете номер мусора. Некоторые части /dev/ будут вызывать исключение разрешения, ДАЖЕ КОГДА используется разрешение пропуска.
/proc/ также искажает размеры файлов по той же причине, что и /dev/
/var/cache/, похоже, не искажает размеры файлов, но выдает исключение разрешения, даже если используется разрешение пропуска.
Я считаю, что это ошибки реализации, поскольку файлы в этих каталогах не являются обычными файлами, но std::filesystem рассматривает их как таковые.