summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2016-12-10 00:48:42 -0800
committerMichael Forney <mforney@mforney.org>2016-12-10 11:56:37 -0800
commit54d24bc3b0de58ee417a040c404e1c26a36244ec (patch)
tree83c7a504062edc6a5868b31f5e196a4c97b1472e
parent1a47d9c6870e4b4e4fcd033d184f31a5b94a7a47 (diff)
perms-hook: Handle GIT_DIR and GIT_WORK_TREE
-rw-r--r--util/perms-hook.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/util/perms-hook.c b/util/perms-hook.c
index 7f92053b..d2afbaa8 100644
--- a/util/perms-hook.c
+++ b/util/perms-hook.c
@@ -40,6 +40,7 @@ struct special {
extern char **environ;
static dev_t rootdev;
+static int rootfd = AT_FDCWD;
static struct special oldsp, newsp;
static int status;
@@ -148,14 +149,14 @@ static int
chmod_v(const char *path, mode_t mode)
{
printf("chmod(\"%s\", %#o)\n", path, mode);
- return chmod(path, mode);
+ return fchmodat(rootfd, path, mode, AT_SYMLINK_NOFOLLOW);
}
static int
mkdir_v(const char *path, mode_t mode)
{
printf("mkdir(\"%s\", %#o)\n", path, mode);
- return mkdir(path, mode);
+ return mkdirat(rootfd, path, mode);
}
static int
@@ -164,7 +165,7 @@ defperm(const char *name)
struct stat st;
mode_t mode;
- if (lstat(name, &st) < 0)
+ if (fstatat(rootfd, name, &st, AT_SYMLINK_NOFOLLOW) < 0)
return -1;
if (st.st_dev != rootdev) {
errno = EXDEV;
@@ -196,7 +197,7 @@ specialperm(struct perm *p)
if (p->attempted)
return 0;
p->attempted = true;
- if (lstat(p->name, &st) < 0) {
+ if (fstatat(rootfd, p->name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
if (errno != ENOENT || !S_ISDIR(p->mode))
return -1;
if (mkdir_v(p->name, p->mode & ~S_IFMT) < 0)
@@ -333,7 +334,7 @@ readchanges(char *old, char *new)
int
main(int argc, char *argv[])
{
- char *prog, *old, *new;
+ char *prog, *old, *new, *tree;
struct stat st;
prog = basename(argv[0]);
@@ -355,10 +356,16 @@ main(int argc, char *argv[])
exit(2);
}
- if (stat(".git", &st) < 0)
+ if (!getenv("GIT_DIR") && stat(".git", &st) < 0)
die("stat .git:");
- if (stat(".", &st) < 0)
- die("stat .:");
+ tree = getenv("GIT_WORK_TREE");
+ if (!tree)
+ tree = ".";
+ rootfd = open(tree, O_RDONLY);
+ if (rootfd < 0)
+ die("open %s:", tree);
+ if (fstat(rootfd, &st) < 0)
+ die("fstat:", tree);
rootdev = st.st_dev;
if (old)