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 */  | 
