Почему 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 разделе об ошибках.