Skip to content

Commit d8ab53d

Browse files
committed
fixup! Windows: add support for a Windows-wide configuration
In the previous commit, we moved the location of the system config to `C:\Program Files\Git\etc\gitconfig`, to give users a reliable location for the system config. Previously, we had introduced `C:\ProgramData\Git\config` as such a location. However, the purpose of `C:\ProgramData\Git\config` was always for the installed Git for Windows to share its configured options. Every upgrade will modify the settings in that file according to what the user specified when running Git for Windows' installer. So it is not really a file whose ownership is shared between all Git implementations, contrary to what the location suggests. Also, it was totally confusing to many users that there was a "system" config and then yet another "sort of system" config that did not even have a corresponding `git config` option such as `--system`. Further, Portable Git should probably never look at `C:\ProgramData\Git\config` to begin with: this makes it rather non-Portable ;-) Finally, support for `C:\ProgramData\Git\config` never really caught on: only libgit2 implemented it, but even JGit (which might be used by more users than libgit2-based applications by grace of backing Android Studio) did not. Therefore, let's finally admit that it was a mistake to introduce `C:\ProgramData\Git\config` and remove support for it. This reverts commit bcbbb4f. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 5083d7c commit d8ab53d

File tree

7 files changed

+7
-213
lines changed

7 files changed

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

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)