📄 ioctl32.c
字号:
/* * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Based on sparc64 ioctl32.c by: * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * * ppc64 changes: * * Copyright (C) 2000 Ken Aaker (kdaaker@rchland.vnet.ibm.com) * Copyright (C) 2001 Anton Blanchard (antonb@au.ibm.com) * * These routines maintain argument size conversion between 32bit and 64bit * ioctls. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */#include <linux/config.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/ioctl.h>#include <linux/if.h>#include <linux/slab.h>#include <linux/hdreg.h>#include <linux/raid/md.h>#include <linux/kd.h>#include <linux/route.h>#include <linux/in6.h>#include <linux/ipv6_route.h>#include <linux/skbuff.h>#include <linux/netlink.h>#include <linux/vt.h>#include <linux/fs.h>#include <linux/file.h>#include <linux/fd.h>#include <linux/ppp_defs.h>#include <linux/if_ppp.h>#include <linux/if_pppox.h>#include <linux/if_tun.h>#include <linux/mtio.h>#include <linux/cdrom.h>#include <linux/loop.h>#include <linux/auto_fs.h>#include <linux/devfs_fs.h>#include <linux/tty.h>#include <linux/vt_kern.h>#include <linux/fb.h>#include <linux/ext2_fs.h>#include <linux/videodev.h>#include <linux/netdevice.h>#include <linux/raw.h>#include <linux/smb_fs.h>#include <linux/blkpg.h>#include <linux/blk.h>#include <linux/elevator.h>#include <linux/rtc.h>#include <linux/pci.h>#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)#include <linux/lvm.h>#endif /* LVM */#include <scsi/scsi.h>/* Ugly hack. */#undef __KERNEL__#include <scsi/scsi_ioctl.h>#define __KERNEL__#include <scsi/sg.h>#include <asm/types.h>#include <asm/uaccess.h>#include <linux/ethtool.h>#include <linux/mii.h>#include <linux/if_bonding.h>#include <asm/module.h>#include <linux/soundcard.h>#include <linux/watchdog.h>#include <linux/lp.h>#include <linux/atm.h>#include <linux/atmarp.h>#include <linux/atmclip.h>#include <linux/atmdev.h>#include <linux/atmioc.h>#include <linux/atmlec.h>#include <linux/atmmpc.h>#include <linux/atmsvc.h>#include <linux/atm_tcp.h>#include <linux/sonet.h>#include <linux/atm_suni.h>#include <linux/mtd/mtd.h>#include <net/bluetooth/bluetooth.h>#include <net/bluetooth/hci.h>#include <linux/usb.h>#include <linux/usbdevice_fs.h>#include <linux/nbd.h>#include <linux/random.h>#include <asm/ppc32.h>#include <asm/ppcdebug.h>/* Aiee. Someone does not find a difference between int and long */#define EXT2_IOC32_GETFLAGS _IOR('f', 1, int)#define EXT2_IOC32_SETFLAGS _IOW('f', 2, int)#define EXT2_IOC32_GETVERSION _IOR('v', 1, int)#define EXT2_IOC32_SETVERSION _IOW('v', 2, int)extern asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg){ mm_segment_t old_fs = get_fs(); int err; unsigned long val; set_fs (KERNEL_DS); err = sys_ioctl(fd, cmd, (unsigned long)&val); set_fs (old_fs); if (!err && put_user(val, (u32 *)arg)) return -EFAULT; return err;} static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg){ mm_segment_t old_fs = get_fs(); int err; unsigned long val; if (get_user(val, (u32 *)arg)) return -EFAULT; set_fs (KERNEL_DS); err = sys_ioctl(fd, cmd, (unsigned long)&val); set_fs (old_fs); if (!err && put_user(val, (u32 *)arg)) return -EFAULT; return err;}static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg){ /* These are just misnamed, they actually get/put from/to user an int */ switch (cmd) { case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break; case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break; case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break; case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break; } return sys_ioctl(fd, cmd, arg);} struct video_tuner32 { s32 tuner; u8 name[32]; u32 rangelow, rangehigh; u32 flags; u16 mode, signal;};static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up){ int i; if (get_user(kp->tuner, &up->tuner)) return -EFAULT; for(i = 0; i < 32; i++) __get_user(kp->name[i], &up->name[i]); __get_user(kp->rangelow, &up->rangelow); __get_user(kp->rangehigh, &up->rangehigh); __get_user(kp->flags, &up->flags); __get_user(kp->mode, &up->mode); __get_user(kp->signal, &up->signal); return 0;}static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up){ int i; if (put_user(kp->tuner, &up->tuner)) return -EFAULT; for(i = 0; i < 32; i++) __put_user(kp->name[i], &up->name[i]); __put_user(kp->rangelow, &up->rangelow); __put_user(kp->rangehigh, &up->rangehigh); __put_user(kp->flags, &up->flags); __put_user(kp->mode, &up->mode); __put_user(kp->signal, &up->signal); return 0;}struct video_buffer32 { /* void * */ u32 base; s32 height, width, depth, bytesperline;};static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up){ u32 tmp; if (get_user(tmp, &up->base)) return -EFAULT; kp->base = (void *) ((unsigned long)tmp); __get_user(kp->height, &up->height); __get_user(kp->width, &up->width); __get_user(kp->depth, &up->depth); __get_user(kp->bytesperline, &up->bytesperline); return 0;}static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up){ u32 tmp = (u32)((unsigned long)kp->base); if (put_user(tmp, &up->base)) return -EFAULT; __put_user(kp->height, &up->height); __put_user(kp->width, &up->width); __put_user(kp->depth, &up->depth); __put_user(kp->bytesperline, &up->bytesperline); return 0;}struct video_clip32 { s32 x, y, width, height; /* struct video_clip32 * */ u32 next;};struct video_window32 { u32 x, y, width, height, chromakey, flags; /* struct video_clip32 * */ u32 clips; s32 clipcount;};static void free_kvideo_clips(struct video_window *kp){ struct video_clip *cp; cp = kp->clips; if (cp != NULL) kfree(cp);}static int get_video_window32(struct video_window *kp, struct video_window32 *up){ struct video_clip32 *ucp; struct video_clip *kcp; int nclips, err, i; u32 tmp; if (get_user(kp->x, &up->x)) return -EFAULT; __get_user(kp->y, &up->y); __get_user(kp->width, &up->width); __get_user(kp->height, &up->height); __get_user(kp->chromakey, &up->chromakey); __get_user(kp->flags, &up->flags); __get_user(kp->clipcount, &up->clipcount); __get_user(tmp, &up->clips); ucp = (struct video_clip32 *)A(tmp); kp->clips = NULL; nclips = kp->clipcount; if (nclips == 0) return 0; if (ucp == 0) return -EINVAL; /* Peculiar interface... */ if (nclips < 0) nclips = VIDEO_CLIPMAP_SIZE; kcp = kmalloc(nclips * sizeof(struct video_clip), GFP_KERNEL); err = -ENOMEM; if (kcp == NULL) goto cleanup_and_err; kp->clips = kcp; for(i = 0; i < nclips; i++) { __get_user(kcp[i].x, &ucp[i].x); __get_user(kcp[i].y, &ucp[i].y); __get_user(kcp[i].width, &ucp[i].width); __get_user(kcp[i].height, &ucp[i].height); kcp[nclips].next = NULL; } return 0;cleanup_and_err: free_kvideo_clips(kp); return err;}/* You get back everything except the clips... */static int put_video_window32(struct video_window *kp, struct video_window32 *up){ if (put_user(kp->x, &up->x)) return -EFAULT; __put_user(kp->y, &up->y); __put_user(kp->width, &up->width); __put_user(kp->height, &up->height); __put_user(kp->chromakey, &up->chromakey); __put_user(kp->flags, &up->flags); __put_user(kp->clipcount, &up->clipcount); return 0;}#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32)#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32)#define VIDIOCGWIN32 _IOR('v',9, struct video_window32)#define VIDIOCSWIN32 _IOW('v',10, struct video_window32)#define VIDIOCGFBUF32 _IOR('v',11, struct video_buffer32)#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32)#define VIDIOCGFREQ32 _IOR('v',14, u32)#define VIDIOCSFREQ32 _IOW('v',15, u32)static int do_video_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg){ union { struct video_tuner vt; struct video_buffer vb; struct video_window vw; unsigned long vx; } karg; mm_segment_t old_fs = get_fs(); void *up = (void *)arg; int err = 0; /* First, convert the command. */ switch(cmd) { case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break; case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break; case VIDIOCGWIN32: cmd = VIDIOCGWIN; break; case VIDIOCSWIN32: cmd = VIDIOCSWIN; break; case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break; case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break; case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break; case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break; }; switch(cmd) { case VIDIOCSTUNER: case VIDIOCGTUNER: err = get_video_tuner32(&karg.vt, up); break; case VIDIOCSWIN: err = get_video_window32(&karg.vw, up); break; case VIDIOCSFBUF: err = get_video_buffer32(&karg.vb, up); break; case VIDIOCSFREQ: err = get_user(karg.vx, (u32 *)up); break; }; if (err) goto out; set_fs(KERNEL_DS); err = sys_ioctl(fd, cmd, (unsigned long)&karg); set_fs(old_fs); if (cmd == VIDIOCSWIN) free_kvideo_clips(&karg.vw); if (err == 0) { switch(cmd) { case VIDIOCGTUNER: err = put_video_tuner32(&karg.vt, up); break; case VIDIOCGWIN: err = put_video_window32(&karg.vw, up); break; case VIDIOCGFBUF: err = put_video_buffer32(&karg.vb, up); break; case VIDIOCGFREQ: err = put_user(((u32)karg.vx), (u32 *)up); break; }; }out: return err;}struct timeval32 { int tv_sec; int tv_usec;};static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg){ struct timeval32 *up = (struct timeval32 *)arg; struct timeval ktv; mm_segment_t old_fs = get_fs(); int err; set_fs(KERNEL_DS); err = sys_ioctl(fd, cmd, (unsigned long)&ktv); set_fs(old_fs); if (!err) { err = put_user(ktv.tv_sec, &up->tv_sec); err |= __put_user(ktv.tv_usec, &up->tv_usec); } return err;}struct ifmap32 { u32 mem_start; u32 mem_end; unsigned short base_addr; unsigned char irq; unsigned char dma; unsigned char port;};struct ifreq32 {#define IFHWADDRLEN 6#define IFNAMSIZ 16 union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ } ifr_ifrn; union { struct sockaddr ifru_addr; struct sockaddr ifru_dstaddr; struct sockaddr ifru_broadaddr; struct sockaddr ifru_netmask;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -