plain C: opening a directory with fopen()

前端 未结 2 2038
南笙
南笙 2020-11-30 13:59

I have a program which opens a file and checks its length.

FILE* fd = fopen(argv[1], \"rb\");
fseek(fd, 0, SEEK_END);
size_t flen = ftell(fd);
if (flen == ((         


        
相关标签:
2条回答
  • 2020-11-30 14:39

    From http://pubs.opengroup.org/onlinepubs/7908799/xsh/fopen.html:

    The fopen() function will fail if: 
    [EISDIR] The named file is a directory and mode requires write access.
    

    At least on Linux, if you try to fopen("dirname", "wb") you get an EISDIR error. I also tried with a directory with d-------- access rights, and I still get EISDIR (and not EACCES.)

    0 讨论(0)
  • 2020-11-30 14:47

    Directories do not exist in the C99 standard (or the C2011 one). So by definition, fopen-ing a directory is either implementation specific or undefined behavior.

    fopen(3) can fail (giving a NULL result). fseek(3) can also fail (by returning -1). And then you should preferably check errno(3) or use perror(3)

    ftell is documented to return a long, and -1L on failure. On 64 bits Linux this is 0xffffffffffffffff.

    You code should be instead

    FILE* fd = fopen(argv[1], "rb");
    if (!fd) 
      { perror(argv[1]); exit(EXIT_FAILURE); };
    if (fseek(fd, 0, SEEK_END)<0) 
      { perror("fseek"); exit(EXIT_FAILURE); };
    long flen = ftell(fd);
    if (flen == -1L)
      { perror("ftell"); exit(EXIT_FAILURE); };
    

    BTW, On Linux/Debian/Sid/AMD64 with libc-2.17 and 3.10.6 kernel, that codes runs ok when argv[1] is /tmp; surprizingly, flen is LONG_MAX i.e. 0x7fffffffffffffff

    BTW, on Linux, directories are a special case of files. Use stat(2) on a file path (and fstat on a file descriptor, perhaps obtained with fileno(3) from some FILE*) to know more meta data about some file, including its "type" (thru its mode). You want opendir(3), readdir(3) & closedir(3) to operate on directory contents. See also inode(7).

    0 讨论(0)
提交回复
热议问题