passenger 6.2.0 → 6.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (650) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +33 -1
  3. data/CONTRIBUTING.md +7 -311
  4. data/CONTRIBUTORS +1 -0
  5. data/LICENSE +1 -1
  6. data/README.md +1 -1
  7. data/Rakefile +1 -1
  8. data/bin/passenger +1 -1
  9. data/bin/passenger-config +1 -1
  10. data/bin/passenger-install-apache2-module +1 -1
  11. data/bin/passenger-install-nginx-module +4 -9
  12. data/bin/passenger-memory-stats +1 -1
  13. data/bin/passenger-status +1 -1
  14. data/build/agent.rb +13 -15
  15. data/build/apache2.rb +13 -16
  16. data/build/basics.rb +10 -13
  17. data/build/common_library.rb +5 -9
  18. data/build/cxx_tests.rb +37 -12
  19. data/build/integration_tests.rb +5 -2
  20. data/build/misc.rb +1 -1
  21. data/build/nginx.rb +1 -1
  22. data/build/node_tests.rb +1 -1
  23. data/build/oxt_tests.rb +6 -8
  24. data/build/packaging.rb +1 -1
  25. data/build/ruby_extension.rb +1 -1
  26. data/build/ruby_tests.rb +1 -1
  27. data/build/schema_printer.rb +13 -15
  28. data/build/support/cplusplus.rb +61 -69
  29. data/build/support/cxx_dependency_map.rb +2 -1
  30. data/build/support/general.rb +1 -1
  31. data/build/support/vendor/cxx_hinted_parser/LICENSE.md +1 -1
  32. data/build/support/vendor/cxx_hinted_parser/lib/cxx_hinted_parser/parser.rb +1 -1
  33. data/build/support/vendor/cxx_hinted_parser/lib/cxx_hinted_parser.rb +1 -1
  34. data/build/support/vendor/cxxcodebuilder/LICENSE.md +1 -1
  35. data/build/support/vendor/cxxcodebuilder/lib/cxxcodebuilder/builder.rb +1 -1
  36. data/build/support/vendor/cxxcodebuilder/lib/cxxcodebuilder/initializer_builder.rb +1 -1
  37. data/build/support/vendor/cxxcodebuilder/lib/cxxcodebuilder.rb +1 -1
  38. data/build/test_basics.rb +1 -1
  39. data/dev/copy_boost_headers +1 -1
  40. data/dev/index_cxx_dependencies.rb +5 -1
  41. data/dev/libev-changes.patch +108 -0
  42. data/dev/nginx_version_sha256 +1 -1
  43. data/dev/ruby_server.rb +1 -6
  44. data/dev/upgrading_libuv.sh +16 -0
  45. data/doc/BasicArchitectureOverview.md +55 -0
  46. data/doc/BuildCaching.md +23 -0
  47. data/doc/BuildSystem.md +49 -0
  48. data/doc/DebuggingAndStressTesting.md +2 -0
  49. data/doc/DesignAspects/LimitedGemDependencies.md +1 -0
  50. data/doc/DevEnvironmentSetup.md +46 -0
  51. data/doc/DevHandbook.md +28 -0
  52. data/doc/Packaging.md +1 -1
  53. data/doc/RunningTests.md +88 -0
  54. data/doc/{TempFileHandling.md → SecureTempFileHandling.md} +1 -1
  55. data/doc/{CxxTestingGuide.md → WritingCxxTests.md} +1 -20
  56. data/src/agent/AgentMain.cpp +1 -1
  57. data/src/agent/Core/ApiServer.h +1 -1
  58. data/src/agent/Core/ApplicationPool/AbstractSession.h +1 -1
  59. data/src/agent/Core/ApplicationPool/BasicGroupInfo.h +1 -1
  60. data/src/agent/Core/ApplicationPool/BasicProcessInfo.h +1 -1
  61. data/src/agent/Core/ApplicationPool/Common.h +1 -1
  62. data/src/agent/Core/ApplicationPool/Context.h +1 -1
  63. data/src/agent/Core/ApplicationPool/Group/InitializationAndShutdown.cpp +1 -1
  64. data/src/agent/Core/ApplicationPool/Group/InternalUtils.cpp +1 -1
  65. data/src/agent/Core/ApplicationPool/Group/LifetimeAndBasics.cpp +1 -1
  66. data/src/agent/Core/ApplicationPool/Group/Miscellaneous.cpp +1 -1
  67. data/src/agent/Core/ApplicationPool/Group/OutOfBandWork.cpp +1 -1
  68. data/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp +1 -1
  69. data/src/agent/Core/ApplicationPool/Group/SessionManagement.cpp +1 -1
  70. data/src/agent/Core/ApplicationPool/Group/SpawningAndRestarting.cpp +1 -1
  71. data/src/agent/Core/ApplicationPool/Group/StateInspection.cpp +1 -1
  72. data/src/agent/Core/ApplicationPool/Group/Verification.cpp +1 -1
  73. data/src/agent/Core/ApplicationPool/Group.h +1 -1
  74. data/src/agent/Core/ApplicationPool/Implementation.cpp +1 -1
  75. data/src/agent/Core/ApplicationPool/Options.h +1 -1
  76. data/src/agent/Core/ApplicationPool/Pool/AnalyticsCollection.cpp +1 -1
  77. data/src/agent/Core/ApplicationPool/Pool/GarbageCollection.cpp +1 -1
  78. data/src/agent/Core/ApplicationPool/Pool/GeneralUtils.cpp +1 -1
  79. data/src/agent/Core/ApplicationPool/Pool/GroupUtils.cpp +1 -1
  80. data/src/agent/Core/ApplicationPool/Pool/InitializationAndShutdown.cpp +1 -1
  81. data/src/agent/Core/ApplicationPool/Pool/Miscellaneous.cpp +1 -1
  82. data/src/agent/Core/ApplicationPool/Pool/ProcessUtils.cpp +1 -1
  83. data/src/agent/Core/ApplicationPool/Pool/StateInspection.cpp +1 -1
  84. data/src/agent/Core/ApplicationPool/Pool.h +1 -1
  85. data/src/agent/Core/ApplicationPool/Process.cpp +1 -1
  86. data/src/agent/Core/ApplicationPool/Process.h +1 -1
  87. data/src/agent/Core/ApplicationPool/Session.h +1 -1
  88. data/src/agent/Core/ApplicationPool/Socket.h +1 -1
  89. data/src/agent/Core/ApplicationPool/TestSession.h +1 -1
  90. data/src/agent/Core/Config.h +3 -2
  91. data/src/agent/Core/ConfigChange.cpp +1 -1
  92. data/src/agent/Core/ConfigChange.h +1 -1
  93. data/src/agent/Core/Controller/AppResponse.h +1 -1
  94. data/src/agent/Core/Controller/BufferBody.cpp +1 -1
  95. data/src/agent/Core/Controller/CheckoutSession.cpp +8 -5
  96. data/src/agent/Core/Controller/Client.h +1 -1
  97. data/src/agent/Core/Controller/Config.cpp +1 -1
  98. data/src/agent/Core/Controller/Config.h +2 -2
  99. data/src/agent/Core/Controller/ForwardResponse.cpp +2 -2
  100. data/src/agent/Core/Controller/Hooks.cpp +12 -9
  101. data/src/agent/Core/Controller/Implementation.cpp +1 -1
  102. data/src/agent/Core/Controller/InitRequest.cpp +1 -1
  103. data/src/agent/Core/Controller/InitializationAndShutdown.cpp +1 -1
  104. data/src/agent/Core/Controller/InternalUtils.cpp +1 -1
  105. data/src/agent/Core/Controller/Miscellaneous.cpp +1 -1
  106. data/src/agent/Core/Controller/Request.h +1 -1
  107. data/src/agent/Core/Controller/SendRequest.cpp +1 -1
  108. data/src/agent/Core/Controller/StateInspection.cpp +1 -1
  109. data/src/agent/Core/Controller/TurboCaching.h +1 -1
  110. data/src/agent/Core/Controller.h +1 -1
  111. data/src/agent/Core/CoreMain.cpp +1 -1
  112. data/src/agent/Core/OptionParser.h +1 -1
  113. data/src/agent/Core/ResponseCache.h +1 -1
  114. data/src/agent/Core/SecurityUpdateChecker.h +1 -1
  115. data/src/agent/Core/SpawningKit/Config/AutoGeneratedCode.h +1 -1
  116. data/src/agent/Core/SpawningKit/Config/AutoGeneratedCode.h.cxxcodebuilder +1 -1
  117. data/src/agent/Core/SpawningKit/Config.h +1 -1
  118. data/src/agent/Core/SpawningKit/Context.h +1 -1
  119. data/src/agent/Core/SpawningKit/DirectSpawner.h +1 -1
  120. data/src/agent/Core/SpawningKit/DummySpawner.h +1 -1
  121. data/src/agent/Core/SpawningKit/ErrorRenderer.h +1 -1
  122. data/src/agent/Core/SpawningKit/Exceptions.h +63 -2
  123. data/src/agent/Core/SpawningKit/Factory.h +1 -1
  124. data/src/agent/Core/SpawningKit/Handshake/BackgroundIOCapturer.h +1 -1
  125. data/src/agent/Core/SpawningKit/Handshake/Perform.h +3 -2
  126. data/src/agent/Core/SpawningKit/Handshake/Prepare.h +1 -1
  127. data/src/agent/Core/SpawningKit/Handshake/Session.h +1 -1
  128. data/src/agent/Core/SpawningKit/Handshake/WorkDir.h +1 -1
  129. data/src/agent/Core/SpawningKit/Journey.h +1 -1
  130. data/src/agent/Core/SpawningKit/PipeWatcher.h +1 -1
  131. data/src/agent/Core/SpawningKit/README.md +3 -3
  132. data/src/agent/Core/SpawningKit/Result/AutoGeneratedCode.h +1 -1
  133. data/src/agent/Core/SpawningKit/Result/AutoGeneratedCode.h.cxxcodebuilder +1 -1
  134. data/src/agent/Core/SpawningKit/Result.h +1 -1
  135. data/src/agent/Core/SpawningKit/SmartSpawner.h +17 -17
  136. data/src/agent/Core/SpawningKit/Spawner.h +1 -1
  137. data/src/agent/Core/SpawningKit/UserSwitchingRules.h +1 -1
  138. data/src/agent/Core/TelemetryCollector.h +1 -1
  139. data/src/agent/ExecHelper/ExecHelperMain.cpp +1 -1
  140. data/src/agent/FileReadHelper/FileReadHelperMain.cpp +1 -1
  141. data/src/agent/MainFunctions.h +1 -1
  142. data/src/agent/Shared/ApiAccountUtils.h +4 -3
  143. data/src/agent/Shared/ApiServerUtils.h +1 -2
  144. data/src/agent/Shared/ApplicationPoolApiKey.h +1 -1
  145. data/src/agent/Shared/Fundamentals/AbortHandler.cpp +1 -1
  146. data/src/agent/Shared/Fundamentals/AbortHandler.h +1 -1
  147. data/src/agent/Shared/Fundamentals/Initialization.cpp +1 -1
  148. data/src/agent/Shared/Fundamentals/Initialization.h +1 -1
  149. data/src/agent/Shared/Fundamentals/Utils.cpp +1 -1
  150. data/src/agent/Shared/Fundamentals/Utils.h +1 -1
  151. data/src/agent/SpawnEnvSetupper/SpawnEnvSetupperMain.cpp +1 -1
  152. data/src/agent/SystemMetrics/SystemMetricsMain.cpp +1 -1
  153. data/src/agent/TempDirToucher/TempDirToucherMain.cpp +1 -1
  154. data/src/agent/Watchdog/ApiServer.h +7 -6
  155. data/src/agent/Watchdog/Config.h +2 -2
  156. data/src/apache2_module/Bucket.cpp +1 -1
  157. data/src/apache2_module/Bucket.h +1 -1
  158. data/src/apache2_module/CBindings.cpp +1 -1
  159. data/src/apache2_module/Config.cpp +1 -1
  160. data/src/apache2_module/Config.h +1 -1
  161. data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp +104 -104
  162. data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp.cxxcodebuilder +2 -2
  163. data/src/apache2_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.cpp +1 -1
  164. data/src/apache2_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.cpp.cxxcodebuilder +1 -1
  165. data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp +1 -1
  166. data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp.cxxcodebuilder +1 -1
  167. data/src/apache2_module/ConfigGeneral/Common.h +1 -1
  168. data/src/apache2_module/ConfigGeneral/ManifestGeneration.h +1 -1
  169. data/src/apache2_module/ConfigGeneral/SetterFuncs.h +1 -1
  170. data/src/apache2_module/DirConfig/AutoGeneratedCreateFunction.cpp +1 -1
  171. data/src/apache2_module/DirConfig/AutoGeneratedCreateFunction.cpp.cxxcodebuilder +1 -1
  172. data/src/apache2_module/DirConfig/AutoGeneratedHeaderSerialization.cpp +1 -1
  173. data/src/apache2_module/DirConfig/AutoGeneratedHeaderSerialization.cpp.cxxcodebuilder +1 -1
  174. data/src/apache2_module/DirConfig/AutoGeneratedManifestGeneration.cpp +1 -1
  175. data/src/apache2_module/DirConfig/AutoGeneratedManifestGeneration.cpp.cxxcodebuilder +1 -1
  176. data/src/apache2_module/DirConfig/AutoGeneratedMergeFunction.cpp +1 -1
  177. data/src/apache2_module/DirConfig/AutoGeneratedMergeFunction.cpp.cxxcodebuilder +1 -1
  178. data/src/apache2_module/DirConfig/AutoGeneratedStruct.h +1 -1
  179. data/src/apache2_module/DirConfig/AutoGeneratedStruct.h.cxxcodebuilder +1 -1
  180. data/src/apache2_module/DirectoryMapper.h +1 -1
  181. data/src/apache2_module/Hooks.cpp +8 -2
  182. data/src/apache2_module/Hooks.h +1 -1
  183. data/src/apache2_module/ServerConfig/AutoGeneratedManifestGeneration.cpp +1 -1
  184. data/src/apache2_module/ServerConfig/AutoGeneratedManifestGeneration.cpp.cxxcodebuilder +1 -1
  185. data/src/apache2_module/ServerConfig/AutoGeneratedStruct.h +1 -1
  186. data/src/apache2_module/ServerConfig/AutoGeneratedStruct.h.cxxcodebuilder +1 -1
  187. data/src/apache2_module/Utils.h +1 -1
  188. data/src/apache2_module/mod_passenger.c +1 -1
  189. data/src/cxx_supportlib/Algorithms/Hasher.cpp +1 -1
  190. data/src/cxx_supportlib/Algorithms/Hasher.h +1 -1
  191. data/src/cxx_supportlib/Algorithms/MovingAverage.h +1 -1
  192. data/src/cxx_supportlib/AppLocalConfigFileUtils.h +1 -1
  193. data/src/cxx_supportlib/AppTypeDetector/CBindings.cpp +1 -1
  194. data/src/cxx_supportlib/AppTypeDetector/CBindings.h +1 -1
  195. data/src/cxx_supportlib/AppTypeDetector/Detector.h +1 -1
  196. data/src/cxx_supportlib/BackgroundEventLoop.cpp +1 -1
  197. data/src/cxx_supportlib/BackgroundEventLoop.h +1 -1
  198. data/src/cxx_supportlib/ConfigKit/AsyncUtils.h +1 -1
  199. data/src/cxx_supportlib/ConfigKit/Common.h +1 -1
  200. data/src/cxx_supportlib/ConfigKit/ConfigKit.h +1 -1
  201. data/src/cxx_supportlib/ConfigKit/DummyTranslator.h +1 -1
  202. data/src/cxx_supportlib/ConfigKit/IN_PRACTICE.md +1 -3
  203. data/src/cxx_supportlib/ConfigKit/PrefixTranslator.h +3 -3
  204. data/src/cxx_supportlib/ConfigKit/Schema.h +1 -1
  205. data/src/cxx_supportlib/ConfigKit/SchemaUtils.h +1 -1
  206. data/src/cxx_supportlib/ConfigKit/Store.h +1 -1
  207. data/src/cxx_supportlib/ConfigKit/SubComponentUtils.h +1 -1
  208. data/src/cxx_supportlib/ConfigKit/TableTranslator.h +1 -1
  209. data/src/cxx_supportlib/ConfigKit/Translator.h +1 -1
  210. data/src/cxx_supportlib/ConfigKit/Utils.h +1 -1
  211. data/src/cxx_supportlib/Constants.h +2 -2
  212. data/src/cxx_supportlib/Constants.h.cxxcodebuilder +1 -1
  213. data/src/cxx_supportlib/DataStructures/HashedStaticString.h +1 -1
  214. data/src/cxx_supportlib/DataStructures/LString.cpp +1 -1
  215. data/src/cxx_supportlib/DataStructures/LString.h +1 -1
  216. data/src/cxx_supportlib/DataStructures/StringKeyTable.h +1 -1
  217. data/src/cxx_supportlib/DataStructures/StringMap.h +1 -1
  218. data/src/cxx_supportlib/Exceptions.cpp +1 -1
  219. data/src/cxx_supportlib/Exceptions.h +1 -1
  220. data/src/cxx_supportlib/FileDescriptor.h +1 -1
  221. data/src/cxx_supportlib/FileTools/FileManip.cpp +1 -1
  222. data/src/cxx_supportlib/FileTools/FileManip.h +1 -1
  223. data/src/cxx_supportlib/FileTools/PathManip.cpp +1 -1
  224. data/src/cxx_supportlib/FileTools/PathManip.h +1 -1
  225. data/src/cxx_supportlib/FileTools/PathManipCBindings.cpp +1 -1
  226. data/src/cxx_supportlib/FileTools/PathManipCBindings.h +1 -1
  227. data/src/cxx_supportlib/FileTools/PathSecurityCheck.cpp +1 -1
  228. data/src/cxx_supportlib/FileTools/PathSecurityCheck.h +1 -1
  229. data/src/cxx_supportlib/Hooks.h +1 -1
  230. data/src/cxx_supportlib/IOTools/BufferedIO.h +1 -1
  231. data/src/cxx_supportlib/IOTools/IOUtils.cpp +10 -10
  232. data/src/cxx_supportlib/IOTools/IOUtils.h +1 -1
  233. data/src/cxx_supportlib/IOTools/MessageIO.h +1 -1
  234. data/src/cxx_supportlib/IOTools/MessageSerialization.h +1 -1
  235. data/src/cxx_supportlib/InstanceDirectory.h +1 -1
  236. data/src/cxx_supportlib/Integrations/LibevJsonUtils.h +1 -1
  237. data/src/cxx_supportlib/JsonTools/Autocast.h +1 -1
  238. data/src/cxx_supportlib/JsonTools/CBindings.cpp +1 -1
  239. data/src/cxx_supportlib/JsonTools/CBindings.h +1 -1
  240. data/src/cxx_supportlib/JsonTools/JsonUtils.h +1 -1
  241. data/src/cxx_supportlib/LoggingKit/Assert.h +1 -1
  242. data/src/cxx_supportlib/LoggingKit/Config.h +2 -1
  243. data/src/cxx_supportlib/LoggingKit/Context.h +1 -1
  244. data/src/cxx_supportlib/LoggingKit/Forward.h +1 -1
  245. data/src/cxx_supportlib/LoggingKit/Implementation.cpp +11 -1
  246. data/src/cxx_supportlib/LoggingKit/Logging.h +1 -1
  247. data/src/cxx_supportlib/LoggingKit/LoggingKit.h +1 -1
  248. data/src/cxx_supportlib/LveLoggingDecorator.h +1 -1
  249. data/src/cxx_supportlib/MemoryKit/mbuf.cpp +1 -1
  250. data/src/cxx_supportlib/MemoryKit/mbuf.h +1 -1
  251. data/src/cxx_supportlib/MemoryKit/palloc.cpp +1 -1
  252. data/src/cxx_supportlib/MemoryKit/palloc.h +1 -1
  253. data/src/cxx_supportlib/ProcessManagement/Ruby.cpp +1 -1
  254. data/src/cxx_supportlib/ProcessManagement/Ruby.h +1 -1
  255. data/src/cxx_supportlib/ProcessManagement/Spawn.cpp +1 -1
  256. data/src/cxx_supportlib/ProcessManagement/Spawn.h +1 -1
  257. data/src/cxx_supportlib/ProcessManagement/Utils.cpp +1 -1
  258. data/src/cxx_supportlib/ProcessManagement/Utils.h +1 -1
  259. data/src/cxx_supportlib/RandomGenerator.h +1 -1
  260. data/src/cxx_supportlib/ResourceLocator.h +1 -1
  261. data/src/cxx_supportlib/SafeLibev.h +1 -1
  262. data/src/cxx_supportlib/SecurityKit/Crypto.cpp +9 -27
  263. data/src/cxx_supportlib/SecurityKit/Crypto.h +2 -2
  264. data/src/cxx_supportlib/SecurityKit/MemZeroGuard.h +1 -1
  265. data/src/cxx_supportlib/ServerKit/AcceptLoadBalancer.h +1 -1
  266. data/src/cxx_supportlib/ServerKit/Channel.h +1 -1
  267. data/src/cxx_supportlib/ServerKit/Client.h +1 -1
  268. data/src/cxx_supportlib/ServerKit/ClientRef.h +1 -1
  269. data/src/cxx_supportlib/ServerKit/Config.h +1 -1
  270. data/src/cxx_supportlib/ServerKit/Context.h +1 -1
  271. data/src/cxx_supportlib/ServerKit/CookieUtils.h +1 -1
  272. data/src/cxx_supportlib/ServerKit/Errors.h +1 -1
  273. data/src/cxx_supportlib/ServerKit/FdSinkChannel.h +1 -1
  274. data/src/cxx_supportlib/ServerKit/FdSourceChannel.h +1 -1
  275. data/src/cxx_supportlib/ServerKit/FileBufferedChannel.h +54 -2
  276. data/src/cxx_supportlib/ServerKit/FileBufferedFdSinkChannel.h +1 -1
  277. data/src/cxx_supportlib/ServerKit/HeaderTable.h +1 -1
  278. data/src/cxx_supportlib/ServerKit/Hooks.h +1 -1
  279. data/src/cxx_supportlib/ServerKit/HttpChunkedBodyParser.h +1 -1
  280. data/src/cxx_supportlib/ServerKit/HttpChunkedBodyParserState.h +1 -1
  281. data/src/cxx_supportlib/ServerKit/HttpClient.h +1 -1
  282. data/src/cxx_supportlib/ServerKit/HttpHeaderParser.h +1 -1
  283. data/src/cxx_supportlib/ServerKit/HttpHeaderParserState.h +1 -1
  284. data/src/cxx_supportlib/ServerKit/HttpRequest.h +1 -1
  285. data/src/cxx_supportlib/ServerKit/HttpRequestRef.h +1 -1
  286. data/src/cxx_supportlib/ServerKit/HttpServer.h +1 -1
  287. data/src/cxx_supportlib/ServerKit/Implementation.cpp +1 -1
  288. data/src/cxx_supportlib/ServerKit/Server.h +4 -2
  289. data/src/cxx_supportlib/StaticString.h +1 -1
  290. data/src/cxx_supportlib/StrIntTools/DateParsing.h +1 -1
  291. data/src/cxx_supportlib/StrIntTools/StrIntUtils.cpp +1 -1
  292. data/src/cxx_supportlib/StrIntTools/StrIntUtils.h +1 -1
  293. data/src/cxx_supportlib/StrIntTools/StrIntUtilsNoStrictAliasing.cpp +1 -1
  294. data/src/cxx_supportlib/StrIntTools/StringScanning.h +1 -1
  295. data/src/cxx_supportlib/StrIntTools/Template.h +1 -1
  296. data/src/cxx_supportlib/SystemTools/ContainerHelpers.h +1 -1
  297. data/src/cxx_supportlib/SystemTools/ProcessMetricsCollector.h +1 -1
  298. data/src/cxx_supportlib/SystemTools/SystemMetricsCollector.h +1 -1
  299. data/src/cxx_supportlib/SystemTools/SystemTime.cpp +1 -1
  300. data/src/cxx_supportlib/SystemTools/SystemTime.h +1 -1
  301. data/src/cxx_supportlib/SystemTools/UserDatabase.cpp +1 -1
  302. data/src/cxx_supportlib/SystemTools/UserDatabase.h +1 -1
  303. data/src/cxx_supportlib/Utils/AnsiColorConstants.h +1 -1
  304. data/src/cxx_supportlib/Utils/AsyncSignalSafeUtils.h +1 -1
  305. data/src/cxx_supportlib/Utils/BlockingQueue.h +1 -1
  306. data/src/cxx_supportlib/Utils/CachedFileStat.cpp +1 -1
  307. data/src/cxx_supportlib/Utils/CachedFileStat.h +1 -1
  308. data/src/cxx_supportlib/Utils/CachedFileStat.hpp +1 -1
  309. data/src/cxx_supportlib/Utils/ClassUtils.h +1 -1
  310. data/src/cxx_supportlib/Utils/Curl.h +1 -1
  311. data/src/cxx_supportlib/Utils/FastStringStream.h +1 -1
  312. data/src/cxx_supportlib/Utils/FileChangeChecker.h +1 -1
  313. data/src/cxx_supportlib/Utils/HttpConstants.h +1 -1
  314. data/src/cxx_supportlib/Utils/IniFile.h +1 -1
  315. data/src/cxx_supportlib/Utils/MessagePassing.h +1 -1
  316. data/src/cxx_supportlib/Utils/OptionParsing.h +1 -1
  317. data/src/cxx_supportlib/Utils/ReleaseableScopedPointer.h +1 -1
  318. data/src/cxx_supportlib/Utils/ScopeGuard.h +1 -1
  319. data/src/cxx_supportlib/Utils/SpeedMeter.h +1 -1
  320. data/src/cxx_supportlib/Utils/Timer.h +1 -1
  321. data/src/cxx_supportlib/Utils/VariantMap.h +1 -1
  322. data/src/cxx_supportlib/Utils.cpp +1 -1
  323. data/src/cxx_supportlib/Utils.h +1 -1
  324. data/src/cxx_supportlib/WatchdogLauncher.cpp +1 -1
  325. data/src/cxx_supportlib/WatchdogLauncher.h +1 -1
  326. data/src/cxx_supportlib/WrapperRegistry/CBindings.cpp +1 -1
  327. data/src/cxx_supportlib/WrapperRegistry/CBindings.h +1 -1
  328. data/src/cxx_supportlib/WrapperRegistry/Entry.h +1 -1
  329. data/src/cxx_supportlib/WrapperRegistry/Registry.h +1 -1
  330. data/src/cxx_supportlib/oxt/backtrace.hpp +1 -1
  331. data/src/cxx_supportlib/oxt/detail/backtrace_disabled.hpp +1 -1
  332. data/src/cxx_supportlib/oxt/detail/backtrace_enabled.hpp +1 -1
  333. data/src/cxx_supportlib/oxt/detail/context.hpp +1 -1
  334. data/src/cxx_supportlib/oxt/detail/tracable_exception_disabled.hpp +1 -1
  335. data/src/cxx_supportlib/oxt/detail/tracable_exception_enabled.hpp +1 -1
  336. data/src/cxx_supportlib/oxt/dynamic_thread_group.hpp +1 -1
  337. data/src/cxx_supportlib/oxt/implementation.cpp +1 -1
  338. data/src/cxx_supportlib/oxt/initialize.hpp +1 -1
  339. data/src/cxx_supportlib/oxt/macros.hpp +1 -1
  340. data/src/cxx_supportlib/oxt/spin_lock.hpp +1 -1
  341. data/src/cxx_supportlib/oxt/system_calls.cpp +1 -1
  342. data/src/cxx_supportlib/oxt/system_calls.hpp +1 -1
  343. data/src/cxx_supportlib/oxt/thread.hpp +1 -1
  344. data/src/cxx_supportlib/oxt/tracable_exception.hpp +1 -1
  345. data/src/cxx_supportlib/vendor-copy/adhoc_lve.h +1 -1
  346. data/src/cxx_supportlib/vendor-copy/libuv/AUTHORS +353 -3
  347. data/src/cxx_supportlib/vendor-copy/libuv/ChangeLog +3981 -2
  348. data/src/cxx_supportlib/vendor-copy/libuv/LICENSE +1 -28
  349. data/src/cxx_supportlib/vendor-copy/libuv/LICENSE-docs +396 -0
  350. data/src/cxx_supportlib/vendor-copy/libuv/LICENSE-extra +36 -0
  351. data/src/cxx_supportlib/vendor-copy/libuv/Makefile.am +275 -58
  352. data/src/cxx_supportlib/vendor-copy/libuv/Makefile.in +4380 -2125
  353. data/src/cxx_supportlib/vendor-copy/libuv/aclocal.m4 +425 -221
  354. data/src/cxx_supportlib/vendor-copy/libuv/ar-lib +30 -10
  355. data/src/cxx_supportlib/vendor-copy/libuv/compile +31 -14
  356. data/src/cxx_supportlib/vendor-copy/libuv/config.guess +1084 -690
  357. data/src/cxx_supportlib/vendor-copy/libuv/config.sub +1844 -1297
  358. data/src/cxx_supportlib/vendor-copy/libuv/configure +6935 -3664
  359. data/src/cxx_supportlib/vendor-copy/libuv/configure.ac +43 -19
  360. data/src/cxx_supportlib/vendor-copy/libuv/depcomp +12 -11
  361. data/src/cxx_supportlib/vendor-copy/libuv/include/{uv-darwin.h → uv/darwin.h} +3 -3
  362. data/src/cxx_supportlib/vendor-copy/libuv/include/{uv-errno.h → uv/errno.h} +119 -60
  363. data/src/cxx_supportlib/vendor-copy/libuv/include/{uv-linux.h → uv/linux.h} +1 -1
  364. data/src/cxx_supportlib/vendor-copy/libuv/include/uv/os390.h +33 -0
  365. data/src/cxx_supportlib/vendor-copy/libuv/include/uv/posix.h +31 -0
  366. data/src/cxx_supportlib/vendor-copy/libuv/include/{uv-threadpool.h → uv/threadpool.h} +1 -1
  367. data/src/cxx_supportlib/vendor-copy/libuv/include/{tree.h → uv/tree.h} +3 -250
  368. data/src/cxx_supportlib/vendor-copy/libuv/include/{uv-unix.h → uv/unix.h} +186 -60
  369. data/src/cxx_supportlib/vendor-copy/libuv/include/{uv-version.h → uv/version.h} +3 -3
  370. data/src/cxx_supportlib/vendor-copy/libuv/include/uv/win.h +703 -0
  371. data/src/cxx_supportlib/vendor-copy/libuv/include/uv.h +528 -40
  372. data/src/cxx_supportlib/vendor-copy/libuv/install-sh +110 -70
  373. data/src/cxx_supportlib/vendor-copy/libuv/libuv-static.pc.in +12 -0
  374. data/src/cxx_supportlib/vendor-copy/libuv/libuv.pc.in +4 -2
  375. data/src/cxx_supportlib/vendor-copy/libuv/ltmain.sh +995 -619
  376. data/src/cxx_supportlib/vendor-copy/libuv/m4/ax_pthread.m4 +485 -0
  377. data/src/cxx_supportlib/vendor-copy/libuv/m4/libtool.m4 +438 -289
  378. data/src/cxx_supportlib/vendor-copy/libuv/m4/libuv-check-flags.m4 +21 -4
  379. data/src/cxx_supportlib/vendor-copy/libuv/m4/libuv-check-versions.m4 +7 -0
  380. data/src/cxx_supportlib/vendor-copy/libuv/m4/ltoptions.m4 +69 -39
  381. data/src/cxx_supportlib/vendor-copy/libuv/m4/ltsugar.m4 +1 -1
  382. data/src/cxx_supportlib/vendor-copy/libuv/m4/ltversion.m4 +7 -6
  383. data/src/cxx_supportlib/vendor-copy/libuv/m4/lt~obsolete.m4 +2 -2
  384. data/src/cxx_supportlib/vendor-copy/libuv/missing +55 -34
  385. data/src/cxx_supportlib/vendor-copy/libuv/src/fs-poll.c +52 -20
  386. data/src/cxx_supportlib/vendor-copy/libuv/src/idna.c +560 -0
  387. data/src/cxx_supportlib/vendor-copy/libuv/src/idna.h +31 -0
  388. data/src/cxx_supportlib/vendor-copy/libuv/src/inet.c +5 -16
  389. data/src/cxx_supportlib/vendor-copy/libuv/src/queue.h +68 -86
  390. data/src/cxx_supportlib/vendor-copy/libuv/src/random.c +123 -0
  391. data/src/cxx_supportlib/vendor-copy/libuv/src/strscpy.c +38 -0
  392. data/src/cxx_supportlib/vendor-copy/libuv/src/strscpy.h +39 -0
  393. data/src/cxx_supportlib/vendor-copy/libuv/src/strtok.c +52 -0
  394. data/src/cxx_supportlib/vendor-copy/libuv/src/strtok.h +27 -0
  395. data/src/cxx_supportlib/vendor-copy/libuv/src/thread-common.c +175 -0
  396. data/src/cxx_supportlib/vendor-copy/libuv/src/threadpool.c +172 -57
  397. data/src/cxx_supportlib/vendor-copy/libuv/src/{unix/timer.c → timer.c} +57 -29
  398. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/aix-common.c +89 -0
  399. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/aix.c +418 -256
  400. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/async.c +168 -129
  401. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/bsd-ifaddrs.c +163 -0
  402. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/bsd-proctitle.c +99 -0
  403. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/core.c +1312 -378
  404. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/cygwin.c +93 -0
  405. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/darwin-proctitle.c +18 -32
  406. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/darwin-stub.h +97 -0
  407. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/darwin-syscalls.h +17 -0
  408. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/darwin.c +41 -139
  409. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/dl.c +1 -1
  410. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/freebsd.c +75 -235
  411. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/fs.c +1308 -299
  412. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/fsevents.c +150 -148
  413. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/getaddrinfo.c +58 -8
  414. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/getnameinfo.c +3 -2
  415. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/haiku.c +172 -0
  416. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/hurd.c +172 -0
  417. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/ibmi.c +542 -0
  418. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/internal.h +297 -106
  419. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/kqueue.c +325 -94
  420. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux.c +2708 -0
  421. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/loop-watcher.c +11 -11
  422. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/loop.c +105 -24
  423. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/netbsd.c +51 -157
  424. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/no-fsevents.c +42 -0
  425. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/no-proctitle.c +45 -0
  426. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/openbsd.c +42 -183
  427. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/os390-proctitle.c +136 -0
  428. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/os390-syscalls.c +536 -0
  429. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/os390-syscalls.h +75 -0
  430. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/os390.c +1070 -0
  431. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/pipe.c +324 -55
  432. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/poll.c +58 -11
  433. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/posix-hrtime.c +36 -0
  434. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/posix-poll.c +385 -0
  435. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/process.c +795 -248
  436. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/procfs-exepath.c +45 -0
  437. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/proctitle.c +77 -22
  438. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/qnx.c +142 -0
  439. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/random-devurandom.c +93 -0
  440. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/random-getentropy.c +57 -0
  441. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/random-getrandom.c +86 -0
  442. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/random-sysctl-linux.c +99 -0
  443. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/signal.c +147 -39
  444. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/stream.c +426 -474
  445. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/sunos.c +240 -98
  446. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/sysinfo-loadavg.c +36 -0
  447. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/sysinfo-memory.c +42 -0
  448. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/tcp.c +402 -91
  449. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/thread.c +497 -145
  450. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/tty.c +269 -45
  451. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/udp.c +695 -165
  452. data/src/cxx_supportlib/vendor-copy/libuv/src/uv-common.c +463 -61
  453. data/src/cxx_supportlib/vendor-copy/libuv/src/uv-common.h +248 -44
  454. data/src/cxx_supportlib/vendor-copy/libuv/src/uv-data-getter-setters.c +119 -0
  455. data/src/cxx_supportlib/vendor-copy/libuv/tsansupp.txt +2 -0
  456. data/src/cxx_supportlib/vendor-modified/libev/Changes +109 -0
  457. data/src/cxx_supportlib/vendor-modified/libev/Makefile.am +2 -1
  458. data/src/cxx_supportlib/vendor-modified/libev/Makefile.in +47 -33
  459. data/src/cxx_supportlib/vendor-modified/libev/README +2 -1
  460. data/src/cxx_supportlib/vendor-modified/libev/aclocal.m4 +1653 -1224
  461. data/src/cxx_supportlib/vendor-modified/libev/config.guess +376 -316
  462. data/src/cxx_supportlib/vendor-modified/libev/config.h.in +13 -2
  463. data/src/cxx_supportlib/vendor-modified/libev/config.sub +156 -154
  464. data/src/cxx_supportlib/vendor-modified/libev/configure +1431 -940
  465. data/src/cxx_supportlib/vendor-modified/libev/configure.ac +3 -3
  466. data/src/cxx_supportlib/vendor-modified/libev/depcomp +5 -5
  467. data/src/cxx_supportlib/vendor-modified/libev/ev++.h +109 -107
  468. data/src/cxx_supportlib/vendor-modified/libev/ev.c +807 -319
  469. data/src/cxx_supportlib/vendor-modified/libev/ev.h +111 -105
  470. data/src/cxx_supportlib/vendor-modified/libev/ev_epoll.c +42 -29
  471. data/src/cxx_supportlib/vendor-modified/libev/ev_iouring.c +694 -0
  472. data/src/cxx_supportlib/vendor-modified/libev/ev_kqueue.c +15 -9
  473. data/src/cxx_supportlib/vendor-modified/libev/ev_linuxaio.c +620 -0
  474. data/src/cxx_supportlib/vendor-modified/libev/ev_poll.c +19 -14
  475. data/src/cxx_supportlib/vendor-modified/libev/ev_port.c +8 -5
  476. data/src/cxx_supportlib/vendor-modified/libev/ev_select.c +6 -6
  477. data/src/cxx_supportlib/vendor-modified/libev/ev_vars.h +48 -3
  478. data/src/cxx_supportlib/vendor-modified/libev/ev_win32.c +2 -2
  479. data/src/cxx_supportlib/vendor-modified/libev/ev_wrap.h +72 -0
  480. data/src/cxx_supportlib/vendor-modified/libev/install-sh +23 -13
  481. data/src/cxx_supportlib/vendor-modified/libev/libev.m4 +6 -1
  482. data/src/cxx_supportlib/vendor-modified/libev/ltmain.sh +3581 -1993
  483. data/src/cxx_supportlib/vendor-modified/libev/missing +8 -8
  484. data/src/cxx_supportlib/vendor-modified/libev/mkinstalldirs +3 -3
  485. data/src/cxx_supportlib/vendor-modified/modp_b64_strict_aliasing.cpp +1 -1
  486. data/src/helper-scripts/backtrace-sanitizer.rb +1 -1
  487. data/src/helper-scripts/crash-watch.rb +1 -1
  488. data/src/helper-scripts/download_binaries/extconf.rb +1 -1
  489. data/src/helper-scripts/meteor-loader.rb +1 -1
  490. data/src/helper-scripts/node-loader.js +1 -1
  491. data/src/helper-scripts/prespawn +1 -1
  492. data/src/helper-scripts/rack-loader.rb +1 -1
  493. data/src/helper-scripts/rack-preloader.rb +1 -1
  494. data/src/helper-scripts/wsgi-loader.py +1 -1
  495. data/src/nginx_module/ConfigGeneral/AutoGeneratedDefinitions.c +1 -1
  496. data/src/nginx_module/ConfigGeneral/AutoGeneratedDefinitions.c.cxxcodebuilder +1 -1
  497. data/src/nginx_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.c +1 -1
  498. data/src/nginx_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.c.cxxcodebuilder +1 -1
  499. data/src/nginx_module/ConfigGeneral/AutoGeneratedSetterFuncs.c +1 -1
  500. data/src/nginx_module/ConfigGeneral/AutoGeneratedSetterFuncs.c.cxxcodebuilder +1 -1
  501. data/src/nginx_module/Configuration.c +1 -1
  502. data/src/nginx_module/Configuration.h +1 -1
  503. data/src/nginx_module/ContentHandler.c +1 -1
  504. data/src/nginx_module/ContentHandler.h +1 -1
  505. data/src/nginx_module/LocationConfig/AutoGeneratedCreateFunction.c +1 -1
  506. data/src/nginx_module/LocationConfig/AutoGeneratedCreateFunction.c.cxxcodebuilder +1 -1
  507. data/src/nginx_module/LocationConfig/AutoGeneratedHeaderSerialization.c +1 -1
  508. data/src/nginx_module/LocationConfig/AutoGeneratedHeaderSerialization.c.cxxcodebuilder +1 -1
  509. data/src/nginx_module/LocationConfig/AutoGeneratedManifestGeneration.c +1 -1
  510. data/src/nginx_module/LocationConfig/AutoGeneratedManifestGeneration.c.cxxcodebuilder +1 -1
  511. data/src/nginx_module/LocationConfig/AutoGeneratedMergeFunction.c +1 -1
  512. data/src/nginx_module/LocationConfig/AutoGeneratedMergeFunction.c.cxxcodebuilder +1 -1
  513. data/src/nginx_module/LocationConfig/AutoGeneratedStruct.h +1 -1
  514. data/src/nginx_module/LocationConfig/AutoGeneratedStruct.h.cxxcodebuilder +1 -1
  515. data/src/nginx_module/MainConfig/AutoGeneratedCreateFunction.c +1 -1
  516. data/src/nginx_module/MainConfig/AutoGeneratedCreateFunction.c.cxxcodebuilder +1 -1
  517. data/src/nginx_module/MainConfig/AutoGeneratedManifestGeneration.c +1 -1
  518. data/src/nginx_module/MainConfig/AutoGeneratedManifestGeneration.c.cxxcodebuilder +1 -1
  519. data/src/nginx_module/MainConfig/AutoGeneratedStruct.h +1 -1
  520. data/src/nginx_module/MainConfig/AutoGeneratedStruct.h.cxxcodebuilder +1 -1
  521. data/src/nginx_module/StaticContentHandler.c +1 -1
  522. data/src/nginx_module/StaticContentHandler.h +1 -1
  523. data/src/nginx_module/ngx_http_passenger_module.c +1 -1
  524. data/src/nginx_module/ngx_http_passenger_module.h +1 -1
  525. data/src/nodejs_supportlib/phusion_passenger/line_reader.js +1 -1
  526. data/src/ruby_native_extension/extconf.rb +1 -1
  527. data/src/ruby_native_extension/passenger_native_support.c +1 -1
  528. data/src/ruby_supportlib/phusion_passenger/abstract_installer.rb +1 -1
  529. data/src/ruby_supportlib/phusion_passenger/admin_tools/instance.rb +1 -1
  530. data/src/ruby_supportlib/phusion_passenger/admin_tools/instance_registry.rb +1 -1
  531. data/src/ruby_supportlib/phusion_passenger/admin_tools/memory_stats.rb +2 -12
  532. data/src/ruby_supportlib/phusion_passenger/admin_tools.rb +1 -1
  533. data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +1 -1
  534. data/src/ruby_supportlib/phusion_passenger/apache2/config_utils.rb +1 -1
  535. data/src/ruby_supportlib/phusion_passenger/common_library.rb +8 -10
  536. data/src/ruby_supportlib/phusion_passenger/config/about_command.rb +1 -1
  537. data/src/ruby_supportlib/phusion_passenger/config/agent_compiler.rb +1 -1
  538. data/src/ruby_supportlib/phusion_passenger/config/api_call_command.rb +1 -1
  539. data/src/ruby_supportlib/phusion_passenger/config/build_native_support_command.rb +1 -1
  540. data/src/ruby_supportlib/phusion_passenger/config/command.rb +1 -1
  541. data/src/ruby_supportlib/phusion_passenger/config/compile_agent_command.rb +1 -1
  542. data/src/ruby_supportlib/phusion_passenger/config/compile_nginx_engine_command.rb +1 -1
  543. data/src/ruby_supportlib/phusion_passenger/config/detach_process_command.rb +1 -1
  544. data/src/ruby_supportlib/phusion_passenger/config/download_agent_command.rb +1 -1
  545. data/src/ruby_supportlib/phusion_passenger/config/download_nginx_engine_command.rb +1 -1
  546. data/src/ruby_supportlib/phusion_passenger/config/install_agent_command.rb +1 -1
  547. data/src/ruby_supportlib/phusion_passenger/config/install_standalone_runtime_command.rb +1 -1
  548. data/src/ruby_supportlib/phusion_passenger/config/installation_utils.rb +1 -1
  549. data/src/ruby_supportlib/phusion_passenger/config/list_instances_command.rb +1 -1
  550. data/src/ruby_supportlib/phusion_passenger/config/main.rb +1 -1
  551. data/src/ruby_supportlib/phusion_passenger/config/nginx_engine_compiler.rb +3 -2
  552. data/src/ruby_supportlib/phusion_passenger/config/reopen_logs_command.rb +6 -1
  553. data/src/ruby_supportlib/phusion_passenger/config/restart_app_command.rb +1 -1
  554. data/src/ruby_supportlib/phusion_passenger/config/system_metrics_command.rb +1 -1
  555. data/src/ruby_supportlib/phusion_passenger/config/system_properties_command.rb +1 -1
  556. data/src/ruby_supportlib/phusion_passenger/config/utils.rb +1 -1
  557. data/src/ruby_supportlib/phusion_passenger/config/validate_install_command.rb +1 -1
  558. data/src/ruby_supportlib/phusion_passenger/console_text_template.rb +1 -1
  559. data/src/ruby_supportlib/phusion_passenger/constants.rb +1 -1
  560. data/src/ruby_supportlib/phusion_passenger/debug_logging.rb +1 -1
  561. data/src/ruby_supportlib/phusion_passenger/loader_shared_helpers.rb +1 -1
  562. data/src/ruby_supportlib/phusion_passenger/message_channel.rb +1 -1
  563. data/src/ruby_supportlib/phusion_passenger/message_client.rb +1 -1
  564. data/src/ruby_supportlib/phusion_passenger/native_support.rb +1 -1
  565. data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +1 -1
  566. data/src/ruby_supportlib/phusion_passenger/packaging.rb +4 -3
  567. data/src/ruby_supportlib/phusion_passenger/platform_info/apache.rb +1 -1
  568. data/src/ruby_supportlib/phusion_passenger/platform_info/apache_detector.rb +1 -1
  569. data/src/ruby_supportlib/phusion_passenger/platform_info/binary_compatibility.rb +1 -1
  570. data/src/ruby_supportlib/phusion_passenger/platform_info/compiler.rb +195 -11
  571. data/src/ruby_supportlib/phusion_passenger/platform_info/crypto.rb +1 -1
  572. data/src/ruby_supportlib/phusion_passenger/platform_info/curl.rb +1 -1
  573. data/src/ruby_supportlib/phusion_passenger/platform_info/cxx_portability.rb +1 -1
  574. data/src/ruby_supportlib/phusion_passenger/platform_info/linux.rb +1 -1
  575. data/src/ruby_supportlib/phusion_passenger/platform_info/networking.rb +1 -1
  576. data/src/ruby_supportlib/phusion_passenger/platform_info/openssl.rb +1 -1
  577. data/src/ruby_supportlib/phusion_passenger/platform_info/operating_system.rb +1 -1
  578. data/src/ruby_supportlib/phusion_passenger/platform_info/pcre.rb +1 -1
  579. data/src/ruby_supportlib/phusion_passenger/platform_info/ruby.rb +1 -1
  580. data/src/ruby_supportlib/phusion_passenger/platform_info/zlib.rb +1 -1
  581. data/src/ruby_supportlib/phusion_passenger/platform_info.rb +1 -1
  582. data/src/ruby_supportlib/phusion_passenger/plugin.rb +1 -1
  583. data/src/ruby_supportlib/phusion_passenger/preloader_shared_helpers.rb +1 -1
  584. data/src/ruby_supportlib/phusion_passenger/public_api.rb +1 -1
  585. data/src/ruby_supportlib/phusion_passenger/rack/handler.rb +1 -1
  586. data/src/ruby_supportlib/phusion_passenger/rack/out_of_band_gc.rb +1 -1
  587. data/src/ruby_supportlib/phusion_passenger/rack/thread_handler_extension.rb +1 -1
  588. data/src/ruby_supportlib/phusion_passenger/rack_handler.rb +1 -1
  589. data/src/ruby_supportlib/phusion_passenger/request_handler/thread_handler.rb +2 -7
  590. data/src/ruby_supportlib/phusion_passenger/request_handler.rb +1 -1
  591. data/src/ruby_supportlib/phusion_passenger/ruby_core_enhancements.rb +1 -1
  592. data/src/ruby_supportlib/phusion_passenger/ruby_core_io_enhancements.rb +1 -1
  593. data/src/ruby_supportlib/phusion_passenger/simple_benchmarking.rb +1 -1
  594. data/src/ruby_supportlib/phusion_passenger/standalone/app_finder.rb +1 -1
  595. data/src/ruby_supportlib/phusion_passenger/standalone/command.rb +1 -1
  596. data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +1 -1
  597. data/src/ruby_supportlib/phusion_passenger/standalone/config_utils.rb +1 -1
  598. data/src/ruby_supportlib/phusion_passenger/standalone/control_utils.rb +1 -1
  599. data/src/ruby_supportlib/phusion_passenger/standalone/main.rb +1 -1
  600. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +2 -2
  601. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/nginx_engine.rb +4 -8
  602. data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +1 -1
  603. data/src/ruby_supportlib/phusion_passenger/standalone/status_command.rb +1 -1
  604. data/src/ruby_supportlib/phusion_passenger/standalone/stop_command.rb +1 -1
  605. data/src/ruby_supportlib/phusion_passenger/standalone/version_command.rb +1 -1
  606. data/src/ruby_supportlib/phusion_passenger/utils/ansi_colors.rb +1 -1
  607. data/src/ruby_supportlib/phusion_passenger/utils/download.rb +1 -1
  608. data/src/ruby_supportlib/phusion_passenger/utils/file_system_watcher.rb +1 -1
  609. data/src/ruby_supportlib/phusion_passenger/utils/hosts_file_parser.rb +1 -1
  610. data/src/ruby_supportlib/phusion_passenger/utils/lock.rb +1 -1
  611. data/src/ruby_supportlib/phusion_passenger/utils/native_support_utils.rb +1 -1
  612. data/src/ruby_supportlib/phusion_passenger/utils/progress_bar.rb +1 -1
  613. data/src/ruby_supportlib/phusion_passenger/utils/strscan.rb +1 -1
  614. data/src/ruby_supportlib/phusion_passenger/utils/terminal_choice_menu.rb +1 -1
  615. data/src/ruby_supportlib/phusion_passenger/utils/unseekable_socket.rb +3 -13
  616. data/src/ruby_supportlib/phusion_passenger/utils.rb +1 -1
  617. data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/app.rb +1 -1
  618. data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/base.rb +1 -1
  619. data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/gdb_controller.rb +1 -1
  620. data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/lldb_controller.rb +1 -1
  621. data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/utils.rb +1 -1
  622. data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/version.rb +1 -1
  623. data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller/lock_file.rb +8 -6
  624. data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller/spawn.rb +4 -3
  625. data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller/version.rb +6 -4
  626. data/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller.rb +395 -579
  627. data/src/ruby_supportlib/phusion_passenger.rb +8 -8
  628. data/src/schema_printer/SchemaPrinterMain.cpp +1 -1
  629. data/src/schema_printer/SchemaPrinterMain.cpp.cxxcodebuilder +1 -1
  630. metadata +69 -32
  631. data/doc/DeveloperQuickstart.md +0 -70
  632. data/src/README.md +0 -7
  633. data/src/cxx_supportlib/vendor-copy/libuv/README.md +0 -245
  634. data/src/cxx_supportlib/vendor-copy/libuv/checksparse.sh +0 -234
  635. data/src/cxx_supportlib/vendor-copy/libuv/common.gypi +0 -210
  636. data/src/cxx_supportlib/vendor-copy/libuv/gyp_uv.py +0 -93
  637. data/src/cxx_supportlib/vendor-copy/libuv/include/android-ifaddrs.h +0 -54
  638. data/src/cxx_supportlib/vendor-copy/libuv/include/pthread-fixes.h +0 -72
  639. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/android-ifaddrs.c +0 -703
  640. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/atomic-ops.h +0 -77
  641. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-core.c +0 -899
  642. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-inotify.c +0 -285
  643. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-syscalls.c +0 -471
  644. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/linux-syscalls.h +0 -158
  645. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/pthread-fixes.c +0 -104
  646. data/src/cxx_supportlib/vendor-copy/libuv/src/unix/spinlock.h +0 -53
  647. data/src/cxx_supportlib/vendor-copy/libuv/uv.gyp +0 -508
  648. /data/src/cxx_supportlib/vendor-copy/libuv/include/{uv-aix.h → uv/aix.h} +0 -0
  649. /data/src/cxx_supportlib/vendor-copy/libuv/include/{uv-bsd.h → uv/bsd.h} +0 -0
  650. /data/src/cxx_supportlib/vendor-copy/libuv/include/{uv-sunos.h → uv/sunos.h} +0 -0
@@ -30,45 +30,75 @@
30
30
  #include "internal.h"
31
31
 
32
32
  #include <errno.h>
33
+ #include <dlfcn.h>
34
+ #include <stdatomic.h>
33
35
  #include <stdio.h>
34
36
  #include <stdlib.h>
35
37
  #include <string.h>
38
+ #include <limits.h> /* PATH_MAX */
36
39
 
37
40
  #include <sys/types.h>
38
41
  #include <sys/socket.h>
39
42
  #include <sys/stat.h>
40
43
  #include <sys/time.h>
41
44
  #include <sys/uio.h>
42
- #include <pthread.h>
43
45
  #include <unistd.h>
44
46
  #include <fcntl.h>
45
- #include <utime.h>
46
47
  #include <poll.h>
47
48
 
48
- #if defined(__DragonFly__) || \
49
- defined(__FreeBSD__) || \
50
- defined(__OpenBSD__) || \
49
+ #if defined(__linux__)
50
+ # include <sys/sendfile.h>
51
+ #endif
52
+
53
+ #if defined(__sun)
54
+ # include <sys/sendfile.h>
55
+ # include <sys/sysmacros.h>
56
+ #endif
57
+
58
+ #if defined(__APPLE__)
59
+ # include <sys/sysctl.h>
60
+ #elif defined(__linux__) && !defined(FICLONE)
61
+ # include <sys/ioctl.h>
62
+ # define FICLONE _IOW(0x94, 9, int)
63
+ #endif
64
+
65
+ #if defined(_AIX) && !defined(_AIX71)
66
+ # include <utime.h>
67
+ #endif
68
+
69
+ #if defined(__APPLE__) || \
70
+ defined(__DragonFly__) || \
71
+ defined(__FreeBSD__) || \
72
+ defined(__OpenBSD__) || \
51
73
  defined(__NetBSD__)
52
- # define HAVE_PREADV 1
74
+ # include <sys/param.h>
75
+ # include <sys/mount.h>
76
+ #elif defined(__sun) || \
77
+ defined(__MVS__) || \
78
+ defined(__NetBSD__) || \
79
+ defined(__HAIKU__) || \
80
+ defined(__QNX__)
81
+ # include <sys/statvfs.h>
53
82
  #else
54
- # define HAVE_PREADV 0
83
+ # include <sys/statfs.h>
55
84
  #endif
56
85
 
57
- #if defined(__linux__) || defined(__sun)
58
- # include <sys/sendfile.h>
86
+ #if defined(_AIX) && _XOPEN_SOURCE <= 600
87
+ extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
59
88
  #endif
60
89
 
61
90
  #define INIT(subtype) \
62
91
  do { \
63
- req->type = UV_FS; \
64
- if (cb != NULL) \
65
- uv__req_init(loop, req, UV_FS); \
92
+ if (req == NULL) \
93
+ return UV_EINVAL; \
94
+ UV_REQ_INIT(req, UV_FS); \
66
95
  req->fs_type = UV_FS_ ## subtype; \
67
96
  req->result = 0; \
68
97
  req->ptr = NULL; \
69
98
  req->loop = loop; \
70
99
  req->path = NULL; \
71
100
  req->new_path = NULL; \
101
+ req->bufs = NULL; \
72
102
  req->cb = cb; \
73
103
  } \
74
104
  while (0)
@@ -80,10 +110,8 @@
80
110
  req->path = path; \
81
111
  } else { \
82
112
  req->path = uv__strdup(path); \
83
- if (req->path == NULL) { \
84
- uv__req_unregister(loop, req); \
85
- return -ENOMEM; \
86
- } \
113
+ if (req->path == NULL) \
114
+ return UV_ENOMEM; \
87
115
  } \
88
116
  } \
89
117
  while (0)
@@ -99,10 +127,8 @@
99
127
  path_len = strlen(path) + 1; \
100
128
  new_path_len = strlen(new_path) + 1; \
101
129
  req->path = uv__malloc(path_len + new_path_len); \
102
- if (req->path == NULL) { \
103
- uv__req_unregister(loop, req); \
104
- return -ENOMEM; \
105
- } \
130
+ if (req->path == NULL) \
131
+ return UV_ENOMEM; \
106
132
  req->new_path = req->path + path_len; \
107
133
  memcpy((void*) req->path, path, path_len); \
108
134
  memcpy((void*) req->new_path, new_path, new_path_len); \
@@ -113,7 +139,12 @@
113
139
  #define POST \
114
140
  do { \
115
141
  if (cb != NULL) { \
116
- uv__work_submit(loop, &req->work_req, uv__fs_work, uv__fs_done); \
142
+ uv__req_register(loop); \
143
+ uv__work_submit(loop, \
144
+ &req->work_req, \
145
+ UV__WORK_FAST_IO, \
146
+ uv__fs_work, \
147
+ uv__fs_done); \
117
148
  return 0; \
118
149
  } \
119
150
  else { \
@@ -124,71 +155,93 @@
124
155
  while (0)
125
156
 
126
157
 
127
- static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
128
- #if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
129
- return fdatasync(req->file);
130
- #elif defined(__APPLE__) && defined(F_FULLFSYNC)
131
- return fcntl(req->file, F_FULLFSYNC);
132
- #else
133
- return fsync(req->file);
134
- #endif
158
+ static int uv__fs_close(int fd) {
159
+ int rc;
160
+
161
+ rc = uv__close_nocancel(fd);
162
+ if (rc == -1)
163
+ if (errno == EINTR || errno == EINPROGRESS)
164
+ rc = 0; /* The close is in progress, not an error. */
165
+
166
+ return rc;
135
167
  }
136
168
 
137
169
 
138
- static ssize_t uv__fs_futime(uv_fs_t* req) {
139
- #if defined(__linux__)
140
- /* utimesat() has nanosecond resolution but we stick to microseconds
141
- * for the sake of consistency with other platforms.
170
+ static ssize_t uv__fs_fsync(uv_fs_t* req) {
171
+ #if defined(__APPLE__)
172
+ /* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache
173
+ * to the drive platters. This is in contrast to Linux's fdatasync and fsync
174
+ * which do, according to recent man pages. F_FULLFSYNC is Apple's equivalent
175
+ * for flushing buffered data to permanent storage. If F_FULLFSYNC is not
176
+ * supported by the file system we fall back to F_BARRIERFSYNC or fsync().
177
+ * This is the same approach taken by sqlite, except sqlite does not issue
178
+ * an F_BARRIERFSYNC call.
142
179
  */
143
- static int no_utimesat;
144
- struct timespec ts[2];
145
- struct timeval tv[2];
146
- char path[sizeof("/proc/self/fd/") + 3 * sizeof(int)];
147
180
  int r;
148
181
 
149
- if (no_utimesat)
150
- goto skip;
151
-
152
- ts[0].tv_sec = req->atime;
153
- ts[0].tv_nsec = (unsigned long)(req->atime * 1000000) % 1000000 * 1000;
154
- ts[1].tv_sec = req->mtime;
155
- ts[1].tv_nsec = (unsigned long)(req->mtime * 1000000) % 1000000 * 1000;
156
-
157
- r = uv__utimesat(req->file, NULL, ts, 0);
158
- if (r == 0)
159
- return r;
160
-
161
- if (errno != ENOSYS)
162
- return r;
182
+ r = fcntl(req->file, F_FULLFSYNC);
183
+ if (r != 0)
184
+ r = fcntl(req->file, 85 /* F_BARRIERFSYNC */); /* fsync + barrier */
185
+ if (r != 0)
186
+ r = fsync(req->file);
187
+ return r;
188
+ #else
189
+ return fsync(req->file);
190
+ #endif
191
+ }
163
192
 
164
- no_utimesat = 1;
165
193
 
166
- skip:
194
+ static ssize_t uv__fs_fdatasync(uv_fs_t* req) {
195
+ #if defined(__linux__) || defined(__sun) || defined(__NetBSD__)
196
+ return fdatasync(req->file);
197
+ #elif defined(__APPLE__)
198
+ /* See the comment in uv__fs_fsync. */
199
+ return uv__fs_fsync(req);
200
+ #else
201
+ return fsync(req->file);
202
+ #endif
203
+ }
167
204
 
168
- tv[0].tv_sec = req->atime;
169
- tv[0].tv_usec = (unsigned long)(req->atime * 1000000) % 1000000;
170
- tv[1].tv_sec = req->mtime;
171
- tv[1].tv_usec = (unsigned long)(req->mtime * 1000000) % 1000000;
172
- snprintf(path, sizeof(path), "/proc/self/fd/%d", (int) req->file);
173
205
 
174
- r = utimes(path, tv);
175
- if (r == 0)
176
- return r;
206
+ UV_UNUSED(static struct timespec uv__fs_to_timespec(double time)) {
207
+ struct timespec ts;
208
+ ts.tv_sec = time;
209
+ ts.tv_nsec = (time - ts.tv_sec) * 1e9;
177
210
 
178
- switch (errno) {
179
- case ENOENT:
180
- if (fcntl(req->file, F_GETFL) == -1 && errno == EBADF)
181
- break;
182
- /* Fall through. */
211
+ /* TODO(bnoordhuis) Remove this. utimesat() has nanosecond resolution but we
212
+ * stick to microsecond resolution for the sake of consistency with other
213
+ * platforms. I'm the original author of this compatibility hack but I'm
214
+ * less convinced it's useful nowadays.
215
+ */
216
+ ts.tv_nsec -= ts.tv_nsec % 1000;
183
217
 
184
- case EACCES:
185
- case ENOTDIR:
186
- errno = ENOSYS;
187
- break;
218
+ if (ts.tv_nsec < 0) {
219
+ ts.tv_nsec += 1e9;
220
+ ts.tv_sec -= 1;
188
221
  }
222
+ return ts;
223
+ }
189
224
 
190
- return r;
225
+ UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) {
226
+ struct timeval tv;
227
+ tv.tv_sec = time;
228
+ tv.tv_usec = (time - tv.tv_sec) * 1e6;
229
+ if (tv.tv_usec < 0) {
230
+ tv.tv_usec += 1e6;
231
+ tv.tv_sec -= 1;
232
+ }
233
+ return tv;
234
+ }
191
235
 
236
+ static ssize_t uv__fs_futime(uv_fs_t* req) {
237
+ #if defined(__linux__) \
238
+ || defined(_AIX71) \
239
+ || defined(__HAIKU__) \
240
+ || defined(__GNU__)
241
+ struct timespec ts[2];
242
+ ts[0] = uv__fs_to_timespec(req->atime);
243
+ ts[1] = uv__fs_to_timespec(req->mtime);
244
+ return futimens(req->file, ts);
192
245
  #elif defined(__APPLE__) \
193
246
  || defined(__DragonFly__) \
194
247
  || defined(__FreeBSD__) \
@@ -196,15 +249,21 @@ skip:
196
249
  || defined(__OpenBSD__) \
197
250
  || defined(__sun)
198
251
  struct timeval tv[2];
199
- tv[0].tv_sec = req->atime;
200
- tv[0].tv_usec = (unsigned long)(req->atime * 1000000) % 1000000;
201
- tv[1].tv_sec = req->mtime;
202
- tv[1].tv_usec = (unsigned long)(req->mtime * 1000000) % 1000000;
252
+ tv[0] = uv__fs_to_timeval(req->atime);
253
+ tv[1] = uv__fs_to_timeval(req->mtime);
203
254
  # if defined(__sun)
204
255
  return futimesat(req->file, NULL, tv);
205
256
  # else
206
257
  return futimes(req->file, tv);
207
258
  # endif
259
+ #elif defined(__MVS__)
260
+ attrib_t atr;
261
+ memset(&atr, 0, sizeof(atr));
262
+ atr.att_mtimechg = 1;
263
+ atr.att_atimechg = 1;
264
+ atr.att_mtime = req->mtime;
265
+ atr.att_atime = req->atime;
266
+ return __fchattr(req->file, &atr, sizeof(atr));
208
267
  #else
209
268
  errno = ENOSYS;
210
269
  return -1;
@@ -217,22 +276,103 @@ static ssize_t uv__fs_mkdtemp(uv_fs_t* req) {
217
276
  }
218
277
 
219
278
 
220
- static ssize_t uv__fs_open(uv_fs_t* req) {
221
- static int no_cloexec_support;
279
+ static int (*uv__mkostemp)(char*, int);
280
+
281
+
282
+ static void uv__mkostemp_initonce(void) {
283
+ /* z/os doesn't have RTLD_DEFAULT but that's okay
284
+ * because it doesn't have mkostemp(O_CLOEXEC) either.
285
+ */
286
+ #ifdef RTLD_DEFAULT
287
+ uv__mkostemp = (int (*)(char*, int)) dlsym(RTLD_DEFAULT, "mkostemp");
288
+
289
+ /* We don't care about errors, but we do want to clean them up.
290
+ * If there has been no error, then dlerror() will just return
291
+ * NULL.
292
+ */
293
+ dlerror();
294
+ #endif /* RTLD_DEFAULT */
295
+ }
296
+
297
+
298
+ static int uv__fs_mkstemp(uv_fs_t* req) {
299
+ static uv_once_t once = UV_ONCE_INIT;
222
300
  int r;
301
+ #ifdef O_CLOEXEC
302
+ static _Atomic int no_cloexec_support;
303
+ #endif
304
+ static const char pattern[] = "XXXXXX";
305
+ static const size_t pattern_size = sizeof(pattern) - 1;
306
+ char* path;
307
+ size_t path_length;
308
+
309
+ path = (char*) req->path;
310
+ path_length = strlen(path);
311
+
312
+ /* EINVAL can be returned for 2 reasons:
313
+ 1. The template's last 6 characters were not XXXXXX
314
+ 2. open() didn't support O_CLOEXEC
315
+ We want to avoid going to the fallback path in case
316
+ of 1, so it's manually checked before. */
317
+ if (path_length < pattern_size ||
318
+ strcmp(path + path_length - pattern_size, pattern)) {
319
+ errno = EINVAL;
320
+ r = -1;
321
+ goto clobber;
322
+ }
323
+
324
+ uv_once(&once, uv__mkostemp_initonce);
223
325
 
224
- /* Try O_CLOEXEC before entering locks */
225
- if (no_cloexec_support == 0) {
226
326
  #ifdef O_CLOEXEC
227
- r = open(req->path, req->flags | O_CLOEXEC, req->mode);
327
+ if (atomic_load_explicit(&no_cloexec_support, memory_order_relaxed) == 0 &&
328
+ uv__mkostemp != NULL) {
329
+ r = uv__mkostemp(path, O_CLOEXEC);
330
+
228
331
  if (r >= 0)
229
332
  return r;
333
+
334
+ /* If mkostemp() returns EINVAL, it means the kernel doesn't
335
+ support O_CLOEXEC, so we just fallback to mkstemp() below. */
230
336
  if (errno != EINVAL)
231
- return r;
232
- no_cloexec_support = 1;
337
+ goto clobber;
338
+
339
+ /* We set the static variable so that next calls don't even
340
+ try to use mkostemp. */
341
+ atomic_store_explicit(&no_cloexec_support, 1, memory_order_relaxed);
342
+ }
233
343
  #endif /* O_CLOEXEC */
344
+
345
+ if (req->cb != NULL)
346
+ uv_rwlock_rdlock(&req->loop->cloexec_lock);
347
+
348
+ r = mkstemp(path);
349
+
350
+ /* In case of failure `uv__cloexec` will leave error in `errno`,
351
+ * so it is enough to just set `r` to `-1`.
352
+ */
353
+ if (r >= 0 && uv__cloexec(r, 1) != 0) {
354
+ r = uv__close(r);
355
+ if (r != 0)
356
+ abort();
357
+ r = -1;
234
358
  }
235
359
 
360
+ if (req->cb != NULL)
361
+ uv_rwlock_rdunlock(&req->loop->cloexec_lock);
362
+
363
+ clobber:
364
+ if (r < 0)
365
+ path[0] = '\0';
366
+ return r;
367
+ }
368
+
369
+
370
+ static ssize_t uv__fs_open(uv_fs_t* req) {
371
+ #ifdef O_CLOEXEC
372
+ return open(req->path, req->flags | O_CLOEXEC, req->mode);
373
+ #else /* O_CLOEXEC */
374
+ int r;
375
+
236
376
  if (req->cb != NULL)
237
377
  uv_rwlock_rdlock(&req->loop->cloexec_lock);
238
378
 
@@ -243,7 +383,7 @@ static ssize_t uv__fs_open(uv_fs_t* req) {
243
383
  */
244
384
  if (r >= 0 && uv__cloexec(r, 1) != 0) {
245
385
  r = uv__close(r);
246
- if (r != 0 && r != -EINPROGRESS)
386
+ if (r != 0)
247
387
  abort();
248
388
  r = -1;
249
389
  }
@@ -252,163 +392,404 @@ static ssize_t uv__fs_open(uv_fs_t* req) {
252
392
  uv_rwlock_rdunlock(&req->loop->cloexec_lock);
253
393
 
254
394
  return r;
395
+ #endif /* O_CLOEXEC */
255
396
  }
256
397
 
257
398
 
258
- static ssize_t uv__fs_read(uv_fs_t* req) {
259
- #if defined(__linux__)
260
- static int no_preadv;
399
+ static ssize_t uv__preadv_or_pwritev_emul(int fd,
400
+ const struct iovec* bufs,
401
+ size_t nbufs,
402
+ off_t off,
403
+ int is_pread) {
404
+ ssize_t total;
405
+ ssize_t r;
406
+ size_t i;
407
+ size_t n;
408
+ void* p;
409
+
410
+ total = 0;
411
+ for (i = 0; i < (size_t) nbufs; i++) {
412
+ p = bufs[i].iov_base;
413
+ n = bufs[i].iov_len;
414
+
415
+ do
416
+ if (is_pread)
417
+ r = pread(fd, p, n, off);
418
+ else
419
+ r = pwrite(fd, p, n, off);
420
+ while (r == -1 && errno == EINTR);
421
+
422
+ if (r == -1) {
423
+ if (total > 0)
424
+ return total;
425
+ return -1;
426
+ }
427
+
428
+ off += r;
429
+ total += r;
430
+
431
+ if ((size_t) r < n)
432
+ return total;
433
+ }
434
+
435
+ return total;
436
+ }
437
+
438
+
439
+ #ifdef __linux__
440
+ typedef int uv__iovcnt;
441
+ #else
442
+ typedef size_t uv__iovcnt;
261
443
  #endif
262
- ssize_t result;
263
444
 
264
- #if defined(_AIX)
265
- struct stat buf;
266
- if(fstat(req->file, &buf))
267
- return -1;
268
- if(S_ISDIR(buf.st_mode)) {
269
- errno = EISDIR;
270
- return -1;
445
+
446
+ static ssize_t uv__preadv_emul(int fd,
447
+ const struct iovec* bufs,
448
+ uv__iovcnt nbufs,
449
+ off_t off) {
450
+ return uv__preadv_or_pwritev_emul(fd, bufs, nbufs, off, /*is_pread*/1);
451
+ }
452
+
453
+
454
+ static ssize_t uv__pwritev_emul(int fd,
455
+ const struct iovec* bufs,
456
+ uv__iovcnt nbufs,
457
+ off_t off) {
458
+ return uv__preadv_or_pwritev_emul(fd, bufs, nbufs, off, /*is_pread*/0);
459
+ }
460
+
461
+
462
+ /* The function pointer cache is an uintptr_t because _Atomic void*
463
+ * doesn't work on macos/ios/etc...
464
+ * Disable optimization on armv7 to work around the bug described in
465
+ * https://github.com/libuv/libuv/issues/4532
466
+ */
467
+ #if defined(__arm__) && (__ARM_ARCH == 7)
468
+ __attribute__((optimize("O0")))
469
+ #endif
470
+ static ssize_t uv__preadv_or_pwritev(int fd,
471
+ const struct iovec* bufs,
472
+ size_t nbufs,
473
+ off_t off,
474
+ _Atomic uintptr_t* cache,
475
+ int is_pread) {
476
+ ssize_t (*f)(int, const struct iovec*, uv__iovcnt, off_t);
477
+ void* p;
478
+
479
+ p = (void*) atomic_load_explicit(cache, memory_order_relaxed);
480
+ if (p == NULL) {
481
+ #ifdef RTLD_DEFAULT
482
+ p = dlsym(RTLD_DEFAULT, is_pread ? "preadv" : "pwritev");
483
+ dlerror(); /* Clear errors. */
484
+ #endif /* RTLD_DEFAULT */
485
+ if (p == NULL)
486
+ p = is_pread ? uv__preadv_emul : uv__pwritev_emul;
487
+ atomic_store_explicit(cache, (uintptr_t) p, memory_order_relaxed);
271
488
  }
272
- #endif /* defined(_AIX) */
273
- if (req->off < 0) {
274
- if (req->nbufs == 1)
275
- result = read(req->file, req->bufs[0].base, req->bufs[0].len);
276
- else
277
- result = readv(req->file, (struct iovec*) req->bufs, req->nbufs);
489
+
490
+ /* Use memcpy instead of `f = p` to work around a compiler bug,
491
+ * see https://github.com/libuv/libuv/issues/4532
492
+ */
493
+ memcpy(&f, &p, sizeof(p));
494
+ return f(fd, bufs, nbufs, off);
495
+ }
496
+
497
+
498
+ static ssize_t uv__preadv(int fd,
499
+ const struct iovec* bufs,
500
+ size_t nbufs,
501
+ off_t off) {
502
+ static _Atomic uintptr_t cache;
503
+ return uv__preadv_or_pwritev(fd, bufs, nbufs, off, &cache, /*is_pread*/1);
504
+ }
505
+
506
+
507
+ static ssize_t uv__pwritev(int fd,
508
+ const struct iovec* bufs,
509
+ size_t nbufs,
510
+ off_t off) {
511
+ static _Atomic uintptr_t cache;
512
+ return uv__preadv_or_pwritev(fd, bufs, nbufs, off, &cache, /*is_pread*/0);
513
+ }
514
+
515
+
516
+ static ssize_t uv__fs_read(uv_fs_t* req) {
517
+ const struct iovec* bufs;
518
+ unsigned int iovmax;
519
+ size_t nbufs;
520
+ ssize_t r;
521
+ off_t off;
522
+ int fd;
523
+
524
+ fd = req->file;
525
+ off = req->off;
526
+ bufs = (const struct iovec*) req->bufs;
527
+ nbufs = req->nbufs;
528
+
529
+ iovmax = uv__getiovmax();
530
+ if (nbufs > iovmax)
531
+ nbufs = iovmax;
532
+
533
+ r = 0;
534
+ if (off < 0) {
535
+ if (nbufs == 1)
536
+ r = read(fd, bufs->iov_base, bufs->iov_len);
537
+ else if (nbufs > 1)
538
+ r = readv(fd, bufs, nbufs);
278
539
  } else {
279
- if (req->nbufs == 1) {
280
- result = pread(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
281
- goto done;
282
- }
540
+ if (nbufs == 1)
541
+ r = pread(fd, bufs->iov_base, bufs->iov_len, off);
542
+ else if (nbufs > 1)
543
+ r = uv__preadv(fd, bufs, nbufs, off);
544
+ }
283
545
 
284
- #if HAVE_PREADV
285
- result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
286
- #else
287
- # if defined(__linux__)
288
- if (no_preadv) retry:
289
- # endif
290
- {
291
- off_t nread;
292
- size_t index;
293
-
294
- nread = 0;
295
- index = 0;
296
- result = 1;
297
- do {
298
- if (req->bufs[index].len > 0) {
299
- result = pread(req->file,
300
- req->bufs[index].base,
301
- req->bufs[index].len,
302
- req->off + nread);
303
- if (result > 0)
304
- nread += result;
305
- }
306
- index++;
307
- } while (index < req->nbufs && result > 0);
308
- if (nread > 0)
309
- result = nread;
546
+ #ifdef __PASE__
547
+ /* PASE returns EOPNOTSUPP when reading a directory, convert to EISDIR */
548
+ if (r == -1 && errno == EOPNOTSUPP) {
549
+ struct stat buf;
550
+ ssize_t rc;
551
+ rc = uv__fstat(fd, &buf);
552
+ if (rc == 0 && S_ISDIR(buf.st_mode)) {
553
+ errno = EISDIR;
310
554
  }
311
- # if defined(__linux__)
312
- else {
313
- result = uv__preadv(req->file,
314
- (struct iovec*)req->bufs,
315
- req->nbufs,
316
- req->off);
317
- if (result == -1 && errno == ENOSYS) {
318
- no_preadv = 1;
319
- goto retry;
320
- }
321
- }
322
- # endif
323
- #endif
324
555
  }
556
+ #endif
325
557
 
326
- done:
327
- return result;
558
+ /* We don't own the buffer list in the synchronous case. */
559
+ if (req->cb != NULL)
560
+ if (req->bufs != req->bufsml)
561
+ uv__free(req->bufs);
562
+
563
+ req->bufs = NULL;
564
+ req->nbufs = 0;
565
+
566
+ return r;
328
567
  }
329
568
 
330
569
 
331
- #if defined(__OpenBSD__) || (defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_8))
332
- static int uv__fs_scandir_filter(uv__dirent_t* dent) {
333
- #else
334
570
  static int uv__fs_scandir_filter(const uv__dirent_t* dent) {
335
- #endif
336
571
  return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0;
337
572
  }
338
573
 
339
574
 
575
+ static int uv__fs_scandir_sort(const uv__dirent_t** a, const uv__dirent_t** b) {
576
+ return strcmp((*a)->d_name, (*b)->d_name);
577
+ }
578
+
579
+
340
580
  static ssize_t uv__fs_scandir(uv_fs_t* req) {
341
- uv__dirent_t **dents;
342
- int saved_errno;
581
+ uv__dirent_t** dents;
343
582
  int n;
344
583
 
345
584
  dents = NULL;
346
- n = scandir(req->path, &dents, uv__fs_scandir_filter, alphasort);
585
+ n = scandir(req->path, &dents, uv__fs_scandir_filter, uv__fs_scandir_sort);
347
586
 
348
587
  /* NOTE: We will use nbufs as an index field */
349
588
  req->nbufs = 0;
350
589
 
351
- if (n == 0)
352
- goto out; /* osx still needs to deallocate some memory */
353
- else if (n == -1)
590
+ if (n == 0) {
591
+ /* OS X still needs to deallocate some memory.
592
+ * Memory was allocated using the system allocator, so use free() here.
593
+ */
594
+ free(dents);
595
+ dents = NULL;
596
+ } else if (n == -1) {
354
597
  return n;
598
+ }
355
599
 
356
600
  req->ptr = dents;
357
601
 
358
602
  return n;
603
+ }
359
604
 
360
- out:
361
- saved_errno = errno;
362
- if (dents != NULL) {
363
- int i;
605
+ static int uv__fs_opendir(uv_fs_t* req) {
606
+ uv_dir_t* dir;
364
607
 
365
- for (i = 0; i < n; i++)
366
- uv__free(dents[i]);
367
- uv__free(dents);
368
- }
369
- errno = saved_errno;
608
+ dir = uv__malloc(sizeof(*dir));
609
+ if (dir == NULL)
610
+ goto error;
611
+
612
+ dir->dir = opendir(req->path);
613
+ if (dir->dir == NULL)
614
+ goto error;
370
615
 
616
+ req->ptr = dir;
617
+ return 0;
618
+
619
+ error:
620
+ uv__free(dir);
371
621
  req->ptr = NULL;
622
+ return -1;
623
+ }
372
624
 
373
- return n;
625
+ static int uv__fs_readdir(uv_fs_t* req) {
626
+ uv_dir_t* dir;
627
+ uv_dirent_t* dirent;
628
+ struct dirent* res;
629
+ unsigned int dirent_idx;
630
+ unsigned int i;
631
+
632
+ dir = req->ptr;
633
+ dirent_idx = 0;
634
+
635
+ while (dirent_idx < dir->nentries) {
636
+ /* readdir() returns NULL on end of directory, as well as on error. errno
637
+ is used to differentiate between the two conditions. */
638
+ errno = 0;
639
+ res = readdir(dir->dir);
640
+
641
+ if (res == NULL) {
642
+ if (errno != 0)
643
+ goto error;
644
+ break;
645
+ }
646
+
647
+ if (strcmp(res->d_name, ".") == 0 || strcmp(res->d_name, "..") == 0)
648
+ continue;
649
+
650
+ dirent = &dir->dirents[dirent_idx];
651
+ dirent->name = uv__strdup(res->d_name);
652
+
653
+ if (dirent->name == NULL)
654
+ goto error;
655
+
656
+ dirent->type = uv__fs_get_dirent_type(res);
657
+ ++dirent_idx;
658
+ }
659
+
660
+ return dirent_idx;
661
+
662
+ error:
663
+ for (i = 0; i < dirent_idx; ++i) {
664
+ uv__free((char*) dir->dirents[i].name);
665
+ dir->dirents[i].name = NULL;
666
+ }
667
+
668
+ return -1;
669
+ }
670
+
671
+ static int uv__fs_closedir(uv_fs_t* req) {
672
+ uv_dir_t* dir;
673
+
674
+ dir = req->ptr;
675
+
676
+ if (dir->dir != NULL) {
677
+ closedir(dir->dir);
678
+ dir->dir = NULL;
679
+ }
680
+
681
+ uv__free(req->ptr);
682
+ req->ptr = NULL;
683
+ return 0;
374
684
  }
375
685
 
686
+ static int uv__fs_statfs(uv_fs_t* req) {
687
+ uv_statfs_t* stat_fs;
688
+ #if defined(__sun) || \
689
+ defined(__MVS__) || \
690
+ defined(__NetBSD__) || \
691
+ defined(__HAIKU__) || \
692
+ defined(__QNX__)
693
+ struct statvfs buf;
694
+
695
+ if (0 != statvfs(req->path, &buf))
696
+ #else
697
+ struct statfs buf;
698
+
699
+ if (0 != statfs(req->path, &buf))
700
+ #endif /* defined(__sun) */
701
+ return -1;
702
+
703
+ stat_fs = uv__malloc(sizeof(*stat_fs));
704
+ if (stat_fs == NULL) {
705
+ errno = ENOMEM;
706
+ return -1;
707
+ }
708
+
709
+ #if defined(__sun) || \
710
+ defined(__MVS__) || \
711
+ defined(__OpenBSD__) || \
712
+ defined(__NetBSD__) || \
713
+ defined(__HAIKU__) || \
714
+ defined(__QNX__)
715
+ stat_fs->f_type = 0; /* f_type is not supported. */
716
+ #else
717
+ stat_fs->f_type = buf.f_type;
718
+ #endif
719
+ stat_fs->f_bsize = buf.f_bsize;
720
+ stat_fs->f_blocks = buf.f_blocks;
721
+ stat_fs->f_bfree = buf.f_bfree;
722
+ stat_fs->f_bavail = buf.f_bavail;
723
+ stat_fs->f_files = buf.f_files;
724
+ stat_fs->f_ffree = buf.f_ffree;
725
+ req->ptr = stat_fs;
726
+ return 0;
727
+ }
376
728
 
377
729
  static ssize_t uv__fs_pathmax_size(const char* path) {
378
730
  ssize_t pathmax;
379
731
 
380
732
  pathmax = pathconf(path, _PC_PATH_MAX);
381
733
 
382
- if (pathmax == -1) {
383
- #if defined(PATH_MAX)
384
- return PATH_MAX;
385
- #else
386
- return 4096;
387
- #endif
388
- }
734
+ if (pathmax == -1)
735
+ pathmax = UV__PATH_MAX;
389
736
 
390
737
  return pathmax;
391
738
  }
392
739
 
393
740
  static ssize_t uv__fs_readlink(uv_fs_t* req) {
741
+ ssize_t maxlen;
394
742
  ssize_t len;
395
743
  char* buf;
396
744
 
397
- len = uv__fs_pathmax_size(req->path);
398
- buf = uv__malloc(len + 1);
745
+ #if defined(_POSIX_PATH_MAX) || defined(PATH_MAX)
746
+ maxlen = uv__fs_pathmax_size(req->path);
747
+ #else
748
+ /* We may not have a real PATH_MAX. Read size of link. */
749
+ struct stat st;
750
+ int ret;
751
+ ret = uv__lstat(req->path, &st);
752
+ if (ret != 0)
753
+ return -1;
754
+ if (!S_ISLNK(st.st_mode)) {
755
+ errno = EINVAL;
756
+ return -1;
757
+ }
758
+
759
+ maxlen = st.st_size;
760
+
761
+ /* According to readlink(2) lstat can report st_size == 0
762
+ for some symlinks, such as those in /proc or /sys. */
763
+ if (maxlen == 0)
764
+ maxlen = uv__fs_pathmax_size(req->path);
765
+ #endif
766
+
767
+ buf = uv__malloc(maxlen);
399
768
 
400
769
  if (buf == NULL) {
401
770
  errno = ENOMEM;
402
771
  return -1;
403
772
  }
404
773
 
405
- len = readlink(req->path, buf, len);
774
+ #if defined(__MVS__)
775
+ len = os390_readlink(req->path, buf, maxlen);
776
+ #else
777
+ len = readlink(req->path, buf, maxlen);
778
+ #endif
406
779
 
407
780
  if (len == -1) {
408
781
  uv__free(buf);
409
782
  return -1;
410
783
  }
411
784
 
785
+ /* Uncommon case: resize to make room for the trailing nul byte. */
786
+ if (len == maxlen) {
787
+ buf = uv__reallocf(buf, len + 1);
788
+
789
+ if (buf == NULL)
790
+ return -1;
791
+ }
792
+
412
793
  buf[len] = '\0';
413
794
  req->ptr = buf;
414
795
 
@@ -416,8 +797,23 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
416
797
  }
417
798
 
418
799
  static ssize_t uv__fs_realpath(uv_fs_t* req) {
419
- ssize_t len;
420
800
  char* buf;
801
+ char* tmp;
802
+
803
+ #if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L
804
+ tmp = realpath(req->path, NULL);
805
+ if (tmp == NULL)
806
+ return -1;
807
+ buf = uv__strdup(tmp);
808
+ free(tmp); /* _Not_ uv__free. */
809
+ if (buf == NULL) {
810
+ errno = ENOMEM;
811
+ return -1;
812
+ }
813
+ #else
814
+ ssize_t len;
815
+
816
+ (void)tmp;
421
817
 
422
818
  len = uv__fs_pathmax_size(req->path);
423
819
  buf = uv__malloc(len + 1);
@@ -431,6 +827,7 @@ static ssize_t uv__fs_realpath(uv_fs_t* req) {
431
827
  uv__free(buf);
432
828
  return -1;
433
829
  }
830
+ #endif
434
831
 
435
832
  req->ptr = buf;
436
833
 
@@ -539,17 +936,101 @@ static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
539
936
  }
540
937
  }
541
938
 
542
- offset += nread;
543
- nsent += nread;
939
+ offset += nread;
940
+ nsent += nread;
941
+ }
942
+
943
+ out:
944
+ if (nsent != -1)
945
+ req->off = offset;
946
+
947
+ return nsent;
948
+ }
949
+
950
+
951
+ #ifdef __linux__
952
+ /* Pre-4.20 kernels have a bug where CephFS uses the RADOS copy-from command
953
+ * in copy_file_range() when it shouldn't. There is no workaround except to
954
+ * fall back to a regular copy.
955
+ */
956
+ static int uv__is_buggy_cephfs(int fd) {
957
+ struct statfs s;
958
+
959
+ if (-1 == fstatfs(fd, &s))
960
+ return 0;
961
+
962
+ if (s.f_type != /* CephFS */ 0xC36400)
963
+ return 0;
964
+
965
+ return uv__kernel_version() < /* 4.20.0 */ 0x041400;
966
+ }
967
+
968
+
969
+ static int uv__is_cifs_or_smb(int fd) {
970
+ struct statfs s;
971
+
972
+ if (-1 == fstatfs(fd, &s))
973
+ return 0;
974
+
975
+ switch ((unsigned) s.f_type) {
976
+ case 0x0000517Bu: /* SMB */
977
+ case 0xFE534D42u: /* SMB2 */
978
+ case 0xFF534D42u: /* CIFS */
979
+ return 1;
980
+ }
981
+
982
+ return 0;
983
+ }
984
+
985
+
986
+ static ssize_t uv__fs_try_copy_file_range(int in_fd, off_t* off,
987
+ int out_fd, size_t len) {
988
+ static _Atomic int no_copy_file_range_support;
989
+ ssize_t r;
990
+
991
+ if (atomic_load_explicit(&no_copy_file_range_support, memory_order_relaxed)) {
992
+ errno = ENOSYS;
993
+ return -1;
544
994
  }
545
995
 
546
- out:
547
- if (nsent != -1)
548
- req->off = offset;
996
+ r = uv__fs_copy_file_range(in_fd, off, out_fd, NULL, len, 0);
549
997
 
550
- return nsent;
998
+ if (r != -1)
999
+ return r;
1000
+
1001
+ switch (errno) {
1002
+ case EACCES:
1003
+ /* Pre-4.20 kernels have a bug where CephFS uses the RADOS
1004
+ * copy-from command when it shouldn't.
1005
+ */
1006
+ if (uv__is_buggy_cephfs(in_fd))
1007
+ errno = ENOSYS; /* Use fallback. */
1008
+ break;
1009
+ case ENOSYS:
1010
+ atomic_store_explicit(&no_copy_file_range_support, 1, memory_order_relaxed);
1011
+ break;
1012
+ case EPERM:
1013
+ /* It's been reported that CIFS spuriously fails.
1014
+ * Consider it a transient error.
1015
+ */
1016
+ if (uv__is_cifs_or_smb(out_fd))
1017
+ errno = ENOSYS; /* Use fallback. */
1018
+ break;
1019
+ case ENOTSUP:
1020
+ case EXDEV:
1021
+ /* ENOTSUP - it could work on another file system type.
1022
+ * EXDEV - it will not work when in_fd and out_fd are not on the same
1023
+ * mounted filesystem (pre Linux 5.3)
1024
+ */
1025
+ errno = ENOSYS; /* Use fallback. */
1026
+ break;
1027
+ }
1028
+
1029
+ return -1;
551
1030
  }
552
1031
 
1032
+ #endif /* __linux__ */
1033
+
553
1034
 
554
1035
  static ssize_t uv__fs_sendfile(uv_fs_t* req) {
555
1036
  int in_fd;
@@ -562,9 +1043,20 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
562
1043
  {
563
1044
  off_t off;
564
1045
  ssize_t r;
1046
+ size_t len;
1047
+ int try_sendfile;
565
1048
 
566
1049
  off = req->off;
567
- r = sendfile(out_fd, in_fd, &off, req->bufsml[0].len);
1050
+ len = req->bufsml[0].len;
1051
+ try_sendfile = 1;
1052
+
1053
+ #ifdef __linux__
1054
+ r = uv__fs_try_copy_file_range(in_fd, &off, out_fd, len);
1055
+ try_sendfile = (r == -1 && errno == ENOSYS);
1056
+ #endif
1057
+
1058
+ if (try_sendfile)
1059
+ r = sendfile(out_fd, in_fd, &off, len);
568
1060
 
569
1061
  /* sendfile() on SunOS returns EINVAL if the target fd is not a socket but
570
1062
  * it still writes out data. Fortunately, we can detect it by checking if
@@ -586,7 +1078,10 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
586
1078
 
587
1079
  return -1;
588
1080
  }
589
- #elif defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
1081
+ /* sendfile() on iOS(arm64) will throw SIGSYS signal cause crash. */
1082
+ #elif (defined(__APPLE__) && !TARGET_OS_IPHONE) \
1083
+ || defined(__DragonFly__) \
1084
+ || defined(__FreeBSD__)
590
1085
  {
591
1086
  off_t len;
592
1087
  ssize_t r;
@@ -597,6 +1092,17 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
597
1092
  */
598
1093
 
599
1094
  #if defined(__FreeBSD__) || defined(__DragonFly__)
1095
+ #if defined(__FreeBSD__)
1096
+ off_t off;
1097
+
1098
+ off = req->off;
1099
+ r = uv__fs_copy_file_range(in_fd, &off, out_fd, NULL, req->bufsml[0].len, 0);
1100
+ if (r >= 0) {
1101
+ r = off - req->off;
1102
+ req->off = off;
1103
+ return r;
1104
+ }
1105
+ #endif
600
1106
  len = 0;
601
1107
  r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0);
602
1108
  #else
@@ -639,89 +1145,305 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
639
1145
 
640
1146
 
641
1147
  static ssize_t uv__fs_utime(uv_fs_t* req) {
1148
+ #if defined(__linux__) \
1149
+ || defined(_AIX71) \
1150
+ || defined(__sun) \
1151
+ || defined(__HAIKU__)
1152
+ struct timespec ts[2];
1153
+ ts[0] = uv__fs_to_timespec(req->atime);
1154
+ ts[1] = uv__fs_to_timespec(req->mtime);
1155
+ return utimensat(AT_FDCWD, req->path, ts, 0);
1156
+ #elif defined(__APPLE__) \
1157
+ || defined(__DragonFly__) \
1158
+ || defined(__FreeBSD__) \
1159
+ || defined(__NetBSD__) \
1160
+ || defined(__OpenBSD__)
1161
+ struct timeval tv[2];
1162
+ tv[0] = uv__fs_to_timeval(req->atime);
1163
+ tv[1] = uv__fs_to_timeval(req->mtime);
1164
+ return utimes(req->path, tv);
1165
+ #elif defined(_AIX) \
1166
+ && !defined(_AIX71)
642
1167
  struct utimbuf buf;
643
1168
  buf.actime = req->atime;
644
1169
  buf.modtime = req->mtime;
645
- return utime(req->path, &buf); /* TODO use utimes() where available */
1170
+ return utime(req->path, &buf);
1171
+ #elif defined(__MVS__)
1172
+ attrib_t atr;
1173
+ memset(&atr, 0, sizeof(atr));
1174
+ atr.att_mtimechg = 1;
1175
+ atr.att_atimechg = 1;
1176
+ atr.att_mtime = req->mtime;
1177
+ atr.att_atime = req->atime;
1178
+ return __lchattr((char*) req->path, &atr, sizeof(atr));
1179
+ #else
1180
+ errno = ENOSYS;
1181
+ return -1;
1182
+ #endif
646
1183
  }
647
1184
 
648
1185
 
649
- static ssize_t uv__fs_write(uv_fs_t* req) {
650
- #if defined(__linux__)
651
- static int no_pwritev;
1186
+ static ssize_t uv__fs_lutime(uv_fs_t* req) {
1187
+ #if defined(__linux__) || \
1188
+ defined(_AIX71) || \
1189
+ defined(__sun) || \
1190
+ defined(__HAIKU__) || \
1191
+ defined(__GNU__) || \
1192
+ defined(__OpenBSD__)
1193
+ struct timespec ts[2];
1194
+ ts[0] = uv__fs_to_timespec(req->atime);
1195
+ ts[1] = uv__fs_to_timespec(req->mtime);
1196
+ return utimensat(AT_FDCWD, req->path, ts, AT_SYMLINK_NOFOLLOW);
1197
+ #elif defined(__APPLE__) || \
1198
+ defined(__DragonFly__) || \
1199
+ defined(__FreeBSD__) || \
1200
+ defined(__NetBSD__)
1201
+ struct timeval tv[2];
1202
+ tv[0] = uv__fs_to_timeval(req->atime);
1203
+ tv[1] = uv__fs_to_timeval(req->mtime);
1204
+ return lutimes(req->path, tv);
1205
+ #else
1206
+ errno = ENOSYS;
1207
+ return -1;
652
1208
  #endif
1209
+ }
1210
+
1211
+
1212
+ static ssize_t uv__fs_write(uv_fs_t* req) {
1213
+ const struct iovec* bufs;
1214
+ size_t nbufs;
653
1215
  ssize_t r;
1216
+ off_t off;
1217
+ int fd;
1218
+
1219
+ fd = req->file;
1220
+ off = req->off;
1221
+ bufs = (const struct iovec*) req->bufs;
1222
+ nbufs = req->nbufs;
1223
+
1224
+ r = 0;
1225
+ if (off < 0) {
1226
+ if (nbufs == 1)
1227
+ r = write(fd, bufs->iov_base, bufs->iov_len);
1228
+ else if (nbufs > 1)
1229
+ r = writev(fd, bufs, nbufs);
1230
+ } else {
1231
+ if (nbufs == 1)
1232
+ r = pwrite(fd, bufs->iov_base, bufs->iov_len, off);
1233
+ else if (nbufs > 1)
1234
+ r = uv__pwritev(fd, bufs, nbufs, off);
1235
+ }
1236
+
1237
+ return r;
1238
+ }
1239
+
1240
+
1241
+ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
1242
+ uv_fs_t fs_req;
1243
+ uv_file srcfd;
1244
+ uv_file dstfd;
1245
+ struct stat src_statsbuf;
1246
+ struct stat dst_statsbuf;
1247
+ struct timespec times[2];
1248
+ int dst_flags;
1249
+ int result;
1250
+ int err;
1251
+ off_t bytes_to_send;
1252
+ off_t in_offset;
1253
+ off_t bytes_written;
1254
+ size_t bytes_chunk;
1255
+
1256
+ dstfd = -1;
1257
+ err = 0;
1258
+
1259
+ /* Open the source file. */
1260
+ srcfd = uv_fs_open(NULL, &fs_req, req->path, O_RDONLY, 0, NULL);
1261
+ uv_fs_req_cleanup(&fs_req);
1262
+
1263
+ if (srcfd < 0)
1264
+ return srcfd;
1265
+
1266
+ /* Get the source file's mode. */
1267
+ if (uv__fstat(srcfd, &src_statsbuf)) {
1268
+ err = UV__ERR(errno);
1269
+ goto out;
1270
+ }
1271
+
1272
+ dst_flags = O_WRONLY | O_CREAT;
1273
+
1274
+ if (req->flags & UV_FS_COPYFILE_EXCL)
1275
+ dst_flags |= O_EXCL;
1276
+
1277
+ /* Open the destination file. */
1278
+ dstfd = uv_fs_open(NULL,
1279
+ &fs_req,
1280
+ req->new_path,
1281
+ dst_flags,
1282
+ src_statsbuf.st_mode,
1283
+ NULL);
1284
+ uv_fs_req_cleanup(&fs_req);
1285
+
1286
+ if (dstfd < 0) {
1287
+ err = dstfd;
1288
+ goto out;
1289
+ }
1290
+
1291
+ /* If the file is not being opened exclusively, verify that the source and
1292
+ destination are not the same file. If they are the same, bail out early. */
1293
+ if ((req->flags & UV_FS_COPYFILE_EXCL) == 0) {
1294
+ /* Get the destination file's mode. */
1295
+ if (uv__fstat(dstfd, &dst_statsbuf)) {
1296
+ err = UV__ERR(errno);
1297
+ goto out;
1298
+ }
1299
+
1300
+ /* Check if srcfd and dstfd refer to the same file */
1301
+ if (src_statsbuf.st_dev == dst_statsbuf.st_dev &&
1302
+ src_statsbuf.st_ino == dst_statsbuf.st_ino) {
1303
+ goto out;
1304
+ }
654
1305
 
655
- /* Serialize writes on OS X, concurrent write() and pwrite() calls result in
656
- * data loss. We can't use a per-file descriptor lock, the descriptor may be
657
- * a dup().
1306
+ /* Truncate the file in case the destination already existed. */
1307
+ if (ftruncate(dstfd, 0) != 0) {
1308
+ err = UV__ERR(errno);
1309
+
1310
+ /* ftruncate() on ceph-fuse fails with EACCES when the file is created
1311
+ * with read only permissions. Since ftruncate() on a newly created
1312
+ * file is a meaningless operation anyway, detect that condition
1313
+ * and squelch the error.
1314
+ */
1315
+ if (err != UV_EACCES)
1316
+ goto out;
1317
+
1318
+ if (dst_statsbuf.st_size > 0)
1319
+ goto out;
1320
+
1321
+ err = 0;
1322
+ }
1323
+ }
1324
+
1325
+ /**
1326
+ * Change the timestamps of the destination file to match the source file.
658
1327
  */
659
1328
  #if defined(__APPLE__)
660
- static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
661
-
662
- if (pthread_mutex_lock(&lock))
663
- abort();
1329
+ times[0] = src_statsbuf.st_atimespec;
1330
+ times[1] = src_statsbuf.st_mtimespec;
1331
+ #elif defined(_AIX)
1332
+ times[0].tv_sec = src_statsbuf.st_atime;
1333
+ times[0].tv_nsec = src_statsbuf.st_atime_n;
1334
+ times[1].tv_sec = src_statsbuf.st_mtime;
1335
+ times[1].tv_nsec = src_statsbuf.st_mtime_n;
1336
+ #else
1337
+ times[0] = src_statsbuf.st_atim;
1338
+ times[1] = src_statsbuf.st_mtim;
664
1339
  #endif
665
1340
 
666
- if (req->off < 0) {
667
- if (req->nbufs == 1)
668
- r = write(req->file, req->bufs[0].base, req->bufs[0].len);
669
- else
670
- r = writev(req->file, (struct iovec*) req->bufs, req->nbufs);
671
- } else {
672
- if (req->nbufs == 1) {
673
- r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
674
- goto done;
1341
+ if (futimens(dstfd, times) == -1) {
1342
+ err = UV__ERR(errno);
1343
+ goto out;
1344
+ }
1345
+
1346
+ /*
1347
+ * Change the ownership and permissions of the destination file to match the
1348
+ * source file.
1349
+ * `cp -p` does not care about errors here, so we don't either. Reuse the
1350
+ * `result` variable to silence a -Wunused-result warning.
1351
+ */
1352
+ result = fchown(dstfd, src_statsbuf.st_uid, src_statsbuf.st_gid);
1353
+
1354
+ if (fchmod(dstfd, src_statsbuf.st_mode) == -1) {
1355
+ err = UV__ERR(errno);
1356
+ #ifdef __linux__
1357
+ /* fchmod() on CIFS shares always fails with EPERM unless the share is
1358
+ * mounted with "noperm". As fchmod() is a meaningless operation on such
1359
+ * shares anyway, detect that condition and squelch the error.
1360
+ */
1361
+ if (err != UV_EPERM)
1362
+ goto out;
1363
+
1364
+ if (!uv__is_cifs_or_smb(dstfd))
1365
+ goto out;
1366
+
1367
+ err = 0;
1368
+ #else /* !__linux__ */
1369
+ goto out;
1370
+ #endif /* !__linux__ */
1371
+ }
1372
+
1373
+ #ifdef FICLONE
1374
+ if (req->flags & UV_FS_COPYFILE_FICLONE ||
1375
+ req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
1376
+ if (ioctl(dstfd, FICLONE, srcfd) == 0) {
1377
+ /* ioctl() with FICLONE succeeded. */
1378
+ goto out;
1379
+ }
1380
+ /* If an error occurred and force was set, return the error to the caller;
1381
+ * fall back to sendfile() when force was not set. */
1382
+ if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
1383
+ err = UV__ERR(errno);
1384
+ goto out;
675
1385
  }
676
- #if HAVE_PREADV
677
- r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
1386
+ }
678
1387
  #else
679
- # if defined(__linux__)
680
- if (no_pwritev) retry:
681
- # endif
682
- {
683
- off_t written;
684
- size_t index;
685
-
686
- written = 0;
687
- index = 0;
688
- r = 0;
689
- do {
690
- if (req->bufs[index].len > 0) {
691
- r = pwrite(req->file,
692
- req->bufs[index].base,
693
- req->bufs[index].len,
694
- req->off + written);
695
- if (r > 0)
696
- written += r;
697
- }
698
- index++;
699
- } while (index < req->nbufs && r >= 0);
700
- if (written > 0)
701
- r = written;
1388
+ if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) {
1389
+ err = UV_ENOSYS;
1390
+ goto out;
1391
+ }
1392
+ #endif
1393
+
1394
+ bytes_to_send = src_statsbuf.st_size;
1395
+ in_offset = 0;
1396
+ while (bytes_to_send != 0) {
1397
+ bytes_chunk = SSIZE_MAX;
1398
+ if (bytes_to_send < (off_t) bytes_chunk)
1399
+ bytes_chunk = bytes_to_send;
1400
+ uv_fs_sendfile(NULL, &fs_req, dstfd, srcfd, in_offset, bytes_chunk, NULL);
1401
+ bytes_written = fs_req.result;
1402
+ uv_fs_req_cleanup(&fs_req);
1403
+
1404
+ if (bytes_written < 0) {
1405
+ err = bytes_written;
1406
+ break;
702
1407
  }
703
- # if defined(__linux__)
704
- else {
705
- r = uv__pwritev(req->file,
706
- (struct iovec*) req->bufs,
707
- req->nbufs,
708
- req->off);
709
- if (r == -1 && errno == ENOSYS) {
710
- no_pwritev = 1;
711
- goto retry;
712
- }
1408
+
1409
+ bytes_to_send -= bytes_written;
1410
+ in_offset += bytes_written;
1411
+ }
1412
+
1413
+ out:
1414
+ if (err < 0)
1415
+ result = err;
1416
+ else
1417
+ result = 0;
1418
+
1419
+ /* Close the source file. */
1420
+ err = uv__close_nocheckstdio(srcfd);
1421
+
1422
+ /* Don't overwrite any existing errors. */
1423
+ if (err != 0 && result == 0)
1424
+ result = err;
1425
+
1426
+ /* Close the destination file if it is open. */
1427
+ if (dstfd >= 0) {
1428
+ err = uv__close_nocheckstdio(dstfd);
1429
+
1430
+ /* Don't overwrite any existing errors. */
1431
+ if (err != 0 && result == 0)
1432
+ result = err;
1433
+
1434
+ /* Remove the destination file if something went wrong. */
1435
+ if (result != 0) {
1436
+ uv_fs_unlink(NULL, &fs_req, req->new_path, NULL);
1437
+ /* Ignore the unlink return value, as an error already happened. */
1438
+ uv_fs_req_cleanup(&fs_req);
713
1439
  }
714
- # endif
715
- #endif
716
1440
  }
717
1441
 
718
- done:
719
- #if defined(__APPLE__)
720
- if (pthread_mutex_unlock(&lock))
721
- abort();
722
- #endif
1442
+ if (result == 0)
1443
+ return 0;
723
1444
 
724
- return r;
1445
+ errno = UV__ERR(result);
1446
+ return -1;
725
1447
  }
726
1448
 
727
1449
  static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
@@ -749,16 +1471,22 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
749
1471
  dst->st_gen = src->st_gen;
750
1472
  #elif defined(__ANDROID__)
751
1473
  dst->st_atim.tv_sec = src->st_atime;
752
- dst->st_atim.tv_nsec = src->st_atime_nsec;
1474
+ dst->st_atim.tv_nsec = src->st_atimensec;
753
1475
  dst->st_mtim.tv_sec = src->st_mtime;
754
- dst->st_mtim.tv_nsec = src->st_mtime_nsec;
1476
+ dst->st_mtim.tv_nsec = src->st_mtimensec;
755
1477
  dst->st_ctim.tv_sec = src->st_ctime;
756
- dst->st_ctim.tv_nsec = src->st_ctime_nsec;
1478
+ dst->st_ctim.tv_nsec = src->st_ctimensec;
757
1479
  dst->st_birthtim.tv_sec = src->st_ctime;
758
- dst->st_birthtim.tv_nsec = src->st_ctime_nsec;
1480
+ dst->st_birthtim.tv_nsec = src->st_ctimensec;
759
1481
  dst->st_flags = 0;
760
1482
  dst->st_gen = 0;
761
- #elif !defined(_AIX) && ( \
1483
+ #elif !defined(_AIX) && \
1484
+ !defined(__MVS__) && ( \
1485
+ defined(__DragonFly__) || \
1486
+ defined(__FreeBSD__) || \
1487
+ defined(__OpenBSD__) || \
1488
+ defined(__NetBSD__) || \
1489
+ defined(_GNU_SOURCE) || \
762
1490
  defined(_BSD_SOURCE) || \
763
1491
  defined(_SVID_SOURCE) || \
764
1492
  defined(_XOPEN_SOURCE) || \
@@ -769,9 +1497,7 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
769
1497
  dst->st_mtim.tv_nsec = src->st_mtim.tv_nsec;
770
1498
  dst->st_ctim.tv_sec = src->st_ctim.tv_sec;
771
1499
  dst->st_ctim.tv_nsec = src->st_ctim.tv_nsec;
772
- # if defined(__DragonFly__) || \
773
- defined(__FreeBSD__) || \
774
- defined(__OpenBSD__) || \
1500
+ # if defined(__FreeBSD__) || \
775
1501
  defined(__NetBSD__)
776
1502
  dst->st_birthtim.tv_sec = src->st_birthtim.tv_sec;
777
1503
  dst->st_birthtim.tv_nsec = src->st_birthtim.tv_nsec;
@@ -798,11 +1524,79 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) {
798
1524
  }
799
1525
 
800
1526
 
1527
+ static int uv__fs_statx(int fd,
1528
+ const char* path,
1529
+ int is_fstat,
1530
+ int is_lstat,
1531
+ uv_stat_t* buf) {
1532
+ STATIC_ASSERT(UV_ENOSYS != -1);
1533
+ #ifdef __linux__
1534
+ static _Atomic int no_statx;
1535
+ struct uv__statx statxbuf;
1536
+ int dirfd;
1537
+ int flags;
1538
+ int mode;
1539
+ int rc;
1540
+
1541
+ if (atomic_load_explicit(&no_statx, memory_order_relaxed))
1542
+ return UV_ENOSYS;
1543
+
1544
+ dirfd = AT_FDCWD;
1545
+ flags = 0; /* AT_STATX_SYNC_AS_STAT */
1546
+ mode = 0xFFF; /* STATX_BASIC_STATS + STATX_BTIME */
1547
+
1548
+ if (is_fstat) {
1549
+ dirfd = fd;
1550
+ flags |= 0x1000; /* AT_EMPTY_PATH */
1551
+ }
1552
+
1553
+ if (is_lstat)
1554
+ flags |= AT_SYMLINK_NOFOLLOW;
1555
+
1556
+ rc = uv__statx(dirfd, path, flags, mode, &statxbuf);
1557
+
1558
+ switch (rc) {
1559
+ case 0:
1560
+ break;
1561
+ case -1:
1562
+ /* EPERM happens when a seccomp filter rejects the system call.
1563
+ * Has been observed with libseccomp < 2.3.3 and docker < 18.04.
1564
+ * EOPNOTSUPP is used on DVS exported filesystems
1565
+ */
1566
+ if (errno != EINVAL && errno != EPERM && errno != ENOSYS && errno != EOPNOTSUPP)
1567
+ return -1;
1568
+ /* Fall through. */
1569
+ default:
1570
+ /* Normally on success, zero is returned and On error, -1 is returned.
1571
+ * Observed on S390 RHEL running in a docker container with statx not
1572
+ * implemented, rc might return 1 with 0 set as the error code in which
1573
+ * case we return ENOSYS.
1574
+ */
1575
+ atomic_store_explicit(&no_statx, 1, memory_order_relaxed);
1576
+ return UV_ENOSYS;
1577
+ }
1578
+
1579
+ uv__statx_to_stat(&statxbuf, buf);
1580
+
1581
+ return 0;
1582
+ #else
1583
+ return UV_ENOSYS;
1584
+ #endif /* __linux__ */
1585
+ }
1586
+
1587
+
801
1588
  static int uv__fs_stat(const char *path, uv_stat_t *buf) {
802
1589
  struct stat pbuf;
803
1590
  int ret;
804
- ret = stat(path, &pbuf);
805
- uv__to_stat(&pbuf, buf);
1591
+
1592
+ ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 0, buf);
1593
+ if (ret != UV_ENOSYS)
1594
+ return ret;
1595
+
1596
+ ret = uv__stat(path, &pbuf);
1597
+ if (ret == 0)
1598
+ uv__to_stat(&pbuf, buf);
1599
+
806
1600
  return ret;
807
1601
  }
808
1602
 
@@ -810,8 +1604,15 @@ static int uv__fs_stat(const char *path, uv_stat_t *buf) {
810
1604
  static int uv__fs_lstat(const char *path, uv_stat_t *buf) {
811
1605
  struct stat pbuf;
812
1606
  int ret;
813
- ret = lstat(path, &pbuf);
814
- uv__to_stat(&pbuf, buf);
1607
+
1608
+ ret = uv__fs_statx(-1, path, /* is_fstat */ 0, /* is_lstat */ 1, buf);
1609
+ if (ret != UV_ENOSYS)
1610
+ return ret;
1611
+
1612
+ ret = uv__lstat(path, &pbuf);
1613
+ if (ret == 0)
1614
+ uv__to_stat(&pbuf, buf);
1615
+
815
1616
  return ret;
816
1617
  }
817
1618
 
@@ -819,14 +1620,33 @@ static int uv__fs_lstat(const char *path, uv_stat_t *buf) {
819
1620
  static int uv__fs_fstat(int fd, uv_stat_t *buf) {
820
1621
  struct stat pbuf;
821
1622
  int ret;
822
- ret = fstat(fd, &pbuf);
823
- uv__to_stat(&pbuf, buf);
1623
+
1624
+ ret = uv__fs_statx(fd, "", /* is_fstat */ 1, /* is_lstat */ 0, buf);
1625
+ if (ret != UV_ENOSYS)
1626
+ return ret;
1627
+
1628
+ ret = uv__fstat(fd, &pbuf);
1629
+ if (ret == 0)
1630
+ uv__to_stat(&pbuf, buf);
1631
+
824
1632
  return ret;
825
1633
  }
826
1634
 
1635
+ static size_t uv__fs_buf_offset(uv_buf_t* bufs, size_t size) {
1636
+ size_t offset;
1637
+ /* Figure out which bufs are done */
1638
+ for (offset = 0; size > 0 && bufs[offset].len <= size; ++offset)
1639
+ size -= bufs[offset].len;
827
1640
 
828
- typedef ssize_t (*uv__fs_buf_iter_processor)(uv_fs_t* req);
829
- static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process) {
1641
+ /* Fix a partial read/write */
1642
+ if (size > 0) {
1643
+ bufs[offset].base += size;
1644
+ bufs[offset].len -= size;
1645
+ }
1646
+ return offset;
1647
+ }
1648
+
1649
+ static ssize_t uv__fs_write_all(uv_fs_t* req) {
830
1650
  unsigned int iovmax;
831
1651
  unsigned int nbufs;
832
1652
  uv_buf_t* bufs;
@@ -843,7 +1663,10 @@ static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process)
843
1663
  if (req->nbufs > iovmax)
844
1664
  req->nbufs = iovmax;
845
1665
 
846
- result = process(req);
1666
+ do
1667
+ result = uv__fs_write(req);
1668
+ while (result < 0 && errno == EINTR);
1669
+
847
1670
  if (result <= 0) {
848
1671
  if (total == 0)
849
1672
  total = result;
@@ -853,6 +1676,7 @@ static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process)
853
1676
  if (req->off >= 0)
854
1677
  req->off += result;
855
1678
 
1679
+ req->nbufs = uv__fs_buf_offset(req->bufs, result);
856
1680
  req->bufs += req->nbufs;
857
1681
  nbufs -= req->nbufs;
858
1682
  total += result;
@@ -860,7 +1684,9 @@ static ssize_t uv__fs_buf_iter(uv_fs_t* req, uv__fs_buf_iter_processor process)
860
1684
 
861
1685
  if (bufs != req->bufsml)
862
1686
  uv__free(bufs);
1687
+
863
1688
  req->bufs = NULL;
1689
+ req->nbufs = 0;
864
1690
 
865
1691
  return total;
866
1692
  }
@@ -872,7 +1698,8 @@ static void uv__fs_work(struct uv__work* w) {
872
1698
  ssize_t r;
873
1699
 
874
1700
  req = container_of(w, uv_fs_t, work_req);
875
- retry_on_eintr = !(req->fs_type == UV_FS_CLOSE);
1701
+ retry_on_eintr = !(req->fs_type == UV_FS_CLOSE ||
1702
+ req->fs_type == UV_FS_READ);
876
1703
 
877
1704
  do {
878
1705
  errno = 0;
@@ -886,38 +1713,46 @@ static void uv__fs_work(struct uv__work* w) {
886
1713
  X(ACCESS, access(req->path, req->flags));
887
1714
  X(CHMOD, chmod(req->path, req->mode));
888
1715
  X(CHOWN, chown(req->path, req->uid, req->gid));
889
- X(CLOSE, close(req->file));
1716
+ X(CLOSE, uv__fs_close(req->file));
1717
+ X(COPYFILE, uv__fs_copyfile(req));
890
1718
  X(FCHMOD, fchmod(req->file, req->mode));
891
1719
  X(FCHOWN, fchown(req->file, req->uid, req->gid));
1720
+ X(LCHOWN, lchown(req->path, req->uid, req->gid));
892
1721
  X(FDATASYNC, uv__fs_fdatasync(req));
893
1722
  X(FSTAT, uv__fs_fstat(req->file, &req->statbuf));
894
- X(FSYNC, fsync(req->file));
1723
+ X(FSYNC, uv__fs_fsync(req));
895
1724
  X(FTRUNCATE, ftruncate(req->file, req->off));
896
1725
  X(FUTIME, uv__fs_futime(req));
1726
+ X(LUTIME, uv__fs_lutime(req));
897
1727
  X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
898
1728
  X(LINK, link(req->path, req->new_path));
899
1729
  X(MKDIR, mkdir(req->path, req->mode));
900
1730
  X(MKDTEMP, uv__fs_mkdtemp(req));
1731
+ X(MKSTEMP, uv__fs_mkstemp(req));
901
1732
  X(OPEN, uv__fs_open(req));
902
- X(READ, uv__fs_buf_iter(req, uv__fs_read));
1733
+ X(READ, uv__fs_read(req));
903
1734
  X(SCANDIR, uv__fs_scandir(req));
1735
+ X(OPENDIR, uv__fs_opendir(req));
1736
+ X(READDIR, uv__fs_readdir(req));
1737
+ X(CLOSEDIR, uv__fs_closedir(req));
904
1738
  X(READLINK, uv__fs_readlink(req));
905
1739
  X(REALPATH, uv__fs_realpath(req));
906
1740
  X(RENAME, rename(req->path, req->new_path));
907
1741
  X(RMDIR, rmdir(req->path));
908
1742
  X(SENDFILE, uv__fs_sendfile(req));
909
1743
  X(STAT, uv__fs_stat(req->path, &req->statbuf));
1744
+ X(STATFS, uv__fs_statfs(req));
910
1745
  X(SYMLINK, symlink(req->path, req->new_path));
911
1746
  X(UNLINK, unlink(req->path));
912
1747
  X(UTIME, uv__fs_utime(req));
913
- X(WRITE, uv__fs_buf_iter(req, uv__fs_write));
1748
+ X(WRITE, uv__fs_write_all(req));
914
1749
  default: abort();
915
1750
  }
916
1751
  #undef X
917
1752
  } while (r == -1 && errno == EINTR && retry_on_eintr);
918
1753
 
919
1754
  if (r == -1)
920
- req->result = -errno;
1755
+ req->result = UV__ERR(errno);
921
1756
  else
922
1757
  req->result = r;
923
1758
 
@@ -933,17 +1768,27 @@ static void uv__fs_done(struct uv__work* w, int status) {
933
1768
  uv_fs_t* req;
934
1769
 
935
1770
  req = container_of(w, uv_fs_t, work_req);
936
- uv__req_unregister(req->loop, req);
1771
+ uv__req_unregister(req->loop);
937
1772
 
938
- if (status == -ECANCELED) {
1773
+ if (status == UV_ECANCELED) {
939
1774
  assert(req->result == 0);
940
- req->result = -ECANCELED;
1775
+ req->result = UV_ECANCELED;
941
1776
  }
942
1777
 
943
1778
  req->cb(req);
944
1779
  }
945
1780
 
946
1781
 
1782
+ void uv__fs_post(uv_loop_t* loop, uv_fs_t* req) {
1783
+ uv__req_register(loop);
1784
+ uv__work_submit(loop,
1785
+ &req->work_req,
1786
+ UV__WORK_FAST_IO,
1787
+ uv__fs_work,
1788
+ uv__fs_done);
1789
+ }
1790
+
1791
+
947
1792
  int uv_fs_access(uv_loop_t* loop,
948
1793
  uv_fs_t* req,
949
1794
  const char* path,
@@ -985,6 +1830,9 @@ int uv_fs_chown(uv_loop_t* loop,
985
1830
  int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
986
1831
  INIT(CLOSE);
987
1832
  req->file = file;
1833
+ if (cb != NULL)
1834
+ if (uv__iou_fs_close(loop, req))
1835
+ return 0;
988
1836
  POST;
989
1837
  }
990
1838
 
@@ -1015,9 +1863,26 @@ int uv_fs_fchown(uv_loop_t* loop,
1015
1863
  }
1016
1864
 
1017
1865
 
1866
+ int uv_fs_lchown(uv_loop_t* loop,
1867
+ uv_fs_t* req,
1868
+ const char* path,
1869
+ uv_uid_t uid,
1870
+ uv_gid_t gid,
1871
+ uv_fs_cb cb) {
1872
+ INIT(LCHOWN);
1873
+ PATH;
1874
+ req->uid = uid;
1875
+ req->gid = gid;
1876
+ POST;
1877
+ }
1878
+
1879
+
1018
1880
  int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1019
1881
  INIT(FDATASYNC);
1020
1882
  req->file = file;
1883
+ if (cb != NULL)
1884
+ if (uv__iou_fs_fsync_or_fdatasync(loop, req, /* IORING_FSYNC_DATASYNC */ 1))
1885
+ return 0;
1021
1886
  POST;
1022
1887
  }
1023
1888
 
@@ -1025,6 +1890,9 @@ int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1025
1890
  int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1026
1891
  INIT(FSTAT);
1027
1892
  req->file = file;
1893
+ if (cb != NULL)
1894
+ if (uv__iou_fs_statx(loop, req, /* is_fstat */ 1, /* is_lstat */ 0))
1895
+ return 0;
1028
1896
  POST;
1029
1897
  }
1030
1898
 
@@ -1032,6 +1900,9 @@ int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1032
1900
  int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) {
1033
1901
  INIT(FSYNC);
1034
1902
  req->file = file;
1903
+ if (cb != NULL)
1904
+ if (uv__iou_fs_fsync_or_fdatasync(loop, req, /* no flags */ 0))
1905
+ return 0;
1035
1906
  POST;
1036
1907
  }
1037
1908
 
@@ -1044,6 +1915,9 @@ int uv_fs_ftruncate(uv_loop_t* loop,
1044
1915
  INIT(FTRUNCATE);
1045
1916
  req->file = file;
1046
1917
  req->off = off;
1918
+ if (cb != NULL)
1919
+ if (uv__iou_fs_ftruncate(loop, req))
1920
+ return 0;
1047
1921
  POST;
1048
1922
  }
1049
1923
 
@@ -1061,10 +1935,26 @@ int uv_fs_futime(uv_loop_t* loop,
1061
1935
  POST;
1062
1936
  }
1063
1937
 
1938
+ int uv_fs_lutime(uv_loop_t* loop,
1939
+ uv_fs_t* req,
1940
+ const char* path,
1941
+ double atime,
1942
+ double mtime,
1943
+ uv_fs_cb cb) {
1944
+ INIT(LUTIME);
1945
+ PATH;
1946
+ req->atime = atime;
1947
+ req->mtime = mtime;
1948
+ POST;
1949
+ }
1950
+
1064
1951
 
1065
1952
  int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
1066
1953
  INIT(LSTAT);
1067
1954
  PATH;
1955
+ if (cb != NULL)
1956
+ if (uv__iou_fs_statx(loop, req, /* is_fstat */ 0, /* is_lstat */ 1))
1957
+ return 0;
1068
1958
  POST;
1069
1959
  }
1070
1960
 
@@ -1076,6 +1966,9 @@ int uv_fs_link(uv_loop_t* loop,
1076
1966
  uv_fs_cb cb) {
1077
1967
  INIT(LINK);
1078
1968
  PATH2;
1969
+ if (cb != NULL)
1970
+ if (uv__iou_fs_link(loop, req))
1971
+ return 0;
1079
1972
  POST;
1080
1973
  }
1081
1974
 
@@ -1088,6 +1981,9 @@ int uv_fs_mkdir(uv_loop_t* loop,
1088
1981
  INIT(MKDIR);
1089
1982
  PATH;
1090
1983
  req->mode = mode;
1984
+ if (cb != NULL)
1985
+ if (uv__iou_fs_mkdir(loop, req))
1986
+ return 0;
1091
1987
  POST;
1092
1988
  }
1093
1989
 
@@ -1098,11 +1994,20 @@ int uv_fs_mkdtemp(uv_loop_t* loop,
1098
1994
  uv_fs_cb cb) {
1099
1995
  INIT(MKDTEMP);
1100
1996
  req->path = uv__strdup(tpl);
1101
- if (req->path == NULL) {
1102
- if (cb != NULL)
1103
- uv__req_unregister(loop, req);
1104
- return -ENOMEM;
1105
- }
1997
+ if (req->path == NULL)
1998
+ return UV_ENOMEM;
1999
+ POST;
2000
+ }
2001
+
2002
+
2003
+ int uv_fs_mkstemp(uv_loop_t* loop,
2004
+ uv_fs_t* req,
2005
+ const char* tpl,
2006
+ uv_fs_cb cb) {
2007
+ INIT(MKSTEMP);
2008
+ req->path = uv__strdup(tpl);
2009
+ if (req->path == NULL)
2010
+ return UV_ENOMEM;
1106
2011
  POST;
1107
2012
  }
1108
2013
 
@@ -1117,6 +2022,9 @@ int uv_fs_open(uv_loop_t* loop,
1117
2022
  PATH;
1118
2023
  req->flags = flags;
1119
2024
  req->mode = mode;
2025
+ if (cb != NULL)
2026
+ if (uv__iou_fs_open(loop, req))
2027
+ return 0;
1120
2028
  POST;
1121
2029
  }
1122
2030
 
@@ -1127,26 +2035,32 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
1127
2035
  unsigned int nbufs,
1128
2036
  int64_t off,
1129
2037
  uv_fs_cb cb) {
2038
+ INIT(READ);
2039
+
1130
2040
  if (bufs == NULL || nbufs == 0)
1131
- return -EINVAL;
2041
+ return UV_EINVAL;
1132
2042
 
1133
- INIT(READ);
2043
+ req->off = off;
1134
2044
  req->file = file;
1135
-
2045
+ req->bufs = (uv_buf_t*) bufs; /* Safe, doesn't mutate |bufs| */
1136
2046
  req->nbufs = nbufs;
2047
+
2048
+ if (cb == NULL)
2049
+ goto post;
2050
+
1137
2051
  req->bufs = req->bufsml;
1138
2052
  if (nbufs > ARRAY_SIZE(req->bufsml))
1139
2053
  req->bufs = uv__malloc(nbufs * sizeof(*bufs));
1140
2054
 
1141
- if (req->bufs == NULL) {
1142
- if (cb != NULL)
1143
- uv__req_unregister(loop, req);
1144
- return -ENOMEM;
1145
- }
2055
+ if (req->bufs == NULL)
2056
+ return UV_ENOMEM;
1146
2057
 
1147
2058
  memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
1148
2059
 
1149
- req->off = off;
2060
+ if (uv__iou_fs_read_or_write(loop, req, /* is_read */ 1))
2061
+ return 0;
2062
+
2063
+ post:
1150
2064
  POST;
1151
2065
  }
1152
2066
 
@@ -1162,6 +2076,40 @@ int uv_fs_scandir(uv_loop_t* loop,
1162
2076
  POST;
1163
2077
  }
1164
2078
 
2079
+ int uv_fs_opendir(uv_loop_t* loop,
2080
+ uv_fs_t* req,
2081
+ const char* path,
2082
+ uv_fs_cb cb) {
2083
+ INIT(OPENDIR);
2084
+ PATH;
2085
+ POST;
2086
+ }
2087
+
2088
+ int uv_fs_readdir(uv_loop_t* loop,
2089
+ uv_fs_t* req,
2090
+ uv_dir_t* dir,
2091
+ uv_fs_cb cb) {
2092
+ INIT(READDIR);
2093
+
2094
+ if (dir == NULL || dir->dir == NULL || dir->dirents == NULL)
2095
+ return UV_EINVAL;
2096
+
2097
+ req->ptr = dir;
2098
+ POST;
2099
+ }
2100
+
2101
+ int uv_fs_closedir(uv_loop_t* loop,
2102
+ uv_fs_t* req,
2103
+ uv_dir_t* dir,
2104
+ uv_fs_cb cb) {
2105
+ INIT(CLOSEDIR);
2106
+
2107
+ if (dir == NULL)
2108
+ return UV_EINVAL;
2109
+
2110
+ req->ptr = dir;
2111
+ POST;
2112
+ }
1165
2113
 
1166
2114
  int uv_fs_readlink(uv_loop_t* loop,
1167
2115
  uv_fs_t* req,
@@ -1190,6 +2138,9 @@ int uv_fs_rename(uv_loop_t* loop,
1190
2138
  uv_fs_cb cb) {
1191
2139
  INIT(RENAME);
1192
2140
  PATH2;
2141
+ if (cb != NULL)
2142
+ if (uv__iou_fs_rename(loop, req))
2143
+ return 0;
1193
2144
  POST;
1194
2145
  }
1195
2146
 
@@ -1220,6 +2171,9 @@ int uv_fs_sendfile(uv_loop_t* loop,
1220
2171
  int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
1221
2172
  INIT(STAT);
1222
2173
  PATH;
2174
+ if (cb != NULL)
2175
+ if (uv__iou_fs_statx(loop, req, /* is_fstat */ 0, /* is_lstat */ 0))
2176
+ return 0;
1223
2177
  POST;
1224
2178
  }
1225
2179
 
@@ -1233,6 +2187,9 @@ int uv_fs_symlink(uv_loop_t* loop,
1233
2187
  INIT(SYMLINK);
1234
2188
  PATH2;
1235
2189
  req->flags = flags;
2190
+ if (cb != NULL)
2191
+ if (uv__iou_fs_symlink(loop, req))
2192
+ return 0;
1236
2193
  POST;
1237
2194
  }
1238
2195
 
@@ -1240,6 +2197,9 @@ int uv_fs_symlink(uv_loop_t* loop,
1240
2197
  int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) {
1241
2198
  INIT(UNLINK);
1242
2199
  PATH;
2200
+ if (cb != NULL)
2201
+ if (uv__iou_fs_unlink(loop, req))
2202
+ return 0;
1243
2203
  POST;
1244
2204
  }
1245
2205
 
@@ -1265,10 +2225,11 @@ int uv_fs_write(uv_loop_t* loop,
1265
2225
  unsigned int nbufs,
1266
2226
  int64_t off,
1267
2227
  uv_fs_cb cb) {
2228
+ INIT(WRITE);
2229
+
1268
2230
  if (bufs == NULL || nbufs == 0)
1269
- return -EINVAL;
2231
+ return UV_EINVAL;
1270
2232
 
1271
- INIT(WRITE);
1272
2233
  req->file = file;
1273
2234
 
1274
2235
  req->nbufs = nbufs;
@@ -1276,35 +2237,83 @@ int uv_fs_write(uv_loop_t* loop,
1276
2237
  if (nbufs > ARRAY_SIZE(req->bufsml))
1277
2238
  req->bufs = uv__malloc(nbufs * sizeof(*bufs));
1278
2239
 
1279
- if (req->bufs == NULL) {
1280
- if (cb != NULL)
1281
- uv__req_unregister(loop, req);
1282
- return -ENOMEM;
1283
- }
2240
+ if (req->bufs == NULL)
2241
+ return UV_ENOMEM;
1284
2242
 
1285
2243
  memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
1286
2244
 
1287
2245
  req->off = off;
2246
+
2247
+ if (cb != NULL)
2248
+ if (uv__iou_fs_read_or_write(loop, req, /* is_read */ 0))
2249
+ return 0;
2250
+
1288
2251
  POST;
1289
2252
  }
1290
2253
 
1291
2254
 
1292
2255
  void uv_fs_req_cleanup(uv_fs_t* req) {
1293
- /* Only necessary for asychronous requests, i.e., requests with a callback.
2256
+ if (req == NULL)
2257
+ return;
2258
+
2259
+ /* Only necessary for asynchronous requests, i.e., requests with a callback.
1294
2260
  * Synchronous ones don't copy their arguments and have req->path and
1295
- * req->new_path pointing to user-owned memory. UV_FS_MKDTEMP is the
1296
- * exception to the rule, it always allocates memory.
2261
+ * req->new_path pointing to user-owned memory. UV_FS_MKDTEMP and
2262
+ * UV_FS_MKSTEMP are the exception to the rule, they always allocate memory.
1297
2263
  */
1298
- if (req->path != NULL && (req->cb != NULL || req->fs_type == UV_FS_MKDTEMP))
2264
+ if (req->path != NULL &&
2265
+ (req->cb != NULL ||
2266
+ req->fs_type == UV_FS_MKDTEMP || req->fs_type == UV_FS_MKSTEMP))
1299
2267
  uv__free((void*) req->path); /* Memory is shared with req->new_path. */
1300
2268
 
1301
2269
  req->path = NULL;
1302
2270
  req->new_path = NULL;
1303
2271
 
2272
+ if (req->fs_type == UV_FS_READDIR && req->ptr != NULL)
2273
+ uv__fs_readdir_cleanup(req);
2274
+
1304
2275
  if (req->fs_type == UV_FS_SCANDIR && req->ptr != NULL)
1305
2276
  uv__fs_scandir_cleanup(req);
1306
2277
 
1307
- if (req->ptr != &req->statbuf)
2278
+ if (req->bufs != req->bufsml)
2279
+ uv__free(req->bufs);
2280
+ req->bufs = NULL;
2281
+
2282
+ if (req->fs_type != UV_FS_OPENDIR && req->ptr != &req->statbuf)
1308
2283
  uv__free(req->ptr);
1309
2284
  req->ptr = NULL;
1310
2285
  }
2286
+
2287
+
2288
+ int uv_fs_copyfile(uv_loop_t* loop,
2289
+ uv_fs_t* req,
2290
+ const char* path,
2291
+ const char* new_path,
2292
+ int flags,
2293
+ uv_fs_cb cb) {
2294
+ INIT(COPYFILE);
2295
+
2296
+ if (flags & ~(UV_FS_COPYFILE_EXCL |
2297
+ UV_FS_COPYFILE_FICLONE |
2298
+ UV_FS_COPYFILE_FICLONE_FORCE)) {
2299
+ return UV_EINVAL;
2300
+ }
2301
+
2302
+ PATH2;
2303
+ req->flags = flags;
2304
+ POST;
2305
+ }
2306
+
2307
+
2308
+ int uv_fs_statfs(uv_loop_t* loop,
2309
+ uv_fs_t* req,
2310
+ const char* path,
2311
+ uv_fs_cb cb) {
2312
+ INIT(STATFS);
2313
+ PATH;
2314
+ POST;
2315
+ }
2316
+
2317
+ int uv_fs_get_system_error(const uv_fs_t* req) {
2318
+ return -req->result;
2319
+ }