summaryrefslogtreecommitdiffstats
path: root/private/crt32/lowio/fstat.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/lowio/fstat.c')
-rw-r--r--private/crt32/lowio/fstat.c352
1 files changed, 352 insertions, 0 deletions
diff --git a/private/crt32/lowio/fstat.c b/private/crt32/lowio/fstat.c
new file mode 100644
index 000000000..dcb013203
--- /dev/null
+++ b/private/crt32/lowio/fstat.c
@@ -0,0 +1,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_ */