1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
|
/***
*fstat.c - OS/2 return file status info
*
* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines fstat() - return file status info
*
*Revision History:
* 03-??-84 RLB Module created
* 05-??-84 DCW Added register variables
* 05-19-86 SKS Ported to OS/2
* 05-21-87 SKS Cleaned up declarations and include files
* 11-01-87 JCR Multi-thread support
* 12-11-87 JCR Added "_LOAD_DS" to declaration
* 05-25-88 PHG Merged DLL and normal version
* 10-03-88 GJF Adapted for new DOSCALLS.H, DOSTYPES.H.
* 10-04-88 JCR 386: Removed 'far' keyword
* 10-10-88 GJF Made API names match DOSCALLS.H
* 11-07-88 GJF Cleanup, now specific to 386
* 04-13-89 JCR New syscall interface
* 05-23-89 PHG Added mask to ignore network bit when testing handle
* type
* 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention
* 03-12-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
* <cruntime.h>, removed #include <register.h> and fixed
* the copyright. Also, cleaned up the formatting a bit.
* 04-04-90 GJF Removed #include <dos.h>.
* 07-24-90 SBM Removed '32' from API names
* 08-13-90 SBM Compiles cleanly with -W3
* 09-28-90 GJF New-style function declarator.
* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
* 01-21-91 GJF ANSI naming.
* 04-26-91 SRW Implemented fstat for _WIN32_ and removed level 3
* warnings.
* 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
* 05-27-92 SKS File Creation and File Last Access timestamps may be 0
* on some file systems (e.g. FAT) in which case the
* File Last Write time should be used instead.
* 06-04-92 SKS Changed comment that used to say "This is a BUG!"
* to explain that this value cannot be computed on
* OS/2 or NT. Only MS-DOS provides this functionality.
* The drive number is not valid for UNC names.
* 06-25-92 GJF Use GetFileInformationByHandle API, also cleaned up
* formatting of Win32 verson [_WIN32_].
* 08-18-92 SKS Add a call to FileTimeToLocalFileTime
* as a temporary fix until _dtoxtime takes UTC
* 08-20-92 GJF Merged two changes above.
* 12-16-92 GJF Win32 GetFileInformationByHandle API doesn't like
* device or pipe handles. Use _S_IFIFO for pipes.
* 04-06-93 GJF Made computation of file times consistent with _stat().
*
*******************************************************************************/
#include <cruntime.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <msdos.h>
#include <dostypes.h>
#include <io.h>
#include <internal.h>
#include <stddef.h>
#include <oscalls.h>
#include <stdio.h>
#include <os2dll.h>
#ifndef _CRUISER_
#include <time.h>
#endif
#define IO_DEVNBR 0x3f
/***
*int _fstat(fildes, buf) - fills supplied buffer with status info
*
*Purpose:
* Fills the supplied buffer with status information on the
* file represented by the specified file designator.
* WARNING: the dev/rdev fields are zero for files. This is
* incompatible with DOS 3 version of this routine.
*
*Entry:
* int fildes - file descriptor
* struct stat *buf - buffer to store result in
*
*Exit:
* fills in buffer pointed to by buf
* returns 0 if successful
* returns -1 and sets errno if unsuccessful
*
*Exceptions:
*
*******************************************************************************/
#ifdef _CRUISER_
int _CRTAPI1 _fstat (
REG2 int fildes,
REG1 struct _stat *buf
)
{
long cpos;
int isdev; /* 0 for a file, 1 for a device */
int retval = 0; /* assume good return */
if (fildes < 0 || fildes >= _nfile) {
errno = EBADF;
return(-1);
}
/* Lock the file */
_lock_fh(fildes);
/* Issue the get-device-info call. */
{
int descrip; /* device descriptor word */
if (DOSQUERYHTYPE(fildes, (unsigned *)&isdev, (unsigned *)&descrip))
{
errno = EBADF;
retval = -1; /* error from DOS call - bad file designator */
goto done; /* join common return code */
}
/* set the common fields */
buf->st_ino = buf->st_uid = buf->st_gid = buf->st_mode = 0;
buf->st_nlink = 1;
buf->st_mode |= (_osfile[fildes] & FRDONLY)
? (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6))
: ((_S_IREAD|_S_IWRITE) +
((_S_IREAD|_S_IWRITE) >> 3)
+ ((_S_IREAD|_S_IWRITE) >> 6));
/* set file date fields - NOTE for code below, it should be
* remembered that calls to QFILEINFO cannot fail since the file
* handle is known to be good since we got by the QHANDTYPE call.
*/
{
FILESTATUS fs;
(void)DOSQUERYFILEINFO(fildes, 1, (FILESTATUS *) & fs, sizeof(fs));
buf->st_mtime = XTIME(fs.fdateLastWrite, fs.ftimeLastWrite);
if ( _DATECAST(fs.fdateLastAccess) || _TIMECAST(fs.ftimeLastAccess) )
buf->st_atime = XTIME(fs.fdateLastAccess, fs.ftimeLastAccess);
else
buf->st_atime = buf->st_mtime ;
if ( _DATECAST(fs.fdateCreation) || _TIMECAST(fs.ftimeCreation) )
buf->st_ctime = XTIME(fs.fdateCreation, fs.ftimeCreation);
else
buf->st_ctime = buf->st_mtime ;
buf->st_mtime = XTIME(fs.fdateLastWrite, fs.ftimeLastWrite);
}
/* check for device or file */
if (isdev & 0xFF) {
/* file designator refers to a device - set file size to 0 */
buf->st_size = 0;
buf->st_mode |= _S_IFCHR;
buf->st_rdev = buf->st_dev = (_dev_t)fildes;
}
else {
/* file designator refers to a file - set actual file size */
cpos = _lseek_lk(fildes, 0L, 1);
buf->st_size = _lseek_lk(fildes, 0L, 2);
_lseek_lk(fildes, cpos, 0);
buf->st_mode |= _S_IFREG;
/*
* On DOS, this field contains the drive number, but
* the drive number is not available on this platform.
* Also, for UNC network names, there is no drive number.
*/
buf->st_rdev = buf->st_dev = 0;
}
/* Common return code */
done:
_unlock_fh(fildes);
return(retval);
}
#else /* ndef _CRUISER_ */
#ifdef _WIN32_
int _CRTAPI1 _fstat (
int fildes,
struct _stat *buf
)
{
int isdev; /* 0 for a file, 1 for a device */
int retval = 0; /* assume good return */
BY_HANDLE_FILE_INFORMATION bhfi;
SYSTEMTIME SystemTime;
if ( (unsigned)fildes >= (unsigned)_nhandle ) {
errno = EBADF;
return(-1);
}
/* Lock the file */
_lock_fh(fildes);
/* Find out what kind of handle underlies filedes
*/
isdev = GetFileType((HANDLE)_osfhnd[fildes]) & ~FILE_TYPE_REMOTE;
if ( isdev != FILE_TYPE_DISK ) {
/* not a disk file. probably a device or pipe
*/
if ( (isdev == FILE_TYPE_CHAR) || (isdev == FILE_TYPE_PIPE) ) {
/* treat pipes and devices similarly. no further info is
* available from any API, so set the fields as reasonably
* as possible and return.
*/
if ( isdev == FILE_TYPE_CHAR )
buf->st_mode = _S_IFCHR;
else
buf->st_mode = _S_IFIFO;
buf->st_rdev = buf->st_dev = (_dev_t)fildes;
buf->st_nlink = 1;
buf->st_uid = buf->st_gid = buf->st_ino = 0;
buf->st_atime = buf->st_mtime = buf->st_ctime = buf->st_size
= 0;
goto done;
}
else if ( isdev == FILE_TYPE_UNKNOWN ) {
errno = EBADF;
retval = -1;
goto done; /* join common return code */
}
else {
/* according to the documentation, this cannot happen, but
* play it safe anyway.
*/
_dosmaperr(GetLastError());
retval = -1;
goto done;
}
}
/* set the common fields
*/
buf->st_ino = buf->st_uid = buf->st_gid = buf->st_mode = 0;
buf->st_nlink = 1;
/* use the file handle to get all the info about the file
*/
if ( !GetFileInformationByHandle((HANDLE)_osfhnd[fildes], &bhfi) ) {
_dosmaperr(GetLastError());
retval = -1;
goto done;
}
if ( bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY )
buf->st_mode |= (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6));
else
buf->st_mode |= ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3)
+ ((_S_IREAD|_S_IWRITE) >> 6));
/* set file date fields
*/
FileTimeToSystemTime( &(bhfi.ftLastWriteTime), &SystemTime );
buf->st_mtime = __gmtotime_t(SystemTime.wYear,
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond
);
if ( bhfi.ftLastAccessTime.dwLowDateTime || bhfi.ftLastAccessTime.
dwHighDateTime ) {
FileTimeToSystemTime( &(bhfi.ftLastAccessTime), &SystemTime );
buf->st_atime = __gmtotime_t(SystemTime.wYear,
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond
);
}
else
buf->st_atime = buf->st_mtime;
if ( bhfi.ftCreationTime.dwLowDateTime || bhfi.ftCreationTime.
dwHighDateTime ) {
FileTimeToSystemTime( &(bhfi.ftCreationTime), &SystemTime );
buf->st_ctime = __gmtotime_t(SystemTime.wYear,
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond
);
}
else
buf->st_ctime = buf->st_mtime;
buf->st_size = bhfi.nFileSizeLow;
buf->st_mode |= _S_IFREG;
/* On DOS, this field contains the drive number, but
* the drive number is not available on this platform.
* Also, for UNC network names, there is no drive number.
*/
buf->st_rdev = buf->st_dev = 0;
/* Common return code */
done:
_unlock_fh(fildes);
return(retval);
}
#else /* ndef _WIN32_ */
#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
#endif /* _WIN32_ */
#endif /* _CRUISER_ */
|