fstat.c 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /* fstat() replacement.
  2. Copyright (C) 2011-2022 Free Software Foundation, Inc.
  3. This file is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as
  5. published by the Free Software Foundation; either version 2.1 of the
  6. License, or (at your option) any later version.
  7. This file 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 Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser 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. }