symlinks.con commit git-push: documentation and tests for pushing only branches (5c633a4)
   1#include "cache.h"
   2
   3int has_symlink_leading_path(const char *name, char *last_symlink)
   4{
   5        char path[PATH_MAX];
   6        const char *sp, *ep;
   7        char *dp;
   8
   9        sp = name;
  10        dp = path;
  11
  12        if (last_symlink && *last_symlink) {
  13                size_t last_len = strlen(last_symlink);
  14                size_t len = strlen(name);
  15                if (last_len < len &&
  16                    !strncmp(name, last_symlink, last_len) &&
  17                    name[last_len] == '/')
  18                        return 1;
  19                *last_symlink = '\0';
  20        }
  21
  22        while (1) {
  23                size_t len;
  24                struct stat st;
  25
  26                ep = strchr(sp, '/');
  27                if (!ep)
  28                        break;
  29                len = ep - sp;
  30                if (PATH_MAX <= dp + len - path + 2)
  31                        return 0; /* new name is longer than that??? */
  32                memcpy(dp, sp, len);
  33                dp[len] = 0;
  34
  35                if (lstat(path, &st))
  36                        return 0;
  37                if (S_ISLNK(st.st_mode)) {
  38                        if (last_symlink)
  39                                strcpy(last_symlink, path);
  40                        return 1;
  41                }
  42
  43                dp[len++] = '/';
  44                dp = dp + len;
  45                sp = ep + 1;
  46        }
  47        return 0;
  48}