diff options
author | Tomasz Kramkowski <tk@the-tk.com> | 2017-02-11 15:30:37 +0000 |
---|---|---|
committer | Tomasz Kramkowski <tk@the-tk.com> | 2017-02-11 15:30:37 +0000 |
commit | b8ede3c284299173f3981aa85dcbd16806a57f55 (patch) | |
tree | 31beb63b99f1840472da304de628e6114ba61f8e | |
parent | 99778c999c364ad3e5967f7a9a0a3e484c279716 (diff) | |
parent | 0fc0c19e4dc2b4ec2f175744e1ac468643b6da71 (diff) | |
download | hktool-b8ede3c284299173f3981aa85dcbd16806a57f55.tar.gz hktool-b8ede3c284299173f3981aa85dcbd16806a57f55.tar.xz hktool-b8ede3c284299173f3981aa85dcbd16806a57f55.zip |
Merge branch 'halfkay-error-handling'
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | eprintf.c | 21 | ||||
-rw-r--r-- | eprintf.h | 9 | ||||
-rw-r--r-- | halfkay.c | 70 | ||||
-rw-r--r-- | hktool.c | 12 | ||||
-rw-r--r-- | log.c | 99 | ||||
-rw-r--r-- | log.h | 42 | ||||
-rw-r--r-- | util.c | 88 | ||||
-rw-r--r-- | util.h | 6 |
9 files changed, 78 insertions, 271 deletions
@@ -15,7 +15,7 @@ CFLAGS = -std=c11 -O2 -flto $(WARNINGS) -MMD -MP $(shell $(PKG_CONFIG) --cflags LDFLAGS = -Wl,--as-needed -O2 -flto LDLIBS = $(shell $(PKG_CONFIG) --libs $(LIBS)) -OBJ := hktool.o halfkay.o log.o params.o util.o eprintf.o +OBJ := hktool.o halfkay.o params.o util.o eprintf.o PREFIX ?= /usr/local @@ -1,9 +1,10 @@ +#include <assert.h> #include <errno.h> #include <stdarg.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <stdint.h> #include "eprintf.h" @@ -15,6 +16,8 @@ void eprintf(const char *fmt, ...) int errnum = errno; va_list va; + assert(fmt); + if (progname() != NULL) fprintf(stderr, "%s: ", progname()); @@ -35,6 +38,8 @@ void weprintf(const char *fmt, ...) int errnum = errno; va_list va; + assert(fmt); + if (progname() != NULL) fprintf(stderr, "%s: ", progname()); @@ -53,6 +58,8 @@ char *estrdup(const char *s) size_t len; char *dup; + assert(s); + len = strlen(s); if (len == SIZE_MAX) eprintf("estrdup(\"%.20s\") failed: Too long", s); @@ -76,6 +83,18 @@ void *emalloc(size_t n) return p; } +/* ecalloc: attempt to allocate memory or exit on error */ +void *ecalloc(size_t nmemb, size_t size) +{ + void *p; + + p = calloc(nmemb, size); + if (p == NULL) + eprintf("ecalloc(%zu, %zu) failed:", nmemb, size); + + return p; +} + /* erealloc: attempt to reallocate memory or exit on error */ void *erealloc(void *p, size_t n) { @@ -6,10 +6,11 @@ noreturn void eprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void weprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); -char *estrdup(const char *); -void *emalloc(size_t); -void *erealloc(void *, size_t); +char *estrdup(const char *str); +void *emalloc(size_t size); +void *ecalloc(size_t nmemb, size_t size); +void *erealloc(void *p, size_t size); char *progname(void); -void setprogname(const char *); +void setprogname(const char *name); #endif /* !EPRINTF_H */ @@ -28,7 +28,7 @@ #include <unistd.h> #include "halfkay.h" -#include "log.h" +#include "eprintf.h" enum { HK_USB_VID = 0x16c0, @@ -40,28 +40,33 @@ enum { HK_USB_VAL = 0x200, TIMEOUT = 2000, TIMEOUT_FIRST = 3000, - TRANS_DELAY = 4000, - TRANS_ATTEMPTS = 10, + SEND_DELAY = 4000, + SEND_ATTEMPTS = 10, + REBOOTCMD_WIDTH = 3, + REBOOTCMD_FILL = 0xff, }; libusb_device_handle *hk_usb_hnd; static inline void libusb_err(const char *action, int code) { - error(0, "libusb %s failed: %s", action, libusb_strerror(code)); + eprintf("libusb %s failed: %s", action, libusb_strerror(code)); } static void usbopen(void) { int rc; + if (hk_usb_hnd != NULL) + return; + rc = libusb_init(NULL); if (libusb_init(NULL) != LIBUSB_SUCCESS) libusb_err("init", rc); hk_usb_hnd = libusb_open_device_with_vid_pid(NULL, HK_USB_VID, HK_USB_PID); if (!hk_usb_hnd) - error(0, "HalfKay device not found"); + eprintf("HalfKay device not found"); libusb_set_auto_detach_kernel_driver(hk_usb_hnd, 1); rc = libusb_claim_interface(hk_usb_hnd, 0); @@ -71,23 +76,28 @@ static void usbopen(void) static void usbclose(void) { + if (hk_usb_hnd == NULL) + return; + libusb_release_interface(hk_usb_hnd, 0); libusb_close(hk_usb_hnd); libusb_exit(NULL); + + hk_usb_hnd = NULL; } static void usbsendcmd(void *data, size_t size, bool firstxfer) { unsigned int timeout = firstxfer ? TIMEOUT_FIRST : TIMEOUT; int rc, attempt = 0; - useconds_t delay = TRANS_DELAY; + useconds_t delay = SEND_DELAY; do { rc = libusb_control_transfer(hk_usb_hnd, HK_USB_REQTYP, HK_USB_REQ, HK_USB_VAL, 0, data, size, timeout); usleep(delay); delay *= 2; - } while (rc == LIBUSB_ERROR_PIPE && ++attempt < TRANS_ATTEMPTS); + } while (rc == LIBUSB_ERROR_PIPE && ++attempt < SEND_ATTEMPTS); if (rc < 0) libusb_err("transfer", rc); @@ -98,6 +108,9 @@ static void fmtcmd(void *_dest, const struct flashparams *fp, size_t addr) static const size_t MAX_SHIFT = sizeof addr * CHAR_BIT / 8; unsigned char *dest = _dest; + assert(dest); + assert(fp); + addr >>= fp->addrshft; for (size_t i = 0; i < fp->cmdsz && i < MAX_SHIFT; i++) dest[i] = (addr >> (i * 8)) & 0xFF; @@ -109,24 +122,18 @@ int flash(const struct flashparams *fp, const char *file) unsigned char *cmd; size_t tsize; + assert(fp); + assert(fp->blksz && (fp->blksz & (fp->blksz - 1)) == 0); + assert(fp->memsz % fp->blksz == 0); + assert(SIZE_MAX - fp->blksz >= fp->cmdsz); assert(file); - /* TODO: move checks to parser */ - /*if (!fp->blksz || !(fp->blksz & fp->blksz - 1))*/ - /*error(0, "Block size is not a power of 2");*/ - /*if (fp->memsz % fp->blksz)*/ - /*error(0, "Memory size is not divisible by block size");*/ - - tsize = fp->blksz + fp->cmdsz; - f = fopen(file, "rb"); if (!f) - error(errno, EMSG_OPEN, file); + eprintf("Could not open '%s':", file); - /* TODO: precalc and check ovf */ - cmd = malloc(tsize); - if (!cmd) - error(errno, EMSG_ALLOC); + tsize = fp->blksz + fp->cmdsz; + cmd = emalloc(tsize); usbopen(); @@ -135,17 +142,18 @@ int flash(const struct flashparams *fp, const char *file) fmtcmd(cmd, fp, blkaddr); count = fread(cmd + fp->cmdsz, 1, fp->blksz, f); + if (count != fp->blksz && ferror(f)) + eprintf("Error while reading '%s', short read", file); if (count == 0) break; - if (count < fp->blksz) { + if (count < fp->blksz) memset(cmd + fp->cmdsz + count, 0, fp->blksz - count); - } usbsendcmd(cmd, tsize, blkaddr == 0); } if (!feof(f)) - fprintf(stderr, "Device ran out of space during writing!"); + weprintf("Device ran out of space during writing!"); usbclose(); @@ -157,10 +165,18 @@ int flash(const struct flashparams *fp, const char *file) int reboot(const struct flashparams *fp) { - size_t tsize = fp->blksz + fp->cmdsz; - unsigned char *cmd = malloc(tsize); - memset(cmd, 0x00, tsize - 3); - memset(cmd, 0xff, 3); + size_t tsize; + unsigned char *cmd; + + assert(fp); + assert(fp->blksz && (fp->blksz & (fp->blksz - 1)) == 0); + assert(fp->memsz % fp->blksz == 0); + assert(SIZE_MAX - fp->blksz >= fp->cmdsz); + + tsize = fp->blksz + fp->cmdsz; + cmd = ecalloc(tsize, 1); + + memset(cmd, REBOOTCMD_FILL, REBOOTCMD_WIDTH); usbopen(); usbsendcmd(cmd, tsize, true); @@ -24,7 +24,6 @@ #include <unistd.h> #include "halfkay.h" -#include "log.h" #include "eprintf.h" #include "params.h" @@ -67,8 +66,7 @@ int main(int argc, char **argv) int opt; struct flashparams fp; - argv0 = argv[0] != NULL ? argv[0] : "hktool"; - setprogname(argv0); + setprogname(argv[0] != NULL ? argv[0] : "hktool"); while (opt = getopt(argc, argv, "f:h-lvr"), opt != -1) { switch (opt) { @@ -97,18 +95,18 @@ int main(int argc, char **argv) return EXIT_FAILURE; break; default: - error(0, "getopt returned unexpected value"); + eprintf("getopt returned unexpected value"); } } if (optind >= argc) - error(0, "No MCU specified\nUsage: %s " USAGE, argv[0]); + eprintf("No MCU specified\nUsage: %s " USAGE, argv[0]); if (!doflash && !doreboot) - error(0, "Nothing to do"); + eprintf("Nothing to do"); if (argc - optind > 1) - error(0, "Invalid number of arguments\nUsage: %s " USAGE, argv[0]); + eprintf("Invalid number of arguments\nUsage: %s " USAGE, argv[0]); if (getparams(&fp, argv[optind]) != 0) return EXIT_FAILURE; @@ -1,99 +0,0 @@ -/* log.c -- Error and warning messages. - * - * Copyright (C) 2016 Tomasz Kramkowski <tk@the-tk.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#include <assert.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "log.h" - -const char *argv0; - -void error(int errnum, const char *fmt, ...) -{ - assert(fmt); - - va_list va; - - fprintf(stderr, "%s: error: ", argv0); - - va_start(va, fmt); - vfprintf(stderr, fmt, va); - va_end(va); - - if (errnum) - fprintf(stderr, ": %s", strerror(errnum)); - - fputc('\n', stderr); - - exit(EXIT_FAILURE); -} - -void errorat(int errnum, const char *file, long line, const char *fmt, ...) -{ - assert(file && fmt); - - va_list va; - - fprintf(stderr, "%s:%s:%ld: error: ", argv0, file, line); - - va_start(va, fmt); - vfprintf(stderr, fmt, va); - va_end(va); - - if (errnum) - fprintf(stderr, ": %s", strerror(errnum)); - - fputc('\n', stderr); - - exit(EXIT_FAILURE); -} - -void warning(int errnum, const char *fmt, ...) -{ - va_list ap; - - fprintf(stderr, "%s: warning: ", argv0); - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - if (errnum) - fprintf(stderr, ": %s", strerror(errnum)); - - fputc('\n', stderr); -} - -void warningat(int errnum, const char *file, long line, const char *fmt, ...) -{ - va_list ap; - - fprintf(stderr, "%s:%s:%ld: warning: ", argv0, file, line); - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - if (errnum) - fprintf(stderr, ": %s", strerror(errnum)); - - fputc('\n', stderr); -} @@ -1,42 +0,0 @@ -/* log.h -- Error and warning messages. - * - * Copyright (C) 2016 Tomasz Kramkowski <tk@the-tk.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef LOG_H -#define LOG_H - -#include <stdnoreturn.h> - -#define EMSG_ALLOC "Could not allocate memory" -#define EMSG_OPEN "Could not open '%s'" -#define EMSG_READ "Could not read '%s'" -#define EMSG_SZOP "Arithmetic operation on size_t would wrap" -#define EMSG_GNOMEM "A call to glob ran out of memory" - -extern const char *argv0; - -noreturn void error(int errnum, const char *fmt, ...) - __attribute__ ((format(printf, 2, 3))); -noreturn void errorat(int errnum, const char *file, long line, const char *fmt, ...) - __attribute__ ((format(printf, 4, 5))); - -void warning(int errnum, const char *fmt, ...) - __attribute__ ((format(printf, 2, 3))); -void warningat(int errnum, const char *file, long line, const char *fmt, ...) - __attribute__ ((format(printf, 4, 5))); - -#endif /* LOG_H */ @@ -15,23 +15,6 @@ * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Some contents of this file (indicated below) are based on work covered by - * the following copyright and permission notice: - * - * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <assert.h> #include <errno.h> @@ -41,81 +24,18 @@ #include <string.h> #include <ctype.h> -#include "log.h" +#include "eprintf.h" #include "util.h" -/* szadd: checked size_t addition */ -size_t szadd(size_t a, size_t b) -{ - if (SIZE_MAX - a < b) - error(0, EMSG_SZOP); - - return a + b; -} - -/* szmul: checked size_t multiplication - * License information can be found at the top of this file */ -size_t szmul(size_t a, size_t b) -{ -#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof (size_t) * 4)) - if ((a >= MUL_NO_OVERFLOW || b >= MUL_NO_OVERFLOW) && - a > 0 && SIZE_MAX / a < b) - error(0, EMSG_SZOP); -#undef MUL_NO_OVERFLOW - - return a * b; -} - /* xstrmalloc: allocate for a string (+1) or exit with error */ void *xstrmalloc(size_t size) { size_t nsize; - nsize = size + 1; - if (nsize < size) - error(0, EMSG_ALLOC); - - return xmalloc(nsize); -} - -/* xstrdup: duplicae string or exit with error */ -char *xstrdup(const char *s) -{ - char *ret; - - assert(s); - - ret = xstrmalloc(strlen(s)); - strcpy(ret, s); - - return ret; -} - -/* xrealloc: reallocate or exit with error */ -void *xrealloc(void *p, size_t size) -{ - p = realloc(p, size); - if (!p) - error(errno, EMSG_ALLOC); - - return p; -} - -/* xmalloc: allocate or exit with error */ -void *xmalloc(size_t size) -{ - return xrealloc(NULL, size); -} - -/* xstrcut: cut out a bit of a string into a new string */ -char *xstrcut(const char *s, size_t offt, size_t len) -{ - char *ret; - - ret = xstrmalloc(len); - strncpy(ret, s + offt, len + 1); + if (size == SIZE_MAX) + eprintf("xstrmalloc(%zu) failed: %zu == SIZE_MAX", size, size); - return ret; + return emalloc(nsize); } /* xstrcasecmp: case insensitive strcmp */ @@ -22,13 +22,7 @@ #include <stdbool.h> #include <stddef.h> -size_t szadd(size_t a, size_t b); -size_t szmul(size_t a, size_t b); void *xstrmalloc(size_t size); -char *xstrdup(const char *s); -void *xmalloc(size_t size); -void *xrealloc(void *p, size_t size); -char *xstrcut(const char *s, size_t offt, size_t len); int xstrcasecmp(const char *s1, const char *s2); #endif /* UTIL_H */ |