changeset 255:d987a5fc4a3e

core: add sys_mkdir function This function creates a directory recursively, will be needed for save.
author David Demelier <markand@malikania.fr>
date Thu, 03 Dec 2020 14:56:07 +0100
parents 6367b976112d
children 9dcb9354dc74
files doc/docs/dev/api/core/sys.md libmlk-core/core/sys.c libmlk-core/core/sys.h
diffstat 3 files changed, 66 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/doc/docs/dev/api/core/sys.md	Thu Dec 03 13:49:54 2020 +0100
+++ b/doc/docs/dev/api/core/sys.md	Thu Dec 03 14:56:07 2020 +0100
@@ -51,6 +51,16 @@
 sys_dir(enum sys_dir kind)
 ```
 
+### sys\_mkdir
+
+Create the directory `path` recursively. Returns false on errors other than
+already existing.
+
+```c
+bool
+sys_mkdir(const char *path)
+```
+
 ### sys\_finish
 
 This function is automatically called from [core_finish](core.md#core_finish)
--- a/libmlk-core/core/sys.c	Thu Dec 03 13:49:54 2020 +0100
+++ b/libmlk-core/core/sys.c	Thu Dec 03 14:56:07 2020 +0100
@@ -25,6 +25,11 @@
 
 #if defined(_WIN32)
 #       include <shlwapi.h>
+#       include <windows.h>
+#else
+#       include <sys/stat.h>
+#       include <errno.h>
+#       include <string.h>
 #endif
 
 #include <SDL.h>
@@ -192,6 +197,21 @@
 	return NULL;
 }
 
+static bool
+mkpath(const char *path)
+{
+#ifdef _WIN32
+	/* TODO: add error using the convenient FormatMessage function. */
+	if (!CreateDirectoryA(path, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
+		return errorf("unable to create directory: %s", path);
+#else
+	if (mkdir(path, 0755) < 0 && errno != EEXIST)
+		return errorf("%s", strerror(errno));
+#endif
+
+	return true;
+}
+
 const char *
 sys_dir(enum sys_dir kind)
 {
@@ -205,6 +225,39 @@
 	}
 }
 
+bool
+sys_mkdir(const char *directory)
+{
+	char path[PATH_MAX], *p;
+
+	/* Copy the directory to normalize and iterate over '/'. */
+	snprintf(path, sizeof (path), "%s", directory);
+	normalize(path);
+
+#if defined(_WIN32)
+	/* Remove drive letter that we don't need. */
+	if ((p = strchr(path, ':')))
+		++p;
+	else
+		p = path;
+#else
+	p = path;
+#endif
+
+	for (p = p + 1; *p; ++p) {
+		if (*p == '/') {
+			*p = 0;
+
+			if (!mkpath(path))
+				return false;
+
+			*p = '/';
+		}
+	}
+
+	return mkpath(path);
+}
+
 void
 sys_finish(void)
 {
--- a/libmlk-core/core/sys.h	Thu Dec 03 13:49:54 2020 +0100
+++ b/libmlk-core/core/sys.h	Thu Dec 03 14:56:07 2020 +0100
@@ -35,6 +35,9 @@
 const char *
 sys_dir(enum sys_dir kind);
 
+bool
+sys_mkdir(const char *path);
+
 void
 sys_finish(void);