path.c 21.9 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] = '/';
}

David Turner's avatar
David Turner committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
struct common_dir {
	/* Not considered garbage for report_linked_checkout_garbage */
	unsigned ignore_garbage:1;
	unsigned is_dir:1;
	/* Not common even though its parent is */
	unsigned exclude:1;
	const char *dirname;
};

static struct common_dir common_list[] = {
	{ 0, 1, 0, "branches" },
	{ 0, 1, 0, "hooks" },
	{ 0, 1, 0, "info" },
	{ 0, 0, 1, "info/sparse-checkout" },
	{ 1, 1, 0, "logs" },
	{ 1, 1, 1, "logs/HEAD" },
	{ 0, 1, 0, "lost-found" },
	{ 0, 1, 0, "objects" },
	{ 0, 1, 0, "refs" },
	{ 0, 1, 0, "remotes" },
	{ 0, 1, 0, "worktrees" },
	{ 0, 1, 0, "rr-cache" },
	{ 0, 1, 0, "svn" },
	{ 0, 0, 0, "config" },
	{ 1, 0, 0, "gc.pid" },
	{ 0, 0, 0, "packed-refs" },
	{ 0, 0, 0, "shallow" },
	{ 0, 0, 0, NULL }
122 123 124 125 126
};

static void update_common_dir(struct strbuf *buf, int git_dir_len)
{
	char *base = buf->buf + git_dir_len;
David Turner's avatar
David Turner committed
127
	const struct common_dir *p;
128

129 130
	if (is_dir_file(base, "logs", "HEAD") ||
	    is_dir_file(base, "info", "sparse-checkout"))
131
		return;	/* keep this in $GIT_DIR */
David Turner's avatar
David Turner committed
132 133 134
	for (p = common_list; p->dirname; p++) {
		const char *path = p->dirname;
		if (p->is_dir && dir_prefix(base, path)) {
135 136 137
			replace_dir(buf, git_dir_len, get_git_common_dir());
			return;
		}
David Turner's avatar
David Turner committed
138
		if (!p->is_dir && !strcmp(base, path)) {
139 140 141 142 143 144
			replace_dir(buf, git_dir_len, get_git_common_dir());
			return;
		}
	}
}

145 146 147
void report_linked_checkout_garbage(void)
{
	struct strbuf sb = STRBUF_INIT;
David Turner's avatar
David Turner committed
148
	const struct common_dir *p;
149 150 151 152 153 154
	int len;

	if (!git_common_dir_env)
		return;
	strbuf_addf(&sb, "%s/", get_git_dir());
	len = sb.len;
David Turner's avatar
David Turner committed
155 156 157
	for (p = common_list; p->dirname; p++) {
		const char *path = p->dirname;
		if (p->ignore_garbage)
158 159 160 161 162 163 164
			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);
165 166
}

167 168 169 170 171 172 173 174 175 176 177
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());
178 179
	else if (git_common_dir_env)
		update_common_dir(buf, git_dir_len);
180 181
}

182
static void do_git_path(struct strbuf *buf, const char *fmt, va_list args)
183
{
184 185
	int gitdir_len;
	strbuf_addstr(buf, get_git_dir());
186 187
	if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
		strbuf_addch(buf, '/');
188
	gitdir_len = buf->len;
189
	strbuf_vaddf(buf, fmt, args);
190
	adjust_git_path(buf, gitdir_len);
191
	strbuf_cleanup_path(buf);
192 193
}

194
void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
195 196 197
{
	va_list args;
	va_start(args, fmt);
198
	do_git_path(sb, fmt, args);
199 200 201
	va_end(args);
}

202
const char *git_path(const char *fmt, ...)
203
{
204
	struct strbuf *pathname = get_pathname();
205 206
	va_list args;
	va_start(args, fmt);
207
	do_git_path(pathname, fmt, args);
208
	va_end(args);
209
	return pathname->buf;
210 211 212
}

char *git_pathdup(const char *fmt, ...)
213
{
214
	struct strbuf path = STRBUF_INIT;
215 216
	va_list args;
	va_start(args, fmt);
217
	do_git_path(&path, fmt, args);
218
	va_end(args);
219
	return strbuf_detach(&path, NULL);
220 221 222
}

char *mkpathdup(const char *fmt, ...)
223
{
224
	struct strbuf sb = STRBUF_INIT;
225 226
	va_list args;
	va_start(args, fmt);
227
	strbuf_vaddf(&sb, fmt, args);
228
	va_end(args);
229 230
	strbuf_cleanup_path(&sb);
	return strbuf_detach(&sb, NULL);
231 232
}

233
const char *mkpath(const char *fmt, ...)
234 235
{
	va_list args;
236
	struct strbuf *pathname = get_pathname();
237
	va_start(args, fmt);
238
	strbuf_vaddf(pathname, fmt, args);
239
	va_end(args);
240
	return cleanup_path(pathname->buf);
241
}
242

243 244
static void do_submodule_path(struct strbuf *buf, const char *path,
			      const char *fmt, va_list args)
245 246 247
{
	const char *git_dir;

248 249 250 251
	strbuf_addstr(buf, path);
	if (buf->len && buf->buf[buf->len - 1] != '/')
		strbuf_addch(buf, '/');
	strbuf_addstr(buf, ".git");
252

253
	git_dir = read_gitfile(buf->buf);
254
	if (git_dir) {
255 256
		strbuf_reset(buf);
		strbuf_addstr(buf, git_dir);
257
	}
258
	strbuf_addch(buf, '/');
259

260 261
	strbuf_vaddf(buf, fmt, args);
	strbuf_cleanup_path(buf);
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
}

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);
}

283
int validate_headref(const char *path)
284 285 286
{
	struct stat st;
	char *buf, buffer[256];
287
	unsigned char sha1[20];
288 289
	int fd;
	ssize_t len;
290 291 292 293 294 295 296

	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);
297
		if (len >= 5 && !memcmp("refs/", buffer, 5))
298 299 300 301 302 303 304 305 306 307
			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;
308
	len = read_in_full(fd, buffer, sizeof(buffer)-1);
309 310 311 312 313
	close(fd);

	/*
	 * Is it a symbolic ref?
	 */
314
	if (len < 4)
315
		return -1;
316 317 318 319 320
	if (!memcmp("ref:", buffer, 4)) {
		buf = buffer + 4;
		len -= 4;
		while (len && isspace(*buf))
			buf++, len--;
321
		if (len >= 5 && !memcmp("refs/", buf, 5))
322 323 324 325 326 327 328
			return 0;
	}

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

331 332 333
	return -1;
}

334
static struct passwd *getpw_str(const char *username, size_t len)
335
{
336
	struct passwd *pw;
337
	char *username_z = xmemdupz(username, len);
338 339 340 341
	pw = getpwnam(username_z);
	free(username_z);
	return pw;
}
342

343 344 345 346 347 348 349 350 351 352 353 354 355
/*
 * 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] == '~') {
356
		const char *first_slash = strchrnul(path, '/');
357 358
		const char *username = path + 1;
		size_t username_len = first_slash - username;
359 360
		if (username_len == 0) {
			const char *home = getenv("HOME");
361 362
			if (!home)
				goto return_null;
363
			strbuf_addstr(&user_path, home);
364 365 366 367
		} else {
			struct passwd *pw = getpw_str(username, username_len);
			if (!pw)
				goto return_null;
368
			strbuf_addstr(&user_path, pw->pw_dir);
369
		}
370
		to_copy = first_slash;
371
	}
372
	strbuf_addstr(&user_path, to_copy);
373 374 375 376
	return strbuf_detach(&user_path, NULL);
return_null:
	strbuf_release(&user_path);
	return NULL;
377 378
}

379 380 381 382 383 384 385 386 387 388
/*
 * 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.
 *
389 390 391
 * 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.
392 393 394 395 396 397
 *
 * 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.
 */
398
const char *enter_repo(const char *path, int strict)
399
{
400 401 402 403
	static char used_path[PATH_MAX];
	static char validated_path[PATH_MAX];

	if (!path)
404 405
		return NULL;

406 407
	if (!strict) {
		static const char *suffix[] = {
408
			"/.git", "", ".git/.git", ".git", NULL,
409
		};
410
		const char *gitfile;
411 412
		int len = strlen(path);
		int i;
413
		while ((1 < len) && (path[len-1] == '/'))
414
			len--;
415

416
		if (PATH_MAX <= len)
417
			return NULL;
418 419 420 421 422
		strncpy(used_path, path, len); used_path[len] = 0 ;
		strcpy(validated_path, used_path);

		if (used_path[0] == '~') {
			char *newpath = expand_user_path(used_path);
423 424
			if (!newpath || (PATH_MAX - 10 < strlen(newpath))) {
				free(newpath);
425
				return NULL;
426 427 428 429 430 431 432 433
			}
			/*
			 * Copy back into the static buffer. A pity
			 * since newpath was not bounded, but other
			 * branches of the if are limited by PATH_MAX
			 * anyway.
			 */
			strcpy(used_path, newpath); free(newpath);
434 435 436
		}
		else if (PATH_MAX - 10 < len)
			return NULL;
437
		len = strlen(used_path);
438
		for (i = 0; suffix[i]; i++) {
439
			struct stat st;
440
			strcpy(used_path + len, suffix[i]);
441 442 443
			if (!stat(used_path, &st) &&
			    (S_ISREG(st.st_mode) ||
			    (S_ISDIR(st.st_mode) && is_git_directory(used_path)))) {
444 445 446 447
				strcat(validated_path, suffix[i]);
				break;
			}
		}
448 449 450 451 452 453
		if (!suffix[i])
			return NULL;
		gitfile = read_gitfile(used_path) ;
		if (gitfile)
			strcpy(used_path, gitfile);
		if (chdir(used_path))
454
			return NULL;
455
		path = validated_path;
456
	}
457 458
	else if (chdir(path))
		return NULL;
459

460
	if (access("objects", X_OK) == 0 && access("refs", X_OK) == 0 &&
461
	    validate_headref("HEAD") == 0) {
René Scharfe's avatar
René Scharfe committed
462
		set_git_dir(".");
463
		check_repository_format();
464
		return path;
465 466 467 468
	}

	return NULL;
}
469

470
static int calc_shared_perm(int mode)
471
{
472
	int tweak;
473

474
	if (shared_repository < 0)
475
		tweak = -shared_repository;
476
	else
477
		tweak = shared_repository;
478 479 480 481 482 483 484 485 486

	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
487
		mode |= tweak;
488

489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
	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)) {
504
		/* Copy read bits to execute bits */
505 506
		new_mode |= (new_mode & 0444) >> 2;
		new_mode |= FORCE_DIR_SET_GID;
507 508
	}

509 510
	if (((old_mode ^ new_mode) & ~S_IFMT) &&
			chmod(path, (new_mode & ~S_IFMT)) < 0)
511 512 513
		return -2;
	return 0;
}
514

515 516 517 518 519 520 521 522 523 524
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);
}

525 526 527 528 529 530 531 532
/*
 * 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)
533
{
534 535 536 537
	int in_len = in ? strlen(in) : 0;
	int prefix_len = prefix ? strlen(prefix) : 0;
	int in_off = 0;
	int prefix_off = 0;
538 539
	int i = 0, j = 0;

540 541 542 543 544
	if (!in_len)
		return "./";
	else if (!prefix_len)
		return in;

545 546 547 548 549 550 551 552 553 554
	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;
	}

555 556 557
	while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
		if (is_dir_sep(prefix[i])) {
			while (is_dir_sep(prefix[i]))
558
				i++;
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
			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]))
583
				j++;
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 614 615 616 617 618
			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++;
619 620 621 622
			continue;
		}
		i++;
	}
623 624 625 626 627 628
	if (!is_dir_sep(prefix[prefix_len - 1]))
		strbuf_addstr(sb, "../");

	strbuf_addstr(sb, in);

	return sb->buf;
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 671 672 673 674 675
/*
 * 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;
}

676
/*
677
 * It is okay if dst == src, but they should not overlap otherwise.
678
 *
679 680 681
 * Performs the following normalizations on src, storing the result in dst:
 * - Ensures that components are separated by '/' (Windows only)
 * - Squashes sequences of '/'.
682 683
 * - Removes "." components.
 * - Removes ".." components, and the components the precede them.
684 685
 * Returns failure (non-zero) if a ".." component appears as first path
 * component anytime during the normalization. Otherwise, returns success (0).
686 687 688
 *
 * Note that this function is purely textual.  It does not follow symlinks,
 * verify the existence of the path, or make any system calls.
689 690 691 692 693 694
 *
 * 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.
695
 */
696
int normalize_path_copy_len(char *dst, const char *src, int *prefix_len)
697
{
698
	char *dst0;
699

700 701 702
	if (has_dos_drive_prefix(src)) {
		*dst++ = *src++;
		*dst++ = *src++;
703
	}
704
	dst0 = dst;
705

706
	if (is_dir_sep(*src)) {
707
		*dst++ = '/';
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 742 743 744 745 746
		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;
				}
			}
		}
747

748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
		/* 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.
		 */
765 766
		dst--;	/* go to trailing '/' */
		if (dst <= dst0)
767
			return -1;
768 769 770
		/* Windows: dst[-1] cannot be backslash anymore */
		while (dst0 < dst && dst[-1] != '/')
			dst--;
771 772
		if (prefix_len && *prefix_len > dst - dst0)
			*prefix_len = dst - dst0;
773
	}
774
	*dst = '\0';
775
	return 0;
776
}
777

778 779 780 781 782
int normalize_path_copy(char *dst, const char *src)
{
	return normalize_path_copy_len(dst, src, NULL);
}

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

801
	if (!strcmp(path, "/"))
802 803
		return -1;

804 805
	for (i = 0; i < prefixes->nr; i++) {
		const char *ceil = prefixes->items[i].string;
806 807
		int len = strlen(ceil);

808 809 810 811 812 813
		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 */
814

815
		if (len > max_len)
816 817 818 819 820
			max_len = len;
	}

	return max_len;
}
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 852 853 854 855 856

/* 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));
}
857 858 859 860 861 862 863 864

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()
865
	 * does not do getcwd() based path canonicalization.
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 899 900 901 902 903
	 *
	 * 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;
		}
	}
}
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 932 933 934 935 936
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;
		}
}
937 938 939 940 941 942 943 944 945 946 947 948 949 950 951

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;
}
952 953 954 955 956 957 958 959 960 961

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")