home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / fstat.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  13KB  |  401 lines

  1. /***
  2. *fstat.c - return file status info
  3. *
  4. *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines fstat() - return file status info
  8. *
  9. *******************************************************************************/
  10.  
  11. #ifndef _MAC
  12.  
  13.  
  14. #include <cruntime.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <errno.h>
  18. #include <msdos.h>
  19. #include <dostypes.h>
  20. #include <io.h>
  21. #include <internal.h>
  22. #include <stddef.h>
  23. #include <oscalls.h>
  24. #include <stdio.h>
  25. #include <mtdll.h>
  26. #include <time.h>
  27.  
  28. #define IO_DEVNBR   0x3f
  29.  
  30. /***
  31. *int _fstat(fildes, buf) - fills supplied buffer with status info
  32. *
  33. *Purpose:
  34. *       Fills the supplied buffer with status information on the
  35. *       file represented by the specified file designator.
  36. *       WARNING: the dev/rdev fields are zero for files.  This is
  37. *       incompatible with DOS 3 version of this routine.
  38. *
  39. *       Note: We cannot directly use the file time stamps returned in the
  40. *       BY_HANDLE_FILE_INFORMATION structure. The values are supposedly in
  41. *       system time and system time is ambiguously defined (it is UTC for
  42. *       Windows NT, local time for Win32S and probably local time for
  43. *       Win32C). Therefore, these values must be converted to local time
  44. *       before than can be used.
  45. *
  46. *Entry:
  47. *       int fildes   - file descriptor
  48. *       struct stat *buf - buffer to store result in
  49. *
  50. *Exit:
  51. *       fills in buffer pointed to by buf
  52. *       returns 0 if successful
  53. *       returns -1 and sets errno if unsuccessful
  54. *
  55. *Exceptions:
  56. *
  57. *******************************************************************************/
  58.  
  59. #ifdef _USE_INT64
  60.  
  61. int __cdecl _fstati64 (
  62.         int fildes,
  63.         struct _stati64 *buf
  64.         )
  65.  
  66. #else  /* _USE_INT64 */
  67.  
  68. int __cdecl _fstat (
  69.         int fildes,
  70.         struct _stat *buf
  71.         )
  72.  
  73. #endif  /* _USE_INT64 */
  74. {
  75.         int isdev;          /* 0 for a file, 1 for a device */
  76.         int retval = 0;     /* assume good return */
  77.         BY_HANDLE_FILE_INFORMATION bhfi;
  78.         FILETIME LocalFTime;
  79.         SYSTEMTIME SystemTime;
  80.  
  81.         if ( ((unsigned)fildes >= (unsigned)_nhandle) ||
  82.              !(_osfile(fildes) & FOPEN) )
  83.         {
  84.             errno = EBADF;
  85.             return(-1);
  86.         }
  87.  
  88.         /* Lock the file */
  89.  
  90.         _lock_fh(fildes);
  91.  
  92.         /* Find out what kind of handle underlies filedes
  93.          */
  94.         isdev = GetFileType((HANDLE)_osfhnd(fildes)) & ~FILE_TYPE_REMOTE;
  95.  
  96.         if ( isdev != FILE_TYPE_DISK ) {
  97.  
  98.             /* not a disk file. probably a device or pipe
  99.              */
  100.             if ( (isdev == FILE_TYPE_CHAR) || (isdev == FILE_TYPE_PIPE) ) {
  101.                 /* treat pipes and devices similarly. no further info is
  102.                  * available from any API, so set the fields as reasonably
  103.                  * as possible and return.
  104.                  */
  105.                 if ( isdev == FILE_TYPE_CHAR )
  106.                     buf->st_mode = _S_IFCHR;
  107.                 else
  108.                     buf->st_mode = _S_IFIFO;
  109.  
  110.                 buf->st_rdev = buf->st_dev = (_dev_t)fildes;
  111.                 buf->st_nlink = 1;
  112.                 buf->st_uid = buf->st_gid = buf->st_ino = 0;
  113.                 buf->st_atime = buf->st_mtime = buf->st_ctime = 0;
  114.                 if ( isdev == FILE_TYPE_CHAR ) {
  115. #ifdef _USE_INT64
  116.                     buf->st_size = 0i64;
  117. #else  /* _USE_INT64 */
  118.                     buf->st_size = 0;
  119. #endif  /* _USE_INT64 */
  120.                 }
  121.                 else {
  122.                     unsigned long ulAvail;
  123.                     int rc;
  124.                     rc = PeekNamedPipe((HANDLE)_osfhnd(fildes),
  125.                                        NULL,
  126.                                        0,
  127.                                        NULL,
  128.                                        &ulAvail,
  129.                                        NULL);
  130.  
  131.                     if (rc) {
  132.                         buf->st_size = (_off_t)ulAvail;
  133.                     }
  134.                     else {
  135.                         buf->st_size = (_off_t)0;
  136.                     }
  137.                 }
  138.  
  139.                 goto done;
  140.             }
  141.             else if ( isdev == FILE_TYPE_UNKNOWN ) {
  142.                 errno = EBADF;
  143.                 retval = -1;
  144.                 goto done;      /* join common return code */
  145.             }
  146.             else {
  147.                 /* according to the documentation, this cannot happen, but
  148.                  * play it safe anyway.
  149.                  */
  150.                 _dosmaperr(GetLastError());
  151.                 retval = -1;
  152.                 goto done;
  153.             }
  154.         }
  155.  
  156.  
  157.         /* set the common fields
  158.          */
  159.         buf->st_ino = buf->st_uid = buf->st_gid = buf->st_mode = 0;
  160.         buf->st_nlink = 1;
  161.  
  162.         /* use the file handle to get all the info about the file
  163.          */
  164.         if ( !GetFileInformationByHandle((HANDLE)_osfhnd(fildes), &bhfi) ) {
  165.             _dosmaperr(GetLastError());
  166.             retval = -1;
  167.             goto done;
  168.         }
  169.  
  170.         if ( bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY )
  171.             buf->st_mode |= (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6));
  172.         else
  173.             buf->st_mode |= ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3)
  174.               + ((_S_IREAD|_S_IWRITE) >> 6));
  175.  
  176.         /* set file date fields
  177.          */
  178.         if ( !FileTimeToLocalFileTime( &(bhfi.ftLastWriteTime), &LocalFTime )
  179.              || !FileTimeToSystemTime( &LocalFTime, &SystemTime ) )
  180.         {
  181.             retval = -1;
  182.             goto done;
  183.         }
  184.  
  185.         buf->st_mtime = __loctotime_t(SystemTime.wYear,
  186.                                       SystemTime.wMonth,
  187.                                       SystemTime.wDay,
  188.                                       SystemTime.wHour,
  189.                                       SystemTime.wMinute,
  190.                                       SystemTime.wSecond,
  191.                                       -1);
  192.  
  193.         if ( bhfi.ftLastAccessTime.dwLowDateTime ||
  194.              bhfi.ftLastAccessTime.dwHighDateTime )
  195.         {
  196.  
  197.             if ( !FileTimeToLocalFileTime( &(bhfi.ftLastAccessTime),
  198.                                            &LocalFTime ) ||
  199.                  !FileTimeToSystemTime( &LocalFTime, &SystemTime ) )
  200.             {
  201.                 retval = -1;
  202.                 goto done;
  203.             }
  204.  
  205.             buf->st_atime = __loctotime_t(SystemTime.wYear,
  206.                                           SystemTime.wMonth,
  207.                                           SystemTime.wDay,
  208.                                           SystemTime.wHour,
  209.                                           SystemTime.wMinute,
  210.                                           SystemTime.wSecond,
  211.                                           -1);
  212.         }
  213.         else
  214.             buf->st_atime = buf->st_mtime;
  215.  
  216.         if ( bhfi.ftCreationTime.dwLowDateTime ||
  217.              bhfi.ftCreationTime.dwHighDateTime )
  218.         {
  219.  
  220.             if ( !FileTimeToLocalFileTime( &(bhfi.ftCreationTime),
  221.                                            &LocalFTime ) ||
  222.                  !FileTimeToSystemTime( &LocalFTime, &SystemTime ) )
  223.             {
  224.                 retval = -1;
  225.                 goto done;
  226.             }
  227.  
  228.             buf->st_ctime = __loctotime_t(SystemTime.wYear,
  229.                                           SystemTime.wMonth,
  230.                                           SystemTime.wDay,
  231.                                           SystemTime.wHour,
  232.                                           SystemTime.wMinute,
  233.                                           SystemTime.wSecond,
  234.                                           -1);
  235.         }
  236.         else
  237.             buf->st_ctime = buf->st_mtime;
  238.  
  239. #ifdef _USE_INT64
  240.         buf->st_size = ((__int64)(bhfi.nFileSizeHigh)) * (0x100000000i64) +
  241.                        (__int64)(bhfi.nFileSizeLow);
  242. #else  /* _USE_INT64 */
  243.         buf->st_size = bhfi.nFileSizeLow;
  244. #endif  /* _USE_INT64 */
  245.  
  246.         buf->st_mode |= _S_IFREG;
  247.  
  248.         /* On DOS, this field contains the drive number, but
  249.          * the drive number is not available on this platform.
  250.          * Also, for UNC network names, there is no drive number.
  251.          */
  252.         buf->st_rdev = buf->st_dev = 0;
  253.  
  254. /* Common return code */
  255.  
  256. done:
  257.         _unlock_fh(fildes);
  258.         return(retval);
  259. }
  260.  
  261.  
  262. #else  /* _MAC */
  263.  
  264.  
  265. #include <cruntime.h>
  266. #include <sys/types.h>
  267. #include <sys/stat.h>
  268. #include <errno.h>
  269. #include <memory.h>
  270. #include <msdos.h>
  271. #include <dostypes.h>
  272. #include <io.h>
  273. #include <internal.h>
  274. #include <stddef.h>
  275. #include <stdio.h>
  276. #include <string.h>
  277. #include <macos\osutils.h>
  278. #include <macos\files.h>
  279. #include <macos\errors.h>
  280.  
  281. #define IO_DEVNBR   0x3f
  282.  
  283. unsigned short __cdecl _dtoxmode ( CInfoPBPtr pcinfoPB );
  284.  
  285. /***
  286. *int _fstat(fildes, buf) - fills supplied buffer with status info
  287. *
  288. *Purpose:
  289. *       Fills the supplied buffer with status information on the
  290. *       file represented by the specified file designator.
  291. *       WARNING: the dev/rdev fields are zero for files.  This is
  292. *       incompatible with DOS 3 version of this routine.
  293. *
  294. *Entry:
  295. *       int fildes -    file descriptor
  296. *       struct stat *buf - buffer to store result in
  297. *
  298. *Exit:
  299. *       fills in buffer pointed to by buf
  300. *       returns 0 if successful
  301. *       returns -1 and sets errno if unsuccessful
  302. *
  303. *Exceptions:
  304. *
  305. *******************************************************************************/
  306.  
  307. int __cdecl _fstat (
  308.         int fildes,
  309.         struct _stat *buf
  310.         )
  311. {
  312.         int retval = 0;         /* assume good return */
  313.         OSErr osErr;
  314.         FCBPBRec parmFCB;
  315.         char st[32];
  316.         CInfoPBRec cinfoPB;
  317.         DateTimeRec dt;
  318.         DateTimeRec dtc;
  319.  
  320.         if (fildes < 0 || fildes >= _nfile) {
  321.                 errno = EBADF;
  322.                 return(-1);
  323.         }
  324.  
  325.         if (_osfhnd[fildes] == -1 && (_osfile[fildes] & FDEV))
  326.         {
  327.                 /* MPW console */
  328.                 buf->st_mode = _S_IFCHR;
  329.                 buf->st_dev=buf->st_rdev = _osfhnd[fildes];
  330.                 buf->st_ino = buf->st_uid = buf->st_gid =  0;
  331.                 buf->st_nlink = 1;
  332.                 buf->st_atime=buf->st_ctime=buf->st_mtime=0;
  333.                 return 0;
  334.         }
  335.  
  336.         /* Issue the get file control block call. */
  337.         memset(&parmFCB, '\0', sizeof(FCBPBRec));
  338.         parmFCB.ioRefNum = _osfhnd[fildes];
  339.         *st = sizeof(st) - 1;
  340.         parmFCB.ioNamePtr = st;
  341.         osErr = PBGetFCBInfoSync(&parmFCB);
  342.         if (osErr != 0)
  343.         {
  344.                 _dosmaperr(osErr);
  345.                 return -1;
  346.         }
  347.  
  348.         memset(&cinfoPB, '\0', sizeof(CInfoPBRec));
  349.         cinfoPB.hFileInfo.ioNamePtr = parmFCB.ioNamePtr;
  350.         cinfoPB.hFileInfo.ioFDirIndex = 0;
  351.         cinfoPB.hFileInfo.ioVRefNum = parmFCB.ioFCBVRefNum;
  352.         cinfoPB.hFileInfo.ioDirID = parmFCB.ioFCBParID;
  353.         osErr = PBGetCatInfoSync(&cinfoPB);
  354.         if (osErr != 0)
  355.         {
  356.                 _dosmaperr(osErr);
  357.                 return -1;
  358.         }
  359.  
  360.         /* set the common fields */
  361.  
  362.         buf->st_ino = buf->st_uid = buf->st_gid = buf->st_mode = 0;
  363.         buf->st_nlink = 1;
  364.         buf->st_mode |= (_osfile[fildes] & FRDONLY)
  365.                         ? (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6))
  366.                         : ((_S_IREAD|_S_IWRITE) +
  367.                           ((_S_IREAD|_S_IWRITE) >> 3)
  368.                           + ((_S_IREAD|_S_IWRITE) >> 6));
  369.  
  370.         /* file or dir ? */
  371.         if (cinfoPB.hFileInfo.ioFlAttrib & 0x10)
  372.         {       /*dir*/
  373.                 Secs2Date(cinfoPB.dirInfo.ioDrMdDat, &dt);
  374.                 Secs2Date(cinfoPB.dirInfo.ioDrCrDat, &dtc);
  375.                 buf->st_size = 0;
  376.         }
  377.         else
  378.         {       /*file*/
  379.                 Secs2Date(cinfoPB.hFileInfo.ioFlMdDat, &dt);
  380.                 Secs2Date(cinfoPB.hFileInfo.ioFlCrDat, &dtc);
  381.                 buf->st_size = cinfoPB.hFileInfo.ioFlLgLen + cinfoPB.hFileInfo.ioFlRLgLen;
  382.         }
  383.         buf->st_mode = _dtoxmode(&cinfoPB);
  384.  
  385.         buf->st_mtime = _gmtotime_t(dt.year, dt.month, dt.day,
  386.                                     dt.hour, dt.minute, dt.second);
  387.         buf->st_atime = buf->st_mtime;
  388.         buf->st_ctime = _gmtotime_t(dtc.year, dtc.month, dtc.day,
  389.                                     dtc.hour, dtc.minute, dtc.second);
  390.  
  391.         buf->st_rdev = buf->st_dev = cinfoPB.hFileInfo.ioVRefNum;
  392.  
  393.  
  394. /* Common return code */
  395.  
  396.         return(retval);
  397. }
  398.  
  399.  
  400. #endif  /* _MAC */
  401.