From 24276ff4ffbfe9d1b93722f83fc7649f2fdf748a Mon Sep 17 00:00:00 2001 From: Gluzskiy Alexandr Date: Sun, 20 Dec 2009 13:23:06 +0200 Subject: new file: media-video/mplayer/mplayer-9999-r20.ebuild renamed: sys-fs/squashfs-tools/squashfs-tools-4.0-lzma.patch -> sys-fs/squashfs-tools/files/squashfs-tools-4.0-lzma.patch --- media-video/mplayer/mplayer-9999-r20.ebuild | 610 ++++++ .../files/squashfs-tools-4.0-lzma.patch | 2210 ++++++++++++++++++++ .../squashfs-tools/squashfs-tools-4.0-lzma.patch | 2210 -------------------- 3 files changed, 2820 insertions(+), 2210 deletions(-) create mode 100644 media-video/mplayer/mplayer-9999-r20.ebuild create mode 100644 sys-fs/squashfs-tools/files/squashfs-tools-4.0-lzma.patch delete mode 100644 sys-fs/squashfs-tools/squashfs-tools-4.0-lzma.patch diff --git a/media-video/mplayer/mplayer-9999-r20.ebuild b/media-video/mplayer/mplayer-9999-r20.ebuild new file mode 100644 index 0000000..a6a77a8 --- /dev/null +++ b/media-video/mplayer/mplayer-9999-r20.ebuild @@ -0,0 +1,610 @@ +# Copyright 1999-2008 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +EAPI="1" +inherit eutils flag-o-matic multilib subversion + +RESTRICT="strip" +IUSE="X 3dfx 3dnow 3dnowext +a52 +aac -aalib +alsa altivec amrnb amrwb -arts +ass + bidi bindist bl cddb cdio cdparanoia cpudetection -custom-cflags debug + dga dirac doc dvb directfb dts +dvd dv dvdnav eac3 enca encode esd + fbcon fpm ftp gif ggi -gtk i8x0 ipv6 ivtv jack joystick jpeg ladspa + libcaca lirc live livecd lzo matrox mga mmx mmxext +mp2 +mp3 +mpeg musepack + nas nemesi nls nut nvidia openal opengl oss +png pnm pulseaudio pvr quicktime + radio rar -real rtc samba schroedinger sdl speex sse sse2 ssse3 svga tga + +theora tivo +truetype +unicode v4l v4l2 vidix +vorbis -win32codecs +x264 + xanim xinerama +xscreensaver +xv +xvid xvmc zoran" + +VIDEO_CARDS="s3virge mga tdfx vesa" + +for x in ${VIDEO_CARDS} ; do + IUSE="${IUSE} video_cards_${x}" +done + +S="${WORKDIR}/${PN}" +SRC_URI="mirror://mplayer/releases/fonts/font-arial-iso-8859-1.tar.bz2 + mirror://mplayer/releases/fonts/font-arial-iso-8859-2.tar.bz2 + mirror://mplayer/releases/fonts/font-arial-cp1250.tar.bz2 + svga? ( mirror://mplayer/contrib/svgalib/svgalib_helper-1.9.17-mplayer.tar.bz2 ) + gtk? ( mirror://mplayer/Skin/productive-1.0.tar.bz2 )" + # Only install Skin if GUI should be build (gtk as USE flag) + +ESVN_REPO_URI="svn://svn.mplayerhq.hu/mplayer/trunk" +ESVN_PROJECT="mplayer" + +DESCRIPTION="A very versatile media player" +HOMEPAGE="http://www.mplayerhq.hu/" + +# 'encode' in USE for MEncoder. +RDEPEND="sys-libs/ncurses + !bindist? ( + x86? ( + win32codecs? ( media-libs/win32codecs ) + real? ( media-libs/win32codecs + media-video/realplayer ) + ) + amd64? ( real? ( media-libs/amd64codecs ) ) + amrnb? ( media-libs/amrnb ) + amrwb? ( media-libs/amrwb ) + ) + aalib? ( media-libs/aalib ) + alsa? ( media-libs/alsa-lib ) + arts? ( kde-base/arts ) + bidi? ( dev-libs/fribidi ) + cdio? ( dev-libs/libcdio ) + cdparanoia? ( media-sound/cdparanoia ) + dga? ( x11-libs/libXxf86dga ) + dirac? ( media-video/dirac ) + directfb? ( dev-libs/DirectFB ) + dts? ( media-libs/libdca ) + dvb? ( media-tv/linuxtv-dvb-headers ) + dvdnav? ( >=media-libs/libdvdnav-9999 + media-libs/libdvdread ) + enca? ( app-i18n/enca ) + encode? ( + aac? ( media-libs/faac ) + dv? ( media-libs/libdv ) + mp2? ( media-sound/twolame ) + mp3? ( media-sound/lame ) + x264? ( media-libs/x264 ) + ) + esd? ( media-sound/esound ) + fontconfig? ( media-libs/fontconfig ) + gif? ( media-libs/giflib ) + ggi? ( media-libs/libggi ) + gtk? ( media-libs/libpng + x11-libs/libXxf86vm + x11-libs/libXext + x11-libs/libXi + x11-libs/gtk+:2 ) + jpeg? ( media-libs/jpeg ) + ladspa? ( media-libs/ladspa-sdk ) + libcaca? ( media-libs/libcaca ) + lirc? ( app-misc/lirc ) + live? ( >=media-plugins/live-2007.02.20 ) + lzo? ( =dev-libs/lzo-1* ) + mp3? ( media-libs/libmad ) + musepack? ( media-libs/libmpcdecsv7 ) + nas? ( media-libs/nas ) + nls? ( virtual/libintl ) + openal? ( media-libs/openal ) + opengl? ( virtual/opengl ) + png? ( media-libs/libpng ) + pulseaudio? ( media-sound/pulseaudio ) + quicktime? ( media-libs/libquicktime ) + samba? ( >=net-fs/samba-2.2.8a ) + schroedinger? ( media-libs/schroedinger ) + sdl? ( media-libs/libsdl ) + speex? ( media-libs/speex ) + svga? ( media-libs/svgalib ) + theora? ( media-libs/libtheora ) + vidix? ( x11-libs/libXxf86vm + x11-libs/libXext ) + vorbis? ( media-libs/libvorbis ) + xscreensaver? ( x11-libs/libXScrnSaver ) + truetype? ( >=media-libs/freetype-2.1 + media-libs/fontconfig ) + xanim? ( media-video/xanim ) + xinerama? ( x11-libs/libXinerama + x11-libs/libXxf86vm + x11-libs/libXext ) + xvid? ( media-libs/xvid ) + xv? ( x11-libs/libXv + x11-libs/libXxf86vm + x11-libs/libXext + xvmc? ( x11-libs/libXvMC ) ) + X? ( x11-libs/libXxf86vm + x11-libs/libXext + joystick? ( x11-drivers/xf86-input-joystick ) ) +" +DEPEND="${RDEPEND} + app-arch/unzip + >=sys-apps/portage-2.1.2 + doc? ( >=app-text/docbook-sgml-dtd-4.1.2 + app-text/docbook-xml-dtd + >=app-text/docbook-xml-simple-dtd-1.50.0 ) + jack? ( >=media-libs/bio2jack-0.4 ) + nls? ( sys-devel/gettext ) + dga? ( x11-proto/xf86dgaproto ) + xinerama? ( x11-proto/xineramaproto ) + xscreensaver? ( x11-proto/scrnsaverproto ) + xv? ( x11-proto/videoproto + x11-proto/xf86vidmodeproto ) + gtk? ( x11-proto/xextproto + x11-proto/xf86vidmodeproto ) + X? ( x11-proto/xextproto + x11-proto/xf86vidmodeproto ) + unicode? ( virtual/libiconv )" + +SLOT="0" +LICENSE="GPL-2" +KEYWORDS="~alpha ~amd64 ~hppa ~ia64 ~ppc ~ppc64 ~sparc ~x86 ~x86-fbsd" + +pkg_setup() { + if use real && use x86 ; then + REALLIBDIR="/opt/RealPlayer/codecs" + elif use real && use amd64 ; then + REALLIBDIR="/usr/$(get_libdir)/codecs" + fi + + if use ass && ! use truetype ; then + echo + ewarn "You enabled the 'ass' USE flag, but text subtitle support will be" + ewarn "disabled unless you also use 'truetype'!" + echo + fi + + if use truetype && ! use unicode ; then + echo + ewarn "You enabled the 'truetype' USE flag, but support will be" + ewarn "disabled unless you also use 'unicode'!" + echo + fi + + if use gtk ; then + echo + ewarn "The gtk useflag enables mplayer's gui (gmplayer), which is" + ewarn "unmaintained upstream. You are encouraged to use a modern" + ewarn "frontend, such as gnome-mplayer, kmplayer or smplayer instead." + echo + fi + + + if [[ -n ${LINGUAS} ]]; then + echo + elog "For MPlayer's language support, the configuration will" + elog "use your LINGUAS variable from /etc/make.conf. If you have more" + elog "than one language enabled, then the first one in the list will" + elog "be used to output the messages, if a translation is available." + elog "man pages will be created for all languages where translations" + elog "are also available." + echo + fi + + if use x86 || use amd64; then + if ! use mmx && use custom-cflags; then + echo + ewarn "You have the 'mmx' use flag disabled for this package, which" + ewarn "means that no CPU optimizations will be used at all." + ewarn "The build will either break or encode very slowly. Check your" + ewarn "/proc/cpuinfo for possible CPU optimization flags that" + ewarn "apply to this ebuild (mmx, mmxext, 3dnow, 3dnowext, sse, sse2, ssse3)." + echo + fi + fi +} + +src_unpack() { + + subversion_src_unpack + + cd "${WORKDIR}" + if ! use truetype || ! use unicode ; then + unpack font-arial-iso-8859-1.tar.bz2 \ + font-arial-iso-8859-2.tar.bz2 \ + font-arial-cp1250.tar.bz2 + fi + + use svga && unpack svgalib_helper-1.9.17-mplayer.tar.bz2 + + use gtk && unpack productive-1.0.tar.bz2 + + # For Version Branding + cd "${ESVN_STORE_DIR}/${ESVN_CO_DIR}/${ESVN_PROJECT}/${ESVN_REPO_URI##*/}" + ./version.sh + mv version.h "${S}" + + cd "${S}" + +# epatch "${FILESDIR}/disable-version-rebranding.patch" + + # eac3 patches from the GSoC project + if use eac3 + then + cd "${WORKDIR}" + einfo "Fetching eac3 sources..." + svn co svn://svn.mplayerhq.hu/soc/eac3 eac3 + cd "${S}" + einfo "Applying eac3 patches..." + epatch "${WORKDIR}/eac3/ffmpeg.patch" + cp ../eac3/*.c ./libavcodec/ || die "copying eac3 files failed" + fi + + # Fix hppa compilation + [ "${ARCH}" = "hppa" ] && sed -i -e "s/-O4/-O1/" "${S}/configure" + + if use svga + then + echo + einfo "Enabling vidix non-root mode." + einfo "(You need a proper svgalib_helper.o module for your kernel" + einfo " to actually use this)" + echo + + mv "${WORKDIR}/svgalib_helper" "${S}/libdha" + fi + + # Fix polish spelling errors + [[ -n ${LINGUAS} ]] && sed -e 's:Zarządano:Zażądano:' -i help/help_mp-pl.h +} + +src_compile() { + + local myconf=" --disable-tv-bsdbt848" + + # broken upstream, won't work with recent kernels + myconf="${myconf} --disable-ivtv" + + # MPlayer reads in the LINGUAS variable from make.conf, and sets + # the languages accordingly. Some will have to be altered to match + # upstream's naming scheme. + [[ -n $LINGUAS ]] && LINGUAS=${LINGUAS/da/dk} + + ##################### + # Optional features # + ##################### + if use cpudetection || use livecd || use bindist + then + myconf="${myconf} --enable-runtime-cpudetection" + fi + + if use unicode + then + myconf="${myconf} --charset=UTF-8" + else + myconf="${myconf} --disable-iconv" + myconf="${myconf} --charset=noconv" + fi + + # libcdio support: prefer libcdio over cdparanoia + # don't check for cddb w/cdio + if use cdio; then + myconf="${myconf} --disable-cdparanoia" + else + myconf="${myconf} --disable-libcdio" + use cdparanoia || myconf="${myconf} --disable-cdparanoia" + use cddb || myconf="${myconf} --disable-cddb" + fi + + use ass || myconf="${myconf} --disable-ass" + use bidi || myconf="${myconf} --disable-fribidi" + use bl && myconf="${myconf} --enable-bl" + use enca || myconf="${myconf} --disable-enca" + use ftp || myconf="${myconf} --disable-ftp" + use nemesi || myconf="${myconf} --disable-nemesi" + use nut || myconf="${myconf} --disable-libnut" + use tivo || myconf="${myconf} --disable-vstream" + use xscreensaver || myconf="${myconf} --disable-xss" + + # DVD support + # dvdread and libdvdcss are internal libs + # http://www.mplayerhq.hu/DOCS/HTML/en/dvd.html + # You can optionally use external dvdread support, but against + # upstream's suggestion. Normally, we don't, but we're using + # external dvdread for dvdnav. + # For this overlay ebuild, we're compiling both libdvdnav + # and this mplayer against external dvdread. + if ! use dvd; then + myconf="${myconf} --disable-dvdnav --disable-dvdread" + use a52 || myconf="${myconf} --disable-liba52" + fi + if use dvd && use dvdnav; then + myconf="${myconf} --disable-dvdread-internal \ + --with-dvdread-config=/usr/bin/dvdread-config \ + --with-dvdnav-config=/usr/bin/dvdnav-config" + fi + + if use encode ; then + myconf="${myconf} --enable-mencoder" + use aac || myconf="${myconf} --disable-faac" + use dv || myconf="${myconf} --disable-libdv" + use mp2 || myconf="${myconf} --disable-twolame --disable-toolame" + use mp3 || myconf="${myconf} --disable-mp3lame --disable-mp3lame-lavc" + use x264 || myconf="${myconf} --disable-x264" + use xvid || myconf="${myconf} --disable-xvid --disable-xvid-lavc" + else + myconf="${myconf} --disable-mencoder --disable-faac --disable-libdv --disable-x264" + fi + + if use !gtk && use !X && use !xv && use !xinerama; then + myconf="${myconf} --disable-gui --disable-x11 --disable-xv \ + --disable-xmga --disable-xinerama --disable-vm --disable-xvmc" + else + #note we ain't touching --enable-vm. That should be locked down in the future. + myconf="${myconf} $(use_enable gtk gui) $(use_enable gtk xshape) \ + $(use_enable X x11) $(use_enable xinerama) $(use_enable xv)" + fi + + myconf="${myconf} $(use_enable joystick)" + use lirc || myconf="${myconf} --disable-lirc --disable-lircc" + use live || myconf="${myconf} --disable-live" + myconf="${myconf} $(use_enable radio) $(use_enable radio radio-capture)" + use ipv6 || myconf="${myconf} --disable-inet6" + use rar || myconf="${myconf} --disable-unrarexec" + use rtc || myconf="${myconf} --disable-rtc" + use samba || myconf="${myconf} --disable-smb" + myconf="${myconf} $(use_enable truetype freetype)" + use truetype || myconf="${myconf} --disable-fontconfig" + + # DVB / Video4Linux / Radio support + if { use dvb || use pvr || use v4l || use v4l2 || use radio; }; then + use dvb || myconf="${myconf} --disable-dvb --disable-dvbhead" + use v4l || myconf="${myconf} --disable-tv-v4l1" + use v4l2 || myconf="${myconf} --disable-tv-v4l2" + use teletext || myconf="${myconf}" + if use radio && { use dvb || use v4l || use v4l2; }; then + myconf="${myconf} --enable-radio $(use_enable encode radio-capture)" + else + myconf="${myconf} --disable-radio-v4l2 --disable-radio-bsdbt848" + fi + else + myconf="${myconf} --disable-tv --disable-tv-v4l1 --disable-tv-v4l2 \ + --disable-radio --disable-radio-v4l2 --disable-radio-bsdbt848 \ + --disable-dvb --disable-dvbhead \ + --disable-pvr" + fi + + ########## + # Codecs # + ########## + for x in gif jpeg ladspa live musepack pnm speex theora xanim; do + use ${x} || myconf="${myconf} --disable-${x}" + done + use aac || myconf="${myconf} --disable-faad-internal" + use aac && use fpm && myconf="${myconf} --enable-faad-fixed" + use dirac || myconf="${myconf} --disable-libdirac-lavc" + use schroedinger || myconf="${myconf} --disable-libschroedinger-lavc" + use dts || myconf="${myconf} --disable-libdca" + ! use png && ! use gtk && myconf="${myconf} --disable-png" + use lzo || myconf="${myconf} --disable-liblzo" + use mpeg || myconf="${myconf} --disable-libmpeg2" + use mp3 || myconf="${myconf} --disable-mp3lib --disable-mad" + use vorbis || myconf="${myconf} --disable-libvorbis" + use xanim && myconf="${myconf} --xanimcodecsdir=/usr/lib/xanim/mods" + if use x86 || use amd64; then + # Real codec support, only available on x86, amd64 + if use real ; then + myconf="${myconf} --enable-real --realcodecsdir=${REALLIBDIR}" + else + myconf="${myconf} --disable-real" + fi + if ! use livecd && ! use bindist ; then + myconf="${myconf} $(use_enable win32codecs win32dll)" + use amrnb || myconf="${myconf} --disable-libamr_nb" + use amrwb || myconf="${myconf} --disable-libamr_wb" + fi + fi + # bug 213836 + if ! use x86 || ! use win32codecs; then + use quicktime || myconf="${myconf} --disable-qtx" + fi + + + ################ + # Video Output # + ################ + use aalib || myconf="${myconf} --disable-aa" + use dga || myconf="${myconf} --disable-dga1 --disable-dga2" + use fbcon || myconf="${myconf} --disable-fbdev" + use fbcon && use video_cards_s3virge && myconf="${myconf} --enable-s3fb" + myconf="${myconf} $(use_enable directfb)" + myconf="${myconf} $(use_enable ggi)" + myconf="${myconf} $(use_enable libcaca caca)" + myconf="${myconf} $(use_enable matrox mga)" + myconf="${myconf} $(use_enable opengl gl)" + myconf="${myconf} $(use_enable sdl)" + use video_cards_vesa || myconf="${myconf} --disable-vesa" + use vidix || myconf="${myconf} --disable-vidix --disable-vidix-pcidb" + use zoran || myconf="${myconf} --disable-zr" + + if use xv; then + if use xvmc; then + myconf="${myconf} --enable-xvmc --with-xvmclib=XvMCW" + else + myconf="${myconf} --disable-xvmc" + fi + else + myconf="${myconf} --disable-xv --disable-xvmc" + fi + + if ! use kernel_linux && ! use video_cards_mga; then + myconf="${myconf} --disable-mga --disable-xmga" + fi + + if use video_cards_tdfx; then + myconf="${myconf} $(use_enable video_cards_tdfx tdfxvid) \ + $(use_enable fbcon tdfxfb)" + else + myconf="${myconf} --disable-3dfx --disable-tdfxvid --disable-tdfxfb" + fi + + ################ + # Audio Output # + ################ + use alsa || myconf="${myconf} --disable-alsa" + use arts || myconf="${myconf} --disable-arts" + use esd || myconf="${myconf} --disable-esd" + use jack || myconf="${myconf} --disable-jack" + use mp3 || myconf="${myconf} --disable-mad" + use nas || myconf="${myconf} --disable-nas" + use openal || myconf="${myconf} --disable-openal" + use oss || myconf="${myconf} --disable-ossaudio" + use pulseaudio || myconf="${myconf} --disable-pulse" + + #################### + # Advanced Options # + #################### + # Platform specific flags, hardcoded on amd64 (see below) + if use x86 || use amd64 || use ppc; then + if use cpudetection || use bindist; then + myconf="${myconf} --enable-runtime-cpudetection" + fi + fi + # Letting users turn off optimizations results in epic build fail + # across the board. MPlayer's build system by default will + # detect them and use them just fine, so don't let them change + # them unless they really know what they are doing anyway. + if use custom-cflags; then + if use mmx; then + for x in 3dnow 3dnowext mmxext sse sse2 ssse3; do + use ${x} || myconf="${myconf} --disable-${x}" + done + else + myconf="${myconf} --disable-mmx --disable-mmxext --disable-sse \ + --disable-sse2 --disable-ssse3 --disable-3dnow \ + --disable-3dnowext" + fi + fi + + use debug && myconf="${myconf} --enable-debug=3" + myconf="${myconf} $(use_enable altivec)" + + if use custom-cflags; then + # let's play the filtration game! MPlayer hates on all! + strip-flags + # ugly optimizations cause MPlayer to cry on x86 systems! + if use x86 ; then + replace-flags -O* -O2 + filter-flags -fPIC -fPIE + use debug || append-flags -fomit-frame-pointer + fi + append-flags -D__STDC_LIMIT_MACROS + else + unset CFLAGS CXXFLAGS + fi + + myconf="--cc=$(tc-getCC) \ + --host-cc=$(tc-getBUILD_CC) \ + --prefix=/usr \ + --confdir=/etc/mplayer \ + --datadir=/usr/share/mplayer \ + --libdir=/usr/$(get_libdir) \ + --enable-menu \ + --enable-network \ + ${myconf}" + CFLAGS="${CFLAGS}" ./configure ${myconf} || die "configure died" + + emake || die "Failed to build MPlayer!" + use doc && make -C DOCS/xml html-chunked +} + +src_install() { + make prefix=${D}/usr \ + BINDIR=${D}/usr/bin \ + LIBDIR=${D}/usr/$(get_libdir) \ + CONFDIR=${D}/usr/share/mplayer \ + DATADIR=${D}/usr/share/mplayer \ + MANDIR=${D}/usr/share/man \ + install || die "Failed to install MPlayer!" + + dodoc AUTHORS Changelog README etc/codecs.conf + # Install the documentation; DOCS is all mixed up not just html + if use doc ; then + find "${S}/DOCS" -type d | xargs -- chmod 0755 + find "${S}/DOCS" -type f | xargs -- chmod 0644 + cp -r "${S}/DOCS" "${D}/usr/share/doc/${PF}/" || die "cp docs died" + fi + + # Copy misc tools to documentation path, as they're not installed directly + # and yes, we are nuking the +x bit. + find "${S}/TOOLS" -type d | xargs -- chmod 0755 + find "${S}/TOOLS" -type f | xargs -- chmod 0644 + cp -r "${S}/TOOLS" "${D}/usr/share/doc/${PF}/" || die "cp tools died" + + # Install the default Skin and Gnome menu entry + if use gtk; then + dodir /usr/share/mplayer/skins + cp -r "${WORKDIR}/productive" "${D}"/usr/share/mplayer/skins/default || die "cp skin died" + + # Fix the symlink + rm -rf "${D}"/usr/bin/gmplayer + dosym mplayer /usr/bin/gmplayer + + insinto /usr/share/pixmaps + newins "${S}"/gui/mplayer/pixmaps/logo.xpm mplayer.xpm + insinto /usr/share/applications + doins "${FILESDIR}/mplayer.desktop" + fi + + if ! use truetype || ! use unicode; then + dodir /usr/share/mplayer/fonts + local x= + # Do this generic, as the mplayer people like to change the structure + # of their zips ... + for x in $(find ${WORKDIR}/ -type d -name 'font-arial-*') + do + cp -pPR ${x} "${D}"/usr/share/mplayer/fonts + done + # Fix the font symlink ... + rm -rf "${D}"/usr/share/mplayer/font + dosym fonts/font-arial-14-iso-8859-1 /usr/share/mplayer/font + fi + + insinto /etc/mplayer + newins "${S}"/etc/example.conf mplayer.conf + dosed -e 's/fs=yes/fs=no/' /etc/mplayer.conf + if use truetype && use unicode ; then + cat >> "${D}"/etc/mplayer/mplayer.conf << EOT +fontconfig=1 +subfont-osd-scale=4 +subfont-text-scale=3 +EOT + fi + dosym ../../../etc/mplayer/mplayer.conf /usr/share/mplayer/mplayer.conf + + # copy the midentify script to /usr/bin + cp "${D}"/usr/share/doc/${PF}/TOOLS/midentify "${D}"/usr/bin + chmod a+x "${D}"/usr/bin/midentify + + insinto /usr/share/mplayer + doins "${S}"/etc/input.conf + doins "${S}"/etc/menu.conf + + # add codec configuration for eac3 + use eac3 && cat "${FILESDIR}/eac3-id.conf" >> "${D}"/usr/share/mplayer/codecs.conf +} + +pkg_preinst() { + + if [ -d "${ROOT}/usr/share/mplayer/Skin/default" ] + then + rm -rf "${ROOT}"/usr/share/mplayer/Skin/default + fi +} + +pkg_postrm() { + + # Cleanup stale symlinks + if [ -L "${ROOT}"/usr/share/mplayer/font -a \ + ! -e "${ROOT}"/usr/share/mplayer/font ] + then + rm -f "${ROOT}"/usr/share/mplayer/font + fi + + if [ -L "${ROOT}"/usr/share/mplayer/subfont.ttf -a \ + ! -e "${ROOT}"/usr/share/mplayer/subfont.ttf ] + then + rm -f "${ROOT}"/usr/share/mplayer/subfont.ttf + fi +} diff --git a/sys-fs/squashfs-tools/files/squashfs-tools-4.0-lzma.patch b/sys-fs/squashfs-tools/files/squashfs-tools-4.0-lzma.patch new file mode 100644 index 0000000..9a7c78c --- /dev/null +++ b/sys-fs/squashfs-tools/files/squashfs-tools-4.0-lzma.patch @@ -0,0 +1,2210 @@ +diff -Naurp squashfs-tools/compressor.c squashfs-tools-lzma/compressor.c +--- squashfs-tools/compressor.c 1970-01-01 00:00:00.000000000 +0000 ++++ squashfs-tools-lzma/compressor.c 2009-10-20 04:03:37.000000000 +0000 +@@ -0,0 +1,78 @@ ++/* ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2, ++ * or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * compressor.c ++ */ ++ ++#include ++#include ++#include "compressor.h" ++#include "squashfs_fs.h" ++ ++extern int gzip_compress(void **, char *, char *, int, int, int *); ++extern int gzip_uncompress(char *, char *, int, int, int *); ++extern int lzma_compress(void **, char *, char *, int, int, int *); ++extern int lzma_uncompress(char *, char *, int, int, int *); ++ ++struct compressor compressor[] = { ++ { gzip_compress, gzip_uncompress, ZLIB_COMPRESSION, "gzip", 1 }, ++#ifdef LZMA_SUPPORT ++ { lzma_compress, lzma_uncompress, LZMA_COMPRESSION, "lzma", 1 }, ++#else ++ { NULL, NULL, LZMA_COMPRESSION, "lzma", 0 }, ++#endif ++ { NULL, NULL , 0, "unknown", 0} ++}; ++ ++ ++struct compressor *lookup_compressor(char *name) ++{ ++ int i; ++ ++ for(i = 0; compressor[i].id; i++) ++ if(strcmp(compressor[i].name, name) == 0) ++ break; ++ ++ return &compressor[i]; ++} ++ ++ ++struct compressor *lookup_compressor_id(int id) ++{ ++ int i; ++ ++ for(i = 0; compressor[i].id; i++) ++ if(id == compressor[i].id) ++ break; ++ ++ return &compressor[i]; ++} ++ ++ ++void display_compressors(char *indent, char *def_comp) ++{ ++ int i; ++ ++ for(i = 0; compressor[i].id; i++) ++ if(compressor[i].supported) ++ fprintf(stderr, "%s\t%s%s\n", indent, ++ compressor[i].name, ++ strcmp(compressor[i].name, def_comp) == 0 ? ++ " (default)" : ""); ++} +diff -Naurp squashfs-tools/compressor.h squashfs-tools-lzma/compressor.h +--- squashfs-tools/compressor.h 1970-01-01 00:00:00.000000000 +0000 ++++ squashfs-tools-lzma/compressor.h 2009-10-20 04:03:37.000000000 +0000 +@@ -0,0 +1,33 @@ ++/* ++ * ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2, ++ * or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * compressor.h ++ */ ++ ++struct compressor { ++ int (*compress)(void **, char *, char *, int, int, int *); ++ int (*uncompress)(char *, char *, int, int, int *); ++ int id; ++ char *name; ++ int supported; ++}; ++ ++extern struct compressor *lookup_compressor(char *); ++extern struct compressor *lookup_compressor_id(int); ++extern void display_compressors(char *, char *); +diff -Naurp squashfs-tools/gzip_wrapper.c squashfs-tools-lzma/gzip_wrapper.c +--- squashfs-tools/gzip_wrapper.c 1970-01-01 00:00:00.000000000 +0000 ++++ squashfs-tools-lzma/gzip_wrapper.c 2009-10-20 04:03:37.000000000 +0000 +@@ -0,0 +1,80 @@ ++/* ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2, ++ * or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * gzip_wrapper.c ++ */ ++ ++#include ++#include ++ ++int gzip_compress(void **strm, char *d, char *s, int size, int block_size, ++ int *error) ++{ ++ int res = 0; ++ z_stream *stream = *strm; ++ ++ if(stream == NULL) { ++ if((stream = *strm = malloc(sizeof(z_stream))) == NULL) ++ goto failed; ++ ++ stream->zalloc = Z_NULL; ++ stream->zfree = Z_NULL; ++ stream->opaque = 0; ++ ++ if((res = deflateInit(stream, 9)) != Z_OK) ++ goto failed; ++ } else if((res = deflateReset(stream)) != Z_OK) ++ goto failed; ++ ++ stream->next_in = (unsigned char *) s; ++ stream->avail_in = size; ++ stream->next_out = (unsigned char *) d; ++ stream->avail_out = block_size; ++ ++ res = deflate(stream, Z_FINISH); ++ if(res == Z_STREAM_END) ++ /* ++ * Success, return the compressed size. ++ */ ++ return (int) stream->total_out; ++ if(res == Z_OK) ++ /* ++ * Output buffer overflow. Return out of buffer space ++ */ ++ return 0; ++failed: ++ /* ++ * All other errors return failure, with the compressor ++ * specific error code in *error ++ */ ++ *error = res; ++ return -1; ++} ++ ++ ++int gzip_uncompress(char *d, char *s, int size, int block_size, int *error) ++{ ++ int res; ++ unsigned long bytes = block_size; ++ ++ res = uncompress((unsigned char *) d, &bytes, ++ (const unsigned char *) s, size); ++ ++ *error = res; ++ return res == Z_OK ? (int) bytes : -1; ++} +diff -Naurp squashfs-tools/lzma_wrapper.c squashfs-tools-lzma/lzma_wrapper.c +--- squashfs-tools/lzma_wrapper.c 1970-01-01 00:00:00.000000000 +0000 ++++ squashfs-tools-lzma/lzma_wrapper.c 2009-10-14 03:32:57.000000000 +0000 +@@ -0,0 +1,93 @@ ++/* ++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ++ * Phillip Lougher ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2, ++ * or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * lzma_wrapper.c ++ */ ++ ++#include ++ ++#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) ++ ++int lzma_compress(void **strm, char *dest, char *src, int size,int block_size, ++ int *error) ++{ ++ unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src; ++ size_t props_size = LZMA_PROPS_SIZE, ++ outlen = block_size - LZMA_HEADER_SIZE; ++ int res; ++ ++ res = LzmaCompress(d + LZMA_HEADER_SIZE, &outlen, s, size, d, ++ &props_size, 5, block_size, 3, 0, 2, 32, 1); ++ ++ if(res == SZ_ERROR_OUTPUT_EOF) { ++ /* ++ * Output buffer overflow. Return out of buffer space error ++ */ ++ return 0; ++ } ++ ++ if(res != SZ_OK) { ++ /* ++ * All other errors return failure, with the compressor ++ * specific error code in *error ++ */ ++ *error = res; ++ return -1; ++ } ++ ++ /* ++ * Fill in the 8 byte little endian uncompressed size field in the ++ * LZMA header. 8 bytes is excessively large for squashfs but ++ * this is the standard LZMA header and which is expected by the kernel ++ * code ++ */ ++ d[LZMA_PROPS_SIZE] = size & 255; ++ d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255; ++ d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255; ++ d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255; ++ d[LZMA_PROPS_SIZE + 4] = 0; ++ d[LZMA_PROPS_SIZE + 5] = 0; ++ d[LZMA_PROPS_SIZE + 6] = 0; ++ d[LZMA_PROPS_SIZE + 7] = 0; ++ ++ /* ++ * Success, return the compressed size. Outlen returned by the LZMA ++ * compressor does not include the LZMA header space ++ */ ++ return outlen + LZMA_HEADER_SIZE; ++} ++ ++ ++int lzma_uncompress(char *dest, char *src, int size, int block_size, ++ int *error) ++{ ++ unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src; ++ size_t outlen, inlen = size - LZMA_HEADER_SIZE; ++ int res; ++ ++ outlen = s[LZMA_PROPS_SIZE] | ++ (s[LZMA_PROPS_SIZE + 1] << 8) | ++ (s[LZMA_PROPS_SIZE + 2] << 16) | ++ (s[LZMA_PROPS_SIZE + 3] << 24); ++ ++ res = LzmaUncompress(d, &outlen, s + LZMA_HEADER_SIZE, &inlen, ++ s, LZMA_PROPS_SIZE); ++ ++ *error = res; ++ return res == SZ_OK ? outlen : -1; ++} +diff -Naurp squashfs-tools/Makefile squashfs-tools-lzma/Makefile +--- squashfs-tools/Makefile 2009-04-05 02:03:36.000000000 +0000 ++++ squashfs-tools-lzma/Makefile 2009-10-22 04:17:12.000000000 +0000 +@@ -1,40 +1,76 @@ ++# ++# Building LZMA support ++# Download LZMA sdk (4.65 used in development, other versions may work), ++# set LZMA_DIR to unpacked source, and uncomment next line ++LZMA_SUPPORT = 1 ++LZMA_DIR = ../../ ++ ++#Compression default. ++COMP_DEFAULT = gzip ++ ++INCLUDEDIR = -I. + INSTALL_DIR = /usr/local/bin + +-INCLUDEDIR = . ++MKSQUASHFS_OBJS = mksquashfs.o read_fs.o sort.o swap.o pseudo.o compressor.o \ ++ gzip_wrapper.o ++ ++UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \ ++ unsquash-4.o swap.o compressor.o gzip_wrapper.o + +-CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 ++CFLAGS := $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ ++ -D_GNU_SOURCE -DCOMP_DEFAULT=\"$(COMP_DEFAULT)\" -O2 -Wall + ++ifdef LZMA_SUPPORT ++LZMA_OBJS = $(LZMA_DIR)/C/Alloc.o $(LZMA_DIR)/C/LzFind.o \ ++ $(LZMA_DIR)/C/LzmaDec.o $(LZMA_DIR)/C/LzmaEnc.o $(LZMA_DIR)/C/LzmaLib.o ++INCLUDEDIR += -I$(LZMA_DIR)/C ++CFLAGS += -DLZMA_SUPPORT -I../../C ++MKSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) ++UNSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) ++endif ++ ++.PHONY: all + all: mksquashfs unsquashfs + +-mksquashfs: mksquashfs.o read_fs.o sort.o swap.o pseudo.o +- $(CC) mksquashfs.o read_fs.o sort.o swap.o pseudo.o -lz -lpthread -lm -o $@ ++mksquashfs: $(MKSQUASHFS_OBJS) ++ $(CC) $(MKSQUASHFS_OBJS) -lz -lpthread -lm -o $@ ++ ++mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ ++ squashfs_swap.h + +-mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h squashfs_swap.h Makefile ++read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h + +-read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h Makefile ++sort.o: sort.c squashfs_fs.h global.h sort.h + +-sort.o: sort.c squashfs_fs.h global.h sort.h Makefile ++swap.o: swap.c + +-swap.o: swap.c Makefile ++pseudo.o: pseudo.c pseudo.h + +-pseudo.o: pseudo.c pseudo.h Makefile ++compressor.o: compressor.c compressor.h + +-unsquashfs: unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o +- $(CC) unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o -lz -lpthread -lm -o $@ ++unsquashfs: $(UNSQUASHFS_OBJS) ++ $(CC) $(UNSQUASHFS_OBJS) -lz -lpthread -lm -o $@ + +-unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h squashfs_compat.h global.h Makefile ++unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h \ ++ squashfs_compat.h global.h + +-unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h global.h Makefile ++unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h \ ++ global.h + +-unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h squashfs_compat.h global.h Makefile ++unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h \ ++ squashfs_compat.h global.h + +-unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h global.h Makefile ++unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h \ ++ global.h + +-unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h global.h Makefile ++unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h \ ++ global.h + ++.PHONY: clean + clean: + -rm -f *.o mksquashfs unsquashfs + ++.PHONY: install + install: mksquashfs unsquashfs + mkdir -p $(INSTALL_DIR) + cp mksquashfs $(INSTALL_DIR) +diff -Naurp squashfs-tools/mksquashfs.c squashfs-tools-lzma/mksquashfs.c +--- squashfs-tools/mksquashfs.c 2009-04-05 21:22:48.000000000 +0000 ++++ squashfs-tools-lzma/mksquashfs.c 2009-10-20 04:03:38.000000000 +0000 +@@ -36,7 +36,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -47,6 +46,7 @@ + #include + #include + #include ++#include + + #ifndef linux + #define __BYTE_ORDER BYTE_ORDER +@@ -64,6 +64,7 @@ + #include "global.h" + #include "sort.h" + #include "pseudo.h" ++#include "compressor.h" + + #ifdef SQUASHFS_TRACE + #define TRACE(s, args...) do { \ +@@ -245,10 +246,8 @@ char **source_path; + /* list of root directory entries read from original filesystem */ + int old_root_entries = 0; + struct old_root_entry_info { +- char name[SQUASHFS_NAME_LEN + 1]; +- squashfs_inode inode; +- int type; +- int inode_number; ++ char *name; ++ struct inode_info inode; + }; + struct old_root_entry_info *old_root_entry; + +@@ -371,10 +370,15 @@ int writer_buffer_size; + int reader_buffer_size; + int fragment_buffer_size; + ++/* compression operations structure */ ++static struct compressor *comp; ++char *comp_name = COMP_DEFAULT; ++ + char *read_from_disk(long long start, unsigned int avail_bytes); + void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, + int type); +-extern int read_super(int fd, squashfs_super_block *sBlk, char *source); ++extern struct compressor *read_super(int fd, squashfs_super_block *sBlk, ++ char *source); + extern long long read_filesystem(char *root_name, int fd, + squashfs_super_block *sBlk, char **cinode_table, char **data_cache, + char **cdirectory_table, char **directory_data_cache, +@@ -831,83 +835,32 @@ void sigalrm_handler() + } + + +-unsigned int mangle2(z_stream **strm, char *d, char *s, int size, ++int mangle2(void **strm, char *d, char *s, int size, + int block_size, int uncompressed, int data_block) + { +- unsigned long c_byte; +- unsigned int res; +- z_stream *stream = *strm; +- +- if(uncompressed) +- goto notcompressed; +- +- if(stream == NULL) { +- if((stream = *strm = malloc(sizeof(z_stream))) == NULL) +- BAD_ERROR("mangle::compress failed, not enough " +- "memory\n"); +- +- stream->zalloc = Z_NULL; +- stream->zfree = Z_NULL; +- stream->opaque = 0; +- +- if((res = deflateInit(stream, 9)) != Z_OK) { +- if(res == Z_MEM_ERROR) +- BAD_ERROR("zlib::compress failed, not enough " +- "memory\n"); +- else if(res == Z_STREAM_ERROR) +- BAD_ERROR("zlib::compress failed, not a valid " +- "compression level\n"); +- else if(res == Z_VERSION_ERROR) +- BAD_ERROR("zlib::compress failed, incorrect " +- "zlib version\n"); +- else +- BAD_ERROR("zlib::compress failed, unknown " +- "error %d\n", res); +- } +- } else if((res = deflateReset(stream)) != Z_OK) { +- if(res == Z_STREAM_ERROR) +- BAD_ERROR("zlib::compress failed, stream state " +- "inconsistent\n"); +- else +- BAD_ERROR("zlib::compress failed, unknown error %d\n", +- res); +- } ++ int error, c_byte = 0; + +- stream->next_in = (unsigned char *) s; +- stream->avail_in = size; +- stream->next_out = (unsigned char *) d; +- stream->avail_out = block_size; +- +- res = deflate(stream, Z_FINISH); +- if(res != Z_STREAM_END && res != Z_OK) { +- if(res == Z_STREAM_ERROR) +- BAD_ERROR("zlib::compress failed, stream state " +- "inconsistent\n"); +- else if(res == Z_BUF_ERROR) +- BAD_ERROR("zlib::compress failed, no progress possible" +- "\n"); +- else +- BAD_ERROR("zlib::compress failed, unknown error %d\n", +- res); ++ if(!uncompressed) { ++ c_byte = comp->compress(strm, d, s, size, block_size, &error); ++ if(c_byte == -1) ++ BAD_ERROR("mangle2:: %s compress failed with error " ++ "code %d\n", comp->name, error); + } + +- c_byte = stream->total_out; +- +- if(res != Z_STREAM_END || c_byte >= size) { +-notcompressed: ++ if(c_byte == 0 || c_byte >= size) { + memcpy(d, s, size); + return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : + SQUASHFS_COMPRESSED_BIT); + } + +- return (unsigned int) c_byte; ++ return c_byte; + } + + +-unsigned int mangle(char *d, char *s, int size, int block_size, ++int mangle(char *d, char *s, int size, int block_size, + int uncompressed, int data_block) + { +- static z_stream *stream = NULL; ++ static void *stream = NULL; + + return mangle2(&stream, d, s, size, block_size, uncompressed, + data_block); +@@ -1660,8 +1613,7 @@ struct file_buffer *get_fragment(struct + pthread_mutex_unlock(&fragment_mutex); + + if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { +- int res; +- unsigned long bytes = block_size; ++ int error, res; + char *data; + + if(compressed_buffer) +@@ -1669,19 +1621,11 @@ struct file_buffer *get_fragment(struct + else + data = read_from_disk(start_block, size); + +- res = uncompress((unsigned char *) buffer->data, &bytes, +- (const unsigned char *) data, size); +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) +- BAD_ERROR("zlib::uncompress failed, not enough " +- "memory\n"); +- else if(res == Z_BUF_ERROR) +- BAD_ERROR("zlib::uncompress failed, not enough " +- "room in output buffer\n"); +- else +- BAD_ERROR("zlib::uncompress failed," +- " unknown error %d\n", res); +- } ++ res = comp->uncompress(buffer->data, data, size, block_size, ++ &error); ++ if(res == -1) ++ BAD_ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); + } else if(compressed_buffer) + memcpy(buffer->data, compressed_buffer->data, size); + else +@@ -1733,9 +1677,7 @@ void unlock_fragments() + entry->buffer->block = bytes; + bytes += compressed_size; + fragments_outstanding --; +- pthread_mutex_unlock(&fragment_mutex); + queue_put(to_writer, entry->buffer); +- pthread_mutex_lock(&fragment_mutex); + TRACE("fragment_locked writing fragment %d, compressed size %d" + "\n", entry->fragment, compressed_size); + free(entry); +@@ -1758,6 +1700,8 @@ int add_pending_fragment(struct file_buf + pthread_mutex_lock(&fragment_mutex); + insert_fragment_list(&frag_locked_list, entry); + pthread_mutex_unlock(&fragment_mutex); ++ ++ return TRUE; + } + + +@@ -1824,7 +1768,9 @@ long long generic_write_table(int length + unsigned short c_byte; + char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; + ++#ifdef SQUASHFS_TRACE + long long obytes = bytes; ++#endif + + for(i = 0; i < meta_blocks; i++) { + int avail_bytes = length > SQUASHFS_METADATA_SIZE ? +@@ -2170,11 +2116,85 @@ struct file_info *duplicate(long long fi + } + + ++static int seq = 0; ++void reader_read_process(struct dir_ent *dir_ent) ++{ ++ struct file_buffer *prev_buffer = NULL, *file_buffer; ++ int status, res, byte, count = 0; ++ int file = get_pseudo_file(dir_ent->inode->pseudo_id)->fd; ++ int child = get_pseudo_file(dir_ent->inode->pseudo_id)->child; ++ long long bytes = 0; ++ ++ while(1) { ++ file_buffer = cache_get(reader_buffer, 0, 0); ++ file_buffer->sequence = seq ++; ++ ++ byte = read_bytes(file, file_buffer->data, block_size); ++ if(byte == -1) ++ goto read_err; ++ ++ file_buffer->size = byte; ++ file_buffer->file_size = -1; ++ file_buffer->block = count ++; ++ file_buffer->error = FALSE; ++ file_buffer->fragment = FALSE; ++ bytes += byte; ++ ++ if(byte == 0) ++ break; ++ ++ /* ++ * Update estimated_uncompressed block count. This is done ++ * on every block rather than waiting for all blocks to be ++ * read incase write_file_process() is running in parallel ++ * with this. Otherwise cur uncompressed block count may ++ * get ahead of the total uncompressed block count. ++ */ ++ estimated_uncompressed ++; ++ ++ if(prev_buffer) ++ queue_put(from_reader, prev_buffer); ++ prev_buffer = file_buffer; ++ } ++ ++ /* ++ * Update inode file size now that the size of the dynamic pseudo file ++ * is known. This is needed for the -info option. ++ */ ++ dir_ent->inode->buf.st_size = bytes; ++ ++ res = waitpid(child, &status, 0); ++ if(res == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) ++ goto read_err; ++ ++ if(prev_buffer == NULL) ++ prev_buffer = file_buffer; ++ else { ++ cache_block_put(file_buffer); ++ seq --; ++ } ++ prev_buffer->file_size = bytes; ++ prev_buffer->fragment = !no_fragments && ++ (count == 2 || always_use_fragments) && (byte < block_size); ++ queue_put(from_reader, prev_buffer); ++ ++ return; ++ ++read_err: ++ if(prev_buffer) { ++ cache_block_put(file_buffer); ++ seq --; ++ file_buffer = prev_buffer; ++ } ++ file_buffer->error = TRUE; ++ queue_put(from_deflate, file_buffer); ++} ++ ++ + void reader_read_file(struct dir_ent *dir_ent) + { + struct stat *buf = &dir_ent->inode->buf, buf2; + struct file_buffer *file_buffer; +- static int index = 0; + int blocks, byte, count, expected, file, frag_block; + long long bytes, read_size; + +@@ -2202,7 +2222,7 @@ again: + if(file_buffer) + queue_put(from_reader, file_buffer); + file_buffer = cache_get(reader_buffer, 0, 0); +- file_buffer->sequence = index ++; ++ file_buffer->sequence = seq ++; + + byte = file_buffer->size = read_bytes(file, file_buffer->data, + block_size); +@@ -2238,7 +2258,7 @@ again: + + read_err: + file_buffer = cache_get(reader_buffer, 0, 0); +- file_buffer->sequence = index ++; ++ file_buffer->sequence = seq ++; + read_err2: + file_buffer->error = TRUE; + queue_put(from_deflate, file_buffer); +@@ -2262,9 +2282,14 @@ void reader_scan(struct dir_info *dir) { + for(i = 0; i < dir->count; i++) { + struct dir_ent *dir_ent = dir->list[i]; + struct stat *buf = &dir_ent->inode->buf; +- if(dir_ent->data) ++ if(dir_ent->inode->root_entry) + continue; + ++ if(dir_ent->inode->pseudo_file) { ++ reader_read_process(dir_ent); ++ continue; ++ } ++ + switch(buf->st_mode & S_IFMT) { + case S_IFREG: + reader_read_file(dir_ent); +@@ -2365,7 +2390,7 @@ int all_zero(struct file_buffer *file_bu + + void *deflator(void *arg) + { +- z_stream *stream = NULL; ++ void *stream = NULL; + int oldstate; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); +@@ -2402,7 +2427,7 @@ void *deflator(void *arg) + + void *frag_deflator(void *arg) + { +- z_stream *stream = NULL; ++ void *stream = NULL; + int oldstate; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); +@@ -2426,8 +2451,8 @@ void *frag_deflator(void *arg) + write_buffer->block = bytes; + bytes += compressed_size; + fragments_outstanding --; +- pthread_mutex_unlock(&fragment_mutex); + queue_put(to_writer, write_buffer); ++ pthread_mutex_unlock(&fragment_mutex); + TRACE("Writing fragment %lld, uncompressed size %d, " + "compressed size %d\n", file_buffer->block, + file_buffer->size, compressed_size); +@@ -2674,6 +2699,98 @@ void write_file_frag(squashfs_inode *ino + } + + ++int write_file_process(squashfs_inode *inode, struct dir_ent *dir_ent, ++ struct file_buffer *read_buffer, int *duplicate_file) ++{ ++ long long read_size, file_bytes, start; ++ struct fragment *fragment; ++ unsigned int *block_list = NULL; ++ int block = 0, status; ++ long long sparse = 0; ++ struct file_buffer *fragment_buffer = NULL; ++ ++ *duplicate_file = FALSE; ++ ++ lock_fragments(); ++ ++ file_bytes = 0; ++ start = bytes; ++ while (1) { ++ read_size = read_buffer->file_size; ++ if(read_buffer->fragment && read_buffer->c_byte) ++ fragment_buffer = read_buffer; ++ else { ++ block_list = realloc(block_list, (block + 1) * ++ sizeof(unsigned int)); ++ if(block_list == NULL) ++ BAD_ERROR("Out of memory allocating block_list" ++ "\n"); ++ block_list[block ++] = read_buffer->c_byte; ++ if(read_buffer->c_byte) { ++ read_buffer->block = bytes; ++ bytes += read_buffer->size; ++ cache_rehash(read_buffer, read_buffer->block); ++ file_bytes += read_buffer->size; ++ queue_put(to_writer, read_buffer); ++ } else { ++ sparse += read_buffer->size; ++ cache_block_put(read_buffer); ++ } ++ } ++ inc_progress_bar(); ++ ++ if(read_size != -1) ++ break; ++ ++ read_buffer = get_file_buffer(from_deflate); ++ if(read_buffer->error) ++ goto read_err; ++ } ++ ++ unlock_fragments(); ++ fragment = get_and_fill_fragment(fragment_buffer); ++ cache_block_put(fragment_buffer); ++ ++ if(duplicate_checking) ++ add_non_dup(read_size, file_bytes, block_list, start, fragment, ++ 0, 0, FALSE); ++ file_count ++; ++ total_bytes += read_size; ++ ++ if(read_size < (1LL << 32) && start < (1LL << 32) && sparse == 0) ++ create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, ++ start, block, block_list, fragment, NULL, 0); ++ else ++ create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, ++ start, block, block_list, fragment, NULL, sparse); ++ ++ if(duplicate_checking == FALSE) ++ free(block_list); ++ ++ return 0; ++ ++read_err: ++ cur_uncompressed -= block; ++ status = read_buffer->error; ++ bytes = start; ++ if(!block_device) { ++ int res; ++ ++ queue_put(to_writer, NULL); ++ if(queue_get(from_writer) != 0) ++ EXIT_MKSQUASHFS(); ++ res = ftruncate(fd, bytes); ++ if(res != 0) ++ BAD_ERROR("Failed to truncate dest file because %s\n", ++ strerror(errno)); ++ } ++ unlock_fragments(); ++ free(block_list); ++ cache_block_put(read_buffer); ++ return status; ++} ++ ++ + int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, + long long read_size, struct file_buffer *read_buffer, + int *duplicate_file) +@@ -2941,7 +3058,10 @@ again: + + read_size = read_buffer->file_size; + +- if(read_size == 0) { ++ if(read_size == -1) ++ status = write_file_process(inode, dir_ent, read_buffer, ++ duplicate_file); ++ else if(read_size == 0) { + write_file_empty(inode, dir_ent, duplicate_file); + cache_block_put(read_buffer); + } else if(read_buffer->fragment && read_buffer->c_byte) +@@ -3036,6 +3156,8 @@ struct inode_info *lookup_inode(struct s + + memcpy(&inode->buf, buf, sizeof(struct stat)); + inode->read = FALSE; ++ inode->root_entry = FALSE; ++ inode->pseudo_file = FALSE; + inode->inode = SQUASHFS_INVALID_BLK; + inode->nlink = 1; + +@@ -3056,7 +3178,7 @@ struct inode_info *lookup_inode(struct s + + + inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, +- struct inode_info *inode_info, void *data, struct dir_info *dir) ++ struct inode_info *inode_info, struct dir_info *dir) + { + if((dir->count % DIR_ENTRIES) == 0) { + dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * +@@ -3075,8 +3197,7 @@ inline void add_dir_entry(char *name, ch + NULL; + dir->list[dir->count]->inode = inode_info; + dir->list[dir->count]->dir = sub_dir; +- dir->list[dir->count]->our_dir = dir; +- dir->list[dir->count++]->data = data; ++ dir->list[dir->count++]->our_dir = dir; + dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); + } + +@@ -3128,10 +3249,10 @@ int scan1_encomp_readdir(char *pathname, + + if(dir->count < old_root_entries) + for(i = 0; i < old_root_entries; i++) { +- if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) ++ if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) + dir->directory_count ++; +- add_dir_entry(old_root_entry[i].name, "", NULL, NULL, +- &old_root_entry[i], dir); ++ add_dir_entry(old_root_entry[i].name, "", NULL, ++ &old_root_entry[i].inode, dir); + } + + while(index < source) { +@@ -3167,10 +3288,10 @@ int scan1_single_readdir(char *pathname, + + if(dir->count < old_root_entries) + for(i = 0; i < old_root_entries; i++) { +- if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) ++ if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) + dir->directory_count ++; +- add_dir_entry(old_root_entry[i].name, "", NULL, NULL, +- &old_root_entry[i], dir); ++ add_dir_entry(old_root_entry[i].name, "", NULL, ++ &old_root_entry[i].inode, dir); + } + + if((d_name = readdir(dir->linuxdir)) != NULL) { +@@ -3215,7 +3336,7 @@ struct dir_ent *scan2_readdir(struct dir + int current_count; + + while((current_count = dir_info->current_count++) < dir_info->count) +- if(dir_info->list[current_count]->data) ++ if(dir_info->list[current_count]->inode->root_entry) + continue; + else + return dir_info->list[current_count]; +@@ -3240,11 +3361,11 @@ struct dir_ent *scan3_readdir(struct dir + int current_count; + + while((current_count = dir_info->current_count++) < dir_info->count) +- if(dir_info->list[current_count]->data) +- add_dir(dir_info->list[current_count]->data->inode, +- dir_info->list[current_count]->data->inode_number, ++ if(dir_info->list[current_count]->inode->root_entry) ++ add_dir(dir_info->list[current_count]->inode->inode, ++ dir_info->list[current_count]->inode->inode_number, + dir_info->list[current_count]->name, +- dir_info->list[current_count]->data->type, dir); ++ dir_info->list[current_count]->inode->type, dir); + else + return dir_info->list[current_count]; + return NULL; +@@ -3313,7 +3434,6 @@ void dir_scan(squashfs_inode *inode, cha + dir_ent->name = dir_ent->pathname = strdup(pathname); + dir_ent->dir = dir_info; + dir_ent->our_dir = NULL; +- dir_ent->data = NULL; + dir_info->dir_ent = dir_ent; + + if(sorted) +@@ -3383,7 +3503,7 @@ struct dir_info *dir_scan1(char *pathnam + sub_dir = NULL; + + add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), +- NULL, dir); ++ dir); + } + + scan1_freedir(dir); +@@ -3399,7 +3519,7 @@ struct dir_info *dir_scan2(struct dir_in + struct dir_ent *dir_ent; + struct pseudo_entry *pseudo_ent; + struct stat buf; +- static pseudo_ino = 1; ++ static int pseudo_ino = 1; + + if(dir == NULL && (dir = scan1_opendir("")) == NULL) + return NULL; +@@ -3415,6 +3535,29 @@ struct dir_info *dir_scan2(struct dir_in + + while((pseudo_ent = pseudo_readdir(pseudo)) != NULL) { + dir_ent = scan2_lookup(dir, pseudo_ent->name); ++ if(pseudo_ent->dev->type == 's') { ++ struct stat *buf; ++ if(dir_ent == NULL) { ++ ERROR("Pseudo set file \"%s\" does not exist " ++ "in source filesystem. Ignoring\n", ++ pseudo_ent->pathname); ++ continue; ++ } ++ if(dir_ent->inode->root_entry) { ++ ERROR("Pseudo set file \"%s\" is a pre-existing" ++ " file in the filesystem being appended" ++ " to. It cannot be modified. " ++ "Ignoring!\n", pseudo_ent->pathname); ++ continue; ++ } ++ buf = &dir_ent->inode->buf; ++ buf->st_mode = (buf->st_mode & S_IFMT) | ++ pseudo_ent->dev->mode; ++ buf->st_uid = pseudo_ent->dev->uid; ++ buf->st_gid = pseudo_ent->dev->gid; ++ continue; ++ } ++ + if(dir_ent) { + ERROR("Pseudo file \"%s\" exists in source filesystem " + "\"%s\"\n", pseudo_ent->pathname, +@@ -3444,8 +3587,29 @@ struct dir_info *dir_scan2(struct dir_in + buf.st_mtime = time(NULL); + buf.st_ino = pseudo_ino ++; + +- add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir, +- lookup_inode(&buf), NULL, dir); ++ if(pseudo_ent->dev->type == 'f') { ++#ifdef USE_TMP_FILE ++ struct stat buf2; ++ int res = stat(pseudo_ent->dev->filename, &buf2); ++ if(res == -1) { ++ ERROR("Stat on pseudo file \"%s\" failed, " ++ "skipping...", pseudo_ent->pathname); ++ continue; ++ } ++ buf.st_size = buf2.st_size; ++ add_dir_entry(pseudo_ent->name, ++ pseudo_ent->dev->filename, sub_dir, ++ lookup_inode(&buf), dir); ++#else ++ struct inode_info *inode = lookup_inode(&buf); ++ inode->pseudo_id = pseudo_ent->dev->pseudo_id; ++ inode->pseudo_file = TRUE; ++ add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, ++ sub_dir, inode, dir); ++#endif ++ } else ++ add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, ++ sub_dir, lookup_inode(&buf), dir); + } + + scan2_freedir(dir); +@@ -3482,8 +3646,9 @@ void dir_scan3(squashfs_inode *inode, st + &duplicate_file); + INFO("file %s, uncompressed size %lld " + "bytes %s\n", filename, +- buf->st_size, duplicate_file ? +- "DUPLICATE" : ""); ++ (long long) buf->st_size, ++ duplicate_file ? "DUPLICATE" : ++ ""); + break; + + case S_IFDIR: +@@ -3557,6 +3722,7 @@ void dir_scan3(squashfs_inode *inode, st + INFO("file %s, uncompressed " + "size %lld bytes LINK" + "\n", filename, ++ (long long) + buf->st_size); + break; + case SQUASHFS_SYMLINK_TYPE: +@@ -3667,10 +3833,11 @@ void add_old_root_entry(char *name, squa + BAD_ERROR("Out of memory in old root directory entries " + "reallocation\n"); + +- strcpy(old_root_entry[old_root_entries].name, name); +- old_root_entry[old_root_entries].inode = inode; +- old_root_entry[old_root_entries].inode_number = inode_number; +- old_root_entry[old_root_entries++].type = type; ++ old_root_entry[old_root_entries].name = strdup(name); ++ old_root_entry[old_root_entries].inode.inode = inode; ++ old_root_entry[old_root_entries].inode.inode_number = inode_number; ++ old_root_entry[old_root_entries].inode.type = type; ++ old_root_entry[old_root_entries++].inode.root_entry = TRUE; + } + + +@@ -4172,26 +4339,28 @@ int main(int argc, char *argv[]) + source_path = argv + 1; + source = i - 2; + for(; i < argc; i++) { +- if(strcmp(argv[i], "-pf") == 0) { ++ if(strcmp(argv[i], "-comp") == 0) { + if(++i == argc) { +- ERROR("%s: -pf missing filename\n", argv[0]); ++ ERROR("%s: -comp missing compression type\n", ++ argv[0]); + exit(1); + } +- if(read_pseudo_file(&pseudo, argv[i]) == FALSE) { +- ERROR("Failed to parse pseudo file \"%s\"\n", +- argv[i]); ++ comp_name = argv[i]; ++ } else if(strcmp(argv[i], "-pf") == 0) { ++ if(++i == argc) { ++ ERROR("%s: -pf missing filename\n", argv[0]); + exit(1); + } ++ if(read_pseudo_file(&pseudo, argv[i]) == FALSE) ++ exit(1); + } else if(strcmp(argv[i], "-p") == 0) { + if(++i == argc) { + ERROR("%s: -p missing pseudo file definition\n", + argv[0]); + exit(1); + } +- if(read_pseudo_def(&pseudo, argv[i]) == FALSE) { +- ERROR("Failed to parse pseudo definition\n"); ++ if(read_pseudo_def(&pseudo, argv[i]) == FALSE) + exit(1); +- } + } else if(strcmp(argv[i], "-recover") == 0) { + if(++i == argc) { + ERROR("%s: -recover missing recovery file\n", +@@ -4394,34 +4563,16 @@ int main(int argc, char *argv[]) + printOptions: + ERROR("SYNTAX:%s source1 source2 ... dest [options] " + "[-e list of exclude\ndirs/files]\n", argv[0]); +- ERROR("\nOptions are\n"); +- ERROR("-version\t\tprint version, licence and " +- "copyright message\n"); +- ERROR("-recover \t\trecover filesystem data " +- "using recovery file \n"); +- ERROR("-no-recovery\t\tdon't generate a recovery " +- "file\n"); +- ERROR("-info\t\t\tprint files written to filesystem\n"); +- ERROR("-no-exports\t\tdon't make the filesystem " +- "exportable via NFS\n"); +- ERROR("-no-progress\t\tdon't display the progress " +- "bar\n"); +- ERROR("-no-sparse\t\tdon't detect sparse files\n"); ++ ERROR("\nFilesystem build options:\n"); ++ ERROR("-comp \t\tselect compression\n"); ++ ERROR("\t\t\tCompressors available:\n"); ++ display_compressors("\t\t\t", COMP_DEFAULT); + ERROR("-b \t\tset data block to " + ". Default %d bytes\n", + SQUASHFS_FILE_SIZE); +- ERROR("-processors \tUse processors." +- " By default will use number of\n"); +- ERROR("\t\t\tprocessors available\n"); +- ERROR("-read-queue \tSet input queue to " +- "Mbytes. Default %d Mbytes\n", +- READER_BUFFER_DEFAULT); +- ERROR("-write-queue \tSet output queue to " +- "Mbytes. Default %d Mbytes\n", +- WRITER_BUFFER_DEFAULT); +- ERROR("-fragment-queue \tSet fagment queue to " +- " Mbytes. Default %d Mbytes\n", +- FRAGMENT_BUFFER_DEFAULT); ++ ERROR("-no-exports\t\tdon't make the filesystem " ++ "exportable via NFS\n"); ++ ERROR("-no-sparse\t\tdon't detect sparse files\n"); + ERROR("-noI\t\t\tdo not compress inode table\n"); + ERROR("-noD\t\t\tdo not compress data blocks\n"); + ERROR("-noF\t\t\tdo not compress fragment blocks\n"); +@@ -4430,13 +4581,34 @@ printOptions: + "files larger than block size\n"); + ERROR("-no-duplicates\t\tdo not perform duplicate " + "checking\n"); +- ERROR("-noappend\t\tdo not append to existing " +- "filesystem\n"); ++ ERROR("-all-root\t\tmake all files owned by root\n"); ++ ERROR("-force-uid uid\t\tset all file uids to uid\n"); ++ ERROR("-force-gid gid\t\tset all file gids to gid\n"); ++ ERROR("-nopad\t\t\tdo not pad filesystem to a multiple " ++ "of 4K\n"); + ERROR("-keep-as-directory\tif one source directory is " + "specified, create a root\n"); + ERROR("\t\t\tdirectory containing that directory, " + "rather than the\n"); + ERROR("\t\t\tcontents of the directory\n"); ++ ERROR("\nFilesystem filter options:\n"); ++ ERROR("-p \tAdd pseudo file definition\n"); ++ ERROR("-pf \tAdd list of pseudo file definitions\n"); ++ ERROR("-sort \tsort files according to " ++ "priorities in . One\n"); ++ ERROR("\t\t\tfile or dir with priority per line. " ++ "Priority -32768 to\n"); ++ ERROR("\t\t\t32767, default priority 0\n"); ++ ERROR("-ef \tlist of exclude dirs/files." ++ " One per line\n"); ++ ERROR("-wildcards\t\tAllow extended shell wildcards " ++ "(globbing) to be used in\n\t\t\texclude " ++ "dirs/files\n"); ++ ERROR("-regex\t\t\tAllow POSIX regular expressions to " ++ "be used in exclude\n\t\t\tdirs/files\n"); ++ ERROR("\nFilesystem append options:\n"); ++ ERROR("-noappend\t\tdo not append to existing " ++ "filesystem\n"); + ERROR("-root-becomes \twhen appending source " + "files/directories, make the\n"); + ERROR("\t\t\toriginal root become a subdirectory in " +@@ -4444,11 +4616,29 @@ printOptions: + ERROR("\t\t\tcalled , rather than adding the new " + "source items\n"); + ERROR("\t\t\tto the original root\n"); +- ERROR("-all-root\t\tmake all files owned by root\n"); +- ERROR("-force-uid uid\t\tset all file uids to uid\n"); +- ERROR("-force-gid gid\t\tset all file gids to gid\n"); +- ERROR("-nopad\t\t\tdo not pad filesystem to a multiple " +- "of 4K\n"); ++ ERROR("\nMksquashfs runtime options:\n"); ++ ERROR("-version\t\tprint version, licence and " ++ "copyright message\n"); ++ ERROR("-recover \t\trecover filesystem data " ++ "using recovery file \n"); ++ ERROR("-no-recovery\t\tdon't generate a recovery " ++ "file\n"); ++ ERROR("-info\t\t\tprint files written to filesystem\n"); ++ ERROR("-no-progress\t\tdon't display the progress " ++ "bar\n"); ++ ERROR("-processors \tUse processors." ++ " By default will use number of\n"); ++ ERROR("\t\t\tprocessors available\n"); ++ ERROR("-read-queue \tSet input queue to " ++ "Mbytes. Default %d Mbytes\n", ++ READER_BUFFER_DEFAULT); ++ ERROR("-write-queue \tSet output queue to " ++ "Mbytes. Default %d Mbytes\n", ++ WRITER_BUFFER_DEFAULT); ++ ERROR("-fragment-queue \tSet fagment queue to " ++ " Mbytes. Default %d Mbytes\n", ++ FRAGMENT_BUFFER_DEFAULT); ++ ERROR("\nMiscellaneous options:\n"); + ERROR("-root-owned\t\talternative name for -all-root" + "\n"); + ERROR("-noInodeCompression\talternative name for -noI" +@@ -4457,20 +4647,6 @@ printOptions: + "\n"); + ERROR("-noFragmentCompression\talternative name for " + "-noF\n"); +- ERROR("-sort \tsort files according to " +- "priorities in . One\n"); +- ERROR("\t\t\tfile or dir with priority per line. " +- "Priority -32768 to\n"); +- ERROR("\t\t\t32767, default priority 0\n"); +- ERROR("-ef \tlist of exclude dirs/files." +- " One per line\n"); +- ERROR("-wildcards\t\tAllow extended shell wildcards " +- "(globbing) to be used in\n\t\t\texclude " +- "dirs/files\n"); +- ERROR("-regex\t\t\tAllow POSIX regular expressions to " +- "be used in exclude\n\t\t\tdirs/files\n"); +- ERROR("-p \tAdd pseudo file definition\n"); +- ERROR("-pf \tAdd list of pseudo file definitions\n"); + exit(1); + } + } +@@ -4548,11 +4724,10 @@ printOptions: + fclose(fd); + } else if(strcmp(argv[i], "-e") == 0) + break; +- else if(strcmp(argv[i], "-b") == 0 || +- strcmp(argv[i], "-root-becomes") == 0 || ++ else if(strcmp(argv[i], "-root-becomes") == 0 || + strcmp(argv[i], "-sort") == 0 || + strcmp(argv[i], "-pf") == 0 || +- strcmp(argv[i], "-p") == 0) ++ strcmp(argv[i], "-comp") == 0) + i++; + + if(i != argc) { +@@ -4574,11 +4749,10 @@ printOptions: + sorted ++; + } else if(strcmp(argv[i], "-e") == 0) + break; +- else if(strcmp(argv[i], "-b") == 0 || +- strcmp(argv[i], "-root-becomes") == 0 || ++ else if(strcmp(argv[i], "-root-becomes") == 0 || + strcmp(argv[i], "-ef") == 0 || + strcmp(argv[i], "-pf") == 0 || +- strcmp(argv[i], "-p") == 0) ++ strcmp(argv[i], "-comp") == 0) + i++; + + #ifdef SQUASHFS_TRACE +@@ -4586,7 +4760,8 @@ printOptions: + #endif + + if(!delete) { +- if(read_super(fd, &sBlk, argv[source + 1]) == 0) { ++ comp = read_super(fd, &sBlk, argv[source + 1]); ++ if(comp == NULL) { + ERROR("Failed to read existing filesystem - will not " + "overwrite - ABORTING!\n"); + ERROR("To force Mksquashfs to write to this block " +@@ -4603,6 +4778,15 @@ printOptions: + always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); + duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); + exportable = SQUASHFS_EXPORTABLE(sBlk.flags); ++ } else { ++ comp = lookup_compressor(comp_name); ++ if(!comp->supported) { ++ ERROR("FATAL_ERROR: Compressor \"%s\" is not " ++ "supported!\n", comp_name); ++ ERROR("Compressors available:\n"); ++ display_compressors("", COMP_DEFAULT); ++ EXIT_MKSQUASHFS(); ++ } + } + + initialise_threads(); +@@ -4648,8 +4832,8 @@ printOptions: + "size %d\n", SQUASHFS_MAJOR, s_minor, argv[source + 1], + block_size); + printf("All -b, -noI, -noD, -noF, no-duplicates, no-fragments, " +- "-always-use-fragments and -exportable options ignored" +- "\n"); ++ "-always-use-fragments,\n-exportable and -comp options " ++ "ignored\n"); + printf("\nIf appending is not wanted, please re-run with " + "-noappend specified!\n\n"); + +@@ -4803,8 +4987,7 @@ restore_filesystem: + + sBlk.bytes_used = bytes; + +- /* Only compression supported */ +- sBlk.compression = ZLIB_COMPRESSION; ++ sBlk.compression = comp->id; + + /* Xattrs are not currently supported */ + sBlk.xattr_table_start = SQUASHFS_INVALID_BLK; +@@ -4820,6 +5003,8 @@ restore_filesystem: + + close(fd); + ++ delete_pseudo_files(); ++ + if(recovery_file[0] != '\0') + unlink(recovery_file); + +@@ -4827,9 +5012,9 @@ restore_filesystem: + * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + + sizeof(squashfs_super_block); + +- printf("\n%sSquashfs %d.%d filesystem, data block size %d\n", +- exportable ? "Exportable " : "", SQUASHFS_MAJOR, SQUASHFS_MINOR, +- block_size); ++ printf("\n%sSquashfs %d.%d filesystem, %s compressed, data block size" ++ " %d\n", exportable ? "Exportable " : "", SQUASHFS_MAJOR, ++ SQUASHFS_MINOR, comp->name, block_size); + printf("\t%s data, %s metadata, %s fragments\n", + noD ? "uncompressed" : "compressed", noI ? "uncompressed" : + "compressed", no_fragments ? "no" : noF ? "uncompressed" : +diff -Naurp squashfs-tools/pseudo.c squashfs-tools-lzma/pseudo.c +--- squashfs-tools/pseudo.c 2009-04-05 02:01:58.000000000 +0000 ++++ squashfs-tools-lzma/pseudo.c 2009-10-20 04:03:38.000000000 +0000 +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + #include "pseudo.h" + +@@ -55,6 +56,9 @@ + #define TRUE 1 + #define FALSE 0 + ++struct pseudo_dev **pseudo_file = NULL; ++int pseudo_count = 0; ++ + static void dump_pseudo(struct pseudo *pseudo, char *string) + { + int i; +@@ -99,7 +103,7 @@ struct pseudo *add_pseudo(struct pseudo + char *target, char *alltarget) + { + char targname[1024]; +- int i, error; ++ int i; + + target = get_component(target, targname); + +@@ -128,12 +132,8 @@ struct pseudo *add_pseudo(struct pseudo + if(target[0] == '\0') { + /* at leaf pathname component */ + pseudo->name[i].pseudo = NULL; +- pseudo->name[i].dev = malloc(sizeof(struct pseudo_dev)); +- if(pseudo->name[i].dev == NULL) +- BAD_ERROR("failed to allocate pseudo file\n"); + pseudo->name[i].pathname = strdup(alltarget); +- memcpy(pseudo->name[i].dev, pseudo_dev, +- sizeof(struct pseudo_dev)); ++ pseudo->name[i].dev = pseudo_dev; + } else { + /* recurse adding child components */ + pseudo->name[i].dev = NULL; +@@ -169,15 +169,9 @@ struct pseudo *add_pseudo(struct pseudo + if(target[0] == '\0') { + if(pseudo->name[i].dev == NULL && + pseudo_dev->type == 'd') { +- pseudo->name[i].dev = +- malloc(sizeof(struct pseudo_dev)); +- if(pseudo->name[i].dev == NULL) +- BAD_ERROR("failed to allocate " +- "pseudo file\n"); + pseudo->name[i].pathname = + strdup(alltarget); +- memcpy(pseudo->name[i].dev, pseudo_dev, +- sizeof(struct pseudo_dev)); ++ pseudo->name[i].dev = pseudo_dev; + } else + ERROR("%s already exists as a " + "directory. Ignoring %s!\n", +@@ -229,16 +223,113 @@ struct pseudo_entry *pseudo_readdir(stru + } + + ++int exec_file(char *command, struct pseudo_dev *dev) ++{ ++ int child, res; ++ static pid_t pid = -1; ++ int pipefd[2]; ++#ifdef USE_TMP_FILE ++ char filename[1024]; ++ int status; ++ static int number = 0; ++#endif ++ ++ if(pid == -1) ++ pid = getpid(); ++ ++#ifdef USE_TMP_FILE ++ sprintf(filename, "/tmp/squashfs_pseudo_%d_%d", pid, number ++); ++ pipefd[1] = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); ++ if(pipefd[1] == -1) { ++ printf("open failed\n"); ++ return -1; ++ } ++#else ++ res = pipe(pipefd); ++ if(res == -1) { ++ printf("pipe failed\n"); ++ return -1; ++ } ++#endif ++ ++ child = fork(); ++ if(child == -1) { ++ printf("fork failed\n"); ++ goto failed; ++ } ++ ++ if(child == 0) { ++ close(STDOUT_FILENO); ++ res = dup(pipefd[1]); ++ if(res == -1) { ++ printf("dup failed\n"); ++ exit(EXIT_FAILURE); ++ } ++ execl("/bin/sh", "sh", "-c", command, (char *) NULL); ++ printf("execl failed\n"); ++ exit(EXIT_FAILURE); ++ } ++ ++#ifdef USE_TMP_FILE ++ res = waitpid(child, &status, 0); ++ close(pipefd[1]); ++ if(res != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0) { ++ dev->filename = strdup(filename); ++ return 0; ++ } ++failed: ++ unlink(filename); ++ return -1; ++#else ++ close(pipefd[1]); ++ dev->fd = pipefd[0]; ++ dev->child = child; ++ return 0; ++failed: ++ return -1; ++#endif ++} ++ ++ ++void add_pseudo_file(struct pseudo_dev *dev) ++{ ++ pseudo_file = realloc(pseudo_file, (pseudo_count + 1) * ++ sizeof(struct pseudo_dev *)); ++ if(pseudo_file == NULL) ++ BAD_ERROR("Failed to realloc pseudo_file\n"); ++ ++ dev->pseudo_id = pseudo_count; ++ pseudo_file[pseudo_count ++] = dev; ++} ++ ++ ++void delete_pseudo_files() ++{ ++#ifdef USE_TMP_FILE ++ int i; ++ ++ for(i = 0; i < pseudo_count; i++) ++ unlink(pseudo_file[i]->filename); ++#endif ++} ++ ++ ++struct pseudo_dev *get_pseudo_file(int pseudo_id) ++{ ++ return pseudo_file[pseudo_id]; ++} ++ ++ + int read_pseudo_def(struct pseudo **pseudo, char *def) + { +- int n; ++ int n, bytes; + unsigned int major = 0, minor = 0, mode; + char filename[2048], type, suid[100], sgid[100], *ptr; + long long uid, gid; +- struct pseudo_dev dev; ++ struct pseudo_dev *dev; + +- n = sscanf(def, "%s %c %o %s %s %u %u", filename, &type, &mode, suid, sgid, +- &major, &minor); ++ n = sscanf(def, "%s %c %o %s %s %n", filename, &type, &mode, suid, ++ sgid, &bytes); + + if(n < 5) { + ERROR("Not enough or invalid arguments in pseudo file " +@@ -249,7 +340,9 @@ int read_pseudo_def(struct pseudo **pseu + switch(type) { + case 'b': + case 'c': +- if(n < 7) { ++ n = sscanf(def + bytes, "%u %u", &major, &minor); ++ ++ if(n < 2) { + ERROR("Not enough or invalid arguments in pseudo file " + "definition\n"); + goto error; +@@ -265,47 +358,15 @@ int read_pseudo_def(struct pseudo **pseu + goto error; + } + +- /* fall through */ +- case 'd': +- if(mode > 0777) { +- ERROR("Mode %o out of range\n", mode); ++ case 'f': ++ if(def[bytes] == '\0') { ++ ERROR("Not enough arguments in pseudo file " ++ "definition\n"); + goto error; +- } +- +- uid = strtoll(suid, &ptr, 10); +- if(*ptr == '\0') { +- if(uid < 0 || uid > ((1LL << 32) - 1)) { +- ERROR("Uid %s out of range\n", suid); +- goto error; +- } +- } else { +- struct passwd *pwuid = getpwnam(suid); +- if(pwuid) +- uid = pwuid->pw_uid; +- else { +- ERROR("Uid %s invalid uid or unknown user\n", +- suid); +- goto error; +- } +- } +- +- gid = strtoll(sgid, &ptr, 10); +- if(*ptr == '\0') { +- if(gid < 0 || gid > ((1LL << 32) - 1)) { +- ERROR("Gid %s out of range\n", sgid); +- goto error; +- } +- } else { +- struct group *grgid = getgrnam(sgid); +- if(grgid) +- gid = grgid->gr_gid; +- else { +- ERROR("Gid %s invalid uid or unknown user\n", +- sgid); +- goto error; +- } +- } +- ++ } ++ break; ++ case 'd': ++ case 'm': + break; + default: + ERROR("Unsupported type %c\n", type); +@@ -313,6 +374,43 @@ int read_pseudo_def(struct pseudo **pseu + } + + ++ if(mode > 0777) { ++ ERROR("Mode %o out of range\n", mode); ++ goto error; ++ } ++ ++ uid = strtoll(suid, &ptr, 10); ++ if(*ptr == '\0') { ++ if(uid < 0 || uid > ((1LL << 32) - 1)) { ++ ERROR("Uid %s out of range\n", suid); ++ goto error; ++ } ++ } else { ++ struct passwd *pwuid = getpwnam(suid); ++ if(pwuid) ++ uid = pwuid->pw_uid; ++ else { ++ ERROR("Uid %s invalid uid or unknown user\n", suid); ++ goto error; ++ } ++ } ++ ++ gid = strtoll(sgid, &ptr, 10); ++ if(*ptr == '\0') { ++ if(gid < 0 || gid > ((1LL << 32) - 1)) { ++ ERROR("Gid %s out of range\n", sgid); ++ goto error; ++ } ++ } else { ++ struct group *grgid = getgrnam(sgid); ++ if(grgid) ++ gid = grgid->gr_gid; ++ else { ++ ERROR("Gid %s invalid uid or unknown user\n", sgid); ++ goto error; ++ } ++ } ++ + switch(type) { + case 'b': + mode |= S_IFBLK; +@@ -323,16 +421,37 @@ int read_pseudo_def(struct pseudo **pseu + case 'd': + mode |= S_IFDIR; + break; ++ case 'f': ++ mode |= S_IFREG; ++ break; + } + +- dev.type = type; +- dev.mode = mode; +- dev.uid = uid; +- dev.gid = gid; +- dev.major = major; +- dev.minor = minor; ++ dev = malloc(sizeof(struct pseudo_dev)); ++ if(dev == NULL) ++ BAD_ERROR("Failed to create pseudo_dev\n"); ++ ++ dev->type = type; ++ dev->mode = mode; ++ dev->uid = uid; ++ dev->gid = gid; ++ dev->major = major; ++ dev->minor = minor; ++ ++ if(type == 'f') { ++ int res; ++ ++ printf("Executing dynamic pseudo file\n"); ++ printf("\t\"%s\"\n", def); ++ res = exec_file(def + bytes, dev); ++ if(res == -1) { ++ ERROR("Failed to execute dynamic pseudo file definition" ++ " \"%s\"\n", def); ++ return FALSE; ++ } ++ add_pseudo_file(dev); ++ } + +- *pseudo = add_pseudo(*pseudo, &dev, filename, filename); ++ *pseudo = add_pseudo(*pseudo, dev, filename, filename); + + return TRUE; + +diff -Naurp squashfs-tools/pseudo.h squashfs-tools-lzma/pseudo.h +--- squashfs-tools/pseudo.h 2009-04-04 01:44:24.000000000 +0000 ++++ squashfs-tools-lzma/pseudo.h 2009-10-20 04:03:38.000000000 +0000 +@@ -27,6 +27,12 @@ struct pseudo_dev { + unsigned int gid; + unsigned int major; + unsigned int minor; ++ int pseudo_id; ++ int fd; ++ int child; ++#ifdef USE_TMP_FILE ++ char *filename; ++#endif + }; + + struct pseudo_entry { +@@ -46,3 +52,5 @@ extern int read_pseudo_def(struct pseudo + extern int read_pseudo_file(struct pseudo **, char *); + extern struct pseudo *pseudo_subdir(char *, struct pseudo *); + extern struct pseudo_entry *pseudo_readdir(struct pseudo *); ++extern struct pseudo_dev *get_pseudo_file(int); ++extern void delete_pseudo_files(); +diff -Naurp squashfs-tools/read_fs.c squashfs-tools-lzma/read_fs.c +--- squashfs-tools/read_fs.c 2009-03-31 04:23:14.000000000 +0000 ++++ squashfs-tools-lzma/read_fs.c 2009-10-20 04:03:38.000000000 +0000 +@@ -36,7 +36,6 @@ extern unsigned int get_guid(unsigned in + #include + #include + #include +-#include + #include + + #ifndef linux +@@ -51,6 +50,7 @@ extern unsigned int get_guid(unsigned in + #include "squashfs_swap.h" + #include "read_fs.h" + #include "global.h" ++#include "compressor.h" + + #include + +@@ -66,7 +66,9 @@ extern unsigned int get_guid(unsigned in + fprintf(stderr, s, ## args); \ + } while(0) + +-int read_block(int fd, long long start, long long *next, unsigned char *block, ++static struct compressor *comp; ++ ++int read_block(int fd, long long start, long long *next, void *block, + squashfs_super_block *sBlk) + { + unsigned short c_byte; +@@ -77,32 +79,24 @@ int read_block(int fd, long long start, + + if(SQUASHFS_COMPRESSED(c_byte)) { + char buffer[SQUASHFS_METADATA_SIZE]; +- int res; +- unsigned long bytes = SQUASHFS_METADATA_SIZE; ++ int error, res; + + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + read_destination(fd, start + offset, c_byte, buffer); + +- res = uncompress(block, &bytes, (const unsigned char *) buffer, +- c_byte); +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "memory\n"); +- else if(res == Z_BUF_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "room in output buffer\n"); +- else +- ERROR("zlib::uncompress failed, unknown error " +- "%d\n", res); ++ res = comp->uncompress(block, buffer, c_byte, ++ SQUASHFS_METADATA_SIZE, &error); ++ if(res == -1) { ++ ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); + return 0; + } + if(next) + *next = start + offset + c_byte; +- return bytes; ++ return res; + } else { + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); +- read_destination(fd, start + offset, c_byte, (char *) block); ++ read_destination(fd, start + offset, c_byte, block); + if(next) + *next = start + offset + c_byte; + return c_byte; +@@ -356,7 +350,7 @@ failed: + } + + +-int read_super(int fd, squashfs_super_block *sBlk, char *source) ++struct compressor *read_super(int fd, squashfs_super_block *sBlk, char *source) + { + read_destination(fd, SQUASHFS_START, sizeof(squashfs_super_block), + (char *) sBlk); +@@ -388,8 +382,18 @@ int read_super(int fd, squashfs_super_bl + goto failed_mount; + } + ++ /* Check the compression type */ ++ comp = lookup_compressor_id(sBlk->compression); ++ if(!comp->supported) { ++ ERROR("Filesystem on %s uses %s compression, this is" ++ "unsupported by this version\n", source, comp->name); ++ display_compressors("", ""); ++ goto failed_mount; ++ } ++ + printf("Found a valid %sSQUASHFS superblock on %s.\n", + SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source); ++ printf("\tCompression used %s\n", comp->name); + printf("\tInodes are %scompressed\n", + SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); + printf("\tData is %scompressed\n", +@@ -417,10 +421,10 @@ int read_super(int fd, squashfs_super_bl + TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start); + printf("\n"); + +- return TRUE; ++ return comp; + + failed_mount: +- return FALSE; ++ return NULL; + } + + +@@ -514,12 +518,17 @@ unsigned int *read_id_table(int fd, squa + SQUASHFS_INSWAP_ID_BLOCKS(index, indexes); + + for(i = 0; i < indexes; i++) { +- int length; +- length = read_block(fd, index[i], NULL, ++ int length = read_block(fd, index[i], NULL, + ((unsigned char *) id_table) + + (i * SQUASHFS_METADATA_SIZE), sBlk); + TRACE("Read id table block %d, from 0x%llx, length %d\n", i, + index[i], length); ++ if(length == 0) { ++ ERROR("Failed to read id table block %d, from 0x%llx, " ++ "length %d\n", i, index[i], length); ++ free(id_table); ++ return NULL; ++ } + } + + SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids); +@@ -563,6 +572,13 @@ int read_fragment_table(int fd, squashfs + (i * SQUASHFS_METADATA_SIZE), sBlk); + TRACE("Read fragment table block %d, from 0x%llx, length %d\n", + i, fragment_table_index[i], length); ++ if(length == 0) { ++ ERROR("Failed to read fragment table block %d, from " ++ "0x%llx, length %d\n", i, ++ fragment_table_index[i], length); ++ free(*fragment_table); ++ return 0; ++ } + } + + for(i = 0; i < sBlk->fragments; i++) +@@ -599,6 +615,13 @@ int read_inode_lookup_table(int fd, squa + (i * SQUASHFS_METADATA_SIZE), sBlk); + TRACE("Read inode lookup table block %d, from 0x%llx, length " + "%d\n", i, index[i], length); ++ if(length == 0) { ++ ERROR("Failed to read inode lookup table block %d, " ++ "from 0x%llx, length %d\n", i, index[i], ++ length); ++ free(*inode_lookup_table); ++ return 0; ++ } + } + + SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes); +diff -Naurp squashfs-tools/sort.c squashfs-tools-lzma/sort.c +--- squashfs-tools/sort.c 2009-03-31 04:25:53.000000000 +0000 ++++ squashfs-tools-lzma/sort.c 2009-10-20 04:03:38.000000000 +0000 +@@ -198,7 +198,7 @@ void generate_file_priorities(struct dir + while(dir->current_count < dir->count) { + struct dir_ent *dir_ent = dir->list[dir->current_count++]; + struct stat *buf = &dir_ent->inode->buf; +- if(dir_ent->data) ++ if(dir_ent->inode->root_entry) + continue; + + switch(buf->st_mode & S_IFMT) { +@@ -254,6 +254,7 @@ void sort_files_and_write(struct dir_inf + write_file(&inode, entry->dir, &duplicate_file); + INFO("file %s, uncompressed size %lld bytes %s" + "\n", entry->dir->pathname, ++ (long long) + entry->dir->inode->buf.st_size, + duplicate_file ? "DUPLICATE" : ""); + entry->dir->inode->inode = inode; +@@ -261,6 +262,7 @@ void sort_files_and_write(struct dir_inf + } else + INFO("file %s, uncompressed size %lld bytes " + "LINK\n", entry->dir->pathname, ++ (long long) + entry->dir->inode->buf.st_size); + } + } +diff -Naurp squashfs-tools/sort.h squashfs-tools-lzma/sort.h +--- squashfs-tools/sort.h 2009-02-08 12:02:53.000000000 +0000 ++++ squashfs-tools-lzma/sort.h 2009-10-20 04:03:38.000000000 +0000 +@@ -42,17 +42,19 @@ struct dir_ent { + struct inode_info *inode; + struct dir_info *dir; + struct dir_info *our_dir; +- struct old_root_entry_info *data; + }; + + struct inode_info { +- unsigned int nlink; + struct stat buf; ++ struct inode_info *next; + squashfs_inode inode; +- unsigned int type; + unsigned int inode_number; ++ unsigned int nlink; ++ int pseudo_id; ++ char type; + char read; +- struct inode_info *next; ++ char root_entry; ++ char pseudo_file; + }; + + struct priority_entry { +diff -Naurp squashfs-tools/squashfs_compat.h squashfs-tools-lzma/squashfs_compat.h +--- squashfs-tools/squashfs_compat.h 2009-03-16 04:27:27.000000000 +0000 ++++ squashfs-tools-lzma/squashfs_compat.h 2009-10-20 04:03:38.000000000 +0000 +@@ -777,11 +777,10 @@ typedef union squashfs_inode_header_2 sq + #endif + + #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ +- int bits;\ +- int b_pos = pos % 8;\ +- unsigned long long val = 0;\ +- unsigned char *s = (unsigned char *)p + (pos / 8);\ +- unsigned char *d = ((unsigned char *) &val) + 7;\ ++ b_pos = pos % 8;\ ++ val = 0;\ ++ s = (unsigned char *)p + (pos / 8);\ ++ d = ((unsigned char *) &val) + 7;\ + for(bits = 0; bits < (tbits + b_pos); bits += 8) \ + *d-- = *s++;\ + value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ +diff -Naurp squashfs-tools/squashfs_fs.h squashfs-tools-lzma/squashfs_fs.h +--- squashfs-tools/squashfs_fs.h 2009-03-18 02:50:20.000000000 +0000 ++++ squashfs-tools-lzma/squashfs_fs.h 2009-10-20 04:03:38.000000000 +0000 +@@ -229,6 +229,7 @@ typedef long long squashfs_block_t; + typedef long long squashfs_inode_t; + + #define ZLIB_COMPRESSION 1 ++#define LZMA_COMPRESSION 2 + + struct squashfs_super_block { + unsigned int s_magic; +diff -Naurp squashfs-tools/unsquash-3.c squashfs-tools-lzma/unsquash-3.c +--- squashfs-tools/unsquash-3.c 2009-03-31 04:35:10.000000000 +0000 ++++ squashfs-tools-lzma/unsquash-3.c 2009-10-20 04:03:38.000000000 +0000 +@@ -36,7 +36,7 @@ int read_fragment_table_3() + sBlk.fragment_table_start); + + if(sBlk.fragments == 0) +- return; ++ return TRUE; + + if((fragment_table = malloc(sBlk.fragments * + sizeof(squashfs_fragment_entry_3))) == NULL) +diff -Naurp squashfs-tools/unsquash-4.c squashfs-tools-lzma/unsquash-4.c +--- squashfs-tools/unsquash-4.c 2009-03-31 04:38:31.000000000 +0000 ++++ squashfs-tools-lzma/unsquash-4.c 2009-10-20 04:03:38.000000000 +0000 +@@ -38,7 +38,7 @@ int read_fragment_table_4() + sBlk.fragment_table_start); + + if(sBlk.fragments == 0) +- return; ++ return TRUE; + + if((fragment_table = malloc(sBlk.fragments * + sizeof(squashfs_fragment_entry))) == NULL) +diff -Naurp squashfs-tools/unsquashfs.c squashfs-tools-lzma/unsquashfs.c +--- squashfs-tools/unsquashfs.c 2009-04-05 21:23:06.000000000 +0000 ++++ squashfs-tools-lzma/unsquashfs.c 2009-10-20 04:03:39.000000000 +0000 +@@ -25,6 +25,9 @@ + #include "squashfs_swap.h" + #include "squashfs_compat.h" + #include "read_fs.h" ++#include "compressor.h" ++ ++#include + + struct cache *fragment_cache, *data_cache; + struct queue *to_reader, *to_deflate, *to_writer, *from_writer; +@@ -36,6 +39,7 @@ int processors = -1; + + struct super_block sBlk; + squashfs_operations s_ops; ++struct compressor *comp; + + int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, + dev_count = 0, fifo_count = 0; +@@ -590,31 +594,23 @@ int read_block(long long start, long lon + offset = 3; + if(SQUASHFS_COMPRESSED(c_byte)) { + char buffer[SQUASHFS_METADATA_SIZE]; +- int res; +- unsigned long bytes = SQUASHFS_METADATA_SIZE; ++ int error, res; + + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + if(read_bytes(start + offset, c_byte, buffer) == FALSE) + goto failed; + +- res = uncompress((unsigned char *) block, &bytes, +- (const unsigned char *) buffer, c_byte); ++ res = comp->uncompress(block, buffer, c_byte, ++ SQUASHFS_METADATA_SIZE, &error); + +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "memory\n"); +- else if(res == Z_BUF_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "room in output buffer\n"); +- else +- ERROR("zlib::uncompress failed, unknown error " +- "%d\n", res); ++ if(res == -1) { ++ ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); + goto failed; + } + if(next) + *next = start + offset + c_byte; +- return bytes; ++ return res; + } else { + c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); + if(read_bytes(start + offset, c_byte, block) == FALSE) +@@ -632,36 +628,26 @@ failed: + + int read_data_block(long long start, unsigned int size, char *block) + { +- int res; +- unsigned long bytes = block_size; ++ int error, res; + int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); + + TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, +- SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), +- SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : ++ c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" : + "uncompressed"); + + if(SQUASHFS_COMPRESSED_BLOCK(size)) { + if(read_bytes(start, c_byte, data) == FALSE) + goto failed; + +- res = uncompress((unsigned char *) block, &bytes, +- (const unsigned char *) data, c_byte); ++ res = comp->uncompress(block, data, c_byte, block_size, &error); + +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "memory\n"); +- else if(res == Z_BUF_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "room in output buffer\n"); +- else +- ERROR("zlib::uncompress failed, unknown error " +- "%d\n", res); ++ if(res == -1) { ++ ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); + goto failed; + } + +- return bytes; ++ return res; + } else { + if(read_bytes(start, c_byte, block) == FALSE) + goto failed; +@@ -671,7 +657,7 @@ int read_data_block(long long start, uns + + failed: + ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start, +- size); ++ c_byte); + return FALSE; + } + +@@ -1383,6 +1369,11 @@ void squashfs_stat(char *source) + #endif + printf("Creation or last append time %s", mkfs_str ? mkfs_str : + "failed to get time\n"); ++ printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", ++ sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); ++ if(sBlk.s_major == 4) ++ printf("Compression %s\n", comp->name); ++ printf("Block size %d\n", sBlk.block_size); + printf("Filesystem is %sexportable via NFS\n", + SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); + +@@ -1409,9 +1400,6 @@ void squashfs_stat(char *source) + SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); + else + printf("Duplicates are removed\n"); +- printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", +- sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); +- printf("Block size %d\n", sBlk.block_size); + if(sBlk.s_major > 1) + printf("Number of fragments %d\n", sBlk.fragments); + printf("Number of inodes %d\n", sBlk.inodes); +@@ -1459,6 +1447,18 @@ int read_super(char *source) + s_ops.read_inode = read_inode_4; + s_ops.read_uids_guids = read_uids_guids_4; + memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4)); ++ ++ /* ++ * Check the compression type ++ */ ++ comp = lookup_compressor_id(sBlk.compression); ++ if(!comp->supported) { ++ ERROR("Filesystem uses %s compression, this is " ++ "unsupported by this version\n", comp->name); ++ ERROR("Decompressors available:\n"); ++ display_compressors("", ""); ++ goto failed_mount; ++ } + return TRUE; + } + +@@ -1548,6 +1548,11 @@ int read_super(char *source) + goto failed_mount; + } + ++ /* ++ * 1.x, 2.x and 3.x filesystems use gzip compression. Gzip is always ++ * suppported. ++ */ ++ comp = lookup_compressor("gzip"); + return TRUE; + + failed_mount: +@@ -1707,32 +1712,24 @@ void *deflator(void *arg) + + while(1) { + struct cache_entry *entry = queue_get(to_deflate); +- int res; +- unsigned long bytes = block_size; ++ int error, res; + +- res = uncompress((unsigned char *) tmp, &bytes, +- (const unsigned char *) entry->data, +- SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size)); +- +- if(res != Z_OK) { +- if(res == Z_MEM_ERROR) +- ERROR("zlib::uncompress failed, not enough" +- "memory\n"); +- else if(res == Z_BUF_ERROR) +- ERROR("zlib::uncompress failed, not enough " +- "room in output buffer\n"); +- else +- ERROR("zlib::uncompress failed, unknown error " +- "%d\n", res); +- } else +- memcpy(entry->data, tmp, bytes); ++ res = comp->uncompress(tmp, entry->data, ++ SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size, ++ &error); ++ ++ if(res == -1) ++ ERROR("%s uncompress failed with error code %d\n", ++ comp->name, error); ++ else ++ memcpy(entry->data, tmp, res); + + /* + * block has been either successfully decompressed, or an error + * occurred, clear pending flag, set error appropriately and + * wake up any threads waiting on this block + */ +- cache_block_ready(entry, res != Z_OK); ++ cache_block_ready(entry, res == -1); + } + } + +@@ -1938,7 +1935,6 @@ int main(int argc, char *argv[]) + int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; + int data_buffer_size = DATA_BUFFER_DEFAULT; + char *b; +- struct winsize winsize; + + pthread_mutex_init(&screen_mutex, NULL); + root_process = geteuid() == 0; +@@ -2087,6 +2083,8 @@ options: + "regular expressions\n"); + ERROR("\t\t\t\trather than use the default shell " + "wildcard\n\t\t\t\texpansion (globbing)\n"); ++ ERROR("\nDecompressors available:\n"); ++ display_compressors("", ""); + } + exit(1); + } +diff -Naurp squashfs-tools/unsquashfs.h squashfs-tools-lzma/unsquashfs.h +--- squashfs-tools/unsquashfs.h 2009-03-29 02:29:02.000000000 +0000 ++++ squashfs-tools-lzma/unsquashfs.h 2009-10-20 04:03:39.000000000 +0000 +@@ -31,7 +31,6 @@ + #include + #include + #include +-#include + #include + #include + #include diff --git a/sys-fs/squashfs-tools/squashfs-tools-4.0-lzma.patch b/sys-fs/squashfs-tools/squashfs-tools-4.0-lzma.patch deleted file mode 100644 index 9a7c78c..0000000 --- a/sys-fs/squashfs-tools/squashfs-tools-4.0-lzma.patch +++ /dev/null @@ -1,2210 +0,0 @@ -diff -Naurp squashfs-tools/compressor.c squashfs-tools-lzma/compressor.c ---- squashfs-tools/compressor.c 1970-01-01 00:00:00.000000000 +0000 -+++ squashfs-tools-lzma/compressor.c 2009-10-20 04:03:37.000000000 +0000 -@@ -0,0 +1,78 @@ -+/* -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 -+ * Phillip Lougher -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2, -+ * or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * compressor.c -+ */ -+ -+#include -+#include -+#include "compressor.h" -+#include "squashfs_fs.h" -+ -+extern int gzip_compress(void **, char *, char *, int, int, int *); -+extern int gzip_uncompress(char *, char *, int, int, int *); -+extern int lzma_compress(void **, char *, char *, int, int, int *); -+extern int lzma_uncompress(char *, char *, int, int, int *); -+ -+struct compressor compressor[] = { -+ { gzip_compress, gzip_uncompress, ZLIB_COMPRESSION, "gzip", 1 }, -+#ifdef LZMA_SUPPORT -+ { lzma_compress, lzma_uncompress, LZMA_COMPRESSION, "lzma", 1 }, -+#else -+ { NULL, NULL, LZMA_COMPRESSION, "lzma", 0 }, -+#endif -+ { NULL, NULL , 0, "unknown", 0} -+}; -+ -+ -+struct compressor *lookup_compressor(char *name) -+{ -+ int i; -+ -+ for(i = 0; compressor[i].id; i++) -+ if(strcmp(compressor[i].name, name) == 0) -+ break; -+ -+ return &compressor[i]; -+} -+ -+ -+struct compressor *lookup_compressor_id(int id) -+{ -+ int i; -+ -+ for(i = 0; compressor[i].id; i++) -+ if(id == compressor[i].id) -+ break; -+ -+ return &compressor[i]; -+} -+ -+ -+void display_compressors(char *indent, char *def_comp) -+{ -+ int i; -+ -+ for(i = 0; compressor[i].id; i++) -+ if(compressor[i].supported) -+ fprintf(stderr, "%s\t%s%s\n", indent, -+ compressor[i].name, -+ strcmp(compressor[i].name, def_comp) == 0 ? -+ " (default)" : ""); -+} -diff -Naurp squashfs-tools/compressor.h squashfs-tools-lzma/compressor.h ---- squashfs-tools/compressor.h 1970-01-01 00:00:00.000000000 +0000 -+++ squashfs-tools-lzma/compressor.h 2009-10-20 04:03:37.000000000 +0000 -@@ -0,0 +1,33 @@ -+/* -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 -+ * Phillip Lougher -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2, -+ * or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * compressor.h -+ */ -+ -+struct compressor { -+ int (*compress)(void **, char *, char *, int, int, int *); -+ int (*uncompress)(char *, char *, int, int, int *); -+ int id; -+ char *name; -+ int supported; -+}; -+ -+extern struct compressor *lookup_compressor(char *); -+extern struct compressor *lookup_compressor_id(int); -+extern void display_compressors(char *, char *); -diff -Naurp squashfs-tools/gzip_wrapper.c squashfs-tools-lzma/gzip_wrapper.c ---- squashfs-tools/gzip_wrapper.c 1970-01-01 00:00:00.000000000 +0000 -+++ squashfs-tools-lzma/gzip_wrapper.c 2009-10-20 04:03:37.000000000 +0000 -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 -+ * Phillip Lougher -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2, -+ * or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * gzip_wrapper.c -+ */ -+ -+#include -+#include -+ -+int gzip_compress(void **strm, char *d, char *s, int size, int block_size, -+ int *error) -+{ -+ int res = 0; -+ z_stream *stream = *strm; -+ -+ if(stream == NULL) { -+ if((stream = *strm = malloc(sizeof(z_stream))) == NULL) -+ goto failed; -+ -+ stream->zalloc = Z_NULL; -+ stream->zfree = Z_NULL; -+ stream->opaque = 0; -+ -+ if((res = deflateInit(stream, 9)) != Z_OK) -+ goto failed; -+ } else if((res = deflateReset(stream)) != Z_OK) -+ goto failed; -+ -+ stream->next_in = (unsigned char *) s; -+ stream->avail_in = size; -+ stream->next_out = (unsigned char *) d; -+ stream->avail_out = block_size; -+ -+ res = deflate(stream, Z_FINISH); -+ if(res == Z_STREAM_END) -+ /* -+ * Success, return the compressed size. -+ */ -+ return (int) stream->total_out; -+ if(res == Z_OK) -+ /* -+ * Output buffer overflow. Return out of buffer space -+ */ -+ return 0; -+failed: -+ /* -+ * All other errors return failure, with the compressor -+ * specific error code in *error -+ */ -+ *error = res; -+ return -1; -+} -+ -+ -+int gzip_uncompress(char *d, char *s, int size, int block_size, int *error) -+{ -+ int res; -+ unsigned long bytes = block_size; -+ -+ res = uncompress((unsigned char *) d, &bytes, -+ (const unsigned char *) s, size); -+ -+ *error = res; -+ return res == Z_OK ? (int) bytes : -1; -+} -diff -Naurp squashfs-tools/lzma_wrapper.c squashfs-tools-lzma/lzma_wrapper.c ---- squashfs-tools/lzma_wrapper.c 1970-01-01 00:00:00.000000000 +0000 -+++ squashfs-tools-lzma/lzma_wrapper.c 2009-10-14 03:32:57.000000000 +0000 -@@ -0,0 +1,93 @@ -+/* -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 -+ * Phillip Lougher -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2, -+ * or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * lzma_wrapper.c -+ */ -+ -+#include -+ -+#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) -+ -+int lzma_compress(void **strm, char *dest, char *src, int size,int block_size, -+ int *error) -+{ -+ unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src; -+ size_t props_size = LZMA_PROPS_SIZE, -+ outlen = block_size - LZMA_HEADER_SIZE; -+ int res; -+ -+ res = LzmaCompress(d + LZMA_HEADER_SIZE, &outlen, s, size, d, -+ &props_size, 5, block_size, 3, 0, 2, 32, 1); -+ -+ if(res == SZ_ERROR_OUTPUT_EOF) { -+ /* -+ * Output buffer overflow. Return out of buffer space error -+ */ -+ return 0; -+ } -+ -+ if(res != SZ_OK) { -+ /* -+ * All other errors return failure, with the compressor -+ * specific error code in *error -+ */ -+ *error = res; -+ return -1; -+ } -+ -+ /* -+ * Fill in the 8 byte little endian uncompressed size field in the -+ * LZMA header. 8 bytes is excessively large for squashfs but -+ * this is the standard LZMA header and which is expected by the kernel -+ * code -+ */ -+ d[LZMA_PROPS_SIZE] = size & 255; -+ d[LZMA_PROPS_SIZE + 1] = (size >> 8) & 255; -+ d[LZMA_PROPS_SIZE + 2] = (size >> 16) & 255; -+ d[LZMA_PROPS_SIZE + 3] = (size >> 24) & 255; -+ d[LZMA_PROPS_SIZE + 4] = 0; -+ d[LZMA_PROPS_SIZE + 5] = 0; -+ d[LZMA_PROPS_SIZE + 6] = 0; -+ d[LZMA_PROPS_SIZE + 7] = 0; -+ -+ /* -+ * Success, return the compressed size. Outlen returned by the LZMA -+ * compressor does not include the LZMA header space -+ */ -+ return outlen + LZMA_HEADER_SIZE; -+} -+ -+ -+int lzma_uncompress(char *dest, char *src, int size, int block_size, -+ int *error) -+{ -+ unsigned char *d = (unsigned char *) dest, *s = (unsigned char *) src; -+ size_t outlen, inlen = size - LZMA_HEADER_SIZE; -+ int res; -+ -+ outlen = s[LZMA_PROPS_SIZE] | -+ (s[LZMA_PROPS_SIZE + 1] << 8) | -+ (s[LZMA_PROPS_SIZE + 2] << 16) | -+ (s[LZMA_PROPS_SIZE + 3] << 24); -+ -+ res = LzmaUncompress(d, &outlen, s + LZMA_HEADER_SIZE, &inlen, -+ s, LZMA_PROPS_SIZE); -+ -+ *error = res; -+ return res == SZ_OK ? outlen : -1; -+} -diff -Naurp squashfs-tools/Makefile squashfs-tools-lzma/Makefile ---- squashfs-tools/Makefile 2009-04-05 02:03:36.000000000 +0000 -+++ squashfs-tools-lzma/Makefile 2009-10-22 04:17:12.000000000 +0000 -@@ -1,40 +1,76 @@ -+# -+# Building LZMA support -+# Download LZMA sdk (4.65 used in development, other versions may work), -+# set LZMA_DIR to unpacked source, and uncomment next line -+LZMA_SUPPORT = 1 -+LZMA_DIR = ../../ -+ -+#Compression default. -+COMP_DEFAULT = gzip -+ -+INCLUDEDIR = -I. - INSTALL_DIR = /usr/local/bin - --INCLUDEDIR = . -+MKSQUASHFS_OBJS = mksquashfs.o read_fs.o sort.o swap.o pseudo.o compressor.o \ -+ gzip_wrapper.o -+ -+UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \ -+ unsquash-4.o swap.o compressor.o gzip_wrapper.o - --CFLAGS := -I$(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_GNU_SOURCE -O2 -+CFLAGS := $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE \ -+ -D_GNU_SOURCE -DCOMP_DEFAULT=\"$(COMP_DEFAULT)\" -O2 -Wall - -+ifdef LZMA_SUPPORT -+LZMA_OBJS = $(LZMA_DIR)/C/Alloc.o $(LZMA_DIR)/C/LzFind.o \ -+ $(LZMA_DIR)/C/LzmaDec.o $(LZMA_DIR)/C/LzmaEnc.o $(LZMA_DIR)/C/LzmaLib.o -+INCLUDEDIR += -I$(LZMA_DIR)/C -+CFLAGS += -DLZMA_SUPPORT -I../../C -+MKSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) -+UNSQUASHFS_OBJS += lzma_wrapper.o $(LZMA_OBJS) -+endif -+ -+.PHONY: all - all: mksquashfs unsquashfs - --mksquashfs: mksquashfs.o read_fs.o sort.o swap.o pseudo.o -- $(CC) mksquashfs.o read_fs.o sort.o swap.o pseudo.o -lz -lpthread -lm -o $@ -+mksquashfs: $(MKSQUASHFS_OBJS) -+ $(CC) $(MKSQUASHFS_OBJS) -lz -lpthread -lm -o $@ -+ -+mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h \ -+ squashfs_swap.h - --mksquashfs.o: mksquashfs.c squashfs_fs.h mksquashfs.h global.h sort.h squashfs_swap.h Makefile -+read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h - --read_fs.o: read_fs.c squashfs_fs.h read_fs.h global.h squashfs_swap.h Makefile -+sort.o: sort.c squashfs_fs.h global.h sort.h - --sort.o: sort.c squashfs_fs.h global.h sort.h Makefile -+swap.o: swap.c - --swap.o: swap.c Makefile -+pseudo.o: pseudo.c pseudo.h - --pseudo.o: pseudo.c pseudo.h Makefile -+compressor.o: compressor.c compressor.h - --unsquashfs: unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o -- $(CC) unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o unsquash-4.o swap.o -lz -lpthread -lm -o $@ -+unsquashfs: $(UNSQUASHFS_OBJS) -+ $(CC) $(UNSQUASHFS_OBJS) -lz -lpthread -lm -o $@ - --unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h squashfs_compat.h global.h Makefile -+unsquashfs.o: unsquashfs.h unsquashfs.c squashfs_fs.h squashfs_swap.h \ -+ squashfs_compat.h global.h - --unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h global.h Makefile -+unsquash-1.o: unsquashfs.h unsquash-1.c squashfs_fs.h squashfs_compat.h \ -+ global.h - --unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h squashfs_compat.h global.h Makefile -+unsquash-2.o: unsquashfs.h unsquash-2.c unsquashfs.h squashfs_fs.h \ -+ squashfs_compat.h global.h - --unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h global.h Makefile -+unsquash-3.o: unsquashfs.h unsquash-3.c squashfs_fs.h squashfs_compat.h \ -+ global.h - --unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h global.h Makefile -+unsquash-4.o: unsquashfs.h unsquash-4.c squashfs_fs.h squashfs_swap.h \ -+ global.h - -+.PHONY: clean - clean: - -rm -f *.o mksquashfs unsquashfs - -+.PHONY: install - install: mksquashfs unsquashfs - mkdir -p $(INSTALL_DIR) - cp mksquashfs $(INSTALL_DIR) -diff -Naurp squashfs-tools/mksquashfs.c squashfs-tools-lzma/mksquashfs.c ---- squashfs-tools/mksquashfs.c 2009-04-05 21:22:48.000000000 +0000 -+++ squashfs-tools-lzma/mksquashfs.c 2009-10-20 04:03:38.000000000 +0000 -@@ -36,7 +36,6 @@ - #include - #include - #include --#include - #include - #include - #include -@@ -47,6 +46,7 @@ - #include - #include - #include -+#include - - #ifndef linux - #define __BYTE_ORDER BYTE_ORDER -@@ -64,6 +64,7 @@ - #include "global.h" - #include "sort.h" - #include "pseudo.h" -+#include "compressor.h" - - #ifdef SQUASHFS_TRACE - #define TRACE(s, args...) do { \ -@@ -245,10 +246,8 @@ char **source_path; - /* list of root directory entries read from original filesystem */ - int old_root_entries = 0; - struct old_root_entry_info { -- char name[SQUASHFS_NAME_LEN + 1]; -- squashfs_inode inode; -- int type; -- int inode_number; -+ char *name; -+ struct inode_info inode; - }; - struct old_root_entry_info *old_root_entry; - -@@ -371,10 +370,15 @@ int writer_buffer_size; - int reader_buffer_size; - int fragment_buffer_size; - -+/* compression operations structure */ -+static struct compressor *comp; -+char *comp_name = COMP_DEFAULT; -+ - char *read_from_disk(long long start, unsigned int avail_bytes); - void add_old_root_entry(char *name, squashfs_inode inode, int inode_number, - int type); --extern int read_super(int fd, squashfs_super_block *sBlk, char *source); -+extern struct compressor *read_super(int fd, squashfs_super_block *sBlk, -+ char *source); - extern long long read_filesystem(char *root_name, int fd, - squashfs_super_block *sBlk, char **cinode_table, char **data_cache, - char **cdirectory_table, char **directory_data_cache, -@@ -831,83 +835,32 @@ void sigalrm_handler() - } - - --unsigned int mangle2(z_stream **strm, char *d, char *s, int size, -+int mangle2(void **strm, char *d, char *s, int size, - int block_size, int uncompressed, int data_block) - { -- unsigned long c_byte; -- unsigned int res; -- z_stream *stream = *strm; -- -- if(uncompressed) -- goto notcompressed; -- -- if(stream == NULL) { -- if((stream = *strm = malloc(sizeof(z_stream))) == NULL) -- BAD_ERROR("mangle::compress failed, not enough " -- "memory\n"); -- -- stream->zalloc = Z_NULL; -- stream->zfree = Z_NULL; -- stream->opaque = 0; -- -- if((res = deflateInit(stream, 9)) != Z_OK) { -- if(res == Z_MEM_ERROR) -- BAD_ERROR("zlib::compress failed, not enough " -- "memory\n"); -- else if(res == Z_STREAM_ERROR) -- BAD_ERROR("zlib::compress failed, not a valid " -- "compression level\n"); -- else if(res == Z_VERSION_ERROR) -- BAD_ERROR("zlib::compress failed, incorrect " -- "zlib version\n"); -- else -- BAD_ERROR("zlib::compress failed, unknown " -- "error %d\n", res); -- } -- } else if((res = deflateReset(stream)) != Z_OK) { -- if(res == Z_STREAM_ERROR) -- BAD_ERROR("zlib::compress failed, stream state " -- "inconsistent\n"); -- else -- BAD_ERROR("zlib::compress failed, unknown error %d\n", -- res); -- } -+ int error, c_byte = 0; - -- stream->next_in = (unsigned char *) s; -- stream->avail_in = size; -- stream->next_out = (unsigned char *) d; -- stream->avail_out = block_size; -- -- res = deflate(stream, Z_FINISH); -- if(res != Z_STREAM_END && res != Z_OK) { -- if(res == Z_STREAM_ERROR) -- BAD_ERROR("zlib::compress failed, stream state " -- "inconsistent\n"); -- else if(res == Z_BUF_ERROR) -- BAD_ERROR("zlib::compress failed, no progress possible" -- "\n"); -- else -- BAD_ERROR("zlib::compress failed, unknown error %d\n", -- res); -+ if(!uncompressed) { -+ c_byte = comp->compress(strm, d, s, size, block_size, &error); -+ if(c_byte == -1) -+ BAD_ERROR("mangle2:: %s compress failed with error " -+ "code %d\n", comp->name, error); - } - -- c_byte = stream->total_out; -- -- if(res != Z_STREAM_END || c_byte >= size) { --notcompressed: -+ if(c_byte == 0 || c_byte >= size) { - memcpy(d, s, size); - return size | (data_block ? SQUASHFS_COMPRESSED_BIT_BLOCK : - SQUASHFS_COMPRESSED_BIT); - } - -- return (unsigned int) c_byte; -+ return c_byte; - } - - --unsigned int mangle(char *d, char *s, int size, int block_size, -+int mangle(char *d, char *s, int size, int block_size, - int uncompressed, int data_block) - { -- static z_stream *stream = NULL; -+ static void *stream = NULL; - - return mangle2(&stream, d, s, size, block_size, uncompressed, - data_block); -@@ -1660,8 +1613,7 @@ struct file_buffer *get_fragment(struct - pthread_mutex_unlock(&fragment_mutex); - - if(SQUASHFS_COMPRESSED_BLOCK(disk_fragment->size)) { -- int res; -- unsigned long bytes = block_size; -+ int error, res; - char *data; - - if(compressed_buffer) -@@ -1669,19 +1621,11 @@ struct file_buffer *get_fragment(struct - else - data = read_from_disk(start_block, size); - -- res = uncompress((unsigned char *) buffer->data, &bytes, -- (const unsigned char *) data, size); -- if(res != Z_OK) { -- if(res == Z_MEM_ERROR) -- BAD_ERROR("zlib::uncompress failed, not enough " -- "memory\n"); -- else if(res == Z_BUF_ERROR) -- BAD_ERROR("zlib::uncompress failed, not enough " -- "room in output buffer\n"); -- else -- BAD_ERROR("zlib::uncompress failed," -- " unknown error %d\n", res); -- } -+ res = comp->uncompress(buffer->data, data, size, block_size, -+ &error); -+ if(res == -1) -+ BAD_ERROR("%s uncompress failed with error code %d\n", -+ comp->name, error); - } else if(compressed_buffer) - memcpy(buffer->data, compressed_buffer->data, size); - else -@@ -1733,9 +1677,7 @@ void unlock_fragments() - entry->buffer->block = bytes; - bytes += compressed_size; - fragments_outstanding --; -- pthread_mutex_unlock(&fragment_mutex); - queue_put(to_writer, entry->buffer); -- pthread_mutex_lock(&fragment_mutex); - TRACE("fragment_locked writing fragment %d, compressed size %d" - "\n", entry->fragment, compressed_size); - free(entry); -@@ -1758,6 +1700,8 @@ int add_pending_fragment(struct file_buf - pthread_mutex_lock(&fragment_mutex); - insert_fragment_list(&frag_locked_list, entry); - pthread_mutex_unlock(&fragment_mutex); -+ -+ return TRUE; - } - - -@@ -1824,7 +1768,9 @@ long long generic_write_table(int length - unsigned short c_byte; - char cbuffer[(SQUASHFS_METADATA_SIZE << 2) + 2]; - -+#ifdef SQUASHFS_TRACE - long long obytes = bytes; -+#endif - - for(i = 0; i < meta_blocks; i++) { - int avail_bytes = length > SQUASHFS_METADATA_SIZE ? -@@ -2170,11 +2116,85 @@ struct file_info *duplicate(long long fi - } - - -+static int seq = 0; -+void reader_read_process(struct dir_ent *dir_ent) -+{ -+ struct file_buffer *prev_buffer = NULL, *file_buffer; -+ int status, res, byte, count = 0; -+ int file = get_pseudo_file(dir_ent->inode->pseudo_id)->fd; -+ int child = get_pseudo_file(dir_ent->inode->pseudo_id)->child; -+ long long bytes = 0; -+ -+ while(1) { -+ file_buffer = cache_get(reader_buffer, 0, 0); -+ file_buffer->sequence = seq ++; -+ -+ byte = read_bytes(file, file_buffer->data, block_size); -+ if(byte == -1) -+ goto read_err; -+ -+ file_buffer->size = byte; -+ file_buffer->file_size = -1; -+ file_buffer->block = count ++; -+ file_buffer->error = FALSE; -+ file_buffer->fragment = FALSE; -+ bytes += byte; -+ -+ if(byte == 0) -+ break; -+ -+ /* -+ * Update estimated_uncompressed block count. This is done -+ * on every block rather than waiting for all blocks to be -+ * read incase write_file_process() is running in parallel -+ * with this. Otherwise cur uncompressed block count may -+ * get ahead of the total uncompressed block count. -+ */ -+ estimated_uncompressed ++; -+ -+ if(prev_buffer) -+ queue_put(from_reader, prev_buffer); -+ prev_buffer = file_buffer; -+ } -+ -+ /* -+ * Update inode file size now that the size of the dynamic pseudo file -+ * is known. This is needed for the -info option. -+ */ -+ dir_ent->inode->buf.st_size = bytes; -+ -+ res = waitpid(child, &status, 0); -+ if(res == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) -+ goto read_err; -+ -+ if(prev_buffer == NULL) -+ prev_buffer = file_buffer; -+ else { -+ cache_block_put(file_buffer); -+ seq --; -+ } -+ prev_buffer->file_size = bytes; -+ prev_buffer->fragment = !no_fragments && -+ (count == 2 || always_use_fragments) && (byte < block_size); -+ queue_put(from_reader, prev_buffer); -+ -+ return; -+ -+read_err: -+ if(prev_buffer) { -+ cache_block_put(file_buffer); -+ seq --; -+ file_buffer = prev_buffer; -+ } -+ file_buffer->error = TRUE; -+ queue_put(from_deflate, file_buffer); -+} -+ -+ - void reader_read_file(struct dir_ent *dir_ent) - { - struct stat *buf = &dir_ent->inode->buf, buf2; - struct file_buffer *file_buffer; -- static int index = 0; - int blocks, byte, count, expected, file, frag_block; - long long bytes, read_size; - -@@ -2202,7 +2222,7 @@ again: - if(file_buffer) - queue_put(from_reader, file_buffer); - file_buffer = cache_get(reader_buffer, 0, 0); -- file_buffer->sequence = index ++; -+ file_buffer->sequence = seq ++; - - byte = file_buffer->size = read_bytes(file, file_buffer->data, - block_size); -@@ -2238,7 +2258,7 @@ again: - - read_err: - file_buffer = cache_get(reader_buffer, 0, 0); -- file_buffer->sequence = index ++; -+ file_buffer->sequence = seq ++; - read_err2: - file_buffer->error = TRUE; - queue_put(from_deflate, file_buffer); -@@ -2262,9 +2282,14 @@ void reader_scan(struct dir_info *dir) { - for(i = 0; i < dir->count; i++) { - struct dir_ent *dir_ent = dir->list[i]; - struct stat *buf = &dir_ent->inode->buf; -- if(dir_ent->data) -+ if(dir_ent->inode->root_entry) - continue; - -+ if(dir_ent->inode->pseudo_file) { -+ reader_read_process(dir_ent); -+ continue; -+ } -+ - switch(buf->st_mode & S_IFMT) { - case S_IFREG: - reader_read_file(dir_ent); -@@ -2365,7 +2390,7 @@ int all_zero(struct file_buffer *file_bu - - void *deflator(void *arg) - { -- z_stream *stream = NULL; -+ void *stream = NULL; - int oldstate; - - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); -@@ -2402,7 +2427,7 @@ void *deflator(void *arg) - - void *frag_deflator(void *arg) - { -- z_stream *stream = NULL; -+ void *stream = NULL; - int oldstate; - - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); -@@ -2426,8 +2451,8 @@ void *frag_deflator(void *arg) - write_buffer->block = bytes; - bytes += compressed_size; - fragments_outstanding --; -- pthread_mutex_unlock(&fragment_mutex); - queue_put(to_writer, write_buffer); -+ pthread_mutex_unlock(&fragment_mutex); - TRACE("Writing fragment %lld, uncompressed size %d, " - "compressed size %d\n", file_buffer->block, - file_buffer->size, compressed_size); -@@ -2674,6 +2699,98 @@ void write_file_frag(squashfs_inode *ino - } - - -+int write_file_process(squashfs_inode *inode, struct dir_ent *dir_ent, -+ struct file_buffer *read_buffer, int *duplicate_file) -+{ -+ long long read_size, file_bytes, start; -+ struct fragment *fragment; -+ unsigned int *block_list = NULL; -+ int block = 0, status; -+ long long sparse = 0; -+ struct file_buffer *fragment_buffer = NULL; -+ -+ *duplicate_file = FALSE; -+ -+ lock_fragments(); -+ -+ file_bytes = 0; -+ start = bytes; -+ while (1) { -+ read_size = read_buffer->file_size; -+ if(read_buffer->fragment && read_buffer->c_byte) -+ fragment_buffer = read_buffer; -+ else { -+ block_list = realloc(block_list, (block + 1) * -+ sizeof(unsigned int)); -+ if(block_list == NULL) -+ BAD_ERROR("Out of memory allocating block_list" -+ "\n"); -+ block_list[block ++] = read_buffer->c_byte; -+ if(read_buffer->c_byte) { -+ read_buffer->block = bytes; -+ bytes += read_buffer->size; -+ cache_rehash(read_buffer, read_buffer->block); -+ file_bytes += read_buffer->size; -+ queue_put(to_writer, read_buffer); -+ } else { -+ sparse += read_buffer->size; -+ cache_block_put(read_buffer); -+ } -+ } -+ inc_progress_bar(); -+ -+ if(read_size != -1) -+ break; -+ -+ read_buffer = get_file_buffer(from_deflate); -+ if(read_buffer->error) -+ goto read_err; -+ } -+ -+ unlock_fragments(); -+ fragment = get_and_fill_fragment(fragment_buffer); -+ cache_block_put(fragment_buffer); -+ -+ if(duplicate_checking) -+ add_non_dup(read_size, file_bytes, block_list, start, fragment, -+ 0, 0, FALSE); -+ file_count ++; -+ total_bytes += read_size; -+ -+ if(read_size < (1LL << 32) && start < (1LL << 32) && sparse == 0) -+ create_inode(inode, dir_ent, SQUASHFS_FILE_TYPE, read_size, -+ start, block, block_list, fragment, NULL, 0); -+ else -+ create_inode(inode, dir_ent, SQUASHFS_LREG_TYPE, read_size, -+ start, block, block_list, fragment, NULL, sparse); -+ -+ if(duplicate_checking == FALSE) -+ free(block_list); -+ -+ return 0; -+ -+read_err: -+ cur_uncompressed -= block; -+ status = read_buffer->error; -+ bytes = start; -+ if(!block_device) { -+ int res; -+ -+ queue_put(to_writer, NULL); -+ if(queue_get(from_writer) != 0) -+ EXIT_MKSQUASHFS(); -+ res = ftruncate(fd, bytes); -+ if(res != 0) -+ BAD_ERROR("Failed to truncate dest file because %s\n", -+ strerror(errno)); -+ } -+ unlock_fragments(); -+ free(block_list); -+ cache_block_put(read_buffer); -+ return status; -+} -+ -+ - int write_file_blocks(squashfs_inode *inode, struct dir_ent *dir_ent, - long long read_size, struct file_buffer *read_buffer, - int *duplicate_file) -@@ -2941,7 +3058,10 @@ again: - - read_size = read_buffer->file_size; - -- if(read_size == 0) { -+ if(read_size == -1) -+ status = write_file_process(inode, dir_ent, read_buffer, -+ duplicate_file); -+ else if(read_size == 0) { - write_file_empty(inode, dir_ent, duplicate_file); - cache_block_put(read_buffer); - } else if(read_buffer->fragment && read_buffer->c_byte) -@@ -3036,6 +3156,8 @@ struct inode_info *lookup_inode(struct s - - memcpy(&inode->buf, buf, sizeof(struct stat)); - inode->read = FALSE; -+ inode->root_entry = FALSE; -+ inode->pseudo_file = FALSE; - inode->inode = SQUASHFS_INVALID_BLK; - inode->nlink = 1; - -@@ -3056,7 +3178,7 @@ struct inode_info *lookup_inode(struct s - - - inline void add_dir_entry(char *name, char *pathname, struct dir_info *sub_dir, -- struct inode_info *inode_info, void *data, struct dir_info *dir) -+ struct inode_info *inode_info, struct dir_info *dir) - { - if((dir->count % DIR_ENTRIES) == 0) { - dir->list = realloc(dir->list, (dir->count + DIR_ENTRIES) * -@@ -3075,8 +3197,7 @@ inline void add_dir_entry(char *name, ch - NULL; - dir->list[dir->count]->inode = inode_info; - dir->list[dir->count]->dir = sub_dir; -- dir->list[dir->count]->our_dir = dir; -- dir->list[dir->count++]->data = data; -+ dir->list[dir->count++]->our_dir = dir; - dir->byte_count += strlen(name) + sizeof(squashfs_dir_entry); - } - -@@ -3128,10 +3249,10 @@ int scan1_encomp_readdir(char *pathname, - - if(dir->count < old_root_entries) - for(i = 0; i < old_root_entries; i++) { -- if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) -+ if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) - dir->directory_count ++; -- add_dir_entry(old_root_entry[i].name, "", NULL, NULL, -- &old_root_entry[i], dir); -+ add_dir_entry(old_root_entry[i].name, "", NULL, -+ &old_root_entry[i].inode, dir); - } - - while(index < source) { -@@ -3167,10 +3288,10 @@ int scan1_single_readdir(char *pathname, - - if(dir->count < old_root_entries) - for(i = 0; i < old_root_entries; i++) { -- if(old_root_entry[i].type == SQUASHFS_DIR_TYPE) -+ if(old_root_entry[i].inode.type == SQUASHFS_DIR_TYPE) - dir->directory_count ++; -- add_dir_entry(old_root_entry[i].name, "", NULL, NULL, -- &old_root_entry[i], dir); -+ add_dir_entry(old_root_entry[i].name, "", NULL, -+ &old_root_entry[i].inode, dir); - } - - if((d_name = readdir(dir->linuxdir)) != NULL) { -@@ -3215,7 +3336,7 @@ struct dir_ent *scan2_readdir(struct dir - int current_count; - - while((current_count = dir_info->current_count++) < dir_info->count) -- if(dir_info->list[current_count]->data) -+ if(dir_info->list[current_count]->inode->root_entry) - continue; - else - return dir_info->list[current_count]; -@@ -3240,11 +3361,11 @@ struct dir_ent *scan3_readdir(struct dir - int current_count; - - while((current_count = dir_info->current_count++) < dir_info->count) -- if(dir_info->list[current_count]->data) -- add_dir(dir_info->list[current_count]->data->inode, -- dir_info->list[current_count]->data->inode_number, -+ if(dir_info->list[current_count]->inode->root_entry) -+ add_dir(dir_info->list[current_count]->inode->inode, -+ dir_info->list[current_count]->inode->inode_number, - dir_info->list[current_count]->name, -- dir_info->list[current_count]->data->type, dir); -+ dir_info->list[current_count]->inode->type, dir); - else - return dir_info->list[current_count]; - return NULL; -@@ -3313,7 +3434,6 @@ void dir_scan(squashfs_inode *inode, cha - dir_ent->name = dir_ent->pathname = strdup(pathname); - dir_ent->dir = dir_info; - dir_ent->our_dir = NULL; -- dir_ent->data = NULL; - dir_info->dir_ent = dir_ent; - - if(sorted) -@@ -3383,7 +3503,7 @@ struct dir_info *dir_scan1(char *pathnam - sub_dir = NULL; - - add_dir_entry(dir_name, filename, sub_dir, lookup_inode(&buf), -- NULL, dir); -+ dir); - } - - scan1_freedir(dir); -@@ -3399,7 +3519,7 @@ struct dir_info *dir_scan2(struct dir_in - struct dir_ent *dir_ent; - struct pseudo_entry *pseudo_ent; - struct stat buf; -- static pseudo_ino = 1; -+ static int pseudo_ino = 1; - - if(dir == NULL && (dir = scan1_opendir("")) == NULL) - return NULL; -@@ -3415,6 +3535,29 @@ struct dir_info *dir_scan2(struct dir_in - - while((pseudo_ent = pseudo_readdir(pseudo)) != NULL) { - dir_ent = scan2_lookup(dir, pseudo_ent->name); -+ if(pseudo_ent->dev->type == 's') { -+ struct stat *buf; -+ if(dir_ent == NULL) { -+ ERROR("Pseudo set file \"%s\" does not exist " -+ "in source filesystem. Ignoring\n", -+ pseudo_ent->pathname); -+ continue; -+ } -+ if(dir_ent->inode->root_entry) { -+ ERROR("Pseudo set file \"%s\" is a pre-existing" -+ " file in the filesystem being appended" -+ " to. It cannot be modified. " -+ "Ignoring!\n", pseudo_ent->pathname); -+ continue; -+ } -+ buf = &dir_ent->inode->buf; -+ buf->st_mode = (buf->st_mode & S_IFMT) | -+ pseudo_ent->dev->mode; -+ buf->st_uid = pseudo_ent->dev->uid; -+ buf->st_gid = pseudo_ent->dev->gid; -+ continue; -+ } -+ - if(dir_ent) { - ERROR("Pseudo file \"%s\" exists in source filesystem " - "\"%s\"\n", pseudo_ent->pathname, -@@ -3444,8 +3587,29 @@ struct dir_info *dir_scan2(struct dir_in - buf.st_mtime = time(NULL); - buf.st_ino = pseudo_ino ++; - -- add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, sub_dir, -- lookup_inode(&buf), NULL, dir); -+ if(pseudo_ent->dev->type == 'f') { -+#ifdef USE_TMP_FILE -+ struct stat buf2; -+ int res = stat(pseudo_ent->dev->filename, &buf2); -+ if(res == -1) { -+ ERROR("Stat on pseudo file \"%s\" failed, " -+ "skipping...", pseudo_ent->pathname); -+ continue; -+ } -+ buf.st_size = buf2.st_size; -+ add_dir_entry(pseudo_ent->name, -+ pseudo_ent->dev->filename, sub_dir, -+ lookup_inode(&buf), dir); -+#else -+ struct inode_info *inode = lookup_inode(&buf); -+ inode->pseudo_id = pseudo_ent->dev->pseudo_id; -+ inode->pseudo_file = TRUE; -+ add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, -+ sub_dir, inode, dir); -+#endif -+ } else -+ add_dir_entry(pseudo_ent->name, pseudo_ent->pathname, -+ sub_dir, lookup_inode(&buf), dir); - } - - scan2_freedir(dir); -@@ -3482,8 +3646,9 @@ void dir_scan3(squashfs_inode *inode, st - &duplicate_file); - INFO("file %s, uncompressed size %lld " - "bytes %s\n", filename, -- buf->st_size, duplicate_file ? -- "DUPLICATE" : ""); -+ (long long) buf->st_size, -+ duplicate_file ? "DUPLICATE" : -+ ""); - break; - - case S_IFDIR: -@@ -3557,6 +3722,7 @@ void dir_scan3(squashfs_inode *inode, st - INFO("file %s, uncompressed " - "size %lld bytes LINK" - "\n", filename, -+ (long long) - buf->st_size); - break; - case SQUASHFS_SYMLINK_TYPE: -@@ -3667,10 +3833,11 @@ void add_old_root_entry(char *name, squa - BAD_ERROR("Out of memory in old root directory entries " - "reallocation\n"); - -- strcpy(old_root_entry[old_root_entries].name, name); -- old_root_entry[old_root_entries].inode = inode; -- old_root_entry[old_root_entries].inode_number = inode_number; -- old_root_entry[old_root_entries++].type = type; -+ old_root_entry[old_root_entries].name = strdup(name); -+ old_root_entry[old_root_entries].inode.inode = inode; -+ old_root_entry[old_root_entries].inode.inode_number = inode_number; -+ old_root_entry[old_root_entries].inode.type = type; -+ old_root_entry[old_root_entries++].inode.root_entry = TRUE; - } - - -@@ -4172,26 +4339,28 @@ int main(int argc, char *argv[]) - source_path = argv + 1; - source = i - 2; - for(; i < argc; i++) { -- if(strcmp(argv[i], "-pf") == 0) { -+ if(strcmp(argv[i], "-comp") == 0) { - if(++i == argc) { -- ERROR("%s: -pf missing filename\n", argv[0]); -+ ERROR("%s: -comp missing compression type\n", -+ argv[0]); - exit(1); - } -- if(read_pseudo_file(&pseudo, argv[i]) == FALSE) { -- ERROR("Failed to parse pseudo file \"%s\"\n", -- argv[i]); -+ comp_name = argv[i]; -+ } else if(strcmp(argv[i], "-pf") == 0) { -+ if(++i == argc) { -+ ERROR("%s: -pf missing filename\n", argv[0]); - exit(1); - } -+ if(read_pseudo_file(&pseudo, argv[i]) == FALSE) -+ exit(1); - } else if(strcmp(argv[i], "-p") == 0) { - if(++i == argc) { - ERROR("%s: -p missing pseudo file definition\n", - argv[0]); - exit(1); - } -- if(read_pseudo_def(&pseudo, argv[i]) == FALSE) { -- ERROR("Failed to parse pseudo definition\n"); -+ if(read_pseudo_def(&pseudo, argv[i]) == FALSE) - exit(1); -- } - } else if(strcmp(argv[i], "-recover") == 0) { - if(++i == argc) { - ERROR("%s: -recover missing recovery file\n", -@@ -4394,34 +4563,16 @@ int main(int argc, char *argv[]) - printOptions: - ERROR("SYNTAX:%s source1 source2 ... dest [options] " - "[-e list of exclude\ndirs/files]\n", argv[0]); -- ERROR("\nOptions are\n"); -- ERROR("-version\t\tprint version, licence and " -- "copyright message\n"); -- ERROR("-recover \t\trecover filesystem data " -- "using recovery file \n"); -- ERROR("-no-recovery\t\tdon't generate a recovery " -- "file\n"); -- ERROR("-info\t\t\tprint files written to filesystem\n"); -- ERROR("-no-exports\t\tdon't make the filesystem " -- "exportable via NFS\n"); -- ERROR("-no-progress\t\tdon't display the progress " -- "bar\n"); -- ERROR("-no-sparse\t\tdon't detect sparse files\n"); -+ ERROR("\nFilesystem build options:\n"); -+ ERROR("-comp \t\tselect compression\n"); -+ ERROR("\t\t\tCompressors available:\n"); -+ display_compressors("\t\t\t", COMP_DEFAULT); - ERROR("-b \t\tset data block to " - ". Default %d bytes\n", - SQUASHFS_FILE_SIZE); -- ERROR("-processors \tUse processors." -- " By default will use number of\n"); -- ERROR("\t\t\tprocessors available\n"); -- ERROR("-read-queue \tSet input queue to " -- "Mbytes. Default %d Mbytes\n", -- READER_BUFFER_DEFAULT); -- ERROR("-write-queue \tSet output queue to " -- "Mbytes. Default %d Mbytes\n", -- WRITER_BUFFER_DEFAULT); -- ERROR("-fragment-queue \tSet fagment queue to " -- " Mbytes. Default %d Mbytes\n", -- FRAGMENT_BUFFER_DEFAULT); -+ ERROR("-no-exports\t\tdon't make the filesystem " -+ "exportable via NFS\n"); -+ ERROR("-no-sparse\t\tdon't detect sparse files\n"); - ERROR("-noI\t\t\tdo not compress inode table\n"); - ERROR("-noD\t\t\tdo not compress data blocks\n"); - ERROR("-noF\t\t\tdo not compress fragment blocks\n"); -@@ -4430,13 +4581,34 @@ printOptions: - "files larger than block size\n"); - ERROR("-no-duplicates\t\tdo not perform duplicate " - "checking\n"); -- ERROR("-noappend\t\tdo not append to existing " -- "filesystem\n"); -+ ERROR("-all-root\t\tmake all files owned by root\n"); -+ ERROR("-force-uid uid\t\tset all file uids to uid\n"); -+ ERROR("-force-gid gid\t\tset all file gids to gid\n"); -+ ERROR("-nopad\t\t\tdo not pad filesystem to a multiple " -+ "of 4K\n"); - ERROR("-keep-as-directory\tif one source directory is " - "specified, create a root\n"); - ERROR("\t\t\tdirectory containing that directory, " - "rather than the\n"); - ERROR("\t\t\tcontents of the directory\n"); -+ ERROR("\nFilesystem filter options:\n"); -+ ERROR("-p \tAdd pseudo file definition\n"); -+ ERROR("-pf \tAdd list of pseudo file definitions\n"); -+ ERROR("-sort \tsort files according to " -+ "priorities in . One\n"); -+ ERROR("\t\t\tfile or dir with priority per line. " -+ "Priority -32768 to\n"); -+ ERROR("\t\t\t32767, default priority 0\n"); -+ ERROR("-ef \tlist of exclude dirs/files." -+ " One per line\n"); -+ ERROR("-wildcards\t\tAllow extended shell wildcards " -+ "(globbing) to be used in\n\t\t\texclude " -+ "dirs/files\n"); -+ ERROR("-regex\t\t\tAllow POSIX regular expressions to " -+ "be used in exclude\n\t\t\tdirs/files\n"); -+ ERROR("\nFilesystem append options:\n"); -+ ERROR("-noappend\t\tdo not append to existing " -+ "filesystem\n"); - ERROR("-root-becomes \twhen appending source " - "files/directories, make the\n"); - ERROR("\t\t\toriginal root become a subdirectory in " -@@ -4444,11 +4616,29 @@ printOptions: - ERROR("\t\t\tcalled , rather than adding the new " - "source items\n"); - ERROR("\t\t\tto the original root\n"); -- ERROR("-all-root\t\tmake all files owned by root\n"); -- ERROR("-force-uid uid\t\tset all file uids to uid\n"); -- ERROR("-force-gid gid\t\tset all file gids to gid\n"); -- ERROR("-nopad\t\t\tdo not pad filesystem to a multiple " -- "of 4K\n"); -+ ERROR("\nMksquashfs runtime options:\n"); -+ ERROR("-version\t\tprint version, licence and " -+ "copyright message\n"); -+ ERROR("-recover \t\trecover filesystem data " -+ "using recovery file \n"); -+ ERROR("-no-recovery\t\tdon't generate a recovery " -+ "file\n"); -+ ERROR("-info\t\t\tprint files written to filesystem\n"); -+ ERROR("-no-progress\t\tdon't display the progress " -+ "bar\n"); -+ ERROR("-processors \tUse processors." -+ " By default will use number of\n"); -+ ERROR("\t\t\tprocessors available\n"); -+ ERROR("-read-queue \tSet input queue to " -+ "Mbytes. Default %d Mbytes\n", -+ READER_BUFFER_DEFAULT); -+ ERROR("-write-queue \tSet output queue to " -+ "Mbytes. Default %d Mbytes\n", -+ WRITER_BUFFER_DEFAULT); -+ ERROR("-fragment-queue \tSet fagment queue to " -+ " Mbytes. Default %d Mbytes\n", -+ FRAGMENT_BUFFER_DEFAULT); -+ ERROR("\nMiscellaneous options:\n"); - ERROR("-root-owned\t\talternative name for -all-root" - "\n"); - ERROR("-noInodeCompression\talternative name for -noI" -@@ -4457,20 +4647,6 @@ printOptions: - "\n"); - ERROR("-noFragmentCompression\talternative name for " - "-noF\n"); -- ERROR("-sort \tsort files according to " -- "priorities in . One\n"); -- ERROR("\t\t\tfile or dir with priority per line. " -- "Priority -32768 to\n"); -- ERROR("\t\t\t32767, default priority 0\n"); -- ERROR("-ef \tlist of exclude dirs/files." -- " One per line\n"); -- ERROR("-wildcards\t\tAllow extended shell wildcards " -- "(globbing) to be used in\n\t\t\texclude " -- "dirs/files\n"); -- ERROR("-regex\t\t\tAllow POSIX regular expressions to " -- "be used in exclude\n\t\t\tdirs/files\n"); -- ERROR("-p \tAdd pseudo file definition\n"); -- ERROR("-pf \tAdd list of pseudo file definitions\n"); - exit(1); - } - } -@@ -4548,11 +4724,10 @@ printOptions: - fclose(fd); - } else if(strcmp(argv[i], "-e") == 0) - break; -- else if(strcmp(argv[i], "-b") == 0 || -- strcmp(argv[i], "-root-becomes") == 0 || -+ else if(strcmp(argv[i], "-root-becomes") == 0 || - strcmp(argv[i], "-sort") == 0 || - strcmp(argv[i], "-pf") == 0 || -- strcmp(argv[i], "-p") == 0) -+ strcmp(argv[i], "-comp") == 0) - i++; - - if(i != argc) { -@@ -4574,11 +4749,10 @@ printOptions: - sorted ++; - } else if(strcmp(argv[i], "-e") == 0) - break; -- else if(strcmp(argv[i], "-b") == 0 || -- strcmp(argv[i], "-root-becomes") == 0 || -+ else if(strcmp(argv[i], "-root-becomes") == 0 || - strcmp(argv[i], "-ef") == 0 || - strcmp(argv[i], "-pf") == 0 || -- strcmp(argv[i], "-p") == 0) -+ strcmp(argv[i], "-comp") == 0) - i++; - - #ifdef SQUASHFS_TRACE -@@ -4586,7 +4760,8 @@ printOptions: - #endif - - if(!delete) { -- if(read_super(fd, &sBlk, argv[source + 1]) == 0) { -+ comp = read_super(fd, &sBlk, argv[source + 1]); -+ if(comp == NULL) { - ERROR("Failed to read existing filesystem - will not " - "overwrite - ABORTING!\n"); - ERROR("To force Mksquashfs to write to this block " -@@ -4603,6 +4778,15 @@ printOptions: - always_use_fragments = SQUASHFS_ALWAYS_FRAGMENTS(sBlk.flags); - duplicate_checking = SQUASHFS_DUPLICATES(sBlk.flags); - exportable = SQUASHFS_EXPORTABLE(sBlk.flags); -+ } else { -+ comp = lookup_compressor(comp_name); -+ if(!comp->supported) { -+ ERROR("FATAL_ERROR: Compressor \"%s\" is not " -+ "supported!\n", comp_name); -+ ERROR("Compressors available:\n"); -+ display_compressors("", COMP_DEFAULT); -+ EXIT_MKSQUASHFS(); -+ } - } - - initialise_threads(); -@@ -4648,8 +4832,8 @@ printOptions: - "size %d\n", SQUASHFS_MAJOR, s_minor, argv[source + 1], - block_size); - printf("All -b, -noI, -noD, -noF, no-duplicates, no-fragments, " -- "-always-use-fragments and -exportable options ignored" -- "\n"); -+ "-always-use-fragments,\n-exportable and -comp options " -+ "ignored\n"); - printf("\nIf appending is not wanted, please re-run with " - "-noappend specified!\n\n"); - -@@ -4803,8 +4987,7 @@ restore_filesystem: - - sBlk.bytes_used = bytes; - -- /* Only compression supported */ -- sBlk.compression = ZLIB_COMPRESSION; -+ sBlk.compression = comp->id; - - /* Xattrs are not currently supported */ - sBlk.xattr_table_start = SQUASHFS_INVALID_BLK; -@@ -4820,6 +5003,8 @@ restore_filesystem: - - close(fd); - -+ delete_pseudo_files(); -+ - if(recovery_file[0] != '\0') - unlink(recovery_file); - -@@ -4827,9 +5012,9 @@ restore_filesystem: - * sizeof(unsigned short) + guid_count * sizeof(unsigned short) + - sizeof(squashfs_super_block); - -- printf("\n%sSquashfs %d.%d filesystem, data block size %d\n", -- exportable ? "Exportable " : "", SQUASHFS_MAJOR, SQUASHFS_MINOR, -- block_size); -+ printf("\n%sSquashfs %d.%d filesystem, %s compressed, data block size" -+ " %d\n", exportable ? "Exportable " : "", SQUASHFS_MAJOR, -+ SQUASHFS_MINOR, comp->name, block_size); - printf("\t%s data, %s metadata, %s fragments\n", - noD ? "uncompressed" : "compressed", noI ? "uncompressed" : - "compressed", no_fragments ? "no" : noF ? "uncompressed" : -diff -Naurp squashfs-tools/pseudo.c squashfs-tools-lzma/pseudo.c ---- squashfs-tools/pseudo.c 2009-04-05 02:01:58.000000000 +0000 -+++ squashfs-tools-lzma/pseudo.c 2009-10-20 04:03:38.000000000 +0000 -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - #include "pseudo.h" - -@@ -55,6 +56,9 @@ - #define TRUE 1 - #define FALSE 0 - -+struct pseudo_dev **pseudo_file = NULL; -+int pseudo_count = 0; -+ - static void dump_pseudo(struct pseudo *pseudo, char *string) - { - int i; -@@ -99,7 +103,7 @@ struct pseudo *add_pseudo(struct pseudo - char *target, char *alltarget) - { - char targname[1024]; -- int i, error; -+ int i; - - target = get_component(target, targname); - -@@ -128,12 +132,8 @@ struct pseudo *add_pseudo(struct pseudo - if(target[0] == '\0') { - /* at leaf pathname component */ - pseudo->name[i].pseudo = NULL; -- pseudo->name[i].dev = malloc(sizeof(struct pseudo_dev)); -- if(pseudo->name[i].dev == NULL) -- BAD_ERROR("failed to allocate pseudo file\n"); - pseudo->name[i].pathname = strdup(alltarget); -- memcpy(pseudo->name[i].dev, pseudo_dev, -- sizeof(struct pseudo_dev)); -+ pseudo->name[i].dev = pseudo_dev; - } else { - /* recurse adding child components */ - pseudo->name[i].dev = NULL; -@@ -169,15 +169,9 @@ struct pseudo *add_pseudo(struct pseudo - if(target[0] == '\0') { - if(pseudo->name[i].dev == NULL && - pseudo_dev->type == 'd') { -- pseudo->name[i].dev = -- malloc(sizeof(struct pseudo_dev)); -- if(pseudo->name[i].dev == NULL) -- BAD_ERROR("failed to allocate " -- "pseudo file\n"); - pseudo->name[i].pathname = - strdup(alltarget); -- memcpy(pseudo->name[i].dev, pseudo_dev, -- sizeof(struct pseudo_dev)); -+ pseudo->name[i].dev = pseudo_dev; - } else - ERROR("%s already exists as a " - "directory. Ignoring %s!\n", -@@ -229,16 +223,113 @@ struct pseudo_entry *pseudo_readdir(stru - } - - -+int exec_file(char *command, struct pseudo_dev *dev) -+{ -+ int child, res; -+ static pid_t pid = -1; -+ int pipefd[2]; -+#ifdef USE_TMP_FILE -+ char filename[1024]; -+ int status; -+ static int number = 0; -+#endif -+ -+ if(pid == -1) -+ pid = getpid(); -+ -+#ifdef USE_TMP_FILE -+ sprintf(filename, "/tmp/squashfs_pseudo_%d_%d", pid, number ++); -+ pipefd[1] = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); -+ if(pipefd[1] == -1) { -+ printf("open failed\n"); -+ return -1; -+ } -+#else -+ res = pipe(pipefd); -+ if(res == -1) { -+ printf("pipe failed\n"); -+ return -1; -+ } -+#endif -+ -+ child = fork(); -+ if(child == -1) { -+ printf("fork failed\n"); -+ goto failed; -+ } -+ -+ if(child == 0) { -+ close(STDOUT_FILENO); -+ res = dup(pipefd[1]); -+ if(res == -1) { -+ printf("dup failed\n"); -+ exit(EXIT_FAILURE); -+ } -+ execl("/bin/sh", "sh", "-c", command, (char *) NULL); -+ printf("execl failed\n"); -+ exit(EXIT_FAILURE); -+ } -+ -+#ifdef USE_TMP_FILE -+ res = waitpid(child, &status, 0); -+ close(pipefd[1]); -+ if(res != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0) { -+ dev->filename = strdup(filename); -+ return 0; -+ } -+failed: -+ unlink(filename); -+ return -1; -+#else -+ close(pipefd[1]); -+ dev->fd = pipefd[0]; -+ dev->child = child; -+ return 0; -+failed: -+ return -1; -+#endif -+} -+ -+ -+void add_pseudo_file(struct pseudo_dev *dev) -+{ -+ pseudo_file = realloc(pseudo_file, (pseudo_count + 1) * -+ sizeof(struct pseudo_dev *)); -+ if(pseudo_file == NULL) -+ BAD_ERROR("Failed to realloc pseudo_file\n"); -+ -+ dev->pseudo_id = pseudo_count; -+ pseudo_file[pseudo_count ++] = dev; -+} -+ -+ -+void delete_pseudo_files() -+{ -+#ifdef USE_TMP_FILE -+ int i; -+ -+ for(i = 0; i < pseudo_count; i++) -+ unlink(pseudo_file[i]->filename); -+#endif -+} -+ -+ -+struct pseudo_dev *get_pseudo_file(int pseudo_id) -+{ -+ return pseudo_file[pseudo_id]; -+} -+ -+ - int read_pseudo_def(struct pseudo **pseudo, char *def) - { -- int n; -+ int n, bytes; - unsigned int major = 0, minor = 0, mode; - char filename[2048], type, suid[100], sgid[100], *ptr; - long long uid, gid; -- struct pseudo_dev dev; -+ struct pseudo_dev *dev; - -- n = sscanf(def, "%s %c %o %s %s %u %u", filename, &type, &mode, suid, sgid, -- &major, &minor); -+ n = sscanf(def, "%s %c %o %s %s %n", filename, &type, &mode, suid, -+ sgid, &bytes); - - if(n < 5) { - ERROR("Not enough or invalid arguments in pseudo file " -@@ -249,7 +340,9 @@ int read_pseudo_def(struct pseudo **pseu - switch(type) { - case 'b': - case 'c': -- if(n < 7) { -+ n = sscanf(def + bytes, "%u %u", &major, &minor); -+ -+ if(n < 2) { - ERROR("Not enough or invalid arguments in pseudo file " - "definition\n"); - goto error; -@@ -265,47 +358,15 @@ int read_pseudo_def(struct pseudo **pseu - goto error; - } - -- /* fall through */ -- case 'd': -- if(mode > 0777) { -- ERROR("Mode %o out of range\n", mode); -+ case 'f': -+ if(def[bytes] == '\0') { -+ ERROR("Not enough arguments in pseudo file " -+ "definition\n"); - goto error; -- } -- -- uid = strtoll(suid, &ptr, 10); -- if(*ptr == '\0') { -- if(uid < 0 || uid > ((1LL << 32) - 1)) { -- ERROR("Uid %s out of range\n", suid); -- goto error; -- } -- } else { -- struct passwd *pwuid = getpwnam(suid); -- if(pwuid) -- uid = pwuid->pw_uid; -- else { -- ERROR("Uid %s invalid uid or unknown user\n", -- suid); -- goto error; -- } -- } -- -- gid = strtoll(sgid, &ptr, 10); -- if(*ptr == '\0') { -- if(gid < 0 || gid > ((1LL << 32) - 1)) { -- ERROR("Gid %s out of range\n", sgid); -- goto error; -- } -- } else { -- struct group *grgid = getgrnam(sgid); -- if(grgid) -- gid = grgid->gr_gid; -- else { -- ERROR("Gid %s invalid uid or unknown user\n", -- sgid); -- goto error; -- } -- } -- -+ } -+ break; -+ case 'd': -+ case 'm': - break; - default: - ERROR("Unsupported type %c\n", type); -@@ -313,6 +374,43 @@ int read_pseudo_def(struct pseudo **pseu - } - - -+ if(mode > 0777) { -+ ERROR("Mode %o out of range\n", mode); -+ goto error; -+ } -+ -+ uid = strtoll(suid, &ptr, 10); -+ if(*ptr == '\0') { -+ if(uid < 0 || uid > ((1LL << 32) - 1)) { -+ ERROR("Uid %s out of range\n", suid); -+ goto error; -+ } -+ } else { -+ struct passwd *pwuid = getpwnam(suid); -+ if(pwuid) -+ uid = pwuid->pw_uid; -+ else { -+ ERROR("Uid %s invalid uid or unknown user\n", suid); -+ goto error; -+ } -+ } -+ -+ gid = strtoll(sgid, &ptr, 10); -+ if(*ptr == '\0') { -+ if(gid < 0 || gid > ((1LL << 32) - 1)) { -+ ERROR("Gid %s out of range\n", sgid); -+ goto error; -+ } -+ } else { -+ struct group *grgid = getgrnam(sgid); -+ if(grgid) -+ gid = grgid->gr_gid; -+ else { -+ ERROR("Gid %s invalid uid or unknown user\n", sgid); -+ goto error; -+ } -+ } -+ - switch(type) { - case 'b': - mode |= S_IFBLK; -@@ -323,16 +421,37 @@ int read_pseudo_def(struct pseudo **pseu - case 'd': - mode |= S_IFDIR; - break; -+ case 'f': -+ mode |= S_IFREG; -+ break; - } - -- dev.type = type; -- dev.mode = mode; -- dev.uid = uid; -- dev.gid = gid; -- dev.major = major; -- dev.minor = minor; -+ dev = malloc(sizeof(struct pseudo_dev)); -+ if(dev == NULL) -+ BAD_ERROR("Failed to create pseudo_dev\n"); -+ -+ dev->type = type; -+ dev->mode = mode; -+ dev->uid = uid; -+ dev->gid = gid; -+ dev->major = major; -+ dev->minor = minor; -+ -+ if(type == 'f') { -+ int res; -+ -+ printf("Executing dynamic pseudo file\n"); -+ printf("\t\"%s\"\n", def); -+ res = exec_file(def + bytes, dev); -+ if(res == -1) { -+ ERROR("Failed to execute dynamic pseudo file definition" -+ " \"%s\"\n", def); -+ return FALSE; -+ } -+ add_pseudo_file(dev); -+ } - -- *pseudo = add_pseudo(*pseudo, &dev, filename, filename); -+ *pseudo = add_pseudo(*pseudo, dev, filename, filename); - - return TRUE; - -diff -Naurp squashfs-tools/pseudo.h squashfs-tools-lzma/pseudo.h ---- squashfs-tools/pseudo.h 2009-04-04 01:44:24.000000000 +0000 -+++ squashfs-tools-lzma/pseudo.h 2009-10-20 04:03:38.000000000 +0000 -@@ -27,6 +27,12 @@ struct pseudo_dev { - unsigned int gid; - unsigned int major; - unsigned int minor; -+ int pseudo_id; -+ int fd; -+ int child; -+#ifdef USE_TMP_FILE -+ char *filename; -+#endif - }; - - struct pseudo_entry { -@@ -46,3 +52,5 @@ extern int read_pseudo_def(struct pseudo - extern int read_pseudo_file(struct pseudo **, char *); - extern struct pseudo *pseudo_subdir(char *, struct pseudo *); - extern struct pseudo_entry *pseudo_readdir(struct pseudo *); -+extern struct pseudo_dev *get_pseudo_file(int); -+extern void delete_pseudo_files(); -diff -Naurp squashfs-tools/read_fs.c squashfs-tools-lzma/read_fs.c ---- squashfs-tools/read_fs.c 2009-03-31 04:23:14.000000000 +0000 -+++ squashfs-tools-lzma/read_fs.c 2009-10-20 04:03:38.000000000 +0000 -@@ -36,7 +36,6 @@ extern unsigned int get_guid(unsigned in - #include - #include - #include --#include - #include - - #ifndef linux -@@ -51,6 +50,7 @@ extern unsigned int get_guid(unsigned in - #include "squashfs_swap.h" - #include "read_fs.h" - #include "global.h" -+#include "compressor.h" - - #include - -@@ -66,7 +66,9 @@ extern unsigned int get_guid(unsigned in - fprintf(stderr, s, ## args); \ - } while(0) - --int read_block(int fd, long long start, long long *next, unsigned char *block, -+static struct compressor *comp; -+ -+int read_block(int fd, long long start, long long *next, void *block, - squashfs_super_block *sBlk) - { - unsigned short c_byte; -@@ -77,32 +79,24 @@ int read_block(int fd, long long start, - - if(SQUASHFS_COMPRESSED(c_byte)) { - char buffer[SQUASHFS_METADATA_SIZE]; -- int res; -- unsigned long bytes = SQUASHFS_METADATA_SIZE; -+ int error, res; - - c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); - read_destination(fd, start + offset, c_byte, buffer); - -- res = uncompress(block, &bytes, (const unsigned char *) buffer, -- c_byte); -- if(res != Z_OK) { -- if(res == Z_MEM_ERROR) -- ERROR("zlib::uncompress failed, not enough " -- "memory\n"); -- else if(res == Z_BUF_ERROR) -- ERROR("zlib::uncompress failed, not enough " -- "room in output buffer\n"); -- else -- ERROR("zlib::uncompress failed, unknown error " -- "%d\n", res); -+ res = comp->uncompress(block, buffer, c_byte, -+ SQUASHFS_METADATA_SIZE, &error); -+ if(res == -1) { -+ ERROR("%s uncompress failed with error code %d\n", -+ comp->name, error); - return 0; - } - if(next) - *next = start + offset + c_byte; -- return bytes; -+ return res; - } else { - c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); -- read_destination(fd, start + offset, c_byte, (char *) block); -+ read_destination(fd, start + offset, c_byte, block); - if(next) - *next = start + offset + c_byte; - return c_byte; -@@ -356,7 +350,7 @@ failed: - } - - --int read_super(int fd, squashfs_super_block *sBlk, char *source) -+struct compressor *read_super(int fd, squashfs_super_block *sBlk, char *source) - { - read_destination(fd, SQUASHFS_START, sizeof(squashfs_super_block), - (char *) sBlk); -@@ -388,8 +382,18 @@ int read_super(int fd, squashfs_super_bl - goto failed_mount; - } - -+ /* Check the compression type */ -+ comp = lookup_compressor_id(sBlk->compression); -+ if(!comp->supported) { -+ ERROR("Filesystem on %s uses %s compression, this is" -+ "unsupported by this version\n", source, comp->name); -+ display_compressors("", ""); -+ goto failed_mount; -+ } -+ - printf("Found a valid %sSQUASHFS superblock on %s.\n", - SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source); -+ printf("\tCompression used %s\n", comp->name); - printf("\tInodes are %scompressed\n", - SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : ""); - printf("\tData is %scompressed\n", -@@ -417,10 +421,10 @@ int read_super(int fd, squashfs_super_bl - TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start); - printf("\n"); - -- return TRUE; -+ return comp; - - failed_mount: -- return FALSE; -+ return NULL; - } - - -@@ -514,12 +518,17 @@ unsigned int *read_id_table(int fd, squa - SQUASHFS_INSWAP_ID_BLOCKS(index, indexes); - - for(i = 0; i < indexes; i++) { -- int length; -- length = read_block(fd, index[i], NULL, -+ int length = read_block(fd, index[i], NULL, - ((unsigned char *) id_table) + - (i * SQUASHFS_METADATA_SIZE), sBlk); - TRACE("Read id table block %d, from 0x%llx, length %d\n", i, - index[i], length); -+ if(length == 0) { -+ ERROR("Failed to read id table block %d, from 0x%llx, " -+ "length %d\n", i, index[i], length); -+ free(id_table); -+ return NULL; -+ } - } - - SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids); -@@ -563,6 +572,13 @@ int read_fragment_table(int fd, squashfs - (i * SQUASHFS_METADATA_SIZE), sBlk); - TRACE("Read fragment table block %d, from 0x%llx, length %d\n", - i, fragment_table_index[i], length); -+ if(length == 0) { -+ ERROR("Failed to read fragment table block %d, from " -+ "0x%llx, length %d\n", i, -+ fragment_table_index[i], length); -+ free(*fragment_table); -+ return 0; -+ } - } - - for(i = 0; i < sBlk->fragments; i++) -@@ -599,6 +615,13 @@ int read_inode_lookup_table(int fd, squa - (i * SQUASHFS_METADATA_SIZE), sBlk); - TRACE("Read inode lookup table block %d, from 0x%llx, length " - "%d\n", i, index[i], length); -+ if(length == 0) { -+ ERROR("Failed to read inode lookup table block %d, " -+ "from 0x%llx, length %d\n", i, index[i], -+ length); -+ free(*inode_lookup_table); -+ return 0; -+ } - } - - SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes); -diff -Naurp squashfs-tools/sort.c squashfs-tools-lzma/sort.c ---- squashfs-tools/sort.c 2009-03-31 04:25:53.000000000 +0000 -+++ squashfs-tools-lzma/sort.c 2009-10-20 04:03:38.000000000 +0000 -@@ -198,7 +198,7 @@ void generate_file_priorities(struct dir - while(dir->current_count < dir->count) { - struct dir_ent *dir_ent = dir->list[dir->current_count++]; - struct stat *buf = &dir_ent->inode->buf; -- if(dir_ent->data) -+ if(dir_ent->inode->root_entry) - continue; - - switch(buf->st_mode & S_IFMT) { -@@ -254,6 +254,7 @@ void sort_files_and_write(struct dir_inf - write_file(&inode, entry->dir, &duplicate_file); - INFO("file %s, uncompressed size %lld bytes %s" - "\n", entry->dir->pathname, -+ (long long) - entry->dir->inode->buf.st_size, - duplicate_file ? "DUPLICATE" : ""); - entry->dir->inode->inode = inode; -@@ -261,6 +262,7 @@ void sort_files_and_write(struct dir_inf - } else - INFO("file %s, uncompressed size %lld bytes " - "LINK\n", entry->dir->pathname, -+ (long long) - entry->dir->inode->buf.st_size); - } - } -diff -Naurp squashfs-tools/sort.h squashfs-tools-lzma/sort.h ---- squashfs-tools/sort.h 2009-02-08 12:02:53.000000000 +0000 -+++ squashfs-tools-lzma/sort.h 2009-10-20 04:03:38.000000000 +0000 -@@ -42,17 +42,19 @@ struct dir_ent { - struct inode_info *inode; - struct dir_info *dir; - struct dir_info *our_dir; -- struct old_root_entry_info *data; - }; - - struct inode_info { -- unsigned int nlink; - struct stat buf; -+ struct inode_info *next; - squashfs_inode inode; -- unsigned int type; - unsigned int inode_number; -+ unsigned int nlink; -+ int pseudo_id; -+ char type; - char read; -- struct inode_info *next; -+ char root_entry; -+ char pseudo_file; - }; - - struct priority_entry { -diff -Naurp squashfs-tools/squashfs_compat.h squashfs-tools-lzma/squashfs_compat.h ---- squashfs-tools/squashfs_compat.h 2009-03-16 04:27:27.000000000 +0000 -+++ squashfs-tools-lzma/squashfs_compat.h 2009-10-20 04:03:38.000000000 +0000 -@@ -777,11 +777,10 @@ typedef union squashfs_inode_header_2 sq - #endif - - #define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ -- int bits;\ -- int b_pos = pos % 8;\ -- unsigned long long val = 0;\ -- unsigned char *s = (unsigned char *)p + (pos / 8);\ -- unsigned char *d = ((unsigned char *) &val) + 7;\ -+ b_pos = pos % 8;\ -+ val = 0;\ -+ s = (unsigned char *)p + (pos / 8);\ -+ d = ((unsigned char *) &val) + 7;\ - for(bits = 0; bits < (tbits + b_pos); bits += 8) \ - *d-- = *s++;\ - value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ -diff -Naurp squashfs-tools/squashfs_fs.h squashfs-tools-lzma/squashfs_fs.h ---- squashfs-tools/squashfs_fs.h 2009-03-18 02:50:20.000000000 +0000 -+++ squashfs-tools-lzma/squashfs_fs.h 2009-10-20 04:03:38.000000000 +0000 -@@ -229,6 +229,7 @@ typedef long long squashfs_block_t; - typedef long long squashfs_inode_t; - - #define ZLIB_COMPRESSION 1 -+#define LZMA_COMPRESSION 2 - - struct squashfs_super_block { - unsigned int s_magic; -diff -Naurp squashfs-tools/unsquash-3.c squashfs-tools-lzma/unsquash-3.c ---- squashfs-tools/unsquash-3.c 2009-03-31 04:35:10.000000000 +0000 -+++ squashfs-tools-lzma/unsquash-3.c 2009-10-20 04:03:38.000000000 +0000 -@@ -36,7 +36,7 @@ int read_fragment_table_3() - sBlk.fragment_table_start); - - if(sBlk.fragments == 0) -- return; -+ return TRUE; - - if((fragment_table = malloc(sBlk.fragments * - sizeof(squashfs_fragment_entry_3))) == NULL) -diff -Naurp squashfs-tools/unsquash-4.c squashfs-tools-lzma/unsquash-4.c ---- squashfs-tools/unsquash-4.c 2009-03-31 04:38:31.000000000 +0000 -+++ squashfs-tools-lzma/unsquash-4.c 2009-10-20 04:03:38.000000000 +0000 -@@ -38,7 +38,7 @@ int read_fragment_table_4() - sBlk.fragment_table_start); - - if(sBlk.fragments == 0) -- return; -+ return TRUE; - - if((fragment_table = malloc(sBlk.fragments * - sizeof(squashfs_fragment_entry))) == NULL) -diff -Naurp squashfs-tools/unsquashfs.c squashfs-tools-lzma/unsquashfs.c ---- squashfs-tools/unsquashfs.c 2009-04-05 21:23:06.000000000 +0000 -+++ squashfs-tools-lzma/unsquashfs.c 2009-10-20 04:03:39.000000000 +0000 -@@ -25,6 +25,9 @@ - #include "squashfs_swap.h" - #include "squashfs_compat.h" - #include "read_fs.h" -+#include "compressor.h" -+ -+#include - - struct cache *fragment_cache, *data_cache; - struct queue *to_reader, *to_deflate, *to_writer, *from_writer; -@@ -36,6 +39,7 @@ int processors = -1; - - struct super_block sBlk; - squashfs_operations s_ops; -+struct compressor *comp; - - int bytes = 0, swap, file_count = 0, dir_count = 0, sym_count = 0, - dev_count = 0, fifo_count = 0; -@@ -590,31 +594,23 @@ int read_block(long long start, long lon - offset = 3; - if(SQUASHFS_COMPRESSED(c_byte)) { - char buffer[SQUASHFS_METADATA_SIZE]; -- int res; -- unsigned long bytes = SQUASHFS_METADATA_SIZE; -+ int error, res; - - c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); - if(read_bytes(start + offset, c_byte, buffer) == FALSE) - goto failed; - -- res = uncompress((unsigned char *) block, &bytes, -- (const unsigned char *) buffer, c_byte); -+ res = comp->uncompress(block, buffer, c_byte, -+ SQUASHFS_METADATA_SIZE, &error); - -- if(res != Z_OK) { -- if(res == Z_MEM_ERROR) -- ERROR("zlib::uncompress failed, not enough " -- "memory\n"); -- else if(res == Z_BUF_ERROR) -- ERROR("zlib::uncompress failed, not enough " -- "room in output buffer\n"); -- else -- ERROR("zlib::uncompress failed, unknown error " -- "%d\n", res); -+ if(res == -1) { -+ ERROR("%s uncompress failed with error code %d\n", -+ comp->name, error); - goto failed; - } - if(next) - *next = start + offset + c_byte; -- return bytes; -+ return res; - } else { - c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); - if(read_bytes(start + offset, c_byte, block) == FALSE) -@@ -632,36 +628,26 @@ failed: - - int read_data_block(long long start, unsigned int size, char *block) - { -- int res; -- unsigned long bytes = block_size; -+ int error, res; - int c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(size); - - TRACE("read_data_block: block @0x%llx, %d %s bytes\n", start, -- SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte), -- SQUASHFS_COMPRESSED_BLOCK(c_byte) ? "compressed" : -+ c_byte, SQUASHFS_COMPRESSED_BLOCK(size) ? "compressed" : - "uncompressed"); - - if(SQUASHFS_COMPRESSED_BLOCK(size)) { - if(read_bytes(start, c_byte, data) == FALSE) - goto failed; - -- res = uncompress((unsigned char *) block, &bytes, -- (const unsigned char *) data, c_byte); -+ res = comp->uncompress(block, data, c_byte, block_size, &error); - -- if(res != Z_OK) { -- if(res == Z_MEM_ERROR) -- ERROR("zlib::uncompress failed, not enough " -- "memory\n"); -- else if(res == Z_BUF_ERROR) -- ERROR("zlib::uncompress failed, not enough " -- "room in output buffer\n"); -- else -- ERROR("zlib::uncompress failed, unknown error " -- "%d\n", res); -+ if(res == -1) { -+ ERROR("%s uncompress failed with error code %d\n", -+ comp->name, error); - goto failed; - } - -- return bytes; -+ return res; - } else { - if(read_bytes(start, c_byte, block) == FALSE) - goto failed; -@@ -671,7 +657,7 @@ int read_data_block(long long start, uns - - failed: - ERROR("read_data_block: failed to read block @0x%llx, size %d\n", start, -- size); -+ c_byte); - return FALSE; - } - -@@ -1383,6 +1369,11 @@ void squashfs_stat(char *source) - #endif - printf("Creation or last append time %s", mkfs_str ? mkfs_str : - "failed to get time\n"); -+ printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", -+ sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); -+ if(sBlk.s_major == 4) -+ printf("Compression %s\n", comp->name); -+ printf("Block size %d\n", sBlk.block_size); - printf("Filesystem is %sexportable via NFS\n", - SQUASHFS_EXPORTABLE(sBlk.flags) ? "" : "not "); - -@@ -1409,9 +1400,6 @@ void squashfs_stat(char *source) - SQUASHFS_DUPLICATES(sBlk.flags) ? "" : "not "); - else - printf("Duplicates are removed\n"); -- printf("Filesystem size %.2f Kbytes (%.2f Mbytes)\n", -- sBlk.bytes_used / 1024.0, sBlk.bytes_used / (1024.0 * 1024.0)); -- printf("Block size %d\n", sBlk.block_size); - if(sBlk.s_major > 1) - printf("Number of fragments %d\n", sBlk.fragments); - printf("Number of inodes %d\n", sBlk.inodes); -@@ -1459,6 +1447,18 @@ int read_super(char *source) - s_ops.read_inode = read_inode_4; - s_ops.read_uids_guids = read_uids_guids_4; - memcpy(&sBlk, &sBlk_4, sizeof(sBlk_4)); -+ -+ /* -+ * Check the compression type -+ */ -+ comp = lookup_compressor_id(sBlk.compression); -+ if(!comp->supported) { -+ ERROR("Filesystem uses %s compression, this is " -+ "unsupported by this version\n", comp->name); -+ ERROR("Decompressors available:\n"); -+ display_compressors("", ""); -+ goto failed_mount; -+ } - return TRUE; - } - -@@ -1548,6 +1548,11 @@ int read_super(char *source) - goto failed_mount; - } - -+ /* -+ * 1.x, 2.x and 3.x filesystems use gzip compression. Gzip is always -+ * suppported. -+ */ -+ comp = lookup_compressor("gzip"); - return TRUE; - - failed_mount: -@@ -1707,32 +1712,24 @@ void *deflator(void *arg) - - while(1) { - struct cache_entry *entry = queue_get(to_deflate); -- int res; -- unsigned long bytes = block_size; -+ int error, res; - -- res = uncompress((unsigned char *) tmp, &bytes, -- (const unsigned char *) entry->data, -- SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size)); -- -- if(res != Z_OK) { -- if(res == Z_MEM_ERROR) -- ERROR("zlib::uncompress failed, not enough" -- "memory\n"); -- else if(res == Z_BUF_ERROR) -- ERROR("zlib::uncompress failed, not enough " -- "room in output buffer\n"); -- else -- ERROR("zlib::uncompress failed, unknown error " -- "%d\n", res); -- } else -- memcpy(entry->data, tmp, bytes); -+ res = comp->uncompress(tmp, entry->data, -+ SQUASHFS_COMPRESSED_SIZE_BLOCK(entry->size), block_size, -+ &error); -+ -+ if(res == -1) -+ ERROR("%s uncompress failed with error code %d\n", -+ comp->name, error); -+ else -+ memcpy(entry->data, tmp, res); - - /* - * block has been either successfully decompressed, or an error - * occurred, clear pending flag, set error appropriately and - * wake up any threads waiting on this block - */ -- cache_block_ready(entry, res != Z_OK); -+ cache_block_ready(entry, res == -1); - } - } - -@@ -1938,7 +1935,6 @@ int main(int argc, char *argv[]) - int fragment_buffer_size = FRAGMENT_BUFFER_DEFAULT; - int data_buffer_size = DATA_BUFFER_DEFAULT; - char *b; -- struct winsize winsize; - - pthread_mutex_init(&screen_mutex, NULL); - root_process = geteuid() == 0; -@@ -2087,6 +2083,8 @@ options: - "regular expressions\n"); - ERROR("\t\t\t\trather than use the default shell " - "wildcard\n\t\t\t\texpansion (globbing)\n"); -+ ERROR("\nDecompressors available:\n"); -+ display_compressors("", ""); - } - exit(1); - } -diff -Naurp squashfs-tools/unsquashfs.h squashfs-tools-lzma/unsquashfs.h ---- squashfs-tools/unsquashfs.h 2009-03-29 02:29:02.000000000 +0000 -+++ squashfs-tools-lzma/unsquashfs.h 2009-10-20 04:03:39.000000000 +0000 -@@ -31,7 +31,6 @@ - #include - #include - #include --#include - #include - #include - #include -- cgit v1.2.3