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