diff options
Diffstat (limited to 'compat')
-rw-r--r-- | compat/mingw.c | 74 | ||||
-rw-r--r-- | compat/mingw.h | 3 | ||||
-rw-r--r-- | compat/precompose_utf8.c | 2 | ||||
-rw-r--r-- | compat/win32/syslog.c | 6 |
4 files changed, 78 insertions, 7 deletions
diff --git a/compat/mingw.c b/compat/mingw.c index 0413d5c3cd..a8218e6f0f 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -286,6 +286,49 @@ int mingw_rmdir(const char *pathname) return ret; } +static inline int needs_hiding(const char *path) +{ + const char *basename; + + if (hide_dotfiles == HIDE_DOTFILES_FALSE) + return 0; + + /* We cannot use basename(), as it would remove trailing slashes */ + mingw_skip_dos_drive_prefix((char **)&path); + if (!*path) + return 0; + + for (basename = path; *path; path++) + if (is_dir_sep(*path)) { + do { + path++; + } while (is_dir_sep(*path)); + /* ignore trailing slashes */ + if (*path) + basename = path; + } + + if (hide_dotfiles == HIDE_DOTFILES_TRUE) + return *basename == '.'; + + assert(hide_dotfiles == HIDE_DOTFILES_DOTGITONLY); + return !strncasecmp(".git", basename, 4) && + (!basename[4] || is_dir_sep(basename[4])); +} + +static int set_hidden_flag(const wchar_t *path, int set) +{ + DWORD original = GetFileAttributesW(path), modified; + if (set) + modified = original | FILE_ATTRIBUTE_HIDDEN; + else + modified = original & ~FILE_ATTRIBUTE_HIDDEN; + if (original == modified || SetFileAttributesW(path, modified)) + return 0; + errno = err_win_to_posix(GetLastError()); + return -1; +} + int mingw_mkdir(const char *path, int mode) { int ret; @@ -293,6 +336,8 @@ int mingw_mkdir(const char *path, int mode) if (xutftowcs_path(wpath, path) < 0) return -1; ret = _wmkdir(wpath); + if (!ret && needs_hiding(path)) + return set_hidden_flag(wpath, 1); return ret; } @@ -319,6 +364,21 @@ int mingw_open (const char *filename, int oflags, ...) if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) errno = EISDIR; } + if ((oflags & O_CREAT) && needs_hiding(filename)) { + /* + * Internally, _wopen() uses the CreateFile() API which errors + * out with an ERROR_ACCESS_DENIED if CREATE_ALWAYS was + * specified and an already existing file's attributes do not + * match *exactly*. As there is no mode or flag we can set that + * would correspond to FILE_ATTRIBUTE_HIDDEN, let's just try + * again *without* the O_CREAT flag (that corresponds to the + * CREATE_ALWAYS flag of CreateFile()). + */ + if (fd < 0 && errno == EACCES) + fd = _wopen(wfilename, oflags & ~O_CREAT, mode); + if (fd >= 0 && set_hidden_flag(wfilename, 1)) + warning("could not mark '%s' as hidden.", filename); + } return fd; } @@ -350,6 +410,7 @@ int mingw_fgetc(FILE *stream) #undef fopen FILE *mingw_fopen (const char *filename, const char *otype) { + int hide = needs_hiding(filename); FILE *file; wchar_t wfilename[MAX_PATH], wotype[4]; if (filename && !strcmp(filename, "/dev/null")) @@ -357,12 +418,19 @@ FILE *mingw_fopen (const char *filename, const char *otype) if (xutftowcs_path(wfilename, filename) < 0 || xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0) return NULL; + if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) { + error("could not unhide %s", filename); + return NULL; + } file = _wfopen(wfilename, wotype); + if (file && hide && set_hidden_flag(wfilename, 1)) + warning("could not mark '%s' as hidden.", filename); return file; } FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream) { + int hide = needs_hiding(filename); FILE *file; wchar_t wfilename[MAX_PATH], wotype[4]; if (filename && !strcmp(filename, "/dev/null")) @@ -370,7 +438,13 @@ FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream) if (xutftowcs_path(wfilename, filename) < 0 || xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0) return NULL; + if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) { + error("could not unhide %s", filename); + return NULL; + } file = _wfreopen(wfilename, wotype, stream); + if (file && hide && set_hidden_flag(wfilename, 1)) + warning("could not mark '%s' as hidden.", filename); return file; } diff --git a/compat/mingw.h b/compat/mingw.h index edec9e0253..69bb43dc35 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -417,9 +417,6 @@ int mingw_offset_1st_component(const char *path); void mingw_open_html(const char *path); #define open_html mingw_open_html -void mingw_mark_as_git_dir(const char *dir); -#define mark_as_git_dir mingw_mark_as_git_dir - /** * Converts UTF-8 encoded string to UTF-16LE. * diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c index dfbe6d8408..4293b53b17 100644 --- a/compat/precompose_utf8.c +++ b/compat/precompose_utf8.c @@ -147,7 +147,7 @@ struct dirent_prec_psx *precompose_utf8_readdir(PREC_DIR *prec_dir) if (errno || inleft) { /* * iconv() failed and errno could be E2BIG, EILSEQ, EINVAL, EBADF - * MacOS X avoids illegal byte sequemces. + * MacOS X avoids illegal byte sequences. * If they occur on a mounted drive (e.g. NFS) it is not worth to * die() for that, but rather let the user see the original name */ diff --git a/compat/win32/syslog.c b/compat/win32/syslog.c index b905aea31b..6c7c9b6053 100644 --- a/compat/win32/syslog.c +++ b/compat/win32/syslog.c @@ -28,13 +28,13 @@ void syslog(int priority, const char *fmt, ...) va_end(ap); if (str_len < 0) { - warning("vsnprintf failed: '%s'", strerror(errno)); + warning_errno("vsnprintf failed"); return; } str = malloc(st_add(str_len, 1)); if (!str) { - warning("malloc failed: '%s'", strerror(errno)); + warning_errno("malloc failed"); return; } @@ -45,7 +45,7 @@ void syslog(int priority, const char *fmt, ...) while ((pos = strstr(str, "%1")) != NULL) { str = realloc(str, st_add(++str_len, 1)); if (!str) { - warning("realloc failed: '%s'", strerror(errno)); + warning_errno("realloc failed"); return; } memmove(pos + 2, pos + 1, strlen(pos)); |