xref: /netbsd-src/external/gpl2/xcvs/dist/lib/lstat.c (revision 5a6c14c844c4c665da5632061aebde7bb2cb5766)
1a7c91847Schristos /* Work around a bug of lstat on some systems
2a7c91847Schristos 
3a7c91847Schristos    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free
4a7c91847Schristos    Software Foundation, Inc.
5a7c91847Schristos 
6a7c91847Schristos    This program is free software; you can redistribute it and/or modify
7a7c91847Schristos    it under the terms of the GNU General Public License as published by
8a7c91847Schristos    the Free Software Foundation; either version 2, or (at your option)
9a7c91847Schristos    any later version.
10a7c91847Schristos 
11a7c91847Schristos    This program is distributed in the hope that it will be useful,
12a7c91847Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
13a7c91847Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14a7c91847Schristos    GNU General Public License for more details.
15a7c91847Schristos 
16a7c91847Schristos    You should have received a copy of the GNU General Public License
17a7c91847Schristos    along with this program; if not, write to the Free Software Foundation,
18a7c91847Schristos    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
19*5a6c14c8Schristos #include <sys/cdefs.h>
20*5a6c14c8Schristos __RCSID("$NetBSD: lstat.c,v 1.2 2016/05/17 14:00:09 christos Exp $");
21*5a6c14c8Schristos 
22a7c91847Schristos 
23a7c91847Schristos /* written by Jim Meyering */
24a7c91847Schristos 
25a7c91847Schristos #ifdef HAVE_CONFIG_H
26a7c91847Schristos # include <config.h>
27a7c91847Schristos #endif
28a7c91847Schristos 
29a7c91847Schristos /* The specification of these functions is in sys_stat.h.  But we cannot
30a7c91847Schristos    include this include file here, because on some systems, a
31a7c91847Schristos    "#define lstat lstat64" is being used, and sys_stat.h deletes this
32a7c91847Schristos    definition.  */
33a7c91847Schristos 
34a7c91847Schristos #include <sys/types.h>
35a7c91847Schristos #include <sys/stat.h>
36a7c91847Schristos #include <stdlib.h>
37a7c91847Schristos #include <string.h>
38a7c91847Schristos 
39a7c91847Schristos #include "stat-macros.h"
40a7c91847Schristos #include "xalloc.h"
41a7c91847Schristos 
42a7c91847Schristos /* lstat works differently on Linux and Solaris systems.  POSIX (see
43a7c91847Schristos    `pathname resolution' in the glossary) requires that programs like `ls'
44a7c91847Schristos    take into consideration the fact that FILE has a trailing slash when
45a7c91847Schristos    FILE is a symbolic link.  On Linux systems, the lstat function already
46a7c91847Schristos    has the desired semantics (in treating `lstat("symlink/",sbuf)' just like
47a7c91847Schristos    `lstat("symlink/.",sbuf)', but on Solaris it does not.
48a7c91847Schristos 
49a7c91847Schristos    If FILE has a trailing slash and specifies a symbolic link,
50a7c91847Schristos    then append a `.' to FILE and call lstat a second time.  */
51a7c91847Schristos 
52a7c91847Schristos int
rpl_lstat(const char * file,struct stat * sbuf)53a7c91847Schristos rpl_lstat (const char *file, struct stat *sbuf)
54a7c91847Schristos {
55a7c91847Schristos   size_t len;
56a7c91847Schristos   char *new_file;
57a7c91847Schristos 
58a7c91847Schristos   int lstat_result = lstat (file, sbuf);
59a7c91847Schristos 
60a7c91847Schristos   if (lstat_result != 0 || !S_ISLNK (sbuf->st_mode))
61a7c91847Schristos     return lstat_result;
62a7c91847Schristos 
63a7c91847Schristos   len = strlen (file);
64a7c91847Schristos   if (len == 0 || file[len - 1] != '/')
65a7c91847Schristos     return lstat_result;
66a7c91847Schristos 
67a7c91847Schristos   /* FILE refers to a symbolic link and the name ends with a slash.
68a7c91847Schristos      Append a `.' to FILE and repeat the lstat call.  */
69a7c91847Schristos 
70a7c91847Schristos   /* Add one for the `.' we'll append, and one more for the trailing NUL.  */
71a7c91847Schristos   new_file = xmalloc (len + 1 + 1);
72a7c91847Schristos   memcpy (new_file, file, len);
73a7c91847Schristos   new_file[len] = '.';
74a7c91847Schristos   new_file[len + 1] = 0;
75a7c91847Schristos 
76a7c91847Schristos   lstat_result = lstat (new_file, sbuf);
77a7c91847Schristos   free (new_file);
78a7c91847Schristos 
79a7c91847Schristos   return lstat_result;
80a7c91847Schristos }
81