The following commit has been merged in the master branch: commit f2115151c19ff37b305296c23225807b0832086b Author: Guillem Jover <guil...@debian.org> Date: Fri Jul 2 06:15:26 2010 +0200
dpkg-split: Rewrite mksplit in C diff --git a/debian/changelog b/debian/changelog index ff780b7..7bedacf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -60,6 +60,7 @@ dpkg (1.15.8) UNRELEASED; urgency=low stat_halfconfigured and “removal-failed” for stat_halfinstalled. * Check version syntax when parsing it from libdpkg based programs. Closes: #574704 + * Rewrite mksplit in C, and merge it into dpkg-split. [ Updated programs translations ] * Catalan (Guillem Jover). diff --git a/debian/dpkg.install b/debian/dpkg.install index 1b1b998..c3106d6 100644 --- a/debian/dpkg.install +++ b/debian/dpkg.install @@ -12,7 +12,6 @@ usr/bin/dpkg-split usr/bin/dpkg-statoverride usr/bin/dpkg-trigger usr/bin/update-alternatives -usr/lib/dpkg/mksplit usr/sbin usr/share/dpkg usr/share/locale/*/LC_MESSAGES/dpkg.mo diff --git a/dpkg-split/.gitignore b/dpkg-split/.gitignore index dedc3fc..26aab39 100644 --- a/dpkg-split/.gitignore +++ b/dpkg-split/.gitignore @@ -1,2 +1 @@ dpkg-split -mksplit diff --git a/dpkg-split/Makefile.am b/dpkg-split/Makefile.am index 6f6043c..64a1d27 100644 --- a/dpkg-split/Makefile.am +++ b/dpkg-split/Makefile.am @@ -24,20 +24,5 @@ dpkg_split_LDADD = \ ../lib/compat/libcompat.a \ $(LIBINTL) - -pkglib_SCRIPTS = mksplit -EXTRA_DIST = mksplit.pl -CLEANFILES = $(pkglib_SCRIPTS) - - -do_perl_subst = $(AM_V_GEN) sed -e "s:^\#![:space:]*/usr/bin/perl:\#!$(PERL):" - - -%: %.pl Makefile - @test -d `dirname $...@` || $(mkdir_p) `dirname $...@` - $(do_perl_subst) <$< >$@ - $(AM_V_at) chmod +x $@ - - install-data-local: $(mkdir_p) $(DESTDIR)$(admindir)/parts diff --git a/dpkg-split/mksplit.pl b/dpkg-split/mksplit.pl deleted file mode 100644 index 2950b1e..0000000 --- a/dpkg-split/mksplit.pl +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/perl -- -# This script is only supposed to be called by dpkg-split. -# Its arguments are: -# <sourcefile> <partsize> <prefix> <totalsize> <partsizeallow> <msdostruncyesno> -# Stdin is also redirected from the source archive by dpkg-split. - -# Copyright © 1995 Ian Jackson <i...@chiark.greenend.org.uk> -# -# This 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 of the License, or -# (at your option) any later version. -# -# This 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, see <http://www.gnu.org/licenses/>. - -...@argv == 6 || die "mksplit: bad invocation\n"; - -($sourcefile,$partsize,$prefix,$orgsize,$partsizeallow,$msdos) = @ARGV; - -sub output { - $!=0; $rv= `$_[0]`; $? && die "mksplit $_[0]: $! $?\n"; - $rv =~ s/\n$//; $rv =~ s/\s+$//; $rv =~ s/^\s+//; - $rv; -} - -$myversion='2.1'; -$csum= &output("md5sum <\"$sourcefile\""); -$csum =~ s/\s.*//; -$package= &output("dpkg-deb --field \"$sourcefile\" Package"); -$version= &output("dpkg-deb --field \"$sourcefile\" Version"); -$revision= &output("dpkg-deb --field \"$sourcefile\" Package_Revision"); -$version.= "-$revision" if length($revision); -$nparts=int(($orgsize+$partsize-1)/$partsize); -$startat=0; -$showpartnum=1; - -$|=1; -print("Splitting package $package into $nparts parts: "); - -$msdos= ($msdos eq 'yes'); -if ($msdos) { - $prefixdir= $prefix; $prefixdir =~ s:(/?)/*[^/]+$:$1:; - $cleanprefix= $prefix; $cleanprefix =~ s:^.*/+::; - $cleanprefix =~ y/A-Za-z0-9+/a-za-z0-9x/; - $cleanprefix =~ y/a-z0-9//cd; -} - -sub add { - $data .= - sprintf("%-16s%-12d0 0 100644 %-10d%c\n%s%s", - $_[0], time, length($_[1]), 0140, $_[1], - (length($_[1]) & 1) ? "\n" : ""); -} - -while ($startat < $orgsize) { - $dsp= "$myversion\n$package\n$version\n$csum\n$orgsize\n$partsize\n". - "$showpartnum/$nparts\n"; - defined($thispartreallen= read(STDIN,$pd,$partsize)) || die "mksplit: read: $!\n"; - $data= "!<arch>\n"; - print("$showpartnum "); - &add('debian-split',$dsp); - &add("data.$showpartnum",$pd); - if ($thispartreallen > $partsizeallow) { - die "Header is too long, making part too long. Your package name or version\n". - "numbers must be extraordinarily long, or something. Giving up.\n"; - } - if ($msdos) { - $basename= "${showpartnum}of$nparts.$cleanprefix"; - $basename= substr($basename,0,9); - $basename =~ s/^([^.]*)\.(.*)$/$2$1/; - $basename= "$prefixdir$basename"; - } else { - $basename= "$prefix.${showpartnum}of$nparts"; - } - open(O,"> $basename.deb") || die("mksplit: open $basename.deb: $!\n"); - print(O $data) || die("mksplit: write $basename.deb: $!\n"); - close(O) || die("mksplit: close $basename.deb: $!\n"); - $startat += $partsize; - $showpartnum++; -} -print("done\n"); - -exit(0); diff --git a/dpkg-split/split.c b/dpkg-split/split.c index b583a46..d5d75f6 100644 --- a/dpkg-split/split.c +++ b/dpkg-split/split.c @@ -3,6 +3,7 @@ * split.c - splitting archives * * Copyright © 1995 Ian Jackson <i...@chiark.greenend.org.uk> + * Copyright © 2010 Guillem Jover <guil...@debian.org> * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,11 +22,17 @@ #include <config.h> #include <compat.h> +#include <sys/types.h> #include <sys/stat.h> +#include <sys/wait.h> #include <limits.h> +#include <errno.h> #include <fcntl.h> +#include <libgen.h> #include <string.h> +#include <ctype.h> +#include <time.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> @@ -33,16 +40,210 @@ #include <dpkg/i18n.h> #include <dpkg/dpkg.h> #include <dpkg/dpkg-db.h> +#include <dpkg/subproc.h> +#include <dpkg/buffer.h> +#include <dpkg/ar.h> #include <dpkg/myopt.h> #include "dpkg-split.h" +static char * +deb_field(const char *filename, const char *field) +{ + pid_t pid; + int p[2]; + struct varbuf buf = VARBUF_INIT; + char *end; + + m_pipe(p); + + pid = subproc_fork(); + if (pid == 0) { + /* Child writes to pipe. */ + m_dup2(p[1], 1); + close(p[0]); + close(p[1]); + + execlp(BACKEND, BACKEND, "--field", filename, field, NULL); + ohshite(_("failed to exec dpkg-deb to extract field value")); + } + close(p[1]); + + /* Parant reads from pipe. */ + varbufreset(&buf); + fd_vbuf_copy(p[0], &buf, -1, _("dpkg-deb field extraction")); + varbufaddc(&buf, '\0'); + + close(p[0]); + + subproc_wait_check(pid, _("dpkg-deb field extraction"), PROCPIPE); + + /* Trim down trailing junk. */ + for (end = buf.buf + strlen(buf.buf) - 1; end - buf.buf >= 1; end--) + if (isspace(*end)) + *end = '\0'; + else + break; + + return varbuf_detach(&buf); +} + +/* Cleanup filename for use in crippled msdos systems. */ +static char * +clean_msdos_filename(char *filename) +{ + char *d, *s; + + for (s = d = filename; *s; d++, s++) { + if (*s == '+') + *d = 'x'; + else if (isupper(*s)) + *d = tolower(*s); + else if (islower(*s) || isdigit(*s)) + *d = *s; + else + s++; + } + + return filename; +} + +static int +mksplit(const char *file_src, const char *prefix, size_t partsize, + size_t maxpartsize, bool msdos) +{ + int fd_src; + struct stat st; + char hash[MD5HASHLEN + 1]; + char *package, *version; + int nparts, curpart; + off_t startat; + char *prefixdir = NULL, *msdos_prefix = NULL; + struct varbuf file_dst = VARBUF_INIT; + struct varbuf partmagic = VARBUF_INIT; + struct varbuf partname = VARBUF_INIT; + char *partdata; + + fd_src = open(file_src, O_RDONLY); + if (fd_src < 0) + ohshite(_("unable to open source file `%.250s'"), file_src); + if (fstat(fd_src, &st)) + ohshite(_("unable to fstat source file")); + if (!S_ISREG(st.st_mode)) + ohshit(_("source file `%.250s' not a plain file"), file_src); + + fd_md5(fd_src, hash, -1, "md5hash"); + lseek(fd_src, 0, SEEK_SET); + + /* FIXME: Use libdpkg-deb. */ + package = deb_field(file_src, "Package"); + version = deb_field(file_src, "Version"); + + nparts = (st.st_size + partsize - 1) / partsize; + + setvbuf(stdout, NULL, _IONBF, 0); + + printf("Splitting package %s into %d parts: ", package, nparts); + + if (msdos) { + char *t; + + t = m_strdup(prefix); + prefixdir = m_strdup(dirname(t)); + free(t); + + t = m_strdup(prefix); + msdos_prefix = m_strdup(basename(t)); + free(t); + + prefix = clean_msdos_filename(msdos_prefix); + } + + partdata = m_malloc(partsize); + curpart = 1; + + for (startat = 0; startat < st.st_size; startat += partsize) { + int fd_dst; + ssize_t partrealsize; + + varbufreset(&file_dst); + /* Generate output filename. */ + if (msdos) { + struct varbuf refname = VARBUF_INIT; + int prefix_max; + + varbufprintf(&refname, "%dof%d", curpart, nparts); + prefix_max = max(8 - strlen(refname.buf), 0); + varbufprintf(&file_dst, "%s/%.*s%.8s.deb", + prefixdir, prefix_max, prefix, + refname.buf); + varbuf_destroy(&refname); + } else { + varbufprintf(&file_dst, "%s.%dof%d.deb", + prefix, curpart, nparts); + } + + /* Read data from the original package. */ + partrealsize = read(fd_src, partdata, partsize); + if (partrealsize < 0) + ohshite("mksplit: read"); + + if ((size_t)partrealsize > maxpartsize) { + ohshit("Header is too long, making part too long. " + "Your package name or version\n" + "numbers must be extraordinarily long, " + "or something. Giving up.\n"); + } + + /* Split the data. */ + fd_dst = open(file_dst.buf, O_CREAT | O_WRONLY, 0644); + if (fd_dst < 0) + ohshite(_("unable to open file '%s'"), file_dst.buf); + + /* Write the ar header. */ + dpkg_ar_put_magic(file_dst.buf, fd_dst); + + /* Write the debian-split part. */ + varbufprintf(&partmagic, "%s\n%s\n%s\n%s\n%zu\n%zu\n%d/%d\n", + SPLITVERSION, package, version, hash, + st.st_size, partsize, curpart, nparts); + dpkg_ar_member_put_mem(file_dst.buf, fd_dst, PARTMAGIC, + partmagic.buf, partmagic.used); + varbufreset(&partmagic); + + /* Write the data part. */ + varbufprintf(&partname, "data.%d", curpart); + dpkg_ar_member_put_mem(file_dst.buf, fd_dst, partname.buf, + partdata, (size_t)partrealsize); + varbufreset(&partname); + + close(fd_dst); + + printf("%d ", curpart); + + curpart++; + } + + varbuf_destroy(&file_dst); + varbuf_destroy(&partname); + varbuf_destroy(&partmagic); + free(partdata); + + free(prefixdir); + free(msdos_prefix); + + close(fd_src); + + printf("done\n"); + + return 0; +} + void do_split(const char *const *argv) { const char *sourcefile, *prefix; char *palloc; - int l, fd; - char partsizebuf[30], lengthbuf[30], partsizeallowbuf[30]; - struct stat stab; + int l; + size_t partsize; sourcefile= *argv++; if (!sourcefile) @@ -60,17 +261,9 @@ void do_split(const char *const *argv) { } prefix= palloc; } - sprintf(partsizebuf,"%ld",maxpartsize-HEADERALLOWANCE); - sprintf(partsizeallowbuf,"%ld",maxpartsize); - fd= open(sourcefile,O_RDONLY); - if (fd < 0) - ohshite(_("unable to open source file `%.250s'"), sourcefile); - if (fstat(fd,&stab)) ohshite(_("unable to fstat source file")); - if (!S_ISREG(stab.st_mode)) ohshit(_("source file `%.250s' not a plain file"),sourcefile); - sprintf(lengthbuf,"%lu",(unsigned long)stab.st_size); - m_dup2(fd,0); - execl(MKSPLITSCRIPT,MKSPLITSCRIPT, - sourcefile,partsizebuf,prefix,lengthbuf,partsizeallowbuf,msdos?"yes":"no", - NULL); - ohshite(_("unable to exec mksplit")); + partsize = maxpartsize - HEADERALLOWANCE; + + mksplit(sourcefile, prefix, partsize, maxpartsize, msdos); + + exit(0); } -- dpkg's main repository -- To UNSUBSCRIBE, email to debian-dpkg-cvs-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org