Commit 6c998eff authored by Bernhard Link's avatar Bernhard Link

some steps towards checkin in .deb's directly

parent 15a609d7
......@@ -3,8 +3,8 @@ bin_PROGRAMS = mirrorer
CPPFLAGS = @CPPFLAGS@ -D_GNU_SOURCE=1 -DPKGDATADIR=\"$(pkgdatadir)\" -Wall
mirrorer_SOURCES = main.c files.c md5.c md5sum.c dirs.c chunks.c reference.c packages.c binaries.c sources.c names.c dpkgversions.c release.c mprintf.c download.c updates.c strlist.c signature.c distribution.c extractcontrol.c checkindeb.c checkindsc.c checkin.c
mirrorer_SOURCES = main.c files.c md5.c md5sum.c dirs.c chunks.c reference.c packages.c binaries.c sources.c names.c dpkgversions.c release.c mprintf.c download.c updates.c strlist.c signature.c distribution.c extractcontrol.c checkindeb.c checkindsc.c checkin.c copyfile.c
mirrorer_LDFLAGS += -ldb3
noinst_HEADERS = md5.h md5sum.h dirs.h files.h chunks.h reference.h packages.h binaries.h sources.h names.h release.h error.h mprintf.h download.h updates.h strlist.h signature.h distribution.h extractcontrol.h checkindeb.h checkindsc.h
noinst_HEADERS = md5.h md5sum.h dirs.h files.h chunks.h reference.h packages.h binaries.h sources.h names.h release.h error.h mprintf.h download.h updates.h strlist.h signature.h distribution.h extractcontrol.h checkindeb.h checkindsc.h copyfile.h
MAINTAINERCLEANFILES = Makefile.in configure install-sh stamp-h.in aclocal.m4 config.h.in mkinstalldirs
......@@ -27,11 +27,17 @@
#include <string.h>
#include <malloc.h>
#include <zlib.h>
#include <db.h>
#include "error.h"
#include "mprintf.h"
#include "md5sum.h"
#include "names.h"
#include "chunks.h"
#include "checkindeb.h"
#include "reference.h"
#include "packages.h"
#include "files.h"
#include "extractcontrol.h"
extern int verbose;
......@@ -39,14 +45,268 @@ extern int verbose;
// create or adopt the chunk of the Packages.gz-file and
// putting it in the various databases.
/* Add <package> with filename <filekey> and chunk <chunk> (which
* alreadycontains "Filename:") and characteristica <md5andsize>
* to the <files> database, add an reference to <referee> in
* <references> and overwrite/add it to <pkgs> removing
* references to oldfilekey that will be fall out of it by this */
retvalue checkindeb_insert(DB *references,const char *referee,
DB *pkgs,
const char *package, const char *chunk,
const char *filekey, const char *oldfilekey) {
retvalue result,r;
/* mark it as needed by this distribution */
r = references_increment(references,filekey,referee);
if( RET_WAS_ERROR(r) )
return r;
/* Add package to distribution's database */
// Todo: do this earlier...
if( oldfilekey != NULL ) {
result = packages_replace(pkgs,package,chunk);
} else {
result = packages_add(pkgs,package,chunk);
}
if( RET_WAS_ERROR(result) )
return result;
/* remove old references to files */
if( oldfilekey ) {
r = references_decrement(references,oldfilekey,referee);
RET_UPDATE(result,r);
}
return result;
}
// should superseed the add_package from main.c for inclusion
// of downloaded packages from main.c
//
/*
retvalue add_package(void *data,const char *chunk,const char *package,const char *sourcename,const char *oldfile,const char *basename,const char *filekey,const char *md5andsize,const char *oldchunk) {
char *newchunk;
retvalue result,r;
char *oldfilekey;
* look for needed files *
r = files_expect(files,mirrordir,filekey,md5andsize);
if( ! RET_IS_OK(r) ) {
printf("Missing file %s\n",filekey);
return r;
}
* calculate the needed and check it in *
newchunk = chunk_replaceentry(chunk,"Filename",filekey);
if( !newchunk )
return RET_ERROR;
oldfilekey = NULL;
if( oldchunk ) {
r = binaries_parse_chunk(oldchunk,NULL,&oldfilekey,NULL,NULL,NULL);
if( RET_WAS_ERROR(r) ) {
free(newchunk);
return r;
}
}
result = insert_package(files,mirrordir,references,referee,pkgs,package,newchunk,filekey,md5andsize,oldfilekey);
free(newchunk);
free(oldfilekey);
return result;
}*/
/* things to do with .deb's checkin by hand: (by comparison with apt-ftparchive)
- extract the control file (that's the hard part)
- extract the control file (that's the hard part -> extractcontrol.c )
- check for Package, Version, Architecture, Maintainer, Description
- apply overwrite if neccesary (section,priority and perhaps maintainer).
- add Size, MD5sum, Filename, Priority, Section
- remove Status (warning if existant?)
- check for Optional-field and reject then..
*/
static inline retvalue getvalue(const char *filename,const char *chunk,const char *field,char **value) {
retvalue r;
r = chunk_getvalue(chunk,field,value);
if( r == RET_NOTHING ) {
fprintf(stderr,"Cannot find %s-header in control file of %s!\n",field,filename);
r = RET_ERROR;
}
return r;
}
static inline retvalue checkvalue(const char *filename,const char *chunk,const char *field) {
retvalue r;
r = chunk_checkfield(chunk,field);
if( r == RET_NOTHING ) {
fprintf(stderr,"Cannot find %s-header in control file of %s!\n",field,filename);
r = RET_ERROR;
}
return r;
}
static inline retvalue getvalue_d(const char *defaul,const char *chunk,const char *field,char **value) {
retvalue r;
r = chunk_getvalue(chunk,field,value);
if( r == RET_NOTHING ) {
*value = strdup(defaul);
if( *value == NULL )
r = RET_ERROR_OOM;
}
return r;
}
static inline char *calcfilekey(const char *component,const char *package,
const char *source,const char *version,const char *arch) {
char *basename,*filekey;
//TODO: the following is anything but in-situ.
// think about if this has to be changed or is good the way it is.
basename = calc_package_basename(package,version,arch);
if( basename == NULL )
return NULL;
filekey = calc_filekey(component,source,basename);
free(basename);
return filekey;
}
static inline char *addfiledata(const char *chunk,const char *filekey,
int pkgsize,const char*pkgmd5) {
char *fieldstoadd,*newchunk;
//TODO: the following is anything but in-situ.
// think about if this has to be changed or is good the way it is.
fieldstoadd = mprintf("Filename: %s\nSize: %d\nMD5Sum: %s",
filekey,pkgsize,pkgmd5);
if( fieldstoadd == NULL )
return NULL;
newchunk = chunk_insertdata(chunk,"Description",fieldstoadd);
free(fieldstoadd);
return newchunk;
}
void deb_free(struct debpackage *pkg) {
if( pkg ) {
free(pkg->package);free(pkg->version);
free(pkg->source);free(pkg->arch);
free(pkg->filekey);free(pkg->control);
}
free(pkg);
}
retvalue deb_read(struct debpackage **pkg, const char *component, const char *filename) {
char *newchunk;
retvalue r;
char pkgmd5[33];off_t pkgsize;
struct debpackage *deb;
r = md5sum(pkgmd5,&pkgsize,filename,0);
// TODO: is RETNOTHING pssoible here?
if( !RET_IS_OK(r) )
return r;
deb = calloc(1,sizeof(struct debpackage));
deb->md5andsize = mprintf("%s %lu",pkgmd5,(long)pkgsize);
if( deb->md5andsize == NULL ) {
deb_free(deb);
return r;
}
r = extractcontrol(&deb->control,filename);
if( RET_WAS_ERROR(r) ) {
deb_free(deb);
return r;
}
/* first look for fields that should be there */
r = getvalue(filename,deb->control,"Package",&deb->package);
if( RET_WAS_ERROR(r) ) {
deb_free(deb);
return r;
}
r = checkvalue(filename,deb->control,"Maintainer");
if( RET_WAS_ERROR(r) ) {
deb_free(deb);
return r;
}
r = checkvalue(filename,deb->control,"Description");
if( RET_WAS_ERROR(r) ) {
deb_free(deb);
return r;
}
r = getvalue(filename,deb->control,"Version",&deb->version);
if( RET_WAS_ERROR(r) ) {
deb_free(deb);
return r;
}
r = getvalue(filename,deb->control,"Architecture",&deb->arch);
if( RET_WAS_ERROR(r) ) {
deb_free(deb);
return r;
}
/* can be there, otherwise we also know what it is */
r = getvalue_d(deb->package,deb->control,"Source",&deb->source);
if( RET_WAS_ERROR(r) ) {
deb_free(deb);
return r;
}
/* check for priority and section, compare with defaults
* and overrides */
//TODO ... do so ...
r = checkvalue(filename,deb->control,"Priority");
if( RET_WAS_ERROR(r) ) {
deb_free(deb);
return r;
}
r = checkvalue(filename,deb->control,"Section");
if( RET_WAS_ERROR(r) ) {
deb_free(deb);
return r;
}
//TODO: add checks here if section implies another component or
// do it another place??
/* Add Filename, md5sum and size-headers... */
deb->filekey = calcfilekey(component,deb->package,deb->source,deb->version,deb->arch);
if( deb->filekey == NULL ) {
deb_free(deb);
return r;
}
newchunk = addfiledata(deb->control,deb->filekey,pkgsize,pkgmd5);
if( newchunk == NULL ) {
deb_free(deb);
return r;
}
free(deb->control);
deb->control = newchunk;
*pkg = deb;
return RET_OK;
}
......@@ -6,4 +6,24 @@
#warning "What's hapening here?"
#endif
/* Add <package> with filename <filekey> and chunk <chunk> (which
* alreadycontains "Filename:"), add an reference to <referee> in
* <references> and overwrite/add it to <pkgs> removing
* references to oldfilekey that will be fall out of it by this */
retvalue checkindeb_insert( DB *references,const char *referee,
DB *pkgs,
const char *package, const char *chunk,
const char *filekey, const char *oldfilekey);
struct debpackage {
char *package,*version,*source,*arch;
char *filekey;
char *md5andsize;
char *control;
};
/* read the data from a .deb, add Filename, Size and md5sum to the control-item */
retvalue deb_read(struct debpackage **pkg, const char *component, const char *filename);
void deb_free(struct debpackage *pkg);
#endif
......@@ -159,6 +159,43 @@ char *chunk_dupnextline(const char **field) {
}
*/
/* create a new chunk with the given data added before another field */
char *chunk_insertdata(const char *chunk,const char *before,const char *new) {
size_t l,ln;
const char *rest;
char *result;
if( !chunk || !new || !before )
return NULL;
/* first search for the field to add before */
l = strlen(before);
rest = chunk;
do {
if(strncmp(before,rest,l) == 0 && rest[l] == ':' ) {
/* create a chunk with the data added */
ln = strlen(new);
result = malloc(2+strlen(chunk)+ln);
if( !result )
return NULL;
strncpy(result,chunk,rest-chunk);
strcpy(result+(rest-chunk),new);
result[ln+(rest-chunk)] = '\n';
strcpy(result+(ln+(rest-chunk))+1,rest);
return result;
}
while( *rest != '\n' && *rest != '\0' )
rest++;
if( *rest == '\0' )
break;
rest++;
/* Reading a chunk should have ended there: */
assert(*rest != '\n');
} while( *rest );
fprintf(stderr,"not finding '%s', so appending '%s'\n",before,new);
/* not found, so append */
return mprintf("%s\n%s",chunk,new);
}
/* create a new chunk with the context of field name replaced with new */
char *chunk_replaceentry(const char *chunk,const char *name,const char *new) {
size_t l;
......@@ -353,3 +390,14 @@ retvalue chunk_gettruth(const char *chunk,const char *name) {
return RET_OK;
}
/* return RET_OK, if field is found, RET_NOTHING, if not */
retvalue chunk_checkfield(const char *chunk,const char *name){
const char *field;
field = chunk_getfield(name,chunk);
if( !field )
return RET_NOTHING;
return RET_OK;
}
......@@ -16,6 +16,8 @@ char *chunk_read(gzFile f);
/* create a new chunk with the context of field name replaced with new,
* prints an error when not found and adds to the end */
char *chunk_replaceentry(const char *chunk,const char *name,const char *new);
/* create a new chunk with the given data added before another field */
char *chunk_insertdata(const char *chunk,const char *before,const char *new);
/* look for name in chunk. returns RET_NOTHING if not found */
retvalue chunk_getvalue(const char *chunk,const char *name,char **value);
......@@ -24,6 +26,8 @@ retvalue chunk_getextralinelist(const char *chunk,const char *name,struct strlis
retvalue chunk_getwordlist(const char *chunk,const char *name,struct strlist *strlist);
/* return RET_OK, if field is found, RET_NOTHING, if not (or value indicates false in future variants) */
retvalue chunk_gettruth(const char *chunk,const char *name);
/* return RET_OK, if field is found, RET_NOTHING, if not */
retvalue chunk_checkfield(const char *chunk,const char *name);
typedef retvalue chunkaction(void *data,const char *chunk);
......
/* This file is part of "mirrorer" (TODO: find better title)
* Copyright (C) 2003 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 as published by
* the Free Software Foundation; either version 2 of the License, 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <config.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include "error.h"
#include "names.h"
#include "dirs.h"
#include "copyfile.h"
retvalue copyfile(const char *mirrordir,const char *filekey,const char *origfile) {
char *destfullfilename;
int ret,fd,fdw;
retvalue r;
struct stat stat;
ssize_t written;
void *content;
fd = open(origfile,O_NOCTTY|O_RDONLY);
if( fd < 0 ) {
ret = errno;
fprintf(stderr,"Error opening '%s': %m\n",origfile);
return RET_ERRNO(ret);
}
ret = fstat(fd,&stat);
if( ret < 0 ) {
ret = errno;
fprintf(stderr,"Error stat'ing '%s': %m\n",origfile);
close(fd);
return RET_ERRNO(ret);
}
content = mmap(NULL,stat.st_size,PROT_READ,MAP_SHARED,fd,0);
if( content == MAP_FAILED ) {
ret = errno;
fprintf(stderr,"Error mmap'ing '%s': %m\n",origfile);
close(fd);
return RET_ERRNO(ret);
}
destfullfilename = calc_fullfilename(mirrordir,filekey);
if( !destfullfilename ) {
close(fd);
return RET_ERROR_OOM;
}
r = dirs_make_parent(destfullfilename);
if( RET_WAS_ERROR(r) ) {
fprintf(stderr,"Error creating '%s': %m\n",destfullfilename);
free(destfullfilename);
close(fd);
return r;
}
fdw = open(destfullfilename,O_NOCTTY|O_WRONLY|O_CREAT|O_EXCL,0777);
if( fdw < 0 ) {
ret = errno;
fprintf(stderr,"Error creating '%s': %m\n",destfullfilename);
free(destfullfilename);
close(fd);
return RET_ERRNO(ret);
}
written = write(fdw,content,stat.st_size);
if( written < stat.st_size ) {
ret = errno;
fprintf(stderr,"Error while writing to '%s': %m\n",destfullfilename);
free(destfullfilename);
close(fd);
close(fdw);
return RET_ERRNO(ret);
}
ret = close(fdw);
if( ret < 0 ) {
ret = errno;
fprintf(stderr,"Error writing to '%s': %m\n",destfullfilename);
free(destfullfilename);
close(fd);
return RET_ERRNO(ret);
}
free(destfullfilename);
ret = munmap(content,stat.st_size);
if( ret < 0 ) {
ret = errno;
fprintf(stderr,"Error munmap'ing '%s': %m\n",origfile);
close(fd);
return RET_ERRNO(ret);
}
close(fd);
return RET_OK;
}
retvalue copyfile(const char *mirrordir,const char *filekey,const char *origfile);
......@@ -223,6 +223,7 @@ int files_expect(DB *filesdb,const char *mirrordir,const char *filekey,const cha
if( strcmp(md5andsize,realmd5andsize) != 0 ) {
fprintf(stderr,"File \"%s\" has other md5sum than expected!\n",filekey);
fprintf(stderr,"File \"%s\" had other md5sum (%s) than expected(%s)!\n",filekey,realmd5andsize,md5andsize);
free(realmd5andsize);
return RET_ERROR_WRONG_MD5;
}
......
......@@ -39,6 +39,9 @@
#include "updates.h"
#include "signature.h"
#include "extractcontrol.h"
#include "checkindeb.h"
#include "copyfile.h"
#ifndef STD_BASE_DIR
#define STD_BASE_DIR "/var/spool/mirrorer"
......@@ -645,52 +648,40 @@ static int prepareaddpackages(int argc,char *argv[]) {
/***********************************addpackages*******************************************/
static retvalue add_package(void *data,const char *chunk,const char *package,const char *sourcename,const char *oldfile,const char *basename,const char *filekey,const char *md5andsize,const char *oldchunk) {
retvalue add_package(void *data,const char *chunk,const char *package,const char *sourcename,const char *oldfile,const char *basename,const char *filekey,const char *md5andsize,const char *oldchunk) {
char *newchunk;
retvalue result,r;
struct distributionhandles *dist = (struct distributionhandles*)data;
char *oldfilekey;
struct distributionhandles *d = data;
/* look for needed files */
r = files_expect(dist->files,mirrordir,filekey,md5andsize);
r = files_expect(d->files,mirrordir,filekey,md5andsize);
if( ! RET_IS_OK(r) ) {
printf("Missing file %s\n",filekey);
return r;
}
/* mark it as needed by this distribution */
r = references_increment(dist->refs,filekey,dist->referee);
if( RET_WAS_ERROR(r) )
return r;
/* Add package to distribution's database */
/* Calculate new chunk, file to replace and checking */
newchunk = chunk_replaceentry(chunk,"Filename",filekey);
if( !newchunk )
return RET_ERROR;
if( oldchunk != NULL ) {
result = packages_replace(dist->pkgs,package,newchunk);
} else {
result = packages_add(dist->pkgs,package,newchunk);
}
free(newchunk);
if( RET_WAS_ERROR(result) )
return result;
/* remove old references to files */
if( oldchunk ) {
r = binaries_parse_chunk(oldchunk,NULL,&oldfilekey,NULL,NULL,NULL);
if( RET_IS_OK(r) ) {
r = references_decrement(dist->refs,oldfilekey,dist->referee);
free(oldfilekey);
if( RET_WAS_ERROR(r) ) {
free(newchunk);
return r;
}
RET_UPDATE(result,r);
}
} else
oldfilekey = NULL;
result = checkindeb_insert(d->refs,d->referee,d->pkgs,package,newchunk,filekey,oldfilekey);
free(newchunk);
free(oldfilekey);
return result;
}
......@@ -1338,6 +1329,62 @@ static int check(int argc,char *argv[]) {
return EXIT_RET(result);
}
/***********************adddeb******************************************/
static int adddeb(int argc,char *argv[]) {
retvalue r;
struct debpackage *pkg;
DB *files;
if( argc < 4 ) {
fprintf(stderr,"mirrorer _adddeb <distribution> <part> <package>\n");
return 1;
}
/* First taking a closer look to the file: */
r = deb_read(&pkg,argv[2],argv[3]);
if( RET_WAS_ERROR(r) ) {
return EXIT_RET(r);
}
fprintf(stderr,"%s,%s,%s,%s\n%s",pkg->package,pkg->source,pkg->version,pkg->arch,pkg->control);
/* then looking if we already have this, or copy it in */
files = files_initialize(dbdir);
if( !files )
return 1;
r = files_expect(files,mirrordir,pkg->filekey,pkg->md5andsize);
if( RET_WAS_ERROR(r) ) {
fprintf(stderr,"Error looking for file %s in archive\n",pkg->filekey);
deb_free(pkg);
return r;
}
if( r == RET_NOTHING ) {
if( verbose > 1 ) {
fprintf(stderr,"Trying to add as '%s'\n",pkg->filekey);
}
r = copyfile(mirrordir,pkg->filekey,argv[3]);
if( RET_WAS_ERROR(r) ) {
fprintf(stderr,"Error moving file %s to %s/%s\n",argv[3],mirrordir,pkg->filekey);
deb_free(pkg);
return r;
}
// TODO: add it to database here.
// (hm, how to handle md5sum?)
}
files_done(files);
/* Finaly add it to the database */
deb_free(pkg);
return 0;
}
/*********************/
/* argument handling */
/*********************/
......@@ -1369,6 +1416,7 @@ static struct action {
{"_addmd5sums",addmd5sums},
{"update",update},
{"__extractcontrol",extract_control},
{"_adddeb",adddeb},
{NULL,NULL}
};
......
......@@ -103,7 +103,7 @@ retvalue md5sum_and_size(char **result,const char *filename,ssize_t bufsize){
}
}
retvalue md5sum(char *result,const char *filename,ssize_t bufsize){
retvalue md5sum(char *result,off_t *size,const char *filename,ssize_t bufsize){
return md5sumAndSize(result,NULL,filename,bufsize);
return md5sumAndSize(result,size,filename,bufsize);
}
......@@ -10,7 +10,7 @@
* bufsize is the size of the buffer to be used, use 0 for
* standard size.
*/
retvalue md5sum(char *result,const char *filename,ssize_t bufsize);
retvalue md5sum(char *result,off_t *size,const char *filename,ssize_t bufsize);
/* returns md5sum " " size */
retvalue md5sum_and_size(char **result,const char *filename,ssize_t bufsize);
......
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