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@xxxxxxxxx> --- 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 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html