]> sourceware.org Git - glibc.git/blob - sysdeps/mach/hurd/fcntl.c
Update.
[glibc.git] / sysdeps / mach / hurd / fcntl.c
1 /* Copyright (C) 1992,93,94,95,96,97,99,2000 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
18
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <hurd.h>
22 #include <hurd/fd.h>
23 #include <stdarg.h>
24 #include <sys/file.h> /* XXX for LOCK_* */
25
26
27 /* Perform file control operations on FD. */
28 int
29 __libc_fcntl (int fd, int cmd, ...)
30 {
31 va_list ap;
32 struct hurd_fd *d;
33 int result;
34
35 d = _hurd_fd_get (fd);
36
37 if (d == NULL)
38 return __hurd_fail (EBADF);
39
40 va_start (ap, cmd);
41
42 switch (cmd)
43 {
44 error_t err;
45
46 default: /* Bad command. */
47 errno = EINVAL;
48 result = -1;
49 break;
50
51 /* First the descriptor-based commands, which do no RPCs. */
52
53 case F_DUPFD: /* Duplicate the file descriptor. */
54 {
55 struct hurd_fd *new;
56 io_t port, ctty;
57 struct hurd_userlink ulink, ctty_ulink;
58 int flags;
59
60 HURD_CRITICAL_BEGIN;
61
62 /* Extract the ports and flags from the file descriptor. */
63 __spin_lock (&d->port.lock);
64 flags = d->flags;
65 ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
66 port = _hurd_port_locked_get (&d->port, &ulink); /* Unlocks D. */
67
68 /* Get a new file descriptor. The third argument to __fcntl is the
69 minimum file descriptor number for it. */
70 new = _hurd_alloc_fd (&result, va_arg (ap, int));
71 if (new == NULL)
72 /* _hurd_alloc_fd has set errno. */
73 result = -1;
74 else
75 {
76 /* Give the ports each a user ref for the new descriptor. */
77 __mach_port_mod_refs (__mach_task_self (), port,
78 MACH_PORT_RIGHT_SEND, 1);
79 if (ctty != MACH_PORT_NULL)
80 __mach_port_mod_refs (__mach_task_self (), ctty,
81 MACH_PORT_RIGHT_SEND, 1);
82
83 /* Install the ports and flags in the new descriptor. */
84 if (ctty != MACH_PORT_NULL)
85 _hurd_port_set (&new->ctty, ctty);
86 /* Duplication clears the FD_CLOEXEC flag. */
87 new->flags = flags & ~FD_CLOEXEC;
88 _hurd_port_locked_set (&new->port, port); /* Unlocks NEW. */
89 }
90
91 HURD_CRITICAL_END;
92
93 _hurd_port_free (&d->port, &ulink, port);
94 if (ctty != MACH_PORT_NULL)
95 _hurd_port_free (&d->ctty, &ctty_ulink, port);
96
97 break;
98 }
99
100 /* Set RESULT by evaluating EXPR with the descriptor locked.
101 Check for an empty descriptor and return EBADF. */
102 #define LOCKED(expr) \
103 HURD_CRITICAL_BEGIN; \
104 __spin_lock (&d->port.lock); \
105 if (d->port.port == MACH_PORT_NULL) \
106 result = __hurd_fail (EBADF); \
107 else \
108 result = (expr); \
109 __spin_unlock (&d->port.lock); \
110 HURD_CRITICAL_END;
111
112 case F_GETFD: /* Get descriptor flags. */
113 LOCKED (d->flags);
114 break;
115
116 case F_SETFD: /* Set descriptor flags. */
117 LOCKED ((d->flags = va_arg (ap, int), 0));
118 break;
119
120
121 /* Now the real io operations, done by RPCs to io servers. */
122
123 case F_GETLK:
124 case F_SETLK:
125 case F_SETLKW:
126 {
127 /* XXX
128 We need new RPCs to support POSIX.1 fcntl file locking!!
129 For the time being we support the whole-file case only,
130 with all kinds of WRONG WRONG WRONG semantics,
131 by using flock. This is definitely the Wrong Thing,
132 but it might be better than nothing (?). */
133 struct flock *fl = va_arg (ap, struct flock *);
134 va_end (ap);
135 switch (cmd)
136 {
137 case F_GETLK:
138 errno = ENOSYS;
139 return -1;
140 case F_SETLK:
141 cmd = LOCK_NB;
142 break;
143 default:
144 cmd = 0;
145 break;
146 }
147 switch (fl->l_type)
148 {
149 case F_RDLCK: cmd |= LOCK_SH; break;
150 case F_WRLCK: cmd |= LOCK_EX; break;
151 case F_UNLCK: cmd |= LOCK_UN; break;
152 default:
153 errno = EINVAL;
154 return -1;
155 }
156 switch (fl->l_whence)
157 {
158 case SEEK_SET:
159 if (fl->l_start == 0 && fl->l_len == 0)
160 break;
161 /* FALLTHROUGH */
162 case SEEK_CUR:
163 case SEEK_END:
164 errno = ENOTSUP;
165 return -1;
166 default:
167 errno = EINVAL;
168 return -1;
169 }
170
171 return __flock (fd, cmd);
172 }
173
174 case F_GETFL: /* Get per-open flags. */
175 if (err = HURD_FD_PORT_USE (d, __io_get_openmodes (port, &result)))
176 result = __hurd_dfail (fd, err);
177 break;
178
179 case F_SETFL: /* Set per-open flags. */
180 err = HURD_FD_PORT_USE (d, __io_set_all_openmodes (port,
181 va_arg (ap, int)));
182 result = err ? __hurd_dfail (fd, err) : 0;
183 break;
184
185 case F_GETOWN: /* Get owner. */
186 if (err = HURD_FD_PORT_USE (d, __io_get_owner (port, &result)))
187 result = __hurd_dfail (fd, err);
188 break;
189
190 case F_SETOWN: /* Set owner. */
191 err = HURD_FD_PORT_USE (d, __io_mod_owner (port, va_arg (ap, pid_t)));
192 result = err ? __hurd_dfail (fd, err) : 0;
193 break;
194 }
195
196 va_end (ap);
197
198 return result;
199 }
200
201 weak_alias (__libc_fcntl, __fcntl)
202 weak_alias (__libc_fcntl, fcntl)
This page took 0.046308 seconds and 5 git commands to generate.