path.c 21.7 KB
Newer Older
1
/*
2
 * Utilities for paths and pathnames
3 4
 */
#include "cache.h"
5
#include "strbuf.h"
6
#include "string-list.h"
7
#include "dir.h"
8

9
static int get_st_mode_bits(const char *path, int *mode)
10 11 12 13 14 15 16 17
{
	struct stat st;
	if (lstat(path, &st) < 0)
		return -1;
	*mode = st.st_mode;
	return 0;
}

18 19
static char bad_path[] = "/bad-path/";

20
static struct strbuf *get_pathname(void)
21
{
22 23 24
	static struct strbuf pathname_array[4] = {
		STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
	};
25
	static int index;
26 27 28
	struct strbuf *sb = &pathname_array[3 & ++index];
	strbuf_reset(sb);
	return sb;
29 30
}

31 32 33 34 35 36 37 38 39 40 41
static char *cleanup_path(char *path)
{
	/* Clean it up */
	if (!memcmp(path, "./", 2)) {
		path += 2;
		while (*path == '/')
			path++;
	}
	return path;
}

42 43 44 45 46 47 48
static void strbuf_cleanup_path(struct strbuf *sb)
{
	char *path = cleanup_path(sb->buf);
	if (path > sb->buf)
		strbuf_remove(sb, 0, path - sb->buf);
}

49 50 51 52 53 54 55 56 57
char *mksnpath(char *buf, size_t n, const char *fmt, ...)
{
	va_list args;
	unsigned len;

	va_start(args, fmt);
	len = vsnprintf(buf, n, fmt, args);
	va_end(args);
	if (len >= n) {
58
		strlcpy(buf, bad_path, n);
59 60 61 62 63
		return buf;
	}
	return cleanup_path(buf);
}

64
static int dir_prefix(const char *buf, const char *dir)
65
{
66 67 68 69
	int len = strlen(dir);
	return !strncmp(buf, dir, len) &&
		(is_dir_sep(buf[len]) || buf[len] == '\0');
}
70

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
/* $buf =~ m|$dir/+$file| but without regex */
static int is_dir_file(const char *buf, const char *dir, const char *file)
{
	int len = strlen(dir);
	if (strncmp(buf, dir, len) || !is_dir_sep(buf[len]))
		return 0;
	while (is_dir_sep(buf[len]))
		len++;
	return !strcmp(buf + len, file);
}

static void replace_dir(struct strbuf *buf, int len, const char *newdir)
{
	int newlen = strlen(newdir);
	int need_sep = (buf->buf[len] && !is_dir_sep(buf->buf[len])) &&
		!is_dir_sep(newdir[newlen - 1]);
	if (need_sep)
		len--;	 /* keep one char, to be replaced with '/'  */
	strbuf_splice(buf, 0, len, newdir, newlen);
	if (need_sep)
		buf->buf[newlen] = '/';
}

94
static const char *common_list[] = {
95
	"/branches", "/hooks", "/info", "!/logs", "/lost-found",
96
	"/objects", "/refs", "/remotes", "/worktrees", "/rr-cache", "/svn",
97
	"config", "!gc.pid", "packed-refs", "shallow",
98 99 100 101 102 103 104 105
	NULL
};

static void update_common_dir(struct strbuf *buf, int git_dir_len)
{
	char *base = buf->buf + git_dir_len;
	const char **p;

106 107
	if (is_dir_file(base, "logs", "HEAD") ||
	    is_dir_file(base, "info", "sparse-checkout"))
108 109 110 111
		return;	/* keep this in $GIT_DIR */
	for (p = common_list; *p; p++) {
		const char *path = *p;
		int is_dir = 0;
112 113
		if (*path == '!')
			path++;
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
		if (*path == '/') {
			path++;
			is_dir = 1;
		}
		if (is_dir && dir_prefix(base, path)) {
			replace_dir(buf, git_dir_len, get_git_common_dir());
			return;
		}
		if (!is_dir && !strcmp(base, path)) {
			replace_dir(buf, git_dir_len, get_git_common_dir());
			return;
		}
	}
}

129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
void report_linked_checkout_garbage(void)
{
	struct strbuf sb = STRBUF_INIT;
	const char **p;
	int len;

	if (!git_common_dir_env)
		return;
	strbuf_addf(&sb, "%s/", get_git_dir());
	len = sb.len;
	for (p = common_list; *p; p++) {
		const char *path = *p;
		if (*path == '!')
			continue;
		strbuf_setlen(&sb, len);
		strbuf_addstr(&sb, path);
		if (file_exists(sb.buf))
			report_garbage("unused in linked checkout", sb.buf);
	}
	strbuf_release(&sb);
149 150
}

151 152 153 154 155 156 157 158 159 160 161
static void adjust_git_path(struct strbuf *buf, int git_dir_len)
{
	const char *base = buf->buf + git_dir_len;
	if (git_graft_env && is_dir_file(base, "info", "grafts"))
		strbuf_splice(buf, 0, buf->len,
			      get_graft_file(), strlen(get_graft_file()));
	else if (git_index_env && !strcmp(base, "index"))
		strbuf_splice(buf, 0, buf->len,
			      get_index_file(), strlen(get_index_file()));
	else if (git_db_env && dir_prefix(base, "objects"))
		replace_dir(buf, git_dir_len + 7, get_object_directory());
162 163
	else if (git_common_dir_env)
		update_common_dir(buf, git_dir_len);
164 165
}

166
static void do_git_path(struct strbuf *buf, const char *fmt, va_list args)
167
{
168 169
	int gitdir_len;
	strbuf_addstr(buf, get_git_dir());
170 171
	if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
		strbuf_addch(buf, '/');
172
	gitdir_len = buf->len;
173
	strbuf_vaddf(buf, fmt, args);
174
	adjust_git_path(buf, gitdir_len);
175
	strbuf_cleanup_path(buf);
176 177
}

Jeff King's avatar
Jeff King committed
178 179 180 181 182 183 184 185 186 187
char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
{
	va_list args;
	strbuf_reset(buf);
	va_start(args, fmt);
	do_git_path(buf, fmt, args);
	va_end(args);
	return buf->buf;
}

188
void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
189 190 191
{
	va_list args;
	va_start(args, fmt);
192
	do_git_path(sb, fmt, args);
193 194 195
	va_end(args);
}

196
const char *git_path(const char *fmt, ...)
197
{
198
	struct strbuf *pathname = get_pathname();
199 200
	va_list args;
	va_start(args, fmt);
201
	do_git_path(pathname, fmt, args);
202
	va_end(args);
203
	return pathname->buf;
204 205 206
}

char *git_pathdup(const char *fmt, ...)
207
{
208
	struct strbuf path = STRBUF_INIT;
209 210
	va_list args;
	va_start(args, fmt);
211
	do_git_path(&path, fmt, args);
212
	va_end(args);
213
	return strbuf_detach(&path, NULL);
214 215 216
}

char *mkpathdup(const char *fmt, ...)
217
{
218
	struct strbuf sb = STRBUF_INIT;
219 220
	va_list args;
	va_start(args, fmt);
221
	strbuf_vaddf(&sb, fmt, args);
222
	va_end(args);
223 224
	strbuf_cleanup_path(&sb);
	return strbuf_detach(&sb, NULL);
225 226
}

227
const char *mkpath(const char *fmt, ...)
228 229
{
	va_list args;
230
	struct strbuf *pathname = get_pathname();
231
	va_start(args, fmt);
232
	strbuf_vaddf(pathname, fmt, args);
233
	va_end(args);
234
	return cleanup_path(pathname->buf);
235
}
236

237 238
static void do_submodule_path(struct strbuf *buf, const char *path,
			      const char *fmt, va_list args)
239 240 241
{
	const char *git_dir;

242 243 244 245
	strbuf_addstr(buf, path);
	if (buf->len && buf->buf[buf->len - 1] != '/')
		strbuf_addch(buf, '/');
	strbuf_addstr(buf, ".git");
246

247
	git_dir = read_gitfile(buf->buf);
248
	if (git_dir) {
249 250
		strbuf_reset(buf);
		strbuf_addstr(buf, git_dir);
251
	}
252
	strbuf_addch(buf, '/');
253

254 255
	strbuf_vaddf(buf, fmt, args);
	strbuf_cleanup_path(buf);
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
}

char *git_pathdup_submodule(const char *path, const char *fmt, ...)
{
	va_list args;
	struct strbuf buf = STRBUF_INIT;
	va_start(args, fmt);
	do_submodule_path(&buf, path, fmt, args);
	va_end(args);
	return strbuf_detach(&buf, NULL);
}

void strbuf_git_path_submodule(struct strbuf *buf, const char *path,
			       const char *fmt, ...)
{
	va_list args;
	va_start(args, fmt);
	do_submodule_path(buf, path, fmt, args);
	va_end(args);
}

277
int validate_headref(const char *path)
278 279 280
{
	struct stat st;
	char *buf, buffer[256];
281
	unsigned char sha1[20];
282 283
	int fd;
	ssize_t len;
284 285 286 287 288 289 290

	if (lstat(path, &st) < 0)
		return -1;

	/* Make sure it is a "refs/.." symlink */
	if (S_ISLNK(st.st_mode)) {
		len = readlink(path, buffer, sizeof(buffer)-1);
291
		if (len >= 5 && !memcmp("refs/", buffer, 5))
292 293 294 295 296 297 298 299 300 301
			return 0;
		return -1;
	}

	/*
	 * Anything else, just open it and try to see if it is a symbolic ref.
	 */
	fd = open(path, O_RDONLY);
	if (fd < 0)
		return -1;
302
	len = read_in_full(fd, buffer, sizeof(buffer)-1);
303 304 305 306 307
	close(fd);

	/*
	 * Is it a symbolic ref?
	 */
308
	if (len < 4)
309
		return -1;
310 311 312 313 314
	if (!memcmp("ref:", buffer, 4)) {
		buf = buffer + 4;
		len -= 4;
		while (len && isspace(*buf))
			buf++, len--;
315
		if (len >= 5 && !memcmp("refs/", buf, 5))
316 317 318 319 320 321 322
			return 0;
	}

	/*
	 * Is this a detached HEAD?
	 */
	if (!get_sha1_hex(buffer, sha1))
323
		return 0;
324

325 326 327
	return -1;
}

328
static struct passwd *getpw_str(const char *username, size_t len)
329
{
330
	struct passwd *pw;
331
	char *username_z = xmemdupz(username, len);
332 333 334 335
	pw = getpwnam(username_z);
	free(username_z);
	return pw;
}
336

337 338 339 340 341 342 343 344 345 346 347 348 349
/*
 * Return a string with ~ and ~user expanded via getpw*.  If buf != NULL,
 * then it is a newly allocated string. Returns NULL on getpw failure or
 * if path is NULL.
 */
char *expand_user_path(const char *path)
{
	struct strbuf user_path = STRBUF_INIT;
	const char *to_copy = path;

	if (path == NULL)
		goto return_null;
	if (path[0] == '~') {
350
		const char *first_slash = strchrnul(path, '/');
351 352
		const char *username = path + 1;
		size_t username_len = first_slash - username;
353 354
		if (username_len == 0) {
			const char *home = getenv("HOME");
355 356
			if (!home)
				goto return_null;
357
			strbuf_addstr(&user_path, home);
358 359 360 361
		} else {
			struct passwd *pw = getpw_str(username, username_len);
			if (!pw)
				goto return_null;
362
			strbuf_addstr(&user_path, pw->pw_dir);
363
		}
364
		to_copy = first_slash;
365
	}
366
	strbuf_addstr(&user_path, to_copy);
367 368 369 370
	return strbuf_detach(&user_path, NULL);
return_null:
	strbuf_release(&user_path);
	return NULL;
371 372
}

373 374 375 376 377 378 379 380 381 382
/*
 * First, one directory to try is determined by the following algorithm.
 *
 * (0) If "strict" is given, the path is used as given and no DWIM is
 *     done. Otherwise:
 * (1) "~/path" to mean path under the running user's home directory;
 * (2) "~user/path" to mean path under named user's home directory;
 * (3) "relative/path" to mean cwd relative directory; or
 * (4) "/absolute/path" to mean absolute directory.
 *
383 384 385
 * Unless "strict" is given, we check "%s/.git", "%s", "%s.git/.git", "%s.git"
 * in this order. We select the first one that is a valid git repository, and
 * chdir() to it. If none match, or we fail to chdir, we return NULL.
386 387 388 389 390 391
 *
 * If all goes well, we return the directory we used to chdir() (but
 * before ~user is expanded), avoiding getcwd() resolving symbolic
 * links.  User relative paths are also returned as they are given,
 * except DWIM suffixing.
 */
392
const char *enter_repo(const char *path, int strict)
393
{
394 395
	static struct strbuf validated_path = STRBUF_INIT;
	static struct strbuf used_path = STRBUF_INIT;
396 397

	if (!path)
398 399
		return NULL;

400 401
	if (!strict) {
		static const char *suffix[] = {
402
			"/.git", "", ".git/.git", ".git", NULL,
403
		};
404
		const char *gitfile;
405 406
		int len = strlen(path);
		int i;
407
		while ((1 < len) && (path[len-1] == '/'))
408
			len--;
409

410 411 412 413
		/*
		 * We can handle arbitrary-sized buffers, but this remains as a
		 * sanity check on untrusted input.
		 */
414
		if (PATH_MAX <= len)
415
			return NULL;
416

417 418 419 420 421 422 423 424
		strbuf_reset(&used_path);
		strbuf_reset(&validated_path);
		strbuf_add(&used_path, path, len);
		strbuf_add(&validated_path, path, len);

		if (used_path.buf[0] == '~') {
			char *newpath = expand_user_path(used_path.buf);
			if (!newpath)
425
				return NULL;
426 427
			strbuf_attach(&used_path, newpath, strlen(newpath),
				      strlen(newpath));
428 429
		}
		for (i = 0; suffix[i]; i++) {
430
			struct stat st;
431 432 433
			size_t baselen = used_path.len;
			strbuf_addstr(&used_path, suffix[i]);
			if (!stat(used_path.buf, &st) &&
434
			    (S_ISREG(st.st_mode) ||
435 436
			    (S_ISDIR(st.st_mode) && is_git_directory(used_path.buf)))) {
				strbuf_addstr(&validated_path, suffix[i]);
437 438
				break;
			}
439
			strbuf_setlen(&used_path, baselen);
440
		}
441 442
		if (!suffix[i])
			return NULL;
443 444 445 446 447 448
		gitfile = read_gitfile(used_path.buf) ;
		if (gitfile) {
			strbuf_reset(&used_path);
			strbuf_addstr(&used_path, gitfile);
		}
		if (chdir(used_path.buf))
449
			return NULL;
450
		path = validated_path.buf;
451
	}
452 453
	else if (chdir(path))
		return NULL;
454

455
	if (access("objects", X_OK) == 0 && access("refs", X_OK) == 0 &&
456
	    validate_headref("HEAD") == 0) {
René Scharfe's avatar
René Scharfe committed
457
		set_git_dir(".");
458
		check_repository_format();
459
		return path;
460 461 462 463
	}

	return NULL;
}
464

465
static int calc_shared_perm(int mode)
466
{
467
	int tweak;
468

469
	if (shared_repository < 0)
470
		tweak = -shared_repository;
471
	else
472
		tweak = shared_repository;
473 474 475 476 477 478 479 480 481

	if (!(mode & S_IWUSR))
		tweak &= ~0222;
	if (mode & S_IXUSR)
		/* Copy read bits to execute bits */
		tweak |= (tweak & 0444) >> 2;
	if (shared_repository < 0)
		mode = (mode & ~0777) | tweak;
	else
482
		mode |= tweak;
483

484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
	return mode;
}


int adjust_shared_perm(const char *path)
{
	int old_mode, new_mode;

	if (!shared_repository)
		return 0;
	if (get_st_mode_bits(path, &old_mode) < 0)
		return -1;

	new_mode = calc_shared_perm(old_mode);
	if (S_ISDIR(old_mode)) {
499
		/* Copy read bits to execute bits */
500 501
		new_mode |= (new_mode & 0444) >> 2;
		new_mode |= FORCE_DIR_SET_GID;
502 503
	}

504 505
	if (((old_mode ^ new_mode) & ~S_IFMT) &&
			chmod(path, (new_mode & ~S_IFMT)) < 0)
506 507 508
		return -2;
	return 0;
}
509

510 511 512 513 514 515 516 517 518 519
static int have_same_root(const char *path1, const char *path2)
{
	int is_abs1, is_abs2;

	is_abs1 = is_absolute_path(path1);
	is_abs2 = is_absolute_path(path2);
	return (is_abs1 && is_abs2 && tolower(path1[0]) == tolower(path2[0])) ||
	       (!is_abs1 && !is_abs2);
}

520 521 522 523 524 525 526 527
/*
 * Give path as relative to prefix.
 *
 * The strbuf may or may not be used, so do not assume it contains the
 * returned path.
 */
const char *relative_path(const char *in, const char *prefix,
			  struct strbuf *sb)
528
{
529 530 531 532
	int in_len = in ? strlen(in) : 0;
	int prefix_len = prefix ? strlen(prefix) : 0;
	int in_off = 0;
	int prefix_off = 0;
533 534
	int i = 0, j = 0;

535 536 537 538 539
	if (!in_len)
		return "./";
	else if (!prefix_len)
		return in;

540 541 542 543 544 545 546 547 548 549
	if (have_same_root(in, prefix)) {
		/* bypass dos_drive, for "c:" is identical to "C:" */
		if (has_dos_drive_prefix(in)) {
			i = 2;
			j = 2;
		}
	} else {
		return in;
	}

550 551 552
	while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
		if (is_dir_sep(prefix[i])) {
			while (is_dir_sep(prefix[i]))
553
				i++;
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
			while (is_dir_sep(in[j]))
				j++;
			prefix_off = i;
			in_off = j;
		} else {
			i++;
			j++;
		}
	}

	if (
	    /* "prefix" seems like prefix of "in" */
	    i >= prefix_len &&
	    /*
	     * but "/foo" is not a prefix of "/foobar"
	     * (i.e. prefix not end with '/')
	     */
	    prefix_off < prefix_len) {
		if (j >= in_len) {
			/* in="/a/b", prefix="/a/b" */
			in_off = in_len;
		} else if (is_dir_sep(in[j])) {
			/* in="/a/b/c", prefix="/a/b" */
			while (is_dir_sep(in[j]))
578
				j++;
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
			in_off = j;
		} else {
			/* in="/a/bbb/c", prefix="/a/b" */
			i = prefix_off;
		}
	} else if (
		   /* "in" is short than "prefix" */
		   j >= in_len &&
		   /* "in" not end with '/' */
		   in_off < in_len) {
		if (is_dir_sep(prefix[i])) {
			/* in="/a/b", prefix="/a/b/c/" */
			while (is_dir_sep(prefix[i]))
				i++;
			in_off = in_len;
		}
	}
	in += in_off;
	in_len -= in_off;

	if (i >= prefix_len) {
		if (!in_len)
			return "./";
		else
			return in;
	}

	strbuf_reset(sb);
	strbuf_grow(sb, in_len);

	while (i < prefix_len) {
		if (is_dir_sep(prefix[i])) {
			strbuf_addstr(sb, "../");
			while (is_dir_sep(prefix[i]))
				i++;
614 615 616 617
			continue;
		}
		i++;
	}
618 619 620 621 622 623
	if (!is_dir_sep(prefix[prefix_len - 1]))
		strbuf_addstr(sb, "../");

	strbuf_addstr(sb, in);

	return sb->buf;
624
}
625

626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
/*
 * A simpler implementation of relative_path
 *
 * Get relative path by removing "prefix" from "in". This function
 * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter
 * to increase performance when traversing the path to work_tree.
 */
const char *remove_leading_path(const char *in, const char *prefix)
{
	static char buf[PATH_MAX + 1];
	int i = 0, j = 0;

	if (!prefix || !prefix[0])
		return in;
	while (prefix[i]) {
		if (is_dir_sep(prefix[i])) {
			if (!is_dir_sep(in[j]))
				return in;
			while (is_dir_sep(prefix[i]))
				i++;
			while (is_dir_sep(in[j]))
				j++;
			continue;
		} else if (in[j] != prefix[i]) {
			return in;
		}
		i++;
		j++;
	}
	if (
	    /* "/foo" is a prefix of "/foo" */
	    in[j] &&
	    /* "/foo" is not a prefix of "/foobar" */
	    !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])
	   )
		return in;
	while (is_dir_sep(in[j]))
		j++;
	if (!in[j])
		strcpy(buf, ".");
	else
		strcpy(buf, in + j);
	return buf;
}

671
/*
672
 * It is okay if dst == src, but they should not overlap otherwise.
673
 *
674 675 676
 * Performs the following normalizations on src, storing the result in dst:
 * - Ensures that components are separated by '/' (Windows only)
 * - Squashes sequences of '/'.
677 678
 * - Removes "." components.
 * - Removes ".." components, and the components the precede them.
679 680
 * Returns failure (non-zero) if a ".." component appears as first path
 * component anytime during the normalization. Otherwise, returns success (0).
681 682 683
 *
 * Note that this function is purely textual.  It does not follow symlinks,
 * verify the existence of the path, or make any system calls.
684 685 686 687 688 689
 *
 * prefix_len != NULL is for a specific case of prefix_pathspec():
 * assume that src == dst and src[0..prefix_len-1] is already
 * normalized, any time "../" eats up to the prefix_len part,
 * prefix_len is reduced. In the end prefix_len is the remaining
 * prefix that has not been overridden by user pathspec.
690
 */
691
int normalize_path_copy_len(char *dst, const char *src, int *prefix_len)
692
{
693
	char *dst0;
694

695 696 697
	if (has_dos_drive_prefix(src)) {
		*dst++ = *src++;
		*dst++ = *src++;
698
	}
699
	dst0 = dst;
700

701
	if (is_dir_sep(*src)) {
702
		*dst++ = '/';
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741
		while (is_dir_sep(*src))
			src++;
	}

	for (;;) {
		char c = *src;

		/*
		 * A path component that begins with . could be
		 * special:
		 * (1) "." and ends   -- ignore and terminate.
		 * (2) "./"           -- ignore them, eat slash and continue.
		 * (3) ".." and ends  -- strip one and terminate.
		 * (4) "../"          -- strip one, eat slash and continue.
		 */
		if (c == '.') {
			if (!src[1]) {
				/* (1) */
				src++;
			} else if (is_dir_sep(src[1])) {
				/* (2) */
				src += 2;
				while (is_dir_sep(*src))
					src++;
				continue;
			} else if (src[1] == '.') {
				if (!src[2]) {
					/* (3) */
					src += 2;
					goto up_one;
				} else if (is_dir_sep(src[2])) {
					/* (4) */
					src += 3;
					while (is_dir_sep(*src))
						src++;
					goto up_one;
				}
			}
		}
742

743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759
		/* copy up to the next '/', and eat all '/' */
		while ((c = *src++) != '\0' && !is_dir_sep(c))
			*dst++ = c;
		if (is_dir_sep(c)) {
			*dst++ = '/';
			while (is_dir_sep(c))
				c = *src++;
			src--;
		} else if (!c)
			break;
		continue;

	up_one:
		/*
		 * dst0..dst is prefix portion, and dst[-1] is '/';
		 * go up one level.
		 */
760 761
		dst--;	/* go to trailing '/' */
		if (dst <= dst0)
762
			return -1;
763 764 765
		/* Windows: dst[-1] cannot be backslash anymore */
		while (dst0 < dst && dst[-1] != '/')
			dst--;
766 767
		if (prefix_len && *prefix_len > dst - dst0)
			*prefix_len = dst - dst0;
768
	}
769
	*dst = '\0';
770
	return 0;
771
}
772

773 774 775 776 777
int normalize_path_copy(char *dst, const char *src)
{
	return normalize_path_copy_len(dst, src, NULL);
}

778 779
/*
 * path = Canonical absolute path
780 781
 * prefixes = string_list containing normalized, absolute paths without
 * trailing slashes (except for the root directory, which is denoted by "/").
782
 *
783
 * Determines, for each path in prefixes, whether the "prefix"
784 785
 * is an ancestor directory of path.  Returns the length of the longest
 * ancestor directory, excluding any trailing slashes, or -1 if no prefix
786 787
 * is an ancestor.  (Note that this means 0 is returned if prefixes is
 * ["/"].) "/foo" is not considered an ancestor of "/foobar".  Directories
788 789
 * are not considered to be their own ancestors.  path must be in a
 * canonical form: empty components, or "." or ".." components are not
790
 * allowed.
791
 */
792
int longest_ancestor_length(const char *path, struct string_list *prefixes)
793
{
794
	int i, max_len = -1;
795

796
	if (!strcmp(path, "/"))
797 798
		return -1;

799 800
	for (i = 0; i < prefixes->nr; i++) {
		const char *ceil = prefixes->items[i].string;
801 802
		int len = strlen(ceil);

803 804 805 806 807 808
		if (len == 1 && ceil[0] == '/')
			len = 0; /* root matches anything, with length 0 */
		else if (!strncmp(path, ceil, len) && path[len] == '/')
			; /* match of length len */
		else
			continue; /* no match */
809

810
		if (len > max_len)
811 812 813 814 815
			max_len = len;
	}

	return max_len;
}
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851

/* strip arbitrary amount of directory separators at end of path */
static inline int chomp_trailing_dir_sep(const char *path, int len)
{
	while (len && is_dir_sep(path[len - 1]))
		len--;
	return len;
}

/*
 * If path ends with suffix (complete path components), returns the
 * part before suffix (sans trailing directory separators).
 * Otherwise returns NULL.
 */
char *strip_path_suffix(const char *path, const char *suffix)
{
	int path_len = strlen(path), suffix_len = strlen(suffix);

	while (suffix_len) {
		if (!path_len)
			return NULL;

		if (is_dir_sep(path[path_len - 1])) {
			if (!is_dir_sep(suffix[suffix_len - 1]))
				return NULL;
			path_len = chomp_trailing_dir_sep(path, path_len);
			suffix_len = chomp_trailing_dir_sep(suffix, suffix_len);
		}
		else if (path[--path_len] != suffix[--suffix_len])
			return NULL;
	}

	if (path_len && !is_dir_sep(path[path_len - 1]))
		return NULL;
	return xstrndup(path, chomp_trailing_dir_sep(path, path_len));
}
852 853 854 855 856 857 858 859

int daemon_avoid_alias(const char *p)
{
	int sl, ndot;

	/*
	 * This resurrects the belts and suspenders paranoia check by HPA
	 * done in <[email protected]> thread, now enter_repo()
860
	 * does not do getcwd() based path canonicalization.
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
	 *
	 * sl becomes true immediately after seeing '/' and continues to
	 * be true as long as dots continue after that without intervening
	 * non-dot character.
	 */
	if (!p || (*p != '/' && *p != '~'))
		return -1;
	sl = 1; ndot = 0;
	p++;

	while (1) {
		char ch = *p++;
		if (sl) {
			if (ch == '.')
				ndot++;
			else if (ch == '/') {
				if (ndot < 3)
					/* reject //, /./ and /../ */
					return -1;
				ndot = 0;
			}
			else if (ch == 0) {
				if (0 < ndot && ndot < 3)
					/* reject /.$ and /..$ */
					return -1;
				return 0;
			}
			else
				sl = ndot = 0;
		}
		else if (ch == 0)
			return 0;
		else if (ch == '/') {
			sl = 1;
			ndot = 0;
		}
	}
}
899

900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931
static int only_spaces_and_periods(const char *path, size_t len, size_t skip)
{
	if (len < skip)
		return 0;
	len -= skip;
	path += skip;
	while (len-- > 0) {
		char c = *(path++);
		if (c != ' ' && c != '.')
			return 0;
	}
	return 1;
}

int is_ntfs_dotgit(const char *name)
{
	int len;

	for (len = 0; ; len++)
		if (!name[len] || name[len] == '\\' || is_dir_sep(name[len])) {
			if (only_spaces_and_periods(name, len, 4) &&
					!strncasecmp(name, ".git", 4))
				return 1;
			if (only_spaces_and_periods(name, len, 5) &&
					!strncasecmp(name, "git~1", 5))
				return 1;
			if (name[len] != '\\')
				return 0;
			name += len + 1;
			len = -1;
		}
}
932 933 934 935 936 937 938 939 940 941 942 943 944 945 946

char *xdg_config_home(const char *filename)
{
	const char *home, *config_home;

	assert(filename);
	config_home = getenv("XDG_CONFIG_HOME");
	if (config_home && *config_home)
		return mkpathdup("%s/git/%s", config_home, filename);

	home = getenv("HOME");
	if (home)
		return mkpathdup("%s/.config/git/%s", home, filename);
	return NULL;
}
947 948 949 950 951 952 953 954 955 956

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")
GIT_PATH_FUNC(git_path_merge_msg, "MERGE_MSG")
GIT_PATH_FUNC(git_path_merge_rr, "MERGE_RR")
GIT_PATH_FUNC(git_path_merge_mode, "MERGE_MODE")
GIT_PATH_FUNC(git_path_merge_head, "MERGE_HEAD")
GIT_PATH_FUNC(git_path_fetch_head, "FETCH_HEAD")
GIT_PATH_FUNC(git_path_shallow, "shallow")