From 3ff53df7b4cbc331d302181d2d6644f4cb860a52 Mon Sep 17 00:00:00 2001 From: Paul Tan Date: Tue, 4 Aug 2015 21:51:22 +0800 Subject: [PATCH] wrapper: implement xopen() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A common usage pattern of open() is to check if it was successful, and die() if it was not: int fd = open(path, O_WRONLY | O_CREAT, 0777); if (fd < 0) die_errno(_("Could not open '%s' for writing."), path); Implement a wrapper function xopen() that does the above so that we can save a few lines of code, and make the die() messages consistent. Helped-by: Torsten Bögershausen Helped-by: Jeff King Helped-by: Johannes Schindelin Helped-by: Junio C Hamano Signed-off-by: Paul Tan Signed-off-by: Junio C Hamano --- git-compat-util.h | 1 + wrapper.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/git-compat-util.h b/git-compat-util.h index c6d391f864..e168dfd68b 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -717,6 +717,7 @@ 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 int xopen(const char *path, int flags, ...); 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); diff --git a/wrapper.c b/wrapper.c index ff49807948..0a4502d232 100644 --- a/wrapper.c +++ b/wrapper.c @@ -189,6 +189,41 @@ void *xcalloc(size_t nmemb, size_t size) # endif #endif +/** + * xopen() is the same as open(), but it die()s if the open() fails. + */ +int xopen(const char *path, int oflag, ...) +{ + mode_t mode = 0; + va_list ap; + + /* + * va_arg() will have undefined behavior if the specified type is not + * compatible with the argument type. Since integers are promoted to + * ints, we fetch the next argument as an int, and then cast it to a + * mode_t to avoid undefined behavior. + */ + va_start(ap, oflag); + if (oflag & O_CREAT) + mode = va_arg(ap, int); + va_end(ap); + + for (;;) { + int fd = open(path, oflag, mode); + if (fd >= 0) + return fd; + if (errno == EINTR) + continue; + + if ((oflag & O_RDWR) == O_RDWR) + die_errno(_("could not open '%s' for reading and writing"), path); + else if ((oflag & O_WRONLY) == O_WRONLY) + die_errno(_("could not open '%s' for writing"), path); + else + die_errno(_("could not open '%s' for reading"), path); + } +} + /* * xread() is the same a read(), but it automatically restarts read() * operations with a recoverable error (EAGAIN and EINTR). xread()