]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/mach/hurd/fcntl.c
Remade for stable-2.7
[thirdparty/glibc.git] / sysdeps / mach / hurd / fcntl.c
CommitLineData
6b87a564 1/* Copyright (C) 1992-1997,1999,2000,2002 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
AJ
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. */
28f540f4 18
28f540f4
RM
19#include <errno.h>
20#include <fcntl.h>
21#include <hurd.h>
22#include <hurd/fd.h>
23#include <stdarg.h>
0702b5f4 24#include <sys/file.h> /* XXX for LOCK_* */
28f540f4 25
28f540f4
RM
26/* Perform file control operations on FD. */
27int
c1301d9a 28__libc_fcntl (int fd, int cmd, ...)
28f540f4
RM
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 {
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
67 /* Get a new file descriptor. The third argument to __fcntl is the
68 minimum file descriptor number for it. */
69 new = _hurd_alloc_fd (&result, va_arg (ap, int));
70 if (new == NULL)
71 /* _hurd_alloc_fd has set errno. */
72 result = -1;
73 else
74 {
75 /* Give the ports each a user ref for the new descriptor. */
76 __mach_port_mod_refs (__mach_task_self (), port,
77 MACH_PORT_RIGHT_SEND, 1);
78 if (ctty != MACH_PORT_NULL)
79 __mach_port_mod_refs (__mach_task_self (), ctty,
80 MACH_PORT_RIGHT_SEND, 1);
81
82 /* Install the ports and flags in the new descriptor. */
83 if (ctty != MACH_PORT_NULL)
84 _hurd_port_set (&new->ctty, ctty);
85 /* Duplication clears the FD_CLOEXEC flag. */
86 new->flags = flags & ~FD_CLOEXEC;
87 _hurd_port_locked_set (&new->port, port); /* Unlocks NEW. */
88 }
89
90 HURD_CRITICAL_END;
91
92 _hurd_port_free (&d->port, &ulink, port);
93 if (ctty != MACH_PORT_NULL)
94 _hurd_port_free (&d->ctty, &ctty_ulink, port);
95
96 break;
97 }
98
99 /* Set RESULT by evaluating EXPR with the descriptor locked.
100 Check for an empty descriptor and return EBADF. */
101#define LOCKED(expr) \
102 HURD_CRITICAL_BEGIN; \
103 __spin_lock (&d->port.lock); \
104 if (d->port.port == MACH_PORT_NULL) \
105 result = __hurd_fail (EBADF); \
106 else \
107 result = (expr); \
108 __spin_unlock (&d->port.lock); \
109 HURD_CRITICAL_END;
110
111 case F_GETFD: /* Get descriptor flags. */
112 LOCKED (d->flags);
113 break;
114
115 case F_SETFD: /* Set descriptor flags. */
116 LOCKED ((d->flags = va_arg (ap, int), 0));
117 break;
118
119
120 /* Now the real io operations, done by RPCs to io servers. */
121
122 case F_GETLK:
123 case F_SETLK:
124 case F_SETLKW:
125 {
0702b5f4
RM
126 /* XXX
127 We need new RPCs to support POSIX.1 fcntl file locking!!
128 For the time being we support the whole-file case only,
129 with all kinds of WRONG WRONG WRONG semantics,
130 by using flock. This is definitely the Wrong Thing,
131 but it might be better than nothing (?). */
28f540f4 132 struct flock *fl = va_arg (ap, struct flock *);
0702b5f4
RM
133 va_end (ap);
134 switch (cmd)
135 {
136 case F_GETLK:
137 errno = ENOSYS;
138 return -1;
139 case F_SETLK:
140 cmd = LOCK_NB;
141 break;
142 default:
143 cmd = 0;
144 break;
145 }
146 switch (fl->l_type)
147 {
148 case F_RDLCK: cmd |= LOCK_SH; break;
149 case F_WRLCK: cmd |= LOCK_EX; break;
150 case F_UNLCK: cmd |= LOCK_UN; break;
151 default:
152 errno = EINVAL;
153 return -1;
154 }
155 switch (fl->l_whence)
156 {
157 case SEEK_SET:
8bbd8b0b
RM
158 if (fl->l_start == 0 && fl->l_len == 0) /* Whole file request. */
159 break;
160 /* It seems to be common for applications to lock the first
161 byte of the file when they are really doing whole-file locking.
162 So, since it's so wrong already, might as well do that too. */
163 if (fl->l_start == 0 && fl->l_len == 1)
0702b5f4
RM
164 break;
165 /* FALLTHROUGH */
166 case SEEK_CUR:
167 case SEEK_END:
168 errno = ENOTSUP;
169 return -1;
170 default:
171 errno = EINVAL;
172 return -1;
173 }
174
175 return __flock (fd, cmd);
28f540f4
RM
176 }
177
178 case F_GETFL: /* Get per-open flags. */
179 if (err = HURD_FD_PORT_USE (d, __io_get_openmodes (port, &result)))
180 result = __hurd_dfail (fd, err);
181 break;
182
183 case F_SETFL: /* Set per-open flags. */
184 err = HURD_FD_PORT_USE (d, __io_set_all_openmodes (port,
185 va_arg (ap, int)));
186 result = err ? __hurd_dfail (fd, err) : 0;
8ec2f309 187 break;
28f540f4
RM
188
189 case F_GETOWN: /* Get owner. */
190 if (err = HURD_FD_PORT_USE (d, __io_get_owner (port, &result)))
191 result = __hurd_dfail (fd, err);
192 break;
193
194 case F_SETOWN: /* Set owner. */
195 err = HURD_FD_PORT_USE (d, __io_mod_owner (port, va_arg (ap, pid_t)));
196 result = err ? __hurd_dfail (fd, err) : 0;
197 break;
198 }
199
200 va_end (ap);
201
202 return result;
203}
37ba7d66 204libc_hidden_def (__libc_fcntl)
c1301d9a 205weak_alias (__libc_fcntl, __fcntl)
37ba7d66 206libc_hidden_weak (__fcntl)
c1301d9a 207weak_alias (__libc_fcntl, fcntl)