]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/mach/hurd/fcntl.c
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / sysdeps / mach / hurd / fcntl.c
1 /* Copyright (C) 1992-2019 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 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.
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 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
17
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <hurd.h>
21 #include <hurd/fd.h>
22 #include <stdarg.h>
23 #include <sys/file.h> /* XXX for LOCK_* */
24 #include "f_setlk.h"
25
26 /* Perform file control operations on FD. */
27 int
28 __libc_fcntl (int fd, int cmd, ...)
29 {
30 va_list ap;
31 struct hurd_fd *d;
32 int result;
33
34 d = _hurd_fd_get (fd);
35
36 if (d == NULL)
37 return __hurd_fail (EBADF);
38
39 va_start (ap, cmd);
40
41 switch (cmd)
42 {
43 error_t err;
44
45 default: /* Bad command. */
46 errno = EINVAL;
47 result = -1;
48 break;
49
50 /* First the descriptor-based commands, which do no RPCs. */
51
52 case F_DUPFD: /* Duplicate the file descriptor. */
53 case F_DUPFD_CLOEXEC:
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 if (cmd == F_DUPFD_CLOEXEC)
69 flags |= FD_CLOEXEC;
70 else
71 /* Duplication clears the FD_CLOEXEC flag. */
72 flags &= ~FD_CLOEXEC;
73
74 /* Get a new file descriptor. The third argument to __fcntl is the
75 minimum file descriptor number for it. */
76 new = _hurd_alloc_fd (&result, va_arg (ap, int));
77 if (new == NULL)
78 /* _hurd_alloc_fd has set errno. */
79 result = -1;
80 else
81 {
82 /* Give the ports each a user ref for the new descriptor. */
83 __mach_port_mod_refs (__mach_task_self (), port,
84 MACH_PORT_RIGHT_SEND, 1);
85 if (ctty != MACH_PORT_NULL)
86 __mach_port_mod_refs (__mach_task_self (), ctty,
87 MACH_PORT_RIGHT_SEND, 1);
88
89 /* Install the ports and flags in the new descriptor. */
90 if (ctty != MACH_PORT_NULL)
91 _hurd_port_set (&new->ctty, ctty);
92 new->flags = flags;
93 _hurd_port_locked_set (&new->port, port); /* Unlocks NEW. */
94 }
95
96 HURD_CRITICAL_END;
97
98 _hurd_port_free (&d->port, &ulink, port);
99 if (ctty != MACH_PORT_NULL)
100 _hurd_port_free (&d->ctty, &ctty_ulink, port);
101
102 break;
103 }
104
105 /* Set RESULT by evaluating EXPR with the descriptor locked.
106 Check for an empty descriptor and return EBADF. */
107 #define LOCKED(expr) \
108 HURD_CRITICAL_BEGIN; \
109 __spin_lock (&d->port.lock); \
110 if (d->port.port == MACH_PORT_NULL) \
111 result = __hurd_fail (EBADF); \
112 else \
113 result = (expr); \
114 __spin_unlock (&d->port.lock); \
115 HURD_CRITICAL_END;
116
117 case F_GETFD: /* Get descriptor flags. */
118 LOCKED (d->flags);
119 break;
120
121 case F_SETFD: /* Set descriptor flags. */
122 LOCKED ((d->flags = va_arg (ap, int), 0));
123 break;
124
125
126 /* Now the real io operations, done by RPCs to io servers. */
127
128 case F_GETLK:
129 case F_SETLK:
130 case F_SETLKW:
131 {
132 struct flock *fl = va_arg (ap, struct flock *);
133 int wait = 0;
134 va_end (ap);
135 switch (cmd)
136 {
137 case F_GETLK:
138 errno = ENOSYS;
139 return -1;
140 case F_SETLKW:
141 wait = 1;
142 /* FALLTHROUGH */
143 case F_SETLK:
144 return __f_setlk (fd, fl->l_type, fl->l_whence,
145 fl->l_start, fl->l_len, wait);
146 default:
147 errno = EINVAL;
148 return -1;
149 }
150 }
151
152 case F_GETLK64:
153 case F_SETLK64:
154 case F_SETLKW64:
155 {
156 struct flock64 *fl = va_arg (ap, struct flock64 *);
157 int wait = 0;
158 va_end (ap);
159 switch (cmd)
160 {
161 case F_GETLK64:
162 errno = ENOSYS;
163 return -1;
164 case F_SETLKW64:
165 wait = 1;
166 /* FALLTHROUGH */
167 case F_SETLK64:
168 return __f_setlk (fd, fl->l_type, fl->l_whence,
169 fl->l_start, fl->l_len, wait);
170 default:
171 errno = EINVAL;
172 return -1;
173 }
174 }
175
176 case F_GETFL: /* Get per-open flags. */
177 if (err = HURD_FD_PORT_USE (d, __io_get_openmodes (port, &result)))
178 result = __hurd_dfail (fd, err);
179 break;
180
181 case F_SETFL: /* Set per-open flags. */
182 err = HURD_FD_PORT_USE (d, __io_set_all_openmodes (port,
183 va_arg (ap, int)));
184 result = err ? __hurd_dfail (fd, err) : 0;
185 break;
186
187 case F_GETOWN: /* Get owner. */
188 if (err = HURD_FD_PORT_USE (d, __io_get_owner (port, &result)))
189 result = __hurd_dfail (fd, err);
190 break;
191
192 case F_SETOWN: /* Set owner. */
193 err = HURD_FD_PORT_USE (d, __io_mod_owner (port, va_arg (ap, pid_t)));
194 result = err ? __hurd_dfail (fd, err) : 0;
195 break;
196 }
197
198 va_end (ap);
199
200 return result;
201 }
202 libc_hidden_def (__libc_fcntl)
203 weak_alias (__libc_fcntl, __fcntl)
204 libc_hidden_weak (__fcntl)
205 weak_alias (__libc_fcntl, fcntl)
206
207 strong_alias (__libc_fcntl, __libc_fcntl64)
208 libc_hidden_def (__libc_fcntl64)
209 weak_alias (__libc_fcntl64, __fcntl64)
210 libc_hidden_weak (__fcntl64)
211 weak_alias (__fcntl64, fcntl64)