Add d_type to our Windows dirent emulation.
authorThomas Munro <tmunro@postgresql.org>
Mon, 7 Sep 2020 11:18:22 +0000 (23:18 +1200)
committerThomas Munro <tmunro@postgresql.org>
Mon, 7 Sep 2020 11:38:19 +0000 (23:38 +1200)
This allows us to skip some stat calls, by extending commit 861c6e7c to
cover Windows systems.

Author: Juan José Santamaría Flecha <juanjo.santamaria@gmail.com>
Reviewed-by: Alvaro Herrera <alvherre@2ndquadrant.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Magnus Hagander <magnus@hagander.net>
Reviewed-by: Thomas Munro <thomas.munro@gmail.com>
Discussion: https://postgr.es/m/CA%2BhUKG%2BFzxupGGN4GpUdbzZN%2Btn6FQPHo8w0Q%2BAPH5Wz8RG%2Bww%40mail.gmail.com

src/include/port/win32_msvc/dirent.h
src/port/dirent.c

index 9fabdf332b2c6e33b1043c14617cbf2f07372ab5..62799db0014169a8125119771950896a918f8649 100644 (file)
@@ -10,6 +10,7 @@ struct dirent
 {
    long        d_ino;
    unsigned short d_reclen;
+   unsigned char d_type;
    unsigned short d_namlen;
    char        d_name[MAX_PATH];
 };
@@ -20,4 +21,14 @@ DIR         *opendir(const char *);
 struct dirent *readdir(DIR *);
 int            closedir(DIR *);
 
+/* File types for 'd_type'.  */
+#define DT_UNKNOWN     0
+#define DT_FIFO        1
+#define DT_CHR         2
+#define DT_DIR         4
+#define DT_BLK         6
+#define DT_REG         8
+#define DT_LNK         10
+#define DT_SOCK        12
+#define DT_WHT         14
 #endif
index b264484fca246ae672e17925bf8620ce1b718288..70a444f9a53f9565388584cf01faea904411dd5b 100644 (file)
@@ -69,6 +69,7 @@ opendir(const char *dirname)
    d->handle = INVALID_HANDLE_VALUE;
    d->ret.d_ino = 0;           /* no inodes on win32 */
    d->ret.d_reclen = 0;        /* not used on win32 */
+   d->ret.d_type = DT_UNKNOWN;
 
    return d;
 }
@@ -105,6 +106,15 @@ readdir(DIR *d)
    }
    strcpy(d->ret.d_name, fd.cFileName);    /* Both strings are MAX_PATH long */
    d->ret.d_namlen = strlen(d->ret.d_name);
+   /* The only identified types are: directory, regular file or symbolic link */
+   if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
+       d->ret.d_type = DT_DIR;
+   /* For reparse points dwReserved0 field will contain the ReparseTag */
+   else if ((fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0 &&
+            (fd.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT))
+       d->ret.d_type = DT_LNK;
+   else
+       d->ret.d_type = DT_REG;
 
    return &d->ret;
 }