Skip to content

Commit c25f209

Browse files
authored
Merge pull request git-for-windows#2358 from dscho/reconcile-system-config-and-programdata-config
Make `git config --system` work like you think it should on Windows
2 parents 144cb18 + d8ab53d commit c25f209

File tree

8 files changed

+17
-213
lines changed

8 files changed

+17
-213
lines changed

Documentation/config.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ the Git commands' behavior. The files `.git/config` and optionally
77
repository are used to store the configuration for that repository, and
88
`$HOME/.gitconfig` is used to store a per-user configuration as
99
fallback values for the `.git/config` file. The file `/etc/gitconfig`
10-
can be used to store a system-wide default configuration. On Windows,
11-
configuration can also be stored in `C:\ProgramData\Git\config`; This
12-
file will be used also by libgit2-based software.
10+
can be used to store a system-wide default configuration.
1311

1412
The configuration variables are used by both the Git plumbing
1513
and the porcelains. The variables are divided into sections, wherein

Documentation/git-config.txt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -272,16 +272,8 @@ FILES
272272
If not set explicitly with `--file`, there are four files where
273273
'git config' will search for configuration options:
274274

275-
$PROGRAMDATA/Git/config::
276-
(Windows-only) System-wide configuration file shared with other Git
277-
implementations. Typically `$PROGRAMDATA` points to `C:\ProgramData`.
278-
279275
$(prefix)/etc/gitconfig::
280276
System-wide configuration file.
281-
(Windows-only) This file contains only the settings which are
282-
specific for this installation of Git for Windows and which should
283-
not be shared with other Git implementations like JGit, libgit2.
284-
`--system` will select this file.
285277

286278
$XDG_CONFIG_HOME/git/config::
287279
Second user-specific configuration file. If $XDG_CONFIG_HOME is not set

Documentation/git.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -596,8 +596,7 @@ for further details.
596596

597597
`GIT_CONFIG_NOSYSTEM`::
598598
Whether to skip reading settings from the system-wide
599-
`$(prefix)/etc/gitconfig` file (and on Windows, also from the
600-
`%PROGRAMDATA%\Git\config` file). This environment variable can
599+
`$(prefix)/etc/gitconfig` file. This environment variable can
601600
be used along with `$HOME` and `$XDG_CONFIG_HOME` to create a
602601
predictable environment for a picky script, or you can set it
603602
temporarily to avoid using a buggy `/etc/gitconfig` file while

compat/mingw.c

Lines changed: 0 additions & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
#include "win32.h"
33
#include <conio.h>
44
#include <wchar.h>
5-
#include <aclapi.h>
6-
#include <sddl.h>
75
#include <winioctl.h>
86
#include "../strbuf.h"
97
#include "../run-command.h"
@@ -3299,188 +3297,6 @@ int uname(struct utsname *buf)
32993297
return 0;
33003298
}
33013299

3302-
/*
3303-
* Determines whether the SID refers to an administrator or the current user.
3304-
*
3305-
* For convenience, the `info` parameter allows avoiding multiple calls to
3306-
* `OpenProcessToken()` if this function is called more than once. The initial
3307-
* value of `*info` is expected to be `NULL`, and it needs to be released via
3308-
* `free()` after the last call to this function.
3309-
*
3310-
* Returns 0 if the SID indicates a dubious owner of system files, otherwise 1.
3311-
*/
3312-
static int is_valid_system_file_owner(PSID sid, TOKEN_USER **info)
3313-
{
3314-
HANDLE token;
3315-
DWORD len;
3316-
char builtin_administrators_sid[SECURITY_MAX_SID_SIZE];
3317-
3318-
if (IsWellKnownSid(sid, WinBuiltinAdministratorsSid) ||
3319-
IsWellKnownSid(sid, WinLocalSystemSid))
3320-
return 1;
3321-
3322-
/* Obtain current user's SID */
3323-
if (!*info &&
3324-
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
3325-
if (!GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
3326-
*info = xmalloc((size_t)len);
3327-
if (!GetTokenInformation(token, TokenUser, *info, len,
3328-
&len))
3329-
FREE_AND_NULL(*info);
3330-
}
3331-
CloseHandle(token);
3332-
}
3333-
3334-
if (*info && EqualSid(sid, (*info)->User.Sid))
3335-
return 1;
3336-
3337-
/* Is the owner at least a member of BUILTIN\Administrators? */
3338-
len = ARRAY_SIZE(builtin_administrators_sid);
3339-
if (CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL,
3340-
builtin_administrators_sid, &len)) {
3341-
wchar_t name[256], domain[256];
3342-
DWORD name_size = ARRAY_SIZE(name);
3343-
DWORD domain_size = ARRAY_SIZE(domain);
3344-
SID_NAME_USE type;
3345-
PSID *members;
3346-
DWORD dummy, i;
3347-
/*
3348-
* We avoid including the `lm.h` header and linking to
3349-
* `netapi32.dll` directly, in favor of lazy-loading that DLL
3350-
* when, and _only_ when, needed.
3351-
*/
3352-
DECLARE_PROC_ADDR(netapi32.dll, DWORD,
3353-
NetLocalGroupGetMembers, LPCWSTR,
3354-
LPCWSTR, DWORD, LPVOID, DWORD,
3355-
LPDWORD, LPDWORD, PDWORD_PTR);
3356-
DECLARE_PROC_ADDR(netapi32.dll, DWORD,
3357-
NetApiBufferFree, LPVOID);
3358-
3359-
if (LookupAccountSidW(NULL, builtin_administrators_sid,
3360-
name, &name_size, domain, &domain_size,
3361-
&type) &&
3362-
INIT_PROC_ADDR(NetLocalGroupGetMembers) &&
3363-
/*
3364-
* Technically, `NetLocalGroupGetMembers()` wants to assign
3365-
* an array of type `LOCALGROUP_MEMBERS_INFO_0`, which
3366-
* however contains only one field of type `PSID`,
3367-
* therefore we can pretend that it is an array over the
3368-
* type `PSID`.
3369-
*
3370-
* Also, we simply ignore the condition where
3371-
* `ERROR_MORE_DATA` is returned; This should not happen
3372-
* anyway, as we are passing `-1` as `prefmaxlen`
3373-
* parameter, which is equivalent to the constant
3374-
* `MAX_PREFERRED_LENGTH`.
3375-
*/
3376-
!NetLocalGroupGetMembers(NULL, name, 0, &members, -1,
3377-
&len, &dummy, NULL)) {
3378-
for (i = 0; i < len; i++)
3379-
if (EqualSid(sid, members[i]))
3380-
break;
3381-
3382-
if (INIT_PROC_ADDR(NetApiBufferFree))
3383-
NetApiBufferFree(members);
3384-
3385-
/* Did we find the `sid` in the members? */
3386-
return i < len;
3387-
}
3388-
}
3389-
3390-
return 0;
3391-
}
3392-
3393-
/*
3394-
* Verify that the file in question is owned by an administrator or system
3395-
* account, or at least by the current user.
3396-
*
3397-
* This function returns 1 if successful, 0 if the file is not owned by any of
3398-
* these, or -1 on error.
3399-
*/
3400-
static int validate_system_file_ownership(const char *path)
3401-
{
3402-
WCHAR wpath[MAX_LONG_PATH];
3403-
PSID owner_sid = NULL, problem_sid = NULL;
3404-
PSECURITY_DESCRIPTOR descriptor = NULL;
3405-
TOKEN_USER* info = NULL;
3406-
DWORD err;
3407-
int ret;
3408-
3409-
if (xutftowcs_long_path(wpath, path) < 0)
3410-
return -1;
3411-
3412-
err = GetNamedSecurityInfoW(wpath, SE_FILE_OBJECT,
3413-
OWNER_SECURITY_INFORMATION |
3414-
DACL_SECURITY_INFORMATION,
3415-
&owner_sid, NULL, NULL, NULL, &descriptor);
3416-
3417-
/* if the file does not exist, it does not have a valid owner */
3418-
if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
3419-
ret = 0;
3420-
else if (err != ERROR_SUCCESS)
3421-
ret = error(_("failed to validate '%s' (%ld)"), path, err);
3422-
else if (!IsValidSid(owner_sid))
3423-
ret = error(_("invalid owner: '%s'"), path);
3424-
else if (is_valid_system_file_owner(owner_sid, &info))
3425-
ret = 1;
3426-
else {
3427-
ret = 0;
3428-
problem_sid = owner_sid;
3429-
}
3430-
3431-
if (!ret && problem_sid) {
3432-
#define MAX_NAME_OR_DOMAIN 256
3433-
wchar_t name[MAX_NAME_OR_DOMAIN];
3434-
wchar_t domain[MAX_NAME_OR_DOMAIN];
3435-
wchar_t *p = NULL;
3436-
DWORD size = MAX_NAME_OR_DOMAIN;
3437-
SID_NAME_USE type;
3438-
char utf[3 * MAX_NAME_OR_DOMAIN + 1];
3439-
3440-
if (!LookupAccountSidW(NULL, problem_sid, name, &size,
3441-
domain, &size, &type) ||
3442-
xwcstoutf(utf, name, ARRAY_SIZE(utf)) < 0) {
3443-
if (!ConvertSidToStringSidW(problem_sid, &p))
3444-
strlcpy(utf, "(unknown)", ARRAY_SIZE(utf));
3445-
else {
3446-
if (xwcstoutf(utf, p, ARRAY_SIZE(utf)) < 0)
3447-
strlcpy(utf, "(some user)",
3448-
ARRAY_SIZE(utf));
3449-
LocalFree(p);
3450-
}
3451-
}
3452-
3453-
warning(_("'%s' has a dubious owner: '%s'.\n"
3454-
"For security reasons, it is therefore ignored.\n"
3455-
"To fix this, please transfer ownership to an "
3456-
"admininstrator."),
3457-
path, utf);
3458-
}
3459-
3460-
if (descriptor)
3461-
LocalFree(descriptor);
3462-
free(info);
3463-
3464-
return ret;
3465-
}
3466-
3467-
const char *program_data_config(void)
3468-
{
3469-
static struct strbuf path = STRBUF_INIT;
3470-
static unsigned initialized;
3471-
3472-
if (!initialized) {
3473-
const char *env = mingw_getenv("PROGRAMDATA");
3474-
if (env) {
3475-
strbuf_addf(&path, "%s/Git/config", env);
3476-
if (validate_system_file_ownership(path.buf) != 1)
3477-
strbuf_setlen(&path, 0);
3478-
}
3479-
initialized = 1;
3480-
}
3481-
return *path.buf ? path.buf : NULL;
3482-
}
3483-
34843300
/*
34853301
* Based on https://stackoverflow.com/questions/43002803
34863302
*

compat/mingw.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,8 +471,6 @@ extern int (*win32_is_mount_point)(struct strbuf *path);
471471
#define PATH_SEP ';'
472472
extern char *mingw_query_user_email(void);
473473
#define query_user_email mingw_query_user_email
474-
extern const char *program_data_config(void);
475-
#define git_program_data_config program_data_config
476474
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
477475
#define PRIuMAX "I64u"
478476
#define PRId64 "I64d"

config.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,16 +1711,11 @@ static int do_git_config_sequence(const struct config_options *opts,
17111711
repo_config = NULL;
17121712

17131713
current_parsing_scope = CONFIG_SCOPE_SYSTEM;
1714-
if (git_config_system()) {
1715-
int flags = opts->system_gently ? ACCESS_EACCES_OK : 0;
1716-
const char *program_data = git_program_data_config();
1717-
const char *etc = git_etc_gitconfig();
1718-
1719-
if (program_data && !access_or_die(program_data, R_OK, flags))
1720-
ret += git_config_from_file(fn, program_data, data);
1721-
if (!access_or_die(etc, R_OK, flags))
1722-
ret += git_config_from_file(fn, etc, data);
1723-
}
1714+
if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK,
1715+
opts->system_gently ?
1716+
ACCESS_EACCES_OK : 0))
1717+
ret += git_config_from_file(fn, git_etc_gitconfig(),
1718+
data);
17241719

17251720
current_parsing_scope = CONFIG_SCOPE_GLOBAL;
17261721
if (xdg_config && !access_or_die(xdg_config, R_OK, ACCESS_EACCES_OK))

config.mak.uname

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,11 @@ ifeq ($(uname_S),Windows)
424424
NO_POSIX_GOODIES = UnfortunatelyYes
425425
NATIVE_CRLF = YesPlease
426426
DEFAULT_HELP_FORMAT = html
427+
ifeq (/mingw64,$(subst 32,64,$(prefix)))
428+
# Move system config into top-level /etc/
429+
ETC_GITCONFIG = ../etc/gitconfig
430+
ETC_GITATTRIBUTES = ../etc/gitattributes
431+
endif
427432

428433
CC = compat/vcbuild/scripts/clink.pl
429434
AR = compat/vcbuild/scripts/lib.pl
@@ -670,6 +675,11 @@ else
670675
NO_CURL =
671676
USE_NED_ALLOCATOR = YesPlease
672677
NO_PYTHON =
678+
ifeq (/mingw64,$(subst 32,64,$(prefix)))
679+
# Move system config into top-level /etc/
680+
ETC_GITCONFIG = ../etc/gitconfig
681+
ETC_GITATTRIBUTES = ../etc/gitattributes
682+
endif
673683
else
674684
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO
675685
NO_CURL = YesPlease

git-compat-util.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -436,10 +436,6 @@ static inline int git_create_symlink(struct index_state *index, const char *targ
436436
#endif
437437
#endif
438438

439-
#ifndef git_program_data_config
440-
#define git_program_data_config() NULL
441-
#endif
442-
443439
#if defined(__HP_cc) && (__HP_cc >= 61000)
444440
#define NORETURN __attribute__((noreturn))
445441
#define NORETURN_PTR

0 commit comments

Comments
 (0)