int tty_ioctl(struct inode *inode, struct file *file, int cmd, register char *arg) { register struct tty *tty = determine_tty(inode->i_rdev); int ret; switch (cmd) { case TCGETS: ret = verified_memcpy_tofs(arg, &tty->termios, sizeof(struct termios)); break; case TCSETS: case TCSETSW: case TCSETSF: ret = verified_memcpy_fromfs(&tty->termios, arg, sizeof(struct termios)); /* Inform driver that things have changed */ if (tty->ops->ioctl != NULL) tty->ops->ioctl(tty, cmd, arg); break; default: ret = (tty->ops->ioctl == NULL) ? -EINVAL : tty->ops->ioctl(tty, cmd, arg); } return ret; }
int sys_utimes(char *filename, struct timeval *utimes) { int error; struct inode *inode; register struct inode *inodep; struct iattr newattrs; error = namei(filename, &inode, 0, 0); inodep = inode; if (error) return error; if (IS_RDONLY(inodep)) { iput(inodep); return -EROFS; } /* Don't worry, the checks are done in inode_change_ok() */ newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; if (utimes) { struct timeval times[2]; if (error = verified_memcpy_fromfs(×, utimes, sizeof(times))) { iput(inodep); return error; } newattrs.ia_atime = times[0].tv_sec; newattrs.ia_mtime = times[1].tv_sec; newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET; } else if ((error = permission(inodep, MAY_WRITE)) != 0) { iput(inodep); return error; } error = notify_change(inodep, &newattrs); iput(inodep); return error; }
/* set the time of day */ int sys_settimeofday(register struct timeval *tv, struct timezone *tz) { struct timeval tmp_tv; struct timezone tmp_tz; jiff_t now; /* only user running as root can set the time */ if (current->euid != 0) return -EPERM; /* verify we have valid addresses to read from */ if (tv != NULL) { if (verified_memcpy_fromfs(&tmp_tv, tv, sizeof(struct timeval))) return -EFAULT; if (((unsigned long) tmp_tv.tv_usec) >= 1000000L) return -EINVAL; } if (tz != NULL) { if (verified_memcpy_fromfs(&tmp_tz, tz, sizeof(struct timezone))) return -EFAULT; if (((unsigned int)(tmp_tz.tz_dsttime - DST_NONE)) > (DST_AUSTALT - DST_NONE)) return -EINVAL; /* Setting the timezone is easy, just a straight copy */ xzone = tmp_tz; } /* Setting time is a bit tricky, since we don't really keep the time in the xtime * structure. So we need to figure out the offset from the current time and * set xtime based on that. */ if (tv != NULL) { now = jiffies; xtime.tv_sec = tmp_tv.tv_sec - (now / HZ); xtime.tv_usec = tmp_tv.tv_usec - ((now % HZ) * (1000000l / HZ)); } /* success */ return 0; }
static void do_meta_request(kdev_t device) { struct ud_driver *driver = get_driver(major); struct ud_request *udr; struct request *req; char *buff; int major = MAJOR(device); printk("do_meta_request %d %x\n", major, blk_dev[major].current_request); if (NULL == driver) { end_request(0, req->rq_dev); return; } printk("1"); while (1) { req = blk_dev[major].current_request; printk("2"); if (!req || req->rq_dev < 0 || req->rq_sector == -1) return; printk("5"); udr = new_request(); udr->udr_type = UDR_BLK + req->rq_cmd; udr->udr_ptr = req->rq_sector; udr->udr_minor = MINOR(req->rq_dev); printk("6"); post_request(driver, udr); printk("7"); /* Should really check here whether we have a request */ if (req->rq_cmd == WRITE) { /* Can't do this, copies to the wrong task */ #if 0 verified_memcpy_tofs(driver->udd_data, buff, BLOCK_SIZE); /* FIXME FIXME */ fmemcpy(driver->udd_task->mm.dseg, driver->udd_data, get_ds(), buff, 1024); #endif } printk("8"); /* Wake up the driver so it can deal with the request */ wake_up(&driver->udd_wait); printk("request init: wake driver, sleeping\n"); sleep_on(&udr->udr_wait); printk("request continue\n"); /* REQUEST HAS BEEN RETURNED BY USER PROGRAM */ /* request must be dealt with and ended */ if (udr->udr_status == 1) { end_request(0, req->rq_dev); udr->udr_status = 0; continue; } udr->udr_status = 0; buff = req->rq_buffer; if (req->rq_cmd == READ) { /* Can't do this, copies from the wrong task */ #if 0 verified_memcpy_fromfs(buff, driver->udd_data, BLOCK_SIZE); /* FIXME FIXME */ fmemcpy(get_ds(), buff, driver->udd_task->mm.dseg, driver->udd_data, 1024); #endif } end_request(1, req->rq_dev); wake_up(&udr->udr_wait); } }
static int meta_ioctl(struct inode *inode, struct file *filp, int cmd, char *arg) { struct ud_driver *driver; int i, minor = MINOR(inode->i_rdev); printk("meta_ioctl %d %x\n", cmd, inode->i_rdev); if (minor == 0) { if (cmd != META_CREAT) return -EINVAL; printk("registering new "); for (i = 0; i < MAX_UDD; i++) if (drivers[i].udd_type == UDD_NONE) { minor = i + 1; break; } if (minor == 0) return -ENODEV; driver = &drivers[i]; verified_memcpy_fromfs(driver, arg, sizeof(struct ud_driver_trunc)); if (driver->udd_type == UDD_CHR_DEV) { printk("char "); if (register_chrdev(driver->udd_major, "meta", &ucd_fops) < 0) { goto reg_err; } } else if (driver->udd_type == UDD_BLK_DEV) { if ((i = verfy_area(driver->udd_data, 1024)) != 0) { driver->udd_type = UDD_NONE; return i; } printk("block "); /* verify are here on buffer */ if (register_blkdev(driver->udd_major, "meta", &ubd_fops) < 0) { goto reg_err; } blk_dev[driver->udd_major].request_fn = do_meta_request; } printk("device\n"); driver->udd_task = current; #if 0 driver->udd_rwait = NULL; /* FIXME: Not valid */ #endif return minor; reg_err: driver->udd_type = UDD_NONE; return -ENODEV; } driver = &drivers[minor - 1]; if (driver->udd_task != current) { printk("task mismatch %x %x\n", driver->udd_task, current); return -EINVAL; } switch (cmd) { case META_POLL: printk("waiting for request\n"); #if 0 driver->udd_wait = NULL; /* FIXME: not valid */ #endif driver->udd_req = NULL; wake_up(&driver->udd_rwait); interruptible_sleep_on(&driver->udd_wait); printk("Waking up\n"); if (driver->udd_req != NULL) { verified_memcpy_tofs(arg, driver->udd_req, sizeof(struct ud_request)); printk("here is the request\n"); return 0; } printk("No request! up\n"); return -EINTR; break; case META_ACK: printk("acknowledge request\n"); if (driver->udd_req == NULL) { printk("No request was pending!\n"); return -EINVAL; } verified_memcpy_fromfs(driver->udd_req, arg, sizeof(struct ud_request_trunc)); wake_up(&driver->udd_req->udr_wait); #if 0 driver->udd_req->udr_wait = NULL; /* FIXME: Not valid */ #endif interruptible_sleep_on(&driver->udd_req->udr_wait); break; default: printk("Bad ioctl\n"); return -EINVAL; } return 0; }
int sys_mount(char *dev_name, char *dir_name, char *type) { struct file_system_type *fstype; struct inode *inode; register struct inode *inodep; register struct file_operations *fops; kdev_t dev; int retval; char *t; int new_flags = 0; #ifdef CONFIG_FULL_VFS /* FIXME ltype is way too big for our stack goal.. */ char ltype[16]; /* is enough isn't it? */ #endif if (!suser()) return -EPERM; #ifdef BLOAT_FS /* new_flags is set to zero, so this is never true. */ if ((new_flags & MS_REMOUNT) == MS_REMOUNT) { retval = do_remount(dir_name, new_flags & ~MS_REMOUNT, NULL); return retval; } #endif /* * FIMXE: copy type to user cleanly or use numeric types ?? */ #ifdef CONFIG_FULL_VFS debug("MOUNT: performing type check\n"); if ((retval = strlen_fromfs(type)) >= 16) { debug("MOUNT: type size exceeds 16 characters, trunctating\n"); retval = 15; } verified_memcpy_fromfs(ltype, type, retval); ltype[retval] = '\0'; /* make asciiz again */ fstype = get_fs_type(ltype); if (!fstype) return -ENODEV; debug("MOUNT: type check okay\n"); #else fstype = file_systems[0]; #endif t = fstype->name; fops = NULL; #ifdef BLOAT_FS if (fstype->requires_dev) { #endif retval = namei(dev_name, &inode, 0, 0); if (retval) return retval; inodep = inode; debug("MOUNT: made it through namei\n"); if (!S_ISBLK(inodep->i_mode)) { NOTBLK: iput(inodep); return -ENOTBLK; } if (IS_NODEV(inodep)) { iput(inodep); return -EACCES; } dev = inodep->i_rdev; if (MAJOR(dev) >= MAX_BLKDEV) { iput(inodep); return -ENXIO; } fops = get_blkfops(MAJOR(dev)); if (!fops) { goto NOTBLK; } if (fops->open) { struct file dummy; /* allows read-write or read-only flag */ memset(&dummy, 0, sizeof(dummy)); dummy.f_inode = inodep; dummy.f_mode = (new_flags & MS_RDONLY) ? ((mode_t) 1) : ((mode_t) 3); retval = fops->open(inodep, &dummy); if (retval) { iput(inodep); return retval; } } #ifdef BLOAT_FS } else printk("unnumbered fs is unsupported.\n"); #endif retval = do_mount(dev, dir_name, t, new_flags, NULL); if (retval && fops && fops->release) fops->release(inodep, NULL); iput(inodep); return retval; }