From c14a1210b0047213af9dd399d14a1a069352950d Mon Sep 17 00:00:00 2001 From: alexpeshkoff Date: Wed, 17 Dec 2014 14:31:02 +0000 Subject: [PATCH] Work in progress on CORE-3632: make all file descriptors, opened by firebird, close on exec() --- configure.ac | 3 + src/burp/burp.cpp | 11 ++-- src/burp/mvol.cpp | 7 ++- src/burp/split/spit.cpp | 3 +- src/common/classes/TempFile.cpp | 4 +- src/common/classes/alloc.cpp | 5 +- src/common/config/config_file.cpp | 3 +- src/common/isc_file.cpp | 2 +- src/common/os/os_utils.h | 7 ++- src/common/os/posix/divorce.cpp | 3 +- src/common/os/posix/guid.cpp | 11 +--- src/common/os/posix/os_utils.cpp | 52 ++++++++++++++-- src/common/os/win32/os_utils.cpp | 10 ++++ src/common/utils.cpp | 3 +- src/jrd/Optimizer.cpp | 14 ++--- src/jrd/ext.cpp | 5 +- src/jrd/jrd.cpp | 2 +- src/jrd/opt.cpp | 3 +- src/jrd/os/posix/unix.cpp | 28 +++------ src/jrd/svc.cpp | 3 +- src/jrd/trace/TraceConfigStorage.cpp | 4 +- src/lock/lock.cpp | 3 +- src/remote/SockAddr.h | 3 +- src/remote/inet.cpp | 69 +++++++++++++++++++--- src/remote/remote.h | 16 +++-- src/remote/server/os/posix/inet_server.cpp | 3 +- src/remote/server/os/win32/srvr_w32.cpp | 3 +- src/remote/server/server.cpp | 9 ++- src/utilities/analyse.cpp | 2 +- src/utilities/gstat/dba.epp | 3 +- src/utilities/nbackup/nbackup.cpp | 13 ++-- src/yvalve/gds.cpp | 12 ++-- src/yvalve/utl.cpp | 9 +-- 33 files changed, 219 insertions(+), 109 deletions(-) diff --git a/configure.ac b/configure.ac index 41a0ad9fbf..ea1b81aa21 100644 --- a/configure.ac +++ b/configure.ac @@ -883,6 +883,9 @@ AC_CHECK_FUNCS(sigset) dnl Check for fallocate() system call AC_CHECK_FUNCS(fallocate) +dnl Check for close_on_exec support +AC_CHECK_FUNCS(accept4) + dnl Semaphores if test "$ac_cv_header_semaphore_h" = "yes"; then AC_SEARCH_LIBS(sem_init, rt pthread) diff --git a/src/burp/burp.cpp b/src/burp/burp.cpp index d841a21cea..3053355862 100644 --- a/src/burp/burp.cpp +++ b/src/burp/burp.cpp @@ -58,6 +58,7 @@ #include "../common/classes/ClumpletWriter.h" #include "../common/classes/Switches.h" #include "../common/IntlUtil.h" +#include "../common/os/os_utils.h" #include "../burp/burpswi.h" #ifdef HAVE_CTYPE_H @@ -768,7 +769,7 @@ int gbak(Firebird::UtilSvc* uSvc) if (tdgbl->sw_redirect == REDIRECT) // not NOREDIRECT, and not NOOUTPUT { // Make sure the status file doesn't already exist - FILE* tmp_outfile = fopen(redirect, fopen_read_type); + FILE* tmp_outfile = os_utils::fopen(redirect, fopen_read_type); if (tmp_outfile) { BURP_print(true, 66, redirect); @@ -776,7 +777,7 @@ int gbak(Firebird::UtilSvc* uSvc) fclose(tmp_outfile); BURP_exit_local(FINI_ERROR, tdgbl); } - if (! (tdgbl->output_file = fopen(redirect, fopen_write_type))) + if (! (tdgbl->output_file = os_utils::fopen(redirect, fopen_write_type))) { BURP_print(true, 66, redirect); // msg 66 can't open status and error output file %s @@ -1862,7 +1863,7 @@ static gbak_action open_files(const TEXT* file1, if ((fil->fil_fd = MVOL_open(nm.c_str(), MODE_WRITE, CREATE_ALWAYS)) == INVALID_HANDLE_VALUE) #else - if ((fil->fil_fd = open(nm.c_str(), MODE_WRITE, open_mask)) == -1) + if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_WRITE, open_mask)) == -1) #endif // WIN_NT { @@ -1970,7 +1971,7 @@ static gbak_action open_files(const TEXT* file1, if ((fil->fil_fd = MVOL_open(nm.c_str(), MODE_READ, OPEN_EXISTING)) == INVALID_HANDLE_VALUE) #else - if ((fil->fil_fd = open(nm.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE) + if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE) #endif { BURP_error(65, true, fil->fil_name.c_str()); @@ -2019,7 +2020,7 @@ static gbak_action open_files(const TEXT* file1, if ((fil->fil_fd = MVOL_open(nm.c_str(), MODE_READ, OPEN_EXISTING)) == INVALID_HANDLE_VALUE) #else - if ((fil->fil_fd = open(nm.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE) + if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE) #endif { BURP_error(65, false, fil->fil_name.c_str()); diff --git a/src/burp/mvol.cpp b/src/burp/mvol.cpp index 1cfc131257..853ddb4406 100644 --- a/src/burp/mvol.cpp +++ b/src/burp/mvol.cpp @@ -44,6 +44,7 @@ #include "../burp/mvol_proto.h" #include "../yvalve/gds_proto.h" #include "../common/gdsassert.h" +#include "../common/os/os_utils.h" #include #include @@ -905,7 +906,7 @@ static DESC next_volume( DESC handle, ULONG mode, bool full_buffer) new_desc = MVOL_open(new_file, mode, OPEN_ALWAYS); if (new_desc == INVALID_HANDLE_VALUE) #else - new_desc = open(new_file, mode, open_mask); + new_desc = os_utils::open(new_file, mode, open_mask); if (new_desc < 0) #endif // WIN_NT { @@ -975,12 +976,12 @@ static void prompt_for_name(SCHAR* name, int length) // Get a location to read from. fb_assert(!tdgbl->uSvc->isService()); - if (isatty(fileno(stdout)) || !(term_out = fopen(TERM_OUTPUT, "w"))) + if (isatty(fileno(stdout)) || !(term_out = os_utils::fopen(TERM_OUTPUT, "w"))) { term_out = stdout; } - if (isatty(fileno(stdin)) || !(term_in = fopen(TERM_INPUT, "r"))) + if (isatty(fileno(stdin)) || !(term_in = os_utils::fopen(TERM_INPUT, "r"))) { term_in = stdin; } diff --git a/src/burp/split/spit.cpp b/src/burp/split/spit.cpp index 28d2f14213..2291f38987 100644 --- a/src/burp/split/spit.cpp +++ b/src/burp/split/spit.cpp @@ -49,6 +49,7 @@ #include "../common/classes/Switches.h" #include "../burp/std_desc.h" #include "../burp/burpswi.h" +#include "../common/os/os_utils.h" #ifdef HAVE_UNISTD_H #include @@ -68,7 +69,7 @@ static DESC open_platf(const char* name, int writeFlag) return CreateFile(name, (writeFlag ? GENERIC_WRITE : GENERIC_READ), 0, NULL, (writeFlag ? CREATE_ALWAYS : OPEN_EXISTING), FILE_ATTRIBUTE_NORMAL, 0); #else - return open(name, (writeFlag ? mode_write : mode_read), mask); + return os_utils::open(name, (writeFlag ? mode_write : mode_read), mask); #endif } diff --git a/src/common/classes/TempFile.cpp b/src/common/classes/TempFile.cpp index ea80eb0d94..ba75a2e74a 100644 --- a/src/common/classes/TempFile.cpp +++ b/src/common/classes/TempFile.cpp @@ -216,9 +216,7 @@ void TempFile::init(const PathName& directory, const PathName& prefix) system_error::raise("mktemp"); } - do { - handle = open(filename.c_str(), O_RDWR | O_EXCL | O_CREAT); - } while (handle == -1 && errno == EINTR); + handle = os_utils::open(filename.c_str(), O_RDWR | O_EXCL | O_CREAT); #endif if (handle == -1) diff --git a/src/common/classes/alloc.cpp b/src/common/classes/alloc.cpp index 604d1604d3..ac292f49f0 100644 --- a/src/common/classes/alloc.cpp +++ b/src/common/classes/alloc.cpp @@ -52,6 +52,7 @@ #include "../common/classes/locks.h" #include "../common/classes/init.h" #include "../common/classes/vector.h" +#include "../common/os/os_utils.h" #include "gen/iberror.h" #ifdef USE_VALGRIND @@ -828,7 +829,7 @@ void* MemoryPool::allocRaw(size_t size) throw (OOM_EXCEPTION) #else // MAP_ANONYMOUS if (dev_zero_fd < 0) - dev_zero_fd = open("/dev/zero", O_RDWR); + dev_zero_fd = os_utils::open("/dev/zero", O_RDWR); void* result = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero_fd, 0); #endif // MAP_ANONYMOUS @@ -1015,7 +1016,7 @@ void MemoryPool::validate(void) throw () void MemoryPool::print_contents(const char* filename, bool used_only, const char* filter_path) throw () { - FILE* out = fopen(filename, "w"); + FILE* out = os_utils::fopen(filename, "w"); if (!out) return; diff --git a/src/common/config/config_file.cpp b/src/common/config/config_file.cpp index 76649d7530..1523508f11 100644 --- a/src/common/config/config_file.cpp +++ b/src/common/config/config_file.cpp @@ -28,6 +28,7 @@ #include "../common/config/config.h" #include "../common/config/ConfigCache.h" #include "../common/os/path_utils.h" +#include "../common/os/os_utils.h" #include "../common/ScanDir.h" #include "../common/utils_proto.h" #include @@ -49,7 +50,7 @@ class MainStream : public ConfigFile::Stream { public: MainStream(const char* fname, bool errorWhenMissing) - : file(fopen(fname, "rt")), fileName(fname), l(0) + : file(os_utils::fopen(fname, "rt")), fileName(fname), l(0) { if (errorWhenMissing && !file) { diff --git a/src/common/isc_file.cpp b/src/common/isc_file.cpp index a09567099c..50ebfd2c4e 100644 --- a/src/common/isc_file.cpp +++ b/src/common/isc_file.cpp @@ -116,7 +116,7 @@ const char* const MTAB = "/etc/mtab"; #define MTAB_OPEN(path, type) setmntent(path, "r") #define MTAB_CLOSE(stream) endmntent(stream) #else -#define MTAB_OPEN(path, type) fopen(path, type) +#define MTAB_OPEN(path, type) os_utils::fopen(path, type) #define MTAB_CLOSE(stream) fclose(stream) #endif diff --git a/src/common/os/os_utils.h b/src/common/os/os_utils.h index a3afa0a6e6..b58fbf9271 100644 --- a/src/common/os/os_utils.h +++ b/src/common/os/os_utils.h @@ -28,9 +28,7 @@ #ifndef INCLUDE_OS_FILE_UTILS_H #define INCLUDE_OS_FILE_UTILS_H -#ifdef SFIO #include -#endif #include "../common/classes/fb_string.h" #include "../common/StatusArg.h" @@ -47,6 +45,11 @@ namespace os_utils bool touchFile(const char* pathname); bool isIPv6supported(); + + // force descriptor to have O_CLOEXEC set + int open(const char *pathname, int flags, mode_t mode = 0666); + void setCloseOnExec(int fd); // posix only + FILE* fopen(const char *pathname, const char *mode); } // namespace os_utils #endif // INCLUDE_OS_FILE_UTILS_H diff --git a/src/common/os/posix/divorce.cpp b/src/common/os/posix/divorce.cpp index b0116f6b17..ce2089fbe9 100644 --- a/src/common/os/posix/divorce.cpp +++ b/src/common/os/posix/divorce.cpp @@ -52,6 +52,7 @@ #include "firebird.h" #include "../common/os/divorce.h" #include "../common/classes/semaphore.h" +#include "../common/os/os_utils.h" #ifdef HAVE_IO_H #include @@ -123,7 +124,7 @@ void divorce_terminal(int mask) // Perform terminal divorce // this is in case of BSD systems - fid = open("/dev/tty", 2); + fid = os_utils::open("/dev/tty", 2); if (fid >= 0) { ioctl(fid, TIOCNOTTY, 0); diff --git a/src/common/os/posix/guid.cpp b/src/common/os/posix/guid.cpp index 7621fd144a..9ea57fb201 100644 --- a/src/common/os/posix/guid.cpp +++ b/src/common/os/posix/guid.cpp @@ -30,6 +30,7 @@ #include "../common/os/guid.h" #include "fb_exception.h" +#include "../common/os/os_utils.h" #include #include #include @@ -43,15 +44,7 @@ namespace Firebird { void GenerateRandomBytes(void* buffer, FB_SIZE_T size) { // do not use /dev/random because it may return lesser data than we need. - int fd = -1; - for (;;) - { - fd = open("/dev/urandom", O_RDONLY); - if (fd >= 0) - break; - if (errno != EINTR) - Firebird::system_call_failed::raise("open"); - } + int fd = os_utils::open("/dev/urandom", O_RDONLY); for (FB_SIZE_T offset = 0; offset < size; ) { int rc = read(fd, static_cast(buffer) + offset, size - offset); diff --git a/src/common/os/posix/os_utils.cpp b/src/common/os/posix/os_utils.cpp index 4467b9ac20..a5db594cf6 100644 --- a/src/common/os/posix/os_utils.cpp +++ b/src/common/os/posix/os_utils.cpp @@ -58,6 +58,14 @@ #include #endif +#ifdef HAVE_ACCEPT4 +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#endif +#include +#include + using namespace Firebird; namespace os_utils @@ -117,6 +125,7 @@ namespace } } // anonymous namespace + // create directory for lock files and set appropriate access rights void createLockDirectory(const char* pathname) { @@ -173,11 +182,7 @@ static void raiseError(int errCode, const char* filename) // open (or create if missing) and set appropriate access rights int openCreateSharedFile(const char* pathname, int flags) { - int fd; - do { - fd = ::open(pathname, flags | O_RDWR | O_CREAT, S_IREAD | S_IWRITE); - } while (fd < 0 && SYSCALL_INTERRUPTED(errno)); - + int fd = os_utils::open(pathname, flags | O_RDWR | O_CREAT, S_IREAD | S_IWRITE); if (fd < 0) raiseError(fd, pathname); @@ -235,4 +240,41 @@ bool isIPv6supported() return true; } +// setting flag is not absolutely required, therefore ignore errors here +void setCloseOnExec(int fd) +{ + if (fd >= 0) + { + while (fcntl(fd, F_SETFD, O_CLOEXEC) < 0 && SYSCALL_INTERRUPTED(errno)) + ; + } +} + +// force file descriptor to have O_CLOEXEC set +int open(const char *pathname, int flags, mode_t mode) +{ + int fd; + do { + fd = ::open(pathname, flags | O_CLOEXEC, mode); + } while (fd < 0 && SYSCALL_INTERRUPTED(errno)); + + if (fd < 0 && errno == EINVAL) // probably O_CLOEXEC not accepted + { + do { + fd = ::open(pathname, flags | O_CLOEXEC, mode); + } while (fd < 0 && SYSCALL_INTERRUPTED(errno)); + } + + setCloseOnExec(fd); + return fd; +} + +FILE* fopen(const char *pathname, const char *mode) +{ + FILE* f = ::fopen(pathname, mode); // TODO: use open + fdopen to avoid races + if (f) + setCloseOnExec(fileno(f)); + return f; +} + } // namespace os_utils diff --git a/src/common/os/win32/os_utils.cpp b/src/common/os/win32/os_utils.cpp index b12a0b9373..7bf995ab05 100644 --- a/src/common/os/win32/os_utils.cpp +++ b/src/common/os/win32/os_utils.cpp @@ -303,4 +303,14 @@ bool isIPv6supported() return false; } +int open(const char *pathname, int flags, mode_t mode = 0666) +{ + return ::_open(char *pathname, flags, mode); +} + +FILE* fopen(const char *pathname, const char *mode) +{ + return ::fopen(pathname, mode); +} + } // namespace os_utils diff --git a/src/common/utils.cpp b/src/common/utils.cpp index 81453b6b2c..1fecdee629 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -49,6 +49,7 @@ #include "../common/os/path_utils.h" #include "../common/os/fbsyslog.h" #include "../common/StatusArg.h" +#include "../common/os/os_utils.h" #include "../dsql/sqlda_pub.h" #ifdef WIN_NT @@ -734,7 +735,7 @@ namespace { f = stdin; } else { - f = fopen(name.c_str(), "rt"); + f = os_utils::fopen(name.c_str(), "rt"); } if (f && isatty(fileno(f))) { diff --git a/src/jrd/Optimizer.cpp b/src/jrd/Optimizer.cpp index 8587cc8146..535ea25946 100644 --- a/src/jrd/Optimizer.cpp +++ b/src/jrd/Optimizer.cpp @@ -2255,7 +2255,7 @@ void OptimizerRetrieval::printCandidate(const InversionCandidate* candidate) con * **************************************/ - FILE *opt_debug_file = fopen(OPTIMIZER_DEBUG_FILE, "a"); + FILE *opt_debug_file = os_utils::fopen(OPTIMIZER_DEBUG_FILE, "a"); fprintf(opt_debug_file, " cost(%1.2f), selectivity(%1.10f), indexes(%d), matched(%d, %d)", candidate->cost, candidate->selectivity, candidate->indexes, candidate->matchedSegments, candidate->nonFullMatchedSegments); @@ -2289,7 +2289,7 @@ void OptimizerRetrieval::printCandidates(const InversionCandidateList* inversion * **************************************/ - FILE *opt_debug_file = fopen(OPTIMIZER_DEBUG_FILE, "a"); + FILE *opt_debug_file = os_utils::fopen(OPTIMIZER_DEBUG_FILE, "a"); fprintf(opt_debug_file, " retrieval candidates:\n"); fclose(opt_debug_file); const InversionCandidate* const* inversion = inversions->begin(); @@ -2314,7 +2314,7 @@ void OptimizerRetrieval::printFinalCandidate(const InversionCandidate* candidate if (candidate) { - FILE *opt_debug_file = fopen(OPTIMIZER_DEBUG_FILE, "a"); + FILE *opt_debug_file = os_utils::fopen(OPTIMIZER_DEBUG_FILE, "a"); fprintf(opt_debug_file, " final candidate: "); fclose(opt_debug_file); printCandidate(candidate); @@ -3037,7 +3037,7 @@ void OptimizerInnerJoin::printBestOrder() const * **************************************/ - FILE *opt_debug_file = fopen(OPTIMIZER_DEBUG_FILE, "a"); + FILE *opt_debug_file = os_utils::fopen(OPTIMIZER_DEBUG_FILE, "a"); fprintf(opt_debug_file, " best order, streams: "); for (StreamType i = 0; i < optimizer->opt_best_count; i++) { @@ -3064,7 +3064,7 @@ void OptimizerInnerJoin::printFoundOrder(StreamType position, double positionCos * **************************************/ - FILE *opt_debug_file = fopen(OPTIMIZER_DEBUG_FILE, "a"); + FILE *opt_debug_file = os_utils::fopen(OPTIMIZER_DEBUG_FILE, "a"); fprintf(opt_debug_file, " position %2.2d:", position); fprintf(opt_debug_file, " pos. cardinality(%10.2f) pos. cost(%10.2f)", positionCardinality, positionCost); fprintf(opt_debug_file, " cardinality(%10.2f) cost(%10.2f)", cardinality, cost); @@ -3095,7 +3095,7 @@ void OptimizerInnerJoin::printProcessList(const IndexedRelationships* processLis * **************************************/ - FILE *opt_debug_file = fopen(OPTIMIZER_DEBUG_FILE, "a"); + FILE *opt_debug_file = os_utils::fopen(OPTIMIZER_DEBUG_FILE, "a"); fprintf(opt_debug_file, " basestream %d, relationships: stream(cost)", stream); const IndexRelationship* const* relationships = processList->begin(); for (int i = 0; i < processList->getCount(); i++) @@ -3116,7 +3116,7 @@ void OptimizerInnerJoin::printStartOrder() const * **************************************/ - FILE *opt_debug_file = fopen(OPTIMIZER_DEBUG_FILE, "a"); + FILE *opt_debug_file = os_utils::fopen(OPTIMIZER_DEBUG_FILE, "a"); fprintf(opt_debug_file, "Start join order: with stream(baseCost)"); bool firstStream = true; for (int i = 0; i < innerStreams.getCount(); i++) diff --git a/src/jrd/ext.cpp b/src/jrd/ext.cpp index 8000f29d28..a5cfa72f82 100644 --- a/src/jrd/ext.cpp +++ b/src/jrd/ext.cpp @@ -59,6 +59,7 @@ #include "../common/os/path_utils.h" #include "../common/classes/init.h" #include "../common/isc_f_proto.h" +#include "../common/os/os_utils.h" #if defined _MSC_VER && _MSC_VER < 1400 // NS: in VS2003 these only work with static CRT @@ -135,12 +136,12 @@ namespace { // RW mode. If the DB is ReadOnly, then open the external files only in // ReadOnly mode, thus being consistent. if (!dbb->readOnly()) - ext_file->ext_ifi = fopen(file_name, FOPEN_TYPE); + ext_file->ext_ifi = os_utils::fopen(file_name, FOPEN_TYPE); if (!ext_file->ext_ifi) { // could not open the file as read write attempt as read only - if (!(ext_file->ext_ifi = fopen(file_name, FOPEN_READ_ONLY))) + if (!(ext_file->ext_ifi = os_utils::fopen(file_name, FOPEN_READ_ONLY))) { ERR_post(Arg::Gds(isc_io_error) << Arg::Str("fopen") << Arg::Str(file_name) << Arg::Gds(isc_io_open_err) << SYS_ERR(errno)); diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 5d63c90450..6a61e7a945 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -5196,7 +5196,7 @@ void JRD_print_procedure_info(thread_db* tdbb, const char* mesg) TEXT fname[MAXPATHLEN]; Firebird::string fname = fb_utils::getPrefix(IConfigManager::FB_DIR_LOG, "proc_info.log"); - FILE* fptr = fopen(fname.c_str(), "a+"); + FILE* fptr = os_utils::fopen(fname.c_str(), "a+"); if (!fptr) { gds__log("Failed to open %s\n", fname.c_str()); diff --git a/src/jrd/opt.cpp b/src/jrd/opt.cpp index cea0a00298..1176925d1f 100644 --- a/src/jrd/opt.cpp +++ b/src/jrd/opt.cpp @@ -82,6 +82,7 @@ #include "../jrd/UserManagement.h" #include "../common/classes/array.h" #include "../common/classes/objects_array.h" +#include "../common/os/os_utils.h" #include "../jrd/recsrc/RecordSource.h" #include "../jrd/recsrc/Cursor.h" #include "../jrd/Mapping.h" @@ -466,7 +467,7 @@ RecordSource* OPT_compile(thread_db* tdbb, CompilerScratch* csb, RseNode* rse, #ifdef OPT_DEBUG if (opt_debug_flag != DEBUG_NONE && !opt_debug_file) - opt_debug_file = fopen("opt_debug.out", "w"); + opt_debug_file = os_utils::fopen("opt_debug.out", "w"); #endif // If there is a boolean, there is some work to be done. First, diff --git a/src/jrd/os/posix/unix.cpp b/src/jrd/os/posix/unix.cpp index 0312d1df2b..7378a53d12 100644 --- a/src/jrd/os/posix/unix.cpp +++ b/src/jrd/os/posix/unix.cpp @@ -67,6 +67,7 @@ #include "../jrd/ods_proto.h" #include "../jrd/os/pio_proto.h" #include "../common/classes/init.h" +#include "../common/os/os_utils.h" using namespace Jrd; using namespace Firebird; @@ -215,7 +216,7 @@ jrd_file* PIO_create(Database* dbb, const PathName& file_name, #endif #endif - const int desc = open(file_name.c_str(), flag, 0666); + const int desc = os_utils::open(file_name.c_str(), flag, 0666); if (desc == -1) { ERR_post(Arg::Gds(isc_io_error) << Arg::Str("open O_CREAT") << Arg::Str(file_name) << @@ -891,16 +892,7 @@ static int openFile(const char* name, const bool forcedWrites, flag |= O_DIRECT; #endif - for (int i = 0; i < IO_RETRY; i++) - { - int desc = open(name, flag); - if (desc != -1) - return desc; - if (!SYSCALL_INTERRUPTED(errno)) - break; - } - - return -1; + return os_utils::open(name, flag); } @@ -1213,18 +1205,12 @@ static bool raw_devices_validate_database(int desc, const PathName& file_name) static int raw_devices_unlink_database(const PathName& file_name) { char header[MIN_PAGE_SIZE]; - int desc = -1; - for (int i = 0; i < IO_RETRY; i++) + int desc = os_utils::open(file_name.c_str(), O_RDWR | O_BINARY); + if (desc < 0) { - if ((desc = open (file_name.c_str(), O_RDWR | O_BINARY)) != -1) - break; - - if (!SYSCALL_INTERRUPTED(errno)) - { - ERR_post(Arg::Gds(isc_io_error) << Arg::Str("open") << Arg::Str(file_name) << - Arg::Gds(isc_io_open_err) << Arg::Unix(errno)); - } + ERR_post(Arg::Gds(isc_io_error) << Arg::Str("open") << Arg::Str(file_name) << + Arg::Gds(isc_io_open_err) << Arg::Unix(errno)); } memset(header, 0xa5, sizeof(header)); diff --git a/src/jrd/svc.cpp b/src/jrd/svc.cpp index f1855d3c2a..5ed078e3b3 100644 --- a/src/jrd/svc.cpp +++ b/src/jrd/svc.cpp @@ -63,6 +63,7 @@ #include "../jrd/EngineInterface.h" #include "../jrd/Mapping.h" #include "../common/classes/RefMutex.h" +#include "../common/os/os_utils.h" #include "../common/classes/DbImplementation.h" @@ -2194,7 +2195,7 @@ void Service::readFbLog() bool svc_started = false; Firebird::PathName name = fb_utils::getPrefix(IConfigManager::FB_DIR_LOG, LOGFILE); - FILE* file = fopen(name.c_str(), "r"); + FILE* file = os_utils::fopen(name.c_str(), "r"); try { diff --git a/src/jrd/trace/TraceConfigStorage.cpp b/src/jrd/trace/TraceConfigStorage.cpp index b685fbea29..540258546a 100644 --- a/src/jrd/trace/TraceConfigStorage.cpp +++ b/src/jrd/trace/TraceConfigStorage.cpp @@ -208,7 +208,7 @@ void ConfigStorage::checkFile() } else { - m_cfg_file = ::open(cfg_file_name, O_RDWR | O_BINARY); + m_cfg_file = os_utils::open(cfg_file_name, O_RDWR | O_BINARY); if (m_cfg_file < 0) checkFileError(cfg_file_name, "open", isc_io_open_err); @@ -244,7 +244,7 @@ void ConfigStorage::checkFile() configFileName.insert(0, root); } - cfgFile = fopen(configFileName.c_str(), "rb"); + cfgFile = os_utils::fopen(configFileName.c_str(), "rb"); if (!cfgFile) { checkFileError(configFileName.c_str(), "fopen", isc_io_open_err); } diff --git a/src/lock/lock.cpp b/src/lock/lock.cpp index a831c167e6..2f874f4a08 100644 --- a/src/lock/lock.cpp +++ b/src/lock/lock.cpp @@ -54,6 +54,7 @@ #include "../common/classes/semaphore.h" #include "../common/classes/init.h" #include "../common/classes/timestamp.h" +#include "../common/os/os_utils.h" #include #include @@ -1621,7 +1622,7 @@ void LockManager::bug(Arg::StatusVector* statusVector, const TEXT* string) TEXT buffer[MAXPATHLEN]; gds__prefix_lock(buffer, "fb_lock_table.dump"); const TEXT* const lock_file = buffer; - FILE* const fd = fopen(lock_file, "wb"); + FILE* const fd = os_utils::fopen(lock_file, "wb"); if (fd) { FB_UNUSED(fwrite(header, 1, header->lhb_used, fd)); diff --git a/src/remote/SockAddr.h b/src/remote/SockAddr.h index 661f48ba00..28f74e54d9 100644 --- a/src/remote/SockAddr.h +++ b/src/remote/SockAddr.h @@ -45,7 +45,6 @@ #include "../remote/remote.h" - class SockAddr { private: @@ -111,7 +110,7 @@ inline int SockAddr::connect(SOCKET s) const inline int SockAddr::accept(SOCKET s) { - return ::accept(s, (struct sockaddr*) data, &len); + return os_utils::accept(s, (struct sockaddr*) data, &len); } diff --git a/src/remote/inet.cpp b/src/remote/inet.cpp index c8847525c1..8d76c5803f 100644 --- a/src/remote/inet.cpp +++ b/src/remote/inet.cpp @@ -54,6 +54,7 @@ #include "../common/classes/timestamp.h" #include "../common/classes/init.h" #include "../common/ThreadStart.h" +#include "../common/os/os_utils.h" #ifdef HAVE_PWD_H #include @@ -111,7 +112,6 @@ const int INET_RETRY_CALL = 5; #include "../common/config/config.h" #include "../common/utils_proto.h" #include "../common/classes/ClumpletWriter.h" -#include "../common/os/os_utils.h" // Please review. Maybe not needed. See H_ERRNO in common.h. #if defined HPUX @@ -842,7 +842,7 @@ rem_port* INET_connect(const TEXT* name, for (const addrinfo* pai = gai_result; pai; pai = pai->ai_next) { // Allocate a port block and initialize a socket for communications - port->port_handle = socket(pai->ai_family, pai->ai_socktype, pai->ai_protocol); + port->port_handle = os_utils::socket(pai->ai_family, pai->ai_socktype, pai->ai_protocol); if (port->port_handle == INVALID_SOCKET) { @@ -997,7 +997,7 @@ static void INET_server_socket(rem_port* port, USHORT flag, const addrinfo* pai) while (true) { - SOCKET s = accept(port->port_handle, NULL, NULL); + SOCKET s = os_utils::accept(port->port_handle, NULL, NULL); const int inetErrNo = INET_ERRNO; if (s == INVALID_SOCKET) { @@ -1371,7 +1371,7 @@ static rem_port* aux_connect(rem_port* port, PACKET* packet) } } - const SOCKET n = accept(port->port_channel, NULL, NULL); + const SOCKET n = os_utils::accept(port->port_channel, NULL, NULL); inetErrNo = INET_ERRNO; if (n == INVALID_SOCKET) @@ -1416,7 +1416,7 @@ static rem_port* aux_connect(rem_port* port, PACKET* packet) // Set up new socket - SOCKET n = socket(address.family(), SOCK_STREAM, 0); + SOCKET n = os_utils::socket(address.family(), SOCK_STREAM, 0); if (n == INVALID_SOCKET) { int savedError = INET_ERRNO; @@ -1465,7 +1465,7 @@ static rem_port* aux_request( rem_port* port, PACKET* packet) unsigned short aux_port = port->getPortConfig()->getRemoteAuxPort(); our_address.setPort(aux_port); // may be 0 - SOCKET n = socket(our_address.family(), SOCK_STREAM, 0); + SOCKET n = os_utils::socket(our_address.family(), SOCK_STREAM, 0); if (n == INVALID_SOCKET) { inet_error(false, port, "socket", isc_net_event_listen_err, INET_ERRNO); @@ -1966,7 +1966,7 @@ static rem_port* select_accept( rem_port* main_port) rem_port* const port = alloc_port(main_port); inet_ports->registerPort(port); - port->port_handle = accept(main_port->port_handle, NULL, NULL); + port->port_handle = os_utils::accept(main_port->port_handle, NULL, NULL); if (port->port_handle == INVALID_SOCKET) { inet_error(true, port, "accept", isc_net_connect_err, INET_ERRNO); @@ -3081,3 +3081,58 @@ void setStopMainThread(FPTR_INT func) **************************************/ tryStopMainThread = func; } + +namespace os_utils +{ + +// force socket descriptor to have O_CLOEXEC set +int socket(int domain, int type, int protocol) +{ +#ifdef WIN_NT + return ::socket(domain, type, protocol); +#else + int fd; + do { + fd = ::socket(domain, type | O_CLOEXEC, protocol); + } while (fd < 0 && SYSCALL_INTERRUPTED(errno)); + + if (fd < 0 && errno == EINVAL) // probably O_CLOEXEC not accepted + { + do { + fd = ::socket(domain, type, protocol); + } while (fd < 0 && SYSCALL_INTERRUPTED(errno)); + } + + setCloseOnExec(fd); + return fd; +#endif +} + +// force socket descriptor to have O_CLOEXEC set +int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) +{ +#ifdef WIN_NT + return ::accept(sockfd, addr, addrlen); +#else + int fd; +#ifdef HAVE_ACCEPT4 + do { + fd = ::accept4(sockfd, addr, addrlen, O_CLOEXEC); + } while (fd < 0 && SYSCALL_INTERRUPTED(errno)); + + if (fd < 0 && errno == EINVAL) // probably O_CLOEXEC not accepted + { +#endif + do { + fd = ::accept(sockfd, addr, addrlen); + } while (fd < 0 && SYSCALL_INTERRUPTED(errno)); +#ifdef HAVE_ACCEPT4 + } +#endif + + setCloseOnExec(fd); + return fd; +#endif +} + +} // namespace os_utils diff --git a/src/remote/remote.h b/src/remote/remote.h index 3e1622b1a5..de1a68d412 100644 --- a/src/remote/remote.h +++ b/src/remote/remote.h @@ -105,6 +105,17 @@ namespace Firebird { class Exception; } +#ifndef WIN_NT +typedef int SOCKET; +#endif + +namespace os_utils +{ + // force descriptor to have O_CLOEXEC set + SOCKET socket(int domain, int type, int protocol); + SOCKET accept(SOCKET sockfd, sockaddr *addr, socklen_t *addrlen); +} + struct rem_port; typedef Firebird::AutoPtr > UCharArrayAutoPtr; @@ -586,11 +597,6 @@ inline void Rsr::releaseException() // Generalized port definition. -#ifndef WIN_NT -typedef int SOCKET; -#endif - - ////////////////////////////////////////////////////////////////// // fwd. decl. struct p_cnct; diff --git a/src/remote/server/os/posix/inet_server.cpp b/src/remote/server/os/posix/inet_server.cpp index 34a611f8f6..bc1e400403 100644 --- a/src/remote/server/os/posix/inet_server.cpp +++ b/src/remote/server/os/posix/inet_server.cpp @@ -40,6 +40,7 @@ #include "../common/classes/init.h" #include "../common/config/config.h" #include "../common/os/fbsyslog.h" +#include "../common/os/os_utils.h" #include #ifdef HAVE_SYS_TYPES_H @@ -425,7 +426,7 @@ int CLIB_ROUTINE main( int argc, char** argv) //gds_alloc_report(0, __FILE__, __LINE__); Firebird::PathName name = fb_utils::getPrefix( Firebird::IConfigManager::FB_DIR_LOG, "memdebug.log"); - FILE* file = fopen(name.c_str(), "w+t"); + FILE* file = os_utils::fopen(name.c_str(), "w+t"); if (file) { fprintf(file, "Global memory pool allocated objects\n"); diff --git a/src/remote/server/os/win32/srvr_w32.cpp b/src/remote/server/os/win32/srvr_w32.cpp index 9fb38262e4..b3abb649c6 100644 --- a/src/remote/server/os/win32/srvr_w32.cpp +++ b/src/remote/server/os/win32/srvr_w32.cpp @@ -109,6 +109,7 @@ #include "firebird/Interface.h" #include "../common/classes/ImplementHelper.h" +#include "../common/os/os_utils.h" #include "../auth/trusted/AuthSspi.h" #include "../auth/SecurityDatabase/LegacyServer.h" #include "../auth/SecureRemotePassword/server/SrpServer.h" @@ -346,7 +347,7 @@ int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE /*hPrevInst*/, LPSTR lpszArgs, //gds_alloc_report(0, __FILE__, __LINE__); PathName name = fb_utils::getPrefix(IConfigManager::FB_DIR_LOG, "memdebug.log"); - FILE* file = fopen(name.c_str(), "w+t"); + FILE* file = os_utils::fopen(name.c_str(), "w+t"); if (file) { fprintf(file, "Global memory pool allocated objects\n"); diff --git a/src/remote/server/server.cpp b/src/remote/server/server.cpp index ffd77a36a5..ccdaf1cbd6 100644 --- a/src/remote/server/server.cpp +++ b/src/remote/server/server.cpp @@ -73,6 +73,7 @@ #include "../auth/SecurityDatabase/LegacyHash.h" #include "../common/enc_proto.h" #include "../common/classes/InternalMessageBuffer.h" +#include "../common/os/os_utils.h" using namespace Firebird; @@ -637,12 +638,10 @@ public: firebirdPortMutex.printf(PORT_FILE, id); TEXT filename[MAXPATHLEN]; gds__prefix_lock(filename, firebirdPortMutex.c_str()); - while ((fd = open(filename, O_WRONLY | O_CREAT, 0666)) < 0) + fd = os_utils::open(filename, O_WRONLY | O_CREAT, 0666); + if (fd < 0) { - if (errno != EINTR) - { - system_call_failed::raise("open"); - } + system_call_failed::raise("open"); } struct flock lock; diff --git a/src/utilities/analyse.cpp b/src/utilities/analyse.cpp index 6cd06aecb7..57434aa2e6 100644 --- a/src/utilities/analyse.cpp +++ b/src/utilities/analyse.cpp @@ -329,7 +329,7 @@ static void db_open( const char* file_name, USHORT file_length) * **************************************/ - if ((file = open(file_name, 2)) == -1) + if ((file = os_utils::open(file_name, 2)) == -1) db_error(errno); } diff --git a/src/utilities/gstat/dba.epp b/src/utilities/gstat/dba.epp index 1c944b24c7..3dcde21541 100644 --- a/src/utilities/gstat/dba.epp +++ b/src/utilities/gstat/dba.epp @@ -54,6 +54,7 @@ #include "../jrd/ods_proto.h" #include "../common/classes/MsgPrint.h" #include "../common/classes/UserBlob.h" +#include "../common/os/os_utils.h" using MsgFormat::SafeArg; @@ -1949,7 +1950,7 @@ static dba_fil* db_open(const char* file_name, USHORT file_length) fil->fil_fudge = 0; fil->fil_max_page = 0L; - if ((fil->fil_desc = open(file_name, O_RDONLY)) == -1) + if ((fil->fil_desc = os_utils::open(file_name, O_RDONLY)) == -1) { tddba->uSvc->setServiceStatus(GSTAT_MSG_FAC, 29, SafeArg() << file_name); // msg 29: Can't open database file %s diff --git a/src/utilities/nbackup/nbackup.cpp b/src/utilities/nbackup/nbackup.cpp index d3f69ca3ad..b786195673 100644 --- a/src/utilities/nbackup/nbackup.cpp +++ b/src/utilities/nbackup/nbackup.cpp @@ -53,6 +53,7 @@ #include "../common/isc_f_proto.h" #include "../common/StatusArg.h" #include "../common/classes/objects_array.h" +#include "../common/os/os_utils.h" #ifdef HAVE_UNISTD_H #include @@ -457,7 +458,7 @@ void NBackup::open_database_write() if (dbase != INVALID_HANDLE_VALUE) return; #else - dbase = open(dbname.c_str(), O_RDWR | O_LARGEFILE); + dbase = os_utils::open(dbname.c_str(), O_RDWR | O_LARGEFILE); if (dbase >= 0) return; #endif @@ -497,11 +498,11 @@ void NBackup::open_database_scan() #define O_DIRECT 0 #endif // O_DIRECT - dbase = open(dbname.c_str(), O_RDONLY | O_LARGEFILE | O_NOATIME | (direct_io ? O_DIRECT : 0)); + dbase = os_utils::open(dbname.c_str(), O_RDONLY | O_LARGEFILE | O_NOATIME | (direct_io ? O_DIRECT : 0)); if (dbase < 0) { // Non-root may fail when opening file of another user with O_NOATIME - dbase = open(dbname.c_str(), O_RDONLY | O_LARGEFILE | (direct_io ? O_DIRECT : 0)); + dbase = os_utils::open(dbname.c_str(), O_RDONLY | O_LARGEFILE | (direct_io ? O_DIRECT : 0)); } if (dbase < 0) { @@ -540,7 +541,7 @@ void NBackup::create_database() if (dbase != INVALID_HANDLE_VALUE) return; #else - dbase = open(dbname.c_str(), O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE, 0660); + dbase = os_utils::open(dbname.c_str(), O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE, 0660); if (dbase >= 0) return; #endif @@ -655,7 +656,7 @@ void NBackup::open_backup_scan() } else { - backup = open(nm.c_str(), O_RDONLY | O_LARGEFILE); + backup = os_utils::open(nm.c_str(), O_RDONLY | O_LARGEFILE); if (backup >= 0) return; } @@ -684,7 +685,7 @@ void NBackup::create_backup() backup = 1; // Posix file handle for stdout return; } - backup = open(nm.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, 0660); + backup = os_utils::open(nm.c_str(), O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, 0660); if (backup >= 0) return; #endif diff --git a/src/yvalve/gds.cpp b/src/yvalve/gds.cpp index 3aa66967e8..551e0f4f3a 100644 --- a/src/yvalve/gds.cpp +++ b/src/yvalve/gds.cpp @@ -1077,7 +1077,7 @@ void API_ROUTINE gds__trace_raw(const char* text, unsigned int length) ReleaseMutex(CleanupTraceHandles::trace_mutex_handle); #else Firebird::PathName name = fb_utils::getPrefix(Firebird::IConfigManager::FB_DIR_LOG, LOGFILE); - int file = open(name.c_str(), O_CREAT | O_APPEND | O_WRONLY, 0660); + int file = os_utils::open(name.c_str(), O_CREAT | O_APPEND | O_WRONLY, 0660); if (file == -1) return; @@ -1186,7 +1186,7 @@ void API_ROUTINE gds__log(const TEXT* text, ...) #ifdef WIN_NT WaitForSingleObject(CleanupTraceHandles::trace_mutex_handle, INFINITE); #endif - FILE* file = fopen(name.c_str(), "a"); + FILE* file = os_utils::fopen(name.c_str(), "a"); if (file != NULL) { #ifndef WIN_NT @@ -1252,7 +1252,7 @@ void API_ROUTINE gds__print_pool(MemoryPool* pool, const TEXT* text, ...) #ifdef WIN_NT WaitForSingleObject(CleanupTraceHandles::trace_mutex_handle, INFINITE); #endif - FILE* file = fopen(name.c_str(), "a"); + FILE* file = os_utils::fopen(name.c_str(), "a"); if (file != NULL) { TEXT buffer[MAXPATHLEN]; @@ -1585,7 +1585,7 @@ int API_ROUTINE gds__msg_open(void** handle, const TEXT* filename) * and update a message handle. * **************************************/ - const int n = open(filename, O_RDONLY | O_BINARY, 0); + const int n = os_utils::open(filename, O_RDONLY | O_BINARY, 0); if (n < 0) return -2; @@ -2414,11 +2414,11 @@ VoidPtr API_ROUTINE gds__temp_file(BOOLEAN stdio_flag, const TEXT* string, TEXT* if (stdio_flag) { - FILE* result = fopen(filename.c_str(), "w+b"); + FILE* result = os_utils::fopen(filename.c_str(), "w+b"); return result ? result : (void*) (IPTR) (-1); } - return (void*) (IPTR) open(filename.c_str(), O_RDWR | O_EXCL | O_TRUNC); + return (void*) (IPTR) os_utils::open(filename.c_str(), O_RDWR | O_EXCL | O_TRUNC); } catch (const Firebird::Exception&) { diff --git a/src/yvalve/utl.cpp b/src/yvalve/utl.cpp index c6cdc9acd7..328dc33488 100644 --- a/src/yvalve/utl.cpp +++ b/src/yvalve/utl.cpp @@ -66,6 +66,7 @@ #include "../common/isc_f_proto.h" #include "../common/StatusHolder.h" #include "../common/classes/ImplementHelper.h" +#include "../common/os/os_utils.h" #ifdef HAVE_UNISTD_H #include @@ -316,7 +317,7 @@ FB_BOOLEAN edit(IStatus* status, ISC_QUAD* blob_id, IAttachment* att, ITransacti if (status->getStatus() & Firebird::IStatus::FB_HAS_ERRORS) return FB_FALSE; - FILE* file = fopen(tmpf.c_str(), FOPEN_WRITE_TYPE_TEXT); + FILE* file = os_utils::fopen(tmpf.c_str(), FOPEN_WRITE_TYPE_TEXT); if (!file) { unlink(tmpf.c_str()); @@ -338,7 +339,7 @@ FB_BOOLEAN edit(IStatus* status, ISC_QUAD* blob_id, IAttachment* att, ITransacti if (gds__edit(tmpf.c_str(), type)) { - if (!(file = fopen(tmpf.c_str(), FOPEN_READ_TYPE_TEXT))) + if (!(file = os_utils::fopen(tmpf.c_str(), FOPEN_READ_TYPE_TEXT))) { unlink(tmpf.c_str()); system_error::raise("fopen"); @@ -364,7 +365,7 @@ UtlInterface utlInterface; void UtlInterface::dumpBlob(IStatus* status, ISC_QUAD* blobId, IAttachment* att, ITransaction* tra, const char* file_name, FB_BOOLEAN txt) { - FILE* file = fopen(file_name, txt ? FOPEN_WRITE_TYPE_TEXT : FOPEN_WRITE_TYPE); + FILE* file = os_utils::fopen(file_name, txt ? FOPEN_WRITE_TYPE_TEXT : FOPEN_WRITE_TYPE); try { if (!file) @@ -397,7 +398,7 @@ void UtlInterface::loadBlob(IStatus* status, ISC_QUAD* blobId, * Load a blob with the contents of a file. * **************************************/ - FILE* file = fopen(file_name, txt ? FOPEN_READ_TYPE_TEXT : FOPEN_READ_TYPE); + FILE* file = os_utils::fopen(file_name, txt ? FOPEN_READ_TYPE_TEXT : FOPEN_READ_TYPE); try { if (!file)