开发者

Reading a directory

I'm trying to solve exercise from K&R; it's about reading directories. This task is system dependent because it uses system calls. In the book example authors say that their example is written for Version 7 and System V UNIX systems and that they used the directory information in the header < sys/dir.h>, which looks like this:

#ifndef DIRSIZ
#define DIRSIZ 14
#endif
struct direct {    /* directory entry */
    ino_t d_ino;           /* inode number */
    char d_name[DIRSIZ];   /* 开发者_如何学Golong name does not have '\0' */
};

On this system they use 'struct direct' combined with 'read' function to retrieve a directory entry, which consist of file name and inode number.

.....
struct direct dirbuf;    /* local directory structure */
while(read(dp->fd, (char *) &dirbuf, sizeof(dirbuf)
               == sizeof(dirbuf) {
    .....
}
.....

I suppose this works fine on UNIX and Linux systems, but what I want to do is modify this so it works on Windows XP.

Is there some structure in Windows like 'struct direct' so I can use it with 'read' function and if there is what is the header name where it is defined?

Or maybe Windows requires completely different approach?


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


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.


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);
}


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜