msvcrt: set mode bits in _fstati64

Juan Lang juan_lang at yahoo.com
Sun Dec 5 11:29:42 CST 2004


--- Dmitry Timoshkov <dmitry at 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 
-------------- next part --------------
#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();
}


More information about the wine-devel mailing list