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