[PATCH/RFC/GSoC 1/3] path.c: implement xdg_runtime_dir()
this function does the following:
1. if $XDG_RUNTIME_DIR is non-empty, `$XDG_RUNTIME_DIR/git` is used in next
step, otherwise `/tmp/git-$uid` is taken.
2. ensure that above directory does exist. what's more, it must has correct
permission and ownership.
3. a newly allocated string consisting of the path of above directory and
$filename is returned.
Under following situation, NULL will be returned:
+ the directory mentioned in step 1 exists but have wrong permission or
ownership.
+ the directory or its parent cannot be created.
Notice:
+ the caller is responsible for deallocating the returned string.
Signed-off-by: Hui Yiqun <huiyiqun@gmail.com>
---
cache.h | 23 +++++++++++++++++++++++
path.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 82 insertions(+)
diff --git a/cache.h b/cache.h
index b829410..e640a54 100644
--- a/cache.h
+++ b/cache.h
@@ -999,6 +999,29 @@ extern int is_ntfs_dotgit(const char *name);
*/
extern char *xdg_config_home(const char *filename);
+/**
+ * this function does the following:
+ *
+ * 1. if $XDG_RUNTIME_DIR is non-empty, `$XDG_RUNTIME_DIR/git` is used in next
+ * step, otherwise `/tmp/git-$uid` is taken.
+ * 2. ensure that above directory does exist. what's more, it must has correct
+ * permission and ownership.
+ * 3. a newly allocated string consisting of the path of above directory and
+ * $filename is returned.
+ *
+ * Under following situation, NULL will be returned:
+ *
+ * + the directory mentioned in step 1 exists but have wrong permission or
+ * ownership.
+ * + the directory or its parent cannot be created.
+ *
+ * Notice:
+ *
+ * + the caller is responsible for deallocating the returned string.
+ *
+ */
+extern char *xdg_runtime_dir(const char *filename);
+
/* object replacement */
#define LOOKUP_REPLACE_OBJECT 1
#define LOOKUP_UNKNOWN_OBJECT 2
diff --git a/path.c b/path.c
index 8b7e168..2deecb3 100644
--- a/path.c
+++ b/path.c
@@ -5,6 +5,7 @@
#include "strbuf.h"
#include "string-list.h"
#include "dir.h"
+#include "git-compat-util.h"
static int get_st_mode_bits(const char *path, int *mode)
{
@@ -1193,6 +1194,64 @@ char *xdg_config_home(const char *filename)
return NULL;
}
+char *xdg_runtime_dir(const char *filename)
+{
+ char *runtime_dir, *git_runtime_dir;
+ struct stat st;
+ uid_t uid = getuid();
+
+ assert(filename);
+ runtime_dir = getenv("XDG_RUNTIME_DIR");
+ if (runtime_dir && *runtime_dir)
+ git_runtime_dir = mkpathdup("%s/git/", runtime_dir);
+ else
+ git_runtime_dir = mkpathdup("/tmp/git-%d", uid);
+
+ if (!lstat(git_runtime_dir, &st)) {
+ /*
+ * As described in XDG base dir spec[1], the subdirectory
+ * under $XDG_RUNTIME_DIR or its fallback MUST be owned by
+ * the user, and its unix access mode MUST be 0700.
+ *
+ * Calling chmod or chown silently may cause security
+ * problem if somebody chdir to it, sleep, and then, try
+ * to open our protected runtime cache or socket.
+ * So we just put warning and left it to user to solve.
+ *
+ * [1]https://specifications.freedesktop.org/basedir-spec/
+ * basedir-spec-latest.html
+ */
+ if ((st.st_mode & 0777) != S_IRWXU) {
+ fprintf(stderr,
+ "permission of runtime directory '%s' "
+ "MUST be 0700 instead of 0%o\n",
+ git_runtime_dir, (st.st_mode & 0777));
+ return NULL;
+ } else if (st.st_uid != uid) {
+ fprintf(stderr,
+ "owner of runtime directory '%s' "
+ "MUST be %d instead of %d\n",
+ git_runtime_dir, uid, st.st_uid);
+ return NULL;
+ }
+ /* TODO: check whether git_runtime_dir is an directory */
+ } else {
+ if (safe_create_leading_directories_const(git_runtime_dir) < 0) {
+ fprintf(stderr,
+ "unable to create directories for '%s'\n",
+ git_runtime_dir);
+ return NULL;
+ }
+ if (mkdir(git_runtime_dir, 0700) < 0) {
+ fprintf(stderr,
+ "unable to mkdir '%s'\n", git_runtime_dir);
+ return NULL;
+ }
+ }
+ free(git_runtime_dir);
+ return mkpathdup("%s/%s", git_runtime_dir, filename);
+}
+
GIT_PATH_FUNC(git_path_cherry_pick_head, "CHERRY_PICK_HEAD")
GIT_PATH_FUNC(git_path_revert_head, "REVERT_HEAD")
GIT_PATH_FUNC(git_path_squash_msg, "SQUASH_MSG")
--
2.7.2