LCOV - code coverage report
Current view: top level - bash-4.4.23 - hashcmd.c (source / functions) Hit Total Coverage
Test: cov-sh.info Lines: 28 65 43.1 %
Date: 2020-10-29 14:49:55 Functions: 3 6 50.0 %

          Line data    Source code
       1             : /* hashcmd.c - functions for managing a hash table mapping command names to
       2             :                full pathnames. */
       3             : 
       4             : /* Copyright (C) 1997-2009 Free Software Foundation, Inc.
       5             : 
       6             :    This file is part of GNU Bash, the Bourne Again SHell.
       7             : 
       8             :    Bash is free software: you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation, either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    Bash is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include <config.h>
      23             : 
      24             : #include "bashtypes.h"
      25             : #include "posixstat.h"
      26             : 
      27             : #if defined (HAVE_UNISTD_H)
      28             : #  include <unistd.h>
      29             : #endif
      30             : 
      31             : #include "bashansi.h"
      32             : 
      33             : #include "shell.h"
      34             : #include "findcmd.h"
      35             : #include "hashcmd.h"
      36             : 
      37             : extern int hashing_enabled;
      38             : 
      39             : HASH_TABLE *hashed_filenames = (HASH_TABLE *)NULL;
      40             : 
      41             : static void phash_freedata __P((PTR_T));
      42             : 
      43             : void
      44           0 : phash_create ()
      45             : {
      46           0 :   if (hashed_filenames == 0)
      47       44266 :     hashed_filenames = hash_create (FILENAME_HASH_BUCKETS);
      48           0 : }
      49             : 
      50             : static void
      51           0 : phash_freedata (data)
      52             :      PTR_T data;
      53             : {
      54           0 :   free (((PATH_DATA *)data)->path);
      55           0 :   free (data);
      56           0 : }
      57             : 
      58             : void
      59           0 : phash_flush ()
      60             : {
      61           0 :   if (hashed_filenames)
      62           0 :     hash_flush (hashed_filenames, phash_freedata);
      63           0 : }
      64             : 
      65             : /* Remove FILENAME from the table of hashed commands. */
      66             : int
      67          44 : phash_remove (filename)
      68             :      const char *filename;
      69             : {
      70          44 :   register BUCKET_CONTENTS *item;
      71             : 
      72          44 :   if (hashing_enabled == 0 || hashed_filenames == 0)
      73             :     return 0;
      74             : 
      75           0 :   item = hash_remove (filename, hashed_filenames, 0);
      76           0 :   if (item)
      77             :     {
      78           0 :       if (item->data)
      79           0 :         phash_freedata (item->data);
      80           0 :       free (item->key);
      81           0 :       free (item);
      82           0 :       return 0;
      83             :     }
      84             :   return 1;
      85             : }
      86             : 
      87             : /* Place FILENAME (key) and FULL_PATH (data->path) into the
      88             :    hash table.  CHECK_DOT if non-null is for future calls to
      89             :    phash_search (); it means that this file was found
      90             :    in a directory in $PATH that is not an absolute pathname.
      91             :    FOUND is the initial value for times_found. */
      92             : void
      93       47222 : phash_insert (filename, full_path, check_dot, found)
      94             :      char *filename, *full_path;
      95             :      int check_dot, found;
      96             : {
      97       47222 :   register BUCKET_CONTENTS *item;
      98             : 
      99       47222 :   if (hashing_enabled == 0)
     100             :     return;
     101             : 
     102       47222 :   if (hashed_filenames == 0)
     103       44266 :     phash_create ();
     104             : 
     105       47222 :   item = hash_insert (filename, hashed_filenames, 0);
     106       47222 :   if (item->data)
     107           0 :     free (pathdata(item)->path);
     108             :   else
     109             :     {
     110       47222 :       item->key = savestring (filename);
     111       47222 :       item->data = xmalloc (sizeof (PATH_DATA));
     112             :     }
     113       47222 :   pathdata(item)->path = savestring (full_path);
     114       47222 :   pathdata(item)->flags = 0;
     115       47222 :   if (check_dot)
     116           0 :     pathdata(item)->flags |= HASH_CHKDOT;
     117       47222 :   if (*full_path != '/')
     118           0 :     pathdata(item)->flags |= HASH_RELPATH;
     119       47222 :   item->times_found = found;
     120             : }
     121             : 
     122             : /* Return the full pathname that FILENAME hashes to.  If FILENAME
     123             :    is hashed, but (data->flags & HASH_CHKDOT) is non-zero, check
     124             :    ./FILENAME and return that if it is executable.  This always
     125             :    returns a newly-allocated string; the caller is responsible
     126             :    for freeing it. */
     127             : char *
     128     7787945 : phash_search (filename)
     129             :      const char *filename;
     130             : {
     131     7787945 :   register BUCKET_CONTENTS *item;
     132     7787945 :   char *path, *dotted_filename, *tail;
     133     7787945 :   int same;
     134             : 
     135     7787945 :   if (hashing_enabled == 0 || hashed_filenames == 0)
     136             :     return ((char *)NULL);
     137             : 
     138       60464 :   item = hash_search (filename, hashed_filenames, 0);
     139             : 
     140       60464 :   if (item == NULL)
     141             :     return ((char *)NULL);
     142             : 
     143             :   /* If this filename is hashed, but `.' comes before it in the path,
     144             :      see if ./filename is executable.  If the hashed value is not an
     145             :      absolute pathname, see if ./`hashed-value' exists. */
     146          25 :   path = pathdata(item)->path;
     147          25 :   if (pathdata(item)->flags & (HASH_CHKDOT|HASH_RELPATH))
     148             :     {
     149           0 :       tail = (pathdata(item)->flags & HASH_RELPATH) ? path : (char *)filename;   /* XXX - fix const later */
     150             :       /* If the pathname does not start with a `./', add a `./' to it. */
     151           0 :       if (tail[0] != '.' || tail[1] != '/')
     152             :         {
     153           0 :           dotted_filename = (char *)xmalloc (3 + strlen (tail));
     154           0 :           dotted_filename[0] = '.'; dotted_filename[1] = '/';
     155           0 :           strcpy (dotted_filename + 2, tail);
     156             :         }
     157             :       else
     158           0 :         dotted_filename = savestring (tail);
     159             : 
     160           0 :       if (executable_file (dotted_filename))
     161             :         return (dotted_filename);
     162             : 
     163           0 :       free (dotted_filename);
     164             : 
     165             : #if 0
     166             :       if (pathdata(item)->flags & HASH_RELPATH)
     167             :         return ((char *)NULL);
     168             : #endif
     169             : 
     170             :       /* Watch out.  If this file was hashed to "./filename", and
     171             :          "./filename" is not executable, then return NULL. */
     172             : 
     173             :       /* Since we already know "./filename" is not executable, what
     174             :          we're really interested in is whether or not the `path'
     175             :          portion of the hashed filename is equivalent to the current
     176             :          directory, but only if it starts with a `.'.  (This catches
     177             :          ./. and so on.)  same_file () tests general Unix file
     178             :          equivalence -- same device and inode. */
     179           0 :       if (*path == '.')
     180             :         {
     181           0 :           same = 0;
     182           0 :           tail = (char *)strrchr (path, '/');
     183             : 
     184           0 :           if (tail)
     185             :             {
     186           0 :               *tail = '\0';
     187           0 :               same = same_file (".", path, (struct stat *)NULL, (struct stat *)NULL);
     188           0 :               *tail = '/';
     189             :             }
     190             : 
     191           0 :           return same ? (char *)NULL : savestring (path);
     192             :         }
     193             :     }
     194             : 
     195          25 :   return (savestring (path));
     196             : }

Generated by: LCOV version 1.14.0.6.4058