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.
- data/Rakefile +7 -5
- data/doc/Architectural overview.html +729 -1
- data/doc/Architectural overview.txt +0 -5
- data/doc/Security of user switching support.html +605 -1
- data/doc/Users guide.html +110 -106
- data/doc/Users guide.txt +49 -0
- data/doc/cxxapi/ApplicationPoolServer_8h-source.html +400 -372
- data/doc/cxxapi/ApplicationPool_8h-source.html +1 -1
- data/doc/cxxapi/Application_8h-source.html +1 -1
- data/doc/cxxapi/Bucket_8h-source.html +1 -1
- data/doc/cxxapi/CachedFileStat_8h-source.html +56 -65
- data/doc/cxxapi/Configuration_8h-source.html +40 -32
- data/doc/cxxapi/DirectoryMapper_8h-source.html +1 -1
- data/doc/cxxapi/DummySpawnManager_8h-source.html +1 -1
- data/doc/cxxapi/Exceptions_8h-source.html +1 -1
- data/doc/cxxapi/FileChecker_8h-source.html +29 -30
- data/doc/cxxapi/Hooks_8h-source.html +1 -1
- data/doc/cxxapi/Logging_8h-source.html +1 -1
- data/doc/cxxapi/MessageChannel_8h-source.html +1 -1
- data/doc/cxxapi/PoolOptions_8h-source.html +1 -1
- data/doc/cxxapi/SpawnManager_8h-source.html +225 -219
- data/doc/cxxapi/StandardApplicationPool_8h-source.html +451 -445
- data/doc/cxxapi/SystemTime_8h-source.html +1 -1
- data/doc/cxxapi/Utils_8h-source.html +201 -140
- data/doc/cxxapi/annotated.html +2 -2
- data/doc/cxxapi/classClient-members.html +1 -1
- data/doc/cxxapi/classClient.html +1 -1
- data/doc/cxxapi/classHooks-members.html +1 -1
- data/doc/cxxapi/classHooks.html +1 -1
- data/doc/cxxapi/classPassenger_1_1Application-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1Application.html +1 -1
- data/doc/cxxapi/classPassenger_1_1ApplicationPool-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1ApplicationPool.html +1 -1
- data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1ApplicationPoolServer.html +1 -1
- data/doc/cxxapi/classPassenger_1_1ApplicationPool__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1Application_1_1Session-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1Application_1_1Session.html +1 -1
- data/doc/cxxapi/{classPassenger_1_1TempFile-members.html → classPassenger_1_1BufferedUpload-members.html} +5 -5
- data/doc/cxxapi/{classPassenger_1_1TempFile.html → classPassenger_1_1BufferedUpload.html} +33 -43
- data/doc/cxxapi/classPassenger_1_1BusyException-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1BusyException.html +1 -1
- data/doc/cxxapi/classPassenger_1_1ConfigurationException-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1ConfigurationException.html +1 -1
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +1 -1
- data/doc/cxxapi/classPassenger_1_1DummySpawnManager-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1DummySpawnManager.html +1 -1
- data/doc/cxxapi/classPassenger_1_1FileChecker-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1FileChecker.html +2 -2
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException.html +1 -1
- data/doc/cxxapi/classPassenger_1_1FileNotFoundException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1FileSystemException-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1FileSystemException.html +1 -1
- data/doc/cxxapi/classPassenger_1_1FileSystemException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1IOException-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1IOException.html +1 -1
- data/doc/cxxapi/classPassenger_1_1IOException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1MessageChannel.html +1 -1
- data/doc/cxxapi/classPassenger_1_1RuntimeException-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1RuntimeException.html +1 -1
- data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1SpawnException.html +1 -1
- data/doc/cxxapi/classPassenger_1_1SpawnManager-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1SpawnManager.html +1 -1
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool.html +1 -1
- data/doc/cxxapi/classPassenger_1_1StandardApplicationPool__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1SystemException-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1SystemException.html +1 -1
- data/doc/cxxapi/classPassenger_1_1SystemException__inherit__graph.png +0 -0
- data/doc/cxxapi/classPassenger_1_1SystemTime-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1SystemTime.html +1 -1
- data/doc/cxxapi/definitions_8h-source.html +1 -1
- data/doc/cxxapi/files.html +1 -1
- data/doc/cxxapi/functions.html +12 -11
- data/doc/cxxapi/functions_func.html +9 -7
- data/doc/cxxapi/functions_type.html +1 -1
- data/doc/cxxapi/functions_vars.html +2 -4
- data/doc/cxxapi/graph_legend.html +1 -1
- data/doc/cxxapi/graph_legend.png +0 -0
- data/doc/cxxapi/group__Configuration.html +3 -3
- data/doc/cxxapi/group__Configuration.png +0 -0
- data/doc/cxxapi/group__Core.html +1 -1
- data/doc/cxxapi/group__Core.png +0 -0
- data/doc/cxxapi/group__Exceptions.html +1 -1
- data/doc/cxxapi/group__Hooks.html +1 -1
- data/doc/cxxapi/group__Hooks.png +0 -0
- data/doc/cxxapi/group__Support.html +33 -16
- data/doc/cxxapi/hierarchy.html +2 -2
- data/doc/cxxapi/inherit__graph__0.png +0 -0
- data/doc/cxxapi/inherit__graph__1.png +0 -0
- data/doc/cxxapi/inherit__graph__10.map +1 -1
- data/doc/cxxapi/inherit__graph__10.md5 +1 -1
- data/doc/cxxapi/inherit__graph__10.png +0 -0
- data/doc/cxxapi/inherit__graph__11.map +1 -1
- data/doc/cxxapi/inherit__graph__11.md5 +1 -1
- data/doc/cxxapi/inherit__graph__11.png +0 -0
- data/doc/cxxapi/inherit__graph__12.map +1 -2
- data/doc/cxxapi/inherit__graph__12.md5 +1 -1
- data/doc/cxxapi/inherit__graph__12.png +0 -0
- data/doc/cxxapi/inherit__graph__13.map +2 -1
- data/doc/cxxapi/inherit__graph__13.md5 +1 -1
- data/doc/cxxapi/inherit__graph__13.png +0 -0
- data/doc/cxxapi/inherit__graph__14.map +1 -1
- data/doc/cxxapi/inherit__graph__14.md5 +1 -1
- data/doc/cxxapi/inherit__graph__14.png +0 -0
- data/doc/cxxapi/inherit__graph__15.map +1 -1
- data/doc/cxxapi/inherit__graph__15.md5 +1 -1
- data/doc/cxxapi/inherit__graph__15.png +0 -0
- data/doc/cxxapi/inherit__graph__16.map +1 -1
- data/doc/cxxapi/inherit__graph__16.md5 +1 -1
- data/doc/cxxapi/inherit__graph__16.png +0 -0
- data/doc/cxxapi/inherit__graph__17.map +1 -1
- data/doc/cxxapi/inherit__graph__17.md5 +1 -1
- data/doc/cxxapi/inherit__graph__17.png +0 -0
- data/doc/cxxapi/inherit__graph__18.map +1 -1
- data/doc/cxxapi/inherit__graph__18.md5 +1 -1
- data/doc/cxxapi/inherit__graph__18.png +0 -0
- data/doc/cxxapi/inherit__graph__19.map +1 -2
- data/doc/cxxapi/inherit__graph__19.md5 +1 -1
- data/doc/cxxapi/inherit__graph__19.png +0 -0
- data/doc/cxxapi/inherit__graph__2.png +0 -0
- data/doc/cxxapi/inherit__graph__20.map +2 -1
- data/doc/cxxapi/inherit__graph__20.md5 +1 -1
- data/doc/cxxapi/inherit__graph__20.png +0 -0
- data/doc/cxxapi/inherit__graph__21.map +1 -1
- data/doc/cxxapi/inherit__graph__21.md5 +1 -1
- data/doc/cxxapi/inherit__graph__21.png +0 -0
- data/doc/cxxapi/inherit__graph__3.png +0 -0
- data/doc/cxxapi/inherit__graph__4.png +0 -0
- data/doc/cxxapi/inherit__graph__5.png +0 -0
- data/doc/cxxapi/inherit__graph__6.png +0 -0
- data/doc/cxxapi/inherit__graph__7.map +1 -1
- data/doc/cxxapi/inherit__graph__7.md5 +1 -1
- data/doc/cxxapi/inherit__graph__7.png +0 -0
- data/doc/cxxapi/inherit__graph__8.map +1 -1
- data/doc/cxxapi/inherit__graph__8.md5 +1 -1
- data/doc/cxxapi/inherit__graph__8.png +0 -0
- data/doc/cxxapi/inherit__graph__9.map +1 -1
- data/doc/cxxapi/inherit__graph__9.md5 +1 -1
- data/doc/cxxapi/inherit__graph__9.png +0 -0
- data/doc/cxxapi/inherits.html +18 -18
- data/doc/cxxapi/main.html +1 -1
- data/doc/cxxapi/modules.html +1 -1
- data/doc/cxxapi/structPassenger_1_1AnythingToString-members.html +1 -1
- data/doc/cxxapi/structPassenger_1_1AnythingToString.html +1 -1
- data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4-members.html +1 -1
- data/doc/cxxapi/structPassenger_1_1AnythingToString_3_01vector_3_01string_01_4_01_4.html +1 -1
- data/doc/cxxapi/structPassenger_1_1PoolOptions-members.html +1 -1
- data/doc/cxxapi/structPassenger_1_1PoolOptions.html +1 -1
- data/doc/cxxapi/tree.html +4 -4
- data/doc/rdoc/classes/ConditionVariable.html +58 -58
- data/doc/rdoc/classes/Exception.html +11 -11
- data/doc/rdoc/classes/GC.html +4 -4
- data/doc/rdoc/classes/IO.html +14 -14
- data/doc/rdoc/classes/PhusionPassenger.html +11 -11
- data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +1 -1
- data/doc/rdoc/classes/PhusionPassenger/AdminTools/ControlProcess.html +40 -39
- data/doc/rdoc/classes/PhusionPassenger/Application.html +14 -14
- data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +12 -12
- data/doc/rdoc/classes/PhusionPassenger/Railz.html +1 -1
- data/doc/rdoc/classes/PhusionPassenger/Utils.html +15 -8
- data/doc/rdoc/classes/PlatformInfo.html +257 -253
- data/doc/rdoc/classes/RakeExtensions.html +2 -2
- data/doc/rdoc/classes/Signal.html +26 -26
- data/doc/rdoc/created.rid +1 -1
- data/doc/rdoc/files/DEVELOPERS_TXT.html +1 -1
- data/doc/rdoc/files/README.html +1 -1
- data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +9 -9
- data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +1 -1
- data/doc/rdoc/files/{lib → misc}/rake/extensions_rb.html +2 -2
- data/doc/rdoc/fr_file_index.html +1 -1
- data/doc/rdoc/fr_method_index.html +22 -22
- data/ext/apache2/ApplicationPoolServer.h +43 -15
- data/ext/apache2/ApplicationPoolServerExecutable.cpp +27 -52
- data/ext/apache2/CachedFileStat.h +7 -16
- data/ext/apache2/Configuration.h +9 -1
- data/ext/apache2/FileChecker.h +4 -5
- data/ext/apache2/Hooks.cpp +20 -22
- data/ext/apache2/SpawnManager.h +6 -0
- data/ext/apache2/StandardApplicationPool.h +6 -0
- data/ext/apache2/Utils.cpp +174 -16
- data/ext/apache2/Utils.h +99 -38
- data/ext/boost/cstdint.hpp +2 -1
- data/ext/oxt/system_calls.cpp +20 -2
- data/ext/oxt/system_calls.hpp +2 -0
- data/lib/phusion_passenger/abstract_request_handler.rb +5 -1
- data/lib/phusion_passenger/admin_tools.rb +1 -1
- data/lib/phusion_passenger/admin_tools/control_process.rb +2 -1
- data/lib/phusion_passenger/dependencies.rb +7 -4
- data/lib/phusion_passenger/platform_info.rb +8 -2
- data/lib/phusion_passenger/rack/application_spawner.rb +1 -1
- data/lib/phusion_passenger/templates/version_not_found.html.erb +9 -0
- data/lib/phusion_passenger/utils.rb +13 -6
- data/lib/phusion_passenger/wsgi/application_spawner.rb +1 -1
- data/{lib → misc}/rake/cplusplus.rb +0 -0
- data/{lib → misc}/rake/extensions.rb +0 -0
- data/{lib → misc}/rake/gempackagetask.rb +0 -0
- data/{lib → misc}/rake/packagetask.rb +0 -0
- data/{lib → misc}/rake/rdoctask.rb +0 -0
- data/misc/render_error_pages.rb +6 -5
- data/test/CxxTestMain.cpp +109 -7
- data/test/UtilsTest.cpp +61 -51
- data/test/config.yml.example +6 -2
- data/test/integration_tests.rb +4 -0
- data/test/ruby/abstract_request_handler_spec.rb +9 -3
- data/test/ruby/rack/application_spawner_spec.rb +3 -2
- data/test/ruby/rails/application_spawner_spec.rb +15 -4
- data/test/ruby/rails/framework_spawner_spec.rb +4 -2
- data/test/ruby/rails/spawner_error_handling_spec.rb +4 -4
- data/test/ruby/spawn_manager_spec.rb +22 -9
- data/test/ruby/utils_spec.rb +18 -12
- data/test/ruby/wsgi/application_spawner_spec.rb +16 -7
- data/test/stub/apache2/httpd.conf.erb +1 -0
- data/test/stub/wsgi/passenger_wsgi.pyc +0 -0
- metadata +1064 -1090
- data/doc/Users guide Apache.html +0 -3127
- data/doc/Users guide Nginx.html +0 -1458
@@ -403,7 +403,8 @@ private:
|
|
403
403
|
UPDATE_TRACE_POINT();
|
404
404
|
data->disconnect();
|
405
405
|
throw IOException("The ApplicationPool server unexpectedly "
|
406
|
-
"closed the connection
|
406
|
+
"closed the connection while we're reading a response "
|
407
|
+
"for the 'get' command.");
|
407
408
|
}
|
408
409
|
if (args[0] == "ok") {
|
409
410
|
UPDATE_TRACE_POINT();
|
@@ -433,7 +434,8 @@ private:
|
|
433
434
|
}
|
434
435
|
if (!result) {
|
435
436
|
throw IOException("The ApplicationPool server "
|
436
|
-
"unexpectedly closed the connection
|
437
|
+
"unexpectedly closed the connection while "
|
438
|
+
"we're reading the error page data.");
|
437
439
|
}
|
438
440
|
throw SpawnException(args[1], errorPage);
|
439
441
|
} else {
|
@@ -495,7 +497,7 @@ private:
|
|
495
497
|
void shutdownServer() {
|
496
498
|
TRACE_POINT();
|
497
499
|
this_thread::disable_syscall_interruption dsi;
|
498
|
-
int ret;
|
500
|
+
int ret, status;
|
499
501
|
time_t begin;
|
500
502
|
bool done = false;
|
501
503
|
|
@@ -514,21 +516,34 @@ private:
|
|
514
516
|
* Some Apache modules fork(), but don't close file descriptors.
|
515
517
|
* mod_wsgi is one such example. Because of that, closing serverSocket
|
516
518
|
* won't always cause the ApplicationPool server to exit. So we send it a
|
519
|
+
* signal. This must be the same as the oxt/system_calls.hpp interruption
|
517
520
|
* signal.
|
518
521
|
*/
|
519
522
|
syscalls::kill(serverPid, SIGINT);
|
520
523
|
|
521
|
-
ret = syscalls::waitpid(serverPid,
|
524
|
+
ret = syscalls::waitpid(serverPid, &status, WNOHANG);
|
522
525
|
done = ret > 0 || ret == -1;
|
523
526
|
if (!done) {
|
524
527
|
syscalls::usleep(100000);
|
525
528
|
}
|
526
529
|
}
|
527
530
|
if (done) {
|
528
|
-
|
531
|
+
if (ret > 0) {
|
532
|
+
if (WIFEXITED(status)) {
|
533
|
+
P_TRACE(2, "ApplicationPoolServerExecutable exited with exit status " <<
|
534
|
+
WEXITSTATUS(status) << ".");
|
535
|
+
} else if (WIFSIGNALED(status)) {
|
536
|
+
P_TRACE(2, "ApplicationPoolServerExecutable exited because of signal " <<
|
537
|
+
WTERMSIG(status) << ".");
|
538
|
+
} else {
|
539
|
+
P_TRACE(2, "ApplicationPoolServerExecutable exited for an unknown reason.");
|
540
|
+
}
|
541
|
+
} else {
|
542
|
+
P_TRACE(2, "ApplicationPoolServerExecutable exited.");
|
543
|
+
}
|
529
544
|
} else {
|
530
545
|
P_DEBUG("ApplicationPoolServerExecutable not exited in time. Killing it...");
|
531
|
-
syscalls::kill(serverPid,
|
546
|
+
syscalls::kill(serverPid, SIGKILL);
|
532
547
|
syscalls::waitpid(serverPid, NULL, 0);
|
533
548
|
}
|
534
549
|
|
@@ -612,17 +627,12 @@ private:
|
|
612
627
|
TRACE_POINT();
|
613
628
|
char filename[PATH_MAX];
|
614
629
|
int ret;
|
615
|
-
mode_t permissions;
|
616
|
-
|
617
|
-
createPassengerTempDir();
|
630
|
+
mode_t permissions = S_IRUSR | S_IWUSR;
|
618
631
|
|
619
|
-
|
620
|
-
|
621
|
-
} else {
|
622
|
-
permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
623
|
-
}
|
632
|
+
createPassengerTempDir(getSystemTempDir(), m_user.empty(),
|
633
|
+
"nobody", geteuid(), getegid());
|
624
634
|
|
625
|
-
snprintf(filename, sizeof(filename), "%s/status.fifo",
|
635
|
+
snprintf(filename, sizeof(filename), "%s/info/status.fifo",
|
626
636
|
getPassengerTempDir().c_str());
|
627
637
|
filename[PATH_MAX - 1] = '\0';
|
628
638
|
do {
|
@@ -642,6 +652,24 @@ private:
|
|
642
652
|
do {
|
643
653
|
ret = chmod(filename, permissions);
|
644
654
|
} while (ret == -1 && errno == EINTR);
|
655
|
+
|
656
|
+
// Set the FIFO's owner according to whether we're running as root
|
657
|
+
// and whether user switching is enabled.
|
658
|
+
if (geteuid() == 0 && !m_user.empty()) {
|
659
|
+
uid_t uid;
|
660
|
+
gid_t gid;
|
661
|
+
|
662
|
+
determineLowestUserAndGroup(m_user, uid, gid);
|
663
|
+
do {
|
664
|
+
ret = chown(filename, uid, gid);
|
665
|
+
} while (ret == -1 && errno == EINTR);
|
666
|
+
if (errno == -1) {
|
667
|
+
int e = errno;
|
668
|
+
P_WARN("*** WARNING: Unable to set the FIFO file '" <<
|
669
|
+
filename << "' its owner and group to that of user " <<
|
670
|
+
m_user << ": " << strerror(e) << " (" << e << ")");
|
671
|
+
}
|
672
|
+
}
|
645
673
|
}
|
646
674
|
}
|
647
675
|
|
@@ -164,34 +164,9 @@ private:
|
|
164
164
|
*/
|
165
165
|
void lowerPrivilege(const string &username) {
|
166
166
|
struct passwd *entry;
|
167
|
-
int ret, e;
|
168
167
|
|
169
168
|
entry = getpwnam(username.c_str());
|
170
169
|
if (entry != NULL) {
|
171
|
-
do {
|
172
|
-
ret = chown(getPassengerTempDir().c_str(),
|
173
|
-
entry->pw_uid, entry->pw_gid);
|
174
|
-
} while (ret == -1 && errno == EINTR);
|
175
|
-
if (ret == -1) {
|
176
|
-
e = errno;
|
177
|
-
P_WARN("WARNING: Unable to change owner for directory '" <<
|
178
|
-
getPassengerTempDir() << "' to '" << username <<
|
179
|
-
"': " << strerror(e) << " (" << e << ")");
|
180
|
-
} else {
|
181
|
-
do {
|
182
|
-
ret = chmod(getPassengerTempDir().c_str(),
|
183
|
-
S_IRUSR | S_IWUSR | S_IXUSR);
|
184
|
-
} while (ret == -1 && errno == EINTR);
|
185
|
-
if (ret == -1) {
|
186
|
-
e = errno;
|
187
|
-
P_WARN("WARNING: Unable to change "
|
188
|
-
"permissions for directory " <<
|
189
|
-
getPassengerTempDir() << ": " <<
|
190
|
-
strerror(e) <<
|
191
|
-
" (" << e << ")");
|
192
|
-
}
|
193
|
-
}
|
194
|
-
|
195
170
|
if (initgroups(username.c_str(), entry->pw_gid) != 0) {
|
196
171
|
int e = errno;
|
197
172
|
P_WARN("WARNING: Unable to lower ApplicationPoolServerExecutable's "
|
@@ -221,29 +196,22 @@ private:
|
|
221
196
|
}
|
222
197
|
|
223
198
|
static void fatalSignalHandler(int signum) {
|
224
|
-
|
225
|
-
static bool calledBefore = false;
|
199
|
+
char message[1024];
|
226
200
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
sizeof("----------------- Begin gdb output -----------------\n") - 1);
|
242
|
-
system(gdbBacktraceGenerationCommandStr);
|
243
|
-
write(STDERR_FILENO, "----------------- End gdb output -----------------\n",
|
244
|
-
sizeof("----------------- End gdb output -----------------\n") - 1);
|
245
|
-
defaultHandler(signum);
|
246
|
-
}
|
201
|
+
snprintf(message, sizeof(message) - 1,
|
202
|
+
"*** ERROR: ApplicationPoolServerExecutable received fatal signal "
|
203
|
+
"%d. Running gdb to obtain the backtrace:\n\n",
|
204
|
+
signum);
|
205
|
+
message[sizeof(message) - 1] = '\0';
|
206
|
+
write(STDERR_FILENO, message, strlen(message));
|
207
|
+
write(STDERR_FILENO, "----------------- Begin gdb output -----------------\n",
|
208
|
+
sizeof("----------------- Begin gdb output -----------------\n") - 1);
|
209
|
+
system(gdbBacktraceGenerationCommandStr);
|
210
|
+
write(STDERR_FILENO, "----------------- End gdb output -----------------\n",
|
211
|
+
sizeof("----------------- End gdb output -----------------\n") - 1);
|
212
|
+
|
213
|
+
// Invoke default signal handler.
|
214
|
+
kill(getpid(), signum);
|
247
215
|
}
|
248
216
|
|
249
217
|
void setupSignalHandlers() {
|
@@ -259,7 +227,7 @@ private:
|
|
259
227
|
FILE *f;
|
260
228
|
string gdbCommandFile;
|
261
229
|
|
262
|
-
gdbCommandFile = getPassengerTempDir() + "/gdb_backtrace_command.txt";
|
230
|
+
gdbCommandFile = getPassengerTempDir() + "/info/gdb_backtrace_command.txt";
|
263
231
|
f = fopen(gdbCommandFile.c_str(), "w");
|
264
232
|
if (f != NULL) {
|
265
233
|
// Write a file which contains commands for gdb to obtain
|
@@ -276,12 +244,17 @@ private:
|
|
276
244
|
|
277
245
|
// Install the signal handlers.
|
278
246
|
action.sa_handler = fatalSignalHandler;
|
279
|
-
action.sa_flags =
|
247
|
+
action.sa_flags = SA_RESETHAND;
|
280
248
|
sigemptyset(&action.sa_mask);
|
281
|
-
sigaction(
|
249
|
+
sigaction(SIGQUIT, &action, NULL);
|
250
|
+
sigaction(SIGILL, &action, NULL);
|
282
251
|
sigaction(SIGABRT, &action, NULL);
|
283
|
-
sigaction(
|
284
|
-
sigaction(
|
252
|
+
sigaction(SIGFPE, &action, NULL);
|
253
|
+
sigaction(SIGBUS, &action, NULL);
|
254
|
+
sigaction(SIGSEGV, &action, NULL);
|
255
|
+
sigaction(SIGALRM, &action, NULL);
|
256
|
+
sigaction(SIGUSR1, &action, NULL);
|
257
|
+
sigaction(SIGUSR2, &action, NULL);
|
285
258
|
}
|
286
259
|
}
|
287
260
|
|
@@ -299,6 +272,8 @@ public:
|
|
299
272
|
this->serverSocket = serverSocket;
|
300
273
|
this->statusReportFIFO = statusReportFIFO;
|
301
274
|
this->user = user;
|
275
|
+
|
276
|
+
P_TRACE(2, "ApplicationPoolServerExecutable initialized (PID " << getpid() << ")");
|
302
277
|
}
|
303
278
|
|
304
279
|
~Server() {
|
@@ -103,28 +103,19 @@ public:
|
|
103
103
|
* @return 0 if the stat() call succeeded or if no stat() was performed,
|
104
104
|
* -1 if something went wrong while statting the file. In the latter
|
105
105
|
* case, <tt>errno</tt> will be populated with an appropriate error code.
|
106
|
-
* @throws SystemException Something went wrong while retrieving the
|
106
|
+
* @throws SystemException Something went wrong while retrieving the
|
107
|
+
* system time. stat() errors will <em>not</em> result in SystemException
|
108
|
+
* being thrown.
|
107
109
|
* @throws boost::thread_interrupted
|
108
110
|
*/
|
109
111
|
int refresh(unsigned int throttleRate) {
|
110
112
|
time_t currentTime;
|
111
|
-
int ret;
|
112
113
|
|
113
114
|
if (expired(last_time, throttleRate, currentTime)) {
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
* this function again without us returning a
|
119
|
-
* cached EINTR error.
|
120
|
-
*/
|
121
|
-
return -1;
|
122
|
-
} else {
|
123
|
-
last_result = ret;
|
124
|
-
last_errno = errno;
|
125
|
-
last_time = currentTime;
|
126
|
-
return ret;
|
127
|
-
}
|
115
|
+
last_result = syscalls::stat(filename.c_str(), &info);
|
116
|
+
last_errno = errno;
|
117
|
+
last_time = currentTime;
|
118
|
+
return last_result;
|
128
119
|
} else {
|
129
120
|
errno = last_errno;
|
130
121
|
return last_result;
|
data/ext/apache2/Configuration.h
CHANGED
@@ -41,7 +41,7 @@
|
|
41
41
|
*/
|
42
42
|
|
43
43
|
/** Module version number. */
|
44
|
-
#define PASSENGER_VERSION "2.1.
|
44
|
+
#define PASSENGER_VERSION "2.1.3"
|
45
45
|
|
46
46
|
#ifdef __cplusplus
|
47
47
|
#include <set>
|
@@ -301,6 +301,14 @@
|
|
301
301
|
return "nobody";
|
302
302
|
}
|
303
303
|
}
|
304
|
+
|
305
|
+
const char *getTempDir() const {
|
306
|
+
if (tempDir != NULL) {
|
307
|
+
return tempDir;
|
308
|
+
} else {
|
309
|
+
return getSystemTempDir();
|
310
|
+
}
|
311
|
+
}
|
304
312
|
};
|
305
313
|
}
|
306
314
|
|
data/ext/apache2/FileChecker.h
CHANGED
@@ -77,7 +77,9 @@ public:
|
|
77
77
|
* @param throttleRate When set to a non-zero value, throttling will be
|
78
78
|
* enabled. stat() will be called at most once per
|
79
79
|
* throttleRate seconds.
|
80
|
-
* @throws SystemException Something went wrong
|
80
|
+
* @throws SystemException Something went wrong while retrieving the
|
81
|
+
* system time. stat() errors will <em>not</em> result in SystemException
|
82
|
+
* being thrown.
|
81
83
|
* @throws boost::thread_interrupted
|
82
84
|
*/
|
83
85
|
bool changed(unsigned int throttleRate = 0) {
|
@@ -85,10 +87,7 @@ public:
|
|
85
87
|
time_t ctime, mtime;
|
86
88
|
bool result;
|
87
89
|
|
88
|
-
|
89
|
-
ret = cstat.refresh(throttleRate);
|
90
|
-
} while (ret == -1 && errno == EINTR);
|
91
|
-
|
90
|
+
ret = cstat.refresh(throttleRate);
|
92
91
|
if (ret == -1) {
|
93
92
|
ctime = 0;
|
94
93
|
mtime = 0;
|
data/ext/apache2/Hooks.cpp
CHANGED
@@ -53,6 +53,7 @@
|
|
53
53
|
#include <apr_pools.h>
|
54
54
|
#include <apr_strings.h>
|
55
55
|
#include <apr_lib.h>
|
56
|
+
#include <unixd.h>
|
56
57
|
|
57
58
|
using namespace std;
|
58
59
|
using namespace Passenger;
|
@@ -403,7 +404,7 @@ private:
|
|
403
404
|
apr_bucket *b;
|
404
405
|
Application::SessionPtr session;
|
405
406
|
bool expectingUploadData;
|
406
|
-
shared_ptr<
|
407
|
+
shared_ptr<BufferedUpload> uploadData;
|
407
408
|
|
408
409
|
expectingUploadData = ap_should_client_block(r);
|
409
410
|
if (expectingUploadData && atol(lookupHeader(r, "Content-Length"))
|
@@ -490,11 +491,12 @@ private:
|
|
490
491
|
// The API documentation for ap_scan_script_err_brigade() says it
|
491
492
|
// returns HTTP_OK on success, but it actually returns OK.
|
492
493
|
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
494
|
+
/* Manually set the Status header because
|
495
|
+
* ap_scan_script_header_err_brigade() filters it
|
496
|
+
* out. Some broken HTTP clients depend on the
|
497
|
+
* Status header for retrieving the HTTP status.
|
498
|
+
*/
|
499
|
+
if (!r->status_line || *r->status_line == '\0') {
|
498
500
|
r->status_line = apr_psprintf(r->pool,
|
499
501
|
"%d Unknown Status",
|
500
502
|
r->status);
|
@@ -680,9 +682,9 @@ private:
|
|
680
682
|
return APR_SUCCESS;
|
681
683
|
}
|
682
684
|
|
683
|
-
shared_ptr<
|
685
|
+
shared_ptr<BufferedUpload> receiveRequestBody(request_rec *r) {
|
684
686
|
TRACE_POINT();
|
685
|
-
shared_ptr<
|
687
|
+
shared_ptr<BufferedUpload> tempFile(new BufferedUpload());
|
686
688
|
char buf[1024 * 32];
|
687
689
|
apr_off_t len;
|
688
690
|
size_t total_written = 0;
|
@@ -696,7 +698,7 @@ private:
|
|
696
698
|
string message("An error occured while "
|
697
699
|
"buffering HTTP upload data to "
|
698
700
|
"a temporary file in ");
|
699
|
-
message.append(
|
701
|
+
message.append(BufferedUpload::getDir());
|
700
702
|
if (e == ENOSPC) {
|
701
703
|
message.append(". Please make sure "
|
702
704
|
"that this directory has "
|
@@ -723,10 +725,9 @@ private:
|
|
723
725
|
return tempFile;
|
724
726
|
}
|
725
727
|
|
726
|
-
void sendRequestBody(request_rec *r, Application::SessionPtr &session, shared_ptr<
|
728
|
+
void sendRequestBody(request_rec *r, Application::SessionPtr &session, shared_ptr<BufferedUpload> &uploadData) {
|
727
729
|
TRACE_POINT();
|
728
730
|
rewind(uploadData->handle);
|
729
|
-
P_DEBUG("File upload: Content-Length = " << lookupHeader(r, "Content-Length"));
|
730
731
|
while (!feof(uploadData->handle)) {
|
731
732
|
char buf[1024 * 32];
|
732
733
|
size_t size;
|
@@ -765,29 +766,26 @@ public:
|
|
765
766
|
const char *ruby, *user;
|
766
767
|
string applicationPoolServerExe, spawnServer;
|
767
768
|
|
768
|
-
if (config->tempDir != NULL) {
|
769
|
-
setenv("TMPDIR", config->tempDir, 1);
|
770
|
-
} else {
|
771
|
-
unsetenv("TMPDIR");
|
772
|
-
}
|
773
769
|
/*
|
774
770
|
* As described in the comment in init_module, upon (re)starting
|
775
771
|
* Apache, the Hooks constructor is called twice. We unset
|
776
|
-
*
|
772
|
+
* PASSENGER_INSTANCE_TEMP_DIR before calling createPassengerTempDir()
|
777
773
|
* because we want the temp directory's name to contain the PID
|
778
774
|
* of the process in which the Hooks constructor was called for
|
779
775
|
* the second time.
|
780
776
|
*/
|
781
|
-
unsetenv("
|
782
|
-
|
777
|
+
unsetenv("TMPDIR");
|
778
|
+
unsetenv("PASSENGER_INSTANCE_TEMP_DIR");
|
779
|
+
createPassengerTempDir(config->getTempDir(), config->userSwitching,
|
780
|
+
config->getDefaultUser(), unixd_config.user_id,
|
781
|
+
unixd_config.group_id);
|
782
|
+
setenv("TMPDIR", (getPassengerTempDir() + "/var").c_str(), 1);
|
783
783
|
|
784
784
|
ruby = (config->ruby != NULL) ? config->ruby : DEFAULT_RUBY_COMMAND;
|
785
785
|
if (config->userSwitching) {
|
786
786
|
user = "";
|
787
|
-
} else if (config->defaultUser != NULL) {
|
788
|
-
user = config->defaultUser;
|
789
787
|
} else {
|
790
|
-
user =
|
788
|
+
user = config->getDefaultUser();
|
791
789
|
}
|
792
790
|
|
793
791
|
if (config->root == NULL) {
|
data/ext/apache2/SpawnManager.h
CHANGED
@@ -326,6 +326,12 @@ private:
|
|
326
326
|
|
327
327
|
UPDATE_TRACE_POINT();
|
328
328
|
if (args[2] == "unix") {
|
329
|
+
/* Set tighter permissions on the spawned backend process's
|
330
|
+
* Unix socket. We try to make it only readable and writable
|
331
|
+
* by the process that contains the application pool, because
|
332
|
+
* all attempts to connect to a backend process happens
|
333
|
+
* through the application pool.
|
334
|
+
*/
|
329
335
|
int ret;
|
330
336
|
do {
|
331
337
|
ret = chmod(args[1].c_str(), S_IRUSR | S_IWUSR);
|
@@ -356,6 +356,12 @@ private:
|
|
356
356
|
return result.str();
|
357
357
|
}
|
358
358
|
|
359
|
+
/**
|
360
|
+
* Checks whether the given application domain needs to be restarted.
|
361
|
+
*
|
362
|
+
* @throws SystemException Something went wrong while retrieving the system time.
|
363
|
+
* @throws boost::thread_interrupted
|
364
|
+
*/
|
359
365
|
bool needsRestart(const string &appRoot, Domain *domain, const PoolOptions &options) {
|
360
366
|
return domain->alwaysRestartFileStatter.refresh(options.statThrottleRate) == 0
|
361
367
|
|| domain->restartFileChecker.changed(options.statThrottleRate);
|
data/ext/apache2/Utils.cpp
CHANGED
@@ -19,6 +19,7 @@
|
|
19
19
|
*/
|
20
20
|
|
21
21
|
#include <cassert>
|
22
|
+
#include <pwd.h>
|
22
23
|
#include "CachedFileStat.h"
|
23
24
|
#include "Utils.h"
|
24
25
|
|
@@ -217,8 +218,25 @@ escapeForXml(const string &input) {
|
|
217
218
|
return result;
|
218
219
|
}
|
219
220
|
|
221
|
+
void
|
222
|
+
determineLowestUserAndGroup(const string &user, uid_t &uid, gid_t &gid) {
|
223
|
+
struct passwd *ent;
|
224
|
+
|
225
|
+
ent = getpwnam(user.c_str());
|
226
|
+
if (ent == NULL) {
|
227
|
+
ent = getpwnam("nobody");
|
228
|
+
}
|
229
|
+
if (ent == NULL) {
|
230
|
+
uid = (uid_t) -1;
|
231
|
+
gid = (gid_t) -1;
|
232
|
+
} else {
|
233
|
+
uid = ent->pw_uid;
|
234
|
+
gid = ent->pw_gid;
|
235
|
+
}
|
236
|
+
}
|
237
|
+
|
220
238
|
const char *
|
221
|
-
|
239
|
+
getSystemTempDir() {
|
222
240
|
const char *temp_dir = getenv("TMPDIR");
|
223
241
|
if (temp_dir == NULL || *temp_dir == '\0') {
|
224
242
|
temp_dir = "/tmp";
|
@@ -227,11 +245,11 @@ getTempDir() {
|
|
227
245
|
}
|
228
246
|
|
229
247
|
string
|
230
|
-
getPassengerTempDir(bool bypassCache) {
|
248
|
+
getPassengerTempDir(bool bypassCache, const string &systemTempDir) {
|
231
249
|
if (bypassCache) {
|
232
250
|
goto calculateResult;
|
233
251
|
} else {
|
234
|
-
const char *tmp = getenv("
|
252
|
+
const char *tmp = getenv("PASSENGER_INSTANCE_TEMP_DIR");
|
235
253
|
if (tmp != NULL && *tmp != '\0') {
|
236
254
|
return tmp;
|
237
255
|
} else {
|
@@ -240,25 +258,141 @@ getPassengerTempDir(bool bypassCache) {
|
|
240
258
|
}
|
241
259
|
|
242
260
|
calculateResult:
|
243
|
-
const char *temp_dir
|
261
|
+
const char *temp_dir;
|
244
262
|
char buffer[PATH_MAX];
|
245
263
|
|
264
|
+
if (systemTempDir.empty()) {
|
265
|
+
temp_dir = getSystemTempDir();
|
266
|
+
} else {
|
267
|
+
temp_dir = systemTempDir.c_str();
|
268
|
+
}
|
246
269
|
snprintf(buffer, sizeof(buffer), "%s/passenger.%lu",
|
247
270
|
temp_dir, (unsigned long) getpid());
|
248
271
|
buffer[sizeof(buffer) - 1] = '\0';
|
249
|
-
setenv("
|
272
|
+
setenv("PASSENGER_INSTANCE_TEMP_DIR", buffer, 1);
|
250
273
|
return buffer;
|
251
274
|
}
|
252
275
|
|
253
276
|
void
|
254
|
-
createPassengerTempDir(
|
255
|
-
|
277
|
+
createPassengerTempDir(const string &systemTempDir, bool userSwitching,
|
278
|
+
const string &lowestUser, uid_t workerUid, gid_t workerGid) {
|
279
|
+
string tmpDir(getPassengerTempDir(false, systemTempDir));
|
280
|
+
uid_t lowestUid;
|
281
|
+
gid_t lowestGid;
|
282
|
+
|
283
|
+
determineLowestUserAndGroup(lowestUser, lowestUid, lowestGid);
|
284
|
+
|
285
|
+
/* Create the temp directory with the current user as owner (which
|
286
|
+
* is root if the web server was started as root). Only the owner
|
287
|
+
* may write to this directory. Everybody else may only access the
|
288
|
+
* directory. The permissions on the subdirectories will determine
|
289
|
+
* whether a user may access that specific subdirectory.
|
290
|
+
*/
|
291
|
+
makeDirTree(tmpDir, "u=wxs,g=x,o=x");
|
292
|
+
|
293
|
+
/* We want this upload buffer directory to be only accessible by the web server's
|
294
|
+
* worker processs.
|
295
|
+
*
|
296
|
+
* It only makes sense to chown webserver_private to workerUid and workerGid if the web server
|
297
|
+
* is actually able to change the user of the worker processes. That is, if the web server
|
298
|
+
* is running as root.
|
299
|
+
*/
|
300
|
+
if (geteuid() == 0) {
|
301
|
+
makeDirTree(tmpDir + "/webserver_private", "u=wxs,g=,o=", workerUid, workerGid);
|
302
|
+
} else {
|
303
|
+
makeDirTree(tmpDir + "/webserver_private", "u=wxs,g=,o=");
|
304
|
+
}
|
305
|
+
|
306
|
+
/* If the web server is running as root (i.e. user switching is possible to begin with)
|
307
|
+
* but user switching is off...
|
308
|
+
*/
|
309
|
+
if (geteuid() == 0 && !userSwitching) {
|
310
|
+
/* ...then the 'info' subdirectory must be owned by lowestUser, so that only root
|
311
|
+
* or lowestUser can query Phusion Passenger information.
|
312
|
+
*/
|
313
|
+
makeDirTree(tmpDir + "/info", "u=rwxs,g=,o=", lowestUid, lowestGid);
|
314
|
+
} else {
|
315
|
+
/* Otherwise just use the current user and the directory's owner.
|
316
|
+
* This way, only the user that the web server's control process
|
317
|
+
* is running as will be able to query information.
|
318
|
+
*/
|
319
|
+
makeDirTree(tmpDir + "/info", "u=rwxs,g=,o=");
|
320
|
+
}
|
321
|
+
|
322
|
+
if (geteuid() == 0) {
|
323
|
+
if (userSwitching) {
|
324
|
+
/* If user switching is possible and turned on, then each backend
|
325
|
+
* process may be running as a different user, so the backends
|
326
|
+
* subdirectory must be world-writable. However we don't want
|
327
|
+
* everybody to be able to know the sockets' filenames, so
|
328
|
+
* the directory is not readable, not even by its owner.
|
329
|
+
*/
|
330
|
+
makeDirTree(tmpDir + "/backends", "u=wxs,g=wx,o=wx");
|
331
|
+
} else {
|
332
|
+
/* If user switching is off then all backend processes will be
|
333
|
+
* running as lowestUser, so make lowestUser the owner of the
|
334
|
+
* directory. Nobody else (except root) may access this directory.
|
335
|
+
*
|
336
|
+
* The directory is not readable as a security precaution:
|
337
|
+
* nobody should be able to know the sockets' filenames without
|
338
|
+
* having access to the application pool.
|
339
|
+
*/
|
340
|
+
makeDirTree(tmpDir + "/backends", "u=wxs,g=,o=", lowestUid, lowestGid);
|
341
|
+
}
|
342
|
+
} else {
|
343
|
+
/* If user switching is not possible then all backend processes will
|
344
|
+
* be running as the same user as the web server. So we'll make the
|
345
|
+
* backends subdirectory only writable by this user. Nobody else
|
346
|
+
* (except root) may access this subdirectory.
|
347
|
+
*
|
348
|
+
* The directory is not readable as a security precaution:
|
349
|
+
* nobody should be able to know the sockets' filenames without having
|
350
|
+
* access to the application pool.
|
351
|
+
*/
|
352
|
+
makeDirTree(tmpDir + "/backends", "u=wxs,g=,o=");
|
353
|
+
}
|
354
|
+
|
355
|
+
if (geteuid() == 0) {
|
356
|
+
if (userSwitching) {
|
357
|
+
/* If user switching is possible and is on, then each backend
|
358
|
+
* process may be running as a different user. So make the var
|
359
|
+
* directory world-writable.
|
360
|
+
*
|
361
|
+
* The directory is not readable as a security precaution.
|
362
|
+
*/
|
363
|
+
makeDirTree(tmpDir + "/var", "u=wxs,g=wx,o=wx");
|
364
|
+
} else {
|
365
|
+
/* If user switching is off then all backend processes
|
366
|
+
* will be running as lowestUser, so make lowestUser the
|
367
|
+
* owner of the var directory. Only lowestUser may access
|
368
|
+
* the directory.
|
369
|
+
*
|
370
|
+
* The directory is not readble as a security precaution.
|
371
|
+
*/
|
372
|
+
makeDirTree(tmpDir + "/var", "u=wxs,g=,o=", lowestUid, lowestGid);
|
373
|
+
}
|
374
|
+
} else {
|
375
|
+
/* If user switching is not possible then all backend processes will
|
376
|
+
* be running as the same user as the web server. So we'll make the
|
377
|
+
* var subdirectory only accessible by this user. Nobody else
|
378
|
+
* (except root) may access this subdirectory.
|
379
|
+
*
|
380
|
+
* The directory is not readble as a security precaution.
|
381
|
+
*/
|
382
|
+
makeDirTree(tmpDir + "/var", "u=wxs,g=,o=");
|
383
|
+
}
|
256
384
|
}
|
257
385
|
|
258
386
|
void
|
259
|
-
makeDirTree(const
|
387
|
+
makeDirTree(const string &path, const char *mode, uid_t owner, gid_t group) {
|
260
388
|
char command[PATH_MAX + 10];
|
261
|
-
|
389
|
+
struct stat buf;
|
390
|
+
|
391
|
+
if (stat(path.c_str(), &buf) == 0) {
|
392
|
+
return;
|
393
|
+
}
|
394
|
+
|
395
|
+
snprintf(command, sizeof(command), "mkdir -p -m \"%s\" \"%s\"", mode, path.c_str());
|
262
396
|
command[sizeof(command) - 1] = '\0';
|
263
397
|
|
264
398
|
int result;
|
@@ -269,7 +403,8 @@ makeDirTree(const char *path, const char *mode) {
|
|
269
403
|
char message[1024];
|
270
404
|
int e = errno;
|
271
405
|
|
272
|
-
snprintf(message, sizeof(message) - 1, "Cannot create directory '%s'",
|
406
|
+
snprintf(message, sizeof(message) - 1, "Cannot create directory '%s'",
|
407
|
+
path.c_str());
|
273
408
|
message[sizeof(message) - 1] = '\0';
|
274
409
|
if (result == -1) {
|
275
410
|
throw SystemException(message, e);
|
@@ -277,24 +412,47 @@ makeDirTree(const char *path, const char *mode) {
|
|
277
412
|
throw IOException(message);
|
278
413
|
}
|
279
414
|
}
|
415
|
+
|
416
|
+
if (owner != (uid_t) -1 && group != (gid_t) -1) {
|
417
|
+
do {
|
418
|
+
result = chown(path.c_str(), owner, group);
|
419
|
+
} while (result == -1 && errno == EINTR);
|
420
|
+
if (result != 0) {
|
421
|
+
char message[1024];
|
422
|
+
int e = errno;
|
423
|
+
|
424
|
+
snprintf(message, sizeof(message) - 1,
|
425
|
+
"Cannot change the directory '%s' its UID to %lld and GID to %lld",
|
426
|
+
path.c_str(), (long long) owner, (long long) group);
|
427
|
+
message[sizeof(message) - 1] = '\0';
|
428
|
+
throw FileSystemException(message, e, path);
|
429
|
+
}
|
430
|
+
}
|
280
431
|
}
|
281
432
|
|
282
433
|
void
|
283
|
-
removeDirTree(const
|
284
|
-
char command[PATH_MAX +
|
285
|
-
|
434
|
+
removeDirTree(const string &path) {
|
435
|
+
char command[PATH_MAX + 30];
|
436
|
+
int result;
|
437
|
+
|
438
|
+
snprintf(command, sizeof(command), "chmod -R u+rwx \"%s\" 2>/dev/null", path.c_str());
|
286
439
|
command[sizeof(command) - 1] = '\0';
|
440
|
+
do {
|
441
|
+
result = system(command);
|
442
|
+
} while (result == -1 && errno == EINTR);
|
287
443
|
|
288
|
-
|
444
|
+
snprintf(command, sizeof(command), "rm -rf \"%s\"", path.c_str());
|
445
|
+
command[sizeof(command) - 1] = '\0';
|
289
446
|
do {
|
290
447
|
result = system(command);
|
291
448
|
} while (result == -1 && errno == EINTR);
|
292
449
|
if (result == -1) {
|
293
450
|
char message[1024];
|
451
|
+
int e = errno;
|
294
452
|
|
295
|
-
snprintf(message, sizeof(message) - 1, "Cannot
|
453
|
+
snprintf(message, sizeof(message) - 1, "Cannot remove directory '%s'", path.c_str());
|
296
454
|
message[sizeof(message) - 1] = '\0';
|
297
|
-
throw
|
455
|
+
throw FileSystemException(message, e, path);
|
298
456
|
}
|
299
457
|
}
|
300
458
|
|