Cannot Manually Update Database for Locate?

Cannot Manually Update Database for Locate?

I've been trying to update the databases used by locate on my Macbook (10.6.3 Snow Leopard) but even following the commands shown in this thread hasn't gotten me anywhere. I just get an error from it - if I try to use it via sudo, I get some racket about permission denied for such-n-such directory. I tried running it as root (sudo su, then the command) and that didn't work either. Quit back to my regular terminal prompt, and now I just get

macbook:~ monte$ sudo /usr/libexec/locate.updatedb
find: .: Permission denied
macbook:~ monte$

I'm thoroughly confused, and half afraid that I may have hosed something in the process. Any help or suggestions would be greatly appreciated!

Monte

4 Answers

The solution for your problem is very simple. But if you want to know better why the error is occurring and why the proposed solution works, you can read the entire answer.

Otherwise, if you only want to get the answer, go straight to the "How to update your locate db?" session.

What exactly locate.updatedb does?

This is the current behavior of locate.updatedb:

  • If you are running the script as root, the script calls itself with the user nobody. Then, when the children returns, it updates the final locale database with the database saved by the children process (nobody user) in a temporary location, and then exits;

Code (/usr/libexec/locate.updatedb, line 31, with additional comments added by me):

if [ "$(id -u)" = "0" ]; then  ## IF ROOT USER
    rc=0
    export FCODES=`mktemp -t updatedb`  ## CREATE A TEMP FILE
    chown nobody $FCODES  # TEMP FILE OWNED BY THE NOBODY USER
    tmpdb=`su -fm nobody -c "$0"` || rc=1  ## CALL ITSELF AS USER NOBODY
    if [ $rc = 0 ]; then
        install -m 0444 -o nobody -g wheel $FCODES \
            /var/db/locate.database  ## INSTALL THE LOCATE DATABASE SAVED \
                                     ## BY THE CHILDREN IN THE TEMP FILE
    fi
    rm $FCODES
    exit $rc  ## EXIT
fi
  • When running with another user (it is, the user nobody), the script indexes your system (ignoring the paths which it doesn't have permission) and then saves the result in a temporary file (actually, the previously temp file created by its father).

Some considerations:

  • Part of the logic is executed as root, and other part as nobody;
  • If the script is called without sudo, it won't work (only root has permission in the /var/db directory). It is, you must really run the script as root;
  • As a result, locate.updatedb can't index files inside your home directory (the nobody user doesn't have permission to access it);
    • I think locate.updatedb indexes this way because it will be impossible to an user to discover name of files that belongs to another user (in another home directory);
    • If you want to locate files inside your home, you can use mdfind, as proposed by @ted-naleid.

Some code (/usr/libexec/locate.updatedb, line 93, with additional comments):

if $find -s $SEARCHPATHS $excludes -or -print 2>/dev/null |  ## SEARCH
        $mklocatedb -presort > $tmp  ## CREATE LOCALEDB
then
    case X"`$find $tmp -size -257c -print`" in
        X) cat $tmp > $FCODES;;  ## SAVE LOCALEDB IN THE TEMP FILE
[...]
David Miller
Author

David Miller

David Miller brings 15 years of experience in global economics, personal finance strategy, and market dynamics. He specializes in turning complex economic trends into actionable insights for everyday readers.