diff options
author | Elliott Hughes <enh@google.com> | 2015-04-02 17:22:23 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-04-02 17:22:23 +0000 |
commit | 27a158befa90fd8fb965091510d9a3e9079b04f4 (patch) | |
tree | 21ac9653d16034586bd81229c94888ba94ccfd30 | |
parent | c7cddffa14369265c82e5a08797f7ba687d174ef (diff) | |
parent | 4868b07931f02d4e89e4f4f8042bb5ed660aeab5 (diff) | |
download | system_core-27a158befa90fd8fb965091510d9a3e9079b04f4.zip system_core-27a158befa90fd8fb965091510d9a3e9079b04f4.tar.gz system_core-27a158befa90fd8fb965091510d9a3e9079b04f4.tar.bz2 |
Merge "toolbox: ioctl: fix signedness on ioctl_nr"
-rw-r--r-- | toolbox/ioctl.c | 145 |
1 files changed, 96 insertions, 49 deletions
diff --git a/toolbox/ioctl.c b/toolbox/ioctl.c index d1cc14a..093e467 100644 --- a/toolbox/ioctl.c +++ b/toolbox/ioctl.c @@ -1,36 +1,81 @@ -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> +/* + * Copyright (c) 2008, The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <errno.h> +#include <error.h> #include <fcntl.h> #include <getopt.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> #include <string.h> -#include <linux/kd.h> -#include <linux/vt.h> -#include <errno.h> -#include <pthread.h> #include <sys/ioctl.h> #include <unistd.h> -int ioctl_main(int argc, char *argv[]) -{ - int c; - int fd; - int res; +static void usage() { + fprintf(stderr, "%s [-l <length>] [-a <argsize>] [-rdh] <device> <ioctlnr>\n" + " -l <length> Length of io buffer\n" + " -a <argsize> Size of each argument (1-8)\n" + " -r Open device in read only mode\n" + " -d Direct argument (no iobuffer)\n" + " -h Print help\n", getprogname()); + exit(1); +} + +static int xstrtoi(const char* s, const char* what) { + char* endp; + errno = 0; + long result = strtol(s, &endp, 0); + if (errno != 0 || *endp != '\0') { + error(1, errno, "couldn't parse %s '%s'", what, s); + } + if (result > INT_MAX || result < INT_MIN) { + error(1, errno, "%s '%s' out of range", what, s); + } + return result; +} +int ioctl_main(int argc, char* argv[]) { int read_only = 0; int length = -1; int arg_size = 4; int direct_arg = 0; - uint32_t ioctl_nr; + void *ioctl_args = NULL; uint8_t *ioctl_argp; uint8_t *ioctl_argp_save = NULL; int rem; - do { - c = getopt(argc, argv, "rdl:a:h"); - if (c == EOF) - break; + int c; + while ((c = getopt(argc, argv, "rdl:a:h")) != -1) { switch (c) { case 'r': read_only = 1; @@ -39,43 +84,44 @@ int ioctl_main(int argc, char *argv[]) direct_arg = 1; break; case 'l': - length = strtol(optarg, NULL, 0); + length = xstrtoi(optarg, "length"); break; case 'a': - arg_size = strtol(optarg, NULL, 0); + arg_size = xstrtoi(optarg, "argument size"); break; case 'h': - fprintf(stderr, "%s [-l <length>] [-a <argsize>] [-rdh] <device> <ioctlnr>\n" - " -l <length> Length of io buffer\n" - " -a <argsize> Size of each argument (1-8)\n" - " -r Open device in read only mode\n" - " -d Direct argument (no iobuffer)\n" - " -h Print help\n", argv[0]); - return -1; - case '?': - fprintf(stderr, "%s: invalid option -%c\n", - argv[0], optopt); - exit(1); + usage(); + break; + default: + error(1, 0, "invalid option -%c", optopt); } - } while (1); + } - if(optind + 2 > argc) { - fprintf(stderr, "%s: too few arguments\n", argv[0]); - exit(1); + if (optind + 2 > argc) { + usage(); } - if (!strcmp(argv[optind], "-")) { + const char* device = argv[optind]; + int fd; + if (strcmp(device, "-") == 0) { fd = STDIN_FILENO; } else { - fd = open(argv[optind], read_only ? O_RDONLY : (O_RDWR | O_SYNC)); - if (fd < 0) { - fprintf(stderr, "cannot open %s\n", argv[optind]); - return 1; + fd = open(device, read_only ? O_RDONLY : (O_RDWR | O_SYNC)); + if (fd == -1) { + error(1, errno, "cannot open %s", argv[optind]); } } optind++; - - ioctl_nr = strtol(argv[optind], NULL, 0); + + // IOCTL(2) wants second parameter as a signed int. + // Let's let the user specify either negative numbers or large positive + // numbers, for the case where ioctl number is larger than INT_MAX. + errno = 0; + char* endp; + int ioctl_nr = UINT_MAX & strtoll(argv[optind], &endp, 0); + if (errno != 0 || *endp != '\0') { + error(1, errno, "couldn't parse ioctl number '%s'", argv[optind]); + } optind++; if(direct_arg) { @@ -91,11 +137,10 @@ int ioctl_main(int argc, char *argv[]) ioctl_argp_save = ioctl_argp = ioctl_args; rem = length; - while(optind < argc) { + while (optind < argc) { uint64_t tmp = strtoull(argv[optind], NULL, 0); - if(rem < arg_size) { - fprintf(stderr, "%s: too many arguments\n", argv[0]); - exit(1); + if (rem < arg_size) { + error(1, 0, "too many arguments"); } memcpy(ioctl_argp, &tmp, arg_size); ioctl_argp += arg_size; @@ -108,8 +153,9 @@ int ioctl_main(int argc, char *argv[]) while(rem--) { printf(" 0x%02x", *ioctl_argp_save++); } - printf("\n"); + printf(" to %s\n", device); + int res; if(direct_arg) res = ioctl(fd, ioctl_nr, *(uint32_t*)ioctl_args); else if(length) @@ -118,10 +164,10 @@ int ioctl_main(int argc, char *argv[]) res = ioctl(fd, ioctl_nr, 0); if (res < 0) { free(ioctl_args); - fprintf(stderr, "ioctl 0x%x failed, %d\n", ioctl_nr, res); - return 1; + error(1, errno, "ioctl 0x%x failed (returned %d)", ioctl_nr, res); } - if(length) { + + if (length) { printf("return buf:"); ioctl_argp = ioctl_args; rem = length; @@ -131,5 +177,6 @@ int ioctl_main(int argc, char *argv[]) printf("\n"); } free(ioctl_args); + close(fd); return 0; } |