bug-findutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Behaviour of locate with/without glob characters


From: Russell Shaw
Subject: Re: Behaviour of locate with/without glob characters
Date: Thu, 04 Nov 2004 21:06:04 +1100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.2) Gecko/20040820 Debian/1.7.2-4

James Youngman wrote:
Hello all,

I've been examining the functionality of "locate" in findutils and it
appears that its behaviour is as follows :-


1. If your pattern includes no glob characters ([?*) then all filenames in the locatedb which include as a substring the text you specify will be returned.
2. If your pattern includes any glob characters, then only filenames
   in the locatedb which have a basename which matches the glob pattern
   will be returned.


Suppose the locatedb contains

/foo
/foo/bar
/foo/baz

"locate fo*" will return one result, "/foo".  On the other hand
"locate oo" will return all three entries, and "locate o/b" will
return two.


Is it supposed to work this way?
James.

Here is my bug report on how it used to work and how it was changed:

*******************************************************

Hi,
If i do: locate *.pc
i get:

/usr/lib/pkgconfig/libxml.pc
/usr/lib/pkgconfig/openssl.pc
/usr/lib/pkgconfig/ORBit-2.0.pc
/usr/lib/pkgconfig/pango.pc
/usr/lib/pkgconfig/render.pc
/usr/lib/pkgconfig/xcursor.pc
/usr/local/lib/pkgconfig/atk.pc
/usr/local/lib/pkgconfig/gdk-2.0.pc
...

However, if i do: locate x*.pc, i get nothing.

I found that locate tries to match against full path
names. This patch makes it match against the path with
leading directories removed. Now i can do: locate x*.pc
and get:

/usr/lib/pkgconfig/xcursor.pc
/usr/lib/pkgconfig/xft.pc
/usr/lib/pkgconfig/xrender.pc

********************************************************

The suggested patch:


Only in findutils.orig: findutils
diff -apru findutils.orig/locate/locate.c findutils/locate/locate.c
--- findutils.orig/locate/locate.c      Sat Aug  2 22:16:14 2003
+++ findutils/locate/locate.c   Sun Oct 19 22:58:01 2003
@@ -59,7 +59,10 @@
 #undef PACKAGE
 #include <config.h>
 #include <stdio.h>
+
+/* isupper/islower: implicit declaration */
 #include <ctype.h>
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <time.h>
@@ -393,66 +396,47 @@ locate (pathpart, dbfile, ignore_case)
       /* Search backward starting at the end of the path we just read in,
         for the character at the end of the last glob-free subpattern
         in PATHPART.  */
-      if (ignore_case)
-       {
-          for (prev_fast_match = false; s >= cutoff; s--)
-           /* Fast first char check. */
-           if (TOLOWER(*s) == *patend)
-             {
-               char *s2;               /* Scan the path we read in. */
-               register char *p2;      /* Scan `patend'.  */
-
- for (s2 = s - 1, p2 = patend - 1; *p2 != '\0' && TOLOWER(*s2) == *p2;
-                    s2--, p2--)
-                 ;
-               if (*p2 == '\0')
-                 {
-                   /* Success on the fast match.  Compare the whole pattern
-                      if it contains globbing characters.  */
-                   prev_fast_match = true;

--->
- if (globflag == false || fnmatch (pathpart, path, FNM_CASEFOLD) == 0)
<---

-                     {
-                       if (!check_existence || stat(path, &st) == 0)
-                         {
-                           puts (path);
-                           ++printed;
-                         }
-                     }
-                   break;
-                 }
-             }
-       }
-      else {
-
-      for (prev_fast_match = false; s >= cutoff; s--)
-       /* Fast first char check. */
-       if (*s == *patend)
-         {
-           char *s2;           /* Scan the path we read in. */
-           register char *p2;  /* Scan `patend'.  */
-
-           for (s2 = s - 1, p2 = patend - 1; *p2 != '\0' && *s2 == *p2;
-                                              s2--, p2--)
-             ;
-           if (*p2 == '\0')
-             {
-               /* Success on the fast match.  Compare the whole pattern
-                  if it contains globbing characters.  */
-               prev_fast_match = true;

--->
-               if (globflag == false || fnmatch (pathpart, path,
-                                                 0) == 0)
<---

-                 {
-                   if (!check_existence || stat(path, &st) == 0)
-                     {
-                       puts (path);
-                       ++printed;
-                     }
-                 }
-               break;
-             }
-         }
-      }
-
+      for(prev_fast_match=false; s>=cutoff; s--)
+        {
+          char *s2;   /* Scan the path we read in. */
+          register char *p2;  /* Scan `patend'.  */
+
+          /* Fast first char check. */
+          if(ignore_case)
+            {
+              if(TOLOWER(*s)!=*patend)
+                continue;
+            }
+          else if(*s!=*patend)
+            continue;
+
+          if(ignore_case)
+            for(s2=s-1, p2=patend-1; *p2!='\0' && TOLOWER(*s2)==*p2; s2--, 
p2--);
+          else
+            for(s2=s-1, p2=patend-1; *p2!='\0' && *s2==*p2; s2--, p2--);
+
+          if(*p2!='\0')
+            continue;
+          /*  Success on the fast match.  Compare the whole pattern
+              if it contains globbing characters.  */
+          prev_fast_match = true;
+          if(globflag)
+            {
+              if(ignore_case)
+                {

--->
+                  if(fnmatch(pathpart,basename(path),FNM_CASEFOLD)!=0)
<---

+                    break;
+                }
+              else

--->
+                if(fnmatch(pathpart,basename(path),0)!=0)
<---

+                  break;
+            }
+          if(check_existence && stat(path,&st)!=0)
+            break;
+          puts(path);
+          ++printed;
+          break;
+        }
     }

   if (ferror (fp))


The patch above looks large, but that was only to reduce two nearly repeated
pieces of code to one piece. The only change in logic was to change (as shown
after the ---> arrows above):

  fnmatch(pathpart, path, FNM_CASEFOLD)

to:

  fnmatch(pathpart, basename(path), FNM_CASEFOLD)

and:


  fnmatch(pathpart, path, 0)

to:

  fnmatch(pathpart, basename(path))


As a frequent user of locate, i found the ability of being able to search for
all files like eg: libx*.so extremely useful.

However, as discussed some time ago on this list, this is kind of a superficial
fix to make locate a bit more useful. IIRC, a more extensive fix is needed for
locate to do more useful searches using regular expressions. I'm not quite up
to full-on systems utility programming (yet).




reply via email to

[Prev in Thread] Current Thread [Next in Thread]