Ifstream open () не устанавливает биты ошибок, если аргумент является каталогом

В программе на C ++, используя std :: ifstream, я пытаюсь открыть указанный пользователем файл - пока все хорошо. Однако я случайно ввел имя файла, которое на самом деле является каталогом, и был весьма удивлен, увидев, что попытка open () этого каталога не сгенерировала никаких ошибок.

Вот минимальный пример:

std::ifstream f;
f.open("..");
if(!f.is_open() || !f.good() || f.bad() || f.fail()) {
    std::cout << "error bit set on open" << std::endl;
    return 1;
}

Здесь нет никаких признаков ошибки. Если я продолжу и попытаюсь выполнить getline (), getline () установит бит ошибки нормально.

std::string str;
getline(f, str);

if(f.eof()) std::cout << "getline set eofbit" << std::endl;
else if(f.bad()) std::cout << "getline set badbit" << std::endl;
else if(f.fail()) std::cout << "getline set failbit" << std::endl;

Это выводит "getline set badbit", что вполне разумно. Использование оператора >> вызывает исключение потери значимости, что тоже нормально.

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

Кроме того, почему это так? Я понимаю, что с точки зрения программы это одни и те же данные, но я предполагаю, что ОС также отправит сообщение типа «эй, это каталог».


person SáT    schedule 06.03.2012    source источник
comment
На какой платформе вы наблюдаете такое поведение?   -  person Emile Cormier    schedule 07.03.2012
comment
В C ++ нет понятия каталога. Вам нужна библиотека для конкретной платформы (например, Posix или Windows).   -  person Kerrek SB    schedule 07.03.2012
comment
О, Ubuntu 10.04, компилятор - gcc 4.4.3.   -  person SáT    schedule 07.03.2012
comment
@KerrekSB: ... или переносимая библиотека, такая как Boost или Qt.   -  person Emile Cormier    schedule 07.03.2012
comment
Могут быть платформы, на которых открытие каталога и чтение из него - вполне допустимое занятие. Если вы используете Unix-подобную платформу, вы можете использовать fstat, чтобы выяснить, какой это тип файла. У Windows тоже будет какой-то способ сделать это.   -  person deong    schedule 07.03.2012


Ответы (1)


Вы не говорите, какая у вас система, поэтому трудно сказать, но обычно filebuf::open возвращает ошибку только в том случае, если не удается открыть уровень вашей системы. И я работал над системами Unix, где вы могли open() каталог; Я даже работал над некоторыми из них, где вы могли прочитать его после открытия (по крайней мере, если это была локально смонтированная файловая система).

Что с этим делать: все, что я могу придумать, - это попытаться get первый символ, а затем вернуть его. Но это не удается, если файл пуст, так что это тоже не решение. На системном уровне (и с точки зрения QoI я бы ожидал, что filebuf::open сделает это, если система разрешает открытие каталога), вы можете использовать вызов системного уровня (stat в Unix), чтобы определить, является ли файл каталог или нет. (Конечно, существует состояние гонки: между моментом, когда вы обнаруживаете, что это нормальный файл, и моментом, когда вы открываете его, другой процесс может удалить файл и создать каталог. Однако это, вероятно, нечастое явление.)

person James Kanze    schedule 06.03.2012
comment
О, в конце концов, я мог догадаться, что это зависит от платформы. Спасибо за объяснение. Да, это на Linux (что неудивительно, Ubuntu, то же самое происходит с Debian). Поскольку я просто пытаюсь убедиться, что это действительный и читаемый файловый поток, из которого я могу читать материал, получение и отключение является разумным, хотя я надеялся на более чистое решение. Зависимости и системные вызовы кажутся излишними. Я имею в виду, что могу жить с ошибкой, но это выглядело просто странно. - person SáT; 07.03.2012
comment
@ SáT: Я также предполагаю, что это специфично для базовой файловой системы, используемой на оборудовании (примечание: некоторые ОС позволяют вам выбирать файловую систему, используемую на дисках). - person Martin York; 07.03.2012
comment
@LokiAstari Я так думаю. IIRC (с тех пор, как я это пробовал, прошло некоторое время), под Solaris open в каталоге работал на локально смонтированных дисках (UFS), но не, если файловая система была NFS. - person James Kanze; 07.03.2012