Почему dirent.h не работает на дисках sshfs?

Вот код, который я использовал для его проверки.
Он работает на обычных каталогах, но не на тех, которые смонтированы под sshfs.
Моя цель — использовать эти методы в
https://github.com/jlettvin/Greased-Grep
который предназначен для глобального нечеткого поиска
ключевые слова, которые должны присутствовать и ключевые слова, которые должны отсутствовать.

#include <iostream>
#include <string>
#include <functional>
#include <dirent.h>

using std::cout;
using std::endl;
using std::string;
using std::function;

bool neither (const char* path)
{
bool ret = (path != nullptr);
if (ret)
{
if (path[0] == '.')
{
if (path[1] == '\0') ret = false;
if (path[1] == '.' && path[2] == '\0') ret = false;
}
}
return ret;
}

void walk (const string &path, function<void (const string &)> talk)
{
if (auto dir = opendir (path.c_str ())) {
while (auto f = readdir (dir)) {
auto name = f->d_name;
auto type = f->d_type;
if (neither (name))
{
switch (type)
{
case DT_DIR: walk (path + name + "/", talk); break;
case DT_REG: talk (path + name            ); break;
}
}
}
closedir(dir);
}
}

int main (int argc, char** argv)
{
walk ("./", [](const string &path) { cout << path << endl; });
return 0;
}

0

Решение

Вам нужно просмотрите следующую документацию в Linux readdir(3) страница справочника:

  unsigned char       d_type;     /* Type of file; not supported
by all filesystem types */

В частности, ваше внимание направлено на часть «не поддерживается всеми типами файловых систем».

Ваш код ожидает d_type установить. Тем не мение, readdir(3) не гарантирует, что это будет.

Одно из возможных значений для d_type является:

DT_UNKNOWN

The file type could not be determined.

Код, который должен быть подготовлен для обработки всех возможностей, должен явно проверять DT_UNKNOWNи, если да, добавить d_name на имя каталога, stat() имя файла, а затем получить тип файла оттуда.

d_type это ярлык Если это установлено, замечательно. У вас это есть сразу. Если нет, вам придется работать, чтобы получить его.

sshfs очевидно, не поддерживает возвращение d_type от readdir(3), С надеждой, sshfs инвентарь stat(),

P.S., не то, что кроме каталога и обычных файлов, есть также несколько других специальных типов, с которыми вы можете или не можете обращаться (при условии, что sshfs могу даже предоставить их вам). Это то, что вам нужно исследовать самостоятельно.

2

Другие решения

У меня есть код, который я хотел работать.

После масштабных экспериментов со всей чувствительностью ко всевозможным флагам, условиям и ситуациям я решил пойти с предельной простотой.

Я отношусь ко всему найденному как к каталогу, так и к файлу. Если это не каталог, я обнаруживаю и игнорирую все ошибки и продолжаю. Если это каталог, я открываю его и ищу в нем то, что хочу. Это преимущество в Greased-Grep, цель которого — найти подходящие вещи. Имена файлов — это такие же вещи, как и их содержимое.

Итак, мой ответ: мне плевать на неудачи. Меня волнуют только успехи, поэтому я отказываюсь от неудач без каких-либо испытаний.

Это прекрасно работает, когда спускаются каталоги, смонтированные по sshfs.

Любой, кто интересуется, как выглядит этот код, может подписаться на мой github:
https://github.com/jlettvin/Greased-Grep/blob/master/gg.cpp

Вот выдающийся код:

void walk (const string& a_path)
{
// Don't attempt to assess validity of filenames... just fail.
// Treat directories like files and search filenames in directories.
// This enables gg to work on sshfs mounted filesystems.
auto d{a_path};
auto s{d.size ()};
if (s && d[s - 1] == '/') d.resize (s-1);
errno = 0;
if (auto dir = opendir (d.c_str ()))
{
while (!errno)
{
if (auto f = readdir (dir))
{
if (auto p = f->d_name)
{
if (auto q = p)
{
if (!(*q++ == '.' && (!*q || (*q++ == '.' && !*q))))
{
auto e = d + "/" + p;
walk (e);
mapped_search (e.c_str ());
errno = 0;
}
}
else break;
}
else break;
}
else break;
}
}
}
0

По вопросам рекламы [email protected]