Bump to m4 1.4.19
[platform/upstream/m4.git] / lib / readdir.c
1 /* Read the next entry of a directory.
2    Copyright (C) 2011-2021 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16
17 #include <config.h>
18
19 /* Specification.  */
20 #include <dirent.h>
21
22 #include <errno.h>
23 #include <stddef.h>
24
25 #include "dirent-private.h"
26
27 /* Don't assume that UNICODE is not defined.  */
28 #undef FindNextFile
29 #define FindNextFile FindNextFileA
30
31 struct dirent *
32 readdir (DIR *dirp)
33 {
34   char type;
35   struct dirent *result;
36
37   /* There is no need to add code to produce entries for "." and "..".
38      According to the POSIX:2008 section "4.12 Pathname Resolution"
39      <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html>
40      "." and ".." are syntactic entities.
41      POSIX also says:
42        "If entries for dot or dot-dot exist, one entry shall be returned
43         for dot and one entry shall be returned for dot-dot; otherwise,
44         they shall not be returned."  */
45
46   switch (dirp->status)
47     {
48     case -2:
49       /* End of directory already reached.  */
50       return NULL;
51     case -1:
52       break;
53     case 0:
54       if (!FindNextFile (dirp->current, &dirp->entry))
55         {
56           switch (GetLastError ())
57             {
58             case ERROR_NO_MORE_FILES:
59               dirp->status = -2;
60               return NULL;
61             default:
62               errno = EIO;
63               return NULL;
64             }
65         }
66       break;
67     default:
68       errno = dirp->status;
69       return NULL;
70     }
71
72   dirp->status = 0;
73
74   if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
75     type = DT_DIR;
76   else if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
77     type = DT_LNK;
78   else if ((dirp->entry.dwFileAttributes
79             & ~(FILE_ATTRIBUTE_READONLY
80                 | FILE_ATTRIBUTE_HIDDEN
81                 | FILE_ATTRIBUTE_SYSTEM
82                 | FILE_ATTRIBUTE_ARCHIVE
83                 | FILE_ATTRIBUTE_NORMAL
84                 | FILE_ATTRIBUTE_TEMPORARY
85                 | FILE_ATTRIBUTE_SPARSE_FILE
86                 | FILE_ATTRIBUTE_COMPRESSED
87                 | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
88                 | FILE_ATTRIBUTE_ENCRYPTED)) == 0)
89     /* Devices like COM1, LPT1, NUL would also have the attributes 0x20 but
90        they cannot occur here.  */
91     type = DT_REG;
92   else
93     type = DT_UNKNOWN;
94
95   /* Reuse the memory of dirp->entry for the result.  */
96   result =
97     (struct dirent *)
98     ((char *) dirp->entry.cFileName - offsetof (struct dirent, d_name[0]));
99   result->d_type = type;
100
101   return result;
102 }