config.c: avoid xmmap error messages
authorJeff King <peff@peff.net>
Thu, 28 May 2015 07:56:15 +0000 (03:56 -0400)
committerJunio C Hamano <gitster@pobox.com>
Thu, 28 May 2015 18:33:18 +0000 (11:33 -0700)
The config-writing code uses xmmap to map the existing
config file, which will die if the map fails. This has two
downsides:

1. The error message is not very helpful, as it lacks any
context about the file we are mapping:

$ mkdir foo
$ git config --file=foo some.key value
fatal: Out of memory? mmap failed: No such device

2. We normally do not die in this code path; instead, we'd
rather report the error and return an appropriate exit
status (which is part of the public interface
documented in git-config.1).

This patch introduces a "gentle" form of xmmap which lets us
produce our own error message. We do not want to use mmap
directly, because we would like to use the other
compatibility elements of xmmap (e.g., handling 0-length
maps portably).

The end result is:

$ git.compile config --file=foo some.key value
error: unable to mmap 'foo': No such device
$ echo $?
3

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
config.c
git-compat-util.h
sha1_file.c
index dc7f8b2abc8f994ea7045bdec827a07ef9d2a847..d348d792aabb442981ea407be064815b3d8157c6 100644 (file)
--- a/config.c
+++ b/config.c
@@ -2048,8 +2048,15 @@ int git_config_set_multivar_in_file(const char *config_filename,
 
                fstat(in_fd, &st);
                contents_sz = xsize_t(st.st_size);
-               contents = xmmap(NULL, contents_sz, PROT_READ,
-                       MAP_PRIVATE, in_fd, 0);
+               contents = xmmap_gently(NULL, contents_sz, PROT_READ,
+                                       MAP_PRIVATE, in_fd, 0);
+               if (contents == MAP_FAILED) {
+                       error("unable to mmap '%s': %s",
+                             config_filename, strerror(errno));
+                       ret = CONFIG_INVALID_FILE;
+                       contents = NULL;
+                       goto out_free;
+               }
                close(in_fd);
 
                if (chmod(lock->filename.buf, st.st_mode & 07777) < 0) {
index 400e92108687e31dd16fbcea1a43e04556b98566..dc1948aab0e28a48f2d6de47c631a55ca3da2333 100644 (file)
@@ -623,6 +623,7 @@ extern char *xstrndup(const char *str, size_t len);
 extern void *xrealloc(void *ptr, size_t size);
 extern void *xcalloc(size_t nmemb, size_t size);
 extern void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+extern void *xmmap_gently(void *start, size_t length, int prot, int flags, int fd, off_t offset);
 extern ssize_t xread(int fd, void *buf, size_t len);
 extern ssize_t xwrite(int fd, const void *buf, size_t len);
 extern ssize_t xpread(int fd, void *buf, size_t len, off_t offset);
index d7f1838c13f5a88448d0f2034347bfb6482b3edf..ca491ab8bb8d2f28c5d88e52c54f50bfda4123ff 100644 (file)
@@ -707,8 +707,8 @@ static void mmap_limit_check(size_t length)
                    (uintmax_t)length, (uintmax_t)limit);
 }
 
-void *xmmap(void *start, size_t length,
-       int prot, int flags, int fd, off_t offset)
+void *xmmap_gently(void *start, size_t length,
+                 int prot, int flags, int fd, off_t offset)
 {
        void *ret;
 
@@ -719,12 +719,19 @@ void *xmmap(void *start, size_t length,
                        return NULL;
                release_pack_memory(length);
                ret = mmap(start, length, prot, flags, fd, offset);
-               if (ret == MAP_FAILED)
-                       die_errno("Out of memory? mmap failed");
        }
        return ret;
 }
 
+void *xmmap(void *start, size_t length,
+       int prot, int flags, int fd, off_t offset)
+{
+       void *ret = xmmap_gently(start, length, prot, flags, fd, offset);
+       if (ret == MAP_FAILED)
+               die_errno("Out of memory? mmap failed");
+       return ret;
+}
+
 void close_pack_windows(struct packed_git *p)
 {
        while (p->windows) {