summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Fries2014-10-06 11:24:54 -0500
committerElliott Hughes2015-04-01 17:46:20 -0500
commit4868b07931f02d4e89e4f4f8042bb5ed660aeab5 (patch)
treec34cfddeef6955cfa9f2d567f931c3601c2325bc
parent3891cfef5e27da0f33ccab42e9a14cc1e38331ee (diff)
downloadplatform-system-core-4868b07931f02d4e89e4f4f8042bb5ed660aeab5.tar.gz
platform-system-core-4868b07931f02d4e89e4f4f8042bb5ed660aeab5.tar.xz
platform-system-core-4868b07931f02d4e89e4f4f8042bb5ed660aeab5.zip
toolbox: ioctl: fix signedness on ioctl_nr
ioctl_nr is passed signed to the kernel, but many users refer to ioctl's in unsigned 32 bit notation. Let's use stroll to set it, to let people specify either negative numbers or large positive numbers. Also improve error reporting. Reported-By: Alex Piliev <ktnr74@motorola.com> Change-Id: I789434895b70b051d4d5c1a5db566a1925478ef0
-rw-r--r--toolbox/ioctl.c145
1 files changed, 96 insertions, 49 deletions
diff --git a/toolbox/ioctl.c b/toolbox/ioctl.c
index d1cc14a08..093e467de 100644
--- a/toolbox/ioctl.c
+++ b/toolbox/ioctl.c
@@ -1,36 +1,81 @@
1#include <stdio.h> 1/*
2#include <stdlib.h> 2 * Copyright (c) 2008, The Android Open Source Project
3#include <stdint.h> 3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google, Inc. nor the names of its contributors
15 * may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <errno.h>
33#include <error.h>
4#include <fcntl.h> 34#include <fcntl.h>
5#include <getopt.h> 35#include <getopt.h>
36#include <stdio.h>
37#include <stdint.h>
38#include <stdlib.h>
6#include <string.h> 39#include <string.h>
7#include <linux/kd.h>
8#include <linux/vt.h>
9#include <errno.h>
10#include <pthread.h>
11#include <sys/ioctl.h> 40#include <sys/ioctl.h>
12#include <unistd.h> 41#include <unistd.h>
13 42
14int ioctl_main(int argc, char *argv[]) 43static void usage() {
15{ 44 fprintf(stderr, "%s [-l <length>] [-a <argsize>] [-rdh] <device> <ioctlnr>\n"
16 int c; 45 " -l <length> Length of io buffer\n"
17 int fd; 46 " -a <argsize> Size of each argument (1-8)\n"
18 int res; 47 " -r Open device in read only mode\n"
48 " -d Direct argument (no iobuffer)\n"
49 " -h Print help\n", getprogname());
50 exit(1);
51}
52
53static int xstrtoi(const char* s, const char* what) {
54 char* endp;
55 errno = 0;
56 long result = strtol(s, &endp, 0);
57 if (errno != 0 || *endp != '\0') {
58 error(1, errno, "couldn't parse %s '%s'", what, s);
59 }
60 if (result > INT_MAX || result < INT_MIN) {
61 error(1, errno, "%s '%s' out of range", what, s);
62 }
63 return result;
64}
19 65
66int ioctl_main(int argc, char* argv[]) {
20 int read_only = 0; 67 int read_only = 0;
21 int length = -1; 68 int length = -1;
22 int arg_size = 4; 69 int arg_size = 4;
23 int direct_arg = 0; 70 int direct_arg = 0;
24 uint32_t ioctl_nr; 71
25 void *ioctl_args = NULL; 72 void *ioctl_args = NULL;
26 uint8_t *ioctl_argp; 73 uint8_t *ioctl_argp;
27 uint8_t *ioctl_argp_save = NULL; 74 uint8_t *ioctl_argp_save = NULL;
28 int rem; 75 int rem;
29 76
30 do { 77 int c;
31 c = getopt(argc, argv, "rdl:a:h"); 78 while ((c = getopt(argc, argv, "rdl:a:h")) != -1) {
32 if (c == EOF)
33 break;
34 switch (c) { 79 switch (c) {
35 case 'r': 80 case 'r':
36 read_only = 1; 81 read_only = 1;
@@ -39,43 +84,44 @@ int ioctl_main(int argc, char *argv[])
39 direct_arg = 1; 84 direct_arg = 1;
40 break; 85 break;
41 case 'l': 86 case 'l':
42 length = strtol(optarg, NULL, 0); 87 length = xstrtoi(optarg, "length");
43 break; 88 break;
44 case 'a': 89 case 'a':
45 arg_size = strtol(optarg, NULL, 0); 90 arg_size = xstrtoi(optarg, "argument size");
46 break; 91 break;
47 case 'h': 92 case 'h':
48 fprintf(stderr, "%s [-l <length>] [-a <argsize>] [-rdh] <device> <ioctlnr>\n" 93 usage();
49 " -l <length> Length of io buffer\n" 94 break;
50 " -a <argsize> Size of each argument (1-8)\n" 95 default:
51 " -r Open device in read only mode\n" 96 error(1, 0, "invalid option -%c", optopt);
52 " -d Direct argument (no iobuffer)\n"
53 " -h Print help\n", argv[0]);
54 return -1;
55 case '?':
56 fprintf(stderr, "%s: invalid option -%c\n",
57 argv[0], optopt);
58 exit(1);
59 } 97 }
60 } while (1); 98 }
61 99
62 if(optind + 2 > argc) { 100 if (optind + 2 > argc) {
63 fprintf(stderr, "%s: too few arguments\n", argv[0]); 101 usage();
64 exit(1);
65 } 102 }
66 103
67 if (!strcmp(argv[optind], "-")) { 104 const char* device = argv[optind];
105 int fd;
106 if (strcmp(device, "-") == 0) {
68 fd = STDIN_FILENO; 107 fd = STDIN_FILENO;
69 } else { 108 } else {
70 fd = open(argv[optind], read_only ? O_RDONLY : (O_RDWR | O_SYNC)); 109 fd = open(device, read_only ? O_RDONLY : (O_RDWR | O_SYNC));
71 if (fd < 0) { 110 if (fd == -1) {
72 fprintf(stderr, "cannot open %s\n", argv[optind]); 111 error(1, errno, "cannot open %s", argv[optind]);
73 return 1;
74 } 112 }
75 } 113 }
76 optind++; 114 optind++;
77 115
78 ioctl_nr = strtol(argv[optind], NULL, 0); 116 // IOCTL(2) wants second parameter as a signed int.
117 // Let's let the user specify either negative numbers or large positive
118 // numbers, for the case where ioctl number is larger than INT_MAX.
119 errno = 0;
120 char* endp;
121 int ioctl_nr = UINT_MAX & strtoll(argv[optind], &endp, 0);
122 if (errno != 0 || *endp != '\0') {
123 error(1, errno, "couldn't parse ioctl number '%s'", argv[optind]);
124 }
79 optind++; 125 optind++;
80 126
81 if(direct_arg) { 127 if(direct_arg) {
@@ -91,11 +137,10 @@ int ioctl_main(int argc, char *argv[])
91 137
92 ioctl_argp_save = ioctl_argp = ioctl_args; 138 ioctl_argp_save = ioctl_argp = ioctl_args;
93 rem = length; 139 rem = length;
94 while(optind < argc) { 140 while (optind < argc) {
95 uint64_t tmp = strtoull(argv[optind], NULL, 0); 141 uint64_t tmp = strtoull(argv[optind], NULL, 0);
96 if(rem < arg_size) { 142 if (rem < arg_size) {
97 fprintf(stderr, "%s: too many arguments\n", argv[0]); 143 error(1, 0, "too many arguments");
98 exit(1);
99 } 144 }
100 memcpy(ioctl_argp, &tmp, arg_size); 145 memcpy(ioctl_argp, &tmp, arg_size);
101 ioctl_argp += arg_size; 146 ioctl_argp += arg_size;
@@ -108,8 +153,9 @@ int ioctl_main(int argc, char *argv[])
108 while(rem--) { 153 while(rem--) {
109 printf(" 0x%02x", *ioctl_argp_save++); 154 printf(" 0x%02x", *ioctl_argp_save++);
110 } 155 }
111 printf("\n"); 156 printf(" to %s\n", device);
112 157
158 int res;
113 if(direct_arg) 159 if(direct_arg)
114 res = ioctl(fd, ioctl_nr, *(uint32_t*)ioctl_args); 160 res = ioctl(fd, ioctl_nr, *(uint32_t*)ioctl_args);
115 else if(length) 161 else if(length)
@@ -118,10 +164,10 @@ int ioctl_main(int argc, char *argv[])
118 res = ioctl(fd, ioctl_nr, 0); 164 res = ioctl(fd, ioctl_nr, 0);
119 if (res < 0) { 165 if (res < 0) {
120 free(ioctl_args); 166 free(ioctl_args);
121 fprintf(stderr, "ioctl 0x%x failed, %d\n", ioctl_nr, res); 167 error(1, errno, "ioctl 0x%x failed (returned %d)", ioctl_nr, res);
122 return 1;
123 } 168 }
124 if(length) { 169
170 if (length) {
125 printf("return buf:"); 171 printf("return buf:");
126 ioctl_argp = ioctl_args; 172 ioctl_argp = ioctl_args;
127 rem = length; 173 rem = length;
@@ -131,5 +177,6 @@ int ioctl_main(int argc, char *argv[])
131 printf("\n"); 177 printf("\n");
132 } 178 }
133 free(ioctl_args); 179 free(ioctl_args);
180 close(fd);
134 return 0; 181 return 0;
135} 182}