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