From: Keith M. <kei...@us...> - 2010-04-04 15:25:45
|
Update of /cvsroot/mingw/mingw-get/src In directory sfp-cvsdas-4.v30.ch3.sourceforge.com:/tmp/cvs-serv8618 Modified Files: pkgexec.cpp pkgkeys.c pkgkeys.h pkgproc.h tarproc.cpp Added Files: pkginst.cpp tarinst.cpp Log Message: Implement installer function; use per-package file manifests. Index: pkgkeys.h =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/pkgkeys.h,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** pkgkeys.h 2 Mar 2010 22:33:24 -0000 1.6 --- pkgkeys.h 4 Apr 2010 15:25:36 -0000 1.7 *************** *** 54,57 **** --- 54,58 ---- EXTERN_C_DECL const char *le_key; EXTERN_C_DECL const char *lt_key; + EXTERN_C_DECL const char *manifest_key; EXTERN_C_DECL const char *mirror_key; EXTERN_C_DECL const char *modified_key; *************** *** 62,65 **** --- 63,67 ---- EXTERN_C_DECL const char *pathname_key; EXTERN_C_DECL const char *profile_key; + EXTERN_C_DECL const char *reference_key; EXTERN_C_DECL const char *release_key; EXTERN_C_DECL const char *repository_key; Index: pkgexec.cpp =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/pkgexec.cpp,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** pkgexec.cpp 2 Mar 2010 22:33:18 -0000 1.6 --- pkgexec.cpp 4 Apr 2010 15:25:36 -0000 1.7 *************** *** 381,408 **** if( (current->flags & ACTION_INSTALL) == ACTION_INSTALL ) ! { ! /* The selected package has been marked for installation, either explicitly, * or implicitly to complete a package upgrade. - * - * FIXME: Once more, this is a stub, to be extended to provide the working - * installer implementation. */ ! //dmh_printf( " installing %s\n", current->Selection()->GetPropVal( tarname_key, "<unknown>" )); ! if( current->Selection( to_remove ) == NULL ) ! { ! pkgXmlNode *pkg = current->Selection(); ! if( ! match_if_explicit( pkg->ArchiveName(), value_none ) ) ! { ! pkgTarArchiveInstaller package( pkg ); ! if( package.IsOk() ) ! package.Process(); ! } ! } ! else ! dmh_notify( DMH_ERROR, ! "package %s is already installed\n", ! current->Selection()->GetPropVal( tarname_key, "<unknown>" ) ! ); ! } /* Proceed to next package with scheduled actions. --- 381,389 ---- if( (current->flags & ACTION_INSTALL) == ACTION_INSTALL ) ! /* ! * The selected package has been marked for installation, either explicitly, * or implicitly to complete a package upgrade. */ ! pkgInstall( current ); /* Proceed to next package with scheduled actions. Index: pkgkeys.c =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/pkgkeys.c,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** pkgkeys.c 2 Mar 2010 22:33:24 -0000 1.6 --- pkgkeys.c 4 Apr 2010 15:25:36 -0000 1.7 *************** *** 43,46 **** --- 43,47 ---- const char *le_key = "le"; const char *lt_key = "lt"; + const char *manifest_key = "manifest"; const char *mirror_key = "mirror"; const char *modified_key = "modified"; *************** *** 51,54 **** --- 52,56 ---- const char *pathname_key = "path"; const char *profile_key = "profile"; + const char *reference_key = "references"; const char *release_key = "release"; const char *repository_key = "repository"; Index: tarproc.cpp =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/tarproc.cpp,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** tarproc.cpp 2 Mar 2010 21:07:00 -0000 1.4 --- tarproc.cpp 4 Apr 2010 15:25:36 -0000 1.5 *************** *** 53,58 **** --- 53,61 ---- * First, we anticipate an invalid initialisation state... */ + sysroot_len = 0; + sysroot = NULL; sysroot_path = NULL; + installed = NULL; stream = NULL; *************** *** 61,66 **** * 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 --- 64,69 ---- * tarname to identify the package... */ ! if( ((origin = pkg) != NULL) && pkg->IsElementOfType( release_key ) ! && ((tarname = pkg->GetPropVal( tarname_key, NULL )) != NULL) ) { /* When these pre-conditions are satisfied, we may proceed *************** *** 83,87 **** 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 ); } --- 86,90 ---- const char *template_format = "%F%%/M/%%F"; char template_text[mkpath( NULL, template_format, prefix, NULL )]; ! sysroot_len = mkpath( template_text, template_format, prefix, NULL ) - 6; sysroot_path = strdup( template_text ); } *************** *** 105,113 **** 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; } --- 108,118 ---- pkgTarArchiveProcessor::~pkgTarArchiveProcessor() { ! /* Destructor must release the heap memory allocated in ! * the constructor, (by strdup and pkgManifest), clean up ! * the decompression filter state, and close the archive ! * data stream. */ free( (void *)(sysroot_path) ); + delete installed; delete stream; } *************** *** 238,251 **** * of directories, to establish a location within the sysroot * hierarchy... - * - * Note: Microsoft's implementation of stat() appears to choke - * on directory path names with trailing slashes; thus, before - * we invoke the directory processing routine, (which may need - * to call stat(), to check if the specified directory already - * exists), we remove any such trailing slashes. */ ! char *p = pathname + sizeof( pathname ) - 1; ! while( (p > pathname) && ((*--p == '/') || (*p == '\\')) ) ! *p = '\0'; /* We are now ready to process the directory path name entry... --- 243,257 ---- * of directories, to establish a location within the sysroot * hierarchy... */ ! { /* Note: Microsoft's implementation of stat() appears to choke ! * on directory path names with trailing slashes; thus, before ! * we invoke the directory processing routine, (which may need ! * to call stat(), to check if the specified directory already ! * exists), we remove any such trailing slashes. ! */ ! char *p = pathname + sizeof( pathname ) - 1; ! while( (p > pathname) && ((*--p == '/') || (*p == '\\')) ) ! *p = '\0'; ! } /* We are now ready to process the directory path name entry... *************** *** 374,526 **** } - /* 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) && stream->IsReady() ) - { - /* The installation record must identify, as a minimum, - * the canonical name of the package being installed. - */ - installed = new pkgXmlNode( installed_key ); - installed->SetAttribute( tarname_key, tarname ); - if( pkgfile != tarname ) - { - /* If the real package tarball name isn't identically - * the same as the canonical name, we record the real - * file name too. - */ - pkgXmlNode *download = new pkgXmlNode( download_key ); - download->SetAttribute( tarname_key, pkgfile ); - installed->AddChild( download ); - } - - /* Set the 'modified' flag for, and attach the installation - * record to, the relevant sysroot record. - * - * FIXME: We should defer this until AFTER the archive has - * been successfully processed, (in the destructor, perhaps?), - * cleaning up, and not updating the installation manifest, - * in the event of an archive processing failure. - */ - sysroot->SetAttribute( modified_key, yes_value ); - sysroot->AddChild( installed ); - } - } - - int pkgTarArchiveInstaller::ProcessDirectory( const char *pathname ) - { - /* Create the directory infrastructure required to support - * a specific package installation. - */ - #if DEBUGLEVEL < 5 - int status; - - if( (status = mkdir_recursive( pathname, 0755 )) == 0 ) - /* - * Either the specified directory already exists, - * or we just successfully created it; attach a reference - * in the installation manifest for the current package. - */ - UpdateInstallationManifest( dirname_key, pathname ); - - else - /* A required subdirectory could not be created; - * diagnose this failure. - */ - dmh_notify( DMH_ERROR, "cannot create directory `%s'\n", pathname ); - - #else - /* Debugging stub... - * - * FIXME:maybe adapt for 'dry-run' or 'verbose' use. - */ - int status = 0; - - dmh_printf( - "FIXME:ProcessDirectory<stub>:not executing: mkdir -p %s\n", - pathname - ); - #endif - return status; - } - - int pkgTarArchiveInstaller::ProcessDataStream( const char *pathname ) - { - /* Extract file data from the archive, and copy it to the - * associated target file stream, if any. - */ - #if DEBUGLEVEL < 5 - int fd = set_output_stream( pathname, octval( header.field.mode ) ); - int status = ProcessEntityData( fd ); - if( fd >= 0 ) - { - /* File stream was written; close it... - */ - close( fd ); - if( status == 0 ) - { - /* ...and on successful completion, commit it and - * record it in the installation database. - */ - commit_saved_entity( pathname, octval( header.field.mtime ) ); - UpdateInstallationManifest( filename_key, pathname ); - } - - else - { - /* The target file was not successfully and completely - * written; discard it, and diagnose failure. - */ - unlink( pathname ); - dmh_notify( DMH_ERROR, "%s: extraction failed\n", pathname ); - } - } - return status; - - #else - /* Debugging stub... - * - * FIXME:maybe adapt for 'dry-run' or 'verbose' use. - */ - dmh_printf( - "FIXME:ProcessDataStream<stub>:not extracting: %s\n", - pathname - ); - return ProcessEntityData( -1 ); - #endif - } - - void pkgTarArchiveInstaller:: - UpdateInstallationManifest( const char *key, const char *pathname ) - { - /* Write installation database records for directory - * and file entities created during archive extraction. - */ - pkgXmlNode *dir = new pkgXmlNode( key ); - dir->SetAttribute( pathname_key, pathname ); - installed->AddChild( dir ); - } - /* $RCSfile$: end of file */ --- 380,382 ---- --- NEW FILE: pkginst.cpp --- /* * pkginst.cpp * * $Id: pkginst.cpp,v 1.1 2010/04/04 15:25:36 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2010, MinGW Project * * * Implementation of the primary package installation and package * manifest recording methods. * * * 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 <unistd.h> #include "dmh.h" #include "pkginfo.h" #include "pkgkeys.h" #include "pkgproc.h" EXTERN_C const char *hashed_name( int, const char *, const char * ); pkgManifest::pkgManifest( const char *tag, const char *tarname ) { /* Construct an in-memory image for processing a package manifest. * * We begin by initialising this pair of reference pointers, * assuming that this manifest may become invalid... */ manifest = NULL; inventory = NULL; /* Then we check that a package tarname has been provided... */ if( tarname != NULL ) { /* ...in which case, we proceed to set up the reference data... */ int retry = 0; while( retry < 16 ) { /* Generate a hashed signature for the package manifest * record, and derive an associated database file path name * from it. Note that this hash is returned in 'malloc'ed * memory, which we must later free. Also note that there * are eight possible hashes, to mitigate hash collision, * each of which is denoted by retry modulo eight; we make * an initial pass through the possible hashes, looking for * an existing installation map for this sysroot, loading * it immediately if we find it. Otherwise, we continue * with a second cycle, (retry = 8..15), looking for the * first generated hash with no associated file; we then * use this to create a new installation record file. */ pkgXmlDocument *chkfile; const char *signame = hashed_name( retry++, manifest_key, tarname ); const char *sigfile = xmlfile( signame, NULL ); /* Check for an existing file associated with the hash value... */ if( (chkfile = new pkgXmlDocument( sigfile ))->IsOk() ) { /* ...such a file does exist, but we must still check * that it relates to the specified package... */ if( retry < 9 ) { /* ...however, we only perform this check during the * first pass through the possible hashes; (second time * through, we are only interested in a hash which does * not have an associated file; note that the first pass * through is for retry = 0..7, but by the time we get * to here we have already incremented 7 to become 8, * hence the check for retry < 9). */ pkgXmlNode *root, *rel; const char *pkg_id, *pkg_tarname; if( ((root = chkfile->GetRoot()) != NULL) && ((root->IsElementOfType( tag ))) && ((pkg_id = root->GetPropVal( id_key, NULL )) != NULL) && ((strcmp( pkg_id, signame ) == 0)) && ((rel = root->FindFirstAssociate( release_key )) != NULL) && ((pkg_tarname = rel->GetPropVal( tarname_key, NULL )) != NULL) && ((pkg_strcmp( pkg_tarname, tarname ))) ) { /* This is the manifest file we require... * assign it for return, and force an early exit * from the retry loop. */ manifest = chkfile; retry = 16; } } } /* Once more noting the prior increment of retry, such * that it has now become 8 for the hash generation with * retry = 7... */ else if( retry > 8 ) { /* ...we have exhausted all possible hash references, * finding no existing manifest for the specified package; * immediately assign the current (unused) manifest name, * and initialise its root element... */ pkgXmlNode *root = new pkgXmlNode( tag ); (manifest = chkfile)->AddDeclaration( "1.0", "UTF-8", value_yes ); root->SetAttribute( id_key, signame ); manifest->SetRoot( root ); /* ...a container, to be filled later, for recording the * data associated with the specific release of the package * to which this manifest will refer... */ pkgXmlNode *ref = new pkgXmlNode( release_key ); ref->SetAttribute( tarname_key, tarname ); root->AddChild( ref ); /* ...a further container, in which to record the sysroot * associations for installed instances of this package... */ ref = new pkgXmlNode( reference_key ); root->AddChild( ref ); /* ...and one in which to accumulate the content manifest. */ inventory = new pkgXmlNode( manifest_key ); root->AddChild( inventory ); /* Finally, having constructed a skeletal manifest, * force an immediate exit from the retry loop... */ retry = 16; } /* Before abandoning our references to the current hash * signature, and the path name for the associated XML file, * free the memory allocated for them. */ free( (void *)(sigfile) ); free( (void *)(signame) ); /* If we have not yet exhausted all possible hashed file names... */ if( retry < 16 ) /* * ...free the heap memory allocated for the current (unsuitable) * association, so making its "chkfile" reference pointer available * for the next trial, without incurring a memory leak. */ delete chkfile; } } } void pkgManifest::BindSysRoot( pkgXmlNode *sysroot, const char *reference_tag ) { /* Identify the package associated with the current manifest as * having been installed within the specified sysroot, by tagging * with a manifest reference to the sysroot identification key. */ const char *id; if( ((id = sysroot->GetPropVal( id_key, NULL )) != NULL) && (*id != '\0') ) { /* The specified sysroot has a non-NULL, non-blank key; * check for a prior reference to the same key, within the * "references" section of the manifest... */ pkgXmlNode *map, *ref; if( ((ref = manifest->GetRoot()) != NULL) && ((ref->IsElementOfType( reference_tag ))) && ((map = ref->FindFirstAssociate( reference_key )) == NULL) ) { /* This manifest doesn't yet have a "references" section; * create and add one now... */ map = new pkgXmlNode( reference_key ); ref->AddChild( map ); } /* Examine any existing sysroot references within this manifest... */ ref = map->FindFirstAssociate( sysroot_key ); while( (ref != NULL) && (strcmp( id, ref->GetPropVal( id_key, id )) != 0) ) /* * ...progressing to the next reference, if any, until... */ ref = ref->FindNextAssociate( sysroot_key ); /* ...we either matched the required sysroot key, or we * ran out of existing references, without finding a match. */ if( ref == NULL ) { /* When no existing reference was found, add one. */ ref = new pkgXmlNode( sysroot_key ); ref->SetAttribute( id_key, id ); map->AddChild( ref ); } } } void pkgManifest::AddEntry( const char *key, const char *pathname ) { /* Method invoked by package installers, to add file or directory * entries to the tracked inventory of package content. * * Tracking is enabled only if the manifest structure is valid, * AND an inventory table has been allocated... */ if( (this != NULL) && (inventory != NULL) ) { /* ...in which case we allocate a new tracking record, with * "dir" or "file" reference key as appropriate, fill it out * with the associated path name attribute, and insert it in * the inventory table. */ pkgXmlNode *entry = new pkgXmlNode( key ); entry->SetAttribute( pathname_key, pathname ); inventory->AddChild( entry ); } } pkgManifest::~pkgManifest() { /* Destructor for package manifest images; it releases * the memory used while processing a manifest, after first * committing the image to disk storage, or deleting such * a disk image as appropriate. */ pkgXmlNode *ref; const char *sigfile; /* First confirm that an identification signature has been * assigned for this manifest... */ if( ((manifest != NULL)) && ((ref = manifest->GetRoot()) != NULL) && ((sigfile = ref->GetPropVal( id_key, NULL )) != NULL) ) { /* ...and map this to a file system reference path name. */ sigfile = xmlfile( sigfile ); /* Check if any current installation, as identified by * its sysroot key, refers to this manifest... */ if( ((ref = ref->FindFirstAssociate( reference_key )) != NULL) && ((ref = ref->FindFirstAssociate( sysroot_key )) != NULL) ) /* * ...and if so, commit this manifest to disk... */ manifest->Save( sigfile ); else /* ...otherwise, this manifest is defunct, so * delete any current disk copy. */ unlink( sigfile ); /* Release the memory used to identify the path name for * the on-disk copy of this manifest... */ free( (void *)(sigfile) ); } /* ...and finally, expunge its in-memory image. */ delete manifest; } static void record_dependencies( pkgXmlNode *origin, pkgXmlNode *list ) { /* Helper function to record dependency call-outs for the package * which is specified by the XML descriptor reference at "origin", * (which should nominally represent a "release" specification for * the package); the call-out references are collected in the XML * container referenced by "list". */ if( (origin != NULL) && (list != NULL) ) { /* Assume "origin" and "list" represent appropriate XML objects... */ if( ! origin->IsElementOfType( package_key ) ) /* * ...and walk back through the "origin" tree, until we locate * the top level node in the "package" specification. */ record_dependencies( origin->GetParent(), list ); /* As we unwind this recursive walk back search, we copy all * "requires" elements, at each intervening level, from the top * "package" node until we return to the original "release"... */ pkgXmlNode *dep = origin->FindFirstAssociate( requires_key ); while( dep != NULL ) { /* ...each as a simple clone within the "list" container, * (and all at a single level within the "list")... */ list->AddChild( dep->Clone() ); /* ...repeating for all specified "requires" elements * at each level. */ dep = dep->FindNextAssociate( requires_key ); } } } EXTERN_C void pkgRegister ( pkgXmlNode *sysroot, pkgXmlNode *origin, const char *tarname, const char *pkgfile ) { /* Search the installation records for the current sysroot... */ const char *pkg_tarname = NULL; pkgXmlNode *ref = sysroot->FindFirstAssociate( installed_key ); while( (ref != NULL) && ((pkg_tarname = ref->GetPropVal( tarname_key, NULL )) != NULL) && ! (pkg_strcmp( tarname, pkg_tarname )) ) /* * ...continuing until we either run out of installation records, * or we find an already existing reference to this package. */ ref = ref->FindNextAssociate( installed_key ); /* When we didn't find an appropriate existing installation record, * we instantiate a new one... */ if( (ref == NULL) && ((ref = new pkgXmlNode( installed_key )) != NULL) ) { /* Fill out its "tarname" attribution... */ ref->SetAttribute( tarname_key, tarname ); if( pkgfile != tarname ) { /* When the real package tarball name isn't identically * the same as the canonical name, then we record the real * file name too. */ pkgXmlNode *dl = new pkgXmlNode( download_key ); dl->SetAttribute( tarname_key, pkgfile ); ref->AddChild( dl ); } /* Record dependency call-outs for the installed package. */ record_dependencies( origin, ref ); /* Set the 'modified' flag for, and attach the installation * record to, the relevant sysroot record. */ sysroot->SetAttribute( modified_key, value_yes ); sysroot->AddChild( ref ); } } EXTERN_C void pkgInstall( pkgActionItem *current ) { /* Common handler for all package installation tasks... */ pkgXmlNode *pkg; if( (pkg = current->Selection()) != NULL ) { /* The current action item has a valid package association... */ if( current->Selection( to_remove ) == NULL ) { /* The selected package has either not yet been installed, * or any prior installation has been removed in preparation * for re-installation or upgrade. */ const char *pkgfile, *tarname; if( match_if_explicit( pkgfile = pkg->ArchiveName(), value_none ) && ((tarname = pkg->GetPropVal( tarname_key, NULL )) != NULL) ) { /* In this case, the selected package has no associated archive, * (i.e. it is a "virtual" package); provided we can identify an * associated "sysroot"... */ pkgXmlNode *sysroot; pkgSpecs lookup( tarname ); if( (sysroot = pkg->GetSysRoot( lookup.GetSubSystemName() )) != NULL ) /* * ...the installation process becomes a simple matter of * recording the state of this virtual package as "installed", * in the sysroot manifest, and itemising its prerequisites. */ pkgRegister( sysroot, pkg, tarname, pkgfile ); } else { /* Here we have a "real" (physical) package to install; * for the time being, we assume it is packaged in our * standard "tar" archive format. */ pkgTarArchiveInstaller install( pkg ); if( install.IsOk() ) install.Process(); } } else /* There is a prior installation of the selected package, which * prevents us from proceeding; diagnose and otherwise ignore... */ dmh_notify( DMH_ERROR, "package %s is already installed\n", current->Selection()->GetPropVal( tarname_key, "<unknown>" ) ); } } /* $RCSfile: pkginst.cpp,v $: end of file */ --- NEW FILE: tarinst.cpp --- /* * tarinst.cpp * * $Id: tarinst.cpp,v 1.1 2010/04/04 15:25:36 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, 2010, MinGW Project * * * Implementation of package installer methods for installation of * packages which are distributed in the form of 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 <unistd.h> #include <utime.h> #include "dmh.h" //#include "pkginfo.h" #include "pkgkeys.h" #include "pkgproc.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 successfully set up the pkgTarArchiveProcessor * base class, we attach a pkgManifest to track the installation. */ if( (tarname != NULL) && (sysroot != NULL) && stream->IsReady() ) installed = new pkgManifest( package_key, tarname ); } int pkgTarArchiveInstaller::Process() { /* Specialisation of the base class Process() method. */ int status; /* First, process the archive as for the base class... */ if( (status = pkgTarArchiveProcessor::Process()) == 0 ) { /* ...then, on successful completion... * * Update the package installation manifest, to record * the installation in the current sysroot... */ installed->BindSysRoot( sysroot, package_key ); pkgRegister( sysroot, origin, tarname, pkgfile ); } return status; } int pkgTarArchiveInstaller::ProcessDirectory( const char *pathname ) { /* Create the directory infrastructure required to support * a specific package installation. */ #if DEBUGLEVEL < 5 int status; if( (status = mkdir_recursive( pathname, 0755 )) == 0 ) /* * Either the specified directory already exists, * or we just successfully created it; attach a reference * in the installation manifest for the current package. */ installed->AddEntry( dirname_key, pathname + sysroot_len ); else /* A required subdirectory could not be created; * diagnose this failure. */ dmh_notify( DMH_ERROR, "cannot create directory `%s'\n", pathname ); #else /* Debugging stub... * * FIXME:maybe adapt for 'dry-run' or 'verbose' use. */ int status = 0; dmh_printf( "FIXME:ProcessDirectory<stub>:not executing: mkdir -p %s\n", pathname ); # if DEBUGLEVEL > 8 installed->AddEntry( dirname_key, pathname + sysroot_len ); # endif #endif return status; } int pkgTarArchiveInstaller::ProcessDataStream( const char *pathname ) { /* Extract file data from the archive, and copy it to the * associated target file stream, if any. */ #if DEBUGLEVEL < 5 int fd = set_output_stream( pathname, octval( header.field.mode ) ); int status = ProcessEntityData( fd ); if( fd >= 0 ) { /* File stream was written; close it... */ close( fd ); if( status == 0 ) { /* ...and on successful completion, commit it and * record it in the installation database. */ commit_saved_entity( pathname, octval( header.field.mtime ) ); installed->AddEntry( filename_key, pathname + sysroot_len ); } else { /* The target file was not successfully and completely * written; discard it, and diagnose failure. */ unlink( pathname ); dmh_notify( DMH_ERROR, "%s: extraction failed\n", pathname ); } } return status; #else /* Debugging stub... * * FIXME:maybe adapt for 'dry-run' or 'verbose' use. */ dmh_printf( "FIXME:ProcessDataStream<stub>:not extracting: %s\n", pathname ); # if DEBUGLEVEL > 8 installed->AddEntry( filename_key, pathname + sysroot_len ); # endif return ProcessEntityData( -1 ); #endif } /* $RCSfile: tarinst.cpp,v $: end of file */ Index: pkgproc.h =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/pkgproc.h,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** pkgproc.h 10 Feb 2010 22:18:59 -0000 1.2 --- pkgproc.h 4 Apr 2010 15:25:36 -0000 1.3 *************** *** 33,36 **** --- 33,57 ---- #include "pkgstrm.h" + EXTERN_C void pkgInstall( pkgActionItem* ); + EXTERN_C void pkgRegister( pkgXmlNode*, pkgXmlNode*, const char*, const char* ); + + class pkgManifest + { + /* A wrapper around the XML document class, with specialised methods + * for management of the package installation manifest. + */ + public: + pkgManifest( const char*, const char* ); + ~pkgManifest(); + + void AddEntry( const char*, const char* ); + void BindSysRoot( pkgXmlNode*, const char* ); + void DetachSysRoot( pkgXmlNode* ); + + private: + pkgXmlDocument *manifest; + pkgXmlNode *inventory; + }; + class pkgArchiveProcessor { *************** *** 46,49 **** --- 67,72 ---- protected: + int sysroot_len; + /* Pointers to the sysroot management records and installation * path template for a managed package; note that 'tarname' does *************** *** 52,60 **** * 'tarname' property of the package identifier record. */ ! pkgXmlNode *sysroot; ! const char *sysroot_path; ! pkgXmlNode *installed; ! const char *tarname; ! const char *pkgfile; }; --- 75,84 ---- * 'tarname' property of the package identifier record. */ ! pkgXmlNode *origin; ! pkgXmlNode *sysroot; ! const char *sysroot_path; ! pkgManifest *installed; ! const char *tarname; ! const char *pkgfile; }; *************** *** 157,160 **** --- 181,186 ---- virtual ~pkgTarArchiveInstaller(){} + virtual int Process(); + private: /* Specialised implementations of the archive processing methods... *************** *** 162,166 **** virtual int ProcessDirectory( const char* ); virtual int ProcessDataStream( const char* ); - virtual void UpdateInstallationManifest( const char*, const char* ); }; --- 188,191 ---- |