passenger 2.1.2 → 2.1.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (244) hide show
  1. data/Rakefile +7 -5
  2. data/doc/Architectural overview.html +729 -1
  3. data/doc/Architectural overview.txt +0 -5
  4. data/doc/Security of user switching support.html +605 -1
  5. data/doc/Users guide.html +110 -106
  6. data/doc/Users guide.txt +49 -0
  7. data/doc/cxxapi/ApplicationPoolServer_8h-source.html +400 -372
  8. data/doc/cxxapi/ApplicationPool_8h-source.html +1 -1
  9. data/doc/cxxapi/Application_8h-source.html +1 -1
  10. data/doc/cxxapi/Bucket_8h-source.html +1 -1
  11. data/doc/cxxapi/CachedFileStat_8h-source.html +56 -65
  12. data/doc/cxxapi/Configuration_8h-source.html +40 -32
  13. data/doc/cxxapi/DirectoryMapper_8h-source.html +1 -1
  14. data/doc/cxxapi/DummySpawnManager_8h-source.html +1 -1
  15. data/doc/cxxapi/Exceptions_8h-source.html +1 -1
  16. data/doc/cxxapi/FileChecker_8h-source.html +29 -30
  17. data/doc/cxxapi/Hooks_8h-source.html +1 -1
  18. data/doc/cxxapi/Logging_8h-source.html +1 -1
  19. data/doc/cxxapi/MessageChannel_8h-source.html +1 -1
  20. data/doc/cxxapi/PoolOptions_8h-source.html +1 -1
  21. data/doc/cxxapi/SpawnManager_8h-source.html +225 -219
  22. data/doc/cxxapi/StandardApplicationPool_8h-source.html +451 -445
  23. data/doc/cxxapi/SystemTime_8h-source.html +1 -1
  24. data/doc/cxxapi/Utils_8h-source.html +201 -140
  25. data/doc/cxxapi/annotated.html +2 -2
  26. data/doc/cxxapi/classClient-members.html +1 -1
  27. data/doc/cxxapi/classClient.html +1 -1
  28. data/doc/cxxapi/classHooks-members.html +1 -1
  29. data/doc/cxxapi/classHooks.html +1 -1
  30. data/doc/cxxapi/classPassenger_1_1Application-members.html +1 -1
  31. data/doc/cxxapi/classPassenger_1_1Application.html +1 -1
  32. data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +1 -1
  33. data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +1 -1
  34. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +1 -1
  35. data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +1 -1
  36. data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
  37. data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +1 -1
  38. data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +1 -1
  39. data/doc/cxxapi/{classPassenger_1_1TempFile-members.html → classPassenger_1_1BufferedUpload-members.html} +5 -5
  40. data/doc/cxxapi/{classPassenger_1_1TempFile.html → classPassenger_1_1BufferedUpload.html} +33 -43
  41. data/doc/cxxapi/classPassenger_1_1BusyException-members.html +1 -1
  42. data/doc/cxxapi/classPassenger_1_1BusyException.html +1 -1
  43. data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +1 -1
  44. data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +1 -1
  45. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +1 -1
  46. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +1 -1
  47. data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +1 -1
  48. data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +1 -1
  49. data/doc/cxxapi/classPassenger_1_1FileChecker-members.html +1 -1
  50. data/doc/cxxapi/classPassenger_1_1FileChecker.html +2 -2
  51. data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +1 -1
  52. data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +1 -1
  53. data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
  54. data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +1 -1
  55. data/doc/cxxapi/classPassenger_1_1FileSystemException.html +1 -1
  56. data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
  57. data/doc/cxxapi/classPassenger_1_1IOException-members.html +1 -1
  58. data/doc/cxxapi/classPassenger_1_1IOException.html +1 -1
  59. data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
  60. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +1 -1
  61. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +1 -1
  62. data/doc/cxxapi/classPassenger_1_1RuntimeException-members.html +1 -1
  63. data/doc/cxxapi/classPassenger_1_1RuntimeException.html +1 -1
  64. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +1 -1
  65. data/doc/cxxapi/classPassenger_1_1SpawnException.html +1 -1
  66. data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +1 -1
  67. data/doc/cxxapi/classPassenger_1_1SpawnManager.html +1 -1
  68. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +1 -1
  69. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +1 -1
  70. data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
  71. data/doc/cxxapi/classPassenger_1_1SystemException-members.html +1 -1
  72. data/doc/cxxapi/classPassenger_1_1SystemException.html +1 -1
  73. data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
  74. data/doc/cxxapi/classPassenger_1_1SystemTime-members.html +1 -1
  75. data/doc/cxxapi/classPassenger_1_1SystemTime.html +1 -1
  76. data/doc/cxxapi/definitions_8h-source.html +1 -1
  77. data/doc/cxxapi/files.html +1 -1
  78. data/doc/cxxapi/functions.html +12 -11
  79. data/doc/cxxapi/functions_func.html +9 -7
  80. data/doc/cxxapi/functions_type.html +1 -1
  81. data/doc/cxxapi/functions_vars.html +2 -4
  82. data/doc/cxxapi/graph_legend.html +1 -1
  83. data/doc/cxxapi/graph_legend.png +0 -0
  84. data/doc/cxxapi/group__Configuration.html +3 -3
  85. data/doc/cxxapi/group__Configuration.png +0 -0
  86. data/doc/cxxapi/group__Core.html +1 -1
  87. data/doc/cxxapi/group__Core.png +0 -0
  88. data/doc/cxxapi/group__Exceptions.html +1 -1
  89. data/doc/cxxapi/group__Hooks.html +1 -1
  90. data/doc/cxxapi/group__Hooks.png +0 -0
  91. data/doc/cxxapi/group__Support.html +33 -16
  92. data/doc/cxxapi/hierarchy.html +2 -2
  93. data/doc/cxxapi/inherit__graph__0.png +0 -0
  94. data/doc/cxxapi/inherit__graph__1.png +0 -0
  95. data/doc/cxxapi/inherit__graph__10.map +1 -1
  96. data/doc/cxxapi/inherit__graph__10.md5 +1 -1
  97. data/doc/cxxapi/inherit__graph__10.png +0 -0
  98. data/doc/cxxapi/inherit__graph__11.map +1 -1
  99. data/doc/cxxapi/inherit__graph__11.md5 +1 -1
  100. data/doc/cxxapi/inherit__graph__11.png +0 -0
  101. data/doc/cxxapi/inherit__graph__12.map +1 -2
  102. data/doc/cxxapi/inherit__graph__12.md5 +1 -1
  103. data/doc/cxxapi/inherit__graph__12.png +0 -0
  104. data/doc/cxxapi/inherit__graph__13.map +2 -1
  105. data/doc/cxxapi/inherit__graph__13.md5 +1 -1
  106. data/doc/cxxapi/inherit__graph__13.png +0 -0
  107. data/doc/cxxapi/inherit__graph__14.map +1 -1
  108. data/doc/cxxapi/inherit__graph__14.md5 +1 -1
  109. data/doc/cxxapi/inherit__graph__14.png +0 -0
  110. data/doc/cxxapi/inherit__graph__15.map +1 -1
  111. data/doc/cxxapi/inherit__graph__15.md5 +1 -1
  112. data/doc/cxxapi/inherit__graph__15.png +0 -0
  113. data/doc/cxxapi/inherit__graph__16.map +1 -1
  114. data/doc/cxxapi/inherit__graph__16.md5 +1 -1
  115. data/doc/cxxapi/inherit__graph__16.png +0 -0
  116. data/doc/cxxapi/inherit__graph__17.map +1 -1
  117. data/doc/cxxapi/inherit__graph__17.md5 +1 -1
  118. data/doc/cxxapi/inherit__graph__17.png +0 -0
  119. data/doc/cxxapi/inherit__graph__18.map +1 -1
  120. data/doc/cxxapi/inherit__graph__18.md5 +1 -1
  121. data/doc/cxxapi/inherit__graph__18.png +0 -0
  122. data/doc/cxxapi/inherit__graph__19.map +1 -2
  123. data/doc/cxxapi/inherit__graph__19.md5 +1 -1
  124. data/doc/cxxapi/inherit__graph__19.png +0 -0
  125. data/doc/cxxapi/inherit__graph__2.png +0 -0
  126. data/doc/cxxapi/inherit__graph__20.map +2 -1
  127. data/doc/cxxapi/inherit__graph__20.md5 +1 -1
  128. data/doc/cxxapi/inherit__graph__20.png +0 -0
  129. data/doc/cxxapi/inherit__graph__21.map +1 -1
  130. data/doc/cxxapi/inherit__graph__21.md5 +1 -1
  131. data/doc/cxxapi/inherit__graph__21.png +0 -0
  132. data/doc/cxxapi/inherit__graph__3.png +0 -0
  133. data/doc/cxxapi/inherit__graph__4.png +0 -0
  134. data/doc/cxxapi/inherit__graph__5.png +0 -0
  135. data/doc/cxxapi/inherit__graph__6.png +0 -0
  136. data/doc/cxxapi/inherit__graph__7.map +1 -1
  137. data/doc/cxxapi/inherit__graph__7.md5 +1 -1
  138. data/doc/cxxapi/inherit__graph__7.png +0 -0
  139. data/doc/cxxapi/inherit__graph__8.map +1 -1
  140. data/doc/cxxapi/inherit__graph__8.md5 +1 -1
  141. data/doc/cxxapi/inherit__graph__8.png +0 -0
  142. data/doc/cxxapi/inherit__graph__9.map +1 -1
  143. data/doc/cxxapi/inherit__graph__9.md5 +1 -1
  144. data/doc/cxxapi/inherit__graph__9.png +0 -0
  145. data/doc/cxxapi/inherits.html +18 -18
  146. data/doc/cxxapi/main.html +1 -1
  147. data/doc/cxxapi/modules.html +1 -1
  148. data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +1 -1
  149. data/doc/cxxapi/structPassenger_1_1AnythingToString.html +1 -1
  150. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +1 -1
  151. data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +1 -1
  152. data/doc/cxxapi/structPassenger_1_1PoolOptions-members.html +1 -1
  153. data/doc/cxxapi/structPassenger_1_1PoolOptions.html +1 -1
  154. data/doc/cxxapi/tree.html +4 -4
  155. data/doc/rdoc/classes/ConditionVariable.html +58 -58
  156. data/doc/rdoc/classes/Exception.html +11 -11
  157. data/doc/rdoc/classes/GC.html +4 -4
  158. data/doc/rdoc/classes/IO.html +14 -14
  159. data/doc/rdoc/classes/PhusionPassenger.html +11 -11
  160. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +1 -1
  161. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +40 -39
  162. data/doc/rdoc/classes/PhusionPassenger/Application.html +14 -14
  163. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +12 -12
  164. data/doc/rdoc/classes/PhusionPassenger/Railz.html +1 -1
  165. data/doc/rdoc/classes/PhusionPassenger/Utils.html +15 -8
  166. data/doc/rdoc/classes/PlatformInfo.html +257 -253
  167. data/doc/rdoc/classes/RakeExtensions.html +2 -2
  168. data/doc/rdoc/classes/Signal.html +26 -26
  169. data/doc/rdoc/created.rid +1 -1
  170. data/doc/rdoc/files/DEVELOPERS_TXT.html +1 -1
  171. data/doc/rdoc/files/README.html +1 -1
  172. data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +1 -1
  173. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +1 -1
  174. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +1 -1
  175. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +1 -1
  176. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +1 -1
  177. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +1 -1
  178. data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +1 -1
  179. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +1 -1
  180. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +1 -1
  181. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +1 -1
  182. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +1 -1
  183. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +1 -1
  184. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +1 -1
  185. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +1 -1
  186. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +1 -1
  187. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +1 -1
  188. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +1 -1
  189. data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +1 -1
  190. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +1 -1
  191. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +1 -1
  192. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +1 -1
  193. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +1 -1
  194. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +1 -1
  195. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +9 -9
  196. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +1 -1
  197. data/doc/rdoc/files/{lib → misc}/rake/extensions_rb.html +2 -2
  198. data/doc/rdoc/fr_file_index.html +1 -1
  199. data/doc/rdoc/fr_method_index.html +22 -22
  200. data/ext/apache2/ApplicationPoolServer.h +43 -15
  201. data/ext/apache2/ApplicationPoolServerExecutable.cpp +27 -52
  202. data/ext/apache2/CachedFileStat.h +7 -16
  203. data/ext/apache2/Configuration.h +9 -1
  204. data/ext/apache2/FileChecker.h +4 -5
  205. data/ext/apache2/Hooks.cpp +20 -22
  206. data/ext/apache2/SpawnManager.h +6 -0
  207. data/ext/apache2/StandardApplicationPool.h +6 -0
  208. data/ext/apache2/Utils.cpp +174 -16
  209. data/ext/apache2/Utils.h +99 -38
  210. data/ext/boost/cstdint.hpp +2 -1
  211. data/ext/oxt/system_calls.cpp +20 -2
  212. data/ext/oxt/system_calls.hpp +2 -0
  213. data/lib/phusion_passenger/abstract_request_handler.rb +5 -1
  214. data/lib/phusion_passenger/admin_tools.rb +1 -1
  215. data/lib/phusion_passenger/admin_tools/control_process.rb +2 -1
  216. data/lib/phusion_passenger/dependencies.rb +7 -4
  217. data/lib/phusion_passenger/platform_info.rb +8 -2
  218. data/lib/phusion_passenger/rack/application_spawner.rb +1 -1
  219. data/lib/phusion_passenger/templates/version_not_found.html.erb +9 -0
  220. data/lib/phusion_passenger/utils.rb +13 -6
  221. data/lib/phusion_passenger/wsgi/application_spawner.rb +1 -1
  222. data/{lib → misc}/rake/cplusplus.rb +0 -0
  223. data/{lib → misc}/rake/extensions.rb +0 -0
  224. data/{lib → misc}/rake/gempackagetask.rb +0 -0
  225. data/{lib → misc}/rake/packagetask.rb +0 -0
  226. data/{lib → misc}/rake/rdoctask.rb +0 -0
  227. data/misc/render_error_pages.rb +6 -5
  228. data/test/CxxTestMain.cpp +109 -7
  229. data/test/UtilsTest.cpp +61 -51
  230. data/test/config.yml.example +6 -2
  231. data/test/integration_tests.rb +4 -0
  232. data/test/ruby/abstract_request_handler_spec.rb +9 -3
  233. data/test/ruby/rack/application_spawner_spec.rb +3 -2
  234. data/test/ruby/rails/application_spawner_spec.rb +15 -4
  235. data/test/ruby/rails/framework_spawner_spec.rb +4 -2
  236. data/test/ruby/rails/spawner_error_handling_spec.rb +4 -4
  237. data/test/ruby/spawn_manager_spec.rb +22 -9
  238. data/test/ruby/utils_spec.rb +18 -12
  239. data/test/ruby/wsgi/application_spawner_spec.rb +16 -7
  240. data/test/stub/apache2/httpd.conf.erb +1 -0
  241. data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
  242. metadata +1064 -1090
  243. data/doc/Users guide Apache.html +0 -3127
  244. data/doc/Users guide Nginx.html +0 -1458
@@ -219,58 +219,114 @@ string canonicalizePath(const string &path);
219
219
  string escapeForXml(const string &input);
220
220
 
221
221
  /**
222
- * Return the path name for the directory in which temporary files are
223
- * to be stored.
222
+ * Given a username that's supposed to be the "lowest user" in the user switching mechanism,
223
+ * checks whether this username exists. If so, this users's UID and GID will be stored into
224
+ * the arguments of the same names. If not, <em>uid</em> and <em>gid</em> will be set to
225
+ * the UID and GID of the "nobody" user. If that user doesn't exist either, then <em>uid</em>
226
+ * and <em>gid</em> will be set to -1.
227
+ */
228
+ void determineLowestUserAndGroup(const string &user, uid_t &uid, gid_t &gid);
229
+
230
+ /**
231
+ * Return the path name for the directory in which the system stores general
232
+ * temporary files. This is usually "/tmp", but might be something else depending
233
+ * on some environment variables.
224
234
  *
225
235
  * @ensure result != NULL
226
236
  * @ingroup Support
227
237
  */
228
- const char *getTempDir();
238
+ const char *getSystemTempDir();
229
239
 
230
240
  /**
231
241
  * Return the path name for the directory in which Phusion Passenger-specific
232
242
  * temporary files are to be stored. This directory is unique for this instance
233
243
  * of the web server in which Phusion Passenger is running.
234
244
  *
235
- * The result will be cached into the PHUSION_PASSENGER_TMP environment variable,
236
- * which will be used for future calls to this function. To bypass this cache,
245
+ * If the environment variable PASSENGER_INSTANCE_TEMP_DIR is set, then that value
246
+ * will be returned. If this environment variable is not set, then it will be set
247
+ * with the return value.
248
+ *
249
+ * To bypass the usage of the PASSENGER_INSTANCE_TEMP_DIR environment variable,
237
250
  * set 'bypassCache' to true.
238
251
  *
252
+ * @param bypassCache Whether PASSENGER_INSTANCE_TEMP_DIR should be bypassed.
253
+ * @param systemTempDir The directory under which the Phusion Passenger-specific
254
+ * temp directory should be located. If set to the empty string,
255
+ * then the return value of getSystemTempDir() will be used.
239
256
  * @ensure !result.empty()
240
257
  * @ingroup Support
241
258
  */
242
- string getPassengerTempDir(bool bypassCache = false);
259
+ string getPassengerTempDir(bool bypassCache = false, const string &systemTempDir = "");
243
260
 
244
- /* Create a temp folder for storing Phusion Passenger-specific temp files,
245
- * such as temporarily buffered uploads, sockets for backend processes, etc.
246
- * This call also sets the PHUSION_PASSENGER_TMP environment variable, which
247
- * allows backend processes to find this temp folder.
261
+ /* Create a temp directory under <em>systemTempDir</em>, for storing Phusion
262
+ * Passenger-specific temp files, such as temporarily buffered uploads,
263
+ * sockets for backend processes, etc. This call also sets the
264
+ * PASSENGER_INSTANCE_TEMP_DIR environment variable, which allows subprocesses
265
+ * to find this temp directory.
266
+ *
267
+ * The created temp directory will have several subdirectories:
268
+ * - webserver_private - for storing the web server's buffered uploads.
269
+ * - info - for storing files that allow external tools to query information
270
+ * about a running Phusion Passenger instance.
271
+ * - backends - for storing Unix sockets created by backend processes.
272
+ * - var - for storing all other kinds of temp files that the backend processes
273
+ * create.
248
274
  *
249
- * Does nothing if this folder already exists.
275
+ * If a (sub)directory already exists, then it will not result in an error.
250
276
  *
277
+ * The <em>userSwitching</em> and <em>lowestUser</em> arguments passed to
278
+ * this method are used for determining the optimal permissions for the
279
+ * (sub)directories. The permissions will be set as tightly as possible based
280
+ * on the values. The <em>workerUid</em> and <em>workerGid</em> arguments
281
+ * will be used for determining the owner of certain subdirectories.
282
+ *
283
+ * @note You should only call this method inside the web server's master
284
+ * process. In case of Apache, this is the Apache control process,
285
+ * the one that tends to run as root. This is because this function
286
+ * will set directory permissions and owners/groups, which may require
287
+ * root privileges.
288
+ *
289
+ * @param systemTempDir The directory under which the Phusion Passenger-specific
290
+ * temp directory should be created. You should normally
291
+ * specify the return value of getSystemTempDir().
292
+ * @param userSwitching Whether user switching is turned on.
293
+ * @param lowestUser The user that the spawn manager and the pool server will
294
+ * run as, if user switching is turned off.
295
+ * @param workerUid The UID that the web server's worker processes are running
296
+ * as. On Apache, this is the UID that's associated with the
297
+ * 'User' directive.
298
+ * @param workerGid The GID that the web server's worker processes are running
299
+ * as. On Apache, this is the GID that's associated with the
300
+ * 'Group' directive.
251
301
  * @throws IOException Something went wrong.
252
302
  * @throws SystemException Something went wrong.
303
+ * @throws FileSystemException Something went wrong.
253
304
  */
254
- void createPassengerTempDir();
305
+ void createPassengerTempDir(const string &systemTempDir, bool userSwitching,
306
+ const string &lowestUser,
307
+ uid_t workerUid, gid_t workerGid);
255
308
 
256
309
  /**
257
310
  * Create the directory at the given path, creating intermediate directories
258
311
  * if necessary. The created directories' permissions are as specified by the
259
- * 'mode' parameter.
312
+ * 'mode' parameter. You can specify this directory's owner and group through
313
+ * the 'owner' and 'group' parameters. A value of -1 for 'owner' or 'group'
314
+ * means that the owner/group should not be changed.
260
315
  *
261
316
  * If 'path' already exists, then nothing will happen.
262
317
  *
263
318
  * @throws IOException Something went wrong.
264
319
  * @throws SystemException Something went wrong.
320
+ * @throws FileSystemException Something went wrong.
265
321
  */
266
- void makeDirTree(const char *path, const char *mode = "u=rwx,g=,o=");
322
+ void makeDirTree(const string &path, const char *mode = "u=rwx,g=,o=", uid_t owner = -1, gid_t group = -1);
267
323
 
268
324
  /**
269
325
  * Remove an entire directory tree recursively.
270
326
  *
271
- * @throws SystemException Something went wrong.
327
+ * @throws FileSystemException Something went wrong.
272
328
  */
273
- void removeDirTree(const char *path);
329
+ void removeDirTree(const string &path);
274
330
 
275
331
  /**
276
332
  * Check whether the specified directory is a valid Ruby on Rails
@@ -309,53 +365,58 @@ bool verifyWSGIDir(const string &dir, CachedMultiFileStat *mstat = 0,
309
365
  unsigned int throttleRate = 0);
310
366
 
311
367
  /**
312
- * Represents a temporary file. The associated file is automatically
313
- * deleted upon object destruction.
368
+ * Represents a buffered upload file.
314
369
  *
315
370
  * @ingroup Support
316
371
  */
317
- class TempFile {
372
+ class BufferedUpload {
318
373
  public:
319
- /** The filename. If this temp file is anonymous, then the filename is an empty string. */
320
- string filename;
321
374
  /** The file handle. */
322
375
  FILE *handle;
323
376
 
324
377
  /**
325
- * Create an empty, temporary file, and open it for reading and writing.
378
+ * Create an empty upload bufer file, and open it for reading and writing.
326
379
  *
327
- * @param anonymous Set to true if this temp file should be unlinked
328
- * immediately. Anonymous temp files are useful if one just wants
329
- * a big not-in-memory buffer to work with.
330
380
  * @throws SystemException Something went wrong.
331
381
  */
332
- TempFile(const char *identifier = "temp", bool anonymous = true) {
382
+ BufferedUpload(const char *identifier = "temp") {
333
383
  char templ[PATH_MAX];
334
384
  int fd;
335
385
 
336
- snprintf(templ, sizeof(templ), "%s/%s.XXXXXX", getPassengerTempDir().c_str(), identifier);
386
+ snprintf(templ, sizeof(templ), "%s/%s.XXXXXX", getDir().c_str(), identifier);
337
387
  templ[sizeof(templ) - 1] = '\0';
338
388
  fd = mkstemp(templ);
339
389
  if (fd == -1) {
340
390
  char message[1024];
391
+ int e = errno;
392
+
341
393
  snprintf(message, sizeof(message), "Cannot create a temporary file '%s'", templ);
342
394
  message[sizeof(message) - 1] = '\0';
343
- throw SystemException(message, errno);
344
- }
345
- if (anonymous) {
346
- fchmod(fd, 0000);
347
- unlink(templ);
348
- } else {
349
- filename.assign(templ);
395
+ throw SystemException(message, e);
350
396
  }
397
+
398
+ /* We use a POSIX trick here: the file's permissions are set to "u=,g=,o="
399
+ * and the file is deleted immediately from the filesystem, while we
400
+ * keep its file handle open. The result is that no other processes
401
+ * will be able to access this file's contents anymore, except us.
402
+ * We now have an anonymous disk-backed buffer.
403
+ */
404
+ fchmod(fd, 0000);
405
+ unlink(templ);
406
+
351
407
  handle = fdopen(fd, "w+");
352
408
  }
353
409
 
354
- ~TempFile() {
410
+ ~BufferedUpload() {
355
411
  fclose(handle);
356
- if (!filename.empty()) {
357
- unlink(filename.c_str());
358
- }
412
+ }
413
+
414
+ /**
415
+ * Returns the directory in which upload buffer files are stored.
416
+ * This is a subdirectory of the directory returned by getPassengerTempDir().
417
+ */
418
+ static string getDir() {
419
+ return getPassengerTempDir() + "/webserver_private";
359
420
  }
360
421
  };
361
422
 
@@ -123,7 +123,7 @@ namespace boost
123
123
  } // namespace boost
124
124
 
125
125
  #elif defined(__FreeBSD__) && (__FreeBSD__ <= 4) || defined(__osf__) || \
126
- defined(__SOLARIS9__)
126
+ defined(__SOLARIS9__) || defined(__NetBSD__)
127
127
  // FreeBSD, Tru64 and Solaris 9 have an <inttypes.h> that contains much of
128
128
  // what we need.
129
129
  # include <inttypes.h>
@@ -362,6 +362,7 @@ BOOST_HAS_STDINT_H is defined (John Maddock).
362
362
  # define INTMAX_C(value) value##i64
363
363
  # define UINTMAX_C(value) value##ui64
364
364
 
365
+ # elif defined(__NetBSD__)
365
366
  # else
366
367
  // do it the old fashioned way:
367
368
 
@@ -139,7 +139,11 @@ syscalls::recvmsg(int s, struct msghdr *msg, int flags) {
139
139
  ssize_t ret;
140
140
  CHECK_INTERRUPTION(
141
141
  ret == -1,
142
- ret = ::recvmsg(s, msg, flags)
142
+ #ifdef _AIX53
143
+ ret = ::nrecvmsg(s, msg, flags)
144
+ #else
145
+ ret = ::recvmsg(s, msg, flags)
146
+ #endif
143
147
  );
144
148
  return ret;
145
149
  }
@@ -149,7 +153,11 @@ syscalls::sendmsg(int s, const struct msghdr *msg, int flags) {
149
153
  ssize_t ret;
150
154
  CHECK_INTERRUPTION(
151
155
  ret == -1,
152
- ret = ::sendmsg(s, msg, flags)
156
+ #ifdef _AIX53
157
+ ret = ::nsendmsg(s, msg, flags)
158
+ #else
159
+ ret = ::sendmsg(s, msg, flags)
160
+ #endif
153
161
  );
154
162
  return ret;
155
163
  }
@@ -194,6 +202,16 @@ syscalls::fclose(FILE *fp) {
194
202
  return ret;
195
203
  }
196
204
 
205
+ int
206
+ syscalls::stat(const char *path, struct stat *buf) {
207
+ int ret;
208
+ CHECK_INTERRUPTION(
209
+ ret == -1,
210
+ ret = ::stat(path, buf)
211
+ );
212
+ return ret;
213
+ }
214
+
197
215
  time_t
198
216
  syscalls::time(time_t *t) {
199
217
  time_t ret;
@@ -27,6 +27,7 @@
27
27
 
28
28
  #include <boost/thread/tss.hpp>
29
29
  #include <sys/types.h>
30
+ #include <sys/stat.h>
30
31
  #include <sys/wait.h>
31
32
  #include <sys/socket.h>
32
33
  #include <pthread.h>
@@ -131,6 +132,7 @@ namespace oxt {
131
132
 
132
133
  FILE *fopen(const char *path, const char *mode);
133
134
  int fclose(FILE *fp);
135
+ int stat(const char *path, struct stat *buf);
134
136
 
135
137
  time_t time(time_t *t);
136
138
  int usleep(useconds_t usec);
@@ -259,12 +259,16 @@ private
259
259
  else
260
260
  unix_path_max = 100
261
261
  end
262
- @socket_name = "#{passenger_tmpdir}/passenger_backend.#{generate_random_id(:base64)}"
262
+ @socket_name = "#{passenger_tmpdir}/backends/backend.#{generate_random_id(:base64)}"
263
263
  @socket_name = @socket_name.slice(0, unix_path_max - 1)
264
264
  @socket = UNIXServer.new(@socket_name)
265
265
  @socket.listen(BACKLOG_SIZE)
266
266
  @socket_type = "unix"
267
267
  File.chmod(0600, @socket_name)
268
+
269
+ # The SpawnManager class will set tighter permissions on the
270
+ # socket later on. See sendSpawnCommand in SpawnManager.h.
271
+
268
272
  done = true
269
273
  rescue Errno::EADDRINUSE
270
274
  # Do nothing, try again with another name.
@@ -2,7 +2,7 @@ module PhusionPassenger
2
2
 
3
3
  module AdminTools
4
4
  def self.tmpdir
5
- ["PASSENGER_TMPDIR", "TMPDIR"].each do |name|
5
+ ["PASSENGER_TEMP_DIR", "PASSENGER_TMPDIR"].each do |name|
6
6
  if ENV.has_key?(name) && !ENV[name].empty?
7
7
  return ENV[name]
8
8
  end
@@ -27,6 +27,7 @@ class ControlProcess
27
27
  # Stale Passenger temp folder. Clean it up if instructed.
28
28
  if clean_stale
29
29
  puts "*** Cleaning stale folder #{dir}"
30
+ FileUtils.chmod_R(0700, dir) if File.exist?(dir)
30
31
  FileUtils.rm_rf(dir)
31
32
  end
32
33
  end
@@ -70,7 +71,7 @@ class ControlProcess
70
71
  private
71
72
  def reload
72
73
  return if @status
73
- File.open("#{path}/status.fifo", 'r') do |f|
74
+ File.open("#{path}/info/status.fifo", 'r') do |f|
74
75
  channel = MessageChannel.new(f)
75
76
  @status = channel.read_scalar
76
77
  @xml = channel.read_scalar
@@ -129,7 +129,10 @@ module Dependencies # :nodoc: all
129
129
  require 'mkmf'
130
130
  header_dir = Config::CONFIG['rubyhdrdir'] || Config::CONFIG['archdir']
131
131
  result.found(File.exist?("#{header_dir}/ruby.h"))
132
- rescue LoadError
132
+ rescue LoadError, SystemExit
133
+ # On RedHat/Fedora/CentOS, if ruby-devel is not installed then
134
+ # mkmf.rb will print an error and call 'exit'. So here we
135
+ # catch SystemExit.
133
136
  result.not_found
134
137
  end
135
138
  end
@@ -197,7 +200,7 @@ module Dependencies # :nodoc: all
197
200
  end
198
201
  end
199
202
  dep.website = "http://rake.rubyforge.org/"
200
- dep.install_instructions = "Please install RubyGems first, then run <b>#{PlatformInfo::GEM} install rake</b>"
203
+ dep.install_instructions = "Please install RubyGems first, then run <b>#{PlatformInfo::GEM || "gem"} install rake</b>"
201
204
  end
202
205
 
203
206
  Apache2 = Dependency.new do |dep|
@@ -306,7 +309,7 @@ module Dependencies # :nodoc: all
306
309
  result.not_found
307
310
  end
308
311
  end
309
- dep.install_instructions = "Please install RubyGems first, then run <b>#{PlatformInfo::GEM} install fastthread</b>"
312
+ dep.install_instructions = "Please install RubyGems first, then run <b>#{PlatformInfo::GEM || "gem"} install fastthread</b>"
310
313
  end
311
314
 
312
315
  Rack = Dependency.new do |dep|
@@ -323,7 +326,7 @@ module Dependencies # :nodoc: all
323
326
  result.not_found
324
327
  end
325
328
  end
326
- dep.install_instructions = "Please install RubyGems first, then run <b>#{PlatformInfo::GEM} install rack</b>"
329
+ dep.install_instructions = "Please install RubyGems first, then run <b>#{PlatformInfo::GEM || "gem"} install rack</b>"
327
330
  end
328
331
  end
329
332
 
@@ -143,6 +143,8 @@ private
143
143
  if RUBY_PLATFORM =~ /solaris/
144
144
  # Remove flags not supported by GCC
145
145
  flags = flags.split(/ +/).reject{ |f| f =~ /^\-mt/ }.join(' ')
146
+ elsif RUBY_PLATFORM =~ /aix/
147
+ libs << " -Wl,-G -Wl,-brtl"
146
148
  end
147
149
  return [flags, libs]
148
150
  end
@@ -330,14 +332,18 @@ public
330
332
  # when invoking the compiler.
331
333
  def self.portability_cflags
332
334
  # _GLIBCPP__PTHREADS is for fixing Boost compilation on OpenBSD.
333
- flags = ["-D_REENTRANT -D_GLIBCPP__PTHREADS -I/usr/local/include"]
335
+ flags = ["-D_REENTRANT -I/usr/local/include"]
334
336
  if RUBY_PLATFORM =~ /solaris/
335
337
  flags << '-D_XOPEN_SOURCE=500 -D_XPG4_2 -D__EXTENSIONS__ -D__SOLARIS__'
336
338
  flags << '-DBOOST_HAS_STDINT_H' unless RUBY_PLATFORM =~ /solaris2.9/
337
339
  flags << '-D__SOLARIS9__ -DBOOST__STDC_CONSTANT_MACROS_DEFINED' if RUBY_PLATFORM =~ /solaris2.9/
338
340
  flags << '-mcpu=ultrasparc' if RUBY_PLATFORM =~ /sparc/
339
341
  elsif RUBY_PLATFORM =~ /openbsd/
340
- flags << '-DBOOST_HAS_STDINT_H'
342
+ flags << '-DBOOST_HAS_STDINT_H -D_GLIBCPP__PTHREADS'
343
+ elsif RUBY_PLATFORM =~ /aix/
344
+ flags << '-DOXT_DISABLE_BACKTRACES'
345
+ elsif RUBY_PLATFORM =~ /sparc-linux/
346
+ flags << '-DBOOST_SP_USE_PTHREADS'
341
347
  end
342
348
  return flags.compact.join(" ").strip
343
349
  end
@@ -106,7 +106,7 @@ private
106
106
  end
107
107
 
108
108
  def load_rack_app
109
- rackup_code = File.read("config.ru")
109
+ rackup_code = ::File.read("config.ru")
110
110
  eval("Rack::Builder.new {( #{rackup_code}\n )}.to_app", TOPLEVEL_BINDING, "config.ru")
111
111
  end
112
112
  end
@@ -20,6 +20,15 @@
20
20
  </div>
21
21
 
22
22
  <% end %>
23
+
24
+ <p>
25
+ If you are unable to install Ruby on Rails (e.g. because you do not have
26
+ control over this server) then you could also <em>vendor</em> (bundle)
27
+ your Rails version into your application by running <pre>rake vendor:rails</pre>
28
+ in your application's source directory, and redeploying your application.
29
+ Please search the Internet for "vendor rails" if you're not familiar with
30
+ this technique.
31
+ </p>
23
32
 
24
33
  </div>
25
34
  <% end %>
@@ -336,12 +336,19 @@ protected
336
336
  # temporary files. If +create+ is true, then this method creates the
337
337
  # directory if it doesn't exist.
338
338
  def passenger_tmpdir(create = true)
339
- dir = ENV['PHUSION_PASSENGER_TMP']
339
+ dir = ENV['PASSENGER_INSTANCE_TEMP_DIR']
340
340
  if dir.nil? || dir.empty?
341
- dir = Dir.tmpdir
341
+ dir = "#{Dir.tmpdir}/passenger.#{Process.pid}"
342
+ ENV['PASSENGER_INSTANCE_TEMP_DIR'] = dir
342
343
  end
343
344
  if create && !File.exist?(dir)
344
- system("mkdir", "-p", "-m", "u=rwxs,g=wx,o=wx", dir)
345
+ # This is a very minimal implementation of the function
346
+ # passengerCreateTempDir() in Utils.cpp. This implementation
347
+ # is only meant to make the unit tests pass. For production
348
+ # systems one should pre-create the temp directory with
349
+ # passengerCreateTempDir().
350
+ system("mkdir", "-p", "-m", "u=wxs,g=wx,o=wx", dir)
351
+ system("mkdir", "-p", "-m", "u=wxs,g=wx,o=wx", "#{dir}/backends")
345
352
  end
346
353
  return dir
347
354
  end
@@ -484,9 +491,9 @@ module Signal
484
491
  end
485
492
 
486
493
  # Ruby's implementation of UNIXSocket#recv_io and UNIXSocket#send_io
487
- # are broken on 64-bit FreeBSD 7. So we override them with our own
488
- # implementation.
489
- if RUBY_PLATFORM =~ /freebsd/
494
+ # are broken on 64-bit FreeBSD 7 and x86_64/ppc64 OS X. So we override them
495
+ # with our own implementation.
496
+ if RUBY_PLATFORM =~ /freebsd/ || (RUBY_PLATFORM =~ /darwin/ && RUBY_PLATFORM !~ /universal/)
490
497
  require 'socket'
491
498
  UNIXSocket.class_eval do
492
499
  def recv_io