fstat.c 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /* fstat() replacement.
  2. Copyright (C) 2011-2021 Free Software Foundation, Inc.
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. /* If the user's config.h happens to include <sys/stat.h>, let it include only
  14. the system's <sys/stat.h> here, so that orig_fstat doesn't recurse to
  15. rpl_fstat. */
  16. #define __need_system_sys_stat_h
  17. #include <config.h>
  18. /* Get the original definition of fstat. It might be defined as a macro. */
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #undef __need_system_sys_stat_h
  22. #if defined _WIN32 && ! defined __CYGWIN__
  23. # define WINDOWS_NATIVE
  24. #endif
  25. #if !defined WINDOWS_NATIVE
  26. static int
  27. orig_fstat (int fd, struct stat *buf)
  28. {
  29. return fstat (fd, buf);
  30. }
  31. #endif
  32. /* Specification. */
  33. #ifdef __osf__
  34. /* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
  35. eliminates this include because of the preliminary #include <sys/stat.h>
  36. above. */
  37. # include "sys/stat.h"
  38. #else
  39. # include <sys/stat.h>
  40. #endif
  41. #include "stat-time.h"
  42. #include <errno.h>
  43. #include <unistd.h>
  44. #ifdef WINDOWS_NATIVE
  45. # define WIN32_LEAN_AND_MEAN
  46. # include <windows.h>
  47. # if GNULIB_MSVC_NOTHROW
  48. # include "msvc-nothrow.h"
  49. # else
  50. # include <io.h>
  51. # endif
  52. # include "stat-w32.h"
  53. #endif
  54. int
  55. rpl_fstat (int fd, struct stat *buf)
  56. {
  57. #if REPLACE_FCHDIR && REPLACE_OPEN_DIRECTORY
  58. /* Handle the case when rpl_open() used a dummy file descriptor to work
  59. around an open() that can't normally visit directories. */
  60. const char *name = _gl_directory_name (fd);
  61. if (name != NULL)
  62. return stat (name, buf);
  63. #endif
  64. #ifdef WINDOWS_NATIVE
  65. /* Fill the fields ourselves, because the original fstat function returns
  66. values for st_atime, st_mtime, st_ctime that depend on the current time
  67. zone. See
  68. <https://lists.gnu.org/r/bug-gnulib/2017-04/msg00134.html> */
  69. HANDLE h = (HANDLE) _get_osfhandle (fd);
  70. if (h == INVALID_HANDLE_VALUE)
  71. {
  72. errno = EBADF;
  73. return -1;
  74. }
  75. return _gl_fstat_by_handle (h, NULL, buf);
  76. #else
  77. return stat_time_normalize (orig_fstat (fd, buf), buf);
  78. #endif
  79. }