Skip to content

Support windows container. #1645

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 24, 2018
Merged
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
70 changes: 68 additions & 2 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,7 @@ int mingw_lstat(const char *file_name, struct stat *buf)
buf->st_uid = 0;
buf->st_nlink = 1;
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes,
findbuf.dwReserved0);
findbuf.dwReserved0, file_name);
buf->st_size = S_ISLNK(buf->st_mode) ? MAX_LONG_PATH :
fdata.nFileSizeLow | (((off_t) fdata.nFileSizeHigh) << 32);
buf->st_dev = buf->st_rdev = 0; /* not used by Git */
Expand Down Expand Up @@ -824,7 +824,7 @@ static int get_file_info_by_handle(HANDLE hnd, struct stat *buf)
buf->st_dev = buf->st_rdev = 0; /* not used by Git */
buf->st_gid = buf->st_uid = 0;
buf->st_nlink = 1;
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes, 0);
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes, 0, NULL);
buf->st_size = fdata.nFileSizeLow | (((off_t) fdata.nFileSizeHigh) << 32);
filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
Expand Down Expand Up @@ -2480,6 +2480,13 @@ int mingw_rename(const char *pold, const char *pnew)
return 0;
gle = GetLastError();

if (gle == ERROR_ACCESS_DENIED && is_inside_windows_container()) {
/* Fall back to copy to destination & remove source */
if (CopyFileW(wpold, wpnew, FALSE) && !mingw_unlink(pold))
return 0;
gle = GetLastError();
}

/* revert file attributes on failure */
if (attrs != INVALID_FILE_ATTRIBUTES)
SetFileAttributesW(wpnew, attrs);
Expand Down Expand Up @@ -3545,3 +3552,62 @@ const char *program_data_config(void)
}
return *path.buf ? path.buf : NULL;
}

/*
* Based on https://stackoverflow.com/questions/43002803
*
* [HKLM\SYSTEM\CurrentControlSet\Services\cexecsvc]
* "DisplayName"="@%systemroot%\\system32\\cexecsvc.exe,-100"
* "ErrorControl"=dword:00000001
* "ImagePath"=hex(2):25,00,73,00,79,00,73,00,74,00,65,00,6d,00,72,00,6f,00,
* 6f,00,74,00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,
* 5c,00,63,00,65,00,78,00,65,00,63,00,73,00,76,00,63,00,2e,00,65,00,78,00,
* 65,00,00,00
* "Start"=dword:00000002
* "Type"=dword:00000010
* "Description"="@%systemroot%\\system32\\cexecsvc.exe,-101"
* "ObjectName"="LocalSystem"
* "ServiceSidType"=dword:00000001
*/
int is_inside_windows_container(void)
{
static int inside_container = -1; /* -1 uninitialized */
const char *key = "SYSTEM\\CurrentControlSet\\Services\\cexecsvc";
HKEY handle = NULL;

if (inside_container != -1)
return inside_container;

inside_container = ERROR_SUCCESS ==
RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &handle);
RegCloseKey(handle);

return inside_container;
}

int file_attr_to_st_mode (DWORD attr, DWORD tag, const char *path)
{
int fMode = S_IREAD;
if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) &&
tag == IO_REPARSE_TAG_SYMLINK) {
int flag = S_IFLNK;
char buf[MAX_LONG_PATH];

/*
* Windows containers' mapped volumes are marked as reparse
* points and look like symbolic links, but they are not.
*/
if (path && is_inside_windows_container() &&
!readlink(path, buf, sizeof(buf)) &&
starts_with(buf, "/ContainerMappedDirectories/"))
flag = S_IFDIR;

fMode |= flag;
} else if (attr & FILE_ATTRIBUTE_DIRECTORY)
fMode |= S_IFDIR;
else
fMode |= S_IFREG;
if (!(attr & FILE_ATTRIBUTE_READONLY))
fMode |= S_IWRITE;
return fMode;
}
5 changes: 5 additions & 0 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -737,3 +737,8 @@ static int mingw_main(c,v)
* Used by Pthread API implementation for Windows
*/
extern int err_win_to_posix(DWORD winerr);

/*
* Check current process is inside Windows Container.
*/
extern int is_inside_windows_container(void);
14 changes: 1 addition & 13 deletions compat/win32.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,7 @@
#include <windows.h>
#endif

static inline int file_attr_to_st_mode (DWORD attr, DWORD tag)
{
int fMode = S_IREAD;
if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) && tag == IO_REPARSE_TAG_SYMLINK)
fMode |= S_IFLNK;
else if (attr & FILE_ATTRIBUTE_DIRECTORY)
fMode |= S_IFDIR;
else
fMode |= S_IFREG;
if (!(attr & FILE_ATTRIBUTE_READONLY))
fMode |= S_IWRITE;
return fMode;
}
extern int file_attr_to_st_mode (DWORD attr, DWORD tag, const char *path);

static inline int get_file_attr(const char *fname, WIN32_FILE_ATTRIBUTE_DATA *fdata)
{
Expand Down
15 changes: 14 additions & 1 deletion compat/win32/fscache.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,21 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,

fse = fsentry_alloc(list, buf, len);

if (fdata->dwReserved0 == IO_REPARSE_TAG_SYMLINK &&
sizeof(buf) > (list ? list->len + 1 : 0) + fse->len + 1 &&
is_inside_windows_container()) {
size_t off = 0;
if (list) {
memcpy(buf, list->name, list->len);
buf[list->len] = '/';
off = list->len + 1;
}
memcpy(buf + off, fse->name, fse->len);
buf[off + fse->len] = '\0';
}

fse->st_mode = file_attr_to_st_mode(fdata->dwFileAttributes,
fdata->dwReserved0);
fdata->dwReserved0, buf);
fse->st_size = S_ISLNK(fse->st_mode) ? MAX_LONG_PATH :
fdata->nFileSizeLow | (((off_t) fdata->nFileSizeHigh) << 32);
filetime_to_timespec(&(fdata->ftLastAccessTime), &(fse->st_atim));
Expand Down