Imported Upstream version 4.5.14
[platform/upstream/findutils.git] / locate / updatedb.sh
1 #! /bin/sh
2 # updatedb -- build a locate pathname database
3 # Copyright (C) 1994, 1996, 1997, 2000, 2001, 2003, 2004, 2005, 2006,
4 # 2010, 2011 Free 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 # csh original by James Woods; sh conversion by David MacKenzie.
20
21 #exec 2> /tmp/updatedb-trace.txt
22 #set -x
23
24 version='
25 updatedb (@PACKAGE_NAME@) @VERSION@
26 Copyright (C) 2007,2008,2009,2010 Free Software Foundation, Inc.
27 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
28 This is free software: you are free to change and redistribute it.
29 There is NO WARRANTY, to the extent permitted by law.
30
31 Written by Eric B. Decker, James Youngman, and Kevin Dalley.
32 '
33
34
35 usage="\
36 Usage: $0 [--findoptions='-option1 -option2...']
37        [--localpaths='dir1 dir2...'] [--netpaths='dir1 dir2...']
38        [--prunepaths='dir1 dir2...'] [--prunefs='fs1 fs2...']
39        [--output=dbfile] [--netuser=user] [--localuser=user]
40        [--old-format] [--dbformat] [--version] [--help]
41
42 Report bugs to <bug-findutils@gnu.org>."
43 changeto=/
44 old=no
45 for arg
46 do
47   # If we are unable to fork, the back-tick operator will
48   # fail (and the shell will emit an error message).  When
49   # this happens, we exit with error value 71 (EX_OSERR).
50   # Alternative candidate - 75, EX_TEMPFAIL.
51   opt=`echo $arg|sed 's/^\([^=]*\).*/\1/'`  || exit 71
52   val=`echo $arg|sed 's/^[^=]*=\(.*\)/\1/'` || exit 71
53   case "$opt" in
54     --findoptions) FINDOPTIONS="$val" ;;
55     --localpaths) SEARCHPATHS="$val" ;;
56     --netpaths) NETPATHS="$val" ;;
57     --prunepaths) PRUNEPATHS="$val" ;;
58     --prunefs) PRUNEFS="$val" ;;
59     --output) LOCATE_DB="$val" ;;
60     --netuser) NETUSER="$val" ;;
61     --localuser) LOCALUSER="$val" ;;
62     --old-format) old=yes ;;
63     --changecwd)  changeto="$val" ;;
64     --dbformat)   dbformat="$val" ;;
65     --version) fail=0; echo "$version" || fail=1; exit $fail ;;
66     --help)    fail=0; echo "$usage"   || fail=1; exit $fail ;;
67     *) echo "updatedb: invalid option $opt
68 $usage" >&2
69        exit 1 ;;
70   esac
71 done
72
73
74
75
76 case "${dbformat:+yes}_${old}" in
77     yes_yes)
78         echo "The --dbformat and --old cannot both be specified." >&2
79         exit 1
80         ;;
81         *)
82         ;;
83 esac
84
85 if test "$old" = yes || test "$dbformat" = "old" ; then
86     echo "Warning: future versions of findutils will shortly discontinue support for the old locate database format." >&2
87     old=yes
88     sort="@SORT@"
89     print_option="-print"
90     frcode_options=""
91 else
92     frcode_options=""
93     case "$dbformat" in
94         "")
95                 # Default, use LOCATE02
96             ;;
97         LOCATE02)
98             ;;
99         slocate)
100             frcode_options="$frcode_options -S 1"
101             ;;
102         *)
103             echo "Unsupported locate database format ${dbformat}: Supported formats are:" >&2
104             echo "LOCATE02, slocate, old" >&2
105             exit 1
106     esac
107
108
109     if @SORT_SUPPORTS_Z@
110     then
111         sort="@SORT@ -z"
112         print_option="-print0"
113         frcode_options="$frcode_options -0"
114     else
115         sort="@SORT@"
116         print_option="-print"
117     fi
118 fi
119
120 getuid() {
121     # format of "id" output is ...
122     # uid=1(daemon) gid=1(other)
123     # for `id's that don't understand -u
124     id | cut -d'(' -f 1 | cut -d'=' -f2
125 }
126
127 # figure out if su supports the -s option
128 select_shell() {
129     if su "$1" -s $SHELL -c false < /dev/null  ; then
130         # No.
131         echo ""
132     else
133         if su "$1" -s $SHELL -c true < /dev/null  ; then
134             # Yes.
135             echo "-s $SHELL"
136         else
137             # su is unconditionally failing.  We won't be able to
138             # figure out what is wrong, so be conservative.
139             echo ""
140         fi
141     fi
142 }
143
144
145 # You can set these in the environment, or use command-line options,
146 # to override their defaults:
147
148 # Any global options for find?
149 : ${FINDOPTIONS=}
150
151 # What shell shoud we use?  We should use a POSIX-ish sh.
152 : ${SHELL="/bin/sh"}
153
154 # Non-network directories to put in the database.
155 : ${SEARCHPATHS="/"}
156
157 # Network (NFS, AFS, RFS, etc.) directories to put in the database.
158 : ${NETPATHS=}
159
160 # Directories to not put in the database, which would otherwise be.
161 : ${PRUNEPATHS="
162 /afs
163 /amd
164 /proc
165 /sfs
166 /tmp
167 /usr/tmp
168 /var/tmp
169 "}
170
171 # Trailing slashes result in regex items that are never matched, which
172 # is not what the user will expect.   Therefore we now reject such
173 # constructs.
174 for p in $PRUNEPATHS; do
175     case "$p" in
176         /*/)   echo "$0: $p: pruned paths should not contain trailing slashes" >&2
177                exit 1
178     esac
179 done
180
181 # The same, in the form of a regex that find can use.
182 test -z "$PRUNEREGEX" &&
183   PRUNEREGEX=`echo $PRUNEPATHS|sed -e 's,^,\\\(^,' -e 's, ,$\\\)\\\|\\\(^,g' -e 's,$,$\\\),'`
184
185 # The database file to build.
186 : ${LOCATE_DB=@LOCATE_DB@}
187
188 # Directory to hold intermediate files.
189 if test -d /var/tmp; then
190   : ${TMPDIR=/var/tmp}
191 elif test -d /usr/tmp; then
192   : ${TMPDIR=/usr/tmp}
193 else
194   : ${TMPDIR=/tmp}
195 fi
196 export TMPDIR
197
198 # The user to search network directories as.
199 : ${NETUSER=daemon}
200
201 # The directory containing the subprograms.
202 if test -n "$LIBEXECDIR" ; then
203     : LIBEXECDIR already set, do nothing
204 else
205     : ${LIBEXECDIR=@libexecdir@}
206 fi
207
208 # The directory containing find.
209 if test -n "$BINDIR" ; then
210     : BINDIR already set, do nothing
211 else
212     : ${BINDIR=@bindir@}
213 fi
214
215 # The names of the utilities to run to build the database.
216 : ${find:=${BINDIR}/@find@}
217 : ${frcode:=${LIBEXECDIR}/@frcode@}
218 : ${bigram:=${LIBEXECDIR}/@bigram@}
219 : ${code:=${LIBEXECDIR}/@code@}
220
221 make_tempdir () {
222     # This implementation is adapted from the GNU Autoconf manual.
223     {
224         tmp=`
225     (umask 077 && mktemp -d "$TMPDIR/updatedbXXXXXX") 2>/dev/null
226     ` &&
227         test -n "$tmp" && test -d "$tmp"
228     } || {
229         # This method is less secure than mktemp -d, but it's a fallback.
230         #
231         # We use $$ as well as $RANDOM since $RANDOM may not be available.
232         # We also add a time-dependent suffix.  This is actually somewhat
233         # predictable, but then so is $$.  POSIX does not require date to
234         # support +%N.
235         ts=`date +%N%S || date +%S 2>/dev/null`
236         tmp="$TMPDIR"/updatedb"$$"-"${RANDOM:-}${ts}"
237         (umask 077 && mkdir "$tmp")
238     }
239     echo "$tmp"
240 }
241
242 checkbinary () {
243     if test -x "$1" ; then
244         : ok
245     else
246       eval echo "updatedb needs to be able to execute $1, but cannot." >&2
247       exit 1
248     fi
249 }
250
251 for binary in $find $frcode $bigram $code
252 do
253   checkbinary $binary
254 done
255
256
257 : ${PRUNEFS="
258 9P
259 NFS
260 afs
261 autofs
262 cifs
263 coda
264 devfs
265 devpts
266 ftpfs
267 iso9660
268 mfs
269 ncpfs
270 nfs
271 nfs4
272 proc
273 shfs
274 smbfs
275 sysfs
276 "}
277
278 if test -n "$PRUNEFS"; then
279 prunefs_exp=`echo $PRUNEFS |sed -e 's/\([^ ][^ ]*\)/-o -fstype \1/g' \
280  -e 's/-o //' -e 's/$/ -o/'`
281 else
282   prunefs_exp=''
283 fi
284
285 # Make and code the file list.
286 # Sort case insensitively for users' convenience.
287
288 rm -f $LOCATE_DB.n
289 trap 'rm -f $LOCATE_DB.n; exit' HUP TERM
290
291 if test $old = no; then
292 # LOCATE02 or slocate format
293 if {
294 cd "$changeto"
295 if test -n "$SEARCHPATHS"; then
296   if [ "$LOCALUSER" != "" ]; then
297     # : A1
298     su $LOCALUSER `select_shell $LOCALUSER` -c \
299     "$find $SEARCHPATHS $FINDOPTIONS \
300      \\( $prunefs_exp \
301      -type d -regex '$PRUNEREGEX' \\) -prune -o $print_option"
302   else
303     # : A2
304     $find $SEARCHPATHS $FINDOPTIONS \
305      \( $prunefs_exp \
306      -type d -regex "$PRUNEREGEX" \) -prune -o $print_option
307   fi
308 fi
309
310 if test -n "$NETPATHS"; then
311 myuid=`getuid`
312 if [ "$myuid" = 0 ]; then
313     # : A3
314     su $NETUSER `select_shell $NETUSER` -c \
315      "$find $NETPATHS $FINDOPTIONS \\( -type d -regex '$PRUNEREGEX' -prune \\) -o $print_option" ||
316     exit $?
317   else
318     # : A4
319     $find $NETPATHS $FINDOPTIONS \( -type d -regex "$PRUNEREGEX" -prune \) -o $print_option ||
320     exit $?
321   fi
322 fi
323 } | $sort -f | $frcode $frcode_options > $LOCATE_DB.n
324 then
325     : OK so far
326     true
327 else
328     rv=$?
329     echo "Failed to generate $LOCATE_DB.n" >&2
330     rm -f $LOCATE_DB.n
331     exit $rv
332 fi
333
334 # To avoid breaking locate while this script is running, put the
335 # results in a temp file, then rename it atomically.
336 if test -s $LOCATE_DB.n; then
337   chmod 644 ${LOCATE_DB}.n
338   mv ${LOCATE_DB}.n $LOCATE_DB
339 else
340   echo "updatedb: new database would be empty" >&2
341   rm -f $LOCATE_DB.n
342 fi
343
344 else # old
345
346 if temp_directory="`make_tempdir`"; then
347     bigrams="${temp_directory}"/bigrams
348     filelist="${temp_directory}"/filelist
349 else
350     echo "failed to create temporary directory" >&2
351     exit 1
352 fi
353
354 rm -f $LOCATE_DB.n
355 trap 'rm -f $LOCATE_DB.n; rm -rf "${temp_directory}"; exit' HUP TERM
356
357 # Alphabetize subdirectories before file entries using tr.  James Woods says:
358 # "to get everything in monotonic collating sequence, to avoid some
359 # breakage i'll have to think about."
360 {
361 cd "$changeto"
362 if test -n "$SEARCHPATHS"; then
363   if [ "$LOCALUSER" != "" ]; then
364     # : A5
365     su $LOCALUSER `select_shell $LOCALUSER` -c \
366     "$find $SEARCHPATHS $FINDOPTIONS \
367      \( $prunefs_exp \
368      -type d -regex '$PRUNEREGEX' \) -prune -o $print_option" || exit $?
369   else
370     # : A6
371     $find $SEARCHPATHS $FINDOPTIONS \
372      \( $prunefs_exp \
373      -type d -regex "$PRUNEREGEX" \) -prune -o $print_option || exit $?
374   fi
375 fi
376
377 if test -n "$NETPATHS"; then
378   myuid=`getuid`
379   if [ "$myuid" = 0 ]; then
380     # : A7
381     su $NETUSER `select_shell $NETUSER` -c \
382      "$find $NETPATHS $FINDOPTIONS \\( -type d -regex '$PRUNEREGEX' -prune \\) -o $print_option" ||
383     exit $?
384   else
385     # : A8
386     $find $NETPATHS $FINDOPTIONS \( -type d -regex "$PRUNEREGEX" -prune \) -o $print_option ||
387     exit $?
388   fi
389 fi
390 } | tr / '\001' | $sort -f | tr '\001' / > "$filelist"
391
392 # Compute the (at most 128) most common bigrams in the file list.
393 $bigram $bigram_opts < $filelist | sort | uniq -c | sort -nr |
394   awk '{ if (NR <= 128) print $2 }' | tr -d '\012' > "$bigrams"
395
396 # Code the file list.
397 $code "$bigrams" < "$filelist" > $LOCATE_DB.n
398
399 rm -rf "${temp_directory}"
400
401 # To reduce the chances of breaking locate while this script is running,
402 # put the results in a temp file, then rename it atomically.
403 if test -s $LOCATE_DB.n; then
404   chmod 644 ${LOCATE_DB}.n
405   mv ${LOCATE_DB}.n $LOCATE_DB
406 else
407   echo "updatedb: new database would be empty" >&2
408   rm -f $LOCATE_DB.n
409 fi
410
411 fi
412
413 exit 0