From a79c33d61eeba6c0745788b164d35832ef72f1ab Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 30 May 2024 16:05:35 +0200 Subject: [PATCH] Create common recursive mkdir() Avoid duplicating this complexity in too many places. At the same time make the interface more identical to regular mkdir(), for familiarity. --- common/os/os.cxx | 34 +++++++++++++++++++++++++ common/os/os.h | 7 ++++++ unix/vncpasswd/vncpasswd.cxx | 13 +++------- unix/vncserver/vncsession.c | 49 ++++++++++++++++++++---------------- vncviewer/vncviewer.cxx | 49 +++++++++++------------------------- 5 files changed, 87 insertions(+), 65 deletions(-) diff --git a/common/os/os.cxx b/common/os/os.cxx index 35f87b03..83995d0d 100644 --- a/common/os/os.cxx +++ b/common/os/os.cxx @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -39,6 +40,7 @@ #include /* MinGW needs it */ #include #define stat _stat +#define mkdir(path, mode) mkdir(path) #endif static const char* getvncdir(bool userDir, const char *xdg_env, const char *xdg_def) @@ -126,3 +128,35 @@ const char* os::getvncstatedir() { 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; +} diff --git a/common/os/os.h b/common/os/os.h index 8e522676..a3448070 100644 --- a/common/os/os.h +++ b/common/os/os.h @@ -20,6 +20,8 @@ #ifndef OS_OS_H #define OS_OS_H +#include + namespace os { /* @@ -62,6 +64,11 @@ 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 */ diff --git a/unix/vncpasswd/vncpasswd.cxx b/unix/vncpasswd/vncpasswd.cxx index 68c44289..30091a3d 100644 --- a/unix/vncpasswd/vncpasswd.cxx +++ b/unix/vncpasswd/vncpasswd.cxx @@ -23,6 +23,7 @@ #include #endif +#include #include #include #include @@ -161,16 +162,10 @@ int main(int argc, char** argv) 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); } diff --git a/unix/vncserver/vncsession.c b/unix/vncserver/vncsession.c index 31dee57d..1ee096c7 100644 --- a/unix/vncserver/vncsession.c +++ b/unix/vncserver/vncsession.c @@ -358,33 +358,33 @@ switch_user(const char *username, uid_t uid, gid_t gid) } } -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 @@ -431,7 +431,12 @@ redir_stdio(const char *homedir, const char *display, char **envp) #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) { diff --git a/vncviewer/vncviewer.cxx b/vncviewer/vncviewer.cxx index 59be4812..91e2be3b 100644 --- a/vncviewer/vncviewer.cxx +++ b/vncviewer/vncviewer.cxx @@ -37,7 +37,6 @@ #ifdef WIN32 #include #include -#define mkdir(path, mode) _mkdir(path) #endif #ifdef __APPLE__ @@ -429,36 +428,6 @@ static void init_fltk() #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 @@ -755,9 +724,21 @@ int main(int argc, char** argv) 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) -- 2.39.5