Back to index

glibc  2.9
fd.h
Go to the documentation of this file.
00001 /* File descriptors.
00002    Copyright (C) 1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2006,2007
00003        Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #ifndef       _HURD_FD_H
00022 
00023 #define       _HURD_FD_H    1
00024 #include <features.h>
00025 
00026 #include <cthreads.h>
00027 
00028 #include <hurd/hurd_types.h>
00029 #include <hurd/port.h>
00030 #include <sys/socket.h>
00031 
00032 
00033 /* Structure representing a file descriptor.  */
00034 
00035 struct hurd_fd
00036   {
00037     struct hurd_port port;  /* io server port.  */
00038     int flags;                     /* fcntl flags; locked by port.lock.  */
00039 
00040     /* Normal port to the ctty.  When `port' is our ctty, this is a port to
00041        the same io object but which never returns EBACKGROUND; when not,
00042        this is nil.  */
00043     struct hurd_port ctty;
00044   };
00045 
00046 
00047 /* Current file descriptor table.  */
00048 
00049 extern int _hurd_dtablesize;
00050 extern struct hurd_fd **_hurd_dtable;
00051 extern struct mutex _hurd_dtable_lock; /* Locks those two variables.  */
00052 
00053 #include <hurd/signal.h>
00054 
00055 #ifndef _HURD_FD_H_EXTERN_INLINE
00056 #define _HURD_FD_H_EXTERN_INLINE __extern_inline
00057 #endif
00058 
00059 /* Returns the descriptor cell for FD.  If FD is invalid or unused, return
00060    NULL.  The cell is unlocked; when ready to use it, lock it and check for
00061    it being unused.  */
00062 
00063 _HURD_FD_H_EXTERN_INLINE struct hurd_fd *
00064 _hurd_fd_get (int fd)
00065 {
00066   struct hurd_fd *descriptor;
00067 
00068   __mutex_lock (&_hurd_dtable_lock);
00069   if (fd < 0 || fd >= _hurd_dtablesize)
00070     descriptor = NULL;
00071   else
00072     {
00073       struct hurd_fd *cell = _hurd_dtable[fd];
00074       if (cell == NULL)
00075        /* No descriptor allocated at this index.  */
00076        descriptor = NULL;
00077       else
00078        {
00079          __spin_lock (&cell->port.lock);
00080          if (cell->port.port == MACH_PORT_NULL)
00081            /* The descriptor at this index has no port in it.
00082               This happens if it existed before but was closed.  */
00083            descriptor = NULL;
00084          else
00085            descriptor = cell;
00086          __spin_unlock (&cell->port.lock);
00087        }
00088     }
00089   __mutex_unlock (&_hurd_dtable_lock);
00090 
00091   return descriptor;
00092 }
00093 
00094 
00095 /* Evaluate EXPR with the variable `descriptor' bound to a pointer to the
00096    file descriptor structure for FD.   */
00097 
00098 #define       HURD_FD_USE(fd, expr)                                                \
00099   ({ struct hurd_fd *descriptor = _hurd_fd_get (fd);                        \
00100      descriptor == NULL ? EBADF : (expr); })
00101 
00102 /* Evaluate EXPR with the variable `port' bound to the port to FD, and
00103    `ctty' bound to the ctty port.  */
00104 
00105 #define HURD_DPORT_USE(fd, expr) \
00106   HURD_FD_USE ((fd), HURD_FD_PORT_USE (descriptor, (expr)))
00107 
00108 /* Likewise, but FD is a pointer to the file descriptor structure.  */
00109 
00110 #define       HURD_FD_PORT_USE(fd, expr)                                    \
00111   ({ error_t __result;                                                      \
00112      struct hurd_fd *const __d = (fd);                                      \
00113      struct hurd_userlink __ulink, __ctty_ulink;                     \
00114      io_t port, ctty;                                                       \
00115      void *crit = _hurd_critical_section_lock ();                           \
00116      __spin_lock (&__d->port.lock);                                         \
00117      if (__d->port.port == MACH_PORT_NULL)                                  \
00118        {                                                             \
00119         __spin_unlock (&__d->port.lock);                             \
00120         _hurd_critical_section_unlock (crit);                               \
00121         __result = EBADF;                                            \
00122        }                                                             \
00123      else                                                            \
00124        {                                                             \
00125         ctty = _hurd_port_get (&__d->ctty, &__ctty_ulink);                  \
00126         port = _hurd_port_locked_get (&__d->port, &__ulink);                \
00127         _hurd_critical_section_unlock (crit);                               \
00128         __result = (expr);                                           \
00129         _hurd_port_free (&__d->port, &__ulink, port);                       \
00130         if (ctty != MACH_PORT_NULL)                                         \
00131           _hurd_port_free (&__d->ctty, &__ctty_ulink, ctty);                \
00132        }                                                             \
00133      __result; })
00134 
00135 #include <errno.h>
00136 
00137 /* Check if ERR should generate a signal.
00138    Returns the signal to take, or zero if none.  */
00139 
00140 _HURD_FD_H_EXTERN_INLINE int
00141 _hurd_fd_error_signal (error_t err)
00142 {
00143   switch (err)
00144     {
00145     case EMACH_SEND_INVALID_DEST:
00146     case EMIG_SERVER_DIED:
00147       /* The server has disappeared!  */
00148       return SIGLOST;
00149     case EPIPE:
00150       return SIGPIPE;
00151     default:
00152       /* Having a default case avoids -Wenum-switch warnings.  */
00153       return 0;
00154     }
00155 }
00156 
00157 /* Handle an error from an RPC on a file descriptor's port.  You should
00158    always use this function to handle errors from RPCs made on file
00159    descriptor ports.  Some errors are translated into signals.  */
00160 
00161 _HURD_FD_H_EXTERN_INLINE error_t
00162 _hurd_fd_error (int fd, error_t err)
00163 {
00164   int signo = _hurd_fd_error_signal (err);
00165   if (signo)
00166     {
00167       const struct hurd_signal_detail detail
00168        = { code: fd, error: err, exc: 0 };
00169       _hurd_raise_signal (NULL, signo, &detail);
00170     }
00171   return err;
00172 }
00173 
00174 /* Handle error code ERR from an RPC on file descriptor FD's port.
00175    Set `errno' to the appropriate error code, and always return -1.  */
00176 
00177 _HURD_FD_H_EXTERN_INLINE int
00178 __hurd_dfail (int fd, error_t err)
00179 {
00180   errno = _hurd_fd_error (fd, err);
00181   return -1;
00182 }
00183 
00184 /* Likewise, but do not raise SIGPIPE on EPIPE if flags contain
00185    MSG_NOSIGNAL.  */
00186 
00187 _HURD_FD_H_EXTERN_INLINE int
00188 __hurd_sockfail (int fd, int flags, error_t err)
00189 {
00190   if (!(flags & MSG_NOSIGNAL) || err != EPIPE)
00191     err = _hurd_fd_error (fd, err);
00192   errno = err;
00193   return -1;
00194 }
00195 
00196 /* Set up *FD to have PORT its server port, doing appropriate ctty magic.
00197    Does no locking or unlocking.  */
00198 
00199 extern void _hurd_port2fd (struct hurd_fd *fd, io_t port, int flags);
00200 
00201 /* Allocate a new file descriptor and install PORT in it (doing any
00202    appropriate ctty magic); consumes a user reference on PORT.  FLAGS are
00203    as for `open'; only O_IGNORE_CTTY is meaningful, but all are saved.
00204 
00205    If the descriptor table is full, set errno, and return -1.
00206    If DEALLOC is nonzero, deallocate PORT first.  */
00207 
00208 extern int _hurd_intern_fd (io_t port, int flags, int dealloc);
00209 
00210 /* Allocate a new file descriptor in the table and return it, locked.  The
00211    new descriptor number will be no less than FIRST_FD.  If the table is
00212    full, set errno to EMFILE and return NULL.  If FIRST_FD is negative or
00213    bigger than the size of the table, set errno to EINVAL and return NULL.  */
00214 
00215 extern struct hurd_fd *_hurd_alloc_fd (int *fd_ptr, int first_fd);
00216 
00217 /* Allocate a new file descriptor structure and initialize its port cells
00218    with PORT and CTTY.  (This does not affect the descriptor table.)  */
00219 
00220 extern struct hurd_fd *_hurd_new_fd (io_t port, io_t ctty);
00221 
00222 /* Close a file descriptor, making it available for future reallocation.  */
00223 
00224 extern error_t _hurd_fd_close (struct hurd_fd *fd);
00225 
00226 /* Read and write data from a file descriptor; just like `read' and `write'
00227    if OFFSET is -1, or like `pread' and `pwrite' if OFFSET is not -1.
00228    If successful, stores the amount actually read or written in *NBYTES.  */
00229 
00230 extern error_t _hurd_fd_read (struct hurd_fd *fd,
00231                            void *buf, size_t *nbytes, loff_t offset);
00232 extern error_t _hurd_fd_write (struct hurd_fd *fd,
00233                             const void *buf, size_t *nbytes, loff_t offset);
00234 
00235 
00236 /* Call *RPC on PORT and/or CTTY; if a call on CTTY returns EBACKGROUND,
00237    generate SIGTTIN/SIGTTOU or EIO as appropriate.  */
00238 
00239 extern error_t _hurd_ctty_input (io_t port, io_t ctty, error_t (*rpc) (io_t));
00240 extern error_t _hurd_ctty_output (io_t port, io_t ctty, error_t (*rpc) (io_t));
00241 
00242 
00243 /* The guts of `select' and `poll'.  Check the first NFDS descriptors
00244    either in POLLFDS (if nonnull) or in each of READFDS, WRITEFDS,
00245    EXCEPTFDS that is nonnull.  If TIMEOUT is not NULL, time out after
00246    waiting the interval specified therein.  If SIGMASK is nonnull,
00247    the set of blocked signals is temporarily set to that during this call.
00248    Returns the number of ready descriptors, or -1 for errors.  */
00249 struct pollfd;
00250 struct timespec;
00251 extern int _hurd_select (int nfds, struct pollfd *pollfds,
00252                       fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
00253                       const struct timespec *timeout,
00254                       const sigset_t *sigmask);
00255 
00256 /* Variant of file_name_lookup used in *at function implementations.
00257    AT_FLAGS should contain only AT_SYMLINK_NOFOLLOW; other bits
00258    cause EINVAL.  */
00259 extern file_t __file_name_lookup_at (int fd, int at_flags,
00260                                  const char *file_name,
00261                                  int flags, mode_t mode);
00262 
00263 /* Variant of file_name_split used in *at function implementations.  */
00264 extern file_t __file_name_split_at (int fd, const char *file_name,
00265                                 char **name);
00266 
00267 /* Variant of directory_name_split used in *at function implementations.  */
00268 extern file_t __directory_name_split_at (int fd, const char *directory_name,
00269                                     char **name);
00270 
00271 
00272 
00273 #endif /* hurd/fd.h */