static noinline int mmc_ioctl_cdrom_read_audio()

in cdrom.c [3010:3056]


static noinline int mmc_ioctl_cdrom_read_audio(struct cdrom_device_info *cdi,
					       void __user *arg)
{
	struct cdrom_read_audio ra;
	int lba;

#ifdef CONFIG_COMPAT
	if (in_compat_syscall()) {
		struct compat_cdrom_read_audio {
			union cdrom_addr	addr;
			u8			addr_format;
			compat_int_t		nframes;
			compat_caddr_t		buf;
		} ra32;

		if (copy_from_user(&ra32, arg, sizeof(ra32)))
			return -EFAULT;

		ra = (struct cdrom_read_audio) {
			.addr		= ra32.addr,
			.addr_format	= ra32.addr_format,
			.nframes	= ra32.nframes,
			.buf		= compat_ptr(ra32.buf),
		};
	} else
#endif
	{
		if (copy_from_user(&ra, (struct cdrom_read_audio __user *)arg,
				   sizeof(ra)))
			return -EFAULT;
	}

	if (ra.addr_format == CDROM_MSF)
		lba = msf_to_lba(ra.addr.msf.minute,
				 ra.addr.msf.second,
				 ra.addr.msf.frame);
	else if (ra.addr_format == CDROM_LBA)
		lba = ra.addr.lba;
	else
		return -EINVAL;

	/* FIXME: we need upper bound checking, too!! */
	if (lba < 0 || ra.nframes <= 0 || ra.nframes > CD_FRAMES)
		return -EINVAL;

	return cdrom_read_cdda(cdi, ra.buf, lba, ra.nframes);
}