OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [fcntl.c] - Diff between revs 1765 and 1782

Only display areas with differences | Details | Blame | View Log

Rev 1765 Rev 1782
/*
/*
 *  linux/fs/fcntl.c
 *  linux/fs/fcntl.c
 *
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */
 */
 
 
#include <asm/segment.h>
#include <asm/segment.h>
 
 
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/fcntl.h>
#include <linux/string.h>
#include <linux/string.h>
 
 
#include <asm/bitops.h>
#include <asm/bitops.h>
 
 
extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
 
 
static inline int dupfd(unsigned int fd, unsigned int arg)
static inline int dupfd(unsigned int fd, unsigned int arg)
{
{
        struct files_struct * files = current->files;
        struct files_struct * files = current->files;
 
 
        if (fd >= NR_OPEN || !files->fd[fd])
        if (fd >= NR_OPEN || !files->fd[fd])
                return -EBADF;
                return -EBADF;
        if (arg >= NR_OPEN)
        if (arg >= NR_OPEN)
                return -EINVAL;
                return -EINVAL;
        arg = find_next_zero_bit(&files->open_fds, NR_OPEN, arg);
        arg = find_next_zero_bit(&files->open_fds, NR_OPEN, arg);
        if (arg >= current->rlim[RLIMIT_NOFILE].rlim_cur)
        if (arg >= current->rlim[RLIMIT_NOFILE].rlim_cur)
                return -EMFILE;
                return -EMFILE;
        FD_SET(arg, &files->open_fds);
        FD_SET(arg, &files->open_fds);
        FD_CLR(arg, &files->close_on_exec);
        FD_CLR(arg, &files->close_on_exec);
        (files->fd[arg] = files->fd[fd])->f_count++;
        (files->fd[arg] = files->fd[fd])->f_count++;
        return arg;
        return arg;
}
}
 
 
asmlinkage int sys_dup2(unsigned int oldfd, unsigned int newfd)
asmlinkage int sys_dup2(unsigned int oldfd, unsigned int newfd)
{
{
        if (oldfd >= NR_OPEN || !current->files->fd[oldfd])
        if (oldfd >= NR_OPEN || !current->files->fd[oldfd])
                return -EBADF;
                return -EBADF;
        if (newfd == oldfd)
        if (newfd == oldfd)
                return newfd;
                return newfd;
        if (newfd >= NR_OPEN)
        if (newfd >= NR_OPEN)
                return -EBADF;  /* following POSIX.1 6.2.1 */
                return -EBADF;  /* following POSIX.1 6.2.1 */
 
 
        sys_close(newfd);
        sys_close(newfd);
        return dupfd(oldfd,newfd);
        return dupfd(oldfd,newfd);
}
}
 
 
asmlinkage int sys_dup(unsigned int fildes)
asmlinkage int sys_dup(unsigned int fildes)
{
{
        return dupfd(fildes,0);
        return dupfd(fildes,0);
}
}
 
 
asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
{
        struct file * filp;
        struct file * filp;
 
 
        if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
        if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
                return -EBADF;
                return -EBADF;
        switch (cmd) {
        switch (cmd) {
                case F_DUPFD:
                case F_DUPFD:
                        return dupfd(fd,arg);
                        return dupfd(fd,arg);
                case F_GETFD:
                case F_GETFD:
                        return FD_ISSET(fd, &current->files->close_on_exec);
                        return FD_ISSET(fd, &current->files->close_on_exec);
                case F_SETFD:
                case F_SETFD:
                        if (arg&1)
                        if (arg&1)
                                FD_SET(fd, &current->files->close_on_exec);
                                FD_SET(fd, &current->files->close_on_exec);
                        else
                        else
                                FD_CLR(fd, &current->files->close_on_exec);
                                FD_CLR(fd, &current->files->close_on_exec);
                        return 0;
                        return 0;
                case F_GETFL:
                case F_GETFL:
                        return filp->f_flags;
                        return filp->f_flags;
                case F_SETFL:
                case F_SETFL:
                        /*
                        /*
                         * In the case of an append-only file, O_APPEND
                         * In the case of an append-only file, O_APPEND
                         * cannot be cleared
                         * cannot be cleared
                         */
                         */
                        if (IS_APPEND(filp->f_inode) && !(arg & O_APPEND))
                        if (IS_APPEND(filp->f_inode) && !(arg & O_APPEND))
                                return -EPERM;
                                return -EPERM;
                        if ((arg & FASYNC) && !(filp->f_flags & FASYNC) &&
                        if ((arg & FASYNC) && !(filp->f_flags & FASYNC) &&
                            filp->f_op->fasync)
                            filp->f_op->fasync)
                                filp->f_op->fasync(filp->f_inode, filp, 1);
                                filp->f_op->fasync(filp->f_inode, filp, 1);
                        if (!(arg & FASYNC) && (filp->f_flags & FASYNC) &&
                        if (!(arg & FASYNC) && (filp->f_flags & FASYNC) &&
                            filp->f_op->fasync)
                            filp->f_op->fasync)
                                filp->f_op->fasync(filp->f_inode, filp, 0);
                                filp->f_op->fasync(filp->f_inode, filp, 0);
                        /* required for SunOS emulation */
                        /* required for SunOS emulation */
                        if (O_NONBLOCK != O_NDELAY)
                        if (O_NONBLOCK != O_NDELAY)
                               if (arg & O_NDELAY)
                               if (arg & O_NDELAY)
                                   arg |= O_NONBLOCK;
                                   arg |= O_NONBLOCK;
                        filp->f_flags &= ~(O_APPEND | O_NONBLOCK | FASYNC);
                        filp->f_flags &= ~(O_APPEND | O_NONBLOCK | FASYNC);
                        filp->f_flags |= arg & (O_APPEND | O_NONBLOCK |
                        filp->f_flags |= arg & (O_APPEND | O_NONBLOCK |
                                                FASYNC);
                                                FASYNC);
                        return 0;
                        return 0;
                case F_GETLK:
                case F_GETLK:
                        return fcntl_getlk(fd, (struct flock *) arg);
                        return fcntl_getlk(fd, (struct flock *) arg);
                case F_SETLK:
                case F_SETLK:
                        return fcntl_setlk(fd, cmd, (struct flock *) arg);
                        return fcntl_setlk(fd, cmd, (struct flock *) arg);
                case F_SETLKW:
                case F_SETLKW:
                        return fcntl_setlk(fd, cmd, (struct flock *) arg);
                        return fcntl_setlk(fd, cmd, (struct flock *) arg);
                case F_GETOWN:
                case F_GETOWN:
                        /*
                        /*
                         * XXX If f_owner is a process group, the
                         * XXX If f_owner is a process group, the
                         * negative return value will get converted
                         * negative return value will get converted
                         * into an error.  Oops.  If we keep the
                         * into an error.  Oops.  If we keep the
                         * current syscall conventions, the only way
                         * current syscall conventions, the only way
                         * to fix this will be in libc.
                         * to fix this will be in libc.
                         */
                         */
                        return filp->f_owner.pid;
                        return filp->f_owner.pid;
                case F_SETOWN:
                case F_SETOWN:
                        filp->f_owner.pid = arg;
                        filp->f_owner.pid = arg;
                        filp->f_owner.uid = current->uid;
                        filp->f_owner.uid = current->uid;
                        filp->f_owner.euid = current->euid;
                        filp->f_owner.euid = current->euid;
                        if (S_ISSOCK (filp->f_inode->i_mode))
                        if (S_ISSOCK (filp->f_inode->i_mode))
                                sock_fcntl (filp, F_SETOWN, arg);
                                sock_fcntl (filp, F_SETOWN, arg);
                        return 0;
                        return 0;
                default:
                default:
                        /* sockets need a few special fcntls. */
                        /* sockets need a few special fcntls. */
                        if (S_ISSOCK (filp->f_inode->i_mode))
                        if (S_ISSOCK (filp->f_inode->i_mode))
                          {
                          {
                             return (sock_fcntl (filp, cmd, arg));
                             return (sock_fcntl (filp, cmd, arg));
                          }
                          }
                        return -EINVAL;
                        return -EINVAL;
        }
        }
}
}
 
 
static void send_sigio(int sig, int pid, uid_t uid, uid_t euid)
static void send_sigio(int sig, int pid, uid_t uid, uid_t euid)
{
{
        struct task_struct * p;
        struct task_struct * p;
 
 
        for_each_task(p) {
        for_each_task(p) {
                int match = p->pid;
                int match = p->pid;
                if (pid < 0)
                if (pid < 0)
                        match = -p->pgrp;
                        match = -p->pgrp;
                if (pid != match)
                if (pid != match)
                        continue;
                        continue;
                if ((euid != 0) &&
                if ((euid != 0) &&
                    (euid ^ p->suid) && (euid ^ p->uid) &&
                    (euid ^ p->suid) && (euid ^ p->uid) &&
                    (uid ^ p->suid) && (uid ^ p->uid))
                    (uid ^ p->suid) && (uid ^ p->uid))
                        continue;
                        continue;
                p->signal |= 1 << (sig-1);
                p->signal |= 1 << (sig-1);
                if (p->state == TASK_INTERRUPTIBLE && (p->signal & ~p->blocked))
                if (p->state == TASK_INTERRUPTIBLE && (p->signal & ~p->blocked))
                        wake_up_process(p);
                        wake_up_process(p);
        }
        }
}
}
 
 
void kill_fasync(struct fasync_struct *fa, int sig)
void kill_fasync(struct fasync_struct *fa, int sig)
{
{
        while (fa) {
        while (fa) {
                struct fown_struct * fown;
                struct fown_struct * fown;
                if (fa->magic != FASYNC_MAGIC) {
                if (fa->magic != FASYNC_MAGIC) {
                        printk("kill_fasync: bad magic number in "
                        printk("kill_fasync: bad magic number in "
                               "fasync_struct!\n");
                               "fasync_struct!\n");
                        return;
                        return;
                }
                }
                fown = &fa->fa_file->f_owner;
                fown = &fa->fa_file->f_owner;
                if (fown->pid)
                if (fown->pid)
                        send_sigio(sig, fown->pid, fown->uid, fown->euid);
                        send_sigio(sig, fown->pid, fown->uid, fown->euid);
                fa = fa->fa_next;
                fa = fa->fa_next;
        }
        }
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.