1 /* Copyright (C) 1992, 1993, 1994, 1995, 1996 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 Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 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 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA. */
27 /* Perform file control operations on FD. */
29 DEFUN(__fcntl
, (fd
, cmd
), int fd AND
int cmd DOTS
)
35 d
= _hurd_fd_get (fd
);
38 return __hurd_fail (EBADF
);
46 default: /* Bad command. */
51 /* First the descriptor-based commands, which do no RPCs. */
53 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 /* Get a new file descriptor. The third argument to __fcntl is the
69 minimum file descriptor number for it. */
70 new = _hurd_alloc_fd (&result
, va_arg (ap
, int));
72 /* _hurd_alloc_fd has set errno. */
76 /* Give the ports each a user ref for the new descriptor. */
77 __mach_port_mod_refs (__mach_task_self (), port
,
78 MACH_PORT_RIGHT_SEND
, 1);
79 if (ctty
!= MACH_PORT_NULL
)
80 __mach_port_mod_refs (__mach_task_self (), ctty
,
81 MACH_PORT_RIGHT_SEND
, 1);
83 /* Install the ports and flags in the new descriptor. */
84 if (ctty
!= MACH_PORT_NULL
)
85 _hurd_port_set (&new->ctty
, ctty
);
86 /* Duplication clears the FD_CLOEXEC flag. */
87 new->flags
= flags
& ~FD_CLOEXEC
;
88 _hurd_port_locked_set (&new->port
, port
); /* Unlocks NEW. */
93 _hurd_port_free (&d
->port
, &ulink
, port
);
94 if (ctty
!= MACH_PORT_NULL
)
95 _hurd_port_free (&d
->ctty
, &ctty_ulink
, port
);
100 /* Set RESULT by evaluating EXPR with the descriptor locked.
101 Check for an empty descriptor and return EBADF. */
102 #define LOCKED(expr) \
103 HURD_CRITICAL_BEGIN; \
104 __spin_lock (&d->port.lock); \
105 if (d->port.port == MACH_PORT_NULL) \
106 result = __hurd_fail (EBADF); \
109 __spin_unlock (&d->port.lock); \
112 case F_GETFD
: /* Get descriptor flags. */
116 case F_SETFD
: /* Set descriptor flags. */
117 LOCKED ((d
->flags
= va_arg (ap
, int), 0));
121 /* Now the real io operations, done by RPCs to io servers. */
127 struct flock
*fl
= va_arg (ap
, struct flock
*);
128 errno
= fl
?ENOSYS
:EINVAL
; /* XXX mib needs to implement io rpcs. */
133 case F_GETFL
: /* Get per-open flags. */
134 if (err
= HURD_FD_PORT_USE (d
, __io_get_openmodes (port
, &result
)))
135 result
= __hurd_dfail (fd
, err
);
138 case F_SETFL
: /* Set per-open flags. */
139 err
= HURD_FD_PORT_USE (d
, __io_set_all_openmodes (port
,
141 result
= err
? __hurd_dfail (fd
, err
) : 0;
144 case F_GETOWN
: /* Get owner. */
145 if (err
= HURD_FD_PORT_USE (d
, __io_get_owner (port
, &result
)))
146 result
= __hurd_dfail (fd
, err
);
149 case F_SETOWN
: /* Set owner. */
150 err
= HURD_FD_PORT_USE (d
, __io_mod_owner (port
, va_arg (ap
, pid_t
)));
151 result
= err
? __hurd_dfail (fd
, err
) : 0;
160 weak_alias (__fcntl
, fcntl
)