/[gentoo-x86]/eclass/unpacker.eclass
Gentoo

Contents of /eclass/unpacker.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.15 - (show annotations) (download)
Tue Feb 18 06:13:50 2014 UTC (10 months, 1 week ago) by vapier
Branch: MAIN
Changes since 1.14: +2 -2 lines
add makeself 2.2.0 version

1 # Copyright 1999-2013 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3 # $Header: /var/cvsroot/gentoo-x86/eclass/unpacker.eclass,v 1.14 2013/12/22 14:44:07 vapier Exp $
4
5 # @ECLASS: unpacker.eclass
6 # @MAINTAINER:
7 # base-system@gentoo.org
8 # @BLURB: helpers for extraneous file formats and consistent behavior across EAPIs
9 # @DESCRIPTION:
10 # Some extraneous file formats are not part of PMS, or are only in certain
11 # EAPIs. Rather than worrying about that, support the crazy cruft here
12 # and for all EAPI versions.
13
14 # Possible todos:
15 # - merge rpm unpacking
16 # - support partial unpacks?
17
18 if [[ ${___ECLASS_ONCE_UNPACKER} != "recur -_+^+_- spank" ]] ; then
19 ___ECLASS_ONCE_UNPACKER="recur -_+^+_- spank"
20
21 # @ECLASS-VARIABLE: UNPACKER_BZ2
22 # @DEFAULT_UNSET
23 # @DESCRIPTION:
24 # Utility to use to decompress bzip2 files. Will dynamically pick between
25 # `pbzip2` and `bzip2`. Make sure your choice accepts the "-dc" options.
26 # Note: this is meant for users to set, not ebuilds.
27
28 # for internal use only (unpack_pdv and unpack_makeself)
29 find_unpackable_file() {
30 local src=$1
31 if [[ -z ${src} ]] ; then
32 src=${DISTDIR}/${A}
33 else
34 if [[ ${src} == ./* ]] ; then
35 : # already what we want
36 elif [[ -e ${DISTDIR}/${src} ]] ; then
37 src=${DISTDIR}/${src}
38 elif [[ -e ${PWD}/${src} ]] ; then
39 src=${PWD}/${src}
40 elif [[ -e ${src} ]] ; then
41 src=${src}
42 fi
43 fi
44 [[ ! -e ${src} ]] && return 1
45 echo "${src}"
46 }
47
48 unpack_banner() {
49 echo ">>> Unpacking ${1##*/} to ${PWD}"
50 }
51
52 # @FUNCTION: unpack_pdv
53 # @USAGE: <file to unpack> <size of off_t>
54 # @DESCRIPTION:
55 # Unpack those pesky pdv generated files ...
56 # They're self-unpacking programs with the binary package stuffed in
57 # the middle of the archive. Valve seems to use it a lot ... too bad
58 # it seems to like to segfault a lot :(. So lets take it apart ourselves.
59 #
60 # You have to specify the off_t size ... I have no idea how to extract that
61 # information out of the binary executable myself. Basically you pass in
62 # the size of the off_t type (in bytes) on the machine that built the pdv
63 # archive.
64 #
65 # One way to determine this is by running the following commands:
66 #
67 # @CODE
68 # strings <pdv archive> | grep lseek
69 # strace -elseek <pdv archive>
70 # @CODE
71 #
72 # Basically look for the first lseek command (we do the strings/grep because
73 # sometimes the function call is _llseek or something) and steal the 2nd
74 # parameter. Here is an example:
75 #
76 # @CODE
77 # $ strings hldsupdatetool.bin | grep lseek
78 # lseek
79 # $ strace -elseek ./hldsupdatetool.bin
80 # lseek(3, -4, SEEK_END) = 2981250
81 # @CODE
82 #
83 # Thus we would pass in the value of '4' as the second parameter.
84 unpack_pdv() {
85 local src=$(find_unpackable_file "$1")
86 local sizeoff_t=$2
87
88 [[ -z ${src} ]] && die "Could not locate source for '$1'"
89 [[ -z ${sizeoff_t} ]] && die "No idea what off_t size was used for this pdv :("
90
91 unpack_banner "${src}"
92
93 local metaskip=$(tail -c ${sizeoff_t} "${src}" | hexdump -e \"%i\")
94 local tailskip=$(tail -c $((${sizeoff_t}*2)) "${src}" | head -c ${sizeoff_t} | hexdump -e \"%i\")
95
96 # grab metadata for debug reasons
97 local metafile="${T}/${FUNCNAME}.meta"
98 tail -c +$((${metaskip}+1)) "${src}" > "${metafile}"
99
100 # rip out the final file name from the metadata
101 local datafile=$(tail -c +$((${metaskip}+1)) "${src}" | strings | head -n 1)
102 datafile=$(basename "${datafile}")
103
104 # now lets uncompress/untar the file if need be
105 local tmpfile="${T}/${FUNCNAME}"
106 tail -c +$((${tailskip}+1)) ${src} 2>/dev/null | head -c 512 > "${tmpfile}"
107
108 local iscompressed=$(file -b "${tmpfile}")
109 if [[ ${iscompressed:0:8} == "compress" ]] ; then
110 iscompressed=1
111 mv "${tmpfile}"{,.Z}
112 gunzip "${tmpfile}"
113 else
114 iscompressed=0
115 fi
116 local istar=$(file -b "${tmpfile}")
117 if [[ ${istar:0:9} == "POSIX tar" ]] ; then
118 istar=1
119 else
120 istar=0
121 fi
122
123 #for some reason gzip dies with this ... dd cant provide buffer fast enough ?
124 #dd if=${src} ibs=${metaskip} count=1 \
125 # | dd ibs=${tailskip} skip=1 \
126 # | gzip -dc \
127 # > ${datafile}
128 if [ ${iscompressed} -eq 1 ] ; then
129 if [ ${istar} -eq 1 ] ; then
130 tail -c +$((${tailskip}+1)) "${src}" 2>/dev/null \
131 | head -c $((${metaskip}-${tailskip})) \
132 | tar -xzf -
133 else
134 tail -c +$((${tailskip}+1)) "${src}" 2>/dev/null \
135 | head -c $((${metaskip}-${tailskip})) \
136 | gzip -dc \
137 > ${datafile}
138 fi
139 else
140 if [ ${istar} -eq 1 ] ; then
141 tail -c +$((${tailskip}+1)) "${src}" 2>/dev/null \
142 | head -c $((${metaskip}-${tailskip})) \
143 | tar --no-same-owner -xf -
144 else
145 tail -c +$((${tailskip}+1)) "${src}" 2>/dev/null \
146 | head -c $((${metaskip}-${tailskip})) \
147 > ${datafile}
148 fi
149 fi
150 true
151 #[ -s "${datafile}" ] || die "failure unpacking pdv ('${metaskip}' '${tailskip}' '${datafile}')"
152 #assert "failure unpacking pdv ('${metaskip}' '${tailskip}' '${datafile}')"
153 }
154
155 # @FUNCTION: unpack_makeself
156 # @USAGE: [file to unpack] [offset] [tail|dd]
157 # @DESCRIPTION:
158 # Unpack those pesky makeself generated files ...
159 # They're shell scripts with the binary package tagged onto
160 # the end of the archive. Loki utilized the format as does
161 # many other game companies.
162 #
163 # If the file is not specified, then ${A} is used. If the
164 # offset is not specified then we will attempt to extract
165 # the proper offset from the script itself.
166 unpack_makeself() {
167 local src_input=${1:-${A}}
168 local src=$(find_unpackable_file "${src_input}")
169 local skip=$2
170 local exe=$3
171
172 [[ -z ${src} ]] && die "Could not locate source for '${src_input}'"
173
174 unpack_banner "${src}"
175
176 if [[ -z ${skip} ]] ; then
177 local ver=$(grep -m1 -a '#.*Makeself' "${src}" | awk '{print $NF}')
178 local skip=0
179 exe=tail
180 case ${ver} in
181 1.5.*|1.6.0-nv*) # tested 1.5.{3,4,5} ... guessing 1.5.x series is same
182 skip=$(grep -a ^skip= "${src}" | cut -d= -f2)
183 ;;
184 2.0|2.0.1)
185 skip=$(grep -a ^$'\t'tail "${src}" | awk '{print $2}' | cut -b2-)
186 ;;
187 2.1.1)
188 skip=$(grep -a ^offset= "${src}" | awk '{print $2}' | cut -b2-)
189 (( skip++ ))
190 ;;
191 2.1.2)
192 skip=$(grep -a ^offset= "${src}" | awk '{print $3}' | head -n 1)
193 (( skip++ ))
194 ;;
195 2.1.3)
196 skip=`grep -a ^offset= "${src}" | awk '{print $3}'`
197 (( skip++ ))
198 ;;
199 2.1.4|2.1.5|2.1.6|2.2.0)
200 skip=$(grep -a offset=.*head.*wc "${src}" | awk '{print $3}' | head -n 1)
201 skip=$(head -n ${skip} "${src}" | wc -c)
202 exe="dd"
203 ;;
204 *)
205 eerror "I'm sorry, but I was unable to support the Makeself file."
206 eerror "The version I detected was '${ver}'."
207 eerror "Please file a bug about the file ${src##*/} at"
208 eerror "http://bugs.gentoo.org/ so that support can be added."
209 die "makeself version '${ver}' not supported"
210 ;;
211 esac
212 debug-print "Detected Makeself version ${ver} ... using ${skip} as offset"
213 fi
214 case ${exe} in
215 tail) exe="tail -n +${skip} '${src}'";;
216 dd) exe="dd ibs=${skip} skip=1 if='${src}'";;
217 *) die "makeself cant handle exe '${exe}'"
218 esac
219
220 # lets grab the first few bytes of the file to figure out what kind of archive it is
221 local filetype tmpfile="${T}/${FUNCNAME}"
222 eval ${exe} 2>/dev/null | head -c 512 > "${tmpfile}"
223 filetype=$(file -b "${tmpfile}") || die
224 case ${filetype} in
225 *tar\ archive*)
226 eval ${exe} | tar --no-same-owner -xf -
227 ;;
228 bzip2*)
229 eval ${exe} | bzip2 -dc | tar --no-same-owner -xf -
230 ;;
231 gzip*)
232 eval ${exe} | tar --no-same-owner -xzf -
233 ;;
234 compress*)
235 eval ${exe} | gunzip | tar --no-same-owner -xf -
236 ;;
237 XZ*)
238 eval ${exe} | unxz | tar --no-same-owner -xf -
239 ;;
240 *)
241 eerror "Unknown filetype \"${filetype}\" ?"
242 false
243 ;;
244 esac
245 assert "failure unpacking (${filetype}) makeself ${src##*/} ('${ver}' +${skip})"
246 }
247
248 # @FUNCTION: unpack_deb
249 # @USAGE: <one deb to unpack>
250 # @DESCRIPTION:
251 # Unpack a Debian .deb archive in style.
252 unpack_deb() {
253 [[ $# -eq 1 ]] || die "Usage: ${FUNCNAME} <file>"
254
255 local deb=$(find_unpackable_file "$1")
256
257 unpack_banner "${deb}"
258
259 # on AIX ar doesn't work out as their ar used a different format
260 # from what GNU ar (and thus what .deb files) produce
261 if [[ -n ${EPREFIX} ]] ; then
262 {
263 read # global header
264 [[ ${REPLY} = "!<arch>" ]] || die "${deb} does not seem to be a deb archive"
265 local f timestamp uid gid mode size magic
266 while read f timestamp uid gid mode size magic ; do
267 [[ -n ${f} && -n ${size} ]] || continue # ignore empty lines
268 if [[ ${f} = "data.tar"* ]] ; then
269 head -c "${size}" > "${f}"
270 else
271 head -c "${size}" > /dev/null # trash it
272 fi
273 done
274 } < "${deb}"
275 else
276 ar x "${deb}"
277 fi
278
279 unpacker ./data.tar*
280
281 # Clean things up #458658. No one seems to actually care about
282 # these, so wait until someone requests to do something else ...
283 rm -f debian-binary {control,data}.tar*
284 }
285
286 # @FUNCTION: unpack_cpio
287 # @USAGE: <one cpio to unpack>
288 # @DESCRIPTION:
289 # Unpack a cpio archive, file "-" means stdin.
290 unpack_cpio() {
291 [[ $# -eq 1 ]] || die "Usage: ${FUNCNAME} <file>"
292
293 # needed as cpio always reads from stdin
294 local cpio_cmd=( cpio --make-directories --extract --preserve-modification-time )
295 if [[ $1 == "-" ]] ; then
296 unpack_banner "stdin"
297 "${cpio_cmd[@]}"
298 else
299 local cpio=$(find_unpackable_file "$1")
300 unpack_banner "${cpio}"
301 "${cpio_cmd[@]}" <"${cpio}"
302 fi
303 }
304
305 # @FUNCTION: unpack_zip
306 # @USAGE: <zip file>
307 # @DESCRIPTION:
308 # Unpack zip archives.
309 # This function ignores all non-fatal errors (i.e. warnings).
310 # That is useful for zip archives with extra crap attached
311 # (e.g. self-extracting archives).
312 unpack_zip() {
313 [[ $# -eq 1 ]] || die "Usage: ${FUNCNAME} <file>"
314
315 local zip=$(find_unpackable_file "$1")
316 unpack_banner "${zip}"
317 unzip -qo "${zip}"
318
319 [[ $? -le 1 ]] || die "unpacking ${zip} failed (arch=unpack_zip)"
320 }
321
322 # @FUNCTION: _unpacker
323 # @USAGE: <one archive to unpack>
324 # @INTERNAL
325 # @DESCRIPTION:
326 # Unpack the specified archive. We only operate on one archive here
327 # to keep down on the looping logic (that is handled by `unpacker`).
328 _unpacker() {
329 [[ $# -eq 1 ]] || die "Usage: ${FUNCNAME} <file>"
330
331 local a=$1
332 local m=$(echo "${a}" | tr '[:upper:]' '[:lower:]')
333 a=$(find_unpackable_file "${a}")
334
335 # first figure out the decompression method
336 case ${m} in
337 *.bz2|*.tbz|*.tbz2)
338 local bzcmd=${PORTAGE_BZIP2_COMMAND:-$(type -P pbzip2 || type -P bzip2)}
339 local bzuncmd=${PORTAGE_BUNZIP2_COMMAND:-${bzcmd} -d}
340 : ${UNPACKER_BZ2:=${bzuncmd}}
341 comp="${UNPACKER_BZ2} -c"
342 ;;
343 *.z|*.gz|*.tgz)
344 comp="gzip -dc" ;;
345 *.lzma|*.xz|*.txz)
346 comp="xz -dc" ;;
347 *) comp="" ;;
348 esac
349
350 # then figure out if there are any archiving aspects
351 arch=""
352 case ${m} in
353 *.tgz|*.tbz|*.tbz2|*.txz|*.tar.*|*.tar)
354 arch="tar --no-same-owner -xof" ;;
355 *.cpio.*|*.cpio)
356 arch="unpack_cpio" ;;
357 *.deb)
358 arch="unpack_deb" ;;
359 *.run)
360 arch="unpack_makeself" ;;
361 *.sh)
362 # Not all shell scripts are makeself
363 if head -n 30 "${a}" | grep -qs '#.*Makeself' ; then
364 arch="unpack_makeself"
365 fi
366 ;;
367 *.bin)
368 # Makeself archives can be annoyingly named
369 if head -c 100 "${a}" | grep -qs '#.*Makeself' ; then
370 arch="unpack_makeself"
371 fi
372 ;;
373 *.zip)
374 arch="unpack_zip" ;;
375 esac
376
377 # finally do the unpack
378 if [[ -z ${arch}${comp} ]] ; then
379 unpack "$1"
380 return $?
381 fi
382
383 [[ ${arch} != unpack_* ]] && unpack_banner "${a}"
384
385 if [[ -z ${arch} ]] ; then
386 # Need to decompress the file into $PWD #408801
387 local _a=${a%.*}
388 ${comp} "${a}" > "${_a##*/}"
389 elif [[ -z ${comp} ]] ; then
390 ${arch} "${a}"
391 else
392 ${comp} "${a}" | ${arch} -
393 fi
394
395 assert "unpacking ${a} failed (comp=${comp} arch=${arch})"
396 }
397
398 # @FUNCTION: unpacker
399 # @USAGE: [archives to unpack]
400 # @DESCRIPTION:
401 # This works in the same way that `unpack` does. If you don't specify
402 # any files, it will default to ${A}.
403 unpacker() {
404 local a
405 [[ $# -eq 0 ]] && set -- ${A}
406 for a ; do _unpacker "${a}" ; done
407 }
408
409 # @FUNCTION: unpacker_src_unpack
410 # @DESCRIPTION:
411 # Run `unpacker` to unpack all our stuff.
412 unpacker_src_unpack() {
413 unpacker
414 }
415
416 # @FUNCTION: unpacker_src_uri_depends
417 # @USAGE: [archives that we will unpack]
418 # @RETURN: Dependencies needed to unpack all the archives
419 # @DESCRIPTION:
420 # Walk all the specified files (defaults to $SRC_URI) and figure out the
421 # dependencies that are needed to unpack things.
422 #
423 # Note: USE flags are not yet handled.
424 unpacker_src_uri_depends() {
425 local uri deps d
426
427 [[ $# -eq 0 ]] && set -- ${SRC_URI}
428
429 for uri in "$@" ; do
430 case ${uri} in
431 *.cpio.*|*.cpio)
432 d="app-arch/cpio" ;;
433 *.rar|*.RAR)
434 d="app-arch/unrar" ;;
435 *.7z)
436 d="app-arch/p7zip" ;;
437 *.xz)
438 d="app-arch/xz-utils" ;;
439 *.zip)
440 d="app-arch/unzip" ;;
441 esac
442 deps+=" ${d}"
443 done
444
445 echo "${deps}"
446 }
447
448 EXPORT_FUNCTIONS src_unpack
449
450 fi

  ViewVC Help
Powered by ViewVC 1.1.20