2.9
[glibc/nacl-glibc.git] / sysdeps / mach / hurd / fcntl.c
blob470614b360e8b1e37a5ef9fd9dfe4c85fc2c86b8
1 /* Copyright (C) 1992-1997,1999,2000,2002,2007 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
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_* */
26 /* Perform file control operations on FD. */
27 int
28 __libc_fcntl (int fd, int cmd, ...)
30 va_list ap;
31 struct hurd_fd *d;
32 int result;
34 d = _hurd_fd_get (fd);
36 if (d == NULL)
37 return __hurd_fail (EBADF);
39 va_start (ap, cmd);
41 switch (cmd)
43 error_t err;
45 default: /* Bad command. */
46 errno = EINVAL;
47 result = -1;
48 break;
50 /* First the descriptor-based commands, which do no RPCs. */
52 case F_DUPFD: /* Duplicate the file descriptor. */
53 case F_DUPFD_CLOEXEC:
55 struct hurd_fd *new;
56 io_t port, ctty;
57 struct hurd_userlink ulink, ctty_ulink;
58 int flags;
60 HURD_CRITICAL_BEGIN;
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. */
68 if (cmd == F_DUPFD_CLOEXEC)
69 flags |= FD_CLOEXEC;
70 else
71 /* Duplication clears the FD_CLOEXEC flag. */
72 flags &= ~FD_CLOEXEC;
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
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);
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. */
96 HURD_CRITICAL_END;
98 _hurd_port_free (&d->port, &ulink, port);
99 if (ctty != MACH_PORT_NULL)
100 _hurd_port_free (&d->ctty, &ctty_ulink, port);
102 break;
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;
117 case F_GETFD: /* Get descriptor flags. */
118 LOCKED (d->flags);
119 break;
121 case F_SETFD: /* Set descriptor flags. */
122 LOCKED ((d->flags = va_arg (ap, int), 0));
123 break;
126 /* Now the real io operations, done by RPCs to io servers. */
128 case F_GETLK:
129 case F_SETLK:
130 case F_SETLKW:
132 /* XXX
133 We need new RPCs to support POSIX.1 fcntl file locking!!
134 For the time being we support the whole-file case only,
135 with all kinds of WRONG WRONG WRONG semantics,
136 by using flock. This is definitely the Wrong Thing,
137 but it might be better than nothing (?). */
138 struct flock *fl = va_arg (ap, struct flock *);
139 va_end (ap);
140 switch (cmd)
142 case F_GETLK:
143 errno = ENOSYS;
144 return -1;
145 case F_SETLK:
146 cmd = LOCK_NB;
147 break;
148 default:
149 cmd = 0;
150 break;
152 switch (fl->l_type)
154 case F_RDLCK: cmd |= LOCK_SH; break;
155 case F_WRLCK: cmd |= LOCK_EX; break;
156 case F_UNLCK: cmd |= LOCK_UN; break;
157 default:
158 errno = EINVAL;
159 return -1;
161 switch (fl->l_whence)
163 case SEEK_SET:
164 if (fl->l_start == 0 && fl->l_len == 0) /* Whole file request. */
165 break;
166 /* It seems to be common for applications to lock the first
167 byte of the file when they are really doing whole-file locking.
168 So, since it's so wrong already, might as well do that too. */
169 if (fl->l_start == 0 && fl->l_len == 1)
170 break;
171 /* FALLTHROUGH */
172 case SEEK_CUR:
173 case SEEK_END:
174 errno = ENOTSUP;
175 return -1;
176 default:
177 errno = EINVAL;
178 return -1;
181 return __flock (fd, cmd);
184 case F_GETFL: /* Get per-open flags. */
185 if (err = HURD_FD_PORT_USE (d, __io_get_openmodes (port, &result)))
186 result = __hurd_dfail (fd, err);
187 break;
189 case F_SETFL: /* Set per-open flags. */
190 err = HURD_FD_PORT_USE (d, __io_set_all_openmodes (port,
191 va_arg (ap, int)));
192 result = err ? __hurd_dfail (fd, err) : 0;
193 break;
195 case F_GETOWN: /* Get owner. */
196 if (err = HURD_FD_PORT_USE (d, __io_get_owner (port, &result)))
197 result = __hurd_dfail (fd, err);
198 break;
200 case F_SETOWN: /* Set owner. */
201 err = HURD_FD_PORT_USE (d, __io_mod_owner (port, va_arg (ap, pid_t)));
202 result = err ? __hurd_dfail (fd, err) : 0;
203 break;
206 va_end (ap);
208 return result;
210 libc_hidden_def (__libc_fcntl)
211 weak_alias (__libc_fcntl, __fcntl)
212 libc_hidden_weak (__fcntl)
213 weak_alias (__libc_fcntl, fcntl)