LCOV - code coverage report
Current view: top level - lib - same.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 18 20 90.0 %
Date: 2018-01-30 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /* Determine whether two file names refer to the same file.
       2             : 
       3             :    Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006 Free
       4             :    Software Foundation, Inc.
       5             : 
       6             :    This program is free software: you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      18             : 
      19             : /* written by Jim Meyering */
      20             : 
      21             : #include <config.h>
      22             : 
      23             : #include <stdbool.h>
      24             : #include <stdio.h>
      25             : #include <unistd.h>
      26             : #include <stdlib.h>
      27             : #include <sys/types.h>
      28             : #include <sys/stat.h>
      29             : #include <ctype.h>
      30             : #include <errno.h>
      31             : 
      32             : #include <string.h>
      33             : 
      34             : #include <limits.h>
      35             : #ifndef _POSIX_NAME_MAX
      36             : # define _POSIX_NAME_MAX 14
      37             : #endif
      38             : 
      39             : #include "same.h"
      40             : #include "dirname.h"
      41             : #include "error.h"
      42             : #include "same-inode.h"
      43             : #include "xalloc.h"
      44             : 
      45             : #ifndef MIN
      46             : # define MIN(a, b) ((a) < (b) ? (a) : (b))
      47             : #endif
      48             : 
      49             : /* Return nonzero if SOURCE and DEST point to the same name in the same
      50             :    directory.  */
      51             : 
      52             : bool
      53          25 : same_name (const char *source, const char *dest)
      54             : {
      55             :   /* Compare the basenames.  */
      56          25 :   char const *source_basename = last_component (source);
      57          25 :   char const *dest_basename = last_component (dest);
      58          25 :   size_t source_baselen = base_len (source_basename);
      59          25 :   size_t dest_baselen = base_len (dest_basename);
      60          25 :   bool identical_basenames =
      61             :     (source_baselen == dest_baselen
      62          25 :      && memcmp (source_basename, dest_basename, dest_baselen) == 0);
      63          25 :   bool compare_dirs = identical_basenames;
      64          25 :   bool same = false;
      65             : 
      66             : #if ! _POSIX_NO_TRUNC && HAVE_PATHCONF && defined _PC_NAME_MAX
      67             :   /* This implementation silently truncates components of file names.  If
      68             :      the base names might be truncated, check whether the truncated
      69             :      base names are the same, while checking the directories.  */
      70             :   size_t slen_max = HAVE_LONG_FILE_NAMES ? 255 : _POSIX_NAME_MAX;
      71             :   size_t min_baselen = MIN (source_baselen, dest_baselen);
      72             :   if (slen_max <= min_baselen
      73             :       && memcmp (source_basename, dest_basename, slen_max) == 0)
      74             :     compare_dirs = true;
      75             : #endif
      76             : 
      77          25 :   if (compare_dirs)
      78             :     {
      79             :       struct stat source_dir_stats;
      80             :       struct stat dest_dir_stats;
      81             :       char *source_dirname, *dest_dirname;
      82             : 
      83             :       /* Compare the parent directories (via the device and inode numbers).  */
      84          19 :       source_dirname = dir_name (source);
      85          19 :       dest_dirname = dir_name (dest);
      86             : 
      87          19 :       if (stat (source_dirname, &source_dir_stats))
      88             :         {
      89             :           /* Shouldn't happen.  */
      90           0 :           error (1, errno, "%s", source_dirname);
      91             :         }
      92             : 
      93          19 :       if (stat (dest_dirname, &dest_dir_stats))
      94             :         {
      95             :           /* Shouldn't happen.  */
      96           0 :           error (1, errno, "%s", dest_dirname);
      97             :         }
      98             : 
      99          19 :       same = SAME_INODE (source_dir_stats, dest_dir_stats);
     100             : 
     101             : #if ! _POSIX_NO_TRUNC && HAVE_PATHCONF && defined _PC_NAME_MAX
     102             :       if (same && ! identical_basenames)
     103             :         {
     104             :           long name_max = (errno = 0, pathconf (dest_dirname, _PC_NAME_MAX));
     105             :           if (name_max < 0)
     106             :             {
     107             :               if (errno)
     108             :                 {
     109             :                   /* Shouldn't happen.  */
     110             :                   error (1, errno, "%s", dest_dirname);
     111             :                 }
     112             :               same = false;
     113             :             }
     114             :           else
     115             :             same = (name_max <= min_baselen
     116             :                     && memcmp (source_basename, dest_basename, name_max) == 0);
     117             :         }
     118             : #endif
     119             : 
     120          19 :       free (source_dirname);
     121          19 :       free (dest_dirname);
     122             :     }
     123             : 
     124          25 :   return same;
     125             : }

Generated by: LCOV version 1.10