root/lib/lstat.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. orig_lstat
  2. rpl_lstat

     1 /* Work around a bug of lstat on some systems
     2 
     3    Copyright (C) 1997-2006, 2008-2023 Free Software Foundation, Inc.
     4 
     5    This file is free software: you can redistribute it and/or modify
     6    it under the terms of the GNU Lesser General Public License as
     7    published by the Free Software Foundation; either version 2.1 of the
     8    License, or (at your option) any later version.
     9 
    10    This file is distributed in the hope that it will be useful,
    11    but WITHOUT ANY WARRANTY; without even the implied warranty of
    12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13    GNU Lesser General Public License for more details.
    14 
    15    You should have received a copy of the GNU Lesser General Public License
    16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
    17 
    18 /* written by Jim Meyering */
    19 
    20 /* If the user's config.h happens to include <sys/stat.h>, let it include only
    21    the system's <sys/stat.h> here, so that orig_lstat doesn't recurse to
    22    rpl_lstat.  */
    23 #define __need_system_sys_stat_h
    24 #include <config.h>
    25 
    26 #if !HAVE_LSTAT
    27 /* On systems that lack symlinks, our replacement <sys/stat.h> already
    28    defined lstat as stat, so there is nothing further to do other than
    29    avoid an empty file.  */
    30 typedef int dummy;
    31 #else /* HAVE_LSTAT */
    32 
    33 /* Get the original definition of lstat.  It might be defined as a macro.  */
    34 # include <sys/types.h>
    35 # include <sys/stat.h>
    36 # undef __need_system_sys_stat_h
    37 
    38 static int
    39 orig_lstat (const char *filename, struct stat *buf)
    40 {
    41   return lstat (filename, buf);
    42 }
    43 
    44 /* Specification.  */
    45 # ifdef __osf__
    46 /* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
    47    eliminates this include because of the preliminary #include <sys/stat.h>
    48    above.  */
    49 #  include "sys/stat.h"
    50 # else
    51 #  include <sys/stat.h>
    52 # endif
    53 
    54 # include "stat-time.h"
    55 
    56 # include <string.h>
    57 # include <errno.h>
    58 
    59 /* lstat works differently on Linux and Solaris systems.  POSIX (see
    60    "pathname resolution" in the glossary) requires that programs like
    61    'ls' take into consideration the fact that FILE has a trailing slash
    62    when FILE is a symbolic link.  On Linux and Solaris 10 systems, the
    63    lstat function already has the desired semantics (in treating
    64    'lstat ("symlink/", sbuf)' just like 'lstat ("symlink/.", sbuf)',
    65    but on Solaris 9 and earlier it does not.
    66 
    67    If FILE has a trailing slash and specifies a symbolic link,
    68    then use stat() to get more info on the referent of FILE.
    69    If the referent is a non-directory, then set errno to ENOTDIR
    70    and return -1.  Otherwise, return stat's result.  */
    71 
    72 int
    73 rpl_lstat (const char *file, struct stat *sbuf)
    74 {
    75   int result = orig_lstat (file, sbuf);
    76 
    77   /* This replacement file can blindly check against '/' rather than
    78      using the ISSLASH macro, because all platforms with '\\' either
    79      lack symlinks (mingw) or have working lstat (cygwin) and thus do
    80      not compile this file.  0 len should have already been filtered
    81      out above, with a failure return of ENOENT.  */
    82   if (result == 0)
    83     {
    84       if (S_ISDIR (sbuf->st_mode) || file[strlen (file) - 1] != '/')
    85         result = stat_time_normalize (result, sbuf);
    86       else
    87         {
    88           /* At this point, a trailing slash is permitted only on
    89              symlink-to-dir; but it should have found information on the
    90              directory, not the symlink.  Call 'stat' to get info about the
    91              link's referent.  Our replacement stat guarantees valid results,
    92              even if the symlink is not pointing to a directory.  */
    93           if (!S_ISLNK (sbuf->st_mode))
    94             {
    95               errno = ENOTDIR;
    96               return -1;
    97             }
    98           result = stat (file, sbuf);
    99         }
   100     }
   101   return result;
   102 }
   103 
   104 #endif /* HAVE_LSTAT */

/* [<][>][^][v][top][bottom][index][help] */