]> Dogcows Code - chaz/yoink/blob - tools/install.sh
repository cleanup
[chaz/yoink] / tools / install.sh
1 #!/bin/sh
2 #
3 # INSTALL (C) 2002 Emile van Bergen. Distribution of this file is allowed under
4 # the conditions detailed in the GNU General Public License (GPL). See the file
5 # COPYING for more information.
6 #
7 # This script installs zero or more files into a specified directory. If one or
8 # more components of the destination path do not exist, they are created. The
9 # permissions of the destination file and the destination directory(s), if any
10 # need to be created, can be specified separately. The user can also specify
11 # that the operation must be skipped if the destination file or the destination
12 # directory already exists. Source files are stripped of their directory
13 # components before determining the destination name.
14 #
15 # It is intended to replace the /usr/bin/install command, which has no portable
16 # subset of features that offers anything above /bin/cp. Each version is broken
17 # in its own ways, the most annoying examples being that some can only install
18 # a single file at a time and that some do not create destination directories
19 # recursively. Hence this shell script, that is intended to be portable across
20 # all POSIX-compliant /bin/sh shells. It does not assume a working 'mkdir -p'
21 # command.
22 #
23 # Invocation:
24 #
25 # install arguments...
26 #
27 # Each argument is either an option, as specified below, a source file, or
28 # a destination directory, with -d prepended. Each time a destination
29 # directory is encountered, the source files leading up to it are installed,
30 # and then all options are reset, allowing you to perform multiple install
31 # operations with one command.
32 #
33 # Options:
34 #
35 # -h Show a brief usage message
36 # -v Show what's being done
37 # -m specify mode of destination files
38 # -md specify mode of destination directories, if any are created
39 # -n skip operation if destination file exists
40 # -nd skip operation if destination directory exists
41 #
42 # Return values:
43 #
44 # 0 Successful completion
45 # >0 Error occurred
46 #
47 # Limitations:
48 #
49 # * Source files cannot start with a '-' or contain spaces
50 # * Destination directories cannot start with a '-' or contain spaces
51 # * If multiple different modes are desired for files in a single destination
52 # directory, you must specify multiple installation sets (-d options), one
53 # for each mode (eg. install -m 644 file1 file2 -d dir file3 -m 600 -d dir).
54 # * The /bin/sh shell used to run this script must support user-defined
55 # functions.
56 # * The system must have mkdir, chmod, basename, tr, sed and cp available.
57 # If needed, basename and tr could be provided by sed, but I don't think
58 # that should be done by default as they are very common.
59 #
60 # Notes (not bugs, features. Really!):
61 #
62 # * If the destination directory already exists, its mode is not changed
63 # even if -md is specified; that mode is only used when creating new ones.
64 # * If the destination file already exists but is overwritten because no -n
65 # was specified, the new mode, if specified, is applied as well.
66 # * QNX-style paths starting with // are honored, as are .. path components.
67 # An initial .. works as expected, and a destination path a/b/../c creates
68 # a, a/b, a/c and installs the files in a/c.
69 #
70 # History
71 #
72 # 2002/09/13 - EvB - Created
73
74
75 make_dir() {
76
77 dir="$1"
78 [ -n "$verbose" ] && echo "Creating directory $dir"
79
80 mkdir "$dir" || exit 1
81
82 if [ -n "$mode_dir" ]
83 then
84 chmod "$mode_dir" "$dir" || exit 2
85 fi
86
87 return
88 }
89
90
91 make_dir_tree() {
92
93 root=`echo $1 | sed -e 's/[^/].*$//g'`
94 components=`echo $1 | tr / " "`
95
96 cumul=
97 for comp in $components
98 do
99 if [ -n "$cumul" ]
100 then
101 cumul="$cumul/$comp"
102 else
103 cumul="$comp"
104 fi
105 [ "$comp" = "." ] || [ "$comp" = ".." ] ||
106 [ -d "$root$cumul" ] || make_dir "$root$cumul"
107 done
108
109 dest=$root$cumul
110 }
111
112
113 do_install() {
114
115 dest="$1"
116
117 if [ ! -d "$dest" ]
118 then
119 make_dir_tree "$dest"
120 else
121 if [ -n "$new_dir" ]
122 then
123 echo "$me: Directory $dest already exists -- skipping"
124 return
125 fi
126 fi
127
128 for src_file in $src
129 do
130 file=`basename $src_file`
131 dest_file="$dest/$file"
132
133 if [ -n "$new" ] && [ -f $dest_file ]
134 then
135 echo "$me: File $dest_file already exists -- skipping"
136 continue
137 fi
138
139 [ -n "$verbose" ] && echo "Copying $src_file to $dest_file"
140 cp "$src_file" "$dest_file" || exit 3
141
142 if [ -n "$mode" ]
143 then
144 chmod "$mode" "$dest_file" || exit 4
145 fi
146 done
147
148 return
149 }
150
151
152 init_opts() {
153 verbose=
154 mode=
155 mode_dir=
156 new=
157 new_dir=
158 src=
159 }
160
161
162 ### Main entry point
163
164 me=`basename $0`
165 init_opts
166 while [ -n "$1" ]
167 do
168 case "$1" in
169
170 -v) verbose=1 ;;
171
172 -m) mode="$2" ; shift ;;
173 -md) mode_dir="$2" ; shift ;;
174
175 -n) new=1 ;;
176 -nd) new_dir=1 ;;
177
178 -d) do_install "$2" ; init_opts ; shift ;;
179
180 -*)
181 echo Usage: $me [options] [file...] -d directory
182 exit 5
183 ;;
184
185 *) src="$src $1" ;;
186
187 esac
188 shift
189 done
190
191 exit 0
This page took 0.043592 seconds and 4 git commands to generate.