aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/config.h44
-rw-r--r--src/mds.c165
-rw-r--r--src/mds.h22
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
diff --git a/src/mds.c b/src/mds.c
index e017cb6..4f245f7 100644
--- a/src/mds.c
+++ b/src/mds.c
@@ -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;
+}
+
diff --git a/src/mds.h b/src/mds.h
index cc84f29..20b5f66 100644
--- a/src/mds.h
+++ b/src/mds.h
@@ -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