LCOV - code coverage report
Current view: directory - gllib - fdopendir.c (source / functions) Found Hit Coverage
Test: 000-gnulib-simple Lines: 7 7 100.0 %
Date: 2009-11-12 Functions: 1 1 100.0 %
Colors: not hit hit

       1                 : /* provide a replacement fdopendir function
       2                 :    Copyright (C) 2004-2009 Free Software Foundation, Inc.
       3                 : 
       4                 :    This program is free software: you can redistribute it and/or modify
       5                 :    it under the terms of the GNU General Public License as published by
       6                 :    the Free Software Foundation; either version 3 of the License, or
       7                 :    (at your option) any later version.
       8                 : 
       9                 :    This program 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
      12                 :    GNU General Public License for more details.
      13                 : 
      14                 :    You should have received a copy of the GNU General Public License
      15                 :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      16                 : 
      17                 : /* written by Jim Meyering */
      18                 : 
      19                 : #include <config.h>
      20                 : 
      21                 : #include <dirent.h>
      22                 : 
      23                 : #include <stdlib.h>
      24                 : #include <unistd.h>
      25                 : 
      26                 : #if !HAVE_FDOPENDIR
      27                 : 
      28                 : # include "openat.h"
      29                 : # include "openat-priv.h"
      30                 : # include "save-cwd.h"
      31                 : 
      32                 : # if GNULIB_DIRENT_SAFER
      33                 : #  include "dirent--.h"
      34                 : # endif
      35                 : 
      36                 : /* Replacement for Solaris' function by the same name.
      37                 :    <http://www.google.com/search?q=fdopendir+site:docs.sun.com>
      38                 :    First, try to simulate it via opendir ("/proc/self/fd/FD").  Failing
      39                 :    that, simulate it by using fchdir metadata, or by doing
      40                 :    save_cwd/fchdir/opendir(".")/restore_cwd.
      41                 :    If either the save_cwd or the restore_cwd fails (relatively unlikely),
      42                 :    then give a diagnostic and exit nonzero.
      43                 :    Otherwise, this function works just like Solaris' fdopendir.
      44                 : 
      45                 :    W A R N I N G:
      46                 :    Unlike other fd-related functions, this one effectively consumes
      47                 :    its FD parameter.  The caller should not close or otherwise
      48                 :    manipulate FD if this function returns successfully.  Also, this
      49                 :    implementation does not guarantee that dirfd(fdopendir(n))==n;
      50                 :    the open directory stream may use a clone of FD, or have no
      51                 :    associated fd at all.  */
      52                 : DIR *
      53                 : fdopendir (int fd)
      54                 : {
      55                 :   int saved_errno;
      56                 :   DIR *dir;
      57                 : 
      58                 :   char buf[OPENAT_BUFFER_SIZE];
      59                 :   char *proc_file = openat_proc_name (buf, fd, ".");
      60                 :   if (proc_file)
      61                 :     {
      62                 :       dir = opendir (proc_file);
      63                 :       saved_errno = errno;
      64                 :     }
      65                 :   else
      66                 :     {
      67                 :       dir = NULL;
      68                 :       saved_errno = EOPNOTSUPP;
      69                 :     }
      70                 : 
      71                 :   /* If the syscall fails with an expected errno value, resort to
      72                 :      save_cwd/restore_cwd.  */
      73                 :   if (! dir && EXPECTED_ERRNO (saved_errno))
      74                 :     {
      75                 : # if REPLACE_FCHDIR
      76                 :       const char *name = _gl_directory_name (fd);
      77                 :       if (name)
      78                 :         dir = opendir (name);
      79                 :       saved_errno = errno;
      80                 : # else /* !REPLACE_FCHDIR */
      81                 :       struct saved_cwd saved_cwd;
      82                 :       if (save_cwd (&saved_cwd) != 0)
      83                 :         openat_save_fail (errno);
      84                 : 
      85                 :       if (fchdir (fd) != 0)
      86                 :         {
      87                 :           dir = NULL;
      88                 :           saved_errno = errno;
      89                 :         }
      90                 :       else
      91                 :         {
      92                 :           dir = opendir (".");
      93                 :           saved_errno = errno;
      94                 : 
      95                 :           if (restore_cwd (&saved_cwd) != 0)
      96                 :             openat_restore_fail (errno);
      97                 :         }
      98                 : 
      99                 :       free_cwd (&saved_cwd);
     100                 : # endif /* !REPLACE_FCHDIR */
     101                 :     }
     102                 : 
     103                 :   if (dir)
     104                 :     close (fd);
     105                 :   if (proc_file != buf)
     106                 :     free (proc_file);
     107                 :   errno = saved_errno;
     108                 :   return dir;
     109                 : }
     110                 : 
     111                 : #else /* HAVE_FDOPENDIR */
     112                 : 
     113                 : # include <errno.h>
     114                 : # include <sys/stat.h>
     115                 : 
     116                 : # undef fdopendir
     117                 : 
     118                 : /* Like fdopendir, but work around GNU/Hurd bug by validating FD.  */
     119                 : 
     120                 : DIR *
     121                 : rpl_fdopendir (int fd)
     122              42 : {
     123                 :   struct stat st;
     124              42 :   if (fstat (fd, &st))
     125               1 :     return NULL;
     126              41 :   if (!S_ISDIR (st.st_mode))
     127                 :     {
     128               1 :       errno = ENOTDIR;
     129               1 :       return NULL;
     130                 :     }
     131              40 :   return fdopendir (fd);
     132                 : }
     133                 : 
     134                 : #endif /* HAVE_FDOPENDIR */

Generated by: LCOV version 1.7