summaryrefslogtreecommitdiffstats
path: root/private/crt32/lowio/fstat.c
blob: dcb013203847e8881ea1e702b63b180b013b950a (plain) (blame)
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_ */