Avoid duplicating this complexity in too many places.
At the same time make the interface more identical to regular mkdir(),
for familiarity.
#include <os/os.h>
#include <assert.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <wininet.h> /* MinGW needs it */
#include <shlobj.h>
#define stat _stat
+#define mkdir(path, mode) mkdir(path)
#endif
static const char* getvncdir(bool userDir, const char *xdg_env, const char *xdg_def)
{
return getvncdir(false, "XDG_STATE_HOME", ".local/state");
}
+
+int os::mkdir_p(const char *path_, mode_t mode)
+{
+ char *path = strdup(path_);
+ char *p;
+
+#ifdef WIN32
+ (void)mode;
+#endif
+
+ for (p = path + 1; *p; p++) {
+ if (*p == '/') {
+ *p = '\0';
+ if (mkdir(path, mode) == -1) {
+ if (errno != EEXIST) {
+ free(path);
+ return -1;
+ }
+ }
+ *p = '/';
+ }
+ }
+
+ if (mkdir(path, mode) == -1) {
+ free(path);
+ return -1;
+ }
+
+ free(path);
+
+ return 0;
+}
#ifndef OS_OS_H
#define OS_OS_H
+#include <sys/stat.h>
+
namespace os {
/*
*/
const char* getvncstatedir();
+ /*
+ * Create directory recursively. Useful to create the nested directory
+ * structures needed for the above directories.
+ */
+ int mkdir_p(const char *path, mode_t mode);
}
#endif /* OS_OS_H */
#include <config.h>
#endif
+#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
fprintf(stderr, "Can't obtain VNC config directory\n");
exit(1);
}
- strcpy(fname, configDir);
- char *p = NULL;
- for (p = fname + 1; *p; p++) {
- if (*p == '/') {
- *p = '\0';
- mkdir(fname, 0777);
- *p = '/';
- }
+ if (os::mkdir_p(configDir, 0777) == -1) {
+ fprintf(stderr, "Could not create VNC config directory: %s\n", strerror(errno));
+ exit(1);
}
- mkdir(fname, 0777);
snprintf(fname, sizeof(fname), "%s/passwd", configDir);
}
}
}
-static void
-mkvncdir(const char *dir)
+static int
+mkdir_p(const char *path_, mode_t mode)
{
- if (mkdir(dir, 0755) == -1) {
- if (errno != EEXIST) {
- syslog(LOG_CRIT, "Failure creating \"%s\": %s", dir, strerror(errno));
- _exit(EX_OSERR);
- }
- }
-}
+ char *path = strdup(path_);
+ char *p;
-static void
-mkdirrecursive(const char *dir)
-{
- char *path = strdup(dir);
- char *p;
-
- for (p = path + 1; *p; p++) {
- if (*p == '/') {
- *p = '\0';
- mkvncdir(path);
- *p = '/';
+ for (p = path + 1; *p; p++) {
+ if (*p == '/') {
+ *p = '\0';
+ if (mkdir(path, mode) == -1) {
+ if (errno != EEXIST) {
+ free(path);
+ return -1;
}
+ }
+ *p = '/';
}
+ }
- mkvncdir(path);
+ if (mkdir(path, mode) == -1) {
free(path);
+ return -1;
+ }
+
+ free(path);
+
+ return 0;
}
static void
#endif
}
- mkdirrecursive(logfile);
+ if (mkdir_p(logfile, 0755) == -1) {
+ if (errno != EEXIST) {
+ syslog(LOG_CRIT, "Failure creating \"%s\": %s", logfile, strerror(errno));
+ _exit(EX_OSERR);
+ }
+ }
hostlen = sysconf(_SC_HOST_NAME_MAX);
if (hostlen < 0) {
#ifdef WIN32
#include <os/winerrno.h>
#include <direct.h>
-#define mkdir(path, mode) _mkdir(path)
#endif
#ifdef __APPLE__
#endif
}
-static int mkvncdir(const char *dir)
-{
- int result = mkdir(dir, 0755);
- if (result == -1 && errno != EEXIST) {
- vlog.error(_("Could not create VNC directory %s: %s"), dir, strerror(errno));
- return result;
- }
- return 0;
-}
-
-static void mkdirrecursive(const char *dir)
-{
- char *path = strdup(dir);
- char *p;
-
- for (p = path + 1; *p; p++) {
- if (*p == '/') {
- *p = '\0';
- if (mkvncdir(path) != 0) {
- free(path);
- return;
- }
- *p = '/';
- }
- }
-
- mkvncdir(path);
- free(path);
-}
-
static void usage(const char *programName)
{
#ifdef WIN32
if (vncdir != NULL && strcmp(vncdir, "vnc") == 0)
vlog.info(_("%%APPDATA%%\\vnc is deprecated, please switch to the %%APPDATA%%\\TigerVNC location."));
#endif
- mkdirrecursive(os::getvncconfigdir());
- mkdirrecursive(os::getvncdatadir());
- mkdirrecursive(os::getvncstatedir());
+
+ if (os::mkdir_p(os::getvncconfigdir(), 0755) == -1) {
+ if (errno != EEXIST)
+ vlog.error(_("Could not create VNC config directory: %s"), strerror(errno));
+ }
+
+ if (os::mkdir_p(os::getvncdatadir(), 0755) == -1) {
+ if (errno != EEXIST)
+ vlog.error(_("Could not create VNC data directory: %s"), strerror(errno));
+ }
+
+ if (os::mkdir_p(os::getvncstatedir(), 0755) == -1) {
+ if (errno != EEXIST)
+ vlog.error(_("Could not create VNC state directory: %s"), strerror(errno));
+ }
CSecurity::upg = &dlg;
#if defined(HAVE_GNUTLS) || defined(HAVE_NETTLE)