autoupdate
[gnulib.git] / build-aux / install-sh
1 #!/bin/sh
2 # install - install a program, script, or datafile
3
4 scriptversion=2013-10-30.23; # UTC
5
6 # This originates from X11R5 (mit/util/scripts/install.sh), which was
7 # later released in X11R6 (xc/config/util/install.sh) with the
8 # following copyright and license.
9 #
10 # Copyright (C) 1994 X Consortium
11 #
12 # Permission is hereby granted, free of charge, to any person obtaining a copy
13 # of this software and associated documentation files (the "Software"), to
14 # deal in the Software without restriction, including without limitation the
15 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 # sell copies of the Software, and to permit persons to whom the Software is
17 # furnished to do so, subject to the following conditions:
18 #
19 # The above copyright notice and this permission notice shall be included in
20 # all copies or substantial portions of the Software.
21 #
22 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25 # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26 # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
27 # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #
29 # Except as contained in this notice, the name of the X Consortium shall not
30 # be used in advertising or otherwise to promote the sale, use or other deal-
31 # ings in this Software without prior written authorization from the X Consor-
32 # tium.
33 #
34 #
35 # FSF changes to this file are in the public domain.
36 #
37 # Calling this script install-sh is preferred over install.sh, to prevent
38 # 'make' implicit rules from creating a file called install from it
39 # when there is no Makefile.
40 #
41 # This script is compatible with the BSD install script, but was written
42 # from scratch.
43
44 tab='   '
45 nl='
46 '
47 IFS=" $tab$nl"
48
49 # Set DOITPROG to "echo" to test this script.
50
51 doit=${DOITPROG-}
52 doit_exec=${doit:-exec}
53
54 # Put in absolute file names if you don't have them in your path;
55 # or use environment vars.
56
57 chgrpprog=${CHGRPPROG-chgrp}
58 chmodprog=${CHMODPROG-chmod}
59 chownprog=${CHOWNPROG-chown}
60 cmpprog=${CMPPROG-cmp}
61 cpprog=${CPPROG-cp}
62 mkdirprog=${MKDIRPROG-mkdir}
63 mvprog=${MVPROG-mv}
64 rmprog=${RMPROG-rm}
65 stripprog=${STRIPPROG-strip}
66
67 posix_mkdir=
68
69 # Desired mode of installed file.
70 mode=0755
71
72 chgrpcmd=
73 chmodcmd=$chmodprog
74 chowncmd=
75 mvcmd=$mvprog
76 rmcmd="$rmprog -f"
77 stripcmd=
78
79 src=
80 dst=
81 dir_arg=
82 dst_arg=
83
84 copy_on_change=false
85 no_target_directory=
86
87 usage="\
88 Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
89    or: $0 [OPTION]... SRCFILES... DIRECTORY
90    or: $0 [OPTION]... -t DIRECTORY SRCFILES...
91    or: $0 [OPTION]... -d DIRECTORIES...
92
93 In the 1st form, copy SRCFILE to DSTFILE.
94 In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
95 In the 4th, create DIRECTORIES.
96
97 Options:
98      --help     display this help and exit.
99      --version  display version info and exit.
100
101   -c            (ignored)
102   -C            install only if different (preserve the last data modification time)
103   -d            create directories instead of installing files.
104   -g GROUP      $chgrpprog installed files to GROUP.
105   -m MODE       $chmodprog installed files to MODE.
106   -o USER       $chownprog installed files to USER.
107   -s            $stripprog installed files.
108   -t DIRECTORY  install into DIRECTORY.
109   -T            report an error if DSTFILE is a directory.
110
111 Environment variables override the default commands:
112   CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
113   RMPROG STRIPPROG
114 "
115
116 while test $# -ne 0; do
117   case $1 in
118     -c) ;;
119
120     -C) copy_on_change=true;;
121
122     -d) dir_arg=true;;
123
124     -g) chgrpcmd="$chgrpprog $2"
125         shift;;
126
127     --help) echo "$usage"; exit $?;;
128
129     -m) mode=$2
130         case $mode in
131           *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
132             echo "$0: invalid mode: $mode" >&2
133             exit 1;;
134         esac
135         shift;;
136
137     -o) chowncmd="$chownprog $2"
138         shift;;
139
140     -s) stripcmd=$stripprog;;
141
142     -t) dst_arg=$2
143         # Protect names problematic for 'test' and other utilities.
144         case $dst_arg in
145           -* | [=\(\)!]) dst_arg=./$dst_arg;;
146         esac
147         shift;;
148
149     -T) no_target_directory=true;;
150
151     --version) echo "$0 $scriptversion"; exit $?;;
152
153     --) shift
154         break;;
155
156     -*) echo "$0: invalid option: $1" >&2
157         exit 1;;
158
159     *)  break;;
160   esac
161   shift
162 done
163
164 if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
165   # When -d is used, all remaining arguments are directories to create.
166   # When -t is used, the destination is already specified.
167   # Otherwise, the last argument is the destination.  Remove it from $@.
168   for arg
169   do
170     if test -n "$dst_arg"; then
171       # $@ is not empty: it contains at least $arg.
172       set fnord "$@" "$dst_arg"
173       shift # fnord
174     fi
175     shift # arg
176     dst_arg=$arg
177     # Protect names problematic for 'test' and other utilities.
178     case $dst_arg in
179       -* | [=\(\)!]) dst_arg=./$dst_arg;;
180     esac
181   done
182 fi
183
184 if test $# -eq 0; then
185   if test -z "$dir_arg"; then
186     echo "$0: no input file specified." >&2
187     exit 1
188   fi
189   # It's OK to call 'install-sh -d' without argument.
190   # This can happen when creating conditional directories.
191   exit 0
192 fi
193
194 if test -z "$dir_arg"; then
195   do_exit='(exit $ret); exit $ret'
196   trap "ret=129; $do_exit" 1
197   trap "ret=130; $do_exit" 2
198   trap "ret=141; $do_exit" 13
199   trap "ret=143; $do_exit" 15
200
201   # Set umask so as not to create temps with too-generous modes.
202   # However, 'strip' requires both read and write access to temps.
203   case $mode in
204     # Optimize common cases.
205     *644) cp_umask=133;;
206     *755) cp_umask=22;;
207
208     *[0-7])
209       if test -z "$stripcmd"; then
210         u_plus_rw=
211       else
212         u_plus_rw='% 200'
213       fi
214       cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
215     *)
216       if test -z "$stripcmd"; then
217         u_plus_rw=
218       else
219         u_plus_rw=,u+rw
220       fi
221       cp_umask=$mode$u_plus_rw;;
222   esac
223 fi
224
225 for src
226 do
227   # Protect names problematic for 'test' and other utilities.
228   case $src in
229     -* | [=\(\)!]) src=./$src;;
230   esac
231
232   if test -n "$dir_arg"; then
233     dst=$src
234     dstdir=$dst
235     test -d "$dstdir"
236     dstdir_status=$?
237   else
238
239     # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
240     # might cause directories to be created, which would be especially bad
241     # if $src (and thus $dsttmp) contains '*'.
242     if test ! -f "$src" && test ! -d "$src"; then
243       echo "$0: $src does not exist." >&2
244       exit 1
245     fi
246
247     if test -z "$dst_arg"; then
248       echo "$0: no destination specified." >&2
249       exit 1
250     fi
251     dst=$dst_arg
252
253     # If destination is a directory, append the input filename; won't work
254     # if double slashes aren't ignored.
255     if test -d "$dst"; then
256       if test -n "$no_target_directory"; then
257         echo "$0: $dst_arg: Is a directory" >&2
258         exit 1
259       fi
260       dstdir=$dst
261       dst=$dstdir/`basename "$src"`
262       dstdir_status=0
263     else
264       dstdir=`dirname "$dst"`
265       test -d "$dstdir"
266       dstdir_status=$?
267     fi
268   fi
269
270   obsolete_mkdir_used=false
271
272   if test $dstdir_status != 0; then
273     case $posix_mkdir in
274       '')
275         # Create intermediate dirs using mode 755 as modified by the umask.
276         # This is like FreeBSD 'install' as of 1997-10-28.
277         umask=`umask`
278         case $stripcmd.$umask in
279           # Optimize common cases.
280           *[2367][2367]) mkdir_umask=$umask;;
281           .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
282
283           *[0-7])
284             mkdir_umask=`expr $umask + 22 \
285               - $umask % 100 % 40 + $umask % 20 \
286               - $umask % 10 % 4 + $umask % 2
287             `;;
288           *) mkdir_umask=$umask,go-w;;
289         esac
290
291         # With -d, create the new directory with the user-specified mode.
292         # Otherwise, rely on $mkdir_umask.
293         if test -n "$dir_arg"; then
294           mkdir_mode=-m$mode
295         else
296           mkdir_mode=
297         fi
298
299         posix_mkdir=false
300         case $umask in
301           *[123567][0-7][0-7])
302             # POSIX mkdir -p sets u+wx bits regardless of umask, which
303             # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
304             ;;
305           *)
306             tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
307             trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
308
309             if (umask $mkdir_umask &&
310                 exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
311             then
312               if test -z "$dir_arg" || {
313                    # Check for POSIX incompatibilities with -m.
314                    # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
315                    # other-writable bit of parent directory when it shouldn't.
316                    # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
317                    ls_ld_tmpdir=`ls -ld "$tmpdir"`
318                    case $ls_ld_tmpdir in
319                      d????-?r-*) different_mode=700;;
320                      d????-?--*) different_mode=755;;
321                      *) false;;
322                    esac &&
323                    $mkdirprog -m$different_mode -p -- "$tmpdir" && {
324                      ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
325                      test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
326                    }
327                  }
328               then posix_mkdir=:
329               fi
330               rmdir "$tmpdir/d" "$tmpdir"
331             else
332               # Remove any dirs left behind by ancient mkdir implementations.
333               rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
334             fi
335             trap '' 0;;
336         esac;;
337     esac
338
339     if
340       $posix_mkdir && (
341         umask $mkdir_umask &&
342         $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
343       )
344     then :
345     else
346
347       # The umask is ridiculous, or mkdir does not conform to POSIX,
348       # or it failed possibly due to a race condition.  Create the
349       # directory the slow way, step by step, checking for races as we go.
350
351       case $dstdir in
352         /*) prefix='/';;
353         [-=\(\)!]*) prefix='./';;
354         *)  prefix='';;
355       esac
356
357       oIFS=$IFS
358       IFS=/
359       set -f
360       set fnord $dstdir
361       shift
362       set +f
363       IFS=$oIFS
364
365       prefixes=
366
367       for d
368       do
369         test X"$d" = X && continue
370
371         prefix=$prefix$d
372         if test -d "$prefix"; then
373           prefixes=
374         else
375           if $posix_mkdir; then
376             (umask=$mkdir_umask &&
377              $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
378             # Don't fail if two instances are running concurrently.
379             test -d "$prefix" || exit 1
380           else
381             case $prefix in
382               *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
383               *) qprefix=$prefix;;
384             esac
385             prefixes="$prefixes '$qprefix'"
386           fi
387         fi
388         prefix=$prefix/
389       done
390
391       if test -n "$prefixes"; then
392         # Don't fail if two instances are running concurrently.
393         (umask $mkdir_umask &&
394          eval "\$doit_exec \$mkdirprog $prefixes") ||
395           test -d "$dstdir" || exit 1
396         obsolete_mkdir_used=true
397       fi
398     fi
399   fi
400
401   if test -n "$dir_arg"; then
402     { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
403     { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
404     { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
405       test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
406   else
407
408     # Make a couple of temp file names in the proper directory.
409     dsttmp=$dstdir/_inst.$$_
410     rmtmp=$dstdir/_rm.$$_
411
412     # Trap to clean up those temp files at exit.
413     trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
414
415     # Copy the file name to the temp name.
416     (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
417
418     # and set any options; do chmod last to preserve setuid bits.
419     #
420     # If any of these fail, we abort the whole thing.  If we want to
421     # ignore errors from any of these, just make sure not to ignore
422     # errors from the above "$doit $cpprog $src $dsttmp" command.
423     #
424     { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
425     { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
426     { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
427     { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
428
429     # If -C, don't bother to copy if it wouldn't change the file.
430     if $copy_on_change &&
431        old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
432        new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
433        set -f &&
434        set X $old && old=:$2:$4:$5:$6 &&
435        set X $new && new=:$2:$4:$5:$6 &&
436        set +f &&
437        test "$old" = "$new" &&
438        $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
439     then
440       rm -f "$dsttmp"
441     else
442       # Rename the file to the real destination.
443       $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
444
445       # The rename failed, perhaps because mv can't rename something else
446       # to itself, or perhaps because mv is so ancient that it does not
447       # support -f.
448       {
449         # Now remove or move aside any old file at destination location.
450         # We try this two ways since rm can't unlink itself on some
451         # systems and the destination file might be busy for other
452         # reasons.  In this case, the final cleanup might fail but the new
453         # file should still install successfully.
454         {
455           test ! -f "$dst" ||
456           $doit $rmcmd -f "$dst" 2>/dev/null ||
457           { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
458             { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
459           } ||
460           { echo "$0: cannot unlink or rename $dst" >&2
461             (exit 1); exit 1
462           }
463         } &&
464
465         # Now rename the file to the real destination.
466         $doit $mvcmd "$dsttmp" "$dst"
467       }
468     fi || exit 1
469
470     trap '' 0
471   fi
472 done
473
474 # Local variables:
475 # eval: (add-hook 'write-file-hooks 'time-stamp)
476 # time-stamp-start: "scriptversion="
477 # time-stamp-format: "%:y-%02m-%02d.%02H"
478 # time-stamp-time-zone: "UTC"
479 # time-stamp-end: "; # UTC"
480 # End: