|
From: Keith M. <kei...@us...> - 2010-02-02 20:19:36
|
Update of /cvsroot/mingw/mingw-get/src In directory sfp-cvsdas-1.v30.ch3.sourceforge.com:/tmp/cvs-serv23477/src Modified Files: climain.cpp mkpath.c mkpath.h pkgbase.h pkgdeps.cpp pkgexec.cpp pkginet.cpp pkgkeys.c pkgkeys.h pkgname.cpp sysroot.cpp Added Files: pkgproc.h tarproc.cpp Log Message: Implement package installer for tar archives. Index: pkgkeys.h =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/pkgkeys.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** pkgkeys.h 26 Jan 2010 21:07:18 -0000 1.2 --- pkgkeys.h 2 Feb 2010 20:19:28 -0000 1.3 *************** *** 41,44 **** --- 41,45 ---- EXTERN_C_DECL const char *catalogue_key; EXTERN_C_DECL const char *component_key; + EXTERN_C_DECL const char *download_key; EXTERN_C_DECL const char *download_host_key; EXTERN_C_DECL const char *eq_key; *************** *** 51,54 **** --- 52,56 ---- EXTERN_C_DECL const char *lt_key; EXTERN_C_DECL const char *mirror_key; + EXTERN_C_DECL const char *modified_key; EXTERN_C_DECL const char *name_key; EXTERN_C_DECL const char *package_key; *************** *** 60,63 **** --- 62,66 ---- EXTERN_C_DECL const char *repository_key; EXTERN_C_DECL const char *requires_key; + EXTERN_C_DECL const char *source_key; EXTERN_C_DECL const char *subsystem_key; EXTERN_C_DECL const char *sysmap_key; Index: pkgexec.cpp =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/pkgexec.cpp,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** pkgexec.cpp 26 Jan 2010 21:07:18 -0000 1.4 --- pkgexec.cpp 2 Feb 2010 20:19:28 -0000 1.5 *************** *** 32,35 **** --- 32,36 ---- #include "pkginfo.h" #include "pkgtask.h" + #include "pkgproc.h" EXTERN_C const char *action_name( unsigned long index ) *************** *** 387,391 **** * installer implementation. */ ! dmh_printf( " installing %s\n", current->Selection()->GetPropVal( tarname_key, "<unknown>" )); } --- 388,403 ---- * installer implementation. */ ! //dmh_printf( " installing %s\n", current->Selection()->GetPropVal( tarname_key, "<unknown>" )); ! if( current->Selection( to_remove ) == NULL ) ! { ! pkgTarArchiveInstaller package( current->Selection() ); ! if( package.IsOk() ) ! package.Process(); ! } ! else ! dmh_notify( DMH_ERROR, ! "package %s is already installed\n", ! current->Selection()->GetPropVal( tarname_key, "<unknown>" ) ! ); } Index: sysroot.cpp =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/sysroot.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** sysroot.cpp 22 Jan 2010 17:11:48 -0000 1.1 --- sysroot.cpp 2 Feb 2010 20:19:28 -0000 1.2 *************** *** 112,115 **** --- 112,117 ---- } + static const char *sigpath = "%R" "var/lib/mingw-get/data/%F.xml"; + void pkgXmlDocument::LoadSystemMap() { *************** *** 193,197 **** */ int retry = 0; - const char *sigpath = "%R" "var/lib/mingw-get/data/%F.xml"; while( retry < 16 ) --- 195,198 ---- *************** *** 256,283 **** * finding no existing mapping database for this sysroot... * The current hashed file name has not yet been assigned, ! * so initialise it as a new database for this sysroot. * * FIXME: perhaps we should not do this arbitrarily for * any non-default system root. */ ! check.AddDeclaration( "1.0", "UTF-8", "yes" ); ! ! /* Initialise the root element for this new database. ! */ ! pkgXmlNode root( sysroot_key ); ! root.SetAttribute( id_key, sig ); ! root.SetAttribute( pathname_key, path ); ! check.SetRoot( &root ); ! ! /* Link a copy of it as the corresponding sysroot ! * entry in the internal database. ! */ ! dbase->AddChild( root.Clone() ); ! /* Commit the initial state of this sysroot database ! * to a disk file, for future reference, and terminate ! * the retry loop at the end of this cycle. */ - check.Save( sigfile ); retry = 16; } --- 257,275 ---- * finding no existing mapping database for this sysroot... * The current hashed file name has not yet been assigned, ! * so create a new entry in the internal XML database, ! * marking it as "modified", so that it will be written ! * to disk, when the system map is updated. * * FIXME: perhaps we should not do this arbitrarily for * any non-default system root. */ ! pkgXmlNode *record = new pkgXmlNode( sysroot_key ); ! record->SetAttribute( modified_key, yes_value ); ! record->SetAttribute( id_key, sig ); ! record->SetAttribute( pathname_key, path ); ! dbase->AddChild( record ); ! /* Finally, force termination of the sysroot search. */ retry = 16; } *************** *** 320,323 **** --- 312,357 ---- } + void pkgXmlDocument::UpdateSystemMap() + { + /* Inspect all sysroot records in the current system map; + * save copies of any marked with the 'modified' attribute + * to the appropriate disk files. + */ + pkgXmlNode *entry = GetRoot()->FindFirstAssociate( sysroot_key ); + + while( entry != NULL ) + { + /* We found a sysroot record... + * evaluate and clear its 'modified' attribute... + */ + const char *modified = entry->GetPropVal( modified_key, no_value ); + entry->RemoveAttribute( modified_key ); + + if( (strcmp( modified, yes_value ) == 0) + && ((modified = entry->GetPropVal( id_key, NULL )) != NULL) ) + { + /* The 'modified' attribute for this record was set, + * and the 'id' attribute is valid; establish the path + * name for the file in which to save the record. + */ + char mapfile[mkpath( NULL, sigpath, modified, NULL )]; + mkpath( mapfile, sigpath, modified, NULL ); + + /* Create a copy of the sysroot record, as the content of + * a new freestanding XML document, and write it out to the + * nominated record file. + */ + pkgXmlDocument map; + map.AddDeclaration( "1.0", "UTF-8", yes_value ); + map.SetRoot( entry->Clone() ); + map.Save( mapfile ); + } + + /* Repeat for the next sysroot record, if any... + */ + entry = entry->FindNextAssociate( sysroot_key ); + } + } + pkgXmlNode* pkgXmlNode::GetSysRoot( const char *subsystem ) { Index: mkpath.h =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/mkpath.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** mkpath.h 16 Nov 2009 21:54:30 -0000 1.1 --- mkpath.h 2 Feb 2010 20:19:28 -0000 1.2 *************** *** 42,44 **** --- 42,46 ---- EXTERN_C int mkpath( char *, const char *, const char *, const char * ); + EXTERN_C const char *pkgArchivePath(); + #endif /* MKPATH_H: $RCSfile$: end of file */ Index: climain.cpp =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/climain.cpp,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** climain.cpp 26 Jan 2010 21:07:17 -0000 1.5 --- climain.cpp 2 Feb 2010 20:19:24 -0000 1.6 *************** *** 97,103 **** dbase.Schedule( (unsigned long)(action), *++argv ); ! /* ...and finally, execute all scheduled actions. */ dbase.ExecuteActions(); } --- 97,105 ---- dbase.Schedule( (unsigned long)(action), *++argv ); ! /* ...finally, execute all scheduled actions, and update the ! * system map accordingly. */ dbase.ExecuteActions(); + dbase.UpdateSystemMap(); } Index: pkgkeys.c =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/pkgkeys.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** pkgkeys.c 26 Jan 2010 21:07:18 -0000 1.2 --- pkgkeys.c 2 Feb 2010 20:19:28 -0000 1.3 *************** *** 30,33 **** --- 30,34 ---- const char *catalogue_key = "catalogue"; const char *component_key = "component"; + const char *download_key = "download"; const char *download_host_key = "download-host"; const char *eq_key = "eq"; *************** *** 40,43 **** --- 41,45 ---- const char *lt_key = "lt"; const char *mirror_key = "mirror"; + const char *modified_key = "modified"; const char *name_key = "name"; const char *package_key = "package"; *************** *** 49,52 **** --- 51,55 ---- const char *repository_key = "repository"; const char *requires_key = "requires"; + const char *source_key = "source"; const char *subsystem_key = "subsystem"; const char *sysmap_key = "system-map"; --- NEW FILE: tarproc.cpp --- /* * tarproc.cpp * * $Id: tarproc.cpp,v 1.1 2010/02/02 20:19:28 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, 2010, MinGW Project * * * Implementation of package archive processing methods, for reading * and extracting content from tar archives. * * * This is free software. Permission is granted to copy, modify and * redistribute this software, under the provisions of the GNU General * Public License, Version 3, (or, at your option, any later version), * as published by the Free Software Foundation; see the file COPYING * for licensing details. * * Note, in particular, that this software is provided "as is", in the * hope that it may prove useful, but WITHOUT WARRANTY OF ANY KIND; not * even an implied WARRANTY OF MERCHANTABILITY, nor of FITNESS FOR ANY * PARTICULAR PURPOSE. Under no circumstances will the author, or the * MinGW Project, accept liability for any damages, however caused, * arising from the use of this software. * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include "dmh.h" #include "mkpath.h" #include "pkginfo.h" #include "pkgkeys.h" #include "pkgproc.h" pkgTarArchiveProcessor::pkgTarArchiveProcessor( pkgXmlNode *pkg ) { /* Constructor to associate a package tar archive with its * nominated sysroot and respective installation directory path, * and prepare it for processing, using an appropriate streaming * decompression filter; (choice of filter is based on archive * file name extension; file names are restricted to the * POSIX Portable Character Set). * * First, we anticipate an invalid initialisation state... */ sysroot = NULL; sysroot_path = NULL; stream = NULL; /* The 'pkg' XML database entry must be non-NULL, must * represent a package release, and must specify a canonical * tarname to identify the package... */ if( (pkg != NULL) && pkg->IsElementOfType( release_key ) && ((tarname = pkg->GetPropVal( tarname_key, NULL )) != NULL) ) { /* When these pre-conditions are satisfied, we may proceed * to identify and locate the sysroot record with which this * package is to be associated... */ pkgSpecs lookup( pkgfile = tarname ); if( (sysroot = pkg->GetSysRoot( lookup.GetSubSystemName() )) != NULL ) { /* Having located the requisite sysroot record, we may * retrieve its specified installation path prefix... */ const char *prefix; if( (prefix = sysroot->GetPropVal( pathname_key, NULL )) != NULL ) { /* ...and incorporate it into a formatting template * for use in deriving the full path names for files * which are installed from this package. */ const char *template_format = "%F%%/M/%%F"; char template_text[mkpath( NULL, template_format, prefix, NULL )]; mkpath( template_text, template_format, prefix, NULL ); sysroot_path = strdup( template_text ); } } /* Some older packages don't use the canonical tarname * for the archive file name; identify the real file name * associated with such packages... */ pkgfile = pkg->ArchiveName(); /* Finally, initialise the data stream which we will use * for reading the package content. */ const char *archive_path_template = pkgArchivePath(); char archive_path_name[mkpath( NULL, archive_path_template, pkgfile, NULL )]; mkpath( archive_path_name, archive_path_template, pkgfile, NULL ); stream = pkgOpenArchiveStream( archive_path_name ); } } pkgTarArchiveProcessor::~pkgTarArchiveProcessor() { /* Destructor must release the heap memory allocated in the * constructor, (by strdup), clean up the decompression filter * state, and close the archive data stream. */ free( (void *)(sysroot_path) ); delete stream; } int pkgTarArchiveProcessor::ProcessLinkedEntity( const char *pathname ) { /* FIXME: Win32 links need special handling; for hard links, we * may be able to create them directly, with >= Win2K and NTFS; * for symlinks on *all* Win32 variants, and for hard links on * FAT32 or Win9x, we need to make physical copies of the source * file, at the link target location. * * For now, we simply ignore links. */ dmh_printf( "FIXME:ProcessLinkedEntity<stub>:Ignoring link: %s --> %s\n", pathname, header.field.linkname ); return 0; } static uint64_t compute_octval( const char *p, size_t len ) # define octval( FIELD ) compute_octval( FIELD, sizeof( FIELD ) ) { /* Helper to convert the ASCII representation of octal values, * (as recorded within tar archive header fields), to their actual * numeric values, ignoring leading or trailing garbage. */ uint64_t value = 0LL; while( (len > 0) && ((*p < '0') || (*p > '7')) ) { /* Step over leading garbage. */ ++p; --len; } while( (len > 0) && (*p >= '0') && (*p < '8') ) { /* Accumulate octal digits; (each represents exactly three * bits in the accumulated value), until we either exhaust * the width of the field, or we encounter trailing junk. */ value = (value << 3) + *p++ - '0'; --len; } return value; } int pkgTarArchiveProcessor::GetArchiveEntry() { /* Read header for next available entry in the tar archive; * check for end-of-archive mark, (all zero header); verify * checksum for active entry. */ char *buf = header.aggregate; size_t count = stream->Read( buf, sizeof( header ) ); if( count < sizeof( header ) ) { /* Failed to read a complete header; return error code. */ return -1; } while( count-- ) /* * Outer loop checks for an all zero header... */ if( *buf++ != '\0' ) { /* Any non-zero byte transfers control to an inner loop, * to rescan the entire header, accumulating its checksum... */ uint64_t sum = 0; for( buf = header.aggregate, count = sizeof( header ); count--; ++buf ) { if( (buf < header.field.chksum) || (buf >= header.field.typeflag) ) /* * ...counting the actual binary value of each byte, * in all but the checksum field itself... */ sum += *buf; else /* ...while treating each byte within the checksum field as * having an effective value equivalent to ASCII <space>. */ sum += 0x20; } /* After computing the checksum for a non-zero header, * verify it against the value recorded in the checksum field; * return +1 for a successful match, or -2 for failure. */ return (sum == octval( header.field.chksum )) ? 1 : -2; } /* If we get to here, then the inner loop was never entered; * the outer loop has completed, confirming an all zero header; * return zero, to indicate end of archive. */ return 0; } int pkgTarArchiveProcessor::Process() { /* Generic method for reading tar archives, and extracting their * content; loops over each archive entry in turn... */ while( GetArchiveEntry() > 0 ) { /* Found an archive entry; map it to an equivalent file system * path name, within the designated sysroot hierarchy. */ char *prefix = *header.field.prefix ? header.field.prefix : NULL; char pathname[mkpath( NULL, sysroot_path, header.field.name, prefix )]; mkpath( pathname, sysroot_path, header.field.name, prefix ); /* Direct further processing to the appropriate handler; (this * is specific to the archive entry classification)... */ switch( *header.field.typeflag ) { int status; case TAR_ENTITY_TYPE_DIRECTORY: /* * We may need to take some action in respect of directories; * e.g. we may need to create a directory, or even a sequence * of directories, to establish a location within the sysroot * hierarchy... * */ status = ProcessDirectory( pathname ); break; case TAR_ENTITY_TYPE_LINK: case TAR_ENTITY_TYPE_SYMLINK: /* * Links ultimately represent file system entities in * our sysroot hierarchy, but we need special processing * to handle them correctly... * */ status = ProcessLinkedEntity( pathname ); break; case TAR_ENTITY_TYPE_FILE: case TAR_ENTITY_TYPE_ALTFILE: /* * These represent regular files; the file content is * embedded within the archive stream, so we need to be * prepared to read or copy it, as appropriate... * */ ProcessDataStream( pathname ); break; default: /* FIXME: we make no provision for handling any other * type of archive entry; we should provide some more * robust error handling, but for now we simply emit * a diagnostic, and return an error condition code... * */ dmh_notify( DMH_ERROR, "unexpected archive entry classification: type %d\n", (int)(*header.field.typeflag) ); return -1; } } /* If we didn't bail out before getting to here, then the archive * was processed successfully; return the success code. */ return 0; } int pkgTarArchiveProcessor::ProcessEntityData( int fd ) { /* Generic method for reading past the data associated with * a specific header within a tar archive; if given a negative * value for `fd', it will simply skip over the data, otherwise * `fd' is assumed to represent a descriptor for an opened file * stream, to which the data will be copied (extracted). */ int status = 0; /* Initialise a counter for the length of the data content, and * specify the default size for the transfer buffer in which to * process it; make the initial size of the transfer buffer 16 * times the header size. */ uint64_t bytes_to_copy = octval( header.field.size ); size_t block_size = sizeof( header ) << 4; /* While we still have unread data, and no processing error... */ while( (bytes_to_copy > 0) && (status == 0) ) { /* Adjust the requested size for the transfer buffer, shrinking * it by 50% at each step, until it is smaller than the remaining * data length, but never smaller than the header record length. */ while( (bytes_to_copy < block_size) && (block_size > sizeof( header )) ) block_size >>= 1; /* Allocate a transfer buffer of the requested size, and populate * it, by reading data from the archive; (since the transfer buffer * is never smaller than the header length, this will also capture * any additional padding bytes, which may be required to keep the * data length equal to an exact multiple of the header length). */ char buffer[block_size]; if( stream->Read( buffer, block_size ) < (int)(block_size) ) /* * Failure to fully populate the transfer buffer, (i.e. a short * read), indicates a corrupt archive; bail out immediately. */ return -1; /* When the number of actual data bytes expected is fewer than the * total number of bytes in the transfer buffer... */ if( bytes_to_copy < block_size ) /* * ...then we have reached the end of the data for the current * archived entity; adjust the block size to reflect the number * of actual data bytes present in the transfer buffer... */ block_size = bytes_to_copy; /* With the number of actual data bytes present now accurately * reflected by the block size, we save that data to the stream * specified for archive extraction, (if any). */ if( (fd >= 0) && (write( fd, buffer, block_size ) != (int)(block_size)) ) /* * An extraction error occurred; set the status code to * indicate failure. */ status = -2; /* Adjust the count of remaining unprocessed data bytes, and begin * a new processing cycle, to capture any which may be present. */ bytes_to_copy -= block_size; } /* Finally, when all data for the current archive entry has been * processed, we return to the caller with an appropriate completion * status code. */ return status; } /* Here, we implement the methods for installing software from * packages which are distributed in the form of tar archives. * */ #include <utime.h> static int commit_saved_entity( const char *pathname, time_t mtime ) { /* Helper to set the access and modification times for a file, * after extraction from an archive, to match the specified "mtime"; * (typically "mtime" is as recorded within the archive). */ struct utimbuf timestamp; timestamp.actime = timestamp.modtime = mtime; return utime( pathname, ×tamp ); } pkgTarArchiveInstaller:: pkgTarArchiveInstaller( pkgXmlNode *pkg ):pkgTarArchiveProcessor( pkg ) { /* Constructor: having set up the pkgTarArchiveProcessor base class, * we add a package installation record to the sysroot entry in the * XML database, and mark that sysroot entry as 'modified'. */ if( (tarname != NULL) && (sysroot != NULL) ) { sysroot->SetAttribute( modified_key, yes_value ); pkgXmlNode *installed = new pkgXmlNode( installed_key ); installed->SetAttribute( tarname_key, tarname ); if( pkgfile != tarname ) { pkgXmlNode *download = new pkgXmlNode( download_key ); download->SetAttribute( tarname_key, pkgfile ); installed->AddChild( download ); } sysroot->AddChild( installed ); } } int pkgTarArchiveInstaller::ProcessDirectory( const char *pathname ) { #if DEBUGLEVEL < 5 int status; if( (status = mkdir_recursive( pathname, 0755 )) != 0 ) dmh_notify( DMH_ERROR, "cannot create directory `%s'\n", pathname ); #else int status = 0; dmh_printf( "FIXME:ProcessDirectory<stub>:not executing: mkdir -p %s\n", pathname ); #endif return status; } int pkgTarArchiveInstaller::ProcessDataStream( const char *pathname ) { #if DEBUGLEVEL < 5 int fd = set_output_stream( pathname, octval( header.field.mode ) ); int status = ProcessEntityData( fd ); if( fd >= 0 ) { close( fd ); if( status == 0 ) commit_saved_entity( pathname, octval( header.field.mtime ) ); else { unlink( pathname ); dmh_notify( DMH_ERROR, "%s: extraction failed\n", pathname ); } } return status; #else dmh_printf( "FIXME:ProcessDataStream<stub>:not extracting: %s\n", pathname ); return ProcessEntityData( -1 ); #endif } /* $RCSfile: tarproc.cpp,v $: end of file */ Index: mkpath.c =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/mkpath.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** mkpath.c 16 Nov 2009 21:54:30 -0000 1.1 --- mkpath.c 2 Feb 2010 20:19:28 -0000 1.2 *************** *** 67,70 **** --- 67,78 ---- #endif + const char *pkgArchivePath() + { + /* Specify where downloaded packages are cached, + * within the local file system. + */ + return "%R" "var/cache/mingw-get/packages" "%/M/%F"; + } + int mkpath( char *buf, const char *fmt, const char *file, const char *modifier ) { Index: pkgname.cpp =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/pkgname.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** pkgname.cpp 16 Jan 2010 20:49:57 -0000 1.2 --- pkgname.cpp 2 Feb 2010 20:19:28 -0000 1.3 *************** *** 108,112 **** * "source" element specifying a "tarname" property. */ ! return pkgArchiveName( this, "source", 0 ); } --- 108,112 ---- * "source" element specifying a "tarname" property. */ ! return pkgArchiveName( this, source_key, 0 ); } *************** *** 125,129 **** * unresolved to either of these, returns NULL. */ ! return pkgArchiveName( this, "download", 1 ); } --- 125,129 ---- * unresolved to either of these, returns NULL. */ ! return pkgArchiveName( this, download_key, 1 ); } Index: pkginet.cpp =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/pkginet.cpp,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** pkginet.cpp 26 Jan 2010 21:07:18 -0000 1.5 --- pkginet.cpp 2 Feb 2010 20:19:28 -0000 1.6 *************** *** 96,107 **** static pkgInternetAgent pkgDownloadAgent; - const char *pkgActionItem::ArchivePath() - { - /* Specify where downloaded packages are cached, - * within the local file system. - */ - return "%R" "var/cache/mingw-get/packages" "%/M/%F"; - } - class pkgInternetStreamingAgent { --- 96,99 ---- *************** *** 290,294 **** */ const char *package_name = current->Selection()->ArchiveName(); ! pkgInternetStreamingAgent download( package_name, current->ArchivePath() ); /* Check if the required archive is already available locally... --- 282,286 ---- */ const char *package_name = current->Selection()->ArchiveName(); ! pkgInternetStreamingAgent download( package_name, pkgArchivePath() ); /* Check if the required archive is already available locally... --- NEW FILE: pkgproc.h --- #ifndef PKGPROC_H /* * pkgproc.h * * $Id: pkgproc.h,v 1.1 2010/02/02 20:19:28 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, 2010, MinGW Project * * * Specifications for the internal architecture of package archives, * and the public interface for the package archive processing routines, * used to implement the package installer and uninstaller. * * * This is free software. Permission is granted to copy, modify and * redistribute this software, under the provisions of the GNU General * Public License, Version 3, (or, at your option, any later version), * as published by the Free Software Foundation; see the file COPYING * for licensing details. * * Note, in particular, that this software is provided "as is", in the * hope that it may prove useful, but WITHOUT WARRANTY OF ANY KIND; not * even an implied WARRANTY OF MERCHANTABILITY, nor of FITNESS FOR ANY * PARTICULAR PURPOSE. Under no circumstances will the author, or the * MinGW Project, accept liability for any damages, however caused, * arising from the use of this software. * */ #define PKGPROC_H 1 #include "pkgbase.h" #include "pkgstrm.h" class pkgArchiveProcessor { /* A minimal generic abstract base class, from which we derive * processing tools for handling arbitrary package architectures. */ public: pkgArchiveProcessor(){} virtual ~pkgArchiveProcessor(){} virtual bool IsOk() = 0; virtual int Process() = 0; protected: /* Pointers to the sysroot management records and installation * path template for a managed package; note that 'tarname' does * not explicitly refer only to tar archives; it is simply the * canonical name of the archive file, as recorded in the XML * 'tarname' property of the package identifier record. */ pkgXmlNode *sysroot; const char *sysroot_path; const char *tarname; const char *pkgfile; }; /* Our standard package format specifies the use of tar archives; * the following specialisation of pkgArchiveProcessor provides the * tools we need for processing such archives. * */ union tar_archive_header { /* Layout specification for the tar archive header records, * one of which is associated with each individual data entity * stored within a tar archive. */ char aggregate[512]; /* aggregate size is always 512 bytes */ struct tar_header_field_layout { char name[100]; /* archive entry path name */ char mode[8]; /* unix access mode for archive entry */ char uid[8]; /* user id of archive entry's owner */ char gid[8]; /* group id of archive entry's owner */ char size[12]; /* size of archive entry in bytes */ char mtime[12]; /* last modification time of entry */ char chksum[8]; /* checksum for this header block */ char typeflag[1]; /* type of this archive entry */ char linkname[100]; /* if a link, name of linked file */ char magic[6]; /* `magic' signature for the archive */ char version[2]; /* specification conformance code */ char uname[32]; /* user name of archive entry's owner */ char gname[32]; /* group name of entry's owner */ char devmajor[8]; /* device entity major number */ char devminor[8]; /* device entity minor number */ char prefix[155]; /* prefix to extend "name" field */ } field; }; /* Type descriptors, as used in the `typeflag' field of the above * tar archive header records; (note: this is not a comprehensive * list, but covers all of, and more than, our requirements). */ #define TAR_ENTITY_TYPE_FILE '0' #define TAR_ENTITY_TYPE_LINK '1' #define TAR_ENTITY_TYPE_SYMLINK '2' #define TAR_ENTITY_TYPE_CHRDEV '3' #define TAR_ENTITY_TYPE_BLKDEV '4' #define TAR_ENTITY_TYPE_DIRECTORY '5' /* Some older style tar archives may use '\0' as an alternative to '0', * to identify an archive entry representing a regular file. */ #define TAR_ENTITY_TYPE_ALTFILE '\0' class pkgTarArchiveProcessor : public pkgArchiveProcessor { /* An abstract base class, from which various tar archive * processing tools, (including installers and uninstallers), * are derived; this class implements the generic methods, * which are shared by all such tools. */ public: /* Constructor and destructor... */ pkgTarArchiveProcessor( pkgXmlNode* ); virtual ~pkgTarArchiveProcessor(); inline bool IsOk(){ return stream->IsReady(); } virtual int Process(); protected: /* Class data... */ pkgArchiveStream *stream; union tar_archive_header header; /* Internal archive processing methods... * These are divided into two categories: those for which the * abstract base class furnishes a generic implementation... */ virtual int GetArchiveEntry(); virtual int ProcessEntityData( int ); /* ...those for which each specialisation is expected to * furnish its own task specific implementation... */ virtual int ProcessDirectory( const char* ) = 0; virtual int ProcessDataStream( const char* ) = 0; /* ...and those which would normally be specialised, but * for which we currently provide a generic stub... */ virtual int ProcessLinkedEntity( const char* ); }; class pkgTarArchiveInstaller : public pkgTarArchiveProcessor { public: /* Constructor and destructor... */ pkgTarArchiveInstaller( pkgXmlNode* ); virtual ~pkgTarArchiveInstaller(){} private: /* Specialised implementations of the archive processing methods... */ virtual int ProcessDirectory( const char* ); virtual int ProcessDataStream( const char* ); }; class pkgTarArchiveUninstaller : public pkgTarArchiveProcessor { public: /* Constructor and destructor... */ pkgTarArchiveUninstaller( pkgXmlNode* ); virtual ~pkgTarArchiveUninstaller(){}; private: /* Specialised implementations of the archive processing methods... */ virtual int ProcessDirectory( const char* ); virtual int ProcessDataStream( const char* ); }; #endif /* PKGPROC_H: $RCSfile: pkgproc.h,v $: end of file */ Index: pkgbase.h =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/pkgbase.h,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** pkgbase.h 26 Jan 2010 21:07:18 -0000 1.4 --- pkgbase.h 2 Feb 2010 20:19:28 -0000 1.5 *************** *** 216,223 **** } - /* Method specifying where downloaded packages are stored. - */ - const char* ArchivePath(); - /* Method for processing all scheduled actions. */ --- 216,219 ---- *************** *** 233,236 **** --- 229,233 ---- /* Constructors... */ + inline pkgXmlDocument(){} inline pkgXmlDocument( const char* name ) { *************** *** 267,272 **** * this is a convenience method for setting up a new XML database. */ ! TiXmlDeclaration decl( version, encoding, standalone ); ! LinkEndChild( &decl ); } inline void SetRoot( TiXmlNode* root ) --- 264,268 ---- * this is a convenience method for setting up a new XML database. */ ! LinkEndChild( new TiXmlDeclaration( version, encoding, standalone ) ); } inline void SetRoot( TiXmlNode* root ) *************** *** 311,314 **** --- 307,315 ---- void LoadSystemMap(); + /* Complementary method, to update the saved sysroot data associated + * with the active system map. + */ + void UpdateSystemMap(); + /* Method to locate the XML database entry for a named package. */ Index: pkgdeps.cpp =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/pkgdeps.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pkgdeps.cpp 26 Jan 2010 21:08:30 -0000 1.1 --- pkgdeps.cpp 2 Feb 2010 20:19:28 -0000 1.2 *************** *** 299,303 **** * which is currently installed... */ ! installed = release; if( latest.SelectIfMostRecentFit( release ) == release ) --- 299,303 ---- * which is currently installed... */ ! latest.SelectPackage( installed = release, to_remove ); if( latest.SelectIfMostRecentFit( release ) == release ) |