blob: 7fff30311d0d0b5988b5d42aeb9290d864b0a5b8 [file] [log] [blame]
Dmitry V. Levindf7aa2b2015-01-19 17:02:16 +00001#!/bin/sh
2# Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
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# 1. Redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer.
10# 2. Redistributions in binary form must reproduce the above copyright
11# notice, this list of conditions and the following disclaimer in the
12# documentation and/or other materials provided with the distribution.
13# 3. The name of the author may not be used to endorse or promote products
14# derived from this software without specific prior written permission.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27set -efu
28
29# This script processes header files containing ioctl command definitions in
30# symbolic form, assuming that these definitions match the following regular
31# expressions:
32
33r_define='^[[:space:]]*#[[:space:]]*define[[:space:]]\+'
34r_cmd_name='[A-Z][A-Z0-9_]*'
35r_io='\([A-Z]\+\)\?_S\?\(IO\|IOW\|IOR\|IOWR\|IOC\)'
36r_value='[[:space:]]\+'"$r_io"'[[:space:]]*([^)]'
37regexp="${r_define}${r_cmd_name}${r_value}"
38
39me="${0##*/}"
40msg()
41{
42 printf >&2 '%s\n' "$me: $*"
43}
44
45prefix=
46case $# in
47 1) inc_dir="$1"; shift
48 ;;
49 2) inc_dir="$1"; shift
50 prefix="$1"; shift
51 ;;
52 *) echo >&2 "usage: $me include-directory [prefix]"
53 exit 1
54 ;;
55esac
56
57[ -z "$prefix" ] ||
58 prefix="${prefix%%/}/"
59
60tmpdir=
61cleanup()
62{
63 trap - EXIT
64 [ -z "$tmpdir" ] ||
65 rm -rf -- "$tmpdir"
66 exit "$@"
67}
68
69trap 'cleanup $?' EXIT
70trap 'cleanup 1' HUP PIPE INT QUIT TERM
71tmpdir="$(mktemp -dt "$me.XXXXXX")"
72
73# list interesting files in $inc_dir.
74cd "$inc_dir"
75inc_dir="$(pwd -P)"
76find . -type f -name '*.h' -print0 |
77 xargs -r0 grep -l "$r_value" -- > "$tmpdir"/headers1.list ||
78 exit 0
79cd - > /dev/null
80sed 's|^\./\(uapi/\)\?||' < "$tmpdir"/headers1.list > "$tmpdir"/headers.list
Dmitry V. Levin7e888962015-05-19 18:00:07 +000081LC_COLLATE=C sort -u -o "$tmpdir"/headers.list "$tmpdir"/headers.list
Dmitry V. Levindf7aa2b2015-01-19 17:02:16 +000082
83msg "processing $(wc -l < "$tmpdir"/headers.list) header files from $inc_dir"
84failed=0
85
86CC="${CC:-gcc}"
87CPP="${CPP:-cpp}"
88CPPFLAGS="${CPPFLAGS-} -D__EXPORTED_HEADERS__"
89CFLAGS="${CFLAGS:--Wall -O2} -D__EXPORTED_HEADERS__"
90LDFLAGS="${LDFLAGS-}"
91INCLUDES="-I$inc_dir/uapi -I$inc_dir ${INCLUDES-}"
92
93$CC $INCLUDES $CFLAGS -c -o "$tmpdir"/print_ioctlent.o "${0%/*}"/print_ioctlent.c
94
95# Hook onto <asm-generic/ioctl.h> and <asm/ioctl.h>
96for d in asm-generic asm; do
97 mkdir "$tmpdir/$d"
98 cat > "$tmpdir/$d"/ioctl.h <<__EOF__
99#include_next <$d/ioctl.h>
100#undef _IOC
101#define _IOC(dir,type,nr,size) dir, type, nr, size
102__EOF__
103done
104
105INCLUDES="-I$tmpdir $INCLUDES"
106
107process_file()
108{
109 local f="$1"; shift
110
111 # Common code for every processed file.
112 cat > "$tmpdir"/printents.c <<__EOF__
113#include <asm/termbits.h>
114#include <asm/ioctl.h>
115#include <linux/types.h>
116#include <linux/limits.h>
117#include <linux/major.h>
118
119#include <sys/types.h>
120#include <sys/socket.h>
121#include <stdint.h>
122#include <stdbool.h>
123
124#ifndef NULL
125# define NULL ((void*)0)
126#endif
127#ifndef __user
128# define __user
129#endif
130#ifndef __iomem
131# define __iomem
132#endif
133#ifndef __noreturn
134# define __noreturn __attribute__((noreturn))
135#endif
136#ifndef __packed
137# define __packed __attribute__((packed))
138#endif
139
140typedef signed char s8;
141typedef unsigned char u8;
142typedef signed short s16;
143typedef unsigned short u16;
144typedef signed int s32;
145typedef unsigned int u32;
146typedef signed long long s64;
147typedef unsigned long long u64;
148
149#include "fixes.h"
150
151#include <asm/bitsperlong.h>
152#ifndef BITS_PER_LONG
153# define BITS_PER_LONG __BITS_PER_LONG
154#endif
155
156#include "$f"
157
158void print_ioctlent(const char *, const char *, unsigned short, unsigned short, unsigned short, unsigned short);
159
160int main(void)
161{
162
163#include "defs.h"
164
165return 0;
166}
167__EOF__
168
169 # Soft workarounds for some processed files. Fragile.
170 case "$f" in
171 *asm/cmb.h)
172 echo '#include <asm/dasd.h>'
173 ;;
174 *asm/ioctls.h)
175 cat <<'__EOF__'
176#include <asm/termios.h>
177#include <linux/serial.h>
178__EOF__
179 ;;
Dmitry V. Levine7794ae2016-03-26 23:37:18 +0000180 drm/sis_drm.h)
Dmitry V. Levindf7aa2b2015-01-19 17:02:16 +0000181 echo '#include <drm/drm.h>'
182 ;;
Dmitry V. Levine7794ae2016-03-26 23:37:18 +0000183 *drm/*_drm.h)
184 echo '#include <drm/drm.h>' > "$tmpdir/drm.h"
185 ;;
Dmitry V. Levindf7aa2b2015-01-19 17:02:16 +0000186 fbio.h|*/fbio.h)
187 cat <<'__EOF__'
188#include <linux/fb.h>
189#undef FBIOGETCMAP
190#undef FBIOPUTCMAP
191__EOF__
192 ;;
193 *linux/atm?*.h)
194 echo '#include <linux/atm.h>'
195 ;;
196 *linux/auto_fs*.h)
197 echo 'typedef u32 compat_ulong_t;'
198 ;;
199 *linux/btrfs.h)
200 cat <<'__EOF__'
201struct btrfs_ioctl_defrag_range_args { __u32 unused[12]; };
202#define BTRFS_LABEL_SIZE 256
203__EOF__
204 ;;
205 *linux/coda.h|*android_alarm.h)
206 cat <<'__EOF__'
207#ifndef _LINUX_TIME_H
208# define _LINUX_TIME_H
209#endif
210#ifndef _UAPI_LINUX_TIME_H
211# define _UAPI_LINUX_TIME_H
212#endif
213__EOF__
214 ;;
215 *linux/fs.h|*linux/ncp_fs.h)
216 cat <<'__EOF__'
217#include <linux/blktrace_api.h>
218#include <linux/fiemap.h>
219__EOF__
220 ;;
221 *linux/if_pppox.h)
222 cat <<'__EOF__'
223#include <linux/if.h>
224#include <linux/in.h>
225#include <linux/in6.h>
226__EOF__
227 ;;
228 *linux/if_tun.h|*linux/ppp-ioctl.h)
229 echo '#include <linux/filter.h>'
230 ;;
231 *linux/isdn_ppp.h|*linux/gsmmux.h)
232 echo '#include <linux/if.h>'
233 ;;
Dmitry V. Levine7794ae2016-03-26 23:37:18 +0000234 *media*/saa6588.h)
Dmitry V. Levindf7aa2b2015-01-19 17:02:16 +0000235 echo 'typedef struct poll_table_struct poll_table;'
236 ;;
237 *linux/ivtvfb.h|*linux/meye.h|*media/*.h)
238 echo '#include <linux/videodev2.h>'
239 ;;
240 *linux/kvm.h)
241 cat <<'__EOF__'
Dmitry V. Levind07201a2016-05-17 15:57:28 +0000242#if !(defined __powerpc__)
Dmitry V. Levindf7aa2b2015-01-19 17:02:16 +0000243struct kvm_allocate_rma { __u32 unused[2]; };
Dmitry V. Levinf95cf992015-05-21 16:12:31 +0000244struct kvm_create_spapr_tce { __u32 unused[3]; };
Dmitry V. Levind07201a2016-05-17 15:57:28 +0000245struct kvm_create_spapr_tce_64 { __u32 unused[8]; };
Dmitry V. Levindf7aa2b2015-01-19 17:02:16 +0000246struct kvm_get_htab_fd { __u32 unused[8]; };
247struct kvm_rtas_token_args { __u8 unused[128]; };
Dmitry V. Levind07201a2016-05-17 15:57:28 +0000248#endif
249
250#if !(defined __arm64__ || defined __arm__)
Dmitry V. Levindf7aa2b2015-01-19 17:02:16 +0000251struct kvm_vcpu_init { __u32 unused[8]; };
Dmitry V. Levind07201a2016-05-17 15:57:28 +0000252#endif
253
254#if !(defined __x86_64__ || defined __i386__)
Dmitry V. Levinf95cf992015-05-21 16:12:31 +0000255struct kvm_cpuid { __u32 unused[2]; };
256struct kvm_cpuid2 { __u32 unused[2]; };
Dmitry V. Levinf95cf992015-05-21 16:12:31 +0000257struct kvm_debugregs { __u32 unused[32]; };
Dmitry V. Levinf95cf992015-05-21 16:12:31 +0000258struct kvm_lapic_state { __u32 unused[256]; };
259struct kvm_memory_alias { __u32 unused[8]; };
260struct kvm_msr_list { __u32 unused[1]; };
261struct kvm_msrs { __u32 unused[2]; };
262struct kvm_pit_state { __u32 unused[18]; };
263struct kvm_pit_state2 { __u32 unused[28]; };
Dmitry V. Levinf95cf992015-05-21 16:12:31 +0000264struct kvm_vcpu_events { __u32 unused[16]; };
265struct kvm_x86_mce { __u32 unused[16]; };
266struct kvm_xcrs { __u32 unused[98]; };
267struct kvm_xen_hvm_config { __u32 unused[14]; };
268struct kvm_xsave { __u32 unused[1024]; };
Dmitry V. Levindf7aa2b2015-01-19 17:02:16 +0000269#endif
270__EOF__
271 ;;
272 *linux/sonet.h)
273 echo '#include <linux/atmioc.h>'
274 ;;
275 *linux/usbdevice_fs.h)
276 cat <<'__EOF__'
277struct usbdevfs_ctrltransfer32 { __u32 unused[4]; };
278struct usbdevfs_bulktransfer32 { __u32 unused[4]; };
279struct usbdevfs_disconnectsignal32 { __u32 unused[2]; };
280struct usbdevfs_urb32 { __u8 unused[42]; };
281struct usbdevfs_ioctl32 { __u32 unused[3]; };
282__EOF__
283 ;;
284 logger.h|*/logger.h)
285 echo 'typedef __u32 kuid_t;'
286 ;;
287 *sound/asequencer.h)
288 cat <<'__EOF__'
289#include <sound/asound.h>
290struct snd_seq_queue_owner { __u32 unused[0]; };
291__EOF__
292 ;;
293 *sound/emu10k1.h)
294 cat <<'__EOF__'
295#include <sound/asound.h>
296#ifndef DECLARE_BITMAP
297# define DIV_ROUND_UP(x,y) (((x) + ((y) - 1)) / (y))
298# define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, 8 * sizeof(long))
299# define DECLARE_BITMAP(name,bits) unsigned long name[BITS_TO_LONGS(bits)]
300#endif
301__EOF__
302 ;;
303 *video/sstfb.h)
304 echo 'struct fb_info;'
305 ;;
Dmitry V. Levine7794ae2016-03-26 23:37:18 +0000306 *xen/gntdev.h)
307 cat <<'__EOF__'
308typedef uint32_t grant_ref_t;
309typedef uint16_t domid_t;
310__EOF__
311 ;;
Dmitry V. Levindf7aa2b2015-01-19 17:02:16 +0000312 *xen/interface/*.h)
313 return 0 # false positives
314 ;;
315 *xen/privcmd.h)
316 return 0 # too much work to make it compileable
317 ;;
318 esac > "$tmpdir"/fixes.h
319
320 cat > "$tmpdir"/header.in <<__EOF__
321#include <asm/bitsperlong.h>
322#ifndef BITS_PER_LONG
323# define BITS_PER_LONG __BITS_PER_LONG
324#endif
325#include "$f"
326__EOF__
327
328 if [ -f "$inc_dir/uapi/$f" ]; then
329 s="$inc_dir/uapi/$f"
330 elif [ -f "$inc_dir/$f" ]; then
331 s="$inc_dir/$f"
332 else
333 msg "$f: file not found"
334 return 1
335 fi
336
337 [ -n "${f##*/*}" ] ||
338 mkdir -p "$tmpdir/${f%/*}"
339 # Hard workarounds for some processed files. Very fragile.
340 case "$f" in
Dmitry V. Levine7794ae2016-03-26 23:37:18 +0000341 *acpi/*|*linux/i2o.h|*media*/exynos-fimc.h|*media/v4l2-subdev.h|*net/bluetooth/*|net/nfc/nci_core.h)
Dmitry V. Levindf7aa2b2015-01-19 17:02:16 +0000342 # Fetch macros only.
343 grep "${r_define}${r_cmd_name}" < "$s" > "$tmpdir/$f"
344 ;;
345 binder.h|*/binder.h)
346 # Convert enums to macros.
347 sed '/^enum binder/,/^};/d' < "$s" > "$tmpdir/$f"
348 sed -n '/^enum binder/,/^};/ s/^[[:space:]].*/&/p' < "$s" |
349 sed -e '
350s/^[[:space:]]*\([A-Z][A-Z_0-9]*\)[[:space:]]*=[[:space:]]*_\(IO\|IOW\|IOR\|IOWR\|IOC\)[[:space:]]*(/#define \1 _\2(/
351s/^\(#define .*)\),$/\1/
352s/^\(#define .*,\)$/\1 \\/
353s/^\([[:space:]]\+[^),]\+)\),$/\1/' >> "$tmpdir/$f"
354 ;;
355 *drm/r128_drm.h)
356 # Filter out the code that references unknown types.
357 sed '/drm_r128_clear2_t/d' < "$s" > "$tmpdir/$f"
358 ;;
359 *drm/sis_drm.h)
360 # Filter out the code that references unknown types.
361 sed '/^struct sis_file_private/,/^}/d' < "$s" > "$tmpdir/$f"
362 ;;
363 *drm/via_drm.h)
364 # Create the file it attempts to include.
365 touch "$tmpdir/via_drmclient.h"
366 # Filter out the code that references unknown types.
367 sed '/^struct via_file_private/,/^}/d' < "$s" > "$tmpdir/$f"
368 ;;
369 *linux/vmw_vmci_defs.h)
370 # Fetch ioctl macros only.
371 grep "${r_define}I" < "$s" > "$tmpdir/$f"
372 ;;
373 *media/v4l2-common.h)
374 # Fetch one piece of code containing ioctls definitions.
375 sed -n '/ remaining ioctls/,/ ---/p' < "$s" > "$tmpdir/$f"
376 ;;
377 *linux/nilfs2_fs.h)
378 # Create the file it attempts to include.
379 touch "$tmpdir/asm/bug.h"
380 ;;
381 openpromio.h|*/openpromio.h|fbio.h|*/fbio.h)
382 # Create the file it attempts to include.
383 mkdir -p "$tmpdir/linux"
384 touch "$tmpdir/linux/compiler.h"
385 esac
386 if [ -f "$tmpdir/$f" ]; then
387 s="$tmpdir/$f"
388 fi
389
390 # This may fail if the file includes unavailable headers.
391 # In case of success it outputs both the #define directives
392 # and the result of preprocessing.
393 $CPP $CPPFLAGS -dD $INCLUDES < "$tmpdir"/header.in > "$tmpdir"/header.out
394
395 # Need to exclude ioctl commands defined elsewhere.
396 local_defines='^[[:space:]]*#[[:space:]]*define[[:space:]]\+\('"$r_cmd_name"'\)[[:space:]]'
397 sed -n 's/'"$local_defines"'.*/\1\\/p' "$s" > "$tmpdir"/local_names
398 r_local_names="$(tr '\n' '|' < "$tmpdir"/local_names)"
399 r_local_names="${r_local_names%%|}"
400 r_local_names="${r_local_names%%\\}"
401
402 # Keep this in sync with $regexp by replacing $r_cmd_name with $r_local_names.
403 defs_regexp="${r_define}\($r_local_names\)${r_value}"
404
405 qf="$(echo "$prefix$f" | sed 's/[&\/]/\\&/g')"
406 # This outputs lines in the following format:
407 # print_ioctlent("filename.h", "IOCTL_CMD_NAME", IOCTL_CMD_NAME);
408 sed -n 's/'"$defs_regexp"'.*/print_ioctlent("'"$qf"'", "\1", \1);/p' \
409 < "$tmpdir"/header.out > "$tmpdir"/defs.h
410
411 # If something is wrong with the file, this will fail.
412 $CC $INCLUDES $CFLAGS -c -o "$tmpdir"/printents.o "$tmpdir"/printents.c
413 $CC $LDFLAGS -o "$tmpdir"/print_ioctlents \
414 "$tmpdir"/printents.o "$tmpdir"/print_ioctlent.o
415 "$tmpdir"/print_ioctlents > "$tmpdir"/ioctlents
416 cat "$tmpdir"/ioctlents
417 msg "$f: fetched $(grep -c '^{' "$tmpdir"/ioctlents) ioctl entries"
418}
419
420while read f; do
421 (process_file "$f" < /dev/null)
422 [ $? -eq 0 ] || {
423 msg "$f: failed to process"
424 failed=$((1 + $failed))
425 }
426done < "$tmpdir"/headers.list
427
428[ $failed -eq 0 ] ||
429 msg "failed to process $failed file(s)"