--- Dmitry Timoshkov dmitry@baikal.ru wrote:
Looks better, except that according to MSDN "_S_IFREG bit is set if path specifies an ordinary file or a device", so you need to add a check for FILE_TYPE_DISK.
Interestingly, you can't _open the root directory of a drive in Windows; it fails with ENOENT. You also can't _open a directory; it fails with ENOACCES. The _S_IFDIR flag never appears to be set, even if you get a handle to a directory.
The attached test program shows the following output under WinXP: file c: flags: couldn't open, errno is 14 file c:\ flags: couldn't open, errno is 2 file c:\boot.ini flags: _S_IFREG file c:\windows flags: couldn't open, errno is 13 directory c: flags: _S_IFREG directory c:\ flags: _S_IFREG directory c:\windows flags: _S_IFREG read pipe flags: _S_IFIFO write pipe flags: _S_IFIFO
I wasn't really interested in getting this 100% correct; the st_mode set before was always 0, so it can't be that critical. Mostly I was tired of fixme's when running MinGW's gcc.exe under wine. So, I'll resubmit a modified patch that isn't entirely correct but is a little closer, anyway :)
--Juan
__________________________________ Do you Yahoo!? Take Yahoo! Mail with you! Get it on your mobile phone. http://mobile.yahoo.com/maildemo
#include <errno.h> #include <fcntl.h> #include <stdint.h> #include <stdio.h> #include <sys/stat.h> #include <windows.h>
static int firstFlag = 1;
static printFlag(const char *flag) { if (!firstFlag) printf("| "); printf(flag); firstFlag = 0; }
static void getFDMode(int fd) { struct _stat st;
firstFlag = 1; if (_fstat(fd, &st) == 0) { if (st.st_mode & _S_IFCHR) printFlag("_S_IFCHR"); if (st.st_mode & _S_IFREG) printFlag("_S_IFREG"); if (st.st_mode & _S_IFDIR) printFlag("_S_IFDIR"); if (st.st_mode & _S_IFIFO) printFlag("_S_IFIFO"); } putchar('\n'); }
static void getFileMode(const char *file) { int fd = _open(file, _O_RDWR, _S_IREAD | _S_IWRITE);
printf("file %s flags: ", file); if (fd == -1) fd = _open(file, _O_RDONLY, _S_IREAD); if (fd != -1) { getFDMode(fd); _close(fd); } else printf("couldn't open, errno is %d\n", errno); }
static void getPipeMode(void) { int fds[2];
if (_pipe(fds, 256, O_BINARY) == 0) { printf("read pipe flags: "); getFDMode(fds[0]); printf("write pipe flags: "); getFDMode(fds[1]); _close(fds[0]); _close(fds[1]); } }
static void getDirectoryMode(const char *directory) { HANDLE h = CreateFileA(directory, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
printf("directory %s flags: ", directory); if (h != INVALID_HANDLE_VALUE) { int fd = _open_osfhandle((intptr_t)h, _O_RDONLY);
if (fd != -1) { getFDMode(fd); _close(fd); } CloseHandle(h); } else printf("failed with GetLastError() = %ld\n", GetLastError()); }
int main(void) { /* expect errno is 13 (EACCES), can't open a device */ getFileMode("c:"); /* expect errno is 2 (ENOENT), can't open a drive */ getFileMode("c:\"); getFileMode("c:\boot.ini"); /* expect errno is 13 (EACCES), can't open a directory */ getFileMode("c:\windows"); getDirectoryMode("c:"); getDirectoryMode("c:\"); getDirectoryMode("c:\windows"); getPipeMode(); }