1 /* Copyright (C) 1992-2018 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, see
16 <http://www.gnu.org/licenses/>. */
23 #include <sys/file.h> /* XXX for LOCK_* */
25 /* Perform file control operations on FD. */
27 __libc_fcntl (int fd
, int cmd
, ...)
33 d
= _hurd_fd_get (fd
);
36 return __hurd_fail (EBADF
);
44 default: /* Bad command. */
49 /* First the descriptor-based commands, which do no RPCs. */
51 case F_DUPFD
: /* Duplicate the file descriptor. */
56 struct hurd_userlink ulink
, ctty_ulink
;
61 /* Extract the ports and flags from the file descriptor. */
62 __spin_lock (&d
->port
.lock
);
64 ctty
= _hurd_port_get (&d
->ctty
, &ctty_ulink
);
65 port
= _hurd_port_locked_get (&d
->port
, &ulink
); /* Unlocks D. */
67 if (cmd
== F_DUPFD_CLOEXEC
)
70 /* Duplication clears the FD_CLOEXEC flag. */
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));
77 /* _hurd_alloc_fd has set errno. */
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);
88 /* Install the ports and flags in the new descriptor. */
89 if (ctty
!= MACH_PORT_NULL
)
90 _hurd_port_set (&new->ctty
, ctty
);
92 _hurd_port_locked_set (&new->port
, port
); /* Unlocks NEW. */
97 _hurd_port_free (&d
->port
, &ulink
, port
);
98 if (ctty
!= MACH_PORT_NULL
)
99 _hurd_port_free (&d
->ctty
, &ctty_ulink
, port
);
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); \
113 __spin_unlock (&d->port.lock); \
116 case F_GETFD
: /* Get descriptor flags. */
120 case F_SETFD
: /* Set descriptor flags. */
121 LOCKED ((d
->flags
= va_arg (ap
, int), 0));
125 /* Now the real io operations, done by RPCs to io servers. */
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 (?). */
137 struct flock
*fl
= va_arg (ap
, struct flock
*);
153 case F_RDLCK
: cmd
|= LOCK_SH
; break;
154 case F_WRLCK
: cmd
|= LOCK_EX
; break;
155 case F_UNLCK
: cmd
|= LOCK_UN
; break;
160 switch (fl
->l_whence
)
163 if (fl
->l_start
== 0 && fl
->l_len
== 0) /* Whole file request. */
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)
180 return __flock (fd
, cmd
);
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
);
188 case F_SETFL
: /* Set per-open flags. */
189 err
= HURD_FD_PORT_USE (d
, __io_set_all_openmodes (port
,
191 result
= err
? __hurd_dfail (fd
, err
) : 0;
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
);
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;
209 libc_hidden_def (__libc_fcntl
)
210 weak_alias (__libc_fcntl
, __fcntl
)
211 libc_hidden_weak (__fcntl
)
212 weak_alias (__libc_fcntl
, fcntl
)