diff options
-rw-r--r-- | src/config.h | 44 | ||||
-rw-r--r-- | src/mds.c | 165 | ||||
-rw-r--r-- | src/mds.h | 22 |
3 files changed, 185 insertions, 46 deletions
diff --git a/src/config.h b/src/config.h index df7f81a..abab904 100644 --- a/src/config.h +++ b/src/config.h @@ -28,10 +28,42 @@ /** + * The directory where all servers are installed + */ +#ifndef LIBEXECDIR +#define LIBEXECDIR "/usr/libexec" +#endif + + +/** + * The system's directory for non-persistent temporary files + */ +#ifndef TMPDIR +#define TMPDIR "/tmp" +#endif + + +/** + * The system's directory for runtime data + */ +#ifndef RUNDIR +#define RUNDIR "/run" +#endif + + +/** * The root directory of all runtime data stored by MDS */ #ifndef MDS_RUNTIME_ROOT_DIRECTORY -#define MDS_RUNTIME_ROOT_DIRECTORY "/run/" PKGNAME +#define MDS_RUNTIME_ROOT_DIRECTORY RUNDIR "/" PKGNAME +#endif + + +/** + * The root directory of temporarily stored data stored by MDS servers + */ +#ifndef MDS_STORAGE_ROOT_DIRECTORY +#define MDS_STORAGE_ROOT_DIRECTORY TMPDIR "/.{system-directory}." PKGNAME #endif @@ -58,7 +90,7 @@ #define NOBODY_GROUP_GID ROOT_GROUP_GID #endif -/* There three names above are redundant, but hat is to avoid errors. */ +/* There three names above are redundant, but that is to avoid errors. */ /** @@ -111,14 +143,6 @@ /** - * The directory where all servers are installed - */ -#ifndef LIBEXECDIR -#define LIBEXECDIR "/usr/libexec" -#endif - - -/** * The minimum time that most have elapsed for respawning to be allowed. */ #ifndef RESPAWN_TIME_LIMIT_SECONDS @@ -32,6 +32,7 @@ #include <sys/un.h> #include <sys/wait.h> #include <time.h> +#include <dirent.h> /** @@ -54,11 +55,11 @@ static char** argv; */ int main(int argc_, char** argv_) { + int fd = -1; struct sockaddr_un address; char pathname[PATH_MAX]; char piddata[64]; unsigned int display; - int fd; FILE *f; int rc; @@ -86,7 +87,7 @@ int main(int argc_, char** argv_) } /* Create directory for socket files, PID files and such. */ - if (create_runtime_root_directory()) + if (create_directory_root(MDS_RUNTIME_ROOT_DIRECTORY)) return 1; /* Determine display index. */ @@ -179,6 +180,14 @@ int main(int argc_, char** argv_) fflush(f); fclose(f); + /* Create data storage directory. */ + if (create_directory_root(MDS_STORAGE_ROOT_DIRECTORY)) + goto fail; + snprintf(pathname, sizeof(pathname) / sizeof(char), + "%s/%u.data", MDS_STORAGE_ROOT_DIRECTORY, display); + if (unlink_recursive(pathname) || create_directory_user(pathname)) + goto fail; + /* Save MDS_DISPLAY environment variable. */ snprintf(pathname, sizeof(pathname) / sizeof(char), /* Excuse the reuse without renaming. */ "%s=:%u", DISPLAY_ENV, display); @@ -193,49 +202,48 @@ int main(int argc_, char** argv_) fd = socket(AF_UNIX, SOCK_STREAM, 0); if ((fchmod(fd, S_IRWXU) < 0) || (fchown(fd, getuid(), NOBODY_GROUP_GID) < 0)) - { - perror(*argv); - close(fd); - return 1; - } + goto fail; if (bind(fd, (struct sockaddr*)(&address), sizeof(address)) < 0) - { - perror(*argv); - close(fd); - return 1; - } + goto fail; /* Start listening on socket. */ if (listen(fd, SOMAXCONN) < 0) - { - perror(*argv); - close(fd); - return 1; - } + goto fail; /* Drop privileges. They most not be propagated non-authorised components. */ /* setgid should not be set, but just to be safe we are restoring both user and group. */ if ((seteuid(getuid()) < 0) || (setegid(getgid()) < 0)) - { - perror(*argv); - close(fd); - return 1; - } + goto fail; /* Start master server and respawn it if it crashes. */ rc = spawn_and_respawn_server(fd); - + + done: /* Shutdown, close and remove the socket. */ - shutdown(fd, SHUT_RDWR); - close(fd); - unlink(pathname); + if (fd != -1) + { + shutdown(fd, SHUT_RDWR); + close(fd); + unlink(pathname); + } /* Remove PID file. */ snprintf(pathname, sizeof(pathname) / sizeof(char), "%s/%u.pid", MDS_RUNTIME_ROOT_DIRECTORY, display); unlink(pathname); + /* Remove directories */ + rmdir(MDS_RUNTIME_ROOT_DIRECTORY); /* Do not care if it fails, it is probably used by another display. */ + rmdir(MDS_STORAGE_ROOT_DIRECTORY); /* Do not care if it fails, it is probably used by another display. */ + snprintf(pathname, sizeof(pathname) / sizeof(char), + "%s/%u.data", MDS_STORAGE_ROOT_DIRECTORY, display); + unlink_recursive(pathname); /* An error will be printed on error, do nothing more. */ + return rc; + + fail: + rc = 1; + goto done; } @@ -347,15 +355,62 @@ int spawn_and_respawn_server(int fd) /** - * Create directory for socket files, PID files and such + * Create a directory owned by the root user and root group + * + * @param pathname The pathname of the directory to create + * @return Non-zero on error + */ +int create_directory_root(const char* pathname) +{ + struct stat attr; + + if (stat(pathname, &attr) == 0) + { + /* Cannot create the directory, its pathname refers to an existing. */ + if (S_ISDIR(attr.st_mode) == 0) + { + /* But it is not a directory so we cannot continue. */ + fprintf(stderr, + "%s: %s already exists but is not a directory.\n", + pathname, *argv); + return 1; + } + } + else + { + /* Directory is missing, create it. */ + if (mkdir(pathname, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) + { + if (errno != EEXIST) /* Unlikely race condition. */ + { + perror(*argv); + return 1; + } + } + else + /* Set ownership. */ + if (chown(pathname, ROOT_USER_UID, ROOT_GROUP_GID) < 0) + { + perror(*argv); + return 1; + } + } + + return 0; +} + + +/** + * Create a directory owned by the real user and nobody group * - * @return Non-zero on error + * @param pathname The pathname of the directory to create + * @return Non-zero on error */ -int create_runtime_root_directory(void) +int create_directory_user(const char* pathname) { struct stat attr; - if (stat(MDS_RUNTIME_ROOT_DIRECTORY, &attr) == 0) + if (stat(pathname, &attr) == 0) { /* Cannot create the directory, its pathname refers to an existing. */ if (S_ISDIR(attr.st_mode) == 0) @@ -363,14 +418,14 @@ int create_runtime_root_directory(void) /* But it is not a directory so we cannot continue. */ fprintf(stderr, "%s: %s already exists but is not a directory.\n", - MDS_RUNTIME_ROOT_DIRECTORY, *argv); + pathname, *argv); return 1; } } else { /* Directory is missing, create it. */ - if (mkdir(MDS_RUNTIME_ROOT_DIRECTORY, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) + if (mkdir(pathname, S_IRWXU) < 0) { if (errno != EEXIST) /* Unlikely race condition. */ { @@ -380,7 +435,7 @@ int create_runtime_root_directory(void) } else /* Set ownership. */ - if (chown(MDS_RUNTIME_ROOT_DIRECTORY, ROOT_USER_UID, ROOT_GROUP_GID) < 0) + if (chown(pathname, getuid(), NOBODY_GROUP_GID) < 0) { perror(*argv); return 1; @@ -390,3 +445,47 @@ int create_runtime_root_directory(void) return 0; } + +/** + * Recursively remove a directory + * + * @param pathname The pathname of the directory to remove + * @return Non-zero on error + */ +int unlink_recursive(const char* pathname) +{ + DIR* dir = opendir(pathname); + int rc = 0; + struct dirent* file; + + if (dir == NULL) + { + perror(*argv); + return 1; + } + + while ((file = readdir(dir)) != NULL) + if (strcmp(file->d_name, ".") && strcmp(file->d_name, "..")) + if (unlink(file->d_name) < 0) + { + if (errno == EISDIR) + unlink_recursive(file->d_name); + else + { + perror(*argv); + rc = 1; + goto done; + } + } + + if (rmdir(pathname) < 0) + { + perror(*argv); + rc = 1; + } + + done: + closedir(dir); + return rc; +} + @@ -27,13 +27,29 @@ */ int spawn_and_respawn_server(int fd); +/** + * Create a directory owned by the root user and root group + * + * @param pathname The pathname of the directory to create + * @return Non-zero on error + */ +int create_directory_root(const char* pathname); + +/** + * Create a directory owned by the real user and nobody group + * + * @param pathname The pathname of the directory to create + * @return Non-zero on error + */ +int create_directory_user(const char* pathname); /** - * Create directory for socket files, PID files and such + * Recursively remove a directory * - * @return Non-zero on error + * @param pathname The pathname of the directory to remove + * @return Non-zero on error */ -int create_runtime_root_directory(void); +int unlink_recursive(const char* pathname); #endif |