views:

102

answers:

4

Hi, I'm making an HTTP server and when I get the path of the file they request I open it with the following:

returned_file = fopen(path, "r");

this (contrary to what I would think) succeeds even if the path is a directory. Is there an easy way to check if the returned_file stream is a directory instead of a file?

A: 

Can you check if the path points to a directory before you call fopen?

Wevah
(Maybe this should have been a comment.)
Wevah
of course I could, but that is basically what I'm asking, how would I check that?
Silmaril89
Maybe I wasn't clear on this, but I can't just check the path by seeing if a '/' is at the end to tell if it is a directory, because it isn't a requirement for a '/' to be at the end for it to be a directory
Silmaril89
No, that would be racy.
Andrew Medico
One of the two recommending fstat is a better choice. (I guess I'm so over-Cocoa'd that I've pushed some of the vanilla C stuff aside…)
Wevah
+4  A: 

you can use fstat on the file descriptor returned by fopen.

Edit: Here's and example program:

#include <sys/stat.h>
#include <stdio.h>

void printISDir( FILE* fp, char const * name ) {
  int fdes = fileno(fp) ;
  struct stat fileInfo ;
  fstat(fdes, &fileInfo ) ;
  if ( S_ISDIR(fileInfo.st_mode ) ) {
    printf("%s: I'm a dir!\n", name ) ;
  } else {
    printf("%s: I'm a file!\n", name ) ;
  }

}

int main( int argc, char** argv ) {
  char const * directoryName = "/etc" ;
  char const * fileName = "/etc/hosts" ;

  FILE* dirFp = fopen(directoryName, "r") ;
  FILE* fileFp = fopen(fileName, "r") ;
  printISDir( dirFp, directoryName ) ;
  printISDir( fileFp, fileName ) ;
  fclose(dirFp) ;
  fclose(fileFp) ;

  return 0 ;
}
Eld
This one's better.
Wevah
A: 

Use stat() on the file name before you open it, or fstat() the file descriptor fileno(returned_file).

Richard Pennington
I tried using stat and it returns a struct stat, now using that structure how do I determine if it is a directory?
Silmaril89
Don't use stat, use fstat. You always need to check after you opened it to avoid the race condition where it was a file when you checked it, but was deleted and turned into a directory before your open completed.
janm
+4  A: 

Elaborating on the other answers, you can call fstat on the returned file descriptor and check the st_mode for the S_IFDIR bit. The S_ISDIR helper macro is helpful:

  #include <sys/stat.h>

...

  FILE* f = fopen(path, "r");

  struct stat buf;
  if (fstat(fileno(f), &buf) == -1) {
    perror("fstat");
  } else {
    if (S_ISDIR(buf.st_mode)) {
      printf("is directory\n");
    } else {
      printf("not directory\n");
    }
  }
allenporter
S_ISDIR(buf.st_mode) from <sys/stat.h> can also be used
DanM