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 37 #include "ioctl_iocdef.h" 38 39 struct ioctlent { 40 const char *info; 41 const char *name; 42 unsigned int dir; 43 unsigned int type_nr; 44 unsigned int size; 45 }; 46 47 static int 48 is_prefix(const char *s1, const char *s2) 49 { 50 size_t len = strlen(s1); 51 52 if (len > strlen(s2)) 53 return 0; 54 return !memcmp(s1, s2, len); 55 } 56 57 static int 58 compare_name_info(const void* a, const void* b) 59 { 60 int rc; 61 62 const char *name1 = ((struct ioctlent *) a)->name; 63 const char *name2 = ((struct ioctlent *) b)->name; 64 const char *info1 = ((struct ioctlent *) a)->info; 65 const char *info2 = ((struct ioctlent *) b)->info; 66 67 rc = strcmp(name1, name2); 68 if (rc) 69 return rc; 70 71 /* 72 * exception from lexicographical order: 73 * "asm/" < "asm-generic/" 74 */ 75 if (is_prefix("asm/", info1) && 76 is_prefix("asm-generic/", info2)) 77 return -1; 78 79 if (is_prefix("asm/", info2) && 80 is_prefix("asm-generic/", info1)) 81 return 1; 82 83 return strcmp(info1, info2); 84 } 85 86 static unsigned int 87 code(const struct ioctlent *e) 88 { 89 return e->type_nr | 90 (e->size << _IOC_SIZESHIFT) | 91 (e->dir << _IOC_DIRSHIFT); 92 } 93 94 static int 95 compare_code_name(const void* a, const void* b) 96 { 97 unsigned int code1 = code((struct ioctlent *) a); 98 unsigned int code2 = code((struct ioctlent *) b); 99 const char *name1 = ((struct ioctlent *) a)->name; 100 const char *name2 = ((struct ioctlent *) b)->name; 101 return (code1 > code2) ? 102 1 : (code1 < code2) ? -1 : strcmp(name1, name2); 103 } 104 105 static void 106 ioctlsort(struct ioctlent *ioctls, size_t nioctls) 107 { 108 size_t i; 109 110 qsort(ioctls, nioctls, sizeof(ioctls[0]), compare_name_info); 111 112 for (i = 1; i < nioctls; ++i) 113 if (!strcmp(ioctls[i-1].name, ioctls[i].name)) { 114 /* 115 * If there are multiple definitions for the same 116 * name, keep the first one and mark all the rest 117 * for deletion. 118 */ 119 ioctls[i].info = NULL; 120 } 121 122 for (i = 1; i < nioctls; ++i) 123 if (!ioctls[i].info) { 124 /* 125 * Change ioctl code of marked elements 126 * to make them sorted to the end of array. 127 */ 128 ioctls[i].dir = 129 ioctls[i].type_nr = 130 ioctls[i].size = 0xffffffffu; 131 } 132 133 qsort(ioctls, nioctls, sizeof(ioctls[0]), compare_code_name); 134 135 puts("/* Generated by ioctlsort. */"); 136 for (i = 0; i < nioctls; ++i) { 137 if (!ioctls[i].info) { 138 /* 139 * We've reached the first element marked for deletion. 140 */ 141 break; 142 } 143 if (i == 0 || code(&ioctls[i-1]) != code(&ioctls[i]) || 144 !is_prefix(ioctls[i-1].name, ioctls[i].name)) 145 printf("{ \"%s\", %#010x },\n", 146 ioctls[i].name, code(ioctls+i)); 147 } 148 } 149 150 static struct ioctlent ioctls[] = { 151 #ifdef IOCTLSORT_INC 152 # include IOCTLSORT_INC 153 #else 154 # include "ioctls_arch.h" 155 # include "ioctls_inc.h" 156 #endif 157 }; 158 159 int 160 main(void) 161 { 162 ioctlsort(ioctls, sizeof(ioctls) / sizeof(ioctls[0])); 163 return 0; 164 } 165