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
24 #include <sys/file.h> /* XXX for LOCK_* */
26 /* Perform file control operations on FD. */
28 __libc_fcntl (int fd, int cmd, ...)
34 d = _hurd_fd_get (fd);
37 return __hurd_fail (EBADF);
45 default: /* Bad command. */
50 /* First the descriptor-based commands, which do no RPCs. */
52 case F_DUPFD: /* Duplicate the file descriptor. */
57 struct hurd_userlink ulink, ctty_ulink;
62 /* Extract the ports and flags from the file descriptor. */
63 __spin_lock (&d->port.lock);
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)
71 /* Duplication clears the FD_CLOEXEC flag. */
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));
78 /* _hurd_alloc_fd has set errno. */
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);
93 _hurd_port_locked_set (&new->port, port); /* Unlocks NEW. */
98 _hurd_port_free (&d->port, &ulink, port);
99 if (ctty != MACH_PORT_NULL)
100 _hurd_port_free (&d->ctty, &ctty_ulink, port);
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); \
114 __spin_unlock (&d->port.lock); \
117 case F_GETFD: /* Get descriptor flags. */
121 case F_SETFD: /* Set descriptor flags. */
122 LOCKED ((d->flags = va_arg (ap, int), 0));
126 /* Now the real io operations, done by RPCs to io servers. */
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 *);
154 case F_RDLCK: cmd |= LOCK_SH; break;
155 case F_WRLCK: cmd |= LOCK_EX; break;
156 case F_UNLCK: cmd |= LOCK_UN; break;
161 switch (fl->l_whence)
164 if (fl->l_start == 0 && fl->l_len == 0) /* Whole file request. */
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)
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);
189 case F_SETFL: /* Set per-open flags. */
190 err = HURD_FD_PORT_USE (d, __io_set_all_openmodes (port,
192 result = err ? __hurd_dfail (fd, err) : 0;
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);
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;
210 libc_hidden_def (__libc_fcntl)
211 weak_alias (__libc_fcntl, __fcntl)
212 libc_hidden_weak (__fcntl)
213 weak_alias (__libc_fcntl, fcntl)