SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) { struct file * file; int error = -EBADF; struct dentry * dentry; file = fget(fd); if (!file) goto out; error = mnt_want_write_file(file); if (error) goto out_fput; dentry = file->f_path.dentry; audit_inode(NULL, dentry); error = chown_common(&file->f_path, user, group); mnt_drop_write(file->f_path.mnt); out_fput: fput(file); out: return error; }
asmlinkage int sunos_getdents(unsigned int fd, void __user *dirent, int cnt) { struct file * file; struct sunos_dirent __user *lastdirent; struct sunos_dirent_callback buf; int error = -EBADF; if (fd >= SUNOS_NR_OPEN) goto out; file = fget(fd); if (!file) goto out; error = -EINVAL; if (cnt < (sizeof(struct sunos_dirent) + 255)) goto out_putf; buf.curr = (struct sunos_dirent __user *) dirent; buf.previous = NULL; buf.count = cnt; buf.error = 0; error = vfs_readdir(file, sunos_filldir, &buf); if (error < 0) goto out_putf; lastdirent = buf.previous; error = buf.error; if (lastdirent) { put_user(file->f_pos, &lastdirent->d_off); error = cnt - buf.count; } out_putf: fput(file); out: return error; }
asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) { struct inode * inode; struct dentry * dentry; struct file * file; int err = -EBADF; struct iattr newattrs; file = fget(fd); if (!file) goto out; dentry = file->f_path.dentry; inode = dentry->d_inode; audit_inode(NULL, dentry); err = mnt_want_write(file->f_path.mnt); if (err) goto out_putf; err = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out_drop_write; mutex_lock(&inode->i_mutex); if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; err = notify_change(dentry, &newattrs); mutex_unlock(&inode->i_mutex); out_drop_write: mnt_drop_write(file->f_path.mnt); out_putf: fput(file); out: return err; }
/* To read a file: * o fget(fd) * o call its virtual read fs_op * o update f_pos * o fput() it * o return the number of bytes read, or an error * * Error cases you must handle for this function at the VFS level: * o EBADF * fd is not a valid file descriptor or is not open for reading. * o EISDIR * fd refers to a directory. * * In all cases, be sure you do not leak file refcounts by returning before * you fput() a file that you fget()'ed. */ int do_read(int fd, void *buf, size_t nbytes) { int bytes_read =0; file_t *f; if((f=fget(fd)) == NULL || curproc->p_files[fd] == NULL) { dbg(DBG_PRINT,"(GRADING2B) given file descriptor is not valid\n"); dbg(DBG_ERROR,"do_read(): the given %d fd is not a valid file descriptor\n",fd); return -EBADF; } if((f->f_mode & FMODE_READ) != FMODE_READ) { fput(f); dbg(DBG_PRINT,"(GRADING2B) the given file is not open for reading\n"); dbg(DBG_ERROR,"do_read(): FILE obtained is not open for reading\n"); return -EBADF; } if(S_ISDIR(f->f_vnode->vn_mode)) { dbg(DBG_PRINT,"(GRADING2B) The given file is actually a directory\n"); dbg(DBG_ERROR, "do_read(): obtained file is a directory\n"); fput(f); return -EISDIR; } bytes_read = f->f_vnode->vn_ops->read(f->f_vnode,f->f_pos,buf,nbytes); f->f_pos = bytes_read + f->f_pos; fput(f); return bytes_read; /*NOT_YET_IMPLEMENTED("VFS: do_read");*/ }
SYSCALL_DEFINE3(getdents64, unsigned int, fd, struct linux_dirent64 __user *, dirent, unsigned int, count) { struct file * file; struct linux_dirent64 __user * lastdirent; struct getdents_callback64 buf; int error; error = -EFAULT; if (!access_ok(VERIFY_WRITE, dirent, count)) goto out; error = -EBADF; file = fget(fd); if (!file) goto out; buf.current_dir = dirent; buf.previous = NULL; buf.file = file; buf.count = count; buf.error = 0; error = vfs_readdir(file, filldir64, &buf); if (error >= 0) error = buf.error; lastdirent = buf.previous; if (lastdirent) { typeof(lastdirent->d_off) d_off = file->f_pos; if (__put_user(d_off, &lastdirent->d_off)) error = -EFAULT; else error = count - buf.count; } fput(file); out: return error; }
asmlinkage long sys_getdents(unsigned int fd, struct linux_dirent __user * dirent, unsigned int count) { struct file * file; struct linux_dirent __user * lastdirent; struct getdents_callback buf; int error; error = -EFAULT; if (!access_ok(VERIFY_WRITE, dirent, count)) goto out; error = -EBADF; file = fget(fd); if (!file) goto out; buf.current_dir = dirent; buf.previous = NULL; buf.count = count; buf.error = 0; error = vfs_readdir(file, filldir, &buf); if (error < 0) goto out_putf; error = buf.error; lastdirent = buf.previous; if (lastdirent) { if (put_user(file->f_pos, &lastdirent->d_off)) error = -EFAULT; else error = count - buf.count; } out_putf: fput(file); out: return error; }
int efab_linux_trampoline_close32(int fd) { /* Firstly, is this one our sockets? If not, do the usual thing */ struct file *f; int rc; TRAMP_DEBUG("close32: %d\n", fd); efab_syscall_enter(); f = fget (fd); if (f) { if (FILE_IS_ENDPOINT(f)) { /* Yep -- it's one of ours. This means current process must be using the * module (otherwise how did one of our sockets get in this proc's fd * table?). It seems it didn't get intercepted -- trampoline back up. * However, only set up trampoline if this has been called via the * correct sys-call entry point */ if (setup_trampoline (PT_REGS_FROM_SYSCALL(), CI_TRAMP_OPCODE_CLOSE, fd, TRAMPOLINE_BITS_32) == 0) { /* The trampoline will get run. Let it handle the rest. */ fput(f); efab_syscall_exit(); return 0; } } /* Undo the fget above */ fput(f); } /* Not one of our FDs -- usual close */ rc = ((int (*)(int))THUNKPTR(state.replace_close->original_entry32))(fd); TRAMP_DEBUG("Close32: Chain returns %d \n", rc); efab_syscall_exit(); return rc; }
/* * Nfs server psuedo system call for the nfsd's * Based on the flag value it either: * - adds a socket to the selection list * - remains in the kernel as an nfsd * - remains in the kernel as an nfsiod * For INET6 we suppose that nfsd provides only IN6P_IPV6_V6ONLY sockets * and that mountd provides * - sockaddr with no IPv4-mapped addresses * - mask for both INET and INET6 families if there is IPv4-mapped overlap */ int nfssvc_nfsserver(struct thread *td, struct nfssvc_args *uap) { struct file *fp; struct nfsd_addsock_args addsockarg; struct nfsd_nfsd_args nfsdarg; cap_rights_t rights; int error; if (uap->flag & NFSSVC_ADDSOCK) { error = copyin(uap->argp, (caddr_t)&addsockarg, sizeof(addsockarg)); if (error) return (error); error = fget(td, addsockarg.sock, cap_rights_init(&rights, CAP_SOCK_SERVER), &fp); if (error) return (error); if (fp->f_type != DTYPE_SOCKET) { fdrop(fp, td); return (error); /* XXXRW: Should be EINVAL? */ } error = nfssvc_addsock(fp, td); fdrop(fp, td); } else if (uap->flag & NFSSVC_OLDNFSD) error = nfssvc_nfsd(td, NULL); else if (uap->flag & NFSSVC_NFSD) { if (!uap->argp) return (EINVAL); error = copyin(uap->argp, (caddr_t)&nfsdarg, sizeof(nfsdarg)); if (error) return (error); error = nfssvc_nfsd(td, &nfsdarg); } else error = ENXIO; return (error); }
/* **************************************************************** * Função "t_snd" * **************************************************************** */ int itnetsnd (int fd, const void *area, int count, int flags) { KFILE *fp; IOREQ io; /* * Prólogo */ if ((fp = fget (fd)) == NOKFILE) return (-1); u.u_oflag = fp->f_flags; if (MINOR (fp->f_inode->i_rdev) != TCP) { u.u_error = EINVAL; return (-1); } /* * Prepara o bloco de E/S */ /*** io.io_fd = ...; ***/ io.io_fp = fp; /*** io.io_ip = ...; ***/ /*** io.io_dev = ...; ***/ io.io_area = (void *)area; io.io_count = count; /*** io.io_offset_low = ...; ***/ /*** io.io_cpflag = ...; ***/ /*** io.io_rablock = ...; ***/ /* * Executa o "t_snd" */ k_snd (&io, flags); return (count - io.io_count); } /* end itnetsnd */
static mali_sync_pt *mali_stream_create_point_internal(int tl_fd, mali_bool timed) { struct sync_timeline *tl; struct sync_pt * pt; struct file *tl_file; tl_file = fget(tl_fd); if (tl_file == NULL) return NULL; if (tl_file->f_op != &stream_fops) { pt = NULL; goto out; } tl = tl_file->private_data; if (unlikely(timed)) { pt = mali_sync_timed_pt_alloc(tl); } else { pt = mali_sync_pt_alloc(tl); } if (!pt) { pt = NULL; goto out; } out: fput(tl_file); return pt; }
SYSCALL_DEFINE3(samba_reserve, int, fd, loff_t __user*, start, loff_t __user*, length) { struct file *file; long ret = -EBADF; loff_t st = 0, len = 0; file = fget(fd); if (!file) goto no_file_out; if (!start) { ret = -EINVAL; goto out; } if (!length) { ret = -EINVAL; goto out; } if (unlikely(copy_from_user(&st, start, sizeof(loff_t)))) { ret = -EFAULT; goto out; } if (unlikely(copy_from_user(&len, length, sizeof(loff_t)))) { ret = -EFAULT; goto out; } //printk("samba_reserve() %p, %lld, %lld\n", file, st, len); ret = do_preallocate(file, st, len); out: fput(file); no_file_out: return ret; }
long do_signalfd(int ufd, sigset_t *sigmask, int flags) { struct signalfd_ctx *ctx; if (ufd == -1) { ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; ctx->sigmask = *sigmask; /* * When we call this, the initialization must be complete, since * anon_inode_getfd() will install the fd. */ ufd = anon_inode_getfd("[signalfd]", &signalfd_fops, ctx, flags & (O_CLOEXEC | O_NONBLOCK)); if (ufd < 0) kfree(ctx); } else { struct file *file = fget(ufd); if (!file) return -EBADF; ctx = file->private_data; if (file->f_op != &signalfd_fops) { fput(file); return -EINVAL; } spin_lock_irq(¤t->sighand->siglock); ctx->sigmask = *sigmask; spin_unlock_irq(¤t->sighand->siglock); wake_up(¤t->sighand->signalfd_wqh); fput(file); } return ufd; }
SYSCALL_DEFINE3(old_readdir, unsigned int, fd, struct old_linux_dirent __user *, dirent, unsigned int, count) { int error; struct file * file; struct readdir_callback buf; error = -EBADF; file = fget(fd); if (!file) goto out; buf.result = 0; buf.dirent = dirent; error = vfs_readdir(file, fillonedir, &buf); if (buf.result) error = buf.result; fput(file); out: return error; }
asmlinkage int old_mmap(struct mmap_arg_struct *arg) { int error = -EFAULT; struct file * file = NULL; struct mmap_arg_struct a; lock_kernel(); if (copy_from_user(&a, arg, sizeof(a))) goto out; if (!(a.flags & MAP_ANONYMOUS)) { error = -EBADF; file = fget(a.fd); if (!file) goto out; } a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); if (file) fput(file); out: unlock_kernel(); return error; }
asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 __user *dirent, unsigned int count) { int error = -EBADF; struct file * file; struct readdir_callback32 buf; file = fget(fd); if (!file) goto out; buf.count = 0; buf.dirent = dirent; error = vfs_readdir(file, (filldir_t)fillonedir, &buf); if (error < 0) goto out_putf; error = buf.count; out_putf: fput(file); out: return error; }
/* common code for old and new mmaps */ static inline long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { int error = -EBADF; struct file * file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) goto out; } down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); if (file) fput(file); out: return error; }
struct socket *sockfd_to_socket(unsigned int sockfd) { struct socket *socket; struct file *file; struct inode *inode; file = fget(sockfd); if (!file) { pr_err("invalid sockfd\n"); return NULL; } inode = file_inode(file); if (!inode || !S_ISSOCK(inode->i_mode)) { fput(file); return NULL; } socket = SOCKET_I(inode); return socket; }
static int ksem_get(struct thread *td, semid_t id, cap_rights_t *rightsp, struct file **fpp) { struct ksem *ks; struct file *fp; int error; error = fget(td, id, rightsp, &fp); if (error) return (EINVAL); if (fp->f_type != DTYPE_SEM) { fdrop(fp, td); return (EINVAL); } ks = fp->f_data; if (ks->ks_flags & KS_DEAD) { fdrop(fp, td); return (EINVAL); } *fpp = fp; return (0); }
SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode) { struct inode * inode; struct dentry * dentry; struct file * file; int err = -EBADF; struct iattr newattrs; file = fget(fd); if (!file) goto out; dentry = file->f_path.dentry; inode = dentry->d_inode; audit_inode(NULL, dentry); err = mnt_want_write_file(file); if (err) goto out_putf; mutex_lock(&inode->i_mutex); err = security_path_chmod(dentry, file->f_vfsmnt, mode); if (err) goto out_unlock; if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; err = notify_change(dentry, &newattrs); out_unlock: mutex_unlock(&inode->i_mutex); mnt_drop_write(file->f_path.mnt); out_putf: fput(file); out: return err; }
/* Linux version of mmap */ static unsigned long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { struct file * file = NULL; unsigned long retval = -EBADF; if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) goto out; } retval = -EINVAL; len = PAGE_ALIGN(len); if (ARCH_SUN4C_SUN4 && (len > 0x20000000 || ((flags & MAP_FIXED) && addr < 0xe0000000 && addr + len > 0x20000000))) goto out_putf; /* See asm-sparc/uaccess.h */ if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) goto out_putf; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); down_write(¤t->mm->mmap_sem); retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); out_putf: if (file) fput(file); out: return retval; }
/* * Set the pipe fd for kernel communication to the daemon. * * Normally this is set at mount using an option but if we * are reconnecting to a busy mount then we need to use this * to tell the autofs mount about the new kernel pipe fd. In * order to protect mounts against incorrectly setting the * pipefd we also require that the autofs mount be catatonic. * * This also sets the process group id used to identify the * controlling process (eg. the owning automount(8) daemon). */ static int autofs_dev_ioctl_setpipefd(struct file *fp, struct autofs_sb_info *sbi, struct autofs_dev_ioctl *param) { int pipefd; int err = 0; if (param->setpipefd.pipefd == -1) return -EINVAL; pipefd = param->setpipefd.pipefd; mutex_lock(&sbi->wq_mutex); if (!sbi->catatonic) { mutex_unlock(&sbi->wq_mutex); return -EBUSY; } else { struct file *pipe = fget(pipefd); if (!pipe) { err = -EBADF; goto out; } if (!pipe->f_op || !pipe->f_op->write) { err = -EPIPE; fput(pipe); goto out; } sbi->oz_pgrp = task_pgrp_nr(current); sbi->pipefd = pipefd; sbi->pipe = pipe; sbi->catatonic = 0; sbi->compat_daemon = is_compat_task(); } out: mutex_unlock(&sbi->wq_mutex); return err; }
/* Same as do_dup, but insted of using get_empty_fd() to get the new fd, * they give it to us in 'nfd'. If nfd is in use (and not the same as ofd) * do_close() it first. Then return the new file descriptor. * * Error cases you must handle for this function at the VFS level: * o EBADF * ofd isn't an open file descriptor, or nfd is out of the allowed * range for file descriptors. */ int do_dup2(int ofd, int nfd) { /*dbg(DBG_PRINT," Entering do_dup2 ****************************************\n"); */ if (nfd < 0 || nfd >= NFILES || ofd == -1) { /*dbg(DBG_PRINT,"ofd %d nfd %d EBADF Leaving do_dup2 ****************************************\n",ofd,nfd);*/ dbg(DBG_PRINT,"(GRADING2C)\n"); return -EBADF; } file_t *f = fget(ofd); dbg(DBG_PRINT,"(GRADING2C)\n"); if (NULL == f){ dbg(DBG_PRINT,"(GRADING2C)\n"); /*dbg(DBG_PRINT,"ofd %d nfd %d EBADF Leaving do_dup2 ****************************************\n",ofd,nfd); */ return -EBADF; } if(nfd == ofd) { dbg(DBG_PRINT,"(GRADING2C)\n"); fput(f); return nfd; } if (curproc->p_files[nfd] != NULL && nfd != ofd) { dbg(DBG_PRINT,"(GRADING2C)\n"); do_close(nfd); } curproc->p_files[nfd] = f; /*dbg(DBG_PRINT," Leaving do_dup2 ****************************************\n");*/ return nfd; }
/* To dup a file: * o fget(fd) to up fd's refcount * o get_empty_fd() * o point the new fd to the same file_t* as the given fd * o return the new file descriptor * * Don't fput() the fd unless something goes wrong. Since we are creating * another reference to the file_t*, we want to up the refcount. * * Error cases you must handle for this function at the VFS level: * o EBADF * fd isn't an open file descriptor. * o EMFILE * The process already has the maximum number of file descriptors open * and tried to open a new one. */ int do_dup(int fd) { dbg(DBG_PRINT,"do_dup called for fd = %d\n", fd); /* NOT_YET_IMPLEMENTED("VFS: do_dup"); */ /*ERROR!!! fd is outside of allowed range of file descriptors*/ if ((fd >= NFILES) || ( fd < 0)) { dbg(DBG_PRINT,"ERROR!!! fd = %d is out of range\n", fd); return -EBADF; } /* o fget(fd) to up fd's refcount*/ file_t *cur_file_t = fget(fd); /* fd is not a valid file descriptor*/ if (cur_file_t == NULL) { dbg(DBG_PRINT,"ERROR!!! No file descriptor entry for correspoding fd = %d\n", fd); /* fput(cur_file_t); */ return -EBADF; } /* o get_empty_fd()*/ int new_fd = get_empty_fd(curproc); /* ERROR!!! The process already has the maximum number of files open.*/ if (new_fd == -EMFILE){ dbg(DBG_PRINT,"ERROR!!! Max limit of file descriptors reached fd\n"); fput(cur_file_t); return -EMFILE; } /* o point the new fd to the same file_t* as the given fd*/ curproc->p_files[new_fd] = cur_file_t; /* o return the new file descriptor*/ dbg(DBG_PRINT,"Returning fd = %d\n", new_fd); return new_fd; }
int options() { char answer[5]; system("clear"); printf("Copy Decrypt0r in the path ?\n"); printf("1) YES\n"); printf("2) NON\n"); fget(answer, 5); if (strcasecmp(answer, "yes")==0 || strcasecmp(answer, "1")==0) { printf("It will also copy dmg et xpwn\n"); system("chmod +x xpwn dmg"); system("sudo cp decrypt0r xpwn dmg /usr/local/bin"); printf("Done\n"); } else { return EXIT_SUCCESS; } }
static struct vperfctr *fd_get_vperfctr(int fd) { struct vperfctr *perfctr; struct file *filp; int err; err = -EBADF; filp = fget(fd); if (!filp) goto out; err = -EINVAL; if (filp->f_op != &vperfctr_file_ops) goto out_filp; perfctr = filp->private_data; if (!perfctr) goto out_filp; atomic_inc(&perfctr->count); fput(filp); return perfctr; out_filp: fput(filp); out: return ERR_PTR(err); }
static int mfi_linux_ioctl(struct thread *p, struct linux_ioctl_args *args) { cap_rights_t rights; struct file *fp; int error; u_long cmd = args->cmd; switch (cmd) { case MFI_LINUX_CMD: cmd = MFI_LINUX_CMD_2; break; case MFI_LINUX_SET_AEN: cmd = MFI_LINUX_SET_AEN_2; break; } error = fget(p, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); if (error != 0) return (error); error = fo_ioctl(fp, cmd, (caddr_t)args->arg, p->td_ucred, p); fdrop(fp, p); return (error); }
asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) { struct _inode * inode; struct _dentry * dentry; struct file * file; int err = -EBADF; struct iattr newattrs; file = fget(fd); if (!file) goto out; dentry = file_get_dentry(file); inode = d_get_inode(dentry); audit_inode(NULL, inode); err = -EROFS; if (IS_RDONLY(inode)) goto out_putf; err = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) goto out_putf; imutex_lock(parent(inode)); if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; err = notify_change(dentry, &newattrs); imutex_unlock(parent(inode)); out_putf: fput(file); out: return err; }
static struct socket *sockfd_lookup(int fd, int *err) { struct file *file; struct inode *inode; struct socket *sock; if (!(file = fget(fd))) { *err = -EBADF; return NULL; } inode = file->f_dentry->d_inode; if (!inode->i_sock || !(sock = socki_lookup(inode))) { *err = -ENOTSOCK; fput(file); return NULL; } if (sock->file != file) { printk(KERN_ERR "socki_lookup: socket file changed!\n"); sock->file = file; } return sock; }
/* * Zero curproc->p_files[fd], and fput() the file. Return 0 on success * * Error cases you must handle for this function at the VFS level: * o EBADF * fd isn't a valid open file descriptor. */ int do_close(int fd) { file_t *file; if (fd < 0) { dbg(DBG_PRINT,"(GRADING2B)\n"); return -EBADF; } file = fget(fd); dbg(DBG_PRINT,"(GRADING2B)\n"); if (file == NULL) { dbg(DBG_PRINT,"(GRADING2B)\n"); return -EBADF; } fput(file); curproc->p_files[fd] = NULL; fput(file); /*NOT_YET_IMPLEMENTED("VFS: do_close");*/ return 0; }
asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg) { struct file *filp; int error = -EBADF; filp = fget(fd); if (!filp) goto out; lock_kernel(); error = -EFAULT; switch ((cmd >> 8) & 0xff) { case 'S': error = solaris_S(filp, fd, cmd, arg); break; case 'T': error = solaris_T(fd, cmd, arg); break; case 'i': error = solaris_i(fd, cmd, arg); break; case 'r': error = solaris_r(fd, cmd, arg); break; case 's': error = solaris_s(fd, cmd, arg); break; case 't': error = solaris_t(fd, cmd, arg); break; case 'f': error = sys_ioctl(fd, cmd, arg); break; case 'm': error = solaris_m(fd, cmd, arg); break; case 'O': error = solaris_O(fd, cmd, arg); break; default: error = -ENOSYS; break; } unlock_kernel(); fput(filp); out: if (error == -ENOSYS) { unsigned char c = cmd>>8; if (c < ' ' || c > 126) c = '.'; printk("solaris_ioctl: Unknown cmd fd(%d) cmd(%08x '%c') arg(%08x)\n", (int)fd, (unsigned int)cmd, c, (unsigned int)arg); error = -EINVAL; }