Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Fix handling of long recursive paths #113

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,10 +456,6 @@ FILE *mingw_fopen (const char *filename, const char *otype)
int hide = 0;
FILE *file;
wchar_t wfilename[MAX_PATH], wotype[4];

if (is_dos_device_name(filename))
return fopen(filename, otype);

if (hide_dotfiles == HIDE_DOTFILES_TRUE &&
basename((char*)filename)[0] == '.')
hide = access(filename, F_OK);
Expand All @@ -474,16 +470,11 @@ FILE *mingw_fopen (const char *filename, const char *otype)
return file;
}

#undef freopen
FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
{
int hide = 0;
FILE *file;
wchar_t wfilename[MAX_PATH], wotype[4];

if (is_dos_device_name(filename))
return freopen(filename, otype, stream);

if (hide_dotfiles == HIDE_DOTFILES_TRUE &&
basename((char*)filename)[0] == '.')
hide = access(filename, F_OK);
Expand Down Expand Up @@ -2148,6 +2139,30 @@ int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen)
return wpos;
}

int xutftowcs_canonical_path(wchar_t *wcs, const char *utf)
{
wchar_t tmp[MAX_PATH];
int result;
result = xutftowcsn(tmp, utf, MAX_PATH, -1);
if (result < 0 && errno == ERANGE) {
errno = ENAMETOOLONG;
}
else if (is_dos_device_name(utf))
wcscpy(wcs, tmp);
else {
wchar_t tmp2[MAX_PATH*2];
result = GetFullPathNameW(tmp, MAX_PATH*2, tmp2, NULL);
if (result && result < MAX_PATH) {
wcsncpy(wcs, tmp2, MAX_PATH-1);
wcs[MAX_PATH-1] = 0;
} else {
result = -1;
errno = ENAMETOOLONG;
}
}
return result;
}

int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen)
{
if (!wcs || !utf || utflen < 1) {
Expand Down
24 changes: 1 addition & 23 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,29 +455,7 @@ static inline int xutftowcs_path(wchar_t *wcs, const char *utf)
* fails with ENAMETOOLONG if input string is too long. This version
* also canonicalizes the path before returning.
*/
static inline int xutftowcs_canonical_path(wchar_t *wcs, const char *utf)
{
wchar_t tmp[SHRT_MAX];
int result;
result = xutftowcsn(tmp, utf, SHRT_MAX, -1);
if (result < 0 && errno == ERANGE)
errno = ENAMETOOLONG;
else if (wcsncmp(tmp, L"nul", 4) == 0 )
wcsncpy(wcs, tmp, 4);
else {
wchar_t tmp2[SHRT_MAX];
GetFullPathNameW(tmp, SHRT_MAX, tmp2, NULL);
if (wcslen(tmp2) < MAX_PATH)
wcsncpy(wcs, tmp2, MAX_PATH - 1);
else {
result = -1;
errno = ENAMETOOLONG;
}
}
if (result != -1)
result = wcslen(wcs);
return result;
}
int xutftowcs_canonical_path(wchar_t *wcs, const char *utf);

/**
* Converts UTF-16LE encoded string to UTF-8.
Expand Down
101 changes: 101 additions & 0 deletions t/t7410-submodule-long-path.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/bin/sh
#
# Copyright (c) 2013 Doug Kelly
#

test_description='Test submodules with a path near PATH_MAX

This test verifies that "git submodule" initialization, update and clones work, including with recursive submodules and paths approaching PATH_MAX (260 characters on Windows)
'

TEST_NO_CREATE_REPO=1
. ./test-lib.sh

longpath=""
for (( i=0; i<4; i++ )); do
longpath="0123456789abcdefghijklmnopqrstuvwxyz$longpath"
done
# Pick a substring maximum of 90 characters
# This should be good, since we'll add on a lot for temp directories
export longpath=${longpath:0:90}

test_expect_success 'submodule with a long path' '
git init --bare remote &&
test_create_repo bundle1 &&
(
cd bundle1 &&
test_commit "shoot" &&
git rev-parse --verify HEAD >../expect
) &&
mkdir home &&
(
cd home &&
git clone ../remote test &&
cd test &&
git submodule add ../bundle1 $longpath &&
test_commit "sogood" &&
(
cd $longpath &&
git rev-parse --verify HEAD >actual &&
test_cmp ../../../expect actual
) &&
git push origin master
) &&
mkdir home2 &&
(
cd home2 &&
git clone ../remote test &&
cd test &&
git checkout master &&
git submodule update --init &&
(
cd $longpath &&
git rev-parse --verify HEAD >actual &&
test_cmp ../../../expect actual
)
)
'

test_expect_success 'recursive submodule with a long path' '
git init --bare super &&
test_create_repo child &&
(
cd child &&
test_commit "shoot" &&
git rev-parse --verify HEAD >../expect
) &&
test_create_repo parent &&
(
cd parent &&
git submodule add ../child $longpath &&
test_commit "aim"
) &&
mkdir home3 &&
(
cd home3 &&
git clone ../super test &&
cd test &&
git submodule add ../parent foo &&
git submodule update --init --recursive
test_commit "sogood" &&
(
cd foo/$longpath &&
git rev-parse --verify HEAD >actual &&
test_cmp ../../../../expect actual
) &&
git push origin master
) &&
mkdir home4 &&
(
cd home4 &&
git clone ../super test --recursive &&
(
cd test/foo/$longpath &&
git rev-parse --verify HEAD >actual &&
test_cmp ../../../../expect actual
)
)
'
unset longpath

test_done