aboutsummaryrefslogtreecommitdiffhomepage
path: root/wutil.cpp
diff options
context:
space:
mode:
authorGravatar Peter Ammon <corydoras@ridiculousfish.com>2012-03-02 00:27:40 -0800
committerGravatar Peter Ammon <corydoras@ridiculousfish.com>2012-03-02 00:27:40 -0800
commit8b26d0104c1d85c271e5ce6e08bfe64a779beba7 (patch)
tree995568526f190084fd12d74bc6dcd0e828b1018a /wutil.cpp
parent36622c35781c3212c2102c45781a496f3e1b3659 (diff)
Some initial changes to use CLO_EXEC, with an eye towards some day using it correctly.
Diffstat (limited to 'wutil.cpp')
-rw-r--r--wutil.cpp80
1 files changed, 65 insertions, 15 deletions
diff --git a/wutil.cpp b/wutil.cpp
index 8cbf7d43..af73c5ce 100644
--- a/wutil.cpp
+++ b/wutil.cpp
@@ -71,6 +71,8 @@ void wutil_destroy()
{
}
+static pthread_mutex_t readdir_lock = PTHREAD_MUTEX_INITIALIZER;
+
bool wreaddir_resolving(DIR *dir, const std::wstring &dir_path, std::wstring &out_name, bool *out_is_dir)
{
struct dirent *d = readdir( dir );
@@ -144,8 +146,39 @@ int wchdir( const wcstring &dir )
FILE *wfopen(const wcstring &path, const char *mode)
{
- cstring tmp = wcs2string(path);
- return fopen(tmp.c_str(), mode);
+ int permissions = 0, options = 0;
+ switch (*mode++) {
+ case 'r':
+ permissions = O_RDONLY;
+ break;
+ case 'w':
+ permissions = O_WRONLY;
+ options = O_CREAT | O_TRUNC;
+ break;
+ case 'a':
+ permissions = O_WRONLY;
+ options = O_CREAT | O_APPEND;
+ break;
+ default:
+ errno = EINVAL;
+ return NULL;
+ break;
+ }
+ /* Skip binary */
+ if (*mode == 'b')
+ mode++;
+
+ /* Consider append option */
+ if (*mode == '+')
+ permissions = O_RDWR;
+
+ int fd = wopen_cloexec(path, permissions | options, 0666);
+ if (fd < 0)
+ return NULL;
+ FILE *result = fdopen(fd, mode);
+ if (result == NULL)
+ close(fd);
+ return result;
}
FILE *wfreopen(const wcstring &path, const char *mode, FILE *stream)
@@ -154,24 +187,41 @@ FILE *wfreopen(const wcstring &path, const char *mode, FILE *stream)
return freopen(tmp.c_str(), mode, stream);
}
-int wopen(const wcstring &pathname, int flags, ...)
+bool set_cloexec(int fd) {
+ int flags = fcntl(fd, F_GETFD, 0);
+ if (flags < 0) {
+ return false;
+ } else if (flags & FD_CLOEXEC) {
+ return true;
+ } else {
+ return fcntl(fd, F_SETFD, flags | FD_CLOEXEC) >= 0;
+ }
+}
+
+static int wopen_internal(const wcstring &pathname, int flags, mode_t mode, bool cloexec)
{
cstring tmp = wcs2string(pathname);
- int res=-1;
- va_list argp;
- if( ! (flags & O_CREAT) )
- {
- res = open(tmp.c_str(), flags);
- }
- else
- {
- va_start( argp, flags );
- res = open(tmp.c_str(), flags, va_arg(argp, int) );
- va_end( argp );
+ int fd = ::open(tmp.c_str(), flags, mode);
+ if (cloexec && fd >= 0 && ! set_cloexec(fd)) {
+ close(fd);
+ fd = -1;
}
- return res;
+ return fd;
+
+}
+int wopen(const wcstring &pathname, int flags, mode_t mode)
+{
+ // off the main thread, always use wopen_cloexec
+ ASSERT_IS_MAIN_THREAD();
+ return wopen_internal(pathname, flags, mode, false);
}
+int wopen_cloexec(const wcstring &pathname, int flags, mode_t mode)
+{
+ return wopen_internal(pathname, flags, mode, true);
+}
+
+
int wcreat(const wcstring &pathname, mode_t mode)
{
cstring tmp = wcs2string(pathname);