Skip to content

Commit 29e44e5

Browse files
committed
Merge pull request msysgit#156 from kblees/kb/symlinks
Symlink support
2 parents 67b5324 + e2eda1c commit 29e44e5

File tree

11 files changed

+569
-204
lines changed

11 files changed

+569
-204
lines changed

compat/mingw.c

Lines changed: 489 additions & 173 deletions
Large diffs are not rendered by default.

compat/mingw.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,6 @@ struct utsname {
123123
* trivial stubs
124124
*/
125125

126-
static inline int readlink(const char *path, char *buf, size_t bufsiz)
127-
{ errno = ENOSYS; return -1; }
128-
static inline int symlink(const char *oldpath, const char *newpath)
129-
{ errno = ENOSYS; return -1; }
130126
static inline int fchmod(int fildes, mode_t mode)
131127
{ errno = ENOSYS; return -1; }
132128
#ifndef __MINGW64_VERSION_MAJOR
@@ -218,6 +214,8 @@ int setitimer(int type, struct itimerval *in, struct itimerval *out);
218214
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
219215
int link(const char *oldpath, const char *newpath);
220216
int uname(struct utsname *buf);
217+
int symlink(const char *target, const char *link);
218+
int readlink(const char *path, char *buf, size_t bufsiz);
221219

222220
/*
223221
* replacements of existing functions
@@ -447,6 +445,8 @@ static inline void convert_slashes(char *path)
447445
int mingw_offset_1st_component(const char *path);
448446
#define offset_1st_component mingw_offset_1st_component
449447
#define PATH_SEP ';'
448+
extern char *mingw_query_user_email(void);
449+
#define query_user_email mingw_query_user_email
450450
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
451451
#define PRIuMAX "I64u"
452452
#define PRId64 "I64d"

compat/win32.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@
66
#include <windows.h>
77
#endif
88

9-
static inline int file_attr_to_st_mode (DWORD attr)
9+
#include "compat/win32/lazyload.h"
10+
11+
static inline int file_attr_to_st_mode (DWORD attr, DWORD tag)
1012
{
1113
int fMode = S_IREAD;
12-
if (attr & FILE_ATTRIBUTE_DIRECTORY)
14+
if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) && tag == IO_REPARSE_TAG_SYMLINK)
15+
fMode |= S_IFLNK;
16+
else if (attr & FILE_ATTRIBUTE_DIRECTORY)
1317
fMode |= S_IFDIR;
1418
else
1519
fMode |= S_IFREG;

compat/win32/dirent.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ static inline void finddata2dirent(struct dirent *ent, WIN32_FIND_DATAW *fdata)
1616
xwcstoutf(ent->d_name, fdata->cFileName, MAX_PATH * 3);
1717

1818
/* Set file type, based on WIN32_FIND_DATA */
19-
if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
19+
if ((fdata->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
20+
&& fdata->dwReserved0 == IO_REPARSE_TAG_SYMLINK)
21+
ent->d_type = DT_LNK;
22+
else if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2023
ent->d_type = DT_DIR;
2124
else
2225
ent->d_type = DT_REG;

compat/win32/fscache.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,10 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
147147

148148
fse = fsentry_alloc(list, buf, len);
149149

150-
fse->st_mode = file_attr_to_st_mode(fdata->dwFileAttributes);
151-
fse->st_size = (((off64_t) (fdata->nFileSizeHigh)) << 32)
152-
| fdata->nFileSizeLow;
150+
fse->st_mode = file_attr_to_st_mode(fdata->dwFileAttributes,
151+
fdata->dwReserved0);
152+
fse->st_size = S_ISLNK(fse->st_mode) ? MAX_LONG_PATH :
153+
fdata->nFileSizeLow | (((off_t) fdata->nFileSizeHigh) << 32);
153154
fse->st_atime = filetime_to_time_t(&(fdata->ftLastAccessTime));
154155
fse->st_mtime = filetime_to_time_t(&(fdata->ftLastWriteTime));
155156
fse->st_ctime = filetime_to_time_t(&(fdata->ftCreationTime));
@@ -440,7 +441,8 @@ static struct dirent *fscache_readdir(DIR *base_dir)
440441
if (!next)
441442
return NULL;
442443
dir->pfsentry = next;
443-
dir->dirent.d_type = S_ISDIR(next->st_mode) ? DT_DIR : DT_REG;
444+
dir->dirent.d_type = S_ISREG(next->st_mode) ? DT_REG :
445+
S_ISDIR(next->st_mode) ? DT_DIR : DT_LNK;
444446
dir->dirent.d_name = (char*) next->name;
445447
return &(dir->dirent);
446448
}

compat/win32/lazyload.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#ifndef LAZYLOAD_H
2+
#define LAZYLOAD_H
3+
4+
/* simplify loading of DLL functions */
5+
6+
struct proc_addr {
7+
const char *const dll;
8+
const char *const function;
9+
FARPROC pfunction;
10+
unsigned initialized : 1;
11+
};
12+
13+
/* Declares a function to be loaded dynamically from a DLL. */
14+
#define DECLARE_PROC_ADDR(dll, rettype, function, ...) \
15+
static struct proc_addr proc_addr_##function = \
16+
{ #dll, #function, NULL, 0 }; \
17+
static rettype (WINAPI *function)(__VA_ARGS__)
18+
19+
/*
20+
* Loads a function from a DLL (once-only).
21+
* Returns non-NULL function pointer on success.
22+
* Returns NULL + errno == ENOSYS on failure.
23+
*/
24+
#define INIT_PROC_ADDR(function) (function = get_proc_addr(&proc_addr_##function))
25+
26+
static inline void *get_proc_addr(struct proc_addr *proc)
27+
{
28+
/* only do this once */
29+
if (!proc->initialized) {
30+
HANDLE hnd;
31+
proc->initialized = 1;
32+
hnd = LoadLibraryExA(proc->dll, NULL,
33+
LOAD_LIBRARY_SEARCH_SYSTEM32);
34+
if (hnd)
35+
proc->pfunction = GetProcAddress(hnd, proc->function);
36+
}
37+
/* set ENOSYS if DLL or function was not found */
38+
if (!proc->pfunction)
39+
errno = ENOSYS;
40+
return proc->pfunction;
41+
}
42+
43+
#endif

compat/winansi.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,26 +41,21 @@ typedef struct _CONSOLE_FONT_INFOEX {
4141
#endif
4242
#endif
4343

44-
typedef BOOL (WINAPI *PGETCURRENTCONSOLEFONTEX)(HANDLE, BOOL,
45-
PCONSOLE_FONT_INFOEX);
46-
4744
static void warn_if_raster_font(void)
4845
{
4946
DWORD fontFamily = 0;
50-
PGETCURRENTCONSOLEFONTEX pGetCurrentConsoleFontEx;
47+
DECLARE_PROC_ADDR(kernel32.dll, BOOL, GetCurrentConsoleFontEx,
48+
HANDLE, BOOL, PCONSOLE_FONT_INFOEX);
5149

5250
/* don't bother if output was ascii only */
5351
if (!non_ascii_used)
5452
return;
5553

5654
/* GetCurrentConsoleFontEx is available since Vista */
57-
pGetCurrentConsoleFontEx = (PGETCURRENTCONSOLEFONTEX) GetProcAddress(
58-
GetModuleHandle("kernel32.dll"),
59-
"GetCurrentConsoleFontEx");
60-
if (pGetCurrentConsoleFontEx) {
55+
if (INIT_PROC_ADDR(GetCurrentConsoleFontEx)) {
6156
CONSOLE_FONT_INFOEX cfi;
6257
cfi.cbSize = sizeof(cfi);
63-
if (pGetCurrentConsoleFontEx(console, 0, &cfi))
58+
if (GetCurrentConsoleFontEx(console, 0, &cfi))
6459
fontFamily = cfi.FontFamily;
6560
} else {
6661
/* pre-Vista: check default console font in registry */

git-compat-util.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,10 @@ static inline char *git_find_last_dir_sep(const char *path)
380380
#define find_last_dir_sep git_find_last_dir_sep
381381
#endif
382382

383+
#ifndef query_user_email
384+
#define query_user_email() NULL
385+
#endif
386+
383387
#if defined(__HP_cc) && (__HP_cc >= 61000)
384388
#define NORETURN __attribute__((noreturn))
385389
#define NORETURN_PTR

ident.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ const char *ident_default_email(void)
169169
strbuf_addstr(&git_default_email, email);
170170
committer_ident_explicitly_given |= IDENT_MAIL_GIVEN;
171171
author_ident_explicitly_given |= IDENT_MAIL_GIVEN;
172+
} else if ((email = query_user_email()) && email[0]) {
173+
strbuf_addstr(&git_default_email, email);
174+
free((char *)email);
172175
} else
173176
copy_email(xgetpwuid_self(&default_email_is_bogus),
174177
&git_default_email, &default_email_is_bogus);

lockfile.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ static void trim_last_path_component(struct strbuf *path)
1717
int i = path->len;
1818

1919
/* back up past trailing slashes, if any */
20-
while (i && path->buf[i - 1] == '/')
20+
while (i && is_dir_sep(path->buf[i - 1]))
2121
i--;
2222

2323
/*
2424
* then go backwards until a slash, or the beginning of the
2525
* string
2626
*/
27-
while (i && path->buf[i - 1] != '/')
27+
while (i && !is_dir_sep(path->buf[i - 1]))
2828
i--;
2929

3030
strbuf_setlen(path, i);

0 commit comments

Comments
 (0)