* lib/install-sh: Initialize IFS, so field splitting isn't
[platform/upstream/automake.git] / lib / install-sh
1 #!/bin/sh
2 # install - install a program, script, or datafile
3
4 scriptversion=2006-05-11.19
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.  It can only install one file at a time, a restriction
43 # shared with many OS's install programs.
44
45 nl='
46 '
47 IFS=" ""        $nl"
48
49 # set DOITPROG to echo to test this script
50
51 # Don't use :- since 4.3BSD and earlier shells don't like it.
52 doit="${DOITPROG-}"
53
54 # put in absolute paths if you don't have them in your path; or use env. vars.
55
56 mvprog="${MVPROG-mv}"
57 cpprog="${CPPROG-cp}"
58 chmodprog="${CHMODPROG-chmod}"
59 chownprog="${CHOWNPROG-chown}"
60 chgrpprog="${CHGRPPROG-chgrp}"
61 stripprog="${STRIPPROG-strip}"
62 rmprog="${RMPROG-rm}"
63 mkdirprog="${MKDIRPROG-mkdir}"
64
65 posix_glob=
66 posix_mkdir=
67
68 # Symbolic mode for testing mkdir with directories.
69 # It is the same as 755, but also tests that "u+" works.
70 test_mode=u=rwx,g=rx,o=rx,u+wx
71
72 # Desired mode of installed file.
73 mode=0755
74
75 # Desired mode of newly created intermediate directories.
76 # It is empty if not known yet.
77 intermediate_mode=
78
79 chmodcmd=$chmodprog
80 chowncmd=
81 chgrpcmd=
82 stripcmd=
83 rmcmd="$rmprog -f"
84 mvcmd="$mvprog"
85 src=
86 dst=
87 dir_arg=
88 dstarg=
89 no_target_directory=
90
91 usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
92    or: $0 [OPTION]... SRCFILES... DIRECTORY
93    or: $0 [OPTION]... -t DIRECTORY SRCFILES...
94    or: $0 [OPTION]... -d DIRECTORIES...
95
96 In the 1st form, copy SRCFILE to DSTFILE.
97 In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
98 In the 4th, create DIRECTORIES.
99
100 Options:
101 -c         (ignored)
102 -d         create directories instead of installing files.
103 -g GROUP   $chgrpprog installed files to GROUP.
104 -m MODE    $chmodprog installed files to MODE.
105 -o USER    $chownprog installed files to USER.
106 -s         $stripprog installed files.
107 -t DIRECTORY  install into DIRECTORY.
108 -T         report an error if DSTFILE is a directory.
109 --help     display this help and exit.
110 --version  display version info and exit.
111
112 Environment variables override the default commands:
113   CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
114 "
115
116 while test $# -ne 0; do
117   case $1 in
118     -c) shift
119         continue;;
120
121     -d) dir_arg=true
122         shift
123         continue;;
124
125     -g) chgrpcmd="$chgrpprog $2"
126         shift
127         shift
128         continue;;
129
130     --help) echo "$usage"; exit $?;;
131
132     -m) mode=$2
133         shift
134         shift
135         continue;;
136
137     -o) chowncmd="$chownprog $2"
138         shift
139         shift
140         continue;;
141
142     -s) stripcmd=$stripprog
143         shift
144         continue;;
145
146     -t) dstarg=$2
147         shift
148         shift
149         continue;;
150
151     -T) no_target_directory=true
152         shift
153         continue;;
154
155     --version) echo "$0 $scriptversion"; exit $?;;
156
157     --) shift
158         break;;
159
160     -*) echo "$0: invalid option: $1" >&2
161         exit 1;;
162
163     *)  break;;
164   esac
165 done
166
167 if test $# -ne 0 && test -z "$dir_arg$dstarg"; then
168   # When -d is used, all remaining arguments are directories to create.
169   # When -t is used, the destination is already specified.
170   # Otherwise, the last argument is the destination.  Remove it from $@.
171   for arg
172   do
173     if test -n "$dstarg"; then
174       # $@ is not empty: it contains at least $arg.
175       set fnord "$@" "$dstarg"
176       shift # fnord
177     fi
178     shift # arg
179     dstarg=$arg
180   done
181 fi
182
183 if test $# -eq 0; then
184   if test -z "$dir_arg"; then
185     echo "$0: no input file specified." >&2
186     exit 1
187   fi
188   # It's OK to call `install-sh -d' without argument.
189   # This can happen when creating conditional directories.
190   exit 0
191 fi
192
193 test -n "$dir_arg" || trap '(exit $?); exit' 1 2 13 15
194
195 for src
196 do
197   # Protect names starting with `-'.
198   case $src in
199     -*) src=./$src ;;
200   esac
201
202   if test -n "$dir_arg"; then
203     dst=$src
204     dstdir=$dst
205     test -d "$dstdir"
206     dstdir_status=$?
207   else
208
209     # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
210     # might cause directories to be created, which would be especially bad
211     # if $src (and thus $dsttmp) contains '*'.
212     if test ! -f "$src" && test ! -d "$src"; then
213       echo "$0: $src does not exist." >&2
214       exit 1
215     fi
216
217     if test -z "$dstarg"; then
218       echo "$0: no destination specified." >&2
219       exit 1
220     fi
221
222     dst=$dstarg
223     # Protect names starting with `-'.
224     case $dst in
225       -*) dst=./$dst ;;
226     esac
227
228     # If destination is a directory, append the input filename; won't work
229     # if double slashes aren't ignored.
230     if test -d "$dst"; then
231       if test -n "$no_target_directory"; then
232         echo "$0: $dstarg: Is a directory" >&2
233         exit 1
234       fi
235       dstdir=$dst
236       dst=$dstdir/`basename "$src"`
237       dstdir_status=0
238     else
239       # Prefer dirname, but fall back on a substitute if dirname fails.
240       dstdir=`
241         (dirname "$dst") 2>/dev/null ||
242         expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
243              X"$dst" : 'X\(//\)[^/]' \| \
244              X"$dst" : 'X\(//\)$' \| \
245              X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
246         echo X"$dst" |
247             sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
248                    s//\1/
249                    q
250                  }
251                  /^X\(\/\/\)[^/].*/{
252                    s//\1/
253                    q
254                  }
255                  /^X\(\/\/\)$/{
256                    s//\1/
257                    q
258                  }
259                  /^X\(\/\).*/{
260                    s//\1/
261                    q
262                  }
263                  s/.*/./; q'
264       `
265
266       test -d "$dstdir"
267       dstdir_status=$?
268     fi
269   fi
270
271   obsolete_mkdir_used=false
272
273   if test $dstdir_status != 0; then
274     case $posix_mkdir in
275       '')
276         posix_mkdir=false
277         if $mkdirprog -m $test_mode -p -- / >/dev/null 2>&1; then
278           posix_mkdir=true
279         else
280           # Remove any dirs left behind by ancient mkdir implementations.
281           rmdir ./-m "$test_mode" ./-p ./-- 2>/dev/null
282         fi ;;
283     esac
284
285     if
286       $posix_mkdir && {
287
288         # With -d, create the new directory with the user-specified mode.
289         # Otherwise, create it using the same intermediate mode that
290         # mkdir -p would use when creating intermediate directories.
291         # POSIX says that this mode is "$(umask -S),u+wx", so use that
292         # if umask -S works.
293
294         if test -n "$dir_arg"; then
295           mkdir_mode=$mode
296         else
297           case $intermediate_mode in
298             '')
299               if umask_S=`(umask -S) 2>/dev/null`; then
300                 intermediate_mode=$umask_S,u+wx
301               else
302                 intermediate_mode=$test_mode
303               fi ;;
304           esac
305           mkdir_mode=$intermediate_mode
306         fi
307
308         $mkdirprog -m "$mkdir_mode" -p -- "$dstdir"
309       }
310     then :
311     else
312
313       # mkdir does not conform to POSIX, or it failed possibly due to
314       # a race condition.  Create the directory the slow way, step by
315       # step, checking for races as we go.
316
317       case $dstdir in
318         /*) pathcomp=/ ;;
319         -*) pathcomp=./ ;;
320         *)  pathcomp= ;;
321       esac
322
323       case $posix_glob in
324         '')
325           if (set -f) 2>/dev/null; then
326             posix_glob=true
327           else
328             posix_glob=false
329           fi ;;
330       esac
331
332       oIFS=$IFS
333       IFS=/
334       $posix_glob && set -f
335       set fnord $dstdir
336       shift
337       $posix_glob && set +f
338       IFS=$oIFS
339
340       for d
341       do
342         test "x$d" = x && continue
343
344         pathcomp=$pathcomp$d
345         if test ! -d "$pathcomp"; then
346           $mkdirprog "$pathcomp"
347           # Don't fail if two instances are running concurrently.
348           test -d "$pathcomp" || exit 1
349         fi
350         pathcomp=$pathcomp/
351       done
352       obsolete_mkdir_used=true
353     fi
354   fi
355
356   if test -n "$dir_arg"; then
357     { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
358     { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
359     { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
360       test -z "$chmodcmd" || $doit $chmodcmd "$mode" "$dst"; } || exit 1
361   else
362
363     # Make a couple of temp file names in the proper directory.
364     dsttmp=$dstdir/_inst.$$_
365     rmtmp=$dstdir/_rm.$$_
366
367     # Trap to clean up those temp files at exit.
368     trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
369
370     # Copy the file name to the temp name.
371     $doit $cpprog "$src" "$dsttmp" &&
372
373     # and set any options; do chmod last to preserve setuid bits.
374     #
375     # If any of these fail, we abort the whole thing.  If we want to
376     # ignore errors from any of these, just make sure not to ignore
377     # errors from the above "$doit $cpprog $src $dsttmp" command.
378     #
379     { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
380       && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
381       && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
382       && { test -z "$chmodcmd" || $doit $chmodcmd "$mode" "$dsttmp"; } &&
383
384     # Now rename the file to the real destination.
385     { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \
386       || {
387            # The rename failed, perhaps because mv can't rename something else
388            # to itself, or perhaps because mv is so ancient that it does not
389            # support -f.
390
391            # Now remove or move aside any old file at destination location.
392            # We try this two ways since rm can't unlink itself on some
393            # systems and the destination file might be busy for other
394            # reasons.  In this case, the final cleanup might fail but the new
395            # file should still install successfully.
396            {
397              if test -f "$dst"; then
398                $doit $rmcmd -f "$dst" 2>/dev/null \
399                || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \
400                      && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\
401                || {
402                  echo "$0: cannot unlink or rename $dst" >&2
403                  (exit 1); exit 1
404                }
405              else
406                :
407              fi
408            } &&
409
410            # Now rename the file to the real destination.
411            $doit $mvcmd "$dsttmp" "$dst"
412          }
413     } || exit 1
414
415     trap '' 0
416   fi
417 done
418
419 # Local variables:
420 # eval: (add-hook 'write-file-hooks 'time-stamp)
421 # time-stamp-start: "scriptversion="
422 # time-stamp-format: "%:y-%02m-%02d.%02H"
423 # time-stamp-end: "$"
424 # End: