tags:

views:

170

answers:

4
+2  A: 

There's nothing like that in windows. If you want to enumerate a directory in Windows, you must use the FindFirstFile/FindNextFile API.

Billy ONeal
Or use cygwin/mingw.
pajton
Somehow I don't think making a Windows application dependent on a Unix Emulation library is a good design choice for new code. Furthermore, MinGW does nothing to fix this problem. You can't open directory files with MinGW. Cygwin might support some kinds of things like this but MinGW does not.
Billy ONeal
pajton
Also, thanks for pointing out that MinGW wouldn't work here, I've edited my answer to correct that one.
pajton
Thanks for that links, I'm gonna try something with FindFirstFile/FindNextFile functions probably.
paleman
+1  A: 

Yes, this works on Linux/Unix only. However if you are just playing around you may use Cygwin to build programs on Windows that use this Unix API.

pajton
No I don't want to use Cygwin,I forgot to write that when I was writing first post, sorry.
paleman
+1  A: 

boost::filesystem::directory_iterator provides a portable equivalent of Windows FindFirstFile/FindNextFile API and POSIX readdir_r() API. See this tutorial.

Note that this is C++ not plain C.

cheers, AR

Alain Rist
I want pure C, but thanks.
paleman
+1  A: 

It is interesting to note that you are using K&R 1st Edition, from 1978, and not the second edition. The second edition has different structures, etc, at that point in the book.

That code from the first edition does not work on many Unix-like systems any more. There are very few Unix machines left with file systems that restrict file names to the 14-character limit, and that code only works on those systems. Specifically, it does not work on MacOS X (10.6.2) or Solaris (10) or Linux (SuSE Linux Enterprise Edition 10, kernel 2.6.16.60-0.21-smp). With the test code shown below, the result is:

read failed: (21: Is a directory)

Current editions of POSIX explicitly permit the implementation to limit what you can do with a file descriptor opened on a directory. Basically, it can be used in the 'fchdir()' system calls and maybe a few relatives, but that is all.

To read the contents of the directory, you have to use the opendir() family of functions, and then readdir() etc. The second edition of K&R goes on to use these system calls instead of raw open() and read() etc.

All-in-all, it is not dreadfully surprising that code from over 30 years ago doesn't quite work the same as it used to.


On Windows, you can either use the POSIX sub-system or an emulation of that such as Cygwin or MingW, and in either case you will need to use the opendir() and readdir() family of function calls, not direct open() and read() on the directory file descriptor.

Or you can use the native Windows API that BillyONeal references, FindFirstFile and relatives.


Test code:

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>

int main()
{
    int fd = open(".", O_RDONLY);
    if (fd != -1)
    {
        char buffer[256];
        ssize_t n = read(fd, buffer, sizeof(buffer));
        if (n < 0)
        {
            int errnum = errno;
            printf("read failed: (%d: %s)\n", errnum, strerror(errnum));
        }
        else
            printf("read OK: %d bytes (%s)\n", (int)n, buffer);
        close(fd);
    }
    return(0);
}
Jonathan Leffler
I was reading that book online once and it was written "2.nd edition" next to the name, I don't have it in paper form yet so I don't know
paleman
Interesting - did what you were looking at use prototypes? If so, it was 2nd Edn rather than 1st. But, in my copy of the 1st Edn (p170), there is '`#define DIRSIZ 14 / struct direct { ino_t d_ino; char d_name[DIRSIZ]; };`' (and no mention of `opendir()` etc). In my copy of the 2nd Edn (marked 'Based on Draft Proposed ANSI C', dated 1988, 1st printing) on p180, there is '`#define NAME_MAX 14 / typedef struct { long ino; char name[NAME_MAX+1]; } Dirent;`' (and a discussion of `opendir()` et al. Your code looks closer to 1st Edn than second edition to me - hence my commentary.
Jonathan Leffler
Jonathan Leffler
I just looked and it has both."#define NAME_MAX 14 / typedef struct { long ino; char name[NAME_MAX+1]; } Dirent;" would be portable structure and it has comment /* portable structure entry */, it also has "#define DIRSIZ 14 / struct direct { ino_t d_ino; char d_name[DIRSIZ]; };" which would be directory entry for that specific system.In the example authors also have written opendir, readdir and closedir.Only their readdir returns 'Dirent *' instead of 'struct dirent *'.In the body of readdir they copy information from 'struct direct' to 'static Dirent' and return address od 'Dirent'.
paleman
I don't have and did not read "The C Answer Book".Only online URL I know of doesn't exist anymore, they decided to take it of, probably because of copyrights, sorry.
paleman