Commit 82ab6225 authored by Bernhard Link's avatar Bernhard Link

add uncompression support to aptmethod.c

parent 8df4731f
......@@ -18,12 +18,12 @@ AM_CPPFLAGS = -std=gnu99 -Wall $(ARCHIVECPP) $(DBCPPFLAGS)
reprepro_LDADD = $(ARCHIVELIBS) $(DBLIBS)
changestool_LDADD = $(ARCHIVELIBS)
reprepro_SOURCES = indexfile.c copypackages.c readcompressed.c sourceextraction.c checksums.c readtextfile.c filecntl.c sha1.c sha256.c configparser.c database.c freespace.c log.c changes.c incoming.c uploaderslist.c guesscomponent.c files.c md5.c dirs.c chunks.c reference.c binaries.c sources.c checks.c names.c dpkgversions.c release.c mprintf.c updates.c strlist.c signature.c distribution.c checkindeb.c checkindsc.c checkin.c upgradelist.c target.c aptmethod.c downloadcache.c main.c override.c terms.c ignore.c filterlist.c exports.c tracking.c optionsfile.c readrelease.c donefile.c pull.c contents.c filelist.c $(ARCHIVE_USED) $(ARCHIVE_CONTENTS)
reprepro_SOURCES = uncompression.c indexfile.c copypackages.c readcompressed.c sourceextraction.c checksums.c readtextfile.c filecntl.c sha1.c sha256.c configparser.c database.c freespace.c log.c changes.c incoming.c uploaderslist.c guesscomponent.c files.c md5.c dirs.c chunks.c reference.c binaries.c sources.c checks.c names.c dpkgversions.c release.c mprintf.c updates.c strlist.c signature.c distribution.c checkindeb.c checkindsc.c checkin.c upgradelist.c target.c aptmethod.c downloadcache.c main.c override.c terms.c ignore.c filterlist.c exports.c tracking.c optionsfile.c readrelease.c donefile.c pull.c contents.c filelist.c $(ARCHIVE_USED) $(ARCHIVE_CONTENTS)
EXTRA_reprepro_SOURCE = $(ARCHIVE_UNUSED)
changestool_SOURCES = readcompressed.c sourceextraction.c readtextfile.c filecntl.c tool.c chunkedit.c strlist.c checksums.c sha1.c sha256.c md5.c mprintf.c chunks.c signature.c dirs.c names.c $(ARCHIVE_USED)
noinst_HEADERS = copypackages.h readcompressed.h sourceextraction.h checksums.h readtextfile.h filecntl.h sha1.h sha256.h configparser.h database_p.h database.h freespace.h log.h changes.h incoming.h guesscomponent.h md5.h dirs.h files.h chunks.h reference.h binaries.h sources.h checks.h names.h release.h error.h mprintf.h updates.h strlist.h signature.h distribution.h debfile.h checkindeb.h checkindsc.h upgradelist.h target.h aptmethod.h downloadcache.h override.h terms.h ignore.h filterlist.h dpkgversions.h checkin.h exports.h globals.h tracking.h trackingt.h optionsfile.h readrelease.h donefile.h pull.h ar.h filelist.h contents.h chunkedit.h uploaderslist.h indexfile.h
noinst_HEADERS = uncompression.h copypackages.h readcompressed.h sourceextraction.h checksums.h readtextfile.h filecntl.h sha1.h sha256.h configparser.h database_p.h database.h freespace.h log.h changes.h incoming.h guesscomponent.h md5.h dirs.h files.h chunks.h reference.h binaries.h sources.h checks.h names.h release.h error.h mprintf.h updates.h strlist.h signature.h distribution.h debfile.h checkindeb.h checkindsc.h upgradelist.h target.h aptmethod.h downloadcache.h override.h terms.h ignore.h filterlist.h dpkgversions.h checkin.h exports.h globals.h tracking.h trackingt.h optionsfile.h readrelease.h donefile.h pull.h ar.h filelist.h contents.h chunkedit.h uploaderslist.h indexfile.h
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in $(srcdir)/configure $(srcdir)/stamp-h.in $(srcdir)/aclocal.m4 $(srcdir)/config.h.in
......
This diff is collapsed.
......@@ -20,22 +20,29 @@ struct tobedone {
/*@notnull@*/
char *filename;
/* if non-NULL, add to the database after found (needs md5sum != NULL) */
/*@null@*/
char *filekey;
union {
/* if filekey != NULL */
struct checksums *checksums;
/* if filekey == NULL: */
/* if !indexfile */
char *filekey;
/* if indexfile, the place the final uncompressed checksum
* is to be saved to: */
/*@null@*/ struct checksums **checksums_p;
};
union {
/* if !indexfile */
/*@null@*/ struct checksums *checksums;
/* if !indexfile */
/*@null@*/ const struct checksums *compressedchecksums;
};
bool indexfile;
/* must be c_none if not a index file */
enum compression compression;
};
retvalue aptmethod_initialize_run(/*@out@*/struct aptmethodrun **run);
retvalue aptmethod_newmethod(struct aptmethodrun *, const char *uri, const char *fallbackuri, const struct strlist *config, /*@out@*/struct aptmethod **);
/* md5sum can be NULL(filekey then, too): if todo != NULL, then *todo will be set */
retvalue aptmethod_queuefile(struct aptmethod *, const char *origfile, const char *destfile, const struct checksums *, const char *filekey, /*@out@*/struct tobedone **);
retvalue aptmethod_queueindexfile(struct aptmethod *, const char *origfile, const char *destfile, /*@null@*/struct checksums **);
retvalue aptmethod_queueindexfile(struct aptmethod *method, const char *suite, const char *origfile, const char *destfile, /*@null@*/struct checksums **, enum compression, /*@null@*/const struct checksums *);
retvalue aptmethod_download(struct aptmethodrun *, struct database *);
retvalue aptmethod_shutdown(/*@only@*/struct aptmethodrun *);
......
/* This file is part of "reprepro"
* Copyright (C) 2008 Bernhard R. Link
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include <config.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <string.h>
#include <zlib.h>
#include <fcntl.h>
#include "globals.h"
#include "error.h"
#include "uncompression.h"
extern int verbose;
const char * const uncompression_suffix[c_COUNT] = {
"", ".gz", ".bz2", ".lzma" };
/* we got an pid, check if it is a uncompressor we care for */
retvalue uncompress_checkpid(pid_t pid, int status) {
// nothing is forked, so nothing to do
return RET_NOTHING;
}
bool uncompress_running(void) {
// nothing is forked, so nothing to do
return false;
}
/* check for existance of external programs */
void uncompressions_check(void) {
// nothing yet to check
}
static inline retvalue builtin_gunzip(const char *compressed, const char *destination) {
gzFile f;
char buffer[4096];
int bytes_read, bytes_written, written;
int destfd;
int e, i, zerror;
f = gzopen(compressed, "r");
if( f == NULL ) {
// TODO: better error message...
fprintf(stderr, "Could not read %s\n",
compressed);
return RET_ERROR;
}
destfd = open(destination, O_WRONLY|O_CREAT|O_EXCL|O_NOCTTY, 0666);
if( destfd < 0 ) {
e = errno;
fprintf(stderr, "Error %d creating '%s': %s\n",
e, destination, strerror(e));
gzclose(f);
return RET_ERRNO(e);
}
do {
bytes_read = gzread(f, buffer, 4096);
if( bytes_read <= 0 )
break;
bytes_written = 0;
while( bytes_written < bytes_read ) {
written = write(destfd, buffer + bytes_written,
bytes_read - bytes_written);
if( written < 0 ) {
e = errno;
fprintf(stderr,
"Error %d writing to '%s': %s\n", e, destination, strerror(e) );
close(destfd);
gzclose(f);
return RET_ERRNO(e);
}
bytes_written += written;
}
} while( true );
e = errno;
if( bytes_read < 0 ) {
const char *msg = gzerror(f, &zerror);
if( zerror != Z_ERRNO ) {
fprintf(stderr, "Zlib Error %d reading from '%s': %s!\n",
zerror, compressed, msg);
(void)close(destfd);
return RET_ERROR;
}
e = errno;
(void)gzclose(f);
} else {
zerror = gzclose(f);
e = errno;
}
if( zerror == Z_ERRNO ) {
fprintf(stderr, "Error %d reading from '%s': %s!\n",
e, compressed, strerror(e));
(void)close(destfd);
return RET_ERRNO(e);
} else if( zerror < 0 ) {
fprintf(stderr, "Zlib Error %d reading from '%s'!\n",
zerror, compressed);
(void)close(destfd);
return RET_ERROR;
}
i = close(destfd);
if( i != 0 ) {
e = errno;
fprintf(stderr, "Error %d writing to '%s': %s!\n",
e, destination, strerror(e));
return RET_ERROR;
}
return RET_OK;
}
retvalue uncompress_queue_file(const char *compressed, const char *destination, enum compression compression, finishaction *action, void *privdata, bool *done_p) {
retvalue r;
if( verbose > 1 ) {
fprintf(stderr, "Uncompress '%s' into '%s'...\n",
compressed, destination);
}
assert( compression == c_gzip );
(void)unlink(destination);
r = builtin_gunzip(compressed, destination);
if( RET_WAS_ERROR(r) ) {
(void)unlink(destination);
return r;
}
*done_p = true;
return action(privdata, compressed, true);
}
retvalue uncompress_file(const char *compressed, const char *destination, enum compression compression) {
retvalue r;
if( verbose > 1 ) {
fprintf(stderr, "Uncompress '%s' into '%s'...\n",
compressed, destination);
}
assert( compression == c_gzip );
(void)unlink(destination);
r = builtin_gunzip(compressed, destination);
if( RET_WAS_ERROR(r) ) {
(void)unlink(destination);
return r;
}
return RET_OK;
}
#ifndef REPREPRO_UNCOMPRESS_H
#define REPREPRO_UNCOMPRESS_H
/* "", ".gz", ... */
extern const char * const uncompression_suffix[c_COUNT];
/* there are two different modes: uncompress a file to memory,
* or uncompress (possibly multiple files) on the filesystem,
* controled by aptmethods */
#define uncompression_supported(c) ((c) == c_gzip || (c) == c_none)
/* we got an pid, check if it is a uncompressor we care for */
retvalue uncompress_checkpid(pid_t, int);
/* still waiting for a client to exit */
bool uncompress_running(void);
typedef retvalue finishaction(void *, const char *, bool);
/* uncompress and call action when finished */
retvalue uncompress_queue_file(const char *, const char *, enum compression, finishaction *, void *, bool *);
retvalue uncompress_file(const char *, const char *, enum compression);
/* check for existance of external programs */
void uncompressions_check(void);
#endif
......@@ -180,14 +180,14 @@ struct update_origin {
struct checksumsarray indexchecksums;
/* index files used */
struct update_index_file *files;
char *basedir;
};
struct update_index_file {
struct update_index_file *next;
struct update_origin *origin;
char *filename;
char *upstream;
const char *upstream_check;
char *upstream_check;
/* != NULL if filename was changed by ListHook, then the original */
char *original_filename;
/* index into origin's checkfile, -1 = none */
......@@ -348,6 +348,7 @@ static void updates_freeorigins(/*@only@*/struct update_origin *o) {
origin = o;
o = origin->next;
free(origin->suite_from);
free(origin->basedir);
free(origin->releasefile);
free(origin->releasegpgfile);
checksumsarray_done(&origin->indexchecksums);
......@@ -355,7 +356,7 @@ static void updates_freeorigins(/*@only@*/struct update_origin *o) {
struct update_index_file *file = origin->files;
origin->files = file->next;
free(file->upstream);
free(file->upstream_check);
free(file->filename);
free(file->original_filename);
free(file);
......@@ -643,6 +644,15 @@ static retvalue instance_pattern(struct update_pattern *pattern, const struct di
free(update);
return RET_ERROR_OOM;
}
if( pattern->flat != NULL )
update->basedir = strdup(update->suite_from);
else
update->basedir = mprintf("dists/%s", update->suite_from);
if( update->basedir == NULL ) {
free(update->suite_from);
free(update);
return RET_ERROR_OOM;
}
pattern->used = true;
update->distribution = distribution;
......@@ -732,7 +742,7 @@ static retvalue getorigins(struct update_pattern *patterns, const struct distrib
static inline struct update_index_file *addindexfile(struct update_origin *origin, const char *codename, const char *architecture_from, const char *component_from, const char *packagetype) {
struct update_index_file *file, *i;
char *f, *u; const char *uc;
char *f, *u;
assert( origin != NULL && origin->pattern != NULL);
......@@ -757,30 +767,21 @@ static inline struct update_index_file *addindexfile(struct update_origin *origi
}
file->filename = f;
if( strcmp(packagetype, "deb") == 0 ) {
if( origin->pattern->flat != NULL ) {
u = mprintf("%s/Packages.gz", origin->suite_from);
uc = "Packages.gz";
} else {
u = mprintf("dists/%s/%s/binary-%s/Packages.gz",
origin->suite_from,
if( origin->pattern->flat != NULL )
u = strdup("Packages.gz");
else
u = mprintf("%s/binary-%s/Packages.gz",
component_from, architecture_from);
uc = u + strlen(origin->suite_from) + 7; /* "dists/%s/" */
}
} else if( strcmp(packagetype, "udeb") == 0 ) {
u = mprintf("dists/%s/%s/debian-installer/binary-%s/Packages.gz",
origin->suite_from,
u = mprintf("%s/debian-installer/binary-%s/Packages.gz",
component_from, architecture_from);
uc = u + strlen(origin->suite_from) + 7; /* "dists/%s/" */
} else if( strcmp(packagetype, "dsc") == 0 ) {
if( origin->pattern->flat != NULL ) {
u = mprintf("%s/Sources.gz", origin->suite_from);
uc = "Sources.gz";
} else {
u = mprintf("dists/%s/%s/source/Sources.gz",
origin->suite_from, component_from);
uc = u + strlen(origin->suite_from) + 7; /* "dists/%s/" */
}
if( origin->pattern->flat != NULL )
u = strdup("Sources.gz");
else
u = mprintf("%s/source/Sources.gz",
component_from);
} else {
u = NULL;
......@@ -791,8 +792,7 @@ static inline struct update_index_file *addindexfile(struct update_origin *origi
free(file);
return NULL;
}
file->upstream = u;
file->upstream_check = uc;
file->upstream_check = u;
file->origin = origin;
file->checksum_ofs = -1;
file->next = origin->files;
......@@ -1217,7 +1217,6 @@ static retvalue updates_startup(struct aptmethodrun *run,struct update_distribut
****************************************************************************/
static inline retvalue queuemetalists(struct update_origin *origin) {
char *toget;
retvalue r;
const struct update_pattern *p = origin->pattern;
......@@ -1228,25 +1227,14 @@ static inline retvalue queuemetalists(struct update_origin *origin) {
return RET_ERROR;
}
if( p->flat != NULL )
toget = mprintf("%s/Release", origin->suite_from);
else
toget = mprintf("dists/%s/Release", origin->suite_from);
r = aptmethod_queueindexfile(origin->download,
toget, origin->releasefile, NULL);
free(toget);
r = aptmethod_queueindexfile(origin->download, origin->basedir, "Release",
origin->releasefile, NULL, c_none, NULL);
if( RET_WAS_ERROR(r) )
return r;
if( p->verifyrelease != NULL ) {
if( p->flat != NULL )
toget = mprintf("%s/Release.gpg", origin->suite_from);
else
toget = mprintf("dists/%s/Release.gpg",
origin->suite_from);
r = aptmethod_queueindexfile(origin->download,
toget, origin->releasegpgfile, NULL);
free(toget);
r = aptmethod_queueindexfile(origin->download, origin->basedir,
"Release.gpg", origin->releasegpgfile, NULL, c_none, NULL);
if( RET_WAS_ERROR(r) )
return r;
}
......@@ -1340,8 +1328,8 @@ static inline retvalue queueindex(struct update_index_file *index) {
retvalue r;
/* TODO: save the content to make sure it is the old instead */
donefile_delete(index->filename);
r = aptmethod_queueindexfile(origin->download,
index->upstream, index->filename, NULL);
r = aptmethod_queueindexfile(origin->download, origin->basedir,
index->upstream_check, index->filename, NULL, c_none, NULL);
if( RET_WAS_ERROR(r) )
index->failed = true;
index->new = true;
......@@ -1400,9 +1388,10 @@ static inline retvalue queueindex(struct update_index_file *index) {
}
index->queued = true;
if( RET_IS_OK(r) ) {
r = aptmethod_queueindexfile(origin->download,
index->upstream, index->filename,
&origin->indexchecksums.checksums[i]);
r = aptmethod_queueindexfile(origin->download, origin->basedir,
index->upstream_check, index->filename,
&origin->indexchecksums.checksums[i],
c_none, NULL);
assert( r != RET_NOTHING );
} else if( r == RET_NOTHING ) {
/* file is already there, but it might still need
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment