You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
4.3 KiB
165 lines
4.3 KiB
/* |
|
* Copyright (c) 2001 Wichert Akkerman <wichert@cistron.nl> |
|
* Copyright (c) 2004-2015 Dmitry V. Levin <ldv@altlinux.org> |
|
* Copyright (c) 1999-2017 The strace developers. |
|
* All rights reserved. |
|
* |
|
* Redistribution and use in source and binary forms, with or without |
|
* modification, are permitted provided that the following conditions |
|
* are met: |
|
* 1. Redistributions of source code must retain the above copyright |
|
* notice, this list of conditions and the following disclaimer. |
|
* 2. 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. |
|
* 3. The name of the author may not be used to endorse or promote products |
|
* derived from this software without specific prior written permission. |
|
* |
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. |
|
*/ |
|
|
|
#ifdef HAVE_CONFIG_H |
|
# include "config.h" |
|
#endif |
|
|
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
|
|
#include "ioctl_iocdef.h" |
|
|
|
struct ioctlent { |
|
const char *info; |
|
const char *name; |
|
unsigned int dir; |
|
unsigned int type_nr; |
|
unsigned int size; |
|
}; |
|
|
|
static int |
|
is_prefix(const char *s1, const char *s2) |
|
{ |
|
size_t len = strlen(s1); |
|
|
|
if (len > strlen(s2)) |
|
return 0; |
|
return !memcmp(s1, s2, len); |
|
} |
|
|
|
static int |
|
compare_name_info(const void *a, const void *b) |
|
{ |
|
int rc; |
|
|
|
const char *name1 = ((struct ioctlent *) a)->name; |
|
const char *name2 = ((struct ioctlent *) b)->name; |
|
const char *info1 = ((struct ioctlent *) a)->info; |
|
const char *info2 = ((struct ioctlent *) b)->info; |
|
|
|
rc = strcmp(name1, name2); |
|
if (rc) |
|
return rc; |
|
|
|
/* |
|
* exception from lexicographical order: |
|
* "asm/" < "asm-generic/" |
|
*/ |
|
if (is_prefix("asm/", info1) && |
|
is_prefix("asm-generic/", info2)) |
|
return -1; |
|
|
|
if (is_prefix("asm/", info2) && |
|
is_prefix("asm-generic/", info1)) |
|
return 1; |
|
|
|
return strcmp(info1, info2); |
|
} |
|
|
|
static unsigned int |
|
code(const struct ioctlent *e) |
|
{ |
|
return e->type_nr | |
|
(e->size << _IOC_SIZESHIFT) | |
|
(e->dir << _IOC_DIRSHIFT); |
|
} |
|
|
|
static int |
|
compare_code_name(const void *a, const void *b) |
|
{ |
|
unsigned int code1 = code((struct ioctlent *) a); |
|
unsigned int code2 = code((struct ioctlent *) b); |
|
const char *name1 = ((struct ioctlent *) a)->name; |
|
const char *name2 = ((struct ioctlent *) b)->name; |
|
return (code1 > code2) ? |
|
1 : (code1 < code2) ? -1 : strcmp(name1, name2); |
|
} |
|
|
|
static void |
|
ioctlsort(struct ioctlent *ioctls, size_t nioctls) |
|
{ |
|
size_t i; |
|
|
|
qsort(ioctls, nioctls, sizeof(ioctls[0]), compare_name_info); |
|
|
|
for (i = 1; i < nioctls; ++i) |
|
if (!strcmp(ioctls[i-1].name, ioctls[i].name)) { |
|
/* |
|
* If there are multiple definitions for the same |
|
* name, keep the first one and mark all the rest |
|
* for deletion. |
|
*/ |
|
ioctls[i].info = NULL; |
|
} |
|
|
|
for (i = 1; i < nioctls; ++i) |
|
if (!ioctls[i].info) { |
|
/* |
|
* Change ioctl code of marked elements |
|
* to make them sorted to the end of array. |
|
*/ |
|
ioctls[i].dir = |
|
ioctls[i].type_nr = |
|
ioctls[i].size = 0xffffffffu; |
|
} |
|
|
|
qsort(ioctls, nioctls, sizeof(ioctls[0]), compare_code_name); |
|
|
|
puts("/* Generated by ioctlsort. */"); |
|
for (i = 0; i < nioctls; ++i) { |
|
if (!ioctls[i].info) { |
|
/* |
|
* We've reached the first element marked for deletion. |
|
*/ |
|
break; |
|
} |
|
if (i == 0 || code(&ioctls[i-1]) != code(&ioctls[i]) || |
|
!is_prefix(ioctls[i-1].name, ioctls[i].name)) |
|
printf("{ \"%s\", %#010x },\n", |
|
ioctls[i].name, code(ioctls+i)); |
|
} |
|
} |
|
|
|
static struct ioctlent ioctls[] = { |
|
#ifdef IOCTLSORT_INC |
|
# include IOCTLSORT_INC |
|
#else |
|
# include "ioctls_arch.h" |
|
# include "ioctls_inc.h" |
|
#endif |
|
}; |
|
|
|
int |
|
main(void) |
|
{ |
|
ioctlsort(ioctls, sizeof(ioctls) / sizeof(ioctls[0])); |
|
return 0; |
|
}
|
|
|