summaryrefslogtreecommitdiffstats
path: root/private/crt32/dos/stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/dos/stat.c')
-rw-r--r--private/crt32/dos/stat.c397
1 files changed, 397 insertions, 0 deletions
diff --git a/private/crt32/dos/stat.c b/private/crt32/dos/stat.c
new file mode 100644
index 000000000..976d96009
--- /dev/null
+++ b/private/crt32/dos/stat.c
@@ -0,0 +1,397 @@
+/***
+*stat.c - get file status
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _stat() - get file status
+*
+*Revision History:
+* 03-??-84 RLB Module created
+* 05-??-84 DCW Some cleanup and addition of register variables
+* 05-17-86 SKS Ported to OS/2
+* 11-19-86 SKS Better check for root directory; KANJI support
+* 05-22-87 SKS Cleaned up declarations and include files
+* 11-18-87 SKS Make _dtoxmode a static near procedure
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 12-21-87 WAJ stat no longer uses chdir to figure out if it has been
+* passed a root directory in the MTHREAD case.
+* 01-05-88 WAJ now uses _MAX_PATH (defined in stdlib.h)
+* 06-22-88 SKS find Hidden and System files, not just normal ones
+* 06-22-88 SKS Always use better algorithm to detect root dirs
+* 06-29-88 WAJ When looking for root dir makes sure it exists
+* 09-28-88 JCR Use new 386 dostypes.h structures
+* 10-03-88 JCR 386: Change DOS calls to SYS calls
+* 10-04-88 JCR 386: Removed 'far' keyword
+* 10-10-88 GJF Made API names match DOSCALLS.H
+* 11-24-88 GJF ".cmd" should be considered executable, not ".bat"
+* 01-31-89 JCR _canonic() is now _fullpath() and args reversed
+* 04-12-89 JCR New syscall interace
+* 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention
+* 03-07-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
+* <cruntime.h>, removed #include <register.h> and
+* removed some leftover 16-bit support. Also, fixed
+* the copyright.
+* 04-02-90 GJF Made _ValidDrive() and _dtoxmode() _CALLTYPE1. Removed
+* #include <dos.h>.
+* 07-23-90 SBM Compiles cleanly with -W3 (added/removed appropriate
+* includes), removed '32' from API names
+* 08-10-90 SBM Compiles cleanly with -W3 with new build of compiler
+* 09-03-90 SBM Removed EXT macro
+* 09-27-90 GJF New-style function declarators.
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler
+* 01-18-91 GJF ANSI naming.
+* 01-28-91 GJF Fixed call to DOSFINDFIRST (removed last arg).
+* 02-28-91 SRW Fixed bug in _dtoxtime calls [_WIN32_]
+* 03-05-91 MHL Fixed stat to not use _ValidDrive for stat of root
+* 05-19-92 SKS .BAT is a valid "executable" extension for NT, as
+* well as CMD. Also, 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.
+* 05-29-92 SKS Files with SYSTEM bit set should NOT be marked
+* READ-ONLY; these two attributes are independent.
+* 08-18-92 SKS Add a call to FileTimeToLocalFileTime
+* as a temporary fix until _dtoxtime takes UTC
+* 11-20-92 SKS _doserrno must always be set whenever errno is.
+* 11-30-92 KRS Port _MBCS support from 16-bit tree.
+* 03-29-93 GJF Converted from using _dtoxtime() to __gmtotime_t().
+* 04-07-93 GJF Changed first arg type to const char *.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <ctype.h>
+#include <msdos.h>
+#include <dostypes.h>
+#include <oscalls.h>
+#include <string.h>
+#include <internal.h>
+#include <stdlib.h>
+#include <direct.h>
+#include <mbstring.h>
+
+int _CRTAPI1 _ValidDrive( unsigned drive );
+
+#define ISSLASH(a) ((a) == '\\' || (a) == '/')
+
+/***
+*static unsigned _dtoxmode(attr, name) -
+*
+*Purpose:
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static unsigned short _CRTAPI3 _dtoxmode (
+ int attr,
+ const char *name
+ )
+{
+ REG1 unsigned short uxmode;
+ unsigned dosmode;
+ REG2 const char *p;
+
+ dosmode = attr & 0xff;
+ if ((p = name)[1] == ':')
+ p += 2;
+
+ /* check to see if this is a directory - note we must make a special
+ * check for the root, which DOS thinks is not a directory
+ */
+
+ uxmode = (unsigned short)
+ (((ISSLASH(*p) && !p[1]) || (dosmode & A_D) || !*p)
+ ? _S_IFDIR|_S_IEXEC : _S_IFREG);
+
+ /* If attribute byte does not have read-only bit, it is read-write */
+
+ uxmode |= (dosmode & A_RO) ? _S_IREAD : (_S_IREAD|_S_IWRITE);
+
+ /* see if file appears to be executable - check extension of name */
+
+ if (p = strrchr(name, '.')) {
+ if ( !_stricmp(p, ".exe") ||
+ !_stricmp(p, ".cmd") ||
+#ifndef _CRUISER_
+ !_stricmp(p, ".bat") ||
+#endif
+ !_stricmp(p, ".com") )
+ uxmode |= _S_IEXEC;
+ }
+
+ /* propagate user read/write/execute bits to group/other fields */
+
+ uxmode |= (uxmode & 0700) >> 3;
+ uxmode |= (uxmode & 0700) >> 6;
+
+ return(uxmode);
+}
+
+
+/***
+*int _stat(name, buf) - get file status info
+*
+*Purpose:
+* _stat obtains information about the file and stores it in the structure
+* pointed to by buf.
+*
+*Entry:
+* char *name - pathname of given file
+* struct _stat *buffer - pointer to buffer to store info in
+*
+*Exit:
+* fills in structure pointed to by buffer
+* returns 0 if successful
+* returns -1 and sets errno if unsuccessful
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _stat (
+ REG1 const char *name,
+ REG2 struct _stat *buf
+ )
+{
+ char * path;
+ char pathbuf[ _MAX_PATH ];
+ int drive; /* A: = 1, B: = 2, etc. */
+
+#ifdef _CRUISER_
+ HDIR findhandle = -1; /* any unused handle */
+ struct _FILEFINDBUF findbuf;
+ unsigned findcount = 1; /* Find only 1 match */
+ unsigned long dmap; /* Valid Drive Map (ignored) */
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ HANDLE findhandle;
+ WIN32_FIND_DATA findbuf;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /* Don't allow wildcards to be interpreted by system */
+
+ if (_mbspbrk(name, "?*")) {
+ errno = ENOENT;
+ _doserrno = E_nofile;
+ return(-1);
+ }
+
+ /* Try to get disk from name. If none, get current disk. */
+
+ if (name[1] == ':'){
+ if ( *name && !name[2] ){
+ errno = ENOENT; /* return an error if name is */
+ _doserrno = E_nofile; /* just drive letter then colon */
+ return( -1 );
+ }
+ drive = tolower(*name) - 'a' + 1;
+ }
+#ifdef _CRUISER_
+ else
+ (void)DOSQUERYCURRENTDISK((unsigned long *) &drive,
+ (unsigned long *) &dmap);
+
+ /* Call Find Match File */
+
+ if (DOSFINDFIRST((char *)name, (HDIR *)&findhandle,
+ A_D + A_H + A_S, /* find everything except volume labels */
+ (struct _FILEFINDBUF *) &findbuf, sizeof(findbuf),
+ (unsigned *) &findcount, 1L)) {
+
+ if ( !( _mbspbrk(name, "./\\") &&
+ (path = _fullpath( pathbuf, name, _MAX_PATH )) &&
+ (strlen( path ) == 3) &&
+ _ValidDrive( drive ) ) ) {
+ errno = ENOENT;
+ _doserrno = E_nofile;
+ return( -1 );
+ }
+
+ findbuf.attrFile = A_D;
+ findbuf.cbFile = 0L;
+ _DATECAST(findbuf.fdateLastWrite) = (1 << 5) + 1; /* 1 January 1980 */
+ _TIMECAST(findbuf.ftimeLastWrite) = 0; /* 00:00:00 */
+ _DATECAST(findbuf.fdateLastAccess) =
+ _DATECAST(findbuf.fdateCreation) =
+ _TIMECAST(findbuf.ftimeLastAccess) =
+ _TIMECAST(findbuf.ftimeCreation) = 0;
+ }
+ else
+ DOSFINDCLOSE(findhandle); /* Release Find handle */
+
+ /* Fill in buf */
+
+ buf->st_mode = _dtoxmode(findbuf.attrFile, name);
+ buf->st_nlink = 1;
+ buf->st_size = findbuf.cbFile;
+ buf->st_mtime = XTIME(findbuf.fdateLastWrite, findbuf.ftimeLastWrite);
+
+ /*
+ * If create and access times are 0L, use modification time instead
+ */
+ if( _DATECAST(findbuf.fdateCreation) || _TIMECAST(findbuf.ftimeCreation) )
+ buf->st_ctime = XTIME(findbuf.fdateCreation, findbuf.ftimeCreation);
+ else
+ buf->st_ctime = buf->st_mtime;
+
+ if( _DATECAST(findbuf.fdateLastAccess) || _TIMECAST(findbuf.ftimeLastAccess) )
+ buf->st_atime = XTIME(findbuf.fdateLastAccess, findbuf.ftimeLastAccess);
+ else
+ buf->st_atime = buf->st_mtime;
+
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+ else
+ drive = _getdrive();
+
+ /* Call Find Match File */
+ findhandle = FindFirstFile((char *)name, &findbuf);
+ if ( findhandle == (HANDLE)0xffffffff ) {
+ if ( !( _mbspbrk(name, "./\\") &&
+ (path = _fullpath( pathbuf, name, _MAX_PATH )) &&
+ (strlen( path ) == 3) &&
+ (GetDriveType( path ) > 1) ) ) {
+ errno = ENOENT;
+ _doserrno = E_nofile;
+ return( -1 );
+ }
+
+ findbuf.dwFileAttributes = A_D;
+ findbuf.nFileSizeHigh = 0;
+ findbuf.nFileSizeLow = 0;
+ findbuf.cFileName[0] = '\0';
+
+ buf->st_mtime = __gmtotime_t(80,1,1,0,0,0);
+ buf->st_atime = buf->st_mtime;
+ buf->st_ctime = buf->st_mtime;
+ }
+ else {
+ SYSTEMTIME SystemTime;
+
+ FileTimeToSystemTime(&findbuf.ftLastWriteTime, &SystemTime);
+
+ buf->st_mtime = __gmtotime_t(SystemTime.wYear,
+ SystemTime.wMonth,
+ SystemTime.wDay,
+ SystemTime.wHour,
+ SystemTime.wMinute,
+ SystemTime.wSecond
+ );
+
+ if ( findbuf.ftLastAccessTime.dwLowDateTime ||
+ findbuf.ftLastAccessTime.dwHighDateTime )
+ {
+ FileTimeToSystemTime(&findbuf.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 ( findbuf.ftCreationTime.dwLowDateTime ||
+ findbuf.ftCreationTime.dwHighDateTime )
+ {
+ FileTimeToSystemTime(&findbuf.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 ;
+
+ FindClose(findhandle);
+ }
+
+ /* Fill in buf */
+
+ buf->st_mode = _dtoxmode(findbuf.dwFileAttributes, name);
+ buf->st_nlink = 1;
+ buf->st_size = findbuf.nFileSizeLow;
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+
+ /* now set the common fields */
+
+ buf->st_uid = buf->st_gid = buf->st_ino = 0;
+
+ buf->st_rdev = buf->st_dev = (_dev_t)(drive - 1); /* A=0, B=1, etc. */
+
+ return(0);
+}
+
+
+/***
+*int _ValidDrive( unsigned drive ) -
+*
+*Purpose: returns non zero if drive is a valid drive number.
+*
+*Entry: drive = 0 => default drive, 1 => a:, 2 => b: ...
+*
+*Exit: 0 => drive does not exist.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _ValidDrive (
+ unsigned drive
+ )
+{
+ unsigned long DriveMap;
+
+#ifdef _CRUISER_
+ unsigned int CurDrive;
+
+ DOSQUERYCURRENTDISK( &CurDrive, &DriveMap );
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+ DriveMap = GetLogicalDrives();
+
+#else /* ndef _WIN32_ */
+
+#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED!
+
+#endif /* _WIN32_ */
+
+#endif /* _CRUISER_ */
+ return( ( DriveMap>>(drive-1) ) & 1l );
+}