]> asedeno.scripts.mit.edu Git - git.git/blobdiff - path.c
Merge branch 'js/maint-clone-insteadof'
[git.git] / path.c
diff --git a/path.c b/path.c
index f4ed979997b6a968ba1987a199beae39035d5da2..496123ca552a3aad32b009c668962045ec78d218 100644 (file)
--- a/path.c
+++ b/path.c
@@ -91,7 +91,8 @@ int validate_headref(const char *path)
        struct stat st;
        char *buf, buffer[256];
        unsigned char sha1[20];
-       int len, fd;
+       int fd;
+       ssize_t len;
 
        if (lstat(path, &st) < 0)
                return -1;
@@ -266,92 +267,79 @@ int adjust_shared_perm(const char *path)
        if (lstat(path, &st) < 0)
                return -1;
        mode = st.st_mode;
-       if (mode & S_IRUSR)
-               mode |= (shared_repository == PERM_GROUP
-                        ? S_IRGRP
-                        : (shared_repository == PERM_EVERYBODY
-                           ? (S_IRGRP|S_IROTH)
-                           : 0));
-
-       if (mode & S_IWUSR)
-               mode |= S_IWGRP;
-
-       if (mode & S_IXUSR)
-               mode |= (shared_repository == PERM_GROUP
-                        ? S_IXGRP
-                        : (shared_repository == PERM_EVERYBODY
-                           ? (S_IXGRP|S_IXOTH)
-                           : 0));
-       if (S_ISDIR(mode))
+
+       if (shared_repository) {
+               int tweak = shared_repository;
+               if (!(mode & S_IWUSR))
+                       tweak &= ~0222;
+               mode = (mode & ~0777) | tweak;
+       } else {
+               /* Preserve old PERM_UMASK behaviour */
+               if (mode & S_IWUSR)
+                       mode |= S_IWGRP;
+       }
+
+       if (S_ISDIR(mode)) {
                mode |= FORCE_DIR_SET_GID;
+
+               /* Copy read bits to execute bits */
+               mode |= (shared_repository & 0444) >> 2;
+       }
+
        if ((mode & st.st_mode) != mode && chmod(path, mode) < 0)
                return -2;
        return 0;
 }
 
-/* We allow "recursive" symbolic links. Only within reason, though. */
-#define MAXDEPTH 5
-
-const char *make_absolute_path(const char *path)
+static const char *get_pwd_cwd(void)
 {
-       static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
-       char cwd[1024] = "";
-       int buf_index = 1, len;
-
-       int depth = MAXDEPTH;
-       char *last_elem = NULL;
-       struct stat st;
-
-       if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
-               die ("Too long path: %.*s", 60, path);
-
-       while (depth--) {
-               if (stat(buf, &st) || !S_ISDIR(st.st_mode)) {
-                       char *last_slash = strrchr(buf, '/');
-                       if (last_slash) {
-                               *last_slash = '\0';
-                               last_elem = xstrdup(last_slash + 1);
-                       } else {
-                               last_elem = xstrdup(buf);
-                               *buf = '\0';
-                       }
-               }
-
-               if (*buf) {
-                       if (!*cwd && !getcwd(cwd, sizeof(cwd)))
-                               die ("Could not get current working directory");
-
-                       if (chdir(buf))
-                               die ("Could not switch to '%s'", buf);
-               }
-               if (!getcwd(buf, PATH_MAX))
-                       die ("Could not get current working directory");
-
-               if (last_elem) {
-                       int len = strlen(buf);
-                       if (len + strlen(last_elem) + 2 > PATH_MAX)
-                               die ("Too long path name: '%s/%s'",
-                                               buf, last_elem);
-                       buf[len] = '/';
-                       strcpy(buf + len + 1, last_elem);
-                       free(last_elem);
-                       last_elem = NULL;
+       static char cwd[PATH_MAX + 1];
+       char *pwd;
+       struct stat cwd_stat, pwd_stat;
+       if (getcwd(cwd, PATH_MAX) == NULL)
+               return NULL;
+       pwd = getenv("PWD");
+       if (pwd && strcmp(pwd, cwd)) {
+               stat(cwd, &cwd_stat);
+               if (!stat(pwd, &pwd_stat) &&
+                   pwd_stat.st_dev == cwd_stat.st_dev &&
+                   pwd_stat.st_ino == cwd_stat.st_ino) {
+                       strlcpy(cwd, pwd, PATH_MAX);
                }
-
-               if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
-                       len = readlink(buf, next_buf, PATH_MAX);
-                       if (len < 0)
-                               die ("Invalid symlink: %s", buf);
-                       next_buf[len] = '\0';
-                       buf = next_buf;
-                       buf_index = 1 - buf_index;
-                       next_buf = bufs[buf_index];
-               } else
-                       break;
        }
+       return cwd;
+}
 
-       if (*cwd && chdir(cwd))
-               die ("Could not change back to '%s'", cwd);
+const char *make_nonrelative_path(const char *path)
+{
+       static char buf[PATH_MAX + 1];
+
+       if (is_absolute_path(path)) {
+               if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
+                       die ("Too long path: %.*s", 60, path);
+       } else {
+               const char *cwd = get_pwd_cwd();
+               if (!cwd)
+                       die("Cannot determine the current working directory");
+               if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
+                       die ("Too long path: %.*s", 60, path);
+       }
+       return buf;
+}
 
+const char *make_relative_path(const char *abs, const char *base)
+{
+       static char buf[PATH_MAX + 1];
+       int baselen;
+       if (!base)
+               return abs;
+       baselen = strlen(base);
+       if (prefixcmp(abs, base))
+               return abs;
+       if (abs[baselen] == '/')
+               baselen++;
+       else if (base[baselen - 1] != '/')
+               return abs;
+       strcpy(buf, abs + baselen);
        return buf;
 }