1 /* 2 * Copyright (c) 2001 Wichert Akkerman <wichert (at) cistron.nl> 3 * Copyright (c) 2004-2015 Dmitry V. Levin <ldv (at) altlinux.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifdef HAVE_CONFIG_H 30 # include "config.h" 31 #endif 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <linux/ioctl.h> 37 38 struct ioctlent { 39 const char *info; 40 const char *name; 41 unsigned int dir; 42 unsigned int type_nr; 43 unsigned int size; 44 }; 45 46 static int 47 is_prefix(const char *s1, const char *s2) 48 { 49 size_t len = strlen(s1); 50 51 if (len > strlen(s2)) 52 return 0; 53 return !memcmp(s1, s2, len); 54 } 55 56 static int 57 compare_name_info(const void* a, const void* b) 58 { 59 int rc; 60 61 const char *name1 = ((struct ioctlent *) a)->name; 62 const char *name2 = ((struct ioctlent *) b)->name; 63 const char *info1 = ((struct ioctlent *) a)->info; 64 const char *info2 = ((struct ioctlent *) b)->info; 65 66 rc = strcmp(name1, name2); 67 if (rc) 68 return rc; 69 70 /* 71 * exception from lexicographical order: 72 * "asm/" < "asm-generic/" 73 */ 74 if (is_prefix("asm/", info1) && 75 is_prefix("asm-generic/", info2)) 76 return -1; 77 78 if (is_prefix("asm/", info2) && 79 is_prefix("asm-generic/", info1)) 80 return 1; 81 82 return strcmp(info1, info2); 83 } 84 85 static unsigned int 86 code(const struct ioctlent *e) 87 { 88 return e->type_nr | 89 (e->size << _IOC_SIZESHIFT) | 90 (e->dir << _IOC_DIRSHIFT); 91 } 92 93 static int 94 compare_code_name(const void* a, const void* b) 95 { 96 unsigned int code1 = code((struct ioctlent *) a); 97 unsigned int code2 = code((struct ioctlent *) b); 98 const char *name1 = ((struct ioctlent *) a)->name; 99 const char *name2 = ((struct ioctlent *) b)->name; 100 return (code1 > code2) ? 101 1 : (code1 < code2) ? -1 : strcmp(name1, name2); 102 } 103 104 static void 105 ioctlsort(struct ioctlent *ioctls, size_t nioctls) 106 { 107 size_t i; 108 109 qsort(ioctls, nioctls, sizeof(ioctls[0]), compare_name_info); 110 111 for (i = 1; i < nioctls; ++i) 112 if (!strcmp(ioctls[i-1].name, ioctls[i].name)) { 113 /* 114 * If there are multiple definitions for the same 115 * name, keep the first one and mark all the rest 116 * for deletion. 117 */ 118 ioctls[i].info = NULL; 119 } 120 121 for (i = 1; i < nioctls; ++i) 122 if (!ioctls[i].info) { 123 /* 124 * Change ioctl code of marked elements 125 * to make them sorted to the end of array. 126 */ 127 ioctls[i].dir = 128 ioctls[i].type_nr = 129 ioctls[i].size = 0xffffffffu; 130 } 131 132 qsort(ioctls, nioctls, sizeof(ioctls[0]), compare_code_name); 133 134 puts("/* Generated by ioctlsort. */"); 135 for (i = 0; i < nioctls; ++i) { 136 if (!ioctls[i].info) { 137 /* 138 * We've reached the first element marked for deletion. 139 */ 140 break; 141 } 142 if (i == 0 || code(&ioctls[i-1]) != code(&ioctls[i]) || 143 !is_prefix(ioctls[i-1].name, ioctls[i].name)) 144 printf("{ \"%s\", %#010x },\n", 145 ioctls[i].name, code(ioctls+i)); 146 } 147 } 148 149 static struct ioctlent ioctls[] = { 150 #ifdef IOCTLSORT_INC 151 # include IOCTLSORT_INC 152 #else 153 # include "ioctls_arch.h" 154 # include "ioctls_inc.h" 155 #endif 156 }; 157 158 int 159 main(void) 160 { 161 ioctlsort(ioctls, sizeof(ioctls) / sizeof(ioctls[0])); 162 return 0; 163 } 164