fixed code to determine file inode - should work now
[reactos.git] / posix / lib / psxdll / dirent / readdir.c
1 /* $Id: readdir.c,v 1.5 2002/03/21 22:41:20 hyperion Exp $
2 */
3 /*
4 * COPYRIGHT: See COPYING in the top level directory
5 * PROJECT: ReactOS POSIX+ Subsystem
6 * FILE: subsys/psx/lib/psxdll/dirent/readdir.c
7 * PURPOSE: Read directory
8 * PROGRAMMER: KJK::Hyperion <noog@libero.it>
9 * UPDATE HISTORY:
10 * 27/01/2002: Created
11 * 13/02/2002: KJK::Hyperion: modified to use file descriptors
12 */
13
14 #include <sys/types.h>
15 #include <fcntl.h>
16 #include <stdlib.h>
17 #include <stddef.h>
18 #include <dirent.h>
19 #include <psx/dirent.h>
20 #include <psx/debug.h>
21 #include <psx/errno.h>
22 #include <psx/safeobj.h>
23 #include <ddk/ntddk.h>
24
25 struct dirent *readdir(DIR *dirp)
26 {
27 struct _Wdirent *lpwdReturn;
28 struct __internal_DIR *pidData;
29 ANSI_STRING strFileName;
30 UNICODE_STRING wstrFileName;
31 NTSTATUS nErrCode;
32
33 /* call Unicode function */
34 lpwdReturn = _Wreaddir(dirp);
35
36 /* failure */
37 if(lpwdReturn == 0)
38 return (0);
39
40 /* get the internal data object */
41 pidData = ((struct __internal_DIR *)dirp);
42
43 /* create NT Unicode string from the Unicode dirent's buffer */
44 RtlInitUnicodeString(&wstrFileName, pidData->ent.de_unicode.d_name);
45
46 /* HACK: make the ANSI string point to the same buffer where the Unicode string is stored */
47 strFileName.Buffer = (PCSZ)&pidData->info.FileName[0];
48 strFileName.Length = 0;
49 strFileName.MaximumLength = MAX_PATH;
50
51 /* convert the filename to ANSI */
52 nErrCode = RtlUnicodeStringToAnsiString(&strFileName, &wstrFileName, FALSE);
53
54 /* failure */
55 if(!NT_SUCCESS(nErrCode))
56 {
57 errno = __status_to_errno(nErrCode);
58 return (0);
59 }
60
61 /* make the ANSI dirent filename point to the ANSI buffer */
62 pidData->ent.de_ansi.d_name = strFileName.Buffer;
63
64 /* null-terminate the ANSI name */
65 pidData->ent.de_ansi.d_name[strFileName.Length] = 0;
66
67 /* success */
68 return (&(pidData->ent.de_ansi));
69 }
70
71 int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
72 {
73 errno = ENOSYS;
74 return (0);
75 }
76
77 struct _Wdirent *_Wreaddir(DIR *dirp)
78 {
79 HANDLE hFile;
80 HANDLE hDir;
81 OBJECT_ATTRIBUTES oaFileAttribs;
82 UNICODE_STRING wstrFileName;
83 FILE_INTERNAL_INFORMATION fiiInfo;
84 IO_STATUS_BLOCK isbStatus;
85 NTSTATUS nErrCode;
86 struct __internal_DIR *pidData;
87
88 /* check the "magic" signature */
89 if(!__safeobj_validate(dirp, __IDIR_MAGIC))
90 {
91 errno = EINVAL;
92 return (0);
93 }
94
95 /* get internal data */
96 pidData = (struct __internal_DIR *)dirp;
97
98 /* get handle */
99 hDir = (HANDLE)fcntl(pidData->fildes, F_GETFH);
100
101 /* failure */
102 if(((int)hDir) == -1)
103 return (0);
104
105 /* read next directory entry */
106 nErrCode = NtQueryDirectoryFile
107 (
108 hDir,
109 NULL,
110 NULL,
111 NULL,
112 &isbStatus,
113 (PVOID)&pidData->info,
114 sizeof(pidData->info) + sizeof(WCHAR) * (MAX_PATH - 1),
115 FileDirectoryInformation,
116 TRUE,
117 NULL,
118 FALSE
119 );
120
121 /* failure or EOF */
122 if(!NT_SUCCESS(nErrCode))
123 {
124 if(nErrCode == (NTSTATUS)STATUS_NO_MORE_FILES)
125 return (0);
126 else
127 {
128 ERR("NtQueryDirectoryFile() failed with status 0x%08X", nErrCode);
129 errno = __status_to_errno(nErrCode);
130 return (0);
131 }
132 }
133
134 /* null-terminate the filename, just in case */
135 pidData->info.FileName[pidData->info.FileNameLength / sizeof(WCHAR)] = 0;
136
137 INFO("this entry: %ls", pidData->info.FileName);
138
139 /* file inodes are not returned by NtQueryDirectoryFile, we have to open every file */
140 /* set file's object attributes */
141 wstrFileName.Length = pidData->info.FileNameLength;
142 wstrFileName.MaximumLength = sizeof(WCHAR) * MAX_PATH;
143 wstrFileName.Buffer = &pidData->info.FileName[0];
144
145 oaFileAttribs.Length = sizeof(OBJECT_ATTRIBUTES);
146 oaFileAttribs.RootDirectory = hDir;
147 oaFileAttribs.ObjectName = &wstrFileName;
148 oaFileAttribs.Attributes = 0;
149 oaFileAttribs.SecurityDescriptor = NULL;
150 oaFileAttribs.SecurityQualityOfService = NULL;
151
152 /* open the file */
153 nErrCode = NtOpenFile
154 (
155 &hFile,
156 FILE_READ_ATTRIBUTES | SYNCHRONIZE,
157 &oaFileAttribs,
158 &isbStatus,
159 0,
160 FILE_SYNCHRONOUS_IO_NONALERT
161 );
162
163 /* failure */
164 if(!NT_SUCCESS(nErrCode))
165 {
166 ERR("NtOpenFile() failed with status %#X", nErrCode);
167 errno = __status_to_errno(nErrCode);
168 return (0);
169 }
170
171 /* get the internal information for the file */
172 nErrCode = NtQueryInformationFile
173 (
174 hFile,
175 &isbStatus,
176 &fiiInfo,
177 sizeof(FILE_INTERNAL_INFORMATION),
178 FileInternalInformation
179 );
180
181 /* close the handle (not needed anymore) */
182 NtClose(hFile);
183
184 /* failure */
185 if(!NT_SUCCESS(nErrCode))
186 {
187 ERR("NtQueryInformationFile() failed with status %#X", nErrCode);
188 errno = __status_to_errno(nErrCode);
189 return (0);
190 }
191
192 /* return file inode */
193 pidData->ent.de_unicode.d_ino = (ino_t)fiiInfo.IndexNumber.QuadPart;
194
195 /* return file name */
196 pidData->ent.de_unicode.d_name = &pidData->info.FileName[0];
197
198 /* success */
199 return &(pidData->ent.de_unicode);
200 }
201
202 int _Wreaddir_r(DIR *dirp, struct _Wdirent *entry, struct _Wdirent **result)
203 {
204 errno = ENOSYS;
205 return (0);
206 }
207
208 /* EOF */
209