[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: dirfd on mingw
From: |
Bruno Haible |
Subject: |
Re: dirfd on mingw |
Date: |
Fri, 29 Apr 2011 00:10:49 +0200 |
User-agent: |
KMail/1.9.9 |
Eric Blake wrote:
> what about my idea of
> starting to associate DIR* with directory fds, for the sake of dirfd?
OK, you want to implement dirfd for native Windows? There are two issues:
1) Use a fake fd without a HANDLE, or use a real HANDLE?
2) How to associate the fd with with a DIR structure?
Ad 1): It is possible to open a HANDLE to a directory, see
<http://msdn.microsoft.com/en-us/library/aa365258%28v=vs.85%29.aspx>
<http://msdn.microsoft.com/en-us/library/aa363858%28v=vs.85%29.aspx>
GetFileType of such a handle return FILE_TYPE_DISK.
Since fstat() supports only handles of type FILE_TYPE_DISK, FILE_TYPE_CHAR,
FILE_TYPE_PIPE, this means fstat() works on such a handle.
The attached program below has been tested on Windows XP (even with an
unprivileged user account).
But an fd with a fake handle (INVALID_HANDLE_VALUE) is possible as well;
it requires a bit more code in fstat() then.
In either case, that fd is not helpful for openat() purposes.
Ad 2): You can wrap the DIR structure so that the gnulib defined DIR is a
wrapper around the original DIR:
struct { int fd; DIR *real_d; }
Then opendir, readdir, closedir, rewinddir need to be overridden.
Or you can make a mapping DIR * -> int , through a simple association list.
(There won't be many DIR * objects open on average.)
For which kinds of operations would you need an int -> DIR * mapping?
Bruno
===============================================================================
#include <stdio.h>
#include <windows.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
int main ()
{
HANDLE h = CreateFile ("c:\\cygwin", GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
printf ("h=%p\n", h);
int type = GetFileType (h);
printf ("%s\n", type == FILE_TYPE_DISK ? "DISK" : type == FILE_TYPE_UNKNOWN ?
"UNKNOWN" : "?");
int fd = _open_osfhandle (h, O_RDWR | O_BINARY);
struct stat statbuf;
int ret = fstat (fd, &statbuf);
printf ("ret = %d\n", ret);
if (ret >= 0)
{
printf ("st_dev = %d\n", statbuf.st_dev);
printf ("st_ino = %d\n", statbuf.st_ino);
printf ("st_mode = 0%3o\n", statbuf.st_mode);
printf ("st_nlink = %d\n", statbuf.st_nlink);
printf ("st_uid = %d\n", statbuf.st_uid);
printf ("st_gid = %d\n", statbuf.st_gid);
printf ("st_rdev = %d\n", statbuf.st_rdev);
printf ("st_size = %d\n", statbuf.st_size);
printf ("st_atime = %s\n", ctime (&statbuf.st_atime));
printf ("st_mtime = %s\n", ctime (&statbuf.st_mtime));
printf ("st_ctime = %s\n", ctime (&statbuf.st_ctime));
}
char byte[1];
SetLastError(0);
ret = read (fd, byte, 1);
printf ("read -> %d %d %d\n", ret, errno, GetLastError()); /* -> -1 EINVAL
ERROR_INVALID_FUNCTION */
return 0;
}
===============================================================================
--
In memoriam Heinz Droßel <http://en.wikipedia.org/wiki/Heinz_Drossel>