1#include"cache.h" 2#include"dir.h" 3#include"string-list.h" 4 5static int inside_git_dir = -1; 6static int inside_work_tree = -1; 7static int work_tree_config_is_bogus; 8 9/* 10 * The input parameter must contain an absolute path, and it must already be 11 * normalized. 12 * 13 * Find the part of an absolute path that lies inside the work tree by 14 * dereferencing symlinks outside the work tree, for example: 15 * /dir1/repo/dir2/file (work tree is /dir1/repo) -> dir2/file 16 * /dir/file (work tree is /) -> dir/file 17 * /dir/symlink1/symlink2 (symlink1 points to work tree) -> symlink2 18 * /dir/repolink/file (repolink points to /dir/repo) -> file 19 * /dir/repo (exactly equal to work tree) -> (empty string) 20 */ 21static intabspath_part_inside_repo(char*path) 22{ 23size_t len; 24size_t wtlen; 25char*path0; 26int off; 27const char*work_tree =get_git_work_tree(); 28 29if(!work_tree) 30return-1; 31 wtlen =strlen(work_tree); 32 len =strlen(path); 33 off =offset_1st_component(path); 34 35/* check if work tree is already the prefix */ 36if(wtlen <= len && !strncmp(path, work_tree, wtlen)) { 37if(path[wtlen] =='/') { 38memmove(path, path + wtlen +1, len - wtlen); 39return0; 40}else if(path[wtlen -1] =='/'|| path[wtlen] =='\0') { 41/* work tree is the root, or the whole path */ 42memmove(path, path + wtlen, len - wtlen +1); 43return0; 44} 45/* work tree might match beginning of a symlink to work tree */ 46 off = wtlen; 47} 48 path0 = path; 49 path += off; 50 51/* check each '/'-terminated level */ 52while(*path) { 53 path++; 54if(*path =='/') { 55*path ='\0'; 56if(strcmp(real_path(path0), work_tree) ==0) { 57memmove(path0, path +1, len - (path - path0)); 58return0; 59} 60*path ='/'; 61} 62} 63 64/* check whole path */ 65if(strcmp(real_path(path0), work_tree) ==0) { 66*path0 ='\0'; 67return0; 68} 69 70return-1; 71} 72 73/* 74 * Normalize "path", prepending the "prefix" for relative paths. If 75 * remaining_prefix is not NULL, return the actual prefix still 76 * remains in the path. For example, prefix = sub1/sub2/ and path is 77 * 78 * foo -> sub1/sub2/foo (full prefix) 79 * ../foo -> sub1/foo (remaining prefix is sub1/) 80 * ../../bar -> bar (no remaining prefix) 81 * ../../sub1/sub2/foo -> sub1/sub2/foo (but no remaining prefix) 82 * `pwd`/../bar -> sub1/bar (no remaining prefix) 83 */ 84char*prefix_path_gently(const char*prefix,int len, 85int*remaining_prefix,const char*path) 86{ 87const char*orig = path; 88char*sanitized; 89if(is_absolute_path(orig)) { 90 sanitized =xmalloc(strlen(path) +1); 91if(remaining_prefix) 92*remaining_prefix =0; 93if(normalize_path_copy_len(sanitized, path, remaining_prefix)) { 94free(sanitized); 95return NULL; 96} 97if(abspath_part_inside_repo(sanitized)) { 98free(sanitized); 99return NULL; 100} 101}else{ 102 sanitized =xmalloc(len +strlen(path) +1); 103if(len) 104memcpy(sanitized, prefix, len); 105strcpy(sanitized + len, path); 106if(remaining_prefix) 107*remaining_prefix = len; 108if(normalize_path_copy_len(sanitized, sanitized, remaining_prefix)) { 109free(sanitized); 110return NULL; 111} 112} 113return sanitized; 114} 115 116char*prefix_path(const char*prefix,int len,const char*path) 117{ 118char*r =prefix_path_gently(prefix, len, NULL, path); 119if(!r) 120die("'%s' is outside repository", path); 121return r; 122} 123 124intpath_inside_repo(const char*prefix,const char*path) 125{ 126int len = prefix ?strlen(prefix) :0; 127char*r =prefix_path_gently(prefix, len, NULL, path); 128if(r) { 129free(r); 130return1; 131} 132return0; 133} 134 135intcheck_filename(const char*prefix,const char*arg) 136{ 137const char*name; 138struct stat st; 139 140if(starts_with(arg,":/")) { 141if(arg[2] =='\0')/* ":/" is root dir, always exists */ 142return1; 143 name = arg +2; 144}else if(prefix) 145 name =prefix_filename(prefix,strlen(prefix), arg); 146else 147 name = arg; 148if(!lstat(name, &st)) 149return1;/* file exists */ 150if(errno == ENOENT || errno == ENOTDIR) 151return0;/* file does not exist */ 152die_errno("failed to stat '%s'", arg); 153} 154 155static void NORETURN die_verify_filename(const char*prefix, 156const char*arg, 157int diagnose_misspelt_rev) 158{ 159if(!diagnose_misspelt_rev) 160die("%s: no such path in the working tree.\n" 161"Use 'git <command> -- <path>...' to specify paths that do not exist locally.", 162 arg); 163/* 164 * Saying "'(icase)foo' does not exist in the index" when the 165 * user gave us ":(icase)foo" is just stupid. A magic pathspec 166 * begins with a colon and is followed by a non-alnum; do not 167 * let maybe_die_on_misspelt_object_name() even trigger. 168 */ 169if(!(arg[0] ==':'&& !isalnum(arg[1]))) 170maybe_die_on_misspelt_object_name(arg, prefix); 171 172/* ... or fall back the most general message. */ 173die("ambiguous argument '%s': unknown revision or path not in the working tree.\n" 174"Use '--' to separate paths from revisions, like this:\n" 175"'git <command> [<revision>...] -- [<file>...]'", arg); 176 177} 178 179/* 180 * Verify a filename that we got as an argument for a pathspec 181 * entry. Note that a filename that begins with "-" never verifies 182 * as true, because even if such a filename were to exist, we want 183 * it to be preceded by the "--" marker (or we want the user to 184 * use a format like "./-filename") 185 * 186 * The "diagnose_misspelt_rev" is used to provide a user-friendly 187 * diagnosis when dying upon finding that "name" is not a pathname. 188 * If set to 1, the diagnosis will try to diagnose "name" as an 189 * invalid object name (e.g. HEAD:foo). If set to 0, the diagnosis 190 * will only complain about an inexisting file. 191 * 192 * This function is typically called to check that a "file or rev" 193 * argument is unambiguous. In this case, the caller will want 194 * diagnose_misspelt_rev == 1 when verifying the first non-rev 195 * argument (which could have been a revision), and 196 * diagnose_misspelt_rev == 0 for the next ones (because we already 197 * saw a filename, there's not ambiguity anymore). 198 */ 199voidverify_filename(const char*prefix, 200const char*arg, 201int diagnose_misspelt_rev) 202{ 203if(*arg =='-') 204die("bad flag '%s' used after filename", arg); 205if(check_filename(prefix, arg)) 206return; 207die_verify_filename(prefix, arg, diagnose_misspelt_rev); 208} 209 210/* 211 * Opposite of the above: the command line did not have -- marker 212 * and we parsed the arg as a refname. It should not be interpretable 213 * as a filename. 214 */ 215voidverify_non_filename(const char*prefix,const char*arg) 216{ 217if(!is_inside_work_tree() ||is_inside_git_dir()) 218return; 219if(*arg =='-') 220return;/* flag */ 221if(!check_filename(prefix, arg)) 222return; 223die("ambiguous argument '%s': both revision and filename\n" 224"Use '--' to separate paths from revisions, like this:\n" 225"'git <command> [<revision>...] -- [<file>...]'", arg); 226} 227 228 229/* 230 * Test if it looks like we're at a git directory. 231 * We want to see: 232 * 233 * - either an objects/ directory _or_ the proper 234 * GIT_OBJECT_DIRECTORY environment variable 235 * - a refs/ directory 236 * - either a HEAD symlink or a HEAD file that is formatted as 237 * a proper "ref:", or a regular file HEAD that has a properly 238 * formatted sha1 object name. 239 */ 240intis_git_directory(const char*suspect) 241{ 242char path[PATH_MAX]; 243size_t len =strlen(suspect); 244 245if(PATH_MAX <= len +strlen("/objects")) 246die("Too long path: %.*s",60, suspect); 247strcpy(path, suspect); 248if(getenv(DB_ENVIRONMENT)) { 249if(access(getenv(DB_ENVIRONMENT), X_OK)) 250return0; 251} 252else{ 253strcpy(path + len,"/objects"); 254if(access(path, X_OK)) 255return0; 256} 257 258strcpy(path + len,"/refs"); 259if(access(path, X_OK)) 260return0; 261 262strcpy(path + len,"/HEAD"); 263if(validate_headref(path)) 264return0; 265 266return1; 267} 268 269intis_inside_git_dir(void) 270{ 271if(inside_git_dir <0) 272 inside_git_dir =is_inside_dir(get_git_dir()); 273return inside_git_dir; 274} 275 276intis_inside_work_tree(void) 277{ 278if(inside_work_tree <0) 279 inside_work_tree =is_inside_dir(get_git_work_tree()); 280return inside_work_tree; 281} 282 283voidsetup_work_tree(void) 284{ 285const char*work_tree, *git_dir; 286static int initialized =0; 287 288if(initialized) 289return; 290 291if(work_tree_config_is_bogus) 292die("unable to set up work tree using invalid config"); 293 294 work_tree =get_git_work_tree(); 295 git_dir =get_git_dir(); 296if(!is_absolute_path(git_dir)) 297 git_dir =real_path(get_git_dir()); 298if(!work_tree ||chdir(work_tree)) 299die("This operation must be run in a work tree"); 300 301/* 302 * Make sure subsequent git processes find correct worktree 303 * if $GIT_WORK_TREE is set relative 304 */ 305if(getenv(GIT_WORK_TREE_ENVIRONMENT)) 306setenv(GIT_WORK_TREE_ENVIRONMENT,".",1); 307 308set_git_dir(remove_leading_path(git_dir, work_tree)); 309 initialized =1; 310} 311 312static intcheck_repository_format_gently(const char*gitdir,int*nongit_ok) 313{ 314char repo_config[PATH_MAX+1]; 315 316/* 317 * git_config() can't be used here because it calls git_pathdup() 318 * to get $GIT_CONFIG/config. That call will make setup_git_env() 319 * set git_dir to ".git". 320 * 321 * We are in gitdir setup, no git dir has been found useable yet. 322 * Use a gentler version of git_config() to check if this repo 323 * is a good one. 324 */ 325snprintf(repo_config, PATH_MAX,"%s/config", gitdir); 326git_config_early(check_repository_format_version, NULL, repo_config); 327if(GIT_REPO_VERSION < repository_format_version) { 328if(!nongit_ok) 329die("Expected git repo version <=%d, found%d", 330 GIT_REPO_VERSION, repository_format_version); 331warning("Expected git repo version <=%d, found%d", 332 GIT_REPO_VERSION, repository_format_version); 333warning("Please upgrade Git"); 334*nongit_ok = -1; 335return-1; 336} 337return0; 338} 339 340/* 341 * Try to read the location of the git directory from the .git file, 342 * return path to git directory if found. 343 */ 344const char*read_gitfile(const char*path) 345{ 346char*buf; 347char*dir; 348const char*slash; 349struct stat st; 350int fd; 351 ssize_t len; 352 353if(stat(path, &st)) 354return NULL; 355if(!S_ISREG(st.st_mode)) 356return NULL; 357 fd =open(path, O_RDONLY); 358if(fd <0) 359die_errno("Error opening '%s'", path); 360 buf =xmalloc(st.st_size +1); 361 len =read_in_full(fd, buf, st.st_size); 362close(fd); 363if(len != st.st_size) 364die("Error reading%s", path); 365 buf[len] ='\0'; 366if(!starts_with(buf,"gitdir: ")) 367die("Invalid gitfile format:%s", path); 368while(buf[len -1] =='\n'|| buf[len -1] =='\r') 369 len--; 370if(len <9) 371die("No path in gitfile:%s", path); 372 buf[len] ='\0'; 373 dir = buf +8; 374 375if(!is_absolute_path(dir) && (slash =strrchr(path,'/'))) { 376size_t pathlen = slash+1- path; 377size_t dirlen = pathlen + len -8; 378 dir =xmalloc(dirlen +1); 379strncpy(dir, path, pathlen); 380strncpy(dir + pathlen, buf +8, len -8); 381 dir[dirlen] ='\0'; 382free(buf); 383 buf = dir; 384} 385 386if(!is_git_directory(dir)) 387die("Not a git repository:%s", dir); 388 path =real_path(dir); 389 390free(buf); 391return path; 392} 393 394static const char*setup_explicit_git_dir(const char*gitdirenv, 395struct strbuf *cwd, 396int*nongit_ok) 397{ 398const char*work_tree_env =getenv(GIT_WORK_TREE_ENVIRONMENT); 399const char*worktree; 400char*gitfile; 401int offset; 402 403if(PATH_MAX -40<strlen(gitdirenv)) 404die("'$%s' too big", GIT_DIR_ENVIRONMENT); 405 406 gitfile = (char*)read_gitfile(gitdirenv); 407if(gitfile) { 408 gitfile =xstrdup(gitfile); 409 gitdirenv = gitfile; 410} 411 412if(!is_git_directory(gitdirenv)) { 413if(nongit_ok) { 414*nongit_ok =1; 415free(gitfile); 416return NULL; 417} 418die("Not a git repository: '%s'", gitdirenv); 419} 420 421if(check_repository_format_gently(gitdirenv, nongit_ok)) { 422free(gitfile); 423return NULL; 424} 425 426/* #3, #7, #11, #15, #19, #23, #27, #31 (see t1510) */ 427if(work_tree_env) 428set_git_work_tree(work_tree_env); 429else if(is_bare_repository_cfg >0) { 430if(git_work_tree_cfg) { 431/* #22.2, #30 */ 432warning("core.bare and core.worktree do not make sense"); 433 work_tree_config_is_bogus =1; 434} 435 436/* #18, #26 */ 437set_git_dir(gitdirenv); 438free(gitfile); 439return NULL; 440} 441else if(git_work_tree_cfg) {/* #6, #14 */ 442if(is_absolute_path(git_work_tree_cfg)) 443set_git_work_tree(git_work_tree_cfg); 444else{ 445char*core_worktree; 446if(chdir(gitdirenv)) 447die_errno("Could not chdir to '%s'", gitdirenv); 448if(chdir(git_work_tree_cfg)) 449die_errno("Could not chdir to '%s'", git_work_tree_cfg); 450 core_worktree =xgetcwd(); 451if(chdir(cwd->buf)) 452die_errno("Could not come back to cwd"); 453set_git_work_tree(core_worktree); 454free(core_worktree); 455} 456} 457else if(!git_env_bool(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,1)) { 458/* #16d */ 459set_git_dir(gitdirenv); 460free(gitfile); 461return NULL; 462} 463else/* #2, #10 */ 464set_git_work_tree("."); 465 466/* set_git_work_tree() must have been called by now */ 467 worktree =get_git_work_tree(); 468 469/* both get_git_work_tree() and cwd are already normalized */ 470if(!strcmp(cwd->buf, worktree)) {/* cwd == worktree */ 471set_git_dir(gitdirenv); 472free(gitfile); 473return NULL; 474} 475 476 offset =dir_inside_of(cwd->buf, worktree); 477if(offset >=0) {/* cwd inside worktree? */ 478set_git_dir(real_path(gitdirenv)); 479if(chdir(worktree)) 480die_errno("Could not chdir to '%s'", worktree); 481strbuf_addch(cwd,'/'); 482free(gitfile); 483return cwd->buf + offset; 484} 485 486/* cwd outside worktree */ 487set_git_dir(gitdirenv); 488free(gitfile); 489return NULL; 490} 491 492static const char*setup_discovered_git_dir(const char*gitdir, 493struct strbuf *cwd,int offset, 494int*nongit_ok) 495{ 496if(check_repository_format_gently(gitdir, nongit_ok)) 497return NULL; 498 499/* --work-tree is set without --git-dir; use discovered one */ 500if(getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) { 501if(offset != cwd->len && !is_absolute_path(gitdir)) 502 gitdir =xstrdup(real_path(gitdir)); 503if(chdir(cwd->buf)) 504die_errno("Could not come back to cwd"); 505returnsetup_explicit_git_dir(gitdir, cwd, nongit_ok); 506} 507 508/* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */ 509if(is_bare_repository_cfg >0) { 510set_git_dir(offset == cwd->len ? gitdir :real_path(gitdir)); 511if(chdir(cwd->buf)) 512die_errno("Could not come back to cwd"); 513return NULL; 514} 515 516/* #0, #1, #5, #8, #9, #12, #13 */ 517set_git_work_tree("."); 518if(strcmp(gitdir, DEFAULT_GIT_DIR_ENVIRONMENT)) 519set_git_dir(gitdir); 520 inside_git_dir =0; 521 inside_work_tree =1; 522if(offset == cwd->len) 523return NULL; 524 525/* Make "offset" point to past the '/', and add a '/' at the end */ 526 offset++; 527strbuf_addch(cwd,'/'); 528return cwd->buf + offset; 529} 530 531/* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */ 532static const char*setup_bare_git_dir(struct strbuf *cwd,int offset, 533int*nongit_ok) 534{ 535int root_len; 536 537if(check_repository_format_gently(".", nongit_ok)) 538return NULL; 539 540setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,"0",1); 541 542/* --work-tree is set without --git-dir; use discovered one */ 543if(getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) { 544const char*gitdir; 545 546 gitdir = offset == cwd->len ?".":xmemdupz(cwd->buf, offset); 547if(chdir(cwd->buf)) 548die_errno("Could not come back to cwd"); 549returnsetup_explicit_git_dir(gitdir, cwd, nongit_ok); 550} 551 552 inside_git_dir =1; 553 inside_work_tree =0; 554if(offset != cwd->len) { 555if(chdir(cwd->buf)) 556die_errno("Cannot come back to cwd"); 557 root_len =offset_1st_component(cwd->buf); 558strbuf_setlen(cwd, offset > root_len ? offset : root_len); 559set_git_dir(cwd->buf); 560} 561else 562set_git_dir("."); 563return NULL; 564} 565 566static const char*setup_nongit(const char*cwd,int*nongit_ok) 567{ 568if(!nongit_ok) 569die("Not a git repository (or any of the parent directories):%s", DEFAULT_GIT_DIR_ENVIRONMENT); 570if(chdir(cwd)) 571die_errno("Cannot come back to cwd"); 572*nongit_ok =1; 573return NULL; 574} 575 576static dev_t get_device_or_die(const char*path,const char*prefix,int prefix_len) 577{ 578struct stat buf; 579if(stat(path, &buf)) { 580die_errno("failed to stat '%*s%s%s'", 581 prefix_len, 582 prefix ? prefix :"", 583 prefix ?"/":"", path); 584} 585return buf.st_dev; 586} 587 588/* 589 * A "string_list_each_func_t" function that canonicalizes an entry 590 * from GIT_CEILING_DIRECTORIES using real_path_if_valid(), or 591 * discards it if unusable. The presence of an empty entry in 592 * GIT_CEILING_DIRECTORIES turns off canonicalization for all 593 * subsequent entries. 594 */ 595static intcanonicalize_ceiling_entry(struct string_list_item *item, 596void*cb_data) 597{ 598int*empty_entry_found = cb_data; 599char*ceil = item->string; 600 601if(!*ceil) { 602*empty_entry_found =1; 603return0; 604}else if(!is_absolute_path(ceil)) { 605return0; 606}else if(*empty_entry_found) { 607/* Keep entry but do not canonicalize it */ 608return1; 609}else{ 610const char*real_path =real_path_if_valid(ceil); 611if(!real_path) 612return0; 613free(item->string); 614 item->string =xstrdup(real_path); 615return1; 616} 617} 618 619/* 620 * We cannot decide in this function whether we are in the work tree or 621 * not, since the config can only be read _after_ this function was called. 622 */ 623static const char*setup_git_directory_gently_1(int*nongit_ok) 624{ 625const char*env_ceiling_dirs =getenv(CEILING_DIRECTORIES_ENVIRONMENT); 626struct string_list ceiling_dirs = STRING_LIST_INIT_DUP; 627static struct strbuf cwd = STRBUF_INIT; 628const char*gitdirenv, *ret; 629char*gitfile; 630int offset, offset_parent, ceil_offset = -1; 631 dev_t current_device =0; 632int one_filesystem =1; 633 634/* 635 * We may have read an incomplete configuration before 636 * setting-up the git directory. If so, clear the cache so 637 * that the next queries to the configuration reload complete 638 * configuration (including the per-repo config file that we 639 * ignored previously). 640 */ 641git_config_clear(); 642 643/* 644 * Let's assume that we are in a git repository. 645 * If it turns out later that we are somewhere else, the value will be 646 * updated accordingly. 647 */ 648if(nongit_ok) 649*nongit_ok =0; 650 651if(strbuf_getcwd(&cwd)) 652die_errno("Unable to read current working directory"); 653 offset = cwd.len; 654 655/* 656 * If GIT_DIR is set explicitly, we're not going 657 * to do any discovery, but we still do repository 658 * validation. 659 */ 660 gitdirenv =getenv(GIT_DIR_ENVIRONMENT); 661if(gitdirenv) 662returnsetup_explicit_git_dir(gitdirenv, &cwd, nongit_ok); 663 664if(env_ceiling_dirs) { 665int empty_entry_found =0; 666 667string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1); 668filter_string_list(&ceiling_dirs,0, 669 canonicalize_ceiling_entry, &empty_entry_found); 670 ceil_offset =longest_ancestor_length(cwd.buf, &ceiling_dirs); 671string_list_clear(&ceiling_dirs,0); 672} 673 674if(ceil_offset <0&&has_dos_drive_prefix(cwd.buf)) 675 ceil_offset =1; 676 677/* 678 * Test in the following order (relative to the cwd): 679 * - .git (file containing "gitdir: <path>") 680 * - .git/ 681 * - ./ (bare) 682 * - ../.git 683 * - ../.git/ 684 * - ../ (bare) 685 * - ../../.git/ 686 * etc. 687 */ 688 one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM",0); 689if(one_filesystem) 690 current_device =get_device_or_die(".", NULL,0); 691for(;;) { 692 gitfile = (char*)read_gitfile(DEFAULT_GIT_DIR_ENVIRONMENT); 693if(gitfile) 694 gitdirenv = gitfile =xstrdup(gitfile); 695else{ 696if(is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT)) 697 gitdirenv = DEFAULT_GIT_DIR_ENVIRONMENT; 698} 699 700if(gitdirenv) { 701 ret =setup_discovered_git_dir(gitdirenv, 702&cwd, offset, 703 nongit_ok); 704free(gitfile); 705return ret; 706} 707free(gitfile); 708 709if(is_git_directory(".")) 710returnsetup_bare_git_dir(&cwd, offset, nongit_ok); 711 712 offset_parent = offset; 713while(--offset_parent > ceil_offset && cwd.buf[offset_parent] !='/'); 714if(offset_parent <= ceil_offset) 715returnsetup_nongit(cwd.buf, nongit_ok); 716if(one_filesystem) { 717 dev_t parent_device =get_device_or_die("..", cwd.buf, 718 offset); 719if(parent_device != current_device) { 720if(nongit_ok) { 721if(chdir(cwd.buf)) 722die_errno("Cannot come back to cwd"); 723*nongit_ok =1; 724return NULL; 725} 726strbuf_setlen(&cwd, offset); 727die("Not a git repository (or any parent up to mount point%s)\n" 728"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).", 729 cwd.buf); 730} 731} 732if(chdir("..")) { 733strbuf_setlen(&cwd, offset); 734die_errno("Cannot change to '%s/..'", cwd.buf); 735} 736 offset = offset_parent; 737} 738} 739 740const char*setup_git_directory_gently(int*nongit_ok) 741{ 742const char*prefix; 743 744 prefix =setup_git_directory_gently_1(nongit_ok); 745if(prefix) 746setenv(GIT_PREFIX_ENVIRONMENT, prefix,1); 747else 748setenv(GIT_PREFIX_ENVIRONMENT,"",1); 749 750if(startup_info) { 751 startup_info->have_repository = !nongit_ok || !*nongit_ok; 752 startup_info->prefix = prefix; 753} 754return prefix; 755} 756 757intgit_config_perm(const char*var,const char*value) 758{ 759int i; 760char*endptr; 761 762if(value == NULL) 763return PERM_GROUP; 764 765if(!strcmp(value,"umask")) 766return PERM_UMASK; 767if(!strcmp(value,"group")) 768return PERM_GROUP; 769if(!strcmp(value,"all") || 770!strcmp(value,"world") || 771!strcmp(value,"everybody")) 772return PERM_EVERYBODY; 773 774/* Parse octal numbers */ 775 i =strtol(value, &endptr,8); 776 777/* If not an octal number, maybe true/false? */ 778if(*endptr !=0) 779returngit_config_bool(var, value) ? PERM_GROUP : PERM_UMASK; 780 781/* 782 * Treat values 0, 1 and 2 as compatibility cases, otherwise it is 783 * a chmod value to restrict to. 784 */ 785switch(i) { 786case PERM_UMASK:/* 0 */ 787return PERM_UMASK; 788case OLD_PERM_GROUP:/* 1 */ 789return PERM_GROUP; 790case OLD_PERM_EVERYBODY:/* 2 */ 791return PERM_EVERYBODY; 792} 793 794/* A filemode value was given: 0xxx */ 795 796if((i &0600) !=0600) 797die("Problem with core.sharedRepository filemode value " 798"(0%.3o).\nThe owner of files must always have " 799"read and write permissions.", i); 800 801/* 802 * Mask filemode value. Others can not get write permission. 803 * x flags for directories are handled separately. 804 */ 805return-(i &0666); 806} 807 808intcheck_repository_format_version(const char*var,const char*value,void*cb) 809{ 810if(strcmp(var,"core.repositoryformatversion") ==0) 811 repository_format_version =git_config_int(var, value); 812else if(strcmp(var,"core.sharedrepository") ==0) 813 shared_repository =git_config_perm(var, value); 814else if(strcmp(var,"core.bare") ==0) { 815 is_bare_repository_cfg =git_config_bool(var, value); 816if(is_bare_repository_cfg ==1) 817 inside_work_tree = -1; 818}else if(strcmp(var,"core.worktree") ==0) { 819if(!value) 820returnconfig_error_nonbool(var); 821free(git_work_tree_cfg); 822 git_work_tree_cfg =xstrdup(value); 823 inside_work_tree = -1; 824} 825return0; 826} 827 828intcheck_repository_format(void) 829{ 830returncheck_repository_format_gently(get_git_dir(), NULL); 831} 832 833/* 834 * Returns the "prefix", a path to the current working directory 835 * relative to the work tree root, or NULL, if the current working 836 * directory is not a strict subdirectory of the work tree root. The 837 * prefix always ends with a '/' character. 838 */ 839const char*setup_git_directory(void) 840{ 841returnsetup_git_directory_gently(NULL); 842} 843 844const char*resolve_gitdir(const char*suspect) 845{ 846if(is_git_directory(suspect)) 847return suspect; 848returnread_gitfile(suspect); 849} 850 851/* if any standard file descriptor is missing open it to /dev/null */ 852voidsanitize_stdfds(void) 853{ 854int fd =open("/dev/null", O_RDWR,0); 855while(fd != -1&& fd <2) 856 fd =dup(fd); 857if(fd == -1) 858die_errno("open /dev/null or dup failed"); 859if(fd >2) 860close(fd); 861} 862 863intdaemonize(void) 864{ 865#ifdef NO_POSIX_GOODIES 866 errno = ENOSYS; 867return-1; 868#else 869switch(fork()) { 870case0: 871break; 872case-1: 873die_errno("fork failed"); 874default: 875exit(0); 876} 877if(setsid() == -1) 878die_errno("setsid failed"); 879close(0); 880close(1); 881close(2); 882sanitize_stdfds(); 883return0; 884#endif 885}