Почему fopen("any_path_name",'r') не выдает NULL в качестве возврата?

При отладке некоторого кода я получил что-то вроде ниже:

#include<stdio.h>

int main()
{
    FILE *fb = fopen("/home/jeegar/","r");
    if(NULL == fb)
        printf("it is null");
    else
        printf("working");
}

Здесь, в fopen, я дал несколько правильное имя пути, но не имя файла. Не должен ли fopen вернуть NULL? Но это не возвращает ноль!

Редактировать:

Если я дам path of valid directory в fopen, то он напечатает working:

Если я дам path of invalid directory в fopen, то он напечатает it is null

Редактировать: спецификация говорит

Upon successful completion, fopen() shall return a pointer to the object 
controlling the stream. Otherwise, a null pointer shall be returned.

поэтому здесь независимо от того, установлен код ошибки или нет, он ДОЛЖЕН возвращать NULL

И установка кода ошибки является расширением до стандарта ISO C.

ОШИБКА ТАКЖЕ НЕ СОБИРАЕТСЯ ЗДЕСЬ

#include<stdio.h>
#include <errno.h>

int main()
{
errno = 0;
FILE *fb = fopen("/home/jeegar/","r");
if(fb==NULL)
    printf("its null");
else
    printf("working");


printf("Error %d \n", errno);


}

ВЫХОД ЕСТЬ

workingError 0 

4 ответа

Решение

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

Страница руководства posix man 3p fopen говорит, в разделе ОШИБКИ:

Функция fopen() должна завершиться ошибкой, если:

[...]

EISDIR Именованный файл является каталогом, а режим требует доступа для записи.

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

О том, что вы можете использовать с FILE* это относится к каталогу, я понятия не имею.

Как вы, возможно, очень хорошо знаете, что почти все в системе Linux - это файл, если не файл, то это процесс (исправления и замечания приветствуются:)) Каталог обрабатывается как файл, в котором перечислены другие файлы ( ссылка из TLDP); поэтому открытие для чтения каталога как файла является допустимой операцией, и поэтому вы не получите никакой ошибки. Хотя попытка записи в него недопустима, поэтому, если вы откроете каталог в режиме записи или добавления, операция fopen завершится неудачно (об этом хорошо упоминались другие ответы и ссылки на документацию fopen). Большинство файловых операций, таких как операции чтения и записи в этом файловом потоке, завершатся с ошибкой, указывающей, что это каталог. Единственное, что можно было найти, - это найти размер файла (в данном случае - каталог), используя fseek в SEEK_END & ftell (что, скорее всего, даст результат 4096).
Что касается использования errno чтобы получить значимые сообщения, вы можете использовать perror который в stdio.h & передать сообщение, которое будет добавлено перед сообщением об ошибке или strerror который в string.h & проходить errno который в errno.h
Надеюсь это поможет!

Как это проверить?

Вы можете проверить errno, например:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
   FILE *fp;
   errno = 0;
   fp = fopen("file.txt", "r");
   if ( errno != 0 ) 
   {
     // Here you can check your error types:
     perror("Error %d \n", errno);
     exit(1);
   }
}

Типы ошибок вы можете найти в http://pubs.opengroup.org/onlinepubs/009695399/functions/fopen.html разделе об ошибках.

Другие вопросы по тегам