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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [fcntl.c] - Blame information for rev 1627

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1627 jcastillo
/*
2
 *  linux/fs/fcntl.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 */
6
 
7
#include <asm/segment.h>
8
 
9
#include <linux/sched.h>
10
#include <linux/kernel.h>
11
#include <linux/errno.h>
12
#include <linux/stat.h>
13
#include <linux/fcntl.h>
14
#include <linux/string.h>
15
 
16
#include <asm/bitops.h>
17
 
18
extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
19
 
20
static inline int dupfd(unsigned int fd, unsigned int arg)
21
{
22
        struct files_struct * files = current->files;
23
 
24
        if (fd >= NR_OPEN || !files->fd[fd])
25
                return -EBADF;
26
        if (arg >= NR_OPEN)
27
                return -EINVAL;
28
        arg = find_next_zero_bit(&files->open_fds, NR_OPEN, arg);
29
        if (arg >= current->rlim[RLIMIT_NOFILE].rlim_cur)
30
                return -EMFILE;
31
        FD_SET(arg, &files->open_fds);
32
        FD_CLR(arg, &files->close_on_exec);
33
        (files->fd[arg] = files->fd[fd])->f_count++;
34
        return arg;
35
}
36
 
37
asmlinkage int sys_dup2(unsigned int oldfd, unsigned int newfd)
38
{
39
        if (oldfd >= NR_OPEN || !current->files->fd[oldfd])
40
                return -EBADF;
41
        if (newfd == oldfd)
42
                return newfd;
43
        if (newfd >= NR_OPEN)
44
                return -EBADF;  /* following POSIX.1 6.2.1 */
45
 
46
        sys_close(newfd);
47
        return dupfd(oldfd,newfd);
48
}
49
 
50
asmlinkage int sys_dup(unsigned int fildes)
51
{
52
        return dupfd(fildes,0);
53
}
54
 
55
asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
56
{
57
        struct file * filp;
58
 
59
        if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
60
                return -EBADF;
61
        switch (cmd) {
62
                case F_DUPFD:
63
                        return dupfd(fd,arg);
64
                case F_GETFD:
65
                        return FD_ISSET(fd, &current->files->close_on_exec);
66
                case F_SETFD:
67
                        if (arg&1)
68
                                FD_SET(fd, &current->files->close_on_exec);
69
                        else
70
                                FD_CLR(fd, &current->files->close_on_exec);
71
                        return 0;
72
                case F_GETFL:
73
                        return filp->f_flags;
74
                case F_SETFL:
75
                        /*
76
                         * In the case of an append-only file, O_APPEND
77
                         * cannot be cleared
78
                         */
79
                        if (IS_APPEND(filp->f_inode) && !(arg & O_APPEND))
80
                                return -EPERM;
81
                        if ((arg & FASYNC) && !(filp->f_flags & FASYNC) &&
82
                            filp->f_op->fasync)
83
                                filp->f_op->fasync(filp->f_inode, filp, 1);
84
                        if (!(arg & FASYNC) && (filp->f_flags & FASYNC) &&
85
                            filp->f_op->fasync)
86
                                filp->f_op->fasync(filp->f_inode, filp, 0);
87
                        /* required for SunOS emulation */
88
                        if (O_NONBLOCK != O_NDELAY)
89
                               if (arg & O_NDELAY)
90
                                   arg |= O_NONBLOCK;
91
                        filp->f_flags &= ~(O_APPEND | O_NONBLOCK | FASYNC);
92
                        filp->f_flags |= arg & (O_APPEND | O_NONBLOCK |
93
                                                FASYNC);
94
                        return 0;
95
                case F_GETLK:
96
                        return fcntl_getlk(fd, (struct flock *) arg);
97
                case F_SETLK:
98
                        return fcntl_setlk(fd, cmd, (struct flock *) arg);
99
                case F_SETLKW:
100
                        return fcntl_setlk(fd, cmd, (struct flock *) arg);
101
                case F_GETOWN:
102
                        /*
103
                         * XXX If f_owner is a process group, the
104
                         * negative return value will get converted
105
                         * into an error.  Oops.  If we keep the
106
                         * current syscall conventions, the only way
107
                         * to fix this will be in libc.
108
                         */
109
                        return filp->f_owner.pid;
110
                case F_SETOWN:
111
                        filp->f_owner.pid = arg;
112
                        filp->f_owner.uid = current->uid;
113
                        filp->f_owner.euid = current->euid;
114
                        if (S_ISSOCK (filp->f_inode->i_mode))
115
                                sock_fcntl (filp, F_SETOWN, arg);
116
                        return 0;
117
                default:
118
                        /* sockets need a few special fcntls. */
119
                        if (S_ISSOCK (filp->f_inode->i_mode))
120
                          {
121
                             return (sock_fcntl (filp, cmd, arg));
122
                          }
123
                        return -EINVAL;
124
        }
125
}
126
 
127
static void send_sigio(int sig, int pid, uid_t uid, uid_t euid)
128
{
129
        struct task_struct * p;
130
 
131
        for_each_task(p) {
132
                int match = p->pid;
133
                if (pid < 0)
134
                        match = -p->pgrp;
135
                if (pid != match)
136
                        continue;
137
                if ((euid != 0) &&
138
                    (euid ^ p->suid) && (euid ^ p->uid) &&
139
                    (uid ^ p->suid) && (uid ^ p->uid))
140
                        continue;
141
                p->signal |= 1 << (sig-1);
142
                if (p->state == TASK_INTERRUPTIBLE && (p->signal & ~p->blocked))
143
                        wake_up_process(p);
144
        }
145
}
146
 
147
void kill_fasync(struct fasync_struct *fa, int sig)
148
{
149
        while (fa) {
150
                struct fown_struct * fown;
151
                if (fa->magic != FASYNC_MAGIC) {
152
                        printk("kill_fasync: bad magic number in "
153
                               "fasync_struct!\n");
154
                        return;
155
                }
156
                fown = &fa->fa_file->f_owner;
157
                if (fown->pid)
158
                        send_sigio(sig, fown->pid, fown->uid, fown->euid);
159
                fa = fa->fa_next;
160
        }
161
}

powered by: WebSVN 2.1.0

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