Пример #1
0
/*
 * When you add any new common ioctls to the switches above and below
 * please update compat_sys_ioctl() too.
 *
 * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
 * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
 */
int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
	     unsigned long arg)
{
	int error = 0;
	int __user *argp = (int __user *)arg;

	switch (cmd) {
	case FIOCLEX:
		set_close_on_exec(fd, 1);
		break;

	case FIONCLEX:
		set_close_on_exec(fd, 0);
		break;

	case FIONBIO:
		/* BKL needed to avoid races tweaking f_flags */
		lock_kernel();
		error = ioctl_fionbio(filp, argp);
		unlock_kernel();
		break;

	case FIOASYNC:
		/* BKL needed to avoid races tweaking f_flags */
		lock_kernel();
		error = ioctl_fioasync(fd, filp, argp);
		unlock_kernel();
		break;

	case FIOQSIZE:
		if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) ||
		    S_ISREG(filp->f_path.dentry->d_inode->i_mode) ||
		    S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) {
			loff_t res =
				inode_get_bytes(filp->f_path.dentry->d_inode);
			error = copy_to_user((loff_t __user *)arg, &res,
					     sizeof(res)) ? -EFAULT : 0;
		} else
			error = -ENOTTY;
		break;

	case FIFREEZE:
		error = ioctl_fsfreeze(filp);
		break;

	case FITHAW:
		error = ioctl_fsthaw(filp);
		break;

	default:
		if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
			error = file_ioctl(filp, cmd, arg);
		else
			error = vfs_ioctl(filp, cmd, arg);
		break;
	}
	return error;
}
Пример #2
0
/*
 * When you add any new common ioctls to the switches above and below
 * please update compat_sys_ioctl() too.
 *
 * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
 * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
 */
int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
	     unsigned long arg)
{
	int error = 0;
	int __user *argp = (int __user *)arg;
	struct inode *inode = file_inode(filp);

	switch (cmd) {
	case FIOCLEX:
		set_close_on_exec(fd, 1);
		break;

	case FIONCLEX:
		set_close_on_exec(fd, 0);
		break;

	case FIONBIO:
		error = ioctl_fionbio(filp, argp);
		break;

	case FIOASYNC:
		error = ioctl_fioasync(fd, filp, argp);
		break;

	case FIOQSIZE:
		if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) ||
		    S_ISLNK(inode->i_mode)) {
			loff_t res = inode_get_bytes(inode);
			error = copy_to_user(argp, &res, sizeof(res)) ?
					-EFAULT : 0;
		} else
			error = -ENOTTY;
		break;

	case FIFREEZE:
		error = ioctl_fsfreeze(filp);
		break;

	case FITHAW:
		error = ioctl_fsthaw(filp);
		break;

	case FS_IOC_FIEMAP:
		return ioctl_fiemap(filp, arg);

	case FIGETBSZ:
		return put_user(inode->i_sb->s_blocksize, argp);

	default:
		if (S_ISREG(inode->i_mode))
			error = file_ioctl(filp, cmd, arg);
		else
			error = vfs_ioctl(filp, cmd, arg);
		break;
	}
	return error;
}
Пример #3
0
static int wdog_daemon(int argc, char *argv[])
{
  FAR struct file filestruct;
  int ret;

  /* Open the watchdog device for reading */

  wdinfo("Opening.\n");
  ret = file_open(&filestruct, CONFIG_WATCHDOG_DEVPATH, O_RDONLY);
  if (ret < 0)
    {
      wderr("ERROR: open %s failed: %d\n", CONFIG_WATCHDOG_DEVPATH, ret);
      goto errout;
    }

  /* Start the watchdog timer. */

  wdinfo("Starting.\n");
  ret = file_ioctl(&filestruct, WDIOC_START, 0);
  if (ret < 0)
    {
      wderr("ERROR: ioctl(WDIOC_START) failed: %d\n", errno);
      goto errout_with_dev;
    }

  nxsig_usleep(200);
  while(1)
    {
      nxsig_usleep((CONFIG_WDT_THREAD_INTERVAL)*1000);

      wdinfo("ping\n");
      ret = file_ioctl(&filestruct, WDIOC_KEEPALIVE, 0);
      if (ret < 0)
        {
          wderr("ERROR: ioctl(WDIOC_KEEPALIVE) failed: %d\n", errno);
          goto errout_with_dev;
        }
    }

errout_with_dev:
  file_close(&filestruct);
errout:
  return ret;
}
Пример #4
0
int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{	
	struct file * filp;

	if (fd >= NR_OPEN || !(filp = current->filp[fd]))
		return -EBADF;
	if (filp->f_inode && S_ISREG(filp->f_inode->i_mode))
		return file_ioctl(filp,cmd,arg);
	if (filp->f_op && filp->f_op->ioctl)
		return filp->f_op->ioctl(filp->f_inode, filp, cmd,arg);
	return -EINVAL;
}
Пример #5
0
int sys_ioctl(int fd, unsigned int cmd, unsigned int arg)
{
    register struct file *filp;
    register struct file_operations *fop;
    int on;

    if (fd >= NR_OPEN || !(filp = current->files.fd[fd]))
	return -EBADF;
    fop = filp->f_op;
    filp->f_inode = filp->f_inode;
    switch (cmd) {
    case FIOCLEX:
	FD_SET(fd, &current->files.close_on_exec);
	return 0;

    case FIONCLEX:
	FD_CLR(fd, &current->files.close_on_exec);
	return 0;

    case FIONBIO:
	memcpy_fromfs(&on, (unsigned int *) arg, 2);
#if 0
	on = get_user((void *) arg);
#endif
	filp->f_flags = (on)
	    ? filp->f_flags | O_NONBLOCK
	    : filp->f_flags & ~O_NONBLOCK;
	return 0;

    default:
	if (filp->f_inode && S_ISREG(filp->f_inode->i_mode))
	    return file_ioctl(filp, cmd, arg);

	if (fop && fop->ioctl)
	    return fop->ioctl(filp->f_inode, filp, cmd, arg);

	return -EINVAL;
    }
}
Пример #6
0
MPERS_PRINTER_DECL(int, btrfs_ioctl,
		   struct tcb *tcp, const unsigned int code, const long arg)
{
	switch (code) {
	/* Take no arguments; command only. */
	case BTRFS_IOC_TRANS_START:
	case BTRFS_IOC_TRANS_END:
	case BTRFS_IOC_SYNC:
	case BTRFS_IOC_SCRUB_CANCEL:
	case BTRFS_IOC_QUOTA_RESCAN_WAIT:
	/*
	 * The codes for these ioctls are based on each accepting a
	 * vol_args but none of them actually consume an argument.
	 */
	case BTRFS_IOC_DEFRAG:
	case BTRFS_IOC_BALANCE:
		break;

	/* takes a signed int */
	case BTRFS_IOC_BALANCE_CTL:
		tprints(", ");
		printxval(btrfs_balance_ctl_cmds, arg, "BTRFS_BALANCE_CTL_???");
		break;

	/* returns a 64 */
	case BTRFS_IOC_START_SYNC: /* R */
		if (entering(tcp))
			return 0;
	/* fall through */
	/* takes a u64 */
	case BTRFS_IOC_DEFAULT_SUBVOL: /* W */
	case BTRFS_IOC_WAIT_SYNC: /* W */
		tprints(", ");
		printnum_int64(tcp, arg, "%" PRIu64);
		break;

	/* u64 but describe a flags bitfield; we can make that symbolic */
	case BTRFS_IOC_SUBVOL_GETFLAGS: { /* R */
		uint64_t flags;

		if (entering(tcp))
			return 0;

		tprints(", ");

		if (umove_or_printaddr(tcp, arg, &flags))
			break;

		printflags64(btrfs_snap_flags_v2, flags, "BTRFS_SUBVOL_???");
		break;
	}

	case BTRFS_IOC_SUBVOL_SETFLAGS: { /* W */
		uint64_t flags;

		tprints(", ");

		if (umove_or_printaddr(tcp, arg, &flags))
			break;

		printflags64(btrfs_snap_flags_v2, flags, "BTRFS_SUBVOL_???");
		break;
	}

	/* More complex types */
	case BTRFS_IOC_BALANCE_V2: /* RW */
		if (entering(tcp)) {
			tprints(", ");
			btrfs_print_balance(tcp, arg, false);
			return 0;
		}

		if (syserror(tcp))
			break;

		tprints(" => ");
		btrfs_print_balance(tcp, arg, true);
		break;
	case BTRFS_IOC_BALANCE_PROGRESS: /* R */
		if (entering(tcp))
			return 0;

		tprints(", ");
		btrfs_print_balance(tcp, arg, true);
		break;

	case BTRFS_IOC_DEFRAG_RANGE: { /* W */
		struct btrfs_ioctl_defrag_range_args args;

		tprints(", ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprintf("{start=%" PRIu64 ", len=", (uint64_t)args.start);

		tprintf("%" PRIu64, (uint64_t) args.len);
		if (args.len == UINT64_MAX)
			tprints(" /* UINT64_MAX */");

		tprints(", flags=");
		printflags64(btrfs_defrag_flags, args.flags,
			     "BTRFS_DEFRAG_RANGE_???");
		tprintf(", extent_thresh=%u, compress_type=",
			args.extent_thresh);
		printxval(btrfs_compress_types, args.compress_type,
			  "BTRFS_COMPRESS_???");
		tprints("}");
		break;
	}

	case BTRFS_IOC_DEV_INFO: { /* RW */
		struct btrfs_ioctl_dev_info_args args;
		char uuid[UUID_STRING_SIZE+1];
		int valid;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;
		tprints("{");

		valid = btrfs_unparse_uuid(args.uuid, uuid);
		if (entering(tcp)) {
			tprintf("devid=%" PRI__u64, args.devid);
			if (valid)
				tprintf(", uuid=%s", uuid);
			tprints("}");
			return 0;
		}
		if (valid)
			tprintf("uuid=%s, ", uuid);
		tprintf("bytes_used=%" PRI__u64
			", total_bytes=%" PRI__u64 ", path=",
			args.bytes_used, args.total_bytes);
		print_quoted_string((const char *)args.path, sizeof(args.path),
				    QUOTE_0_TERMINATED);
		tprints("}");
		break;
	}

	case BTRFS_IOC_DEV_REPLACE: { /* RW */
		struct_btrfs_ioctl_dev_replace_args args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		if (entering(tcp)) {
			tprints("{cmd=");
			printxval64(btrfs_dev_replace_cmds, args.cmd,
				    "BTRFS_IOCTL_DEV_REPLACE_CMD_???");
			if (args.cmd == BTRFS_IOCTL_DEV_REPLACE_CMD_START) {
				const char *str;
				tprintf(", start={srcdevid=%" PRIu64
				   ", cont_reading_from_srcdev_mode=%" PRIu64
				   ", srcdev_name=",
				   (uint64_t) args.start.srcdevid,
				   (uint64_t) args.start.cont_reading_from_srcdev_mode);

				str = (const char*) args.start.srcdev_name;
				print_quoted_string(str,
						sizeof(args.start.srcdev_name),
						QUOTE_0_TERMINATED);
				tprints(", tgtdev_name=");
				str = (const char*) args.start.tgtdev_name;
				print_quoted_string(str,
						sizeof(args.start.tgtdev_name),
						QUOTE_0_TERMINATED);
				tprints("}");

			}
			tprints("}");
			return 0;
		}

		tprints("{result=");
		printxval64(btrfs_dev_replace_results, args.result,
			    "BTRFS_IOCTL_DEV_REPLACE_RESULT_???");
		if (args.cmd == BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS) {
			char buf[sizeof("HH:MM:SS") + 1];
			time_t time;
			tprints(", ");
			printxval64(btrfs_dev_replace_state,
				   args.status.replace_state,
				   "BTRFS_IOCTL_DEV_REPLACE_STATE_???");
			tprintf(", progress_1000=%" PRIu64 " /* ",
				(uint64_t) args.status.progress_1000);
			if (args.status.progress_1000 <= 1000)
				tprintf("%" PRIu64 ".%.2" PRIu64 "%%",
					(uint64_t) args.status.progress_1000 / 10,
					(uint64_t) args.status.progress_1000 % 10);
			else
				tprints("???");
			tprints(" */ ,");

			time = args.status.time_started;
			strftime(buf, sizeof(buf), "%T",
				 localtime(&time));
			tprintf("time_started=%" PRIu64" /* %s */, ",
				(uint64_t) args.status.time_started, buf);

			time = args.status.time_stopped;
			strftime(buf, sizeof(buf), "%T",
				 localtime(&time));
			tprintf("time_stopped=%" PRIu64" /* %s */, ",
				(uint64_t) args.status.time_stopped, buf);

			tprintf("num_write_errors=%" PRIu64
				", num_uncorrectable_read_errors=%" PRIu64,
				(uint64_t) args.status.num_write_errors,
				(uint64_t) args.status.num_uncorrectable_read_errors);
		}
		tprints("}");
		break;
	}

	case BTRFS_IOC_GET_FEATURES: { /* R */
		struct btrfs_ioctl_feature_flags flags;

		if (entering(tcp))
			return 0;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &flags))
			break;

		btrfs_print_features(&flags);
		break;
	}

	case BTRFS_IOC_SET_FEATURES: { /* W */
		struct btrfs_ioctl_feature_flags flarg[2];

		tprints(", ");

		if (umove_or_printaddr(tcp, arg, &flarg))
			break;

		tprints("[");
		btrfs_print_features(&flarg[0]);
		tprints(", ");
		btrfs_print_features(&flarg[1]);
		tprints("]");
		break;
	}

	case BTRFS_IOC_GET_SUPPORTED_FEATURES: { /* R */
		struct btrfs_ioctl_feature_flags flarg[3];

		if (entering(tcp))
			return 0;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &flarg))
			break;

		tprints("[ /* supported */ ");
		btrfs_print_features(&flarg[0]);

		tprints(", /* safe to set */ ");
		btrfs_print_features(&flarg[1]);

		tprints(", /* safe to clear */ ");
		btrfs_print_features(&flarg[2]);
		tprints("]");

		break;
	}

	case BTRFS_IOC_FS_INFO: { /* R */
		struct btrfs_ioctl_fs_info_args args;
		char uuid[UUID_STRING_SIZE+1];
		uint32_t nodesize, sectorsize, clone_alignment;
#ifndef HAVE_STRUCT_BTRFS_IOCTL_FS_INFO_ARGS_NODESIZE
		__u32 *reserved32;
#endif

		if (entering(tcp))
			return 0;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

#ifdef HAVE_STRUCT_BTRFS_IOCTL_FS_INFO_ARGS_NODESIZE
		nodesize = args.nodesize,
		sectorsize = args.sectorsize,
		clone_alignment = args.clone_alignment;
#else
		reserved32 = (__u32 *) (void *) args.reserved;
		nodesize = reserved32[0];
		sectorsize = reserved32[1];
		clone_alignment = reserved32[2];
#endif
		btrfs_unparse_uuid(args.fsid, uuid);

		tprints("{");
		tprintf("max_id=%" PRI__u64 ", num_devices=%" PRI__u64
			", fsid=%s, nodesize=%u, sectorsize=%u"
			", clone_alignment=%u",
			args.max_id, args.num_devices, uuid,
			nodesize, sectorsize, clone_alignment);
		tprints("}");
		break;
	}

	case BTRFS_IOC_GET_DEV_STATS: { /* RW */
		struct btrfs_ioctl_get_dev_stats args;
		uint64_t i;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{");

		if (entering(tcp))
			tprintf("devid=%" PRI__u64 ", ", args.devid);

		tprintf("nr_items=%" PRI__u64 ", flags=", args.nr_items);
		printflags64(btrfs_dev_stats_flags, args.flags,
			     "BTRFS_DEV_STATS_???");

		if (entering(tcp)) {
			tprints("}");
			return 0;
		}

		/*
		 * The structure has a 1k limit; Let's make sure we don't
		 * go off into the middle of nowhere with a bad nr_items
		 * value.
		 */
		tprints(", [");
		for (i = 0; i < args.nr_items; i++) {
			if (i)
				tprints(", ");
			if (i >= ARRAY_SIZE(args.values)) {
				tprints("...");
				break;
			}
			const char *name = xlookup(btrfs_dev_stats_values, i);
			if (name)
				tprintf("/* %s */ ", name);
			tprintf("%" PRI__u64, args.values[i]);
		}
		tprints("]}");
		break;
	}

	case BTRFS_IOC_INO_LOOKUP: { /* RW */
		struct btrfs_ioctl_ino_lookup_args args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		if (entering(tcp)) {
			/* Use subvolume id of the containing root */
			if (args.treeid == 0)
				set_tcb_priv_ulong(tcp, 1);

			tprints("{treeid=");
			btrfs_print_objectid(args.treeid);
			tprints(", objectid=");
			btrfs_print_objectid(args.objectid);
			tprints("}");
			return 0;
		}

		tprints("{");
		if (get_tcb_priv_ulong(tcp)) {
			tprints("treeid=");
			btrfs_print_objectid(args.treeid);
			tprints(", ");
		}

		tprints("name=");
		print_quoted_string(args.name, sizeof(args.name),
				    QUOTE_0_TERMINATED);
		tprints("}");
		break;
	}

	case BTRFS_IOC_INO_PATHS: { /* RW */
		struct btrfs_ioctl_ino_path_args args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{");

		if (entering(tcp)) {
			tprintf("inum=%" PRI__u64 ", size=%" PRI__u64,
				args.inum, args.size);
			tprintf(", fspath=0x%" PRI__x64 "}", args.fspath);
			return 0;
		}

		tprints("fspath=");
		btrfs_print_ino_path_container(tcp, args.fspath);

		tprints("}");
		break;
	}

	case BTRFS_IOC_LOGICAL_INO: { /* RW */
		struct btrfs_ioctl_logical_ino_args args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{");

		if (entering(tcp)) {
			tprintf("logical=%" PRI__u64 ", size=%" PRI__u64,
				args.logical, args.size);
			tprintf(", inodes=0x%" PRI__x64 "}", args.inodes);
			return 0;
		}

		tprints("inodes=");
		btrfs_print_logical_ino_container(tcp, args.inodes);

		tprints("}");
		break;
	}

	case BTRFS_IOC_QGROUP_ASSIGN: { /* W */
		struct btrfs_ioctl_qgroup_assign_args args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprintf("{assign=%" PRI__u64 ", src=%" PRI__u64
			", dst=%" PRI__u64 "}",
			args.assign, args.src, args.dst);
		break;
	}

	case BTRFS_IOC_QGROUP_CREATE: { /* W */
		struct btrfs_ioctl_qgroup_create_args args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprintf("{create=%" PRI__u64 ", qgroupid=%" PRI__u64 "}",
			args.create, args.qgroupid);
		break;
	}

	case BTRFS_IOC_QGROUP_LIMIT: { /* R */
		struct btrfs_ioctl_qgroup_limit_args args;

		if (entering(tcp))
			return 0;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprintf("{qgroupid=%" PRI__u64 ", lim=", args.qgroupid);
		btrfs_print_qgroup_limit(&args.lim);
		tprints("}");
		break;
	}

	case BTRFS_IOC_QUOTA_CTL: { /* W */
		struct btrfs_ioctl_quota_ctl_args args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		printxval64(btrfs_qgroup_ctl_cmds, args.cmd,
			    "BTRFS_QUOTA_CTL_???");
		tprints("}");

		break;
	}

	case BTRFS_IOC_QUOTA_RESCAN: { /* W */
		struct btrfs_ioctl_quota_rescan_args args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprintf("{flags=%" PRIu64 "}", (uint64_t) args.flags);
		break;
	}

	case BTRFS_IOC_QUOTA_RESCAN_STATUS: { /* R */
		struct btrfs_ioctl_quota_rescan_args args;

		if (entering(tcp))
			return 0;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprintf("{flags=%" PRIu64 ", progress=", (uint64_t) args.flags);
		btrfs_print_objectid(args.progress);
		tprints("}");
		break;
	}

	case BTRFS_IOC_SET_RECEIVED_SUBVOL: { /* RW */
		struct_btrfs_ioctl_received_subvol_args args;
		char uuid[UUID_STRING_SIZE+1];

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		if (entering(tcp)) {
			btrfs_unparse_uuid((unsigned char *)args.uuid, uuid);
			tprintf("{uuid=%s, stransid=%" PRIu64
				", stime=%" PRIu64 ".%u, flags=%" PRIu64
				"}", uuid, (uint64_t) args.stransid,
				(uint64_t) args.stime.sec, args.stime.nsec,
				(uint64_t) args.flags);
			return 0;
		}
		tprintf("{rtransid=%" PRIu64 ", rtime=%" PRIu64 ".%u}",
			(uint64_t) args.rtransid, (uint64_t) args.rtime.sec,
			args.rtime.nsec);
		break;
	}

	case BTRFS_IOC_SCRUB: /* RW */
	case BTRFS_IOC_SCRUB_PROGRESS: { /* RW */
		struct btrfs_ioctl_scrub_args args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		if (entering(tcp)) {
			tprintf("{devid=%" PRI__u64, args.devid);
			if (code == BTRFS_IOC_SCRUB) {
				tprintf(", start=%" PRI__u64 ", end=",
					args.start);
				tprintf("%" PRI__u64, args.end);
				if (args.end == UINT64_MAX)
					tprints(" /* UINT64_MAX */");
				tprints(", flags=");
				printflags64(btrfs_scrub_flags, args.flags,
					     "BTRFS_SCRUB_???");
			}
			tprints("}");
			return 0;
		}
		tprintf("{data_extents_scrubbed=%" PRI__u64
			", tree_extents_scrubbed=%" PRI__u64
			", data_bytes_scrubbed=%" PRI__u64
			", tree_bytes_scrubbed=%" PRI__u64
			", read_errors=%" PRI__u64
			", csum_errors=%" PRI__u64
			", verify_errors=%" PRI__u64
			", no_csum=%" PRI__u64
			", csum_discards=%" PRI__u64
			", super_errors=%" PRI__u64
			", malloc_errors=%" PRI__u64
			", uncorrectable_errors=%" PRI__u64
			", corrected_errors=%" PRI__u64
			", last_physical=%" PRI__u64
			", unverified_errors=%" PRI__u64 "}",
			args.progress.data_extents_scrubbed,
			args.progress.tree_extents_scrubbed,
			args.progress.data_bytes_scrubbed,
			args.progress.tree_bytes_scrubbed,
			args.progress.read_errors,
			args.progress.csum_errors,
			args.progress.verify_errors,
			args.progress.no_csum,
			args.progress.csum_discards,
			args.progress.super_errors,
			args.progress.malloc_errors,
			args.progress.uncorrectable_errors,
			args.progress.corrected_errors,
			args.progress.last_physical,
			args.progress.unverified_errors);
		break;
	}

	case BTRFS_IOC_TREE_SEARCH: { /* RW */
		struct btrfs_ioctl_search_args args;
		uint64_t buf_offset;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		buf_offset = offsetof(struct btrfs_ioctl_search_args, buf);
		btrfs_print_tree_search(tcp, &args.key, arg + buf_offset,
					sizeof(args.buf), false);
		if (entering(tcp))
			return 0;
		break;
	}

	case BTRFS_IOC_TREE_SEARCH_V2: { /* RW */
		struct btrfs_ioctl_search_args_v2 args;
		uint64_t buf_offset;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp)) {
			if (tcp->u_error == EOVERFLOW) {
				tprints(" => ");
				tcp->u_error = 0;
				if (!umove_or_printaddr(tcp, arg, &args))
					tprintf("{buf_size=%" PRIu64 "}",
						(uint64_t)args.buf_size);
				tcp->u_error = EOVERFLOW;
			}
			break;
		} else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		buf_offset = offsetof(struct btrfs_ioctl_search_args_v2, buf);
		btrfs_print_tree_search(tcp, &args.key, arg + buf_offset,
					args.buf_size, true);
		if (entering(tcp))
			return 0;
		break;
	}

	case BTRFS_IOC_SEND: { /* W */
		struct_btrfs_ioctl_send_args args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{send_fd=");
		printfd(tcp, args.send_fd);
		tprintf(", clone_sources_count=%" PRIu64 ", clone_sources=",
			(uint64_t) args.clone_sources_count);

		if (abbrev(tcp))
			tprints("...");
		else {
			uint64_t record;
			print_array(tcp, (unsigned long) args.clone_sources,
				    args.clone_sources_count,
				    &record, sizeof(record),
				    umoven_or_printaddr,
				    print_objectid_callback, 0);
		}
		tprints(", parent_root=");
		btrfs_print_objectid(args.parent_root);
		tprints(", flags=");
		printflags64(btrfs_send_flags, args.flags,
			     "BTRFS_SEND_FLAGS_???");
		tprints("}");
		break;
	}

	case BTRFS_IOC_SPACE_INFO: { /* RW */
		struct btrfs_ioctl_space_args args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{");
		if (entering(tcp)) {
			tprintf("space_slots=%" PRI__u64 "}", args.space_slots);
			return 0;
		}

		tprintf("total_spaces=%" PRI__u64, args.total_spaces);

		if (args.space_slots == 0 && args.total_spaces) {
			tprints("}");
			break;
		}

		tprints(", spaces=");

		if (abbrev(tcp))
			tprints("...");
		else {
			struct btrfs_ioctl_space_info info;
			print_array(tcp, arg + offsetof(typeof(args), spaces),
				    args.total_spaces,
				    &info, sizeof(info), umoven_or_printaddr,
				    print_btrfs_ioctl_space_info, 0);
		}
		tprints("}");
		break;
	}

	case BTRFS_IOC_SNAP_CREATE:
	case BTRFS_IOC_RESIZE:
	case BTRFS_IOC_SCAN_DEV:
	case BTRFS_IOC_ADD_DEV:
	case BTRFS_IOC_RM_DEV:
	case BTRFS_IOC_SUBVOL_CREATE:
	case BTRFS_IOC_SNAP_DESTROY:
	case BTRFS_IOC_DEVICES_READY: { /* W */
		struct btrfs_ioctl_vol_args args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{fd=");
		printfd(tcp, args.fd);
		tprints(", name=");
		print_quoted_string(args.name, sizeof(args.name),
				    QUOTE_0_TERMINATED);
		tprints("}");
		break;
	}

	case BTRFS_IOC_SNAP_CREATE_V2:
	case BTRFS_IOC_SUBVOL_CREATE_V2: { /* code is W, but is actually RW */
		struct btrfs_ioctl_vol_args_v2 args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		if (entering(tcp)) {
			tprints("{fd=");
			printfd(tcp, args.fd);
			tprints(", flags=");
			printflags64(btrfs_snap_flags_v2, args.flags,
				     "BTRFS_SUBVOL_???");
			if (args.flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
				tprintf(", size=%" PRI__u64 ", qgroup_inherit=",
					args.size);

				btrfs_print_qgroup_inherit(tcp,
					(unsigned long)args.qgroup_inherit);
			}
			tprintf(", name=");
			print_quoted_string(args.name, sizeof(args.name),
					    QUOTE_0_TERMINATED);
			tprints("}");
			return 0;
		}
		tprintf("{transid=%" PRI__u64 "}", args.transid);
		break;
	}

	case BTRFS_IOC_GET_FSLABEL: /* R */
		if (entering(tcp))
			return 0;
		/* fall through */
	case BTRFS_IOC_SET_FSLABEL: { /* W */
		char label[BTRFS_LABEL_SIZE];

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &label))
			break;
		print_quoted_string(label, sizeof(label), QUOTE_0_TERMINATED);
		break;
	}

	case BTRFS_IOC_CLONE:			/* FICLONE */
	case BTRFS_IOC_CLONE_RANGE:		/* FICLONERANGE */
#ifdef BTRFS_IOC_FILE_EXTENT_SAME
	case BTRFS_IOC_FILE_EXTENT_SAME:	/* FIDEDUPERANGE */
#endif
		/*
		 * FICLONE, FICLONERANGE, and FIDEDUPERANGE started out as
		 * btrfs ioctls and the code was kept for the generic
		 * implementations.  We use the BTRFS_* names here because
		 * they will be available on older systems.
		 */
		return file_ioctl(tcp, code, arg);

	default:
		return RVAL_DECODED;
	};
	return RVAL_DECODED | 1;
}
Пример #7
0
int sam_watchdog_initialize(void)
{
#if (defined(CONFIG_SAM34_WDT) && !defined(CONFIG_WDT_DISABLE_ON_RESET))
  FAR struct file filestruct;
  int ret;

  /* Initialize tha register the watchdog timer device */

  wdinfo("Initializing Watchdog driver...\n");

  sam_wdtinitialize(CONFIG_WATCHDOG_DEVPATH);

  /* Open the watchdog device */

  wdinfo("Opening.\n");

  ret = file_open(&filestruct, CONFIG_WATCHDOG_DEVPATH, O_RDONLY);
  if (ret < 0)
    {
      wderr("ERROR: open %s failed: %d\n", CONFIG_WATCHDOG_DEVPATH, ret);
      goto errout;
    }

  /* Set the watchdog timeout */

  wdinfo("Timeout = %d.\n", CONFIG_WDT_TIMEOUT);

  ret = file_ioctl(&filestruct, WDIOC_SETTIMEOUT,
                   (unsigned long)CONFIG_WDT_TIMEOUT);
  if (ret < 0)
    {
      wderr("ERROR: ioctl(WDIOC_SETTIMEOUT) failed: %d\n", errno);
      goto errout_with_dev;
    }

  /* Set the watchdog minimum time */

  wdinfo("MinTime = %d.\n", CONFIG_WDT_MINTIME);
  ret = file_ioctl(&filestruct, WDIOC_MINTIME,
                   (unsigned long)CONFIG_WDT_MINTIME);
  if (ret < 0)
    {
      wderr("ERROR: ioctl(WDIOC_MINTIME) failed: %d\n", errno);
      goto errout_with_dev;
    }

  /* Start Kicker task */

#if defined(CONFIG_WDT_THREAD)
  sched_lock();

  int taskid = kthread_create(CONFIG_WDT_THREAD_NAME,
                              CONFIG_WDT_THREAD_PRIORITY,
                              CONFIG_WDT_THREAD_STACKSIZE,
                              (main_t)wdog_daemon, (FAR char * const *)NULL);

  DEBUGASSERT(taskid > 0);
  UNUSED(taskid);

  sched_unlock();
#endif
  return OK;
errout_with_dev:
  file_close(&filestruct);
errout:
  return ret;
#else
  return -ENODEV;
#endif
}
Пример #8
0
static int
ioctl_decode(struct tcb *tcp)
{
	const unsigned int code = tcp->u_arg[1];
	const kernel_ulong_t arg = tcp->u_arg[2];

	switch (_IOC_TYPE(code)) {
#if defined(ALPHA) || defined(POWERPC)
	case 'f': {
		int ret = file_ioctl(tcp, code, arg);
		if (ret != RVAL_DECODED)
			return ret;
	}
	case 't':
	case 'T':
		return term_ioctl(tcp, code, arg);
#else /* !ALPHA */
	case 'f':
		return file_ioctl(tcp, code, arg);
	case 0x54:
#endif /* !ALPHA */
		return term_ioctl(tcp, code, arg);
	case 0x89:
		return sock_ioctl(tcp, code, arg);
	case 'p':
		return rtc_ioctl(tcp, code, arg);
	case 0x03:
		return hdio_ioctl(tcp, code, arg);
	case 0x12:
		return block_ioctl(tcp, code, arg);
	case 'X':
		return fs_x_ioctl(tcp, code, arg);
	case 0x22:
		return scsi_ioctl(tcp, code, arg);
	case 'L':
		return loop_ioctl(tcp, code, arg);
	case 'M':
		return mtd_ioctl(tcp, code, arg);
	case 'o':
	case 'O':
		return ubi_ioctl(tcp, code, arg);
	case 'V':
		return v4l2_ioctl(tcp, code, arg);
	case '=':
		return ptp_ioctl(tcp, code, arg);
#ifdef HAVE_LINUX_INPUT_H
	case 'E':
		return evdev_ioctl(tcp, code, arg);
#endif
#ifdef HAVE_LINUX_USERFAULTFD_H
	case 0xaa:
		return uffdio_ioctl(tcp, code, arg);
#endif
#ifdef HAVE_LINUX_BTRFS_H
	case 0x94:
		return btrfs_ioctl(tcp, code, arg);
#endif
#ifdef HAVE_LINUX_DM_IOCTL_H
	case 0xfd:
		return dm_ioctl(tcp, code, arg);
#endif
	default:
		break;
	}
	return 0;
}
Пример #9
0
/*
 * When you add any new common ioctls to the switches above and below
 * please update compat_sys_ioctl() too.
 *
 * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
 * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
 */
int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg)
{
	unsigned int flag;
	int on, error = 0;
	umode_t mode;
	
	struct _file *_filp = tx_cache_get_file(filp);
	/* Patch up ioctl for bad tx cases*/
	if((!_filp) || !_filp->f_dentry ){
#ifdef CONFIG_TX_KSTM_WARNINGS
		printk(KERN_ERR "Fixing up ioctl\n");
#endif
		return 0;
	}
	mode = d_get_inode_ro(f_get_dentry(_filp))->i_mode;

	switch (cmd) {
		case FIOCLEX:
			set_close_on_exec(fd, 1);
			break;

		case FIONCLEX:
			set_close_on_exec(fd, 0);
			break;

		case FIONBIO:
			if ((error = get_user(on, (int __user *)arg)) != 0)
				break;
			flag = O_NONBLOCK;
#ifdef __sparc__
			/* SunOS compatibility item. */
			if(O_NONBLOCK != O_NDELAY)
				flag |= O_NDELAY;
#endif
			if (on)
				_filp->f_flags |= flag;
			else
				_filp->f_flags &= ~flag;
			break;

		case FIOASYNC:
			if ((error = get_user(on, (int __user *)arg)) != 0)
				break;
			flag = on ? FASYNC : 0;

			/* Did FASYNC state change ? */
			if ((flag ^ _filp->f_flags) & FASYNC) {
				if (filp->f_op && filp->f_op->fasync) {
					lock_kernel();
					error = filp->f_op->fasync(fd, filp, on);
					unlock_kernel();
				}
				else error = -ENOTTY;
			}
			if (error != 0)
				break;

			if (on)
				_filp->f_flags |= FASYNC;
			else
				_filp->f_flags &= ~FASYNC;
			break;

		case FIOQSIZE:
			if (S_ISDIR(mode) ||
			    S_ISREG(mode) ||
			    S_ISLNK(mode)) {
				loff_t res = inode_get_bytes(f_get_dentry(_filp)->d_inode);
				error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
			}
			else
				error = -ENOTTY;
			break;
		default:
			if(live_transaction()){
				/* Short circuit this stupid ioctl */
				if(cmd == TIOCGWINSZ){
#ifdef CONFIG_TX_KSTM_WARNINGS
					printk(KERN_ERR "Warning: some bozo wants to know the terminal width in a transaction.\n");
#endif
					error = -EINVAL;
					break;
				} else if(cmd != TCGETS)
					BUG();
			}

			if (S_ISREG(mode))
				error = file_ioctl(filp, cmd, arg);
			else
				error = do_ioctl(filp, cmd, arg);
			break;
	}
	return error;
}
Пример #10
0
static ssize_t pty_read(FAR struct file *filep, FAR char *buffer, size_t len)
{
  FAR struct inode *inode;
  FAR struct pty_dev_s *dev;
  ssize_t ntotal;
#ifdef CONFIG_SERIAL_TERMIOS
  ssize_t nread;
  size_t i;
  char ch;
  int ret;
#endif

  DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
  inode = filep->f_inode;
  dev   = inode->i_private;
  DEBUGASSERT(dev != NULL);

#ifdef CONFIG_SERIAL_TERMIOS
  /* Do input processing if any is enabled
   *
   * Specifically not handled:
   *
   *   All of the local modes; echo, line editing, etc.
   *   Anything to do with break or parity errors.
   *   ISTRIP     - We should be 8-bit clean.
   *   IUCLC      - Not Posix
   *   IXON/OXOFF - No xon/xoff flow control.
   */

  if (dev->pd_iflag & (INLCR | IGNCR | ICRNL))
    {
      /* We will transfer one byte at a time, making the appropriate
       * translations.
       */

      ntotal = 0;
      for (i = 0; i < len; i++)
        {
#ifndef CONFIG_PSEUDOTERM_FULLBLOCKS
          /* This logic should return if the pipe becomes empty after some
           * bytes were read from the pipe.  If we have already read some
           * data, we use the FIONREAD ioctl to test if there are more bytes
           * in the pipe.
           *
           * REVISIT:  An alternative design might be to (1) configure the
           * source file as non-blocking, then (2) wait using poll() for the
           * first byte to be received.  (3) Subsequent bytes would
           * use file_read() without polling and would (4) terminate when no
           * data is returned.
           */

          if (ntotal > 0)
            {
              int nsrc;

              /* There are inherent race conditions in this test.  We lock
               * the scheduler before the test and after the file_read()
               * below to eliminate one race:  (a) We detect that there is
               * data in the source file, (b) we are suspended and another
               * thread reads the data, emptying the fifo, then (c) we
               * resume and call file_read(), blocking indefinitely.
               */

              sched_lock();

              /* Check how many bytes are waiting in the pipe */

              ret = file_ioctl(&dev->pd_src, FIONREAD,
                               (unsigned long)((uintptr_t)&nsrc));
              if (ret < 0)
                {
                  sched_unlock();
                  ntotal = ret;
                  break;
                }

              /* Break out of the loop and return ntotal if the pipe is
               * empty.  This is another race:  There fifo was empty when we
               * called file_ioctl() above, but it might not be empty right
               * now.  Losing that race should not lead to any bad behaviors,
               * however, we the caller will get those bytes on the next
               * read.
               */

              if (nsrc < 1)
                {
                  sched_unlock();
                  break;
                }

              /* Read one byte from the source the byte.  This should not
               * block.
               */

              nread = file_read(&dev->pd_src, &ch, 1);
              sched_unlock();
            }
          else
#else
          /* If we wanted to return full blocks of data, then file_read()
           * may need to be called repeatedly.  That is because the pipe
           * read() method will return early if the fifo becomes empty
           * after any data has been read.
           */

# error Missing logic
#endif
            {
              /* Read one byte from the source the byte.  This call will
               * block if the source pipe is empty.
               *
               * REVISIT: Should not block if the oflags include O_NONBLOCK.
               * How would we ripple the O_NONBLOCK characteristic to the
               * contained soruce pipe?  file_vfcntl()?  Or FIONREAD? See the
               * TODO comment at the top of this file.
               */

              nread = file_read(&dev->pd_src, &ch, 1);
            }

          /* Check if file_read was successful */

          if (nread < 0)
            {
              ntotal = nread;
              break;
            }

          /* Perform input processing */
          /* \n -> \r or \r -> \n translation? */

          if (ch == '\n' && (dev->pd_iflag & INLCR) != 0)
            {
               ch = '\r';
            }
          else if (ch == '\r' && (dev->pd_iflag & ICRNL) != 0)
            {
              ch = '\n';
            }

          /* Discarding \r ?  Print character if (1) character is not \r or
           * if (2) we were not asked to ignore \r.
           */

          if (ch != '\r' || (dev->pd_iflag & IGNCR) == 0)
            {

              /* Transfer the (possibly translated) character and update the
               * count of bytes transferred.
               */

              *buffer++ = ch;
              ntotal++;
            }
        }
    }
  else
#endif
    {
      /* NOTE: the source pipe will block if no data is available in
       * the pipe.   Otherwise, it will return data from the pipe.  If
       * there are fewer than 'len' bytes in the, it will return with
       * ntotal < len.
       *
       * REVISIT: Should not block if the oflags include O_NONBLOCK.
       * How would we ripple the O_NONBLOCK characteristic to the
       * contained source pipe? file_vfcntl()?  Or FIONREAD?  See the
       * TODO comment at the top of this file.
       */

      ntotal = file_read(&dev->pd_src, buffer, len);
    }

  return ntotal;
}
Пример #11
0
asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{	
	struct file * filp;
	unsigned int flag;
	int on, error = -EBADF;

	filp = fget(fd);
	if (!filp)
		goto out;

	error = security_file_ioctl(filp, cmd, arg);
	if (error) {
                fput(filp);
                goto out;
        }

	lock_kernel();
	switch (cmd) {
		case FIOCLEX:
			set_close_on_exec(fd, 1);
			break;

		case FIONCLEX:
			set_close_on_exec(fd, 0);
			break;

		case FIONBIO:
			if ((error = get_user(on, (int __user *)arg)) != 0)
				break;
			flag = O_NONBLOCK;
#ifdef __sparc__
			/* SunOS compatibility item. */
			if(O_NONBLOCK != O_NDELAY)
				flag |= O_NDELAY;
#endif
			if (on)
				filp->f_flags |= flag;
			else
				filp->f_flags &= ~flag;
			break;

		case FIOASYNC:
			if ((error = get_user(on, (int __user *)arg)) != 0)
				break;
			flag = on ? FASYNC : 0;

			/* Did FASYNC state change ? */
			if ((flag ^ filp->f_flags) & FASYNC) {
				if (filp->f_op && filp->f_op->fasync)
					error = filp->f_op->fasync(fd, filp, on);
				else error = -ENOTTY;
			}
			if (error != 0)
				break;

			if (on)
				filp->f_flags |= FASYNC;
			else
				filp->f_flags &= ~FASYNC;
			break;

		case FIOQSIZE:
			if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
			    S_ISREG(filp->f_dentry->d_inode->i_mode) ||
			    S_ISLNK(filp->f_dentry->d_inode->i_mode)) {
				loff_t res = inode_get_bytes(filp->f_dentry->d_inode);
				error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
			}
			else
				error = -ENOTTY;
			break;
		default:
			error = -ENOTTY;
			if (S_ISREG(filp->f_dentry->d_inode->i_mode))
				error = file_ioctl(filp, cmd, arg);
			else if (filp->f_op && filp->f_op->ioctl)
				error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
	}
	unlock_kernel();
	fput(filp);

out:
	return error;
}
Пример #12
0
static int pty_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
  FAR struct inode *inode;
  FAR struct pty_dev_s *dev;
  FAR struct pty_devpair_s *devpair;
  int ret;

  DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
  inode   = filep->f_inode;
  dev     = inode->i_private;
  DEBUGASSERT(dev != NULL && dev->pd_devpair != NULL);
  devpair = dev->pd_devpair;

  /* Get exclusive access */

  pty_semtake(devpair);

  /* Handle IOCTL commands */

  switch (cmd)
    {
      /* PTY IOCTL commands would be handled here */

      case TIOCGPTN:    /* Get Pty Number (of pty-mux device): FAR int* */
        {
#ifdef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
          ret = -ENOSYS;
#else
          FAR int *ptyno = (FAR int *)((uintptr_t)arg);
          if (ptyno == NULL)
            {
              ret = -EINVAL;
            }
          else
            {
              *ptyno = (int)devpair->pp_minor;
              ret = OK;
            }
#endif
        }
        break;

      case TIOCSPTLCK:  /* Lock/unlock Pty: int */
        {
          if (arg == 0)
            {
               int sval;

               /* Unlocking */

               sched_lock();
               devpair->pp_locked = false;

               /* Release any waiting threads */

               do
                 {
                   DEBUGVERIFY(sem_getvalue(&devpair->pp_slavesem, &sval));
                   if (sval < 0)
                     {
                       sem_post(&devpair->pp_slavesem);
                     }
                 }
               while (sval < 0);

               sched_unlock();
               ret = OK;
            }
          else
            {
              /* Locking */

               devpair->pp_locked = true;
               ret = OK;
            }
        }
        break;

      case TIOCGPTLCK:  /* Get Pty lock state: FAR int* */
        {
          FAR int *ptr = (FAR int *)((uintptr_t)arg);
          if (ptr == NULL)
            {
              ret = -EINVAL;
            }
          else
            {
              *ptr = (int)devpair->pp_locked;
              ret = OK;
            }
        }
        break;

      /* Any unrecognized IOCTL commands will be passed to the contained
       * pipe driver.
       */

      default:
        {
          ret = file_ioctl(&dev->pd_src, cmd, arg);
          if (ret >= 0 || ret == -ENOTTY)
            {
              ret = file_ioctl(&dev->pd_sink, cmd, arg);
            }
        }
        break;
    }

  pty_semgive(devpair);
  return ret;
}
Пример #13
0
static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int ret = 0;
	__u32 ui32 = 0;
	__u16 ui16;
	struct dvb_frontend_event event;
	struct dvb_diseqc_master_cmd *sec;
	struct dtv_properties *cmdseq;
	struct dtv_property *tvp = NULL;
	char raw[1 + 3 + 3];
	td_fe t;

	switch(cmd)
	{
		case FE_GET_INFO:
			if (copy_to_user((struct dvb_frontend_info *)arg, &fe_info, sizeof(struct dvb_frontend_info)))
				ret = -EFAULT;
			break;
		case FE_READ_STATUS:
			file_ioctl(TD_FE_READ_STATUS_C, (__u32)&ui32);
			put_user(ui32, (__u32 *)arg);
			break;
		case FE_READ_BER:
			file_ioctl(TD_FE_SET_ERROR_SOURCE, ERR_SRC_VITERBI_BIT_ERRORS);
			file_ioctl(TD_FE_GET_ERRORS, (__u32)&ui32);
			put_user(ui32, (__u32 *)arg);
			break;
		case FE_READ_UNCORRECTED_BLOCKS:
			file_ioctl(TD_FE_SET_ERROR_SOURCE, ERR_SRC_PACKET_ERRORS);
			file_ioctl(TD_FE_GET_ERRORS, (__u32)&ui32);
			put_user(ui32, (__u32 *)arg);
			break;
		case FE_READ_SIGNAL_STRENGTH:
			file_ioctl(TD_FE_READ_SIGNAL_STRENGTH_C, (__u32)&ui16);
			put_user(ui16, (__u16 *)arg);
			break;
		case FE_READ_SNR:
			file_ioctl(TD_FE_READ_SNR_C, (__u32)&ui16);
			put_user(ui16, (__u16 *)arg);
			break;
		case FE_GET_EVENT:
			memset(&event, 0, sizeof(struct dvb_frontend_event));
			file_ioctl(TD_FE_READ_STATUS_C, (__u32)&ui32);
			event.status = ui32;
			file_ioctl(TD_FE_SETUP_GET, (__u32)&t);
			event.parameters.frequency = t.realfrq;
			if (event.status & FE_HAS_LOCK)
				file_ioctl(TD_FE_LOCKLED_ENABLE, 1);
			/* if no poll before GET_EVENT => return error
			   this is adopted to neutrino userspace behaviour */
			if (!polled)
				ret = -EWOULDBLOCK;
			if (copy_to_user((struct dvb_frontend_event *)arg, &event, sizeof(struct dvb_frontend_event)))
				ret = -EFAULT;
			polled = 0;
			break;
		case FE_SET_TONE:
			if (arg == SEC_TONE_ON)
				ui32 = 1;
			tone = ui32;
			ret = file_ioctl(TD_FE_22KHZ_ENABLE, ui32);
			break;
		case FE_SET_VOLTAGE:
			if (arg == SEC_VOLTAGE_OFF) {
				pol = SEC_VOLTAGE_OFF;
				tone = 0;
				file_ioctl(TD_FE_LOCKLED_ENABLE, 0);
				file_ioctl(TD_FE_LNB_ENABLE, 0);
				file_ioctl(TD_FE_22KHZ_ENABLE, 0);
				file_ioctl(TD_FE_SET_STANDBY, 1);
				file_ioctl(TD_FE_LNBLOOPTHROUGH, 1);
				break;
			}
			if (pol == SEC_VOLTAGE_OFF) {
				file_ioctl(TD_FE_DISEQC_MODE, DISEQC_MODE_CMD_ONLY);
				file_ioctl(TD_FE_LNBLOOPTHROUGH, 0);
				file_ioctl(TD_FE_SET_STANDBY, 0);
				file_ioctl(TD_FE_HARDRESET, 0);
				file_ioctl(TD_FE_INIT, 0);
				file_ioctl(TD_FE_LNB_ENABLE, 1);
				file_ioctl(TD_FE_LNB_SET_HORIZONTAL, 0);
			}
			if (arg == SEC_VOLTAGE_13)
				ui32 = 1;
			pol = ui32;
			ret = file_ioctl(TD_FE_LNB_SET_POLARISATION, ui32);
			break;
		case FE_DISEQC_SEND_MASTER_CMD:
			sec = (struct dvb_diseqc_master_cmd *)arg;
			memset(&raw[0], 0, 7);
			raw[0] = sec->msg_len;
			memcpy(&raw[1], sec->msg, sec->msg_len);
			ret = file_ioctl(TD_FE_DISEQC_SEND, (__u32)&raw);
			break;
		case FE_DISEQC_SEND_BURST:
			if (arg == SEC_MINI_B)
				ui32 = 1;
			ret = file_ioctl(TD_FE_DISEQC_SEND_BURST, ui32);
			break;
		case FE_SET_PROPERTY:
#define FREQUENCY 1
#define SYMBOL_RATE 4
#define DELIVERY_SYSTEM 5
			cmdseq = (struct dtv_properties *)arg;
			/* don't even try to tune to DVB-S2 */
			if (cmdseq->props[DELIVERY_SYSTEM].u.data != SYS_DVBS) {
				ret = -EINVAL;
				break;
			}
			t.fec = 0; /* always AUTO_FEC */
			t.frequency = cmdseq->props[FREQUENCY].u.data;
			t.symbolrate = cmdseq->props[SYMBOL_RATE].u.data / 1000;
			t.polarity = pol;
			t.highband = tone;
			file_ioctl(TD_FE_LOCKLED_ENABLE, 0);
			file_ioctl(TD_FE_STOPTHAT, 0);
			file_ioctl(TD_FE_SET_FRANGE, (int)(t.symbolrate / 500));
#ifdef USE_FINETUNE
			file_ioctl(TD_FE_SETUP_NBF, (__u32)&t);
#else
			file_ioctl(TD_FE_SETUP_NB, (__u32)&t);
#endif
			break;
		case FE_GET_PROPERTY:
			cmdseq = (struct dtv_properties *)arg;
			if (cmdseq->num != 1) { /* only DELSYS query supported for now */
				ret = -EINVAL;
				break;
			}
			tvp = kmalloc(cmdseq->num * sizeof(struct dtv_property), GFP_KERNEL);
			if (!tvp) {
				ret = -ENOMEM;
				break;
			}
			if (copy_from_user(tvp, (void __user *)cmdseq->props,
					   cmdseq->num * sizeof(struct dtv_property))) {
				ret = -EFAULT;
				kfree(tvp);
				break;
			}
			ret = -EINVAL;
			if (tvp->cmd == DTV_ENUM_DELSYS) {
				tvp->u.buffer.data[0] = SYS_DVBS;
				tvp->u.buffer.len = 1;
				tvp->result = 0;
				ret = 0;
				if (copy_to_user((void __user *)cmdseq->props, tvp,
						 cmdseq->num * sizeof(struct dtv_property)))
					ret = -EFAULT;
			}
			kfree(tvp);
			break;
		default:
			printk(KERN_ERR "td-dvb-fe: unhandled ioctl 0x%08x\n", cmd);
			ret = -EINVAL;
			break;
	}
	return ret;
}
Пример #14
0
/*
 * When you add any new common ioctls to the switches above and below
 * please update compat_sys_ioctl() too.
 *
 * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
 * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
 */
int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
	     unsigned long arg)
{
	int error = 0;
	int __user *argp = (int __user *)arg;

	switch (cmd) {
	case FIOCLEX:
		set_close_on_exec(fd, 1);
		break;

	case FIONCLEX:
		set_close_on_exec(fd, 0);
		break;

	case FIONBIO:
		error = ioctl_fionbio(filp, argp);
		break;

	case FIOASYNC:
		error = ioctl_fioasync(fd, filp, argp);
		break;

	case FIOQSIZE:
		if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) ||
		    S_ISREG(filp->f_path.dentry->d_inode->i_mode) ||
		    S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) {
			loff_t res =
				inode_get_bytes(filp->f_path.dentry->d_inode);
			error = copy_to_user((loff_t __user *)arg, &res,
					     sizeof(res)) ? -EFAULT : 0;
		} else
			error = -ENOTTY;
		break;

	case FIFREEZE:
		error = ioctl_fsfreeze(filp);
		break;

	case FITHAW:
		error = ioctl_fsthaw(filp);
		break;

	case FS_IOC_FIEMAP:
		return ioctl_fiemap(filp, arg);

	case FIGETBSZ:
	{
		struct super_block *sb = filp->f_path.dentry->d_inode->i_sb;
		int __user *p = (int __user *)arg;
		if (sb->s_blocksize == 1ul << sb->s_blocksize_bits)
			return put_user(sb->s_blocksize, p);
		/* fail through */
	}

	default:
		if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
			error = file_ioctl(filp, cmd, arg);
		else
			error = vfs_ioctl(filp, cmd, arg);
		break;
	}
	return error;
}
Пример #15
0
static int pty_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
  FAR struct inode *inode;
  FAR struct pty_dev_s *dev;
  FAR struct pty_devpair_s *devpair;
  int ret;

  DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
  inode   = filep->f_inode;
  dev     = inode->i_private;
  DEBUGASSERT(dev != NULL && dev->pd_devpair != NULL);
  devpair = dev->pd_devpair;

  /* Get exclusive access */

  pty_semtake(devpair);

  /* Handle IOCTL commands */

  switch (cmd)
    {
      /* PTY IOCTL commands would be handled here */

      case TIOCGPTN:    /* Get Pty Number (of pty-mux device): FAR int* */
        {
#ifdef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
          ret = -ENOSYS;
#else
          FAR int *ptyno = (FAR int *)((uintptr_t)arg);
          if (ptyno == NULL)
            {
              ret = -EINVAL;
            }
          else
            {
              *ptyno = (int)devpair->pp_minor;
              ret = OK;
            }
#endif
        }
        break;

      case TIOCSPTLCK:  /* Lock/unlock Pty: int */
        {
          if (arg == 0)
            {
               int sval;

               /* Unlocking */

               sched_lock();
               devpair->pp_locked = false;

               /* Release any waiting threads */

               do
                 {
                   DEBUGVERIFY(nxsem_getvalue(&devpair->pp_slavesem, &sval));
                   if (sval < 0)
                     {
                       nxsem_post(&devpair->pp_slavesem);
                     }
                 }
               while (sval < 0);

               sched_unlock();
               ret = OK;
            }
          else
            {
              /* Locking */

               devpair->pp_locked = true;
               ret = OK;
            }
        }
        break;

      case TIOCGPTLCK:  /* Get Pty lock state: FAR int* */
        {
          FAR int *ptr = (FAR int *)((uintptr_t)arg);
          if (ptr == NULL)
            {
              ret = -EINVAL;
            }
          else
            {
              *ptr = (int)devpair->pp_locked;
              ret = OK;
            }
        }
        break;

#ifdef CONFIG_SERIAL_TERMIOS
      case TCGETS:
        {
          FAR struct termios *termiosp = (FAR struct termios *)arg;

          if (!termiosp)
            {
              ret = -EINVAL;
              break;
            }

          /* And update with flags from this layer */

          termiosp->c_iflag = dev->pd_iflag;
          termiosp->c_oflag = dev->pd_oflag;
          termiosp->c_lflag = 0;
          ret = OK;
        }
        break;

      case TCSETS:
        {
          FAR struct termios *termiosp = (FAR struct termios *)arg;

          if (!termiosp)
            {
              ret = -EINVAL;
              break;
            }

          /* Update the flags we keep at this layer */

          dev->pd_iflag = termiosp->c_iflag;
          dev->pd_oflag = termiosp->c_oflag;
          ret = OK;
        }
        break;
#endif

      /* Get the number of bytes that are immediately available for reading
       * from the source pipe.
       */

      case FIONREAD:
        {
          ret = file_ioctl(&dev->pd_src, cmd, arg);
        }
        break;

      /* Get the number of bytes waiting in the sink pipe (FIONWRITE) or the
       * number of unused bytes in the sink pipe (FIONSPACE).
       */

      case FIONWRITE:
      case FIONSPACE:
        {
          ret = file_ioctl(&dev->pd_sink, cmd, arg);
        }
        break;

      /* Any unrecognized IOCTL commands will be passed to the contained
       * pipe driver.
       *
       * REVISIT:  We know for a fact that the pipe driver only supports
       * FIONREAD, FIONWRITE, FIONSPACE and PIPEIOC_POLICY.  The first two
       * are handled above and PIPEIOC_POLICY should not be managed by
       * applications -- it can break the PTY!
       */

      default:
        {
#if 0
          ret = file_ioctl(&dev->pd_src, cmd, arg);
          if (ret >= 0 || ret == -ENOTTY)
            {
              ret = file_ioctl(&dev->pd_sink, cmd, arg);
            }
#else
          ret = ENOTTY;
#endif
        }
        break;
    }

  pty_semgive(devpair);
  return ret;
}
Пример #16
0
/*
 * When you add any new common ioctls to the switches above and below
 * please update compat_sys_ioctl() too.
 *
 * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
 * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
 */
int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg)
{
	unsigned int flag;
	int on, error = 0;

	switch (cmd) {
		case FIOCLEX:
			set_close_on_exec(fd, 1);
			break;

		case FIONCLEX:
			set_close_on_exec(fd, 0);
			break;

		case FIONBIO:
			if ((error = get_user(on, (int __user *)arg)) != 0)
				break;
			flag = O_NONBLOCK;
#ifdef __sparc__
			/* SunOS compatibility item. */
			if(O_NONBLOCK != O_NDELAY)
				flag |= O_NDELAY;
#endif
			if (on)
				filp->f_flags |= flag;
			else
				filp->f_flags &= ~flag;
			break;

		case FIOASYNC:
			if ((error = get_user(on, (int __user *)arg)) != 0)
				break;
			flag = on ? FASYNC : 0;

			/* Did FASYNC state change ? */
			if ((flag ^ filp->f_flags) & FASYNC) {
				if (filp->f_op && filp->f_op->fasync) {
					lock_kernel();
					error = filp->f_op->fasync(fd, filp, on);
					unlock_kernel();
				}
				else error = -ENOTTY;
			}
			if (error != 0)
				break;

			if (on)
				filp->f_flags |= FASYNC;
			else
				filp->f_flags &= ~FASYNC;
			break;

		case FIOQSIZE:
			if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
			    S_ISREG(filp->f_dentry->d_inode->i_mode) ||
			    S_ISLNK(filp->f_dentry->d_inode->i_mode)) {
				loff_t res = inode_get_bytes(filp->f_dentry->d_inode);
				error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
			}
			else
				error = -ENOTTY;
			break;

		case FIFREEZE:
			error = ioctl_fsfreeze(filp);
			break;

		case FITHAW:
			error = ioctl_fsthaw(filp);
			break;

		default:
			if (S_ISREG(filp->f_dentry->d_inode->i_mode))
				error = file_ioctl(filp, cmd, arg);
			else
				error = do_ioctl(filp, cmd, arg);
			break;
	}
	return error;
}
Пример #17
0
/*
 * When you add any new common ioctls to the switches above and below
 * please update compat_sys_ioctl() too.
 *
 * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
 * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
 */
int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
	     unsigned long arg)
{
	int error = 0;
	int __user *argp = (int __user *)arg;
#ifdef CONFIG_LTT_LITE
	char ltt_string[LTT_LITE_MAX_LOG_STRING_SIZE];

	sprintf(ltt_string, "fd=%X/cmd=%X/arg=%X/pid=%d\n", fd,
		cmd, (int)arg, current->pid);
	ltt_lite_syscall_param(LTT_EV_FILE_SYSTEM_IOCTL, ltt_string,
		strlen(ltt_string));
	sprintf(ltt_string, "f_op=%X/pid=%d\n", (int)filp->f_op, current->pid);
	ltt_lite_syscall_param(LTT_EV_FILE_SYSTEM_IOCTL, ltt_string,
		strlen(ltt_string));
#endif

	switch (cmd) {
	case FIOCLEX:
		set_close_on_exec(fd, 1);
		break;

	case FIONCLEX:
		set_close_on_exec(fd, 0);
		break;

	case FIONBIO:
		/* BKL needed to avoid races tweaking f_flags */
		lock_kernel();
		error = ioctl_fionbio(filp, argp);
		unlock_kernel();
		break;

	case FIOASYNC:
		/* BKL needed to avoid races tweaking f_flags */
		lock_kernel();
		error = ioctl_fioasync(fd, filp, argp);
		unlock_kernel();
		break;

	case FIOQSIZE:
		if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) ||
		    S_ISREG(filp->f_path.dentry->d_inode->i_mode) ||
		    S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) {
			loff_t res =
				inode_get_bytes(filp->f_path.dentry->d_inode);
			error = copy_to_user((loff_t __user *)arg, &res,
					     sizeof(res)) ? -EFAULT : 0;
		} else
			error = -ENOTTY;
		break;

	case FIFREEZE:
		error = ioctl_fsfreeze(filp);
		break;

	case FITHAW:
		error = ioctl_fsthaw(filp);
		break;

	default:
		if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
			error = file_ioctl(filp, cmd, arg);
		else
			error = vfs_ioctl(filp, cmd, arg);
		break;
	}
	return error;
}