summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2017-06-13 13:47:09 -0700
committerLibravatar Junio C Hamano <gitster@pobox.com>2017-06-13 13:47:09 -0700
commitb9a7d55d938a81eb6268196b789d573437492100 (patch)
tree637c6e3452e5b81394faf99f0a4a24ce73c801e8
parentMerge branch 'rf/completion' (diff)
parentmingw_fopen: report ENOENT for invalid file names (diff)
downloadtgif-b9a7d55d938a81eb6268196b789d573437492100.tar.xz
Merge branch 'nd/fopen-errors'
We often try to open a file for reading whose existence is optional, and silently ignore errors from open/fopen; report such errors if they are not due to missing files. * nd/fopen-errors: mingw_fopen: report ENOENT for invalid file names mingw: verify that paths are not mistaken for remote nicknames log: fix memory leak in open_next_file() rerere.c: move error_errno() closer to the source system call print errno when reporting a system call error wrapper.c: make warn_on_inaccessible() static wrapper.c: add and use fopen_or_warn() wrapper.c: add and use warn_on_fopen_errors() config.mak.uname: set FREAD_READS_DIRECTORIES for Darwin, too config.mak.uname: set FREAD_READS_DIRECTORIES for Linux and FreeBSD clone: use xfopen() instead of fopen() use xfopen() in more places git_fopen: fix a sparse 'not declared' warning
-rw-r--r--attr.c7
-rw-r--r--bisect.c7
-rw-r--r--builtin/am.c8
-rw-r--r--builtin/blame.c2
-rw-r--r--builtin/clone.c2
-rw-r--r--builtin/commit.c5
-rw-r--r--builtin/fast-export.c4
-rw-r--r--builtin/fsck.c3
-rw-r--r--builtin/log.c11
-rw-r--r--builtin/merge.c4
-rw-r--r--builtin/pull.c3
-rw-r--r--commit.c2
-rw-r--r--compat/fopen.c4
-rw-r--r--compat/mingw.c2
-rw-r--r--config.c5
-rw-r--r--config.mak.uname4
-rw-r--r--diff.c8
-rw-r--r--dir.c6
-rw-r--r--fast-import.c4
-rw-r--r--git-compat-util.h15
-rw-r--r--ident.c8
-rw-r--r--remote-testsvn.c8
-rw-r--r--remote.c4
-rw-r--r--rerere.c7
-rw-r--r--sequencer.c8
-rw-r--r--server-info.c2
-rwxr-xr-xt/t1308-config-set.sh13
-rwxr-xr-xt/t5512-ls-remote.sh13
-rwxr-xr-xt/t5580-clone-push-unc.sh10
-rw-r--r--wrapper.c31
-rw-r--r--wt-status.c3
-rw-r--r--xdiff-interface.c4
32 files changed, 125 insertions, 92 deletions
diff --git a/attr.c b/attr.c
index 7e2134471c..821203e2a9 100644
--- a/attr.c
+++ b/attr.c
@@ -720,16 +720,13 @@ void git_attr_set_direction(enum git_attr_direction new_direction,
static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)
{
- FILE *fp = fopen(path, "r");
+ FILE *fp = fopen_or_warn(path, "r");
struct attr_stack *res;
char buf[2048];
int lineno = 0;
- if (!fp) {
- if (errno != ENOENT && errno != ENOTDIR)
- warn_on_inaccessible(path);
+ if (!fp)
return NULL;
- }
res = xcalloc(1, sizeof(*res));
while (fgets(buf, sizeof(buf), fp)) {
char *bufp = buf;
diff --git a/bisect.c b/bisect.c
index c952df692b..2a2b9b7267 100644
--- a/bisect.c
+++ b/bisect.c
@@ -438,10 +438,7 @@ static void read_bisect_paths(struct argv_array *array)
{
struct strbuf str = STRBUF_INIT;
const char *filename = git_path_bisect_names();
- FILE *fp = fopen(filename, "r");
-
- if (!fp)
- die_errno(_("Could not open file '%s'"), filename);
+ FILE *fp = xfopen(filename, "r");
while (strbuf_getline_lf(&str, fp) != EOF) {
strbuf_trim(&str);
@@ -669,7 +666,7 @@ static int is_expected_rev(const struct object_id *oid)
if (stat(filename, &st) || !S_ISREG(st.st_mode))
return 0;
- fp = fopen(filename, "r");
+ fp = fopen_or_warn(filename, "r");
if (!fp)
return 0;
diff --git a/builtin/am.c b/builtin/am.c
index 5ee146bfb3..8881d73615 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -1275,12 +1275,8 @@ static int parse_mail(struct am_state *state, const char *mail)
die("BUG: invalid value for state->scissors");
}
- mi.input = fopen(mail, "r");
- if (!mi.input)
- die("could not open input");
- mi.output = fopen(am_path(state, "info"), "w");
- if (!mi.output)
- die("could not open output 'info'");
+ mi.input = xfopen(mail, "r");
+ mi.output = xfopen(am_path(state, "info"), "w");
if (mailinfo(&mi, am_path(state, "msg"), am_path(state, "patch")))
die("could not parse patch");
diff --git a/builtin/blame.c b/builtin/blame.c
index d7a2df3b47..749ad7f05b 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -481,7 +481,7 @@ static void output(struct blame_scoreboard *sb, int option)
*/
static int read_ancestry(const char *graft_file)
{
- FILE *fp = fopen(graft_file, "r");
+ FILE *fp = fopen_or_warn(graft_file, "r");
struct strbuf buf = STRBUF_INIT;
if (!fp)
return -1;
diff --git a/builtin/clone.c b/builtin/clone.c
index 743f16ae2a..a2ea019c59 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -360,7 +360,7 @@ static void copy_alternates(struct strbuf *src, struct strbuf *dst,
* to turn entries with paths relative to the original
* absolute, so that they can be used in the new repository.
*/
- FILE *in = fopen(src->buf, "r");
+ FILE *in = xfopen(src->buf, "r");
struct strbuf line = STRBUF_INIT;
while (strbuf_getline(&line, in) != EOF) {
diff --git a/builtin/commit.c b/builtin/commit.c
index da1ba4c862..ef52457eff 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1699,10 +1699,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
if (!reflog_msg)
reflog_msg = "commit (merge)";
pptr = commit_list_append(current_head, pptr);
- fp = fopen(git_path_merge_head(), "r");
- if (fp == NULL)
- die_errno(_("could not open '%s' for reading"),
- git_path_merge_head());
+ fp = xfopen(git_path_merge_head(), "r");
while (strbuf_getline_lf(&m, fp) != EOF) {
struct commit *parent;
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 24e29ad7ea..2dfed87454 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -907,9 +907,7 @@ static void export_marks(char *file)
static void import_marks(char *input_file)
{
char line[512];
- FILE *f = fopen(input_file, "r");
- if (!f)
- die_errno("cannot read '%s'", input_file);
+ FILE *f = xfopen(input_file, "r");
while (fgets(line, sizeof(line), f)) {
uint32_t mark;
diff --git a/builtin/fsck.c b/builtin/fsck.c
index cb2ba6cd1b..3a2c27f241 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -280,8 +280,7 @@ static void check_unreachable_object(struct object *obj)
free(filename);
return;
}
- if (!(f = fopen(filename, "w")))
- die_errno("Could not open '%s'", filename);
+ f = xfopen(filename, "w");
if (obj->type == OBJ_BLOB) {
if (stream_blob_to_fd(fileno(f), &obj->oid, NULL, 1))
die_errno("Could not write '%s'", filename);
diff --git a/builtin/log.c b/builtin/log.c
index e89ec941ce..a33c1a70ab 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -846,8 +846,10 @@ static int open_next_file(struct commit *commit, const char *subject,
if (output_directory) {
strbuf_addstr(&filename, output_directory);
if (filename.len >=
- PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len)
+ PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len) {
+ strbuf_release(&filename);
return error(_("name of output directory is too long"));
+ }
strbuf_complete(&filename, '/');
}
@@ -861,8 +863,11 @@ static int open_next_file(struct commit *commit, const char *subject,
if (!quiet)
printf("%s\n", filename.buf + outdir_offset);
- if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL)
- return error(_("Cannot open patch file %s"), filename.buf);
+ if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL) {
+ error_errno(_("Cannot open patch file %s"), filename.buf);
+ strbuf_release(&filename);
+ return -1;
+ }
strbuf_release(&filename);
return 0;
diff --git a/builtin/merge.c b/builtin/merge.c
index a4a098f40f..eab03a026d 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -839,9 +839,7 @@ static int suggest_conflicts(void)
struct strbuf msgbuf = STRBUF_INIT;
filename = git_path_merge_msg();
- fp = fopen(filename, "a");
- if (!fp)
- die_errno(_("Could not open '%s' for writing"), filename);
+ fp = xfopen(filename, "a");
append_conflicts_hint(&msgbuf);
fputs(msgbuf.buf, fp);
diff --git a/builtin/pull.c b/builtin/pull.c
index da8b60fc85..69417e4f36 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -337,8 +337,7 @@ static void get_merge_heads(struct oid_array *merge_heads)
struct strbuf sb = STRBUF_INIT;
struct object_id oid;
- if (!(fp = fopen(filename, "r")))
- die_errno(_("could not open '%s' for reading"), filename);
+ fp = xfopen(filename, "r");
while (strbuf_getline_lf(&sb, fp) != EOF) {
if (get_oid_hex(sb.buf, &oid))
continue; /* invalid line: does not start with SHA1 */
diff --git a/commit.c b/commit.c
index 713f09feb0..99846d9bf4 100644
--- a/commit.c
+++ b/commit.c
@@ -168,7 +168,7 @@ bad_graft_data:
static int read_graft_file(const char *graft_file)
{
- FILE *fp = fopen(graft_file, "r");
+ FILE *fp = fopen_or_warn(graft_file, "r");
struct strbuf buf = STRBUF_INIT;
if (!fp)
return -1;
diff --git a/compat/fopen.c b/compat/fopen.c
index b5ca142fed..107b3e8182 100644
--- a/compat/fopen.c
+++ b/compat/fopen.c
@@ -1,14 +1,14 @@
/*
* The order of the following two lines is important.
*
- * FREAD_READS_DIRECTORIES is undefined before including git-compat-util.h
+ * SUPPRESS_FOPEN_REDEFINITION is defined before including git-compat-util.h
* to avoid the redefinition of fopen within git-compat-util.h. This is
* necessary since fopen is a macro on some platforms which may be set
* based on compiler options. For example, on AIX fopen is set to fopen64
* when _LARGE_FILES is defined. The previous technique of merely undefining
* fopen after including git-compat-util.h is inadequate in this case.
*/
-#undef FREAD_READS_DIRECTORIES
+#define SUPPRESS_FOPEN_REDEFINITION
#include "../git-compat-util.h"
FILE *git_fopen(const char *path, const char *mode)
diff --git a/compat/mingw.c b/compat/mingw.c
index c6134f7c81..8b6fa0db44 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -423,6 +423,8 @@ FILE *mingw_fopen (const char *filename, const char *otype)
return NULL;
}
file = _wfopen(wfilename, wotype);
+ if (!file && GetLastError() == ERROR_INVALID_NAME)
+ errno = ENOENT;
if (file && hide && set_hidden_flag(wfilename, 1))
warning("could not mark '%s' as hidden.", filename);
return file;
diff --git a/config.c b/config.c
index 146cb3452a..34a139c40b 100644
--- a/config.c
+++ b/config.c
@@ -1438,7 +1438,7 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
int ret = -1;
FILE *f;
- f = fopen(filename, "r");
+ f = fopen_or_warn(filename, "r");
if (f) {
flockfile(f);
ret = do_config_from_file(fn, CONFIG_ORIGIN_FILE, filename, filename, f, data);
@@ -2656,6 +2656,9 @@ int git_config_rename_section_in_file(const char *config_filename,
}
if (!(config_file = fopen(config_filename, "rb"))) {
+ ret = warn_on_fopen_errors(config_filename);
+ if (ret)
+ goto out;
/* no config file means nothing to rename, no error */
goto commit_and_out;
}
diff --git a/config.mak.uname b/config.mak.uname
index 192629f143..d2cabe7fb4 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -36,6 +36,7 @@ ifeq ($(uname_S),Linux)
NEEDS_LIBRT = YesPlease
HAVE_GETDELIM = YesPlease
SANE_TEXT_GREP=-a
+ FREAD_READS_DIRECTORIES = UnfortunatelyYes
endif
ifeq ($(uname_S),GNU/kFreeBSD)
HAVE_ALLOCA_H = YesPlease
@@ -43,6 +44,7 @@ ifeq ($(uname_S),GNU/kFreeBSD)
HAVE_PATHS_H = YesPlease
DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
LIBC_CONTAINS_LIBINTL = YesPlease
+ FREAD_READS_DIRECTORIES = UnfortunatelyYes
endif
ifeq ($(uname_S),UnixWare)
CC = cc
@@ -108,6 +110,7 @@ ifeq ($(uname_S),Darwin)
BASIC_CFLAGS += -DPRECOMPOSE_UNICODE
BASIC_CFLAGS += -DPROTECT_HFS_DEFAULT=1
HAVE_BSD_SYSCTL = YesPlease
+ FREAD_READS_DIRECTORIES = UnfortunatelyYes
endif
ifeq ($(uname_S),SunOS)
NEEDS_SOCKET = YesPlease
@@ -201,6 +204,7 @@ ifeq ($(uname_S),FreeBSD)
GMTIME_UNRELIABLE_ERRORS = UnfortunatelyYes
HAVE_BSD_SYSCTL = YesPlease
PAGER_ENV = LESS=FRX LV=-c MORE=FRX
+ FREAD_READS_DIRECTORIES = UnfortunatelyYes
endif
ifeq ($(uname_S),OpenBSD)
NO_STRCASESTR = YesPlease
diff --git a/diff.c b/diff.c
index 5275c4b780..e35cf6c704 100644
--- a/diff.c
+++ b/diff.c
@@ -4071,9 +4071,7 @@ int diff_opt_parse(struct diff_options *options,
DIFF_OPT_CLR(options, FUNCCONTEXT);
else if ((argcount = parse_long_opt("output", av, &optarg))) {
char *path = prefix_filename(prefix, optarg);
- options->file = fopen(path, "w");
- if (!options->file)
- die_errno("Could not open '%s'", path);
+ options->file = xfopen(path, "w");
options->close_file = 1;
if (options->use_color != GIT_COLOR_ALWAYS)
options->use_color = GIT_COLOR_NEVER;
@@ -4807,9 +4805,7 @@ void diff_flush(struct diff_options *options)
*/
if (options->close_file)
fclose(options->file);
- options->file = fopen("/dev/null", "w");
- if (!options->file)
- die_errno("Could not open /dev/null");
+ options->file = xfopen("/dev/null", "w");
options->close_file = 1;
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
diff --git a/dir.c b/dir.c
index 70f2de38f2..1759063817 100644
--- a/dir.c
+++ b/dir.c
@@ -752,9 +752,9 @@ static int add_excludes(const char *fname, const char *base, int baselen,
fd = open(fname, O_RDONLY);
if (fd < 0 || fstat(fd, &st) < 0) {
- if (errno != ENOENT)
- warn_on_inaccessible(fname);
- if (0 <= fd)
+ if (fd < 0)
+ warn_on_fopen_errors(fname);
+ else
close(fd);
if (!istate ||
(buf = read_skip_worktree_file_from_index(istate, fname, &size, sha1_stat)) == NULL)
diff --git a/fast-import.c b/fast-import.c
index e69d219682..9a22fc92c0 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -3285,9 +3285,7 @@ static void option_export_pack_edges(const char *edges)
{
if (pack_edges)
fclose(pack_edges);
- pack_edges = fopen(edges, "a");
- if (!pack_edges)
- die_errno("Cannot open '%s'", edges);
+ pack_edges = xfopen(edges, "a");
}
static int parse_one_option(const char *option)
diff --git a/git-compat-util.h b/git-compat-util.h
index e83fd2eb07..51ba4e6b3b 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -693,10 +693,12 @@ char *gitstrdup(const char *s);
#endif
#ifdef FREAD_READS_DIRECTORIES
-#ifdef fopen
-#undef fopen
-#endif
-#define fopen(a,b) git_fopen(a,b)
+# if !defined(SUPPRESS_FOPEN_REDEFINITION)
+# ifdef fopen
+# undef fopen
+# endif
+# define fopen(a,b) git_fopen(a,b)
+# endif
extern FILE *git_fopen(const char*, const char*);
#endif
@@ -804,6 +806,7 @@ extern int xmkstemp(char *template);
extern int xmkstemp_mode(char *template, int mode);
extern char *xgetcwd(void);
extern FILE *fopen_for_writing(const char *path);
+extern FILE *fopen_or_warn(const char *path, const char *mode);
#define ALLOC_ARRAY(x, alloc) (x) = xmalloc(st_mult(sizeof(*(x)), (alloc)))
#define REALLOC_ARRAY(x, alloc) (x) = xrealloc((x), st_mult(sizeof(*(x)), (alloc)))
@@ -1110,8 +1113,8 @@ int remove_or_warn(unsigned int mode, const char *path);
int access_or_warn(const char *path, int mode, unsigned flag);
int access_or_die(const char *path, int mode, unsigned flag);
-/* Warn on an inaccessible file that ought to be accessible */
-void warn_on_inaccessible(const char *path);
+/* Warn on an inaccessible file if errno indicates this is an error */
+int warn_on_fopen_errors(const char *path);
#ifdef GMTIME_UNRELIABLE_ERRORS
struct tm *git_gmtime(const time_t *);
diff --git a/ident.c b/ident.c
index bea871c8e0..91c7609055 100644
--- a/ident.c
+++ b/ident.c
@@ -72,12 +72,10 @@ static int add_mailname_host(struct strbuf *buf)
FILE *mailname;
struct strbuf mailnamebuf = STRBUF_INIT;
- mailname = fopen("/etc/mailname", "r");
- if (!mailname) {
- if (errno != ENOENT)
- warning_errno("cannot open /etc/mailname");
+ mailname = fopen_or_warn("/etc/mailname", "r");
+ if (!mailname)
return -1;
- }
+
if (strbuf_getline(&mailnamebuf, mailname) == EOF) {
if (ferror(mailname))
warning_errno("cannot read /etc/mailname");
diff --git a/remote-testsvn.c b/remote-testsvn.c
index f87bf851ba..50404ef343 100644
--- a/remote-testsvn.c
+++ b/remote-testsvn.c
@@ -124,10 +124,8 @@ static int note2mark_cb(const unsigned char *object_sha1,
static void regenerate_marks(void)
{
int ret;
- FILE *marksfile = fopen(marksfilename, "w+");
+ FILE *marksfile = xfopen(marksfilename, "w+");
- if (!marksfile)
- die_errno("Couldn't create mark file %s.", marksfilename);
ret = for_each_note(NULL, 0, note2mark_cb, marksfile);
if (ret)
die("Regeneration of marks failed, returned %d.", ret);
@@ -148,9 +146,7 @@ static void check_or_regenerate_marks(int latestrev)
marksfile = fopen(marksfilename, "r");
if (!marksfile) {
regenerate_marks();
- marksfile = fopen(marksfilename, "r");
- if (!marksfile)
- die_errno("cannot read marks file %s!", marksfilename);
+ marksfile = xfopen(marksfilename, "r");
fclose(marksfile);
} else {
strbuf_addf(&sb, ":%d ", latestrev);
diff --git a/remote.c b/remote.c
index 3649d60cdc..f998f989e9 100644
--- a/remote.c
+++ b/remote.c
@@ -251,7 +251,7 @@ static const char *skip_spaces(const char *s)
static void read_remotes_file(struct remote *remote)
{
struct strbuf buf = STRBUF_INIT;
- FILE *f = fopen(git_path("remotes/%s", remote->name), "r");
+ FILE *f = fopen_or_warn(git_path("remotes/%s", remote->name), "r");
if (!f)
return;
@@ -277,7 +277,7 @@ static void read_branches_file(struct remote *remote)
{
char *frag;
struct strbuf buf = STRBUF_INIT;
- FILE *f = fopen(git_path("branches/%s", remote->name), "r");
+ FILE *f = fopen_or_warn(git_path("branches/%s", remote->name), "r");
if (!f)
return;
diff --git a/rerere.c b/rerere.c
index 3bd55caf3b..c26c29f87a 100644
--- a/rerere.c
+++ b/rerere.c
@@ -200,7 +200,7 @@ static struct rerere_id *new_rerere_id(unsigned char *sha1)
static void read_rr(struct string_list *rr)
{
struct strbuf buf = STRBUF_INIT;
- FILE *in = fopen(git_path_merge_rr(), "r");
+ FILE *in = fopen_or_warn(git_path_merge_rr(), "r");
if (!in)
return;
@@ -484,13 +484,14 @@ static int handle_file(const char *path, unsigned char *sha1, const char *output
io.input = fopen(path, "r");
io.io.wrerror = 0;
if (!io.input)
- return error("Could not open %s", path);
+ return error_errno("Could not open %s", path);
if (output) {
io.io.output = fopen(output, "w");
if (!io.io.output) {
+ error_errno("Could not write %s", output);
fclose(io.input);
- return error("Could not write %s", output);
+ return -1;
}
}
diff --git a/sequencer.c b/sequencer.c
index 924fb1d0c3..5282fb849c 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -899,8 +899,8 @@ static void flush_rewritten_pending(void) {
FILE *out;
if (strbuf_read_file(&buf, rebase_path_rewritten_pending(), 82) > 0 &&
- !get_sha1("HEAD", newsha1) &&
- (out = fopen(rebase_path_rewritten_list(), "a"))) {
+ !get_sha1("HEAD", newsha1) &&
+ (out = fopen_or_warn(rebase_path_rewritten_list(), "a"))) {
char *bol = buf.buf, *eol;
while (*bol) {
@@ -919,7 +919,7 @@ static void flush_rewritten_pending(void) {
static void record_in_rewritten(struct object_id *oid,
enum todo_command next_command) {
- FILE *out = fopen(rebase_path_rewritten_pending(), "a");
+ FILE *out = fopen_or_warn(rebase_path_rewritten_pending(), "a");
if (!out)
return;
@@ -1381,7 +1381,7 @@ static int read_populate_todo(struct todo_list *todo_list,
if (is_rebase_i(opts)) {
struct todo_list done = TODO_LIST_INIT;
- FILE *f = fopen(rebase_path_msgtotal(), "w");
+ FILE *f = fopen_or_warn(rebase_path_msgtotal(), "w");
if (strbuf_read_file(&done.buf, rebase_path_done(), 0) > 0 &&
!parse_insn_buffer(done.buf.buf, &done))
diff --git a/server-info.c b/server-info.c
index 6f865b73a3..5ec5b1d827 100644
--- a/server-info.c
+++ b/server-info.c
@@ -133,7 +133,7 @@ static int read_pack_info_file(const char *infofile)
char line[1000];
int old_cnt = 0;
- fp = fopen(infofile, "r");
+ fp = fopen_or_warn(infofile, "r");
if (!fp)
return 1; /* nonexistent is not an error. */
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index ff50960cca..e495a61616 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -183,11 +183,22 @@ test_expect_success 'proper error on non-existent files' '
test_cmp expect actual
'
+test_expect_success 'proper error on directory "files"' '
+ echo "Error (-1) reading configuration file a-directory." >expect &&
+ mkdir a-directory &&
+ test_expect_code 2 test-config configset_get_value foo.bar a-directory 2>output &&
+ grep "^warning:" output &&
+ grep "^Error" output >actual &&
+ test_cmp expect actual
+'
+
test_expect_success POSIXPERM,SANITY 'proper error on non-accessible files' '
chmod -r .git/config &&
test_when_finished "chmod +r .git/config" &&
echo "Error (-1) reading configuration file .git/config." >expect &&
- test_expect_code 2 test-config configset_get_value foo.bar .git/config 2>actual &&
+ test_expect_code 2 test-config configset_get_value foo.bar .git/config 2>output &&
+ grep "^warning:" output &&
+ grep "^Error" output >actual &&
test_cmp expect actual
'
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index 94fc9be9ce..02106c9226 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -85,8 +85,15 @@ test_expect_success 'use branch.<name>.remote if possible' '
'
test_expect_success 'confuses pattern as remote when no remote specified' '
- cat >exp <<-\EOF &&
- fatal: '\''refs*master'\'' does not appear to be a git repository
+ if test_have_prereq MINGW
+ then
+ # Windows does not like asterisks in pathname
+ does_not_exist=master
+ else
+ does_not_exist="refs*master"
+ fi &&
+ cat >exp <<-EOF &&
+ fatal: '\''$does_not_exist'\'' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
@@ -98,7 +105,7 @@ test_expect_success 'confuses pattern as remote when no remote specified' '
# fetch <branch>.
# We could just as easily have used "master"; the "*" emphasizes its
# role as a pattern.
- test_must_fail git ls-remote refs*master >actual 2>&1 &&
+ test_must_fail git ls-remote "$does_not_exist" >actual 2>&1 &&
test_i18ncmp exp actual
'
diff --git a/t/t5580-clone-push-unc.sh b/t/t5580-clone-push-unc.sh
index b195f71ea9..b322c2f722 100755
--- a/t/t5580-clone-push-unc.sh
+++ b/t/t5580-clone-push-unc.sh
@@ -1,10 +1,10 @@
#!/bin/sh
-test_description='various UNC path tests (Windows-only)'
+test_description='various Windows-only path tests'
. ./test-lib.sh
if ! test_have_prereq MINGW; then
- skip_all='skipping UNC path tests, requires Windows'
+ skip_all='skipping Windows-only path tests'
test_done
fi
@@ -45,4 +45,10 @@ test_expect_success push '
test "$rev" = "$(git rev-parse --verify refs/heads/to-push)"
'
+test_expect_success 'remote nick cannot contain backslashes' '
+ BACKSLASHED="$(pwd | tr / \\\\)" &&
+ git ls-remote "$BACKSLASHED" >out 2>err &&
+ test_i18ngrep ! "unable to access" err
+'
+
test_done
diff --git a/wrapper.c b/wrapper.c
index 708e98a965..4632c7d4c0 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -418,6 +418,32 @@ FILE *fopen_for_writing(const char *path)
return ret;
}
+static void warn_on_inaccessible(const char *path)
+{
+ warning_errno(_("unable to access '%s'"), path);
+}
+
+int warn_on_fopen_errors(const char *path)
+{
+ if (errno != ENOENT && errno != ENOTDIR) {
+ warn_on_inaccessible(path);
+ return -1;
+ }
+
+ return 0;
+}
+
+FILE *fopen_or_warn(const char *path, const char *mode)
+{
+ FILE *fp = fopen(path, mode);
+
+ if (fp)
+ return fp;
+
+ warn_on_fopen_errors(path);
+ return NULL;
+}
+
int xmkstemp(char *template)
{
int fd;
@@ -576,11 +602,6 @@ int remove_or_warn(unsigned int mode, const char *file)
return S_ISGITLINK(mode) ? rmdir_or_warn(file) : unlink_or_warn(file);
}
-void warn_on_inaccessible(const char *path)
-{
- warning_errno(_("unable to access '%s'"), path);
-}
-
static int access_error_is_ok(int err, unsigned flag)
{
return (is_missing_file_error(err) ||
diff --git a/wt-status.c b/wt-status.c
index 25aafc35c8..bf651f16fa 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1066,7 +1066,8 @@ static void show_am_in_progress(struct wt_status *s,
static char *read_line_from_git_path(const char *filename)
{
struct strbuf buf = STRBUF_INIT;
- FILE *fp = fopen(git_path("%s", filename), "r");
+ FILE *fp = fopen_or_warn(git_path("%s", filename), "r");
+
if (!fp) {
strbuf_release(&buf);
return NULL;
diff --git a/xdiff-interface.c b/xdiff-interface.c
index 060038c2d6..d3f78ca2a7 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -164,9 +164,9 @@ int read_mmfile(mmfile_t *ptr, const char *filename)
size_t sz;
if (stat(filename, &st))
- return error("Could not stat %s", filename);
+ return error_errno("Could not stat %s", filename);
if ((f = fopen(filename, "rb")) == NULL)
- return error("Could not open %s", filename);
+ return error_errno("Could not open %s", filename);
sz = xsize_t(st.st_size);
ptr->ptr = xmalloc(sz ? sz : 1);
if (sz && fread(ptr->ptr, sz, 1, f) != 1) {