1 /* Copyright (C) 1992-1997,1999,2000,2002 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. */
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 /* 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));
71 /* _hurd_alloc_fd has set errno. */
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);
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. */
92 _hurd_port_free (&d
->port
, &ulink
, port
);
93 if (ctty
!= MACH_PORT_NULL
)
94 _hurd_port_free (&d
->ctty
, &ctty_ulink
, port
);
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); \
108 __spin_unlock (&d->port.lock); \
111 case F_GETFD
: /* Get descriptor flags. */
115 case F_SETFD
: /* Set descriptor flags. */
116 LOCKED ((d
->flags
= va_arg (ap
, int), 0));
120 /* Now the real io operations, done by RPCs to io servers. */
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 (?). */
132 struct flock
*fl
= va_arg (ap
, struct flock
*);
148 case F_RDLCK
: cmd
|= LOCK_SH
; break;
149 case F_WRLCK
: cmd
|= LOCK_EX
; break;
150 case F_UNLCK
: cmd
|= LOCK_UN
; break;
155 switch (fl
->l_whence
)
158 if (fl
->l_start
== 0 && fl
->l_len
== 0) /* Whole file request. */
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)
175 return __flock (fd
, cmd
);
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
);
183 case F_SETFL
: /* Set per-open flags. */
184 err
= HURD_FD_PORT_USE (d
, __io_set_all_openmodes (port
,
186 result
= err
? __hurd_dfail (fd
, err
) : 0;
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
);
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;
204 libc_hidden_def (__libc_fcntl
)
205 weak_alias (__libc_fcntl
, __fcntl
)
206 libc_hidden_weak (__fcntl
)
207 weak_alias (__libc_fcntl
, fcntl
)