ioctl32.c
来自「linux-2.4.29操作系统的源码」· C语言 代码 · 共 2,297 行 · 第 1/5 页
C
2,297 行
/* * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 2000 Silicon Graphics, Inc. * Written by Ulf Carlsson (ulfc@engr.sgi.com) * Copyright (C) 2000 Ralf Baechle * Copyright (C) 2002, 2003 Maciej W. Rozycki * * Mostly stolen from the sparc64 ioctl32 implementation. */#include <linux/config.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.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_u.h>#include <linux/kd.h>#include <linux/route.h>#include <linux/vt.h>#include <linux/fs.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/auto_fs4.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/blkpg.h>#include <linux/blk.h>#include <linux/elevator.h>#include <linux/file.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>#undef __KERNEL__ /* This file was born to be ugly ... */#include <scsi/scsi_ioctl.h>#define __KERNEL__#include <scsi/sg.h>#include <asm/types.h>#include <asm/uaccess.h>#include <linux/soundcard.h>#include <linux/mtd/mtd.h>#include <linux/serial.h>#ifdef CONFIG_SIBYTE_TBPROF#include <asm/sibyte/trace_prof.h>#endiflong 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((unsigned int) 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;}#define A(__x) ((unsigned long)(__x))#ifdef CONFIG_FBstruct fb_fix_screeninfo32 { char id[16]; /* identification string eg "TT Builtin" */ __u32 smem_start; /* Start of frame buffer mem */ /* (physical address) */ __u32 smem_len; /* Length of frame buffer mem */ __u32 type; /* see FB_TYPE_* */ __u32 type_aux; /* Interleave for interleaved Planes */ __u32 visual; /* see FB_VISUAL_* */ __u16 xpanstep; /* zero if no hardware panning */ __u16 ypanstep; /* zero if no hardware panning */ __u16 ywrapstep; /* zero if no hardware ywrap */ __u32 line_length; /* length of a line in bytes */ __u32 mmio_start; /* Start of Memory Mapped I/O */ /* (physical address) */ __u32 mmio_len; /* Length of Memory Mapped I/O */ __u32 accel; /* Type of acceleration available */ __u16 reserved[3]; /* Reserved for future compatibility */};static int do_fbioget_fscreeninfo_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg){ mm_segment_t old_fs = get_fs(); struct fb_fix_screeninfo fix; struct fb_fix_screeninfo32 *fix32 = (struct fb_fix_screeninfo32 *)arg; int err; set_fs(KERNEL_DS); err = sys_ioctl(fd, cmd, (unsigned long)&fix); set_fs(old_fs); if (err == 0) { err = __copy_to_user((char *)fix32->id, (char *)fix.id, sizeof(fix.id)); err |= __put_user((__u32)(unsigned long)fix.smem_start, &fix32->smem_start); err |= __put_user(fix.smem_len, &fix32->smem_len); err |= __put_user(fix.type, &fix32->type); err |= __put_user(fix.type_aux, &fix32->type_aux); err |= __put_user(fix.visual, &fix32->visual); err |= __put_user(fix.xpanstep, &fix32->xpanstep); err |= __put_user(fix.ypanstep, &fix32->ypanstep); err |= __put_user(fix.ywrapstep, &fix32->ywrapstep); err |= __put_user(fix.line_length, &fix32->line_length); err |= __put_user((__u32)(unsigned long)fix.mmio_start, &fix32->mmio_start); err |= __put_user(fix.mmio_len, &fix32->mmio_len); err |= __put_user(fix.accel, &fix32->accel); err |= __copy_to_user((char *)fix32->reserved, (char *)fix.reserved, sizeof(fix.reserved)); if (err) err = -EFAULT; } return err;}struct fb_cmap32 { __u32 start; /* First entry */ __u32 len; /* Number of entries */ __u32 red; /* Red values */ __u32 green; __u32 blue; __u32 transp; /* transparency, can be NULL */};static int do_fbiocmap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg){ mm_segment_t old_fs = get_fs(); u32 red = 0, green = 0, blue = 0, transp = 0; struct fb_cmap cmap; struct fb_cmap32 *cmap32 = (struct fb_cmap32 *)arg; int err; memset(&cmap, 0, sizeof(cmap)); err = __get_user(cmap.start, &cmap32->start); err |= __get_user(cmap.len, &cmap32->len); err |= __get_user(red, &cmap32->red); err |= __get_user(green, &cmap32->green); err |= __get_user(blue, &cmap32->blue); err |= __get_user(transp, &cmap32->transp); if (err) return -EFAULT; err = -ENOMEM; cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); if (!cmap.red) goto out; cmap.green = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); if (!cmap.green) goto out; cmap.blue = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); if (!cmap.blue) goto out; if (transp) { cmap.transp = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); if (!cmap.transp) goto out; } if (cmd == FBIOPUTCMAP) { err = __copy_from_user(cmap.red, (char *)A(red), cmap.len * sizeof(__u16)); err |= __copy_from_user(cmap.green, (char *)A(green), cmap.len * sizeof(__u16)); err |= __copy_from_user(cmap.blue, (char *)A(blue), cmap.len * sizeof(__u16)); if (cmap.transp) err |= __copy_from_user(cmap.transp, (char *)A(transp), cmap.len * sizeof(__u16)); if (err) { err = -EFAULT; goto out; } } set_fs(KERNEL_DS); err = sys_ioctl(fd, cmd, (unsigned long)&cmap); set_fs(old_fs); if (err) goto out; if (cmd == FBIOGETCMAP) { err = __copy_to_user((char *)A(red), cmap.red, cmap.len * sizeof(__u16)); err |= __copy_to_user((char *)A(green), cmap.blue, cmap.len * sizeof(__u16)); err |= __copy_to_user((char *)A(blue), cmap.blue, cmap.len * sizeof(__u16)); if (cmap.transp) err |= __copy_to_user((char *)A(transp), cmap.transp, cmap.len * sizeof(__u16)); if (err) { err = -EFAULT; goto out; } }out: if (cmap.red) kfree(cmap.red); if (cmap.green) kfree(cmap.green); if (cmap.blue) kfree(cmap.blue); if (cmap.transp) kfree(cmap.transp); return err;}#endif /* CONFIG_FB */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;}#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)struct ifmap32 { unsigned int mem_start; unsigned int 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; struct sockaddr ifru_hwaddr; short ifru_flags; int ifru_ivalue; int ifru_mtu; struct ifmap32 ifru_map; char ifru_slave[IFNAMSIZ]; /* Just fits the size */ char ifru_newname[IFNAMSIZ]; __kernel_caddr_t32 ifru_data; } ifr_ifru;};struct ifconf32 { int ifc_len; /* size of buffer */ __kernel_caddr_t32 ifcbuf;};#ifdef CONFIG_NETstatic int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg){ struct ireq32 *uir32 = (struct ireq32 *)arg; struct net_device *dev; struct ifreq32 ifr32; if (copy_from_user(&ifr32, uir32, sizeof(struct ifreq32))) return -EFAULT; read_lock(&dev_base_lock); dev = __dev_get_by_index(ifr32.ifr_ifindex); if (!dev) { read_unlock(&dev_base_lock); return -ENODEV; } strcpy(ifr32.ifr_name, dev->name); read_unlock(&dev_base_lock); if (copy_to_user(uir32, &ifr32, sizeof(struct ifreq32))) return -EFAULT; return 0;}static inline int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg){ struct ioconf32 *uifc32 = (struct ioconf32 *)arg; struct ifconf32 ifc32; struct ifconf ifc; struct ifreq32 *ifr32; struct ifreq *ifr; mm_segment_t old_fs; unsigned int i, j; int err; if (copy_from_user(&ifc32, uifc32, sizeof(struct ifconf32))) return -EFAULT; if(ifc32.ifcbuf == 0) { ifc32.ifc_len = 0; ifc.ifc_len = 0; ifc.ifc_buf = NULL; } else { ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32))) * sizeof (struct ifreq); ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL); if (!ifc.ifc_buf) return -ENOMEM; } ifr = ifc.ifc_req; ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) { if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) { kfree (ifc.ifc_buf); return -EFAULT; } } old_fs = get_fs(); set_fs (KERNEL_DS); err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); set_fs (old_fs); if (err) goto out; ifr = ifc.ifc_req; ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len; i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) { if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) { err = -EFAULT; goto out; } } if (ifc32.ifcbuf == 0) { /* Translate from 64-bit structure multiple to * a 32-bit one. */ i = ifc.ifc_len; i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32)); ifc32.ifc_len = i; } else { if (i <= ifc32.ifc_len) ifc32.ifc_len = i; else ifc32.ifc_len = i - sizeof (struct ifreq32); } if (copy_to_user(uifc32, &ifc32, sizeof(struct ifconf32))) { err = -EFAULT; goto out; }out: if(ifc.ifc_buf != NULL) kfree (ifc.ifc_buf); return err;}static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg){ struct ifreq ifr; mm_segment_t old_fs; int err; switch (cmd) { case SIOCSIFMAP: err = copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(ifr.ifr_name)); err |= __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start)); err |= __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end)); err |= __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr)); err |= __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq)); err |= __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma)); err |= __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port)); if (err) return -EFAULT; break; default: if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) return -EFAULT; break; } old_fs = get_fs(); set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long)&ifr); set_fs (old_fs); if (!err) { switch (cmd) { case SIOCGIFFLAGS: case SIOCGIFMETRIC: case SIOCGIFMTU:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?