This list is closed, nobody may subscribe to it.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(12) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(13) |
Feb
(2) |
Mar
(1) |
Apr
(1) |
May
|
Jun
(38) |
Jul
(10) |
Aug
(70) |
Sep
(63) |
Oct
(61) |
Nov
(41) |
Dec
(28) |
2002 |
Jan
(43) |
Feb
(11) |
Mar
(9) |
Apr
(2) |
May
(97) |
Jun
(94) |
Jul
(13) |
Aug
(49) |
Sep
(41) |
Oct
(24) |
Nov
(55) |
Dec
(126) |
2003 |
Jan
(90) |
Feb
(75) |
Mar
(32) |
Apr
(24) |
May
(54) |
Jun
(54) |
Jul
(22) |
Aug
(4) |
Sep
(16) |
Oct
(8) |
Nov
(6) |
Dec
(13) |
2004 |
Jan
|
Feb
(17) |
Mar
(60) |
Apr
(21) |
May
(12) |
Jun
|
Jul
(13) |
Aug
|
Sep
(29) |
Oct
|
Nov
|
Dec
(2) |
2005 |
Jan
(22) |
Feb
(3) |
Mar
(2) |
Apr
(13) |
May
(82) |
Jun
(18) |
Jul
(30) |
Aug
(17) |
Sep
(3) |
Oct
(19) |
Nov
(4) |
Dec
(8) |
2006 |
Jan
(1) |
Feb
(6) |
Mar
(2) |
Apr
(40) |
May
|
Jun
(21) |
Jul
(1) |
Aug
(410) |
Sep
(3) |
Oct
|
Nov
(56) |
Dec
(7) |
2007 |
Jan
(19) |
Feb
|
Mar
(4) |
Apr
(8) |
May
(19) |
Jun
(6) |
Jul
(4) |
Aug
(6) |
Sep
|
Oct
(4) |
Nov
(3) |
Dec
(2) |
2008 |
Jan
(13) |
Feb
(18) |
Mar
(12) |
Apr
|
May
(2) |
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
|
2009 |
Jan
|
Feb
(6) |
Mar
(8) |
Apr
(2) |
May
(2) |
Jun
|
Jul
|
Aug
(2) |
Sep
(11) |
Oct
(13) |
Nov
(17) |
Dec
(6) |
2010 |
Jan
(24) |
Feb
(10) |
Mar
(27) |
Apr
(20) |
May
(108) |
Jun
(8) |
Jul
(23) |
Aug
(38) |
Sep
(49) |
Oct
(17) |
Nov
(12) |
Dec
(14) |
2011 |
Jan
(17) |
Feb
(7) |
Mar
(28) |
Apr
(8) |
May
(20) |
Jun
(11) |
Jul
(7) |
Aug
(12) |
Sep
(4) |
Oct
(20) |
Nov
(19) |
Dec
(2) |
2012 |
Jan
(2) |
Feb
(6) |
Mar
(5) |
Apr
(24) |
May
(5) |
Jun
(4) |
Jul
(6) |
Aug
(18) |
Sep
(38) |
Oct
(26) |
Nov
(12) |
Dec
(6) |
2013 |
Jan
(19) |
Feb
(18) |
Mar
(44) |
Apr
(35) |
May
(18) |
Jun
(21) |
Jul
(10) |
Aug
(19) |
Sep
(44) |
Oct
(25) |
Nov
(1) |
Dec
(2) |
2014 |
Jan
(8) |
Feb
|
Mar
|
Apr
(5) |
May
(1) |
Jun
(3) |
Jul
|
Aug
(3) |
Sep
|
Oct
(4) |
Nov
(4) |
Dec
(7) |
2015 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(2) |
Jun
(4) |
Jul
(6) |
Aug
(2) |
Sep
(8) |
Oct
(2) |
Nov
(1) |
Dec
(3) |
2016 |
Jan
(7) |
Feb
(9) |
Mar
(5) |
Apr
(5) |
May
(9) |
Jun
(4) |
Jul
(20) |
Aug
(4) |
Sep
(7) |
Oct
(6) |
Nov
(9) |
Dec
(2) |
2017 |
Jan
(7) |
Feb
(7) |
Mar
(5) |
Apr
|
May
(1) |
Jun
(4) |
Jul
(12) |
Aug
(4) |
Sep
(1) |
Oct
(4) |
Nov
(11) |
Dec
(14) |
2018 |
Jan
(3) |
Feb
(3) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
1
|
2
|
3
|
4
|
5
(2) |
6
|
7
|
8
|
9
|
10
|
11
(2) |
12
(3) |
13
|
14
|
15
|
16
(2) |
17
|
18
|
19
|
20
|
21
|
22
(2) |
23
(4) |
24
|
25
|
26
|
27
|
28
|
29
(2) |
30
|
|
|
|
|
|
From: Chris S. <ir0...@us...> - 2009-11-29 23:37:16
|
Update of /cvsroot/mingw/MinGW/inifiles In directory sfp-cvsdas-1.v30.ch3.sourceforge.com:/tmp/cvs-serv19563/inifiles Modified Files: Tag: MinGW-5_1 mingw.ini Log Message: 2009.11.29 Chris Sutcliffe <ir0...@us...> * inifiles/mingw.ini: Updated current for mingwrt. Index: mingw.ini =================================================================== RCS file: /cvsroot/mingw/MinGW/inifiles/Attic/mingw.ini,v retrieving revision 1.12.2.8 retrieving revision 1.12.2.9 diff -C2 -d -r1.12.2.8 -r1.12.2.9 *** mingw.ini 22 Nov 2009 12:50:33 -0000 1.12.2.8 --- mingw.ini 29 Nov 2009 23:37:07 -0000 1.12.2.9 *************** *** 6,11 **** [current] ! runtime=mingwrt-3.15.2-mingw32-dev.tar.gz|7616 ! runtimeDLL=mingwrt-3.15.2-mingw32-dll.tar.gz|40 w32api=w32api-3.14-mingw32-dev.tar.gz|14460 binutils=binutils-2.20-1-mingw32-bin.tar.gz|26979 --- 6,11 ---- [current] ! runtime=mingwrt-3.17-mingw32-dev.tar.gz|7300 ! runtimeDLL=mingwrt-3.17-mingw32-dll.tar.gz|30 w32api=w32api-3.14-mingw32-dev.tar.gz|14460 binutils=binutils-2.20-1-mingw32-bin.tar.gz|26979 *************** *** 19,23 **** [previous] ! runtime=mingw-runtime-3.14.tar.gz|6500 w32api=w32api-3.13-mingw32-dev.tar.gz|14420 binutils=binutils-2.19.1-mingw32-bin.tar.gz|21093 --- 19,24 ---- [previous] ! runtime=mingwrt-3.15.2-mingw32-dev.tar.gz|7616 ! runtimeDLL=mingwrt-3.15.2-mingw32-dll.tar.gz|40 w32api=w32api-3.13-mingw32-dev.tar.gz|14420 binutils=binutils-2.19.1-mingw32-bin.tar.gz|21093 |
From: Chris S. <ir0...@us...> - 2009-11-29 23:37:15
|
Update of /cvsroot/mingw/MinGW In directory sfp-cvsdas-1.v30.ch3.sourceforge.com:/tmp/cvs-serv19563 Modified Files: Tag: MinGW-5_1 ChangeLog Log Message: 2009.11.29 Chris Sutcliffe <ir0...@us...> * inifiles/mingw.ini: Updated current for mingwrt. Index: ChangeLog =================================================================== RCS file: /cvsroot/mingw/MinGW/Attic/ChangeLog,v retrieving revision 1.9.2.6 retrieving revision 1.9.2.7 diff -C2 -d -r1.9.2.6 -r1.9.2.7 *** ChangeLog 22 Nov 2009 12:50:30 -0000 1.9.2.6 --- ChangeLog 29 Nov 2009 23:37:07 -0000 1.9.2.7 *************** *** 1,2 **** --- 1,6 ---- + 2009.11.29 Chris Sutcliffe <ir0...@us...> + + * inifiles/mingw.ini: Updated current for mingwrt. + 2009.11.22 Chris Sutcliffe <ir0...@us...> |
From: Keith M. <kei...@us...> - 2009-11-23 20:45:06
|
Update of /cvsroot/mingw/mingw-get In directory sfp-cvsdas-1.v30.ch3.sourceforge.com:/tmp/cvs-serv25968 Modified Files: ChangeLog Makefile.in Log Message: Add package download and repository synchronisation machinery. Index: Makefile.in =================================================================== RCS file: /cvsroot/mingw/mingw-get/Makefile.in,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** Makefile.in 16 Nov 2009 21:54:30 -0000 1.3 --- Makefile.in 23 Nov 2009 20:44:23 -0000 1.4 *************** *** 45,55 **** LDFLAGS = @LDFLAGS@ ! LIBS = @LIBS@ CORE_DLL_OBJECTS = climain.$(OBJEXT) \ ! pkgexec.$(OBJEXT) pkginfo.$(OBJEXT) pkgspec.$(OBJEXT) \ tinyxml.$(OBJEXT) tinyxmlparser.$(OBJEXT) \ tinystr.$(OBJEXT) tinyxmlerror.$(OBJEXT) \ - mkpath.$(OBJEXT) xmlfile.$(OBJEXT) \ vercmp.$(OBJEXT) dmh.$(OBJEXT) --- 45,56 ---- LDFLAGS = @LDFLAGS@ ! LIBS = -Wl,-Bstatic -lz -lbz2 -llzma -Wl,-Bdynamic -lwininet CORE_DLL_OBJECTS = climain.$(OBJEXT) \ ! pkgbind.$(OBJEXT) pkginet.$(OBJEXT) pkgstrm.$(OBJEXT) pkgname.$(OBJEXT) \ ! pkgexec.$(OBJEXT) pkgfind.$(OBJEXT) pkginfo.$(OBJEXT) pkgspec.$(OBJEXT) \ ! mkpath.$(OBJEXT) xmlfile.$(OBJEXT) keyword.$(OBJEXT) \ tinyxml.$(OBJEXT) tinyxmlparser.$(OBJEXT) \ tinystr.$(OBJEXT) tinyxmlerror.$(OBJEXT) \ vercmp.$(OBJEXT) dmh.$(OBJEXT) *************** *** 72,78 **** dmh.$(OBJEXT): dmh.h ! climain.$(OBJEXT): pkgbase.h pkgtask.h dmh.h ! pkgexec.$(OBJEXT): pkgbase.h pkgtask.h mkpath.h dmh.h ! pkgspec.$(OBJEXT): pkgbase.h pkginfo.h vercmp.h # Dependencies for stand alone pkginfo tool; --- 73,85 ---- dmh.$(OBJEXT): dmh.h ! climain.$(OBJEXT): pkgbase.h pkgtask.h tinyxml.h tinystr.h dmh.h ! ! pkgname.$(OBJEXT): pkgbase.h dmh.h ! pkgfind.$(OBJEXT): pkgbase.h tinyxml.h tinystr.h ! pkgbind.$(OBJEXT): pkgbase.h tinyxml.h tinystr.h dmh.h ! pkgexec.$(OBJEXT): pkgbase.h pkgtask.h tinyxml.h tinystr.h mkpath.h dmh.h ! pkgspec.$(OBJEXT): pkgbase.h pkginfo.h tinyxml.h tinystr.h vercmp.h ! pkginet.$(OBJEXT): pkgbase.h pkgtask.h pkgstrm.h mkpath.h dmh.h ! pkgstrm.$(OBJEXT): pkgstrm.h # Dependencies for stand alone pkginfo tool; *************** *** 84,91 **** # TinyXML dependencies... # ! tinyxml.$(OBJEXT): tinyxml.h ! tinyxmlerror.$(OBJEXT): tinyxml.h ! tinyxmlparser.$(OBJEXT): tinyxml.h ! tinystr.$(OBJEXT): tinyxml.h clean: --- 91,98 ---- # TinyXML dependencies... # ! tinyxml.$(OBJEXT): tinyxml.h tinystr.h ! tinyxmlerror.$(OBJEXT): tinyxml.h tinystr.h ! tinyxmlparser.$(OBJEXT): tinyxml.h tinystr.h ! tinystr.$(OBJEXT): tinystr.h clean: Index: ChangeLog =================================================================== RCS file: /cvsroot/mingw/mingw-get/ChangeLog,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** ChangeLog 16 Nov 2009 21:54:30 -0000 1.9 --- ChangeLog 23 Nov 2009 20:44:17 -0000 1.10 *************** *** 1,2 **** --- 1,17 ---- + 2009-11-23 Keith Marshall <kei...@us...> + + Add package download and repository synchronisation machinery. + + * src/pkgstrm.h: New header file. + + * src/pkgbind.cpp, src/pkginet.cpp, src/pkgstrm.cpp, + src/pkgfind.cpp, src/pkgname.cpp, src/keyword.c: New files. + * Makefile.in (CORE_DLL_OBJECTS): Add build goals for them. + + * xml: New directory. + + * src/climain.cpp (climain): Establish repository bindings from... + * xml/profile.xml: ...this new configuration file. + 2009-11-16 Keith Marshall <kei...@us...> |
From: Keith M. <kei...@us...> - 2009-11-23 20:44:35
|
Update of /cvsroot/mingw/mingw-get/xml In directory sfp-cvsdas-1.v30.ch3.sourceforge.com:/tmp/cvs-serv25968/xml Added Files: profile.xml Log Message: Add package download and repository synchronisation machinery. --- NEW FILE: profile.xml --- <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!-- profile.xml --> <profile project="MinGW" application="mingw-get"> <!-- $Id: profile.xml,v 1.1 2009/11/23 20:44:25 keithmarshall Exp $ Written by Keith Marshall <kei...@us...> Copyright (C) 2009, MinGW Project Master configuration profile for mingw-get. 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. --> <repository uri="" rel="nofollow">http://prdownloads.sourceforge.net/mingw/%F.xml.lzma?download"> <!-- The "repository" specification identifies the URI where package list catalogues may be downloaded; each catalogue download URI is identified by substituting the catalogue name for the "%F" field in the uri specification. FIXME: package lists specified here will inhibit searching of any master index maintained on the repository server. At present, the master index search facility is unsupported, so only these locally specified package lists will be loaded; remove them when the index search feature becomes available, to enable master index search. --> <package-list catalogue="mingw-base" /> </repository> <system-map id="default"> <!-- The system map specifies the installation paths for each managed subsystem. Multiple system maps are supported, provided each is given a unique "id" attribute; each specifies an "installation", comprising a collection of subsystems, each of which in turn is associated with a specific "sysroot path". Each individual "sysroot path" defines one installation of one specific subsystem; parallel installations may be supported by assigning distinct paths to two or more sysroot specifications for the same subsystem; each such sysroot specification must then be assigned to a distinct system-map. Any single sysroot definition may be shared by any number of system-maps, simply by duplicating that definition within each; however, each system-map may contain only one sysroot definition for each individual subsystem. Only one system map may be active at any time. Unless otherwise specified by user selection, the first encountered is accepted as default, irrespective of its actual "id" attribute value. --> <sysroot subsystem="mingw32" path="c:/mingw" /> <sysroot subsystem="MSYS" path="c:/msys/1.0" /> </system-map> </profile> <!-- $RCSfile: profile.xml,v $: end of file --> |
From: Keith M. <kei...@us...> - 2009-11-23 20:44:35
|
Update of /cvsroot/mingw/mingw-get/src In directory sfp-cvsdas-1.v30.ch3.sourceforge.com:/tmp/cvs-serv25968/src Modified Files: climain.cpp Added Files: keyword.c pkgbind.cpp pkgfind.cpp pkginet.cpp pkgname.cpp pkgstrm.cpp pkgstrm.h Log Message: Add package download and repository synchronisation machinery. --- NEW FILE: pkgbind.cpp --- /* * pkgbind.cpp * * $Id: pkgbind.cpp,v 1.1 2009/11/23 20:44:25 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Implementation of repository binding for the pkgXmlDocument class. * * * 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 "pkgbase.h" pkgXmlNode *pkgXmlDocument::BindRepositories() { /* Identify the repositories specified in the application profile, * and merge their associated package distribution lists into the * active XML database, which is bound to the profile. */ pkgXmlNode *dbase = GetRoot(); /* Before blindly proceeding, perform a sanity check... * Verify that this XML database defines an application profile, * and that the associated application is "mingw-get"... */ if( (strcmp( dbase->GetName(), "profile" ) == 0) && (strcmp( dbase->GetPropVal( "application", "?" ), "mingw-get") == 0) ) { /* Sanity check passed... * Walk the XML data tree, selecting "repository" specifications... */ pkgXmlNode *repository = dbase->FindFirstAssociate( "repository" ); while( repository != NULL ) { /* For each "repository" specified, identify its "catalogues"... * * FIXME: this requires the "package-lists" to be individually * specified within the locally defined "repository" elements; * it should allow for deduction of these, from a specifically * named "repository-index" file identified via the repository * URI template, and hosted by the download server itself. */ pkgXmlNode *catalogue = repository->FindFirstAssociate( "package-list" ); while( catalogue != NULL ) { /* ...and for each named "catalogue"... */ const char *dfile, *dname = catalogue->GetPropVal( "catalogue", NULL ); if( (dname != NULL) && ((dfile = xmlfile( dname )) != NULL) ) { /* Check for a locally cached copy of the "package-list" file... */ if( access( dfile, F_OK ) != 0 ) /* * When no local copy is available... * Force a "sync", to fetch a copy from the public host. */ SyncRepository( dname, repository ); /* We SHOULD now have a locally cached copy of the package-list; * attempt to merge it into the active profile database... */ pkgXmlDocument merge( dfile ); if( merge.IsOk() ) { /* We successfully loaded the XML catalogue; refer to its * root element... */ dmh_printf( "Bind repository: %s\n", merge.Value() ); pkgXmlNode *pkglist; if( (pkglist = merge.GetRoot()) != NULL ) { /* ...read it, selecting each of the "package-collection" * records contained within it... */ pkglist = pkglist->FindFirstAssociate( "package-collection" ); while( pkglist != NULL ) { /* ...and append a copy of each to the active profile... */ dbase->LinkEndChild( pkglist->Clone() ); /* Move on to the next "package-collection" (if any) * within the current catalogue... */ pkglist = pkglist->FindNextAssociate( "package-collection" ); } } } else dmh_notify( DMH_WARNING, "Bind repository: FAILED: %s\n", dfile ); /* However we handled it, the XML file's path name in "dfile" was * allocated on the heap; we lose its reference on termination of * this loop, so we must free it to avoid a memory leak. */ free( (void *)(dfile) ); } /* A repository may comprise an arbitrary collection of software * catalogues; move on, to process the next catalogue (if any) in * the current repository collection. */ catalogue = catalogue->FindNextAssociate( "package-list" ); } /* Similarly, a complete distribution may draw from an arbitrary set * of distinct repositories; move on, to process the next repository * specified (if any). */ repository = repository->FindNextAssociate( "repository" ); } /* On successful completion, return a pointer to the root node * of the active XML profile. */ return dbase; } /* Fall through on total failure to interpret the profile, returning * NULL to indicate failure. */ return NULL; } /* $RCSfile: pkgbind.cpp,v $: end of file */ Index: climain.cpp =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/climain.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** climain.cpp 16 Nov 2009 21:54:30 -0000 1.1 --- climain.cpp 23 Nov 2009 20:44:23 -0000 1.2 *************** *** 73,77 **** free( (void *)(dfile) ); - #if 0 /* Merge all package lists, as specified in the "repository" * section of the "profile", into the XML database tree... --- 73,76 ---- *************** *** 83,86 **** --- 82,86 ---- dmh_notify( DMH_FATAL, "%s: invalid application profile\n", dbase.Value() ); + #if 0 /* Now schedule the specified action for each additionally * specified command line argument, (each of which is assumed --- NEW FILE: pkgfind.cpp --- /* * pkgfind.cpp * * $Id: pkgfind.cpp,v 1.1 2009/11/23 20:44:25 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Implementation of search routines for locating specified records * within the XML package-collection database. * * * 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 <string.h> #include "pkgbase.h" static inline bool pkgHasMatchingName( pkgXmlNode *pkg, const char *wanted ) { /* Helper to locate a package specification by package name; * returns "true" if the XML node under consideration defines * a "package", having the "wanted" name; else "false". */ return pkg->IsElementOfType( "package" ) /* * subject to the canonical name of the package matching * the "wanted" name, or any assigned package name alias... */ &&( (strcmp( wanted, pkg->GetPropVal( "name", "" )) == 0) || (has_keyword( pkg->GetPropVal( "alias", NULL ), wanted ) != 0) ); } pkgXmlNode * pkgXmlDocument::FindPackageByName( const char *name, const char *subsystem ) { pkgXmlNode *dir = GetRoot()->GetChildren(); /* * Working from the root of the package directory tree... * search all "package-collection" XML nodes, to locate a package * by "name"; return a pointer to the XML node which contains the * specification for the package, or NULL if no such package. */ while( dir != NULL ) { /* Select only "package-collection" elements... */ if( dir->IsElementOfType( "package-collection" ) && match_if_explicit( subsystem, dir->GetPropVal( "subsystem", NULL )) ) { /* ...inspect the content of each... */ pkgXmlNode *pkg = dir->GetChildren(); while( pkg != NULL ) { /* ...returning immediately, if we find a "package" * element with the required "name" property... */ if( pkgHasMatchingName( pkg, name ) ) return pkg; /* ...otherwise, continue searching among any further * entries in the current "package-collection"... */ pkg = pkg->GetNext(); } } /* ...and ultimately, in any further "package-collection" elements * which may be present. */ dir = dir->GetNext(); } /* If we get to here, we didn't find the required "package"; * return NULL, to indicate failure. */ return NULL; } static pkgXmlNode* pkgFindNextAssociate( pkgXmlNode* pkg, const char* tagname ) { /* Core implementation for both pkgXmlNode::FindFirstAssociate * and pkgXmlNode::FindNextAssociate methods. This helper starts * at the node specified by "pkg", examining it, and if necessary, * each of its siblings in turn, until one of an element type * matching "tagname" is found. */ while( pkg != NULL ) { /* We still have this "pkg" node, not yet examined... */ if( pkg->IsElementOfType( tagname ) ) /* * ...it matches our search criterion; return it... */ return pkg; /* The current "pkg" node didn't match our criterion; * move on, to examine its next sibling, if any... */ pkg = pkg->GetNext(); } /* We ran out of siblings to examine, without finding any * to match our criterion; return nothing... */ return NULL; } pkgXmlNode* pkgXmlNode::FindFirstAssociate( const char* tagname ) { /* For the node on which this method is invoked, * return the first, if any, of its immediate children, * which is an element of the type specified by "tagname"... */ return this ? pkgFindNextAssociate( GetChildren(), tagname ) : NULL; } pkgXmlNode* pkgXmlNode::FindNextAssociate( const char* tagname ) { /* Invoked on any node returned by "FindFirstAssociate", * or on any node already returned by "FindNextAssociate", * return the next sibling node, if any, which is an element * of the type specified by "tagname"... */ return this ? pkgFindNextAssociate( GetNext(), tagname ) : NULL; } /* $RCSfile: pkgfind.cpp,v $: end of file */ --- NEW FILE: pkgname.cpp --- /* * pkgname.cpp * * $Id: pkgname.cpp,v 1.1 2009/11/23 20:44:25 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Implementation for the non-inherited components of the pkgXmlNode * class, as declared in file "pkgdesc.h"; fundamentally, these are * the accessors for package "tarname" properties, as specified in * XML nodes identified as "release" elements. * * * 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 <string.h> #include "dmh.h" #include "pkgbase.h" static const char *pkgArchiveName( pkgXmlNode *rel, const char *tag, unsigned opt ) { /* Local helper to establish actual release file names... * applicable only to XML "release" elements. */ if( ! rel->IsElementOfType( "release" ) ) { dmh_control( DMH_BEGIN_DIGEST ); dmh_notify( DMH_ERROR, "internal package specification error\n" ); dmh_notify( DMH_ERROR, "can't get 'tarname' for non-release element\n" ); dmh_notify( DMH_ERROR, "please report this to the package maintainer\n" ); dmh_control( DMH_END_DIGEST ); return NULL; } /* Given a package release specification... * determine the archive name for the tarball to be processed; this * is retrieved from a child XML element with name specified by "tag"; * by default, if "opt" is non-zero, it is the canonical "tarname" * assigned to the release element itself, unless an alternative * specification is provided; if "opt" is zero, no default is * assumed, and the return value is NULL if no alternative * specification is provided. */ unsigned matched = 0; pkgXmlNode *dl = rel->GetChildren(); while( dl != NULL ) { /* Visit all children of the release specification element, * checking for the presence of an expected specification... */ if( dl->IsElementOfType( tag ) ) { /* Found one; ensure it is the only one... */ if( matched++ ) /* * ...else emit a warning, and ignore this one... */ dmh_notify( DMH_WARNING, "%s: archive name reassignment ignored\n", rel->GetPropVal( "tarname", "<unknown>" ) ); else /* ...ok; this is the first "tag" specification, * accept it as the non-default source of the release's * "tarname" property. */ rel = dl; } /* Continue, until all children have been visited. */ dl = dl->GetNext(); } /* "rel" now points to the XML element having the appropriate * "tarname" specification; return a pointer to it's value. */ return (opt || matched) ? rel->GetPropVal( "tarname", NULL ) : NULL; } const char *pkgXmlNode::SourceArchiveName() { /* Applicable only for XML nodes designated as "release". * * Retrieve the source tarball name, if specified, from the * "tarname" property of the contained "source" element, within * an XML node designated as a "release" element. * * Returns a pointer to the text of the "tarname" property of the * contained "source" element, or NULL if the containing node does * not represent a "release", or if it does not have a contained * "source" element specifying a "tarname" property. */ return pkgArchiveName( this, "source", 0 ); } const char *pkgXmlNode::ArchiveName() { /* Applicable only for XML nodes designated as "release". * * Retrieve the actual tarball name, if specified, from the * "tarname" property of a contained "download" element, within * an XML node designated as a "release" element. * * Returns a pointer to the text of the "tarname" property of the * contained "download" element, or to the "tarname" property of * the containing "release" element, if it does not contain an * alternative specification within a "download" element; if * unresolved to either of these, returns NULL. */ return pkgArchiveName( this, "download", 1 ); } /* $RCSfile: pkgname.cpp,v $: end of file */ --- NEW FILE: pkginet.cpp --- /* * pkginet.cpp * * $Id: pkginet.cpp,v 1.1 2009/11/23 20:44:25 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Implementation of the package download machinery for mingw-get. * * * 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 WIN32_LEAN_AND_MEAN #include <unistd.h> #include <stdlib.h> #include <string.h> #include <wininet.h> #include <errno.h> #include "dmh.h" #include "mkpath.h" #include "pkgbase.h" #include "pkgtask.h" class pkgInternetAgent { /* A minimal, locally implemented class, instantiated ONCE as a * global object, to ensure that wininet's global initialisation is * completed at the proper time, without us doing it explicitly. */ private: HINTERNET SessionHandle; public: inline pkgInternetAgent():SessionHandle( NULL ) { /* Constructor... */ if( InternetAttemptConnect( 0 ) == ERROR_SUCCESS ) SessionHandle = InternetOpen ( "MinGW Installer", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ); } inline ~pkgInternetAgent() { /* Destructor... */ if( SessionHandle != NULL ) Close( SessionHandle ); } /* Remaining methods are simple inline wrappers for the * wininet functions we plan to use... */ inline HINTERNET OpenURL( const char *URL ) { return InternetOpenUrl( SessionHandle, URL, NULL, 0, 0, 0 ); } inline int Read( HINTERNET dl, char *buf, size_t max, DWORD *count ) { return InternetReadFile( dl, buf, max, count ); } inline int Close( HINTERNET id ) { return InternetCloseHandle( id ); } }; /* This is the one and only instantiation of an object of this class. */ 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 { /* Another locally implemented class; each individual file download * gets its own instance of this, either as-is for basic data transfer, * or as a specialised derivative of this base class. */ protected: const char *filename; const char *dest_template; char *dest_file; HINTERNET dl_host; int dl_status; private: virtual int TransferData( int ); public: pkgInternetStreamingAgent( const char*, const char* ); virtual ~pkgInternetStreamingAgent(); virtual int Get( const char* ); inline const char *DestFile(){ return dest_file; } }; pkgInternetStreamingAgent::pkgInternetStreamingAgent ( const char *local_name, const char *dest_specification ) { /* Constructor for the pkgInternetStreamingAgent class. */ filename = local_name; dest_template = dest_specification; dest_file = (char *)(malloc( mkpath( NULL, dest_template, filename, NULL ) )); if( dest_file != NULL ) mkpath( dest_file, dest_template, filename, NULL ); } pkgInternetStreamingAgent::~pkgInternetStreamingAgent() { /* Destructor needs to free the heap memory allocated by the * constructor, for storage of "dest_file" name. */ free( (void *)(dest_file) ); } int pkgInternetStreamingAgent::TransferData( int fd ) { /* In the case of this base class implementation, * we simply read the file's data from the Internet source, * and write a verbatim copy to the destination file. */ char buf[8192]; DWORD count, tally = 0; do { dl_status = pkgDownloadAgent.Read( dl_host, buf, sizeof( buf ), &count ); dmh_printf( "\rdownloading: %s: %I32d b", filename, tally += count ); write( fd, buf, count ); } while( dl_status && (count > 0) ); dmh_printf( "\rdownloading: %s: %I32d b\n", filename, tally ); return dl_status; } static const char *get_host_info ( pkgXmlNode *ref, const char *property, const char *fallback = NULL ) { /* Helper function to retrieve host information from the XML catalogue. * * Call with property = "url", to retrieve the URL template to pass as * "fmt" argument to mkpath(), or with property = "mirror", to retrieve * the substitution text for the "modifier" argument. */ const char *uri = NULL; while( ref != NULL ) { /* Starting from the "ref" package entry in the catalogue... */ pkgXmlNode *host = ref->FindFirstAssociate( "download-host" ); while( host != NULL ) { /* Examine its associate tags; if we find one of type * "download-host", with the requisite property, then we * immediately return that property value... */ if( (uri = host->GetPropVal( property, NULL )) != NULL ) return uri; /* Otherwise, we look for any other candidate tags * associated with the same catalogue entry... */ host = host->FindNextAssociate( "download-host" ); } /* Failing an immediate match, extend the search to the * ancestors of the initial reference entry... */ ref = ref->GetParent(); } /* ...and ultimately, if no match is found, we return the * specified "fallback" property value. */ return fallback; } static inline int set_transit_path( const char *path, const char *file, char *buf = NULL ) { /* Helper to define the transitional path name for downloaded files, * used to save the file data while the download is in progress. */ static const char *transit_dir = "/.in-transit"; return mkpath( buf, path, file, transit_dir ); } int pkgInternetStreamingAgent::Get( const char *from_url ) { /* Set up a "transit-file" to receive the downloaded content. */ char transit_file[set_transit_path( dest_template, filename )]; int fd; set_transit_path( dest_template, filename, transit_file ); if( (fd = set_output_stream( transit_file, 0644 )) >= 0 ) { /* The "transit-file" is ready to receive incoming data... * Configure and invoke the download handler to copy the data * from the appropriate host URL, to this "transit-file". */ if( (dl_host = pkgDownloadAgent.OpenURL( from_url )) != NULL ) { /* With the download transaction fully specified, we may * request processing of the file transfer... */ dl_status = TransferData( fd ); /* We are done with the URL handle; close it. */ pkgDownloadAgent.Close( dl_host ); } /* Always close the "transit-file", whether the download * was successful, or not... */ close( fd ); if( dl_status ) /* * When successful, we move the "transit-file" to its * final downloaded location... */ rename( transit_file, dest_file ); else { /* ...otherwise, report failure... */ dmh_notify( DMH_ERROR, "%s: download failed\n", from_url ); /* ...and discard the incomplete "transit-file". */ unlink( transit_file ); } } /* Report success or failure to the caller... */ return dl_status; } void pkgActionItem::DownloadArchiveFiles( pkgActionItem *current ) { /* Update the local package cache, to ensure that all packages needed * to complete the current set of scheduled actions are present; if any * are missing, invoke an Internet download agent to fetch them. This * requires us to walk the action list... */ while( current != NULL ) { /* ...while we haven't run off the end... */ if( (current->flags & ACTION_INSTALL) == ACTION_INSTALL ) { /* For all packages specified in the current action list, * for which an "install" action is scheduled, and for which * no associated archive file is present in the local archive * cache, place an Internet download agent on standby to fetch * the required archive from a suitable internet mirror host. */ const char *package_name = current->selection->ArchiveName(); pkgInternetStreamingAgent download( package_name, current->ArchivePath() ); /* Check if the required archive is already available locally... */ if( (access( download.DestFile(), R_OK ) != 0) && (errno == ENOENT) ) { /* ...if not, ask the download agent to fetch it... */ const char *url_template = get_host_info( current->selection, "uri" ); if( url_template != NULL ) { /* ...from the URL constructed from the template specified in * the package repository catalogue (configuration database)... */ const char *mirror = get_host_info( current->selection, "mirror" ); char package_url[mkpath( NULL, url_template, package_name, mirror )]; mkpath( package_url, url_template, package_name, mirror ); // dmh_printf( "requesting %s ...\n", package_url ); download.Get( package_url ); } else /* Cannot download; the repository catalogue didn't specify a * template, from which to construct a download URL... */ dmh_notify( DMH_ERROR, "%s: no URL specified for download\n", package_name ); } } /* Repeat download action, for any additional packages specified * in the current "actions" list. */ current = current->next; } } #define DATA_CACHE_PATH "%R" "var/cache/mingw-get/data" #define WORKING_DATA_PATH "%R" "var/lib/mingw-get/data" /* Internet servers host package catalogues in lzma compressed format; * we will decompress them "on the fly", as we download them. To achieve * this, we will use a variant of the pkgInternetStreamingAgent, using a * specialised TransferData method; additionally, this will incorporate * a special derivative of a pkgLzmaArchiveStream, with its GetRawData * method adapted to stream data from an internet URI, instead of * reading from a local file. * * To derive the pkgInternetLzmaStreamingAgent, we need to include the * specialised declarations of a pkgArchiveStream, in order to make the * declaration of pkgLzmaArchiveStream available as our base class. */ #define PKGSTRM_H_SPECIAL 1 #include "pkgstrm.h" class pkgInternetLzmaStreamingAgent : public pkgInternetStreamingAgent, public pkgLzmaArchiveStream { /* Specialisation of the pkgInternetStreamingAgent base class, * providing decompressed copies of LZMA encoded files downloaded * from the Internet; (the LZMA decompression capability is derived * from the pkgLzmaArchiveStream base class). */ public: /* We need a specialised constructor... */ pkgInternetLzmaStreamingAgent( const char*, const char* ); private: /* Specialisation requires overrides for each of this pair of * methods, (the first from the pkgLzmaArchiveStream base class; * the second from pkgInternetStreamingAgent). */ virtual int GetRawData( int, uint8_t*, size_t ); virtual int TransferData( int ); }; /* This specialisation of the pkgInternetStreamingAgent class needs its * own constructor, simply to invoke the constructors for the base classes, * (since neither is instantiated by a default constructor). */ pkgInternetLzmaStreamingAgent::pkgInternetLzmaStreamingAgent ( const char *local_name, const char *dest_specification ): pkgInternetStreamingAgent( local_name, dest_specification ), pkgLzmaArchiveStream( -1 ){} int pkgInternetLzmaStreamingAgent::GetRawData( int fd, uint8_t *buf, size_t max ) { /* Fetch raw (compressed) data from the Internet host, and load it into * the decompression filter's input buffer, whence the TransferData routine * may retrieve it, via the filter, as an uncompressed stream. */ DWORD count; dl_status = pkgDownloadAgent.Read( dl_host, (char *)(buf), max, &count ); return (int)(count); } int pkgInternetLzmaStreamingAgent::TransferData( int fd ) { /* In this case, we read the file's data from the Internet source, * stream it through the lzma decompression filter, and write a copy * of the resultant decompressed data to the destination file. */ char buf[8192]; DWORD count; do { count = pkgLzmaArchiveStream::Read( buf, sizeof( buf ) ); write( fd, buf, count ); } while( dl_status && (count > 0) ); return dl_status; } static const char *serial_number( const char *catalogue ) { /* Local helper function to retrieve issue numbers from any repository * package catalogue; returns the result as a duplicate of the internal * string, allocated on the heap (courtesy of the strdup() function). */ const char *issue; pkgXmlDocument src( catalogue ); if( src.IsOk() && ((issue = src.GetRoot()->GetPropVal( "issue", NULL )) != NULL) ) /* * Found an issue number; return a copy... */ return strdup( issue ); /* If we get to here, we couldn't get a valid issue number; * whatever the reason, return NULL to indicate failure. */ return NULL; } void pkgXmlDocument::SyncRepository( const char *name, pkgXmlNode *repository ) { /* Fetch a named package catalogue from a specified Internet repository. * * Package catalogues are XML files; the master copy on the Internet host * must be stored in lzma compressed format, and named to comply with the * convention "%F.xml.lzma", in which "%F" represents the value of the * "name" argument passed to this pkgXmlDocument class method. */ const char *url_template; if( (url_template = repository->GetPropVal( "uri", NULL )) != NULL ) { /* Initialise a streaming agent, to manage the catalogue download; * (note that we must include the "%/M" placeholder in the template * for the local name, to accommodate the name of the intermediate * "in-transit" directory used by the streaming agent). */ pkgInternetLzmaStreamingAgent download( name, DATA_CACHE_PATH "%/M/%F.xml" ); { /* Construct the full URI for the master catalogue, and stream it to * a locally cached, decompressed copy of the XML file. */ const char *mirror = repository->GetPropVal( "mirror", NULL ); char catalogue_url[mkpath( NULL, url_template, name, mirror )]; mkpath( catalogue_url, url_template, name, mirror ); download.Get( catalogue_url ); } /* We will only replace our current working copy of this catalogue, * (if one already exists), with the copy we just downloaded, if this * downloaded copy bears an issue number indicating that it is more * recent than the working copy. */ const char *repository_version, *working_version; if( (repository_version = serial_number( download.DestFile() )) != NULL ) { /* Identify the location for the working copy, (if it exists). */ const char *working_copy_path_name = WORKING_DATA_PATH "/%F.xml"; char working_copy[mkpath( NULL, working_copy_path_name, name, NULL )]; mkpath( working_copy, working_copy_path_name, name, NULL ); /* Compare issue serial numbers... */ if( ((working_version = serial_number( working_copy )) == NULL) || ((strcmp( repository_version, working_version )) > 0) ) { /* In these circumstances, we couldn't identify an issue number * for the working copy of the catalogue; (maybe there is no such * catalogue, or maybe it doesn't specify a valid issue number); * in either case, we promote the downloaded copy in its place. * * FIXME: we assume that the working file and the downloaded copy * are stored on the same physical file system device, so we may * replace the former by simply deleting it, and renaming the * latter with its original path name; we make no provision for * replacing the working version by physical data copying. */ unlink( working_copy ); rename( download.DestFile(), working_copy ); } /* The issue numbers, returned by the serial_number() function, were * allocated on the heap; free them to avoid leaking memory! */ free( (void *)(repository_version) ); /* * The working copy issue number may be represented by a NULL pointer; * while it may be safe to call free on this, it just *seems* wrong, so * we check it first, to be certain. */ if( working_version != NULL ) free( (void *)(working_version) ); } /* If the downloaded copy of the catalogue is still in the download cache, * we have chosen to keep a previous working copy, so we have no further * use for the downloaded copy; discard it, noting that we don't need to * confirm its existence because this will fail silently, if it is no * longer present. */ unlink( download.DestFile() ); } } /* $RCSfile: pkginet.cpp,v $: end of file */ --- NEW FILE: keyword.c --- /* * keyword.c * * $Id: keyword.c,v 1.1 2009/11/23 20:44:25 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Implementation of "has_keyword()" function; this is used to check * for the presence of a specified keyword with a wihtespace separated * list, appearing as an XML property string. * * * 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 <ctype.h> #include <string.h> #include <stdlib.h> #define FALSE 0 #define TRUE !FALSE static inline char *safe_strdup( const char *src ) { /* Duplicate a "C" string into dynamically allocated memory, * safely handling a NULL source reference. */ return src ? strdup( src ) : NULL; } int has_keyword( const char *keywords, const char *wanted ) { /* Check the given "keywords" list for the presence of * the "wanted" keyword. */ char *inspect; if( (inspect = safe_strdup( keywords )) != NULL ) { /* We've found a non-empty list of keywords to inspect; * initialise a pointer to the first entry for matching... */ char *match = inspect; while( *match ) { /* We haven't yet checked all of the available keywords; * locate the end of the current inspection reference... */ char *brk = match; while( *brk && ! isspace( *brk ) ) ++brk; /* ...and append a NUL terminator. */ if( *brk ) *brk++ = '\0'; /* Check the currently selected alias... */ if( strcmp( match, wanted ) == 0 ) { /* ...and if it's a match, then immediately release the * scratch-pad memory we used for the keyword comparisons, * and return "true". */ free( (void *)(inspect) ); return TRUE; } /* Otherwise, proceed to check the next keyword, if any. */ match = brk; } /* If we get to here, then all assigned aliases have been * checked, without finding a match; the scratch-pad memory * remains allocated, so release it, before falling through * to return "false". */ free( (void *)(inspect) ); } /* Return "false" in all cases where no matching name can be found. */ return FALSE; } /* $RCSfile: keyword.c,v $: end of file */ --- NEW FILE: pkgstrm.cpp --- /* * pkgstrm.cpp * * $Id: pkgstrm.cpp,v 1.1 2009/11/23 20:44:25 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Implementation of the streaming data filters, which will be used * for reading package archives in any supported compression format; * currently supported formats are:-- * * raw (uncompressed) * gzip (compressed) * bzip2 (compressed) * lzma (compressed) * xz (compressed) * * * 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 <unistd.h> #include <fcntl.h> #ifndef O_BINARY /* * MS-Windows nuisances... * Files are expected to be either explicitly text or binary; * (UNIX makes no such specific distinction). We want to force * treatment of all files as binary; define a "no-op" substitute * for the appropriate MS-Windows attribute, for when we compile * on UNIX, so we may henceforth just use it unconditionally. */ # ifdef _O_BINARY # define O_BINARY _O_BINARY # else # define O_BINARY 0 # endif #endif /* We need to enable PKGSTRM_H_SPECIAL awareness, when we compile this... */ #define PKGSTRM_H_SPECIAL 1 #include "pkgstrm.h" /***** * * Class Implementation: pkgArchiveStream * * This class uses a default constructor and default virtual destructor. * We never instantiate objects of this class directly; all derived classes * provide their own specialised constructors and destructors, together with * a mandatory specialised "Read" method. * * We do, however, provide one generic "GetRawData" method, which derived * classes may adopt, or may override, as necessary... * */ int pkgArchiveStream::GetRawData( int fd, uint8_t *buf, size_t max ) { /* Generic helper function for reading a compressed data stream into * its decompressing filter's input buffer. The default implementation * assumes a file stream, and simply invokes a read() request; however, * we segregate this function, to facilitate an override to handle * other input streaming capabilities. */ return read( fd, buf, max ); } /***** * * Class Implementation: pkgRawArchiveStream * * This is the simplest archive stream class, suitable for archives * which have been stored WITHOUT compression... * */ pkgRawArchiveStream::pkgRawArchiveStream( const char *filename ) { /* The constructor has little to to, but to open the archive file * and associate a file descriptor with the resultant data stream. */ fd = open( filename, O_RDONLY | O_BINARY ); } pkgRawArchiveStream::~pkgRawArchiveStream() { /* The destructor needs only to close the data stream. */ close( fd ); } int pkgRawArchiveStream::Read( char *buf, size_t max ) { /* While the stream reader simply transfers the requested number * of bytes from the stream, to the caller's buffer. */ return read( fd, buf, max ); } /***** * * Class Implementation: pkgGzipArchiveStream * * This class creates an input streaming interface, suitable for * reading archives which have been stored with gzip compression. * The implementation is based on the use of libz.a, which allows * for a similar implementation to that of pkgRawArchiveStream. * */ pkgGzipArchiveStream::pkgGzipArchiveStream( const char *filename ) { /* Once more, the constructor has little to do but open the stream; * in this case, the method is analogous to C's fopen(). */ stream = gzopen( filename, "rb" ); } pkgGzipArchiveStream::~pkgGzipArchiveStream() { /* Another destructor, with little to do but close the stream; the * gzclose() call suffices for the purpose. */ gzclose( stream ); } int pkgGzipArchiveStream::Read( char *buf, size_t max ) { /* The reader is again served by a single function call, to transfer * the requested volume of decompressed data from the raw input file * to the caller's buffer. */ return gzread( stream, buf, max ); } /***** * * Class Implementation: pkgBzipArchiveStream * * This class creates an input streaming interface, suitable for * reading archives which have been stored with bzip2 compression. * The implementation is based on the use of libbz2.a, which again * allows for a fairly simple implementation, which is also quite * analogous to that of pkgRawArchiveStream. * */ pkgBzipArchiveStream::pkgBzipArchiveStream( const char *filename ) { /* The constructor carries a marginal additional overhead, in * that it must first open a regular file, before associating * a bzip2 control structure with it; subsequent stream access * is directed exclusively through that control structure. */ FILE *streamfile = fopen( filename, "rb" ); stream = BZ2_bzReadOpen( &bzerror, streamfile, 0, 0, 0, 0 ); } pkgBzipArchiveStream::~pkgBzipArchiveStream() { /* For the destructor, it is again just a matter of closing * the bzip2 stream; (this also takes care of closing the * associated file stream). */ BZ2_bzReadClose( &bzerror, stream ); } int pkgBzipArchiveStream::Read( char *buf, size_t max ) { /* Once again, reading is a simple matter of transferring * the requisite number of bytes to the caller's buffer. */ return BZ2_bzRead( &bzerror, stream, buf, max ); } /***** * * Class Implementation: pkgLzmaArchiveStream * * This class creates an input streaming interface, suitable for * reading archives which have been stored with lzma compression; * based on the use of liblzma.a, this implements an adaptation of * Lasse Collin's "xzdec" code, as configured for use as an lzma * decompressor. * */ static inline uint64_t memlimit() { /* Naively cap the memory available to lzma and xz decoders. * * FIXME: libarchive appears to use this; however, Lasse Collin * provides a more sophisticated method for xz, based on actual * physical memory footprint; we should adopt it. */ return 1ULL << 23 + 1ULL << 21; } static void lzma_stream_initialise( lzma_stream *stream ) { /* This simple helper provides a static template, which is * used to define initial state for lzma and xz decoders. */ static const lzma_stream stream_template = LZMA_STREAM_INIT; *stream = stream_template; /* * ...mark the input buffer as initially empty. */ stream->avail_in = 0; } pkgLzmaArchiveStream::pkgLzmaArchiveStream( const char *filename ) { /* The constructor must first open a file stream... */ if( (fd = open( filename, O_RDONLY | O_BINARY )) >= 0 ) { /* ...then set up the lzma decoder, in appropriately * initialised state... */ lzma_stream_initialise( &stream ); status = lzma_alone_decoder( &stream, memlimit() ); } } pkgLzmaArchiveStream::pkgLzmaArchiveStream( int fileno ):fd( fileno ) { /* ...then set up the lzma decoder, in appropriately * initialised state... */ lzma_stream_initialise( &stream ); status = lzma_alone_decoder( &stream, memlimit() ); } pkgLzmaArchiveStream::~pkgLzmaArchiveStream() { /* The destructor frees memory resources allocated to the decoder, * and closes the input stream file descriptor. * * FIXME: The lzma_alone_decoder may indicate end-of-stream, before * the physical input data stream is exhausted. For now, we silently * ignore any such residual data; (it is likely to be garbage anyway). * Should we handle it any more explicitly? */ lzma_end( &stream ); close( fd ); } int pkgLzmaArchiveStream::Read( char *buf, size_t max ) { /* Read an lzma compressed data stream; store up to "max" bytes of * decompressed data into "buf". * * Start by directing the decoder to use "buf", initially marking it * as "empty". */ stream.next_out = (uint8_t *)(buf); stream.avail_out = max; while( (stream.avail_out > 0) && (status == LZMA_OK) ) { /* "buf" hasn't been filled yet, and the decoder continues to say * that more data may be available. */ if( stream.avail_in == 0 ) { /* We exhausted the current content of the raw input buffer; * top it up again. */ stream.next_in = streambuf; if( (stream.avail_in = GetRawData( fd, streambuf, BUFSIZ )) < 0 ) { /* FIXME: an I/O error occurred here: need to handle it!!! */ } } /* Run the decoder, to decompress as much as possible of the data * currently in the raw input buffer, filling available space in * "buf"; go round again, in case we exhausted the raw input data * before we ran out of available space in "buf". */ status = lzma_code( &stream, LZMA_RUN ); } /* When we get to here, we either filled "buf" completely, or we * completely exhausted the raw input stream; in either case, we * return the actual number of bytes stored in "buf", (i.e. its * total size, less any residual free space). */ return max - stream.avail_out; } /***** * * Class Implementation: pkgXzArchiveStream * * This class creates an input streaming interface, suitable for * reading archives which have been stored with xz compression; * again based on the use of liblzma.a, this implements a further * adaptation of Lasse Collin's "xzdec" code, as configured for * use as an xz decompressor. * */ pkgXzArchiveStream::pkgXzArchiveStream( const char *filename ) { /* The constructor must first open a file stream... */ if( (fd = open( filename, O_RDONLY | O_BINARY )) >= 0 ) { /* ...then set up the lzma decoder, in appropriately * initialised state... */ lzma_stream_initialise( &stream ); status = lzma_stream_decoder( &stream, memlimit(), LZMA_CONCATENATED ); /* Finally, recognising that with LZMA_CONCATENATED data, * we will eventually need to switch the decoder from its * initial LZMA_RUN state to LZMA_FINISH, we must provide * a variable to specify the active state, (which we may * initialise for the LZMA_RUN state). */ opmode = LZMA_RUN; } } pkgXzArchiveStream::~pkgXzArchiveStream() { /* This destructor frees memory resources allocated to the decoder, * and closes the input stream file descriptor; unlike the preceding * case of the lzma_alone_decoder, the lzma_stream_decoder guarantees * that there is no trailing garbage remaining from the input stream. */ lzma_end( &stream ); close( fd ); } int pkgXzArchiveStream::Read( char *buf, size_t max ) { /* Read an xz compressed data stream; store up to "max" bytes of * decompressed data into "buf". * * Start by directing the decoder to use "buf", initially marking it * as "empty". */ stream.next_out = (uint8_t *)(buf); stream.avail_out = max; while( (stream.avail_out > 0) && (status == LZMA_OK) ) { /* "buf" hasn't been filled yet, and the decoder continues to say * that more data may be available. */ if( stream.avail_in == 0 ) { /* We exhausted the current content of the raw input buffer; * top it up again. */ stream.next_in = streambuf; if( (stream.avail_in = GetRawData( fd, streambuf, BUFSIZ )) < 0 ) { /* FIXME: an I/O error occurred here: need to handle it!!! */ } else if( stream.avail_in < BUFSIZ ) { /* A short read indicates end-of-input... * Unlike the case of the lzma_alone_decoder, (as used for * decompressing lzma streams), the lzma_stream_decoder, (when * initialised for LZMA_CONCATENATED data, as we use here), may * run lzma_code in either LZMA_RUN or LZMA_FINISH mode; the * normal mode is LZMA_RUN, but we switch to LZMA_FINISH * when we have exhausted the input stream. */ opmode = LZMA_FINISH; } } /* Run the decoder, to decompress as much as possible of the data * currently in the raw input buffer, filling available space in * "buf"; as noted above, "opmode" will be LZMA_RUN, until we have * exhausted the input stream, when it becomes LZMA_FINISH. */ status = lzma_code( &stream, opmode ); /* We need to go round again, in case we exhausted the raw input * data before we ran out of available space in "buf", except... */ if( (status == LZMA_OK) && (opmode == LZMA_FINISH) ) /* * ...when we've already achieved the LZMA_FINISH state, * this becomes unnecessary, so we break the cycle. */ break; } /* When we get to here, we either filled "buf" completely, or we * completely exhausted the raw input stream; in either case, we * return the actual number of bytes stored in "buf", (i.e. its * total size, less any residual free space). */ return max - stream.avail_out; } /***** * * Auxiliary function: pkgOpenArchiveStream() * * NOTE: Keep this AFTER the class specialisations, so that their derived * class declarations are visible for object instantiation here! * */ #include <string.h> #include <strings.h> extern "C" pkgArchiveStream* pkgOpenArchiveStream( const char* filename ) { /* Naive decompression filter selection, based on file name extension. * * FIXME: adopt more proactive selection method, (similar to that used * by libarchive, perhaps), based on magic patterns within the file. * * NOTE: MS-Windows may use UNICODE file names, but distributed package * archives almost certainly do not. For our purposes, use of the POSIX * Portable Character Set should suffice; we offer no concessions for * any usage beyond this. */ char *ext = strrchr( filename, '.' ); if( ext != NULL ) { if( strcasecmp( ext, ".gz" ) == 0 ) /* * We expect this input stream to be "gzip" compressed, * so we return the appropriate decompressor. */ return new pkgGzipArchiveStream( filename ); else if( strcasecmp( ext, ".bz2" ) == 0 ) /* * We expect this input stream to be "bzip2" compressed, * so again, we return the appropriate decompressor. */ return new pkgBzipArchiveStream( filename ); else if( strcasecmp( ext, ".lzma" ) == 0 ) /* * We expect this input stream to be "lzma" compressed, * so again, we return the appropriate decompressor. */ return new pkgLzmaArchiveStream( filename ); else if( strcasecmp( ext, ".xz" ) == 0 ) /* * We expect this input stream to be "xz" compressed, * so again, we return the appropriate decompressor. */ return new pkgXzArchiveStream( filename ); } /* If we get to here, then we didn't recognise any of the standard * compression indicating file name extensions; fall through, to * process the stream as raw (uncompressed) data. */ return new pkgRawArchiveStream( filename ); } /* $RCSfile: pkgstrm.cpp,v $: end of file */ --- NEW FILE: pkgstrm.h --- #ifndef PKGSTRM_H /* * pkgstrm.h * * $Id: pkgstrm.h,v 1.1 2009/11/23 20:44:25 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Declaration of the streaming API, for reading package 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. * */ #define PKGSTRM_H 1 #include <stdint.h> class pkgArchiveStream { /* Abstract base class... * All archive streaming classes are be derived from this. */ public: pkgArchiveStream(){} virtual int Read( char*, size_t ) = 0; virtual ~pkgArchiveStream(){} protected: virtual int GetRawData( int, uint8_t*, size_t ); }; #ifdef PKGSTRM_H_SPECIAL /* * Specialisations of the generic base class... * Most clients don't need to be specifically aware of these; * those that do must #define PKGSTRM_H_SPECIAL, before they * #include pkgstrm.h * */ class pkgRawArchiveStream : public pkgArchiveStream { /* A regular (uncompressed) data stream... */ protected: int fd; public: pkgRawArchiveStream( int ); pkgRawArchiveStream( const char* ); virtual ~pkgRawArchiveStream(); virtual int Read( char*, size_t ); }; /* Compressed data stream classes... */ #include <zlib.h> #include <bzlib.h> #ifdef __GNUC__ /* * lzma.h is broken w.r.t. static vs. dynamic linking; it always * declares all functions with the dllimport attribute, making it * impossible to link with a static liblzma.a, either by using GNU * ld's -Bstatic option in the presence of co-existing liblzma.a * static and liblzma.dll.a import libraries, or in the case where * the import library is not installed. To work around this defect, * we MUST declare LZMA_API_STATIC before we include lzma.h. This * DOES NOT in any way interfere with GNU ld's default preference * for dynamic linking; this will still be the effective linking * method if the import library is present, and the -Bstatic * option is not specified. */ # define LZMA_API_STATIC 1 #endif #include <lzma.h> class pkgGzipArchiveStream : public pkgArchiveStream { /* A stream compressed using the "gzip" algorithm... */ protected: gzFile stream; public: pkgGzipArchiveStream( int ); pkgGzipArchiveStream( const char* ); virtual ~pkgGzipArchiveStream(); virtual int Read( char*, size_t ); }; class pkgBzipArchiveStream : public pkgArchiveStream { /* A stream compressed using the "bzip2" algorithm... */ protected: BZFILE *stream; int bzerror; public: pkgBzipArchiveStream( int ); pkgBzipArchiveStream( const char* ); virtual ~pkgBzipArchiveStream(); virtual int Read( char*, size_t ); }; class pkgLzmaArchiveStream : public pkgArchiveStream { /* A stream compressed using the "lzma" algorithm... */ protected: int fd; lzma_stream stream; uint8_t streambuf[BUFSIZ]; int status; public: pkgLzmaArchiveStream( int ); pkgLzmaArchiveStream( const char* ); virtual ~pkgLzmaArchiveStream(); virtual int Read( char*, size_t ); }; class pkgXzArchiveStream : public pkgArchiveStream { /* A stream compressed using the "xz" algorithm... */ protected: int fd; lzma_stream stream; uint8_t streambuf[BUFSIZ]; lzma_action opmode; int status; public: pkgXzArchiveStream( int ); pkgXzArchiveStream( const char* ); virtual ~pkgXzArchiveStream(); virtual int Read( char*, size_t ); }; #endif /* PKGSTRM_H_SPECIAL */ /* A generic helper function, to open an archive stream using * the appropriate specialised stream class... */ extern "C" pkgArchiveStream *pkgOpenArchiveStream( const char* ); #endif /* PKGSTRM_H: $RCSfile: pkgstrm.h,v $: end of file */ |
From: Keith M. <kei...@us...> - 2009-11-23 20:40:22
|
Update of /cvsroot/mingw/mingw-get/xml In directory sfp-cvsdas-1.v30.ch3.sourceforge.com:/tmp/cvs-serv25439/xml Log Message: Directory /cvsroot/mingw/mingw-get/xml added to the repository |
From: Chris S. <ir0...@us...> - 2009-11-22 12:50:43
|
Update of /cvsroot/mingw/MinGW/inifiles In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv14721/inifiles Modified Files: Tag: MinGW-5_1 mingw.ini Log Message: 2009.11.22 Chris Sutcliffe <ir0...@us...> * inifiles/mingw.ini: Updated current for w32api. Index: mingw.ini =================================================================== RCS file: /cvsroot/mingw/MinGW/inifiles/Attic/mingw.ini,v retrieving revision 1.12.2.7 retrieving revision 1.12.2.8 diff -C2 -d -r1.12.2.7 -r1.12.2.8 *** mingw.ini 28 Oct 2009 13:37:35 -0000 1.12.2.7 --- mingw.ini 22 Nov 2009 12:50:33 -0000 1.12.2.8 *************** *** 8,12 **** runtime=mingwrt-3.15.2-mingw32-dev.tar.gz|7616 runtimeDLL=mingwrt-3.15.2-mingw32-dll.tar.gz|40 ! w32api=w32api-3.13-mingw32-dev.tar.gz|14420 binutils=binutils-2.20-1-mingw32-bin.tar.gz|26979 core=gcc-core-3.4.5-20060117-3.tar.gz|7712 --- 8,12 ---- runtime=mingwrt-3.15.2-mingw32-dev.tar.gz|7616 runtimeDLL=mingwrt-3.15.2-mingw32-dll.tar.gz|40 ! w32api=w32api-3.14-mingw32-dev.tar.gz|14460 binutils=binutils-2.20-1-mingw32-bin.tar.gz|26979 core=gcc-core-3.4.5-20060117-3.tar.gz|7712 *************** *** 20,24 **** [previous] runtime=mingw-runtime-3.14.tar.gz|6500 ! w32api=w32api-3.11.tar.gz|14500 binutils=binutils-2.19.1-mingw32-bin.tar.gz|21093 core=gcc-core-3.4.2-20040916-1.tar.gz|8627 --- 20,24 ---- [previous] runtime=mingw-runtime-3.14.tar.gz|6500 ! w32api=w32api-3.13-mingw32-dev.tar.gz|14420 binutils=binutils-2.19.1-mingw32-bin.tar.gz|21093 core=gcc-core-3.4.2-20040916-1.tar.gz|8627 |
From: Chris S. <ir0...@us...> - 2009-11-22 12:50:42
|
Update of /cvsroot/mingw/MinGW In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv14721 Modified Files: Tag: MinGW-5_1 ChangeLog Log Message: 2009.11.22 Chris Sutcliffe <ir0...@us...> * inifiles/mingw.ini: Updated current for w32api. Index: ChangeLog =================================================================== RCS file: /cvsroot/mingw/MinGW/Attic/ChangeLog,v retrieving revision 1.9.2.5 retrieving revision 1.9.2.6 diff -C2 -d -r1.9.2.5 -r1.9.2.6 *** ChangeLog 28 Oct 2009 13:37:34 -0000 1.9.2.5 --- ChangeLog 22 Nov 2009 12:50:30 -0000 1.9.2.6 *************** *** 1,2 **** --- 1,6 ---- + 2009.11.22 Chris Sutcliffe <ir0...@us...> + + * inifiles/mingw.ini: Updated current for w32api. + 2009.10.28 Chris Sutcliffe <ir0...@us...> |
From: Keith M. <kei...@us...> - 2009-11-16 21:54:41
|
Update of /cvsroot/mingw/mingw-get In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv19325 Modified Files: ChangeLog Makefile.in Log Message: Add XML database bindings and preliminary action executive for CLI. Index: Makefile.in =================================================================== RCS file: /cvsroot/mingw/mingw-get/Makefile.in,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** Makefile.in 31 Oct 2009 23:38:07 -0000 1.2 --- Makefile.in 16 Nov 2009 21:54:30 -0000 1.3 *************** *** 34,38 **** CXXFLAGS = $(CFLAGS) ! INCLUDES = -I ${srcdir}/src -I ${srcdir}/src/pkginfo LEX = @LEX@ --- 34,38 ---- CXXFLAGS = $(CFLAGS) ! INCLUDES = -I ${srcdir}/src -I ${srcdir}/src/pkginfo -I ${srcdir}/tinyxml LEX = @LEX@ *************** *** 47,50 **** --- 47,57 ---- LIBS = @LIBS@ + CORE_DLL_OBJECTS = climain.$(OBJEXT) \ + pkgexec.$(OBJEXT) pkginfo.$(OBJEXT) pkgspec.$(OBJEXT) \ + tinyxml.$(OBJEXT) tinyxmlparser.$(OBJEXT) \ + tinystr.$(OBJEXT) tinyxmlerror.$(OBJEXT) \ + mkpath.$(OBJEXT) xmlfile.$(OBJEXT) \ + vercmp.$(OBJEXT) dmh.$(OBJEXT) + %.$(OBJEXT): %.c $(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $< *************** *** 53,57 **** $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $< ! all: pkginfo$(EXEEXT) mingw-get$(EXEEXT) pkginfo$(EXEEXT): driver.$(OBJEXT) pkginfo.$(OBJEXT) --- 60,64 ---- $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) -o $@ $< ! all: pkginfo$(EXEEXT) mingw-get$(EXEEXT) mingw-get-0.dll pkginfo$(EXEEXT): driver.$(OBJEXT) pkginfo.$(OBJEXT) *************** *** 61,67 **** --- 68,92 ---- $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) $+ + mingw-get-0.dll: $(CORE_DLL_OBJECTS) + $(CXX) -shared -o $@ $(CXXFLAGS) $(LDFLAGS) $+ $(LIBS) + + dmh.$(OBJEXT): dmh.h + climain.$(OBJEXT): pkgbase.h pkgtask.h dmh.h + pkgexec.$(OBJEXT): pkgbase.h pkgtask.h mkpath.h dmh.h + pkgspec.$(OBJEXT): pkgbase.h pkginfo.h vercmp.h + + # Dependencies for stand alone pkginfo tool; + # (the pkginfo object is also required by the core DLL)... + # driver.$(OBJEXT): pkginfo.h pkginfo.$(OBJEXT): pkginfo.l pkginfo.h + # TinyXML dependencies... + # + tinyxml.$(OBJEXT): tinyxml.h + tinyxmlerror.$(OBJEXT): tinyxml.h + tinyxmlparser.$(OBJEXT): tinyxml.h + tinystr.$(OBJEXT): tinyxml.h + clean: rm -f *.$(OBJEXT) *.dll pkginfo$(EXEEXT) mingw-get$(EXEEXT) Index: ChangeLog =================================================================== RCS file: /cvsroot/mingw/mingw-get/ChangeLog,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** ChangeLog 12 Nov 2009 22:33:23 -0000 1.8 --- ChangeLog 16 Nov 2009 21:54:30 -0000 1.9 *************** *** 1,2 **** --- 1,16 ---- + 2009-11-16 Keith Marshall <kei...@us...> + + Add XML database bindings and preliminary action executive for CLI. + + * src/pkgbase.h, src/pkgtask.h, + src/mkpath.h, src/vercmp.h: New header files. + + * src/climain.cpp, src/pkgexec.cpp, src/pkgspec.cpp, + src/mkpath.c, src/vercmp.cpp, src/xmlfile.c: New files. + + * Makefile.in (CORE_DLL_OBJECTS): Define initial set of files... + (mingw-get-0.dll): ...build them into this new DLL target; add it... + (all): ...as prerequisite for this primary build goal. + 2009-11-12 Keith Marshall <kei...@us...> |
Update of /cvsroot/mingw/mingw-get/src In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv19325/src Added Files: climain.cpp mkpath.c mkpath.h pkgbase.h pkgexec.cpp pkgspec.cpp pkgtask.h vercmp.cpp vercmp.h xmlfile.c Log Message: Add XML database bindings and preliminary action executive for CLI. --- NEW FILE: vercmp.cpp --- #include <stdio.h> /* * vercmp.cpp * * $Id: vercmp.cpp,v 1.1 2009/11/16 21:54:30 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Implementation of package version comparator module. * * * 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 "vercmp.h" pkgVersionInfo::pkgVersionInfo( const char* version, const char* build ) { /* Constructor... * Decompose given version number string, storing components * within the specified class structure. */ const char *p = version ? version : ""; /* Walking over all version number constituent elements... */ for( int index = VERSION_MAJOR; index < VERSION_ELEMENT_COUNT; index++ ) { /* ...initialise default element value to zero. */ unsigned long value = 0L; /* When appropriate... */ if( (index == SNAPSHOT_DATE) && (*p == '\0') && (build != NULL) ) /* * ...select second argument for parsing. */ p = build; /* When parsing a numeric argument... */ while( (*p >= '0') && ((*p - '0') < 10) ) /* * ...accumulate its ultimate value. */ value = *p++ - '0' + 10 * value; /* Store it, and note presence of any suffix. */ version_elements[index].value = value; version_elements[index].suffix = p; /* Skip forward to next element field delimiter. */ while( *p && (*p != '.') && (*p != '-') ) ++p; if( (*p == '-') || ((*p == '\0') && (build != NULL)) ) /* * If we hit the end of the version number, * before we filled out all of its possible elements, * then zero the remainder, before we progress to * capture the build serial number. */ while( index < VERSION_PATCHLEVEL ) { version_elements[++index].value = 0L; version_elements[index].suffix = p; } /* Step over any delimiter, which demarcates the current * version number or build serial number element field. */ if( *p ) ++p; } } long pkgVersionInfo::Compare( const pkgVersionInfo& rhs, int index ) { /* Compare a given element of a package version specification with the * corresponding element of a reference (rhs) version specification; return * <0L, 0L or >0L for less than, equal to or greater than rhs respectively. */ long cmp = version_elements[index].value - rhs.version_elements[index].value; if( cmp == 0L ) { /* The specified element values are identically equal; * discriminate on suffixes, if any... */ const char *p = version_elements[index].suffix; const char *r = rhs.version_elements[index].suffix; /* Check that both version specifications include a suffix; * ( p == r implies both are NULL, hence neither has a suffix ); * if only one has, then that is the greater... */ if( p == r ) return 0L; if( p == NULL ) return 1L; if( r == NULL ) return -1L; /* Both DO have suffixes... */ while( *p && *r && (*p == *r) && (*p != '.') && (*p != '-') ) { /* ...scan both, until we find a mismatched character, * or the terminal delimiter for either. */ ++p; ++r; } /* Compute return value based on difference between the * mismatched characters, representing delimiters as NUL. */ cmp = (*p && (*p != '.') && (*p != '-')) ? (long)(*p) : 0L; cmp -= (*r && (*r != '.') && (*r != '-')) ? (long)(*r) : 0L; } return cmp; } bool pkgVersionInfo::operator<( const pkgVersionInfo& rhs ) { /* Comparison operator... * Does the version number under consideration represent a less * recent release than the specified reference version number. */ long cmp; for( int index = VERSION_MAJOR; index < VERSION_ELEMENT_COUNT; index++ ) if( (cmp = Compare( rhs, index )) != 0L ) return (cmp < 0L); /* If we get to here, lhs and rhs versions are identically equal, * and hence fail the lhs < rhs comparison. */ return false; } bool pkgVersionInfo::operator<=( const pkgVersionInfo& rhs ) { /* Comparison operator... * Does the version number under consideration represent the same, or * a less recent release than the specified reference version number. */ long cmp; for( int index = VERSION_MAJOR; index < VERSION_ELEMENT_COUNT; index++ ) if( (cmp = Compare( rhs, index )) != 0L ) return (cmp > 0L); /* If we get to here, lhs and rhs versions are identically equal, * and hence satisfy the lhs <= rhs comparison. */ return true; } bool pkgVersionInfo::operator==( const pkgVersionInfo& rhs ) { /* Comparison operator... * Does the version number under consideration exactly match * the specified reference version number. */ for( int index = VERSION_MAJOR; index < VERSION_ELEMENT_COUNT; index++ ) if( Compare( rhs, index ) != 0L ) return false; /* If we get to here, lhs and rhs versions are identically equal, * which is what we require to satisfy the lhs == rhs comparison. */ return true; } bool pkgVersionInfo::operator!=( const pkgVersionInfo& rhs ) { /* Comparison operator... * Does the version number under consideration differ from * the specified reference version number. */ for( int index = VERSION_MAJOR; index < VERSION_ELEMENT_COUNT; index++ ) if( Compare( rhs, index ) != 0L ) return true; /* If we get to here, lhs and rhs versions are identically equal, * which is the sole condition to fail the lhs != rhs comparison. */ return false; } bool pkgVersionInfo::operator>=( const pkgVersionInfo& rhs ) { /* Comparison operator... * Does the version number under consideration represent the same, or * a more recent release than the specified reference version number. */ long cmp; for( int index = VERSION_MAJOR; index < VERSION_ELEMENT_COUNT; index++ ) if( (cmp = Compare( rhs, index )) != 0L ) return (cmp > 0L); /* If we get to here, lhs and rhs versions are identically equal, * and hence satisfy the lhs >= rhs comparison. */ return true; } bool pkgVersionInfo::operator>( const pkgVersionInfo& rhs ) { /* Comparison operator... * Does the version number under consideration represent a more * recent release than the specified reference version number. */ long cmp; for( int index = VERSION_MAJOR; index < VERSION_ELEMENT_COUNT; index++ ) if( (cmp = Compare( rhs, index )) != 0L ) return (cmp > 0L); /* If we get to here, lhs and rhs versions are identically equal, * and hence fail the lhs > rhs comparison. */ return false; } /* $RCSfile: vercmp.cpp,v $: end of file */ --- NEW FILE: vercmp.h --- #ifndef VERCMP_H /* * vercmp.h * * $Id: vercmp.h,v 1.1 2009/11/16 21:54:30 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Public interface for the package version comparator module, as * implemented in the "C++" language file "vercmp.cpp". * * * 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 VERCMP_H 1 #include <stdlib.h> enum { /* The constituent elements of a package version number, * and build serial number, in sequential order as they appear * within a correctly formed package tarball name. */ VERSION_MAJOR = 0, VERSION_MINOR, VERSION_PATCHLEVEL, SNAPSHOT_DATE, SERIAL_NUMBER, /* Not a real element of the version/serial number sequence, * but this final entry in the enumeration provides a convenient * counter for the number of real elements listed above. */ VERSION_ELEMENT_COUNT }; struct version_t { /* Internal structure, used to capture an individual element * of a decomposed version number, or build serial number. */ unsigned long value; const char* suffix; }; #ifdef __cplusplus /* * Define the properties of the "C++" class API... */ class pkgVersionInfo { /* A class for capture and manipulation of package version numbers * in decomposed "major.minor.patch-datetamp-sequence" form. */ public: /* Constructor... * This expects either one or two "char *" arguments: * the first is the package version number, in "major.minor.patch" * format; the second is build serial number in "datestamp-sequence" * format. If the second is omitted, the build serial number may * be appended to the first, in the full format as above. */ pkgVersionInfo( const char* version = "", const char* build = NULL ); /* Package version comparison operators. */ bool operator<( const pkgVersionInfo& ); bool operator<=( const pkgVersionInfo& ); bool operator==( const pkgVersionInfo& ); bool operator!=( const pkgVersionInfo& ); bool operator>=( const pkgVersionInfo& ); bool operator>( const pkgVersionInfo& ); private: /* The decomposed version/serial number elements. */ struct version_t version_elements[VERSION_ELEMENT_COUNT]; /* An internal comparison helper function */ long Compare( const pkgVersionInfo&, int ); }; #endif /* __cplusplus */ #endif /* VERCMP_H: $RCSfile: vercmp.h,v $: end of file */ --- NEW FILE: mkpath.h --- #ifndef MKPATH_H /* * mkpath.h * * $Id: mkpath.h,v 1.1 2009/11/16 21:54:30 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Prototype declarations for the path name constructor functions, * and the directory hierarchy and file creation functions, which are * implemented in mkpath.c * * * 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 MKPATH_H 1 #ifndef EXTERN_C # ifdef __cplusplus # define EXTERN_C extern "C" # else # define EXTERN_C # endif #endif EXTERN_C int mkdir_recursive( const char *, int ); EXTERN_C int set_output_stream( const char *, int ); EXTERN_C int mkpath( char *, const char *, const char *, const char * ); #endif /* MKPATH_H: $RCSfile: mkpath.h,v $: end of file */ --- NEW FILE: xmlfile.c --- /* * xmlfile.c * * $Id: xmlfile.c,v 1.1 2009/11/16 21:54:30 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Helper function for constructing path names to the XML data files * specifying the mingw-get configuration, and installation manifest. * * * 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 <stdlib.h> #include "mkpath.h" const char *xmlfile( const char *name, const char *modifier ) { /* Construct a full path name for the file specified by "name", * adding the mandatory ".xml" extension; the path is always based * at "${APPROOT}", with "modifier" specifying an optional subdirectory * of the standard path, (typically used as a temporary location for * internet downloads while in transit). */ const char *datapath = "%R" "var/lib/mingw-get/data" "%/M/%F.xml"; char *datafile = (char *)(malloc( mkpath( NULL, datapath, name, modifier ) )); mkpath( datafile, datapath, name, modifier ); return (const char *)(datafile); } /* $RCSfile: xmlfile.c,v $: end of file */ --- NEW FILE: climain.cpp --- /* * climain.cpp * * $Id: climain.cpp,v 1.1 2009/11/16 21:54:30 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Implementation of the main program function, which is invoked by * the command line start-up stub when arguments are supplied; this * causes the application to continue running as a CLI process. * * * 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 <string.h> #include "dmh.h" #include "pkgbase.h" #include "pkgtask.h" EXTERN_C int climain( int argc, char **argv ) { /* Set up the diagnostic message handler, using the console's * `stderr' stream for notifications... */ dmh_init( DMH_SUBSYSTEM_TTY, *argv++ ); /* TODO: insert code here, to interpret any OPTIONS specified * on the command line. */ /* Interpret the `action keyword', specifying the action to be * performed on this invocation... */ int action = action_code( *argv ); if( action < 0 ) /* * The specified action keyword was invalid; * force an abort through a DMH_FATAL notification... */ dmh_notify( DMH_FATAL, "%s: unknown action keyword\n", *argv ); /* If we get to here, then the specified action identifies a * valid operation; load the package database, according to the * local `profile' configuration, and invoke the operation. */ const char *dfile; pkgXmlDocument dbase( dfile = xmlfile( "profile" ) ); if( dbase.IsOk() ) { /* We successfully loaded the basic settings... * The configuration file name was pushed on to the heap, * by xmlfile(); we don't need that any more, (because it * is reproduced within the database image itself), so * free the heap copy, to avoid memory leaks. */ free( (void *)(dfile) ); #if 0 /* Merge all package lists, as specified in the "repository" * section of the "profile", into the XML database tree... */ if( dbase.BindRepositories() == NULL ) /* * ...bailing out, on an invalid profile specification... */ dmh_notify( DMH_FATAL, "%s: invalid application profile\n", dbase.Value() ); /* Now schedule the specified action for each additionally * specified command line argument, (each of which is assumed * to represent a package name... */ while( --argc ) dbase.Schedule( (unsigned long)(action), *++argv ); /* ...and finally, execute all scheduled actions... */ dbase.ExecuteActions(); #endif /* If we get this far, then all actions completed successfully; * we are done... */ return EXIT_SUCCESS; } /* If we get to here, then the package database load failed; * once more, we force an abort through a DMH_FATAL notification... * * Note: although dmh_notify does not return, in the DMH_FATAL case, * GCC cannot know this, so we pretend that it gives us a return value, * to avoid a possible warning about reaching the end of a non-void * function without a return value assignment... */ return dmh_notify( DMH_FATAL, "%s: cannot load configuration\n", dfile ); } /* $RCSfile: climain.cpp,v $: end of file */ --- NEW FILE: pkgexec.cpp --- /* * pkgexec.cpp * * $Id: pkgexec.cpp,v 1.1 2009/11/16 21:54:30 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Implementation of package management task scheduler and executive. * * * 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 "dmh.h" #include "mkpath.h" #include "pkgbase.h" #include "pkginfo.h" #include "pkgtask.h" EXTERN_C const char *action_name( unsigned long index ) { /* Define the keywords used on the mingw-get command line, * to specify the package management actions to be performed, * mapping each to a unique action code index. */ static const char* action_id[] = { "no change", /* unused; zero cannot test true in a bitwise test */ "remove", /* remove a previously installed package */ "install", /* install a new package */ "upgrade" /* update previously installed packages */ }; /* For specified "index", return a pointer to the associated keyword, * or NULL, if "index" is outside the defined action code range. */ return ((index >= 0) && (index < end_of_actions)) ? action_id[ index ] : NULL; } EXTERN_C int action_code( const char* request ) { /* Match an action keyword specified on the command line * to an entry from the above list... */ int lencode = strlen( request ); int index; for( index = 0; index < end_of_actions; index++ ) { /* Try all defined keywords in turn, until we find a match * or we run out of definitions... */ if( strncmp( request, action_name( index ), lencode ) == 0 ) /* * for a successful match... * immediately return the associated action code index. */ return index; } /* If we get to here, the specified keyword was not matched; * signal this, by returning -1. */ return -1; } pkgActionItem::pkgActionItem( pkgActionItem *after, pkgActionItem *before ) { /* Construct an appropriately initialised non-specific pkgActionItem... */ flags = 0; /* no specific action yet assigned */ min_wanted = NULL; /* no minimum package version constraint... */ max_wanted = NULL; /* nor any maximum version */ selection = NULL; /* no package selection yet, for this item */ /* Insert this item at a specified location in the actions list. */ prev = after; next = before; } pkgActionItem* pkgActionItem::Append( pkgActionItem *item ) { /* Add an "item" to an ActionItems list, attaching it immediately * after the item referenced by the "this" pointer; nominally "this" * refers to the last entry in the list, resulting in a new item * being appended to the list, but the implementation preserves * integrity of any following list items, thus also fulfilling * an "insert after this" function. */ if( this == NULL ) /* * No list exists yet; * return "item" as first and only entry in new list. */ return item; /* Ensure "item" physically exists, or if not, create a generic * placeholder in which to construct it... */ if( (item == NULL) && ((item = new pkgActionItem()) == NULL) ) /* * ...bailing out if no such placeholder can be created. */ return NULL; /* Maintain list integrity... */ if( (item->next = next) != NULL ) /* * ...moving any existing items which already follow the insertion * point in the list structure, to follow the newly added "item". */ next->prev = item; /* Set the new item's own reference pointer, to establish its list * attachment point... */ item->prev = this; /* ...and attach it immediately after that point. */ return next = item; } pkgActionItem* pkgActionItem::Insert( pkgActionItem *item ) { /* Add an "item" to an ActionItems list, inserting it immediately * before the item referenced by the "this" pointer. */ if( this == NULL ) /* * No list exists yet; * return "item" as first and only entry in new list. */ return item; /* Ensure "item" physically exists, or if not, create a generic * placeholder in which to construct it... */ if( (item == NULL) && ((item = new pkgActionItem()) == NULL) ) /* * ...bailing out if no such placeholder can be created. */ return NULL; /* Maintain list integrity... */ if( (item->prev = prev) != NULL ) /* * ...moving any existing items which already precede the insertion * point in the list structure, to precede the newly added "item". */ prev->next = item; /* Set the new item's own reference pointer, to establish the item * currently at the attachment point, as its immediate successor... */ item->next = this; /* ...and attach it, immediately preceding that point. */ return prev = item; } pkgActionItem* pkgActionItem::Schedule( unsigned long action, pkgActionItem& item ) { /* Make a copy of an action item template (which may exist in * a volatile scope) on the heap, assign the requested action, * and return it for inclusion in the task schedule. */ pkgActionItem *rtn = new pkgActionItem(); *rtn = item; rtn->flags = action | (rtn->flags & ~ACTION_MASK); return rtn; } pkgActionItem* pkgActionItem::GetReference( pkgActionItem& item ) { /* Check for a prior reference, within the task schedule, * for the package specified for processing by "item". */ pkgXmlNode* pkg; if( (pkg = item.selection->GetParent()) != NULL ) { /* We have a pointer to the XML database entry which identifies * the package containing the release specified as the selection * associated with "item"; walk the chain of prior entries in * the schedule... */ for( pkgActionItem* item = this; item != NULL; item = item->prev ) { /* ...and if we find another item holding an identical pointer, * (i.e. to the same package), we return it... */ if( item->selection->GetParent() == pkg ) return item; } } /* If we get to here, there is no prior action scheduled for the * specified package, so we return a NULL pointer... */ return NULL; } const char * pkgActionItem::SetRequirements( pkgXmlNode *req ) { /* Establish the selection criteria, for association of any * particular package release with an action item. */ flags &= ACTION_MASK; /* First check for a strict equality requirement... */ if( (min_wanted = req->GetPropVal( "eq", NULL )) != NULL ) /* * ...and if specified, set the selection range such that * only the one specific release can match. */ max_wanted = min_wanted; else { /* Check for either an inclusive, or a strictly exclusive, * minimum requirement (release "greater" than) specification, * setting the minimum release selector... */ if( ((min_wanted = req->GetPropVal( "ge", NULL )) == NULL) && ((min_wanted = req->GetPropVal( "gt", NULL )) != NULL) ) /* * ...and its selection mode flag accordingly. */ flags |= STRICTLY_GT; /* Similarly, check for an inclusive, or a strictly exclusive, * maximum requirement (release "less" than) specification, * setting the maximum release selector... */ if( ((max_wanted = req->GetPropVal( "le", NULL )) == NULL) && ((max_wanted = req->GetPropVal( "lt", NULL )) != NULL) ) /* * ...and its selection mode flag accordingly. */ flags |= STRICTLY_LT; } /* Return a canonical representation of the requirements spec. */ return (min_wanted == NULL) ? max_wanted : min_wanted; } pkgXmlNode *pkgActionItem::SelectIfMostRecentFit( pkgXmlNode *package ) { /* Assign "package" as the "selection" for the referring action item, * provided it matches the specified selection criteria and it represents * a more recent release than any current selection. */ pkgSpecs test( package ); /* Establish the selection criteria... */ pkgSpecs min_fit( min_wanted ); pkgSpecs max_fit( max_wanted ); /* Choose one of the above, as a basis for identification of * a correct package-component match... */ pkgSpecs& fit = min_wanted ? min_fit : max_fit; /* Verify that "package" fulfills the selection criteria... */ if( match_if_explicit( test.GetComponentClass(), fit.GetComponentClass() ) && match_if_explicit( test.GetComponentVersion(), fit.GetComponentVersion() ) && ((max_wanted == NULL) || ((flags & STRICTLY_LT) ? (test < max_fit) : (test <= max_fit))) && ((flags & STRICTLY_GT) ? (test > min_fit) : (test >= min_fit)) ) { /* We have the correct package component, and it fits within * the allowed range of release versions... */ pkgSpecs last( selection ); if( test > last ) /* * It is also more recent than the current selection, * so we now replace that... */ selection = package; } /* Whatever choice we make, we return the resultant selection... */ return selection; } pkgActionItem* pkgXmlDocument::Schedule ( unsigned long action, pkgActionItem& item, pkgActionItem* rank ) { /* Schedule an action item with a specified ranking order in * the action list, (or at the end of the list if no ranking * position is specified)... */ pkgActionItem *ref = rank ? rank : actions; /* Record the requested action code... */ request = action; /* Don't reschedule, if we already have a prior matching item... */ if( (ref->GetReference( item ) == NULL) /* * ...but, when we don't, we raise a new scheduling request... */ && ((ref = ref->Schedule( action, item )) != NULL) ) { /* ...and, when successfully raised, add it to the task list... */ if( rank ) /* * ...at the specified ranking position, if any... */ return rank->Insert( ref ); else /* ...otherwise, at the end of the list. */ return actions = actions->Append( ref ); } /* If we get to here, then no new action was scheduled; we simply * return the current insertion point in the task list. */ return rank; } /* $RCSfile: pkgexec.cpp,v $: end of file */ --- NEW FILE: mkpath.c --- /* * mkpath.c * * $Id: mkpath.c,v 1.1 2009/11/16 21:54:30 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Helper functions for constructing path names, creating directory * hierarchies, and preparing to write new files within any specified * file system hierarchy. * * * 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 "mkpath.h" #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> #ifdef _WIN32 /* * MS-Windows nuisances... * mkdir() function doesn't accept a `mode' argument; ignore it. */ # define mkdir( PATH, MODE ) _mkdir( PATH ) /* * MS-Windows _O_BINARY vs. _O_TEXT discrimination can't be explicitly * resolved in a simple `creat()' call; instead, we will use `_open()', * with the following explicit attribute set... */ # define _O_NEWFILE _O_RDWR | _O_CREAT | _O_TRUNC | _O_BINARY # define creat(P,M) _open( P, _O_NEWFILE, _map_posix_mode(M) ) /* Furthermore, MS-Windows protection modes are naive, in comparison * to the POSIX modes specified within tar archive headers; firstly, * there is no concept of `execute' permissions; secondly, there is * no concept of a `write-only' file, (thus _S_IREAD permission is * implicitly granted for all files); thirdly, `write' permission is * granted only by a single _S_IWRITE flag, so at best, we must set * this if any of POSIX's S_IWUSR, S_IWGRP or S_IWOTH flags are set * in the tar header; finally, MS-Windows has no counterpart for any * of POSIX's `suid', `sgid' or `sticky' bits. */ # define _S_IWANY 0222 /* eqv. POSIX's S_IWUSR | S_IWGRP | S_IWOTH */ # define _map_posix_mode(M) _S_IREAD | (((M) & _S_IWANY) ? _S_IWRITE : 0) #endif int mkpath( char *buf, const char *fmt, const char *file, const char *modifier ) { /* A helper function, for constructing package URL strings. * Return value is the length, in bytes, of the constructed string, * which is returned in "buf"; call with "buf = NULL" to determine * the size of buffer required, without storing the string. * * Constructed URL is copied from "fmt", with... * * %% replaced by a single literal "%" character; * %[/]F replaced by the string passed as "file"; * %[/]M replaced by the string passed as "modifier"; * %[/]R replaced by the "APPROOT" environment string. * * Any other character present in "fmt" is copied literally. In * the case of "%F", "%M" and "%R", inclusion of the optional "/" * flag causes a single "/" character to be inserted before the * substitute string, provided this is not NULL; ("\\" may be * used, but is not recommended, in place of the "/" flag). */ char c; int len = 0; /* Scan "fmt"... */ do { if( (c = *fmt++) == '%' ) { /* Interpret substitution tags... */ char flag = *fmt; const char *subst = NULL; /* ...checking for presence of a "/" flag... */ if( ((flag == '/') || (flag == '\\')) && fmt[1] ) /* * ...and, when found, with a possibly valid format spec, * advance to parse that spec... */ ++fmt; else /* ...establish absence of the flag. */ flag = '\0'; switch( c = *fmt++ ) { case 'F': /* * Schedule substitution of text specified as "file". */ subst = file; break; case 'M': /* * Schedule substitution of text specified as "modifier", */ subst = modifier; break; case 'R': /* * Schedule substitution from the "APPROOT" environment string, */ subst = getenv( "APPROOT" ); break; case '%': /* * Interpreting "%%", but may have been "%/%", which is invalid... */ if( flag == '\0' ) { /* * It was just "%%", so store a literal "%" character. */ if( buf != NULL ) *buf++ = '%'; ++len; break; } /* If we get to here, it was the invalid "%/%" form; backtrack, * and fall through to emit literal "%/", then resume parsing, * treating the second "%" as the possible starting character * of a new format specification. */ c = flag; --fmt; default: if( buf != NULL ) { /* Store the literal "%" character, * followed by the unrecognised tag character. */ *buf++ = '%'; *buf++ = c; } len += 2; } if( subst != NULL ) { /* Perform scheduled substitution of "file", "modifier" * or the APPROOT environment string... */ if( flag ) { ++len; if( buf != NULL ) *buf++ = flag; } while( *subst ) { /* ...counting and copying character by character. */ ++len; if( buf != NULL ) *buf++ = *subst; ++subst; } } } else { /* * Copy one literal character from "fmt"... */ if( buf != NULL ) /* * ...storing as necessary... */ *buf++ = c; /* ...and counting it anyway. */ ++len; } } while( c ); /* Always return the total number of characters which were, or would * have been transferred to "buf". */ return len; } static void create_parent_directory_hierarchy( const char *pathname, int mode ) { /* Recursive helper function to create a directory branch, including * all missing parent directories, (analogous to using "mkdir -p"). * * FIXME: We allow for either "/" or "\" as the directory separator; * do we also need to accommodate possible use of multibyte-character * encodings? (Hopefully, archives should rely exclusively on the * POSIX Portable Character set, i.e. 7-bit ASCII, so maybe not). */ char *parse, *parent, *mark = NULL, *stop = NULL; /* We work with a copy of the supplied "pathname", so we can guarantee * we have a modifiable string, and can accept a "const" input string. */ if( (parse = parent = strdup( pathname )) != NULL ) { /* Having obtained a valid copy of "pathname", we parse it... */ while( *parse ) { /* Set the "stop" mark at the first in the last sequence of * one or more directory separators detected, (if any)... */ stop = mark; /* * ...then step over any following characters which are * neither the string terminator, nor further separators. */ while( *parse && (*parse != '/') && (*parse != '\\') ) ++parse; /* If we haven't yet found the string terminator, then we * must have found a new sequence of one or more separators; * mark it as a new candidate "stop" mark location. */ if( *parse ) mark = parse; /* Now, step over all contiguous separators in the current * sequence, before restarting the outer loop, to parse the * next directory or file name, (if any). Note that we defer * updating the "stop" mark until the start of this new cycle; * this ensures that we correctly ignore any separators which * trail at the end of "pathname", with no following "name" * component. */ while( (*parse == '/') || (*parse == '\\') ) ++parse; } if( stop != NULL ) { /* We found a valid point, at which to split the current leaf * of "pathname" from its parent branch hierarchy; split it and * recurse through the "mkdir" function, to create the parent * directory hierarchy, as required. */ *stop = '\0'; mkdir_recursive( parent, mode ); } /* We are now done with our temporary copy of "pathname"; reclaim * the memory which was allocated to store it. */ free( parent ); } } int mkdir_recursive( const char *pathname, int mode ) { /* Public entry point for the recursive "mkdir" function. * * First, we attempt a simple "mkdir"; if this succeeds, the * parent directory branch is already in place, and we have * nothing more to do. */ if( mkdir( pathname, mode ) == 0 ) return 0; /* Otherwise... */ switch( errno ) { case ENOENT: /* * This indicates a gap in the parent branch hierarchy; * call the preceding helper, to fill the gap... */ create_parent_directory_hierarchy( pathname, mode ); /* * ...before making a further attempt to add the leaf. */ return mkdir( pathname, mode ); case EEXIST: { /* Here, the initial "mkdir" failed because a file * system entity called "pathname" already exists; if * this is already a directory, all is well; (there is * no need to create it again)... */ struct stat target; if( (stat( pathname, &target ) == 0) && S_ISDIR( target.st_mode ) ) return 0; } } /* ...otherwise we simply fall through and fail... */ return -1; } int set_output_stream( const char *pathname, int mode ) { /* Attach the extractor's output data stream to a specified file, * creating the parent directory branch hierarchy as required, and * return a file descriptor on the stream. */ int fd; /* First, simply attempt to create the destination file... */ if( ((fd = creat( pathname, mode )) < 0) && (errno == ENOENT) ) { /* ...but, on failure due to a gap in the directory structure * call the preceding helper to create the necessary hierarchy... */ create_parent_directory_hierarchy( pathname, 0755 ); /* * ...before making a further attempt to create the file. */ return creat( pathname, mode ); } /* Here, we will have the invalid file descriptor from the initial * failed attempt to create the file; we return it to indicate the * ultimate failure to create this file. */ return fd; } /* $RCSfile: mkpath.c,v $: end of file */ --- NEW FILE: pkgtask.h --- #ifndef PKGTASK_H /* * pkgtask.h * * $Id: pkgtask.h,v 1.1 2009/11/16 21:54:30 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * This header provides manifest definitions for the action codes, * which are used by the installer engine's task scheduler. * * * 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 PKGTASK_H 1 enum { action_none = 0, action_remove, action_install, action_upgrade, end_of_actions }; #define ACTION_MASK 0x0F #define ACTION_NONE (unsigned long)(action_none) #define ACTION_REMOVE (unsigned long)(action_remove) #define ACTION_INSTALL (unsigned long)(action_install) #define ACTION_UPGRADE (unsigned long)(action_upgrade) #define STRICTLY_GT ACTION_MASK + 1 #define STRICTLY_LT STRICTLY_GT << 1 #ifndef EXTERN_C # ifdef __cplusplus # define EXTERN_C extern "C" # else # define EXTERN_C # endif #endif EXTERN_C const char *action_name( unsigned long ); EXTERN_C int action_code( const char* ); #endif /* PKGTASK_H: $RCSfile: pkgtask.h,v $: end of file */ --- NEW FILE: pkgbase.h --- #ifndef PKGBASE_H /* * pkgbase.h * * $Id: pkgbase.h,v 1.1 2009/11/16 21:54:30 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Public interface for the package directory management routines; * declares the XML data structures, and their associated class APIs, * which are used to describe packages and their interdependencies. * * * 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 PKGBASE_H 1 #include <tinyxml.h> #include <tinystr.h> #ifndef EXTERN_C # ifdef __cplusplus # define EXTERN_C extern "C" # else # define EXTERN_C # endif #endif class pkgXmlNode : public TiXmlElement { /* A minimal emulation of the wxXmlNode class, founded on * the tinyxml implementation of the TiXmlElement class, and * subsequently extended by application specific features. */ public: /* Constructors... */ inline pkgXmlNode( const char* name ):TiXmlElement( name ){} inline pkgXmlNode( const pkgXmlNode& src ):TiXmlElement( src ){} /* Accessors... */ inline const char* GetName() { /* Retrieve the identifying name of the XML tag; * tinyxml calls this the element "value"... */ return Value(); } inline pkgXmlNode* GetParent() { /* wxXmlNode provides this equivalant of tinyxml's * Parent() method. */ return (pkgXmlNode*)(Parent()); } inline pkgXmlNode* GetChildren() { /* wxXmlNode provides only this one method to access * the children of an element; it is equivalent to the * FirstChild() method in tinyxml's arsenal. */ return (pkgXmlNode*)(FirstChild()); } inline pkgXmlNode* GetNext() { /* This is wxXmlNode's method for visiting other children * of an element, after the first found by GetChildren(); * it is equivalent to tinyxml's NextSibling(). */ return (pkgXmlNode*)(NextSibling()); } inline const char* GetPropVal( const char* name, const char* subst ) { /* tinyxml has no direct equivalent for this wxXmlNode method, * (which substitutes default "subst" text for an omitted property), * but it may be trivially emulated, using the Attribute() method. */ const char* retval = Attribute( name ); return retval ? retval : subst; } /* Additional methods specific to the application. */ inline bool IsElementOfType( const char* tagname ) { /* Confirm if the owner XML node represents a data element * with the specified "tagname". */ return strcmp( GetName(), tagname ) == 0; } /* The following pair of methods provide an iterator * for enumerating the contained nodes, within the owner, * which themselves exhibit a specified tagname. */ pkgXmlNode* FindFirstAssociate( const char* tagname ); pkgXmlNode* FindNextAssociate( const char* tagname ); /* Specific to XML node elements of type "release", * the following pair of methods retrieve the actual name of * the release tarball, and its associated source code tarball, * as they are named on the project download servers. */ const char* ArchiveName(); const char* SourceArchiveName(); }; class pkgActionItem { /* A class implementing a bi-directionally linked list of * "action" descriptors, which is to be associated with the * pkgXmlDocument class, specifying actions to be performed * on the managed software installation. */ private: /* Pointers to predecessor and successor in the linked list * comprising the schedule of action items. */ pkgActionItem* prev; pkgActionItem* next; /* Flags define the specific action associated with this item. */ unsigned long flags; /* Criteria for selection of package versions associated with * this action item. */ const char* min_wanted; const char* max_wanted; /* Pointer to the XML database entry for the package selected * for processing by this action. */ pkgXmlNode* selection; /* Method for retrieving packages from a distribution server. */ void DownloadArchiveFiles( pkgActionItem* ); public: /* Constructor... */ pkgActionItem( pkgActionItem* = NULL, pkgActionItem* = NULL ); /* Methods for assembling action items into a linked list. */ pkgActionItem* Append( pkgActionItem* = NULL ); pkgActionItem* Insert( pkgActionItem* = NULL ); /* Methods for compiling the schedule of actions. */ pkgActionItem* GetReference( pkgActionItem& ); pkgActionItem* Schedule( unsigned long, pkgActionItem& ); /* Methods for defining the selection criteria for * packages to be processed. */ const char* SetRequirements( pkgXmlNode* ); pkgXmlNode* SelectIfMostRecentFit( pkgXmlNode* ); /* Method specifying where downloaded packages are stored. */ const char* ArchivePath(); /* Method for processing all scheduled actions. */ void Execute(); }; class pkgXmlDocument : public TiXmlDocument { /* Minimal emulation of the wxXmlDocument class, founded on * the tinyxml implementation of the TiXmlDocument class. */ public: /* Constructors... */ inline pkgXmlDocument( const char* name ) { /* tinyxml has a similar constructor, but unlike xwXmlDocument, * it DOES NOT automatically load the document; force it. */ LoadFile( name ); /* Always begin with an empty actions list. */ actions = NULL; } /* Accessors... */ inline bool IsOk() { /* tinyxml doesn't have this, but instead provides a complementary * `Error()' indicator, so to simulate `IsOk()'... */ return ! Error(); } inline pkgXmlNode* GetRoot() { /* This is wxXmlDocument's method for locating the document root; * it is equivalent to tinyxml's RootElement() method. */ return (pkgXmlNode *)(RootElement()); } private: /* Properties specifying the schedule of actions. */ unsigned long request; pkgActionItem* actions; /* Method to synchronise the state of the local package manifest * with the master copy held on the distribution server. */ void SyncRepository( const char*, pkgXmlNode* ); public: /* Method to merge content from repository-specific package lists * into the central XML package database. */ pkgXmlNode* BindRepositories(); /* Method to locate the XML database entry for a named package. */ pkgXmlNode* FindPackageByName( const char*, const char* = NULL ); /* Method to resolve the dependencies of a specified package, * by walking the chain of references specified by "requires" * elements in the respective package database entries. */ void ResolveDependencies( pkgXmlNode*, pkgActionItem* = NULL ); /* Methods for compiling a schedule of actions. */ void Schedule( unsigned long, const char* ); pkgActionItem* Schedule( unsigned long, pkgActionItem&, pkgActionItem* = NULL ); /* Method to execute a sequence of scheduled actions. */ inline void ExecuteActions(){ actions->Execute(); } }; EXTERN_C const char *xmlfile( const char*, const char* = NULL ); EXTERN_C int has_keyword( const char*, const char* ); static inline bool match_if_explicit( const char *value, const char *proto ) { /* Helper to compare a pair of "C" strings for equality, * accepting NULL as a match for anything. */ return (value == NULL) || (proto == NULL) || (strcmp( value, proto ) == 0); } #endif /* PKGBASE_H: $RCSfile: pkgbase.h,v $: end of file */ --- NEW FILE: pkgspec.cpp --- /* * pkgspec.cpp * * $Id: pkgspec.cpp,v 1.1 2009/11/16 21:54:30 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Implementation for the "pkgTarName" class, as declared in header * file "pkginfo.h". * * * 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 "pkginfo.h" #include "vercmp.h" #include <string.h> /* Constructors... */ pkgSpecs::pkgSpecs( const char *tarname ) { /* Parse the given tarball name, storing its constituent element * decomposition within the class' local "pkginfo" array structure. */ content = get_pkginfo( tarname ? tarname : "", specs ); } pkgSpecs::pkgSpecs( pkgXmlNode *release ) { /* Retrieve the "tarname" from an XML "release" specification, * then construct the "pkgSpecs" as if it were specified directly. */ const char *tarname = release ? release->GetPropVal( "tarname", NULL ) : NULL; content = get_pkginfo( tarname ? tarname : "", specs ); } /* Copy constructor... */ static void *clone_specs( char *content, pkginfo_t const src, pkginfo_t dst ) { /* Local helper function performs a deep copy of the "content" buffer, * and assigns the "specs" pointers to refer to it; this is the action * required to implement the copy constructor, and it is also used by * the assignment operator implentation. */ char *rtn; int count = PACKAGE_TAG_COUNT; /* Find the last allocated pointer in the source "specs" list; this * tells us where to find the last string in the "content" buffer... */ while( (count > 0) && (src[--count] == NULL) ) ; /* ...whence we may compute the size of the buffer, and allocate * a new buffer, into which to copy the data. */ count = src[count] + strlen( src[count] ) - content; if( (rtn = (char *)(malloc( count + 1))) != NULL ) { /* On successful buffer allocation, copy the data, * then walk the list of pointers... */ rtn = (char *)(memcpy( rtn, content, count )); for( count = 0; count < PACKAGE_TAG_COUNT; ++count ) { if( src[count] == NULL ) /* * ...propagating NULL pointers "as are"... */ dst[count] = NULL; else /* ...and non-NULL adjusted, as necessary, * to point into the copied data buffer... */ dst[count] = (char *)(rtn) + (src[count] - content); } } /* ...ultimately, returning the base address of the new buffer. */ return (void *)(rtn); } /* Formal implementation of the copy constructor... */ pkgSpecs::pkgSpecs( const pkgSpecs& src ) { /* ...requires no more than a call to the local helper function. */ content = clone_specs( (char *)(src.content), src.specs, specs ); } /* Assignment operator... */ pkgSpecs& pkgSpecs::operator=( const pkgSpecs& rhs ) { /* Provided the lhs and rhs represent distinct objects... */ if( this != &rhs ) { /* ...this is much the same as the copy constructor, except that, * while the constructor is guaranteed to be creating a new object, * assignment may be replacing an existing lhs object; this will * own a dynamically allocated data buffer, which must be freed, * to avoid leaking memory. */ free( content ); content = clone_specs( (char *)(rhs.content), rhs.specs, specs ); } return *this; } /* Destructor... */ pkgSpecs::~pkgSpecs() { /* Need to free the dynamic memory associated with the "specs" array, * and in which the actual tarname decomposition is stored. */ free( content ); } /* Comparison operators... */ static inline pkgVersionInfo version( pkgSpecs& pkg ) { /* Local helper, to construct package version descriptors * for use in version comparison operator implementations. */ return pkgVersionInfo( pkg.GetPackageVersion(), pkg.GetPackageBuild() ); } bool pkgSpecs::operator<( pkgSpecs& rhs ) { /* Check if the given package release is less recent, as indicated * by its version and build date/serial number, than another. */ return version( *this ) < version( rhs ); } bool pkgSpecs::operator<=( pkgSpecs& rhs ) { /* Check if the given package release is no more recent, as indicated * by its version and build date/serial number, than another. */ return version( *this ) <= version( rhs ); } bool pkgSpecs::operator>=( pkgSpecs& rhs ) { /* Check if the given package release is no less recent, as indicated * by its version and build date/serial number, than another. */ return version( *this ) >= version( rhs ); } bool pkgSpecs::operator>( pkgSpecs& rhs ) { /* Check if the given package release is more recent, as indicated * by its version and build date/serial number, than another. */ return version( *this ) > version( rhs ); } /* $RCSfile: pkgspec.cpp,v $: end of file */ |
From: Keith M. <kei...@us...> - 2009-11-12 22:33:38
|
Update of /cvsroot/mingw/mingw-get/src/pkginfo In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv10399/src/pkginfo Modified Files: driver.c Log Message: Avoid some potential GCC warnings. Index: driver.c =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/pkginfo/driver.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** driver.c 12 Oct 2009 21:35:29 -0000 1.1 --- driver.c 12 Nov 2009 22:33:26 -0000 1.2 *************** *** 34,37 **** --- 34,38 ---- */ #include <stdio.h> + #include <stdlib.h> #include "pkginfo.h" |
From: Keith M. <kei...@us...> - 2009-11-12 22:33:36
|
Update of /cvsroot/mingw/mingw-get In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv10399 Modified Files: ChangeLog Log Message: Avoid some potential GCC warnings. Index: ChangeLog =================================================================== RCS file: /cvsroot/mingw/mingw-get/ChangeLog,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** ChangeLog 11 Nov 2009 21:59:43 -0000 1.7 --- ChangeLog 12 Nov 2009 22:33:23 -0000 1.8 *************** *** 1,2 **** --- 1,11 ---- + 2009-11-12 Keith Marshall <kei...@us...> + + Avoid some potential GCC warnings. + + * src/clistub.c: Include process.h for `execv' prototype... + (main): Cast `argv' to appropriately matched type when calling it. + + * src/pkginfo/driver.c: Include stdlib.h for `free' prototype. + 2009-11-11 Keith Marshall <kei...@us...> |
From: Keith M. <kei...@us...> - 2009-11-12 22:33:35
|
Update of /cvsroot/mingw/mingw-get/src In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv10399/src Modified Files: clistub.c Log Message: Avoid some potential GCC warnings. Index: clistub.c =================================================================== RCS file: /cvsroot/mingw/mingw-get/src/clistub.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** clistub.c 31 Oct 2009 23:38:07 -0000 1.1 --- clistub.c 12 Nov 2009 22:33:26 -0000 1.2 *************** *** 35,38 **** --- 35,39 ---- #include <stdlib.h> #include <libgen.h> + #include <process.h> #define EXIT_FATAL EXIT_FAILURE + 1 *************** *** 198,202 **** char gui_program[1 + snprintf( NULL, 0, "%S", libexec_path )]; snprintf( gui_program, sizeof( gui_program ), "%S", libexec_path ); ! int status = execv( gui_program, argv ); /* If we get to here, then the GUI could not be started... --- 199,203 ---- char gui_program[1 + snprintf( NULL, 0, "%S", libexec_path )]; snprintf( gui_program, sizeof( gui_program ), "%S", libexec_path ); ! int status = execv( gui_program, (const char* const*)(argv) ); /* If we get to here, then the GUI could not be started... |
From: Keith M. <kei...@us...> - 2009-11-11 22:44:22
|
Update of /cvsroot/mingw/mingw-get/src In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv11100/src Added Files: dmh.cpp dmh.h Log Message: Create diagnostic message handler for CLI usage. --- NEW FILE: dmh.h --- #ifndef DMH_H /* * dmh.h * * $Id: dmh.h,v 1.1 2009/11/11 21:59:43 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * This header file provides the public API declarations for the * diagnostic message handling subsystem. * * * 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 DMH_H 1 #include <stdint.h> #undef EXTERN_C #ifdef __cplusplus # define EXTERN_C extern "C" #else # define EXTERN_C #endif typedef enum dmh_class { DMH_SUBSYSTEM_TTY = 0, DMH_SUBSYSTEM_GUI } dmh_class; typedef enum dmh_severity { DMH_INFO = 0, DMH_WARNING, DMH_ERROR, DMH_FATAL } dmh_severity; EXTERN_C void dmh_init( const dmh_class, const char* ); EXTERN_C int dmh_notify( const dmh_severity, const char *fmt, ... ); EXTERN_C int dmh_printf( const char *fmt, ... ); #define DMH_BEGIN_DIGEST 0x0001U, ~0x0001U #define DMH_END_DIGEST 0x0100U, 0x0000U EXTERN_C uint16_t dmh_control( const uint16_t, const uint16_t ); #endif /* DMH_H: $RCSfile: dmh.h,v $: end of file */ --- NEW FILE: dmh.cpp --- /* * dmh.cpp * * $Id: dmh.cpp,v 1.1 2009/11/11 21:59:43 keithmarshall Exp $ * * Written by Keith Marshall <kei...@us...> * Copyright (C) 2009, MinGW Project * * * Implementation of the diagnostic message handling subsystem. * * * 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 <stdarg.h> #include "dmh.h" class dmhTypeGeneric { /* Abstract base class, from which message handlers are derived. */ public: dmhTypeGeneric( const char* ); virtual uint16_t control( const uint16_t, const uint16_t ) = 0; virtual int notify( const dmh_severity, const char*, va_list ) = 0; virtual int printf( const char*, va_list ) = 0; protected: const char *progname; }; class dmhTypeTTY : public dmhTypeGeneric { /* Diagnostic message handler for use in console applications. */ public: dmhTypeTTY( const char *progname ); virtual uint16_t control( const uint16_t, const uint16_t ); virtual int notify( const dmh_severity, const char*, va_list ); virtual int printf( const char*, va_list ); }; class dmhTypeGUI : public dmhTypeGeneric { /* Diagnostic message handler for use in window applications. */ public: dmhTypeGUI( const char *progname ); virtual uint16_t control( const uint16_t, const uint16_t ); virtual int notify( const dmh_severity, const char*, va_list ); virtual int printf( const char*, va_list ); }; /* Constructors serve to initialise the message handler, * simply creating the class instance, and storing the specified * program name within it. */ dmhTypeGeneric::dmhTypeGeneric( const char* name ):progname( name ){} dmhTypeTTY::dmhTypeTTY( const char* name ):dmhTypeGeneric( name ){} dmhTypeGUI::dmhTypeGUI( const char* name ):dmhTypeGeneric( name ){} /* This pointer stores the address of the message handler * class instance, after initialisation. */ static dmhTypeGeneric *dmh = NULL; EXTERN_C void dmh_init( const dmh_class subsystem, const char *progname ) { /* Public entry point for message handler initialisation... * * We only do it once, silently ignoring any attempt to * establish a second handler. */ if( dmh == NULL ) { /* No message handler has yet been initialised; * passing the specified program name, select... */ if( subsystem == DMH_SUBSYSTEM_GUI ) /* * ...a GUI class handler on demand... */ dmh = new dmhTypeGUI( progname ); else /* ...otherwise, a console class handler by default. */ dmh = new dmhTypeTTY( progname ); } } static inline int abort_if_fatal( const dmh_severity code, int status ) { /* Helper function to abort an application, on notification * of a DMH_FATAL exception. */ if( code == DMH_FATAL ) exit( EXIT_FAILURE ); /* If the exception wasn't DMH_FATAL, then fall through to * return the specified status code. */ return status; } uint16_t dmhTypeGUI::control( const uint16_t request, const uint16_t mask ) { /* Select optional features of the GUI class message handler. * * FIXME: this is a stub; implementation to be provided. */ return 0; } int dmhTypeGUI::notify( const dmh_severity code, const char *fmt, va_list argv ) { /* Message dispatcher for GUI applications. * * FIXME: this is a stub; implementation to be provided. */ return fprintf( stderr, "%s: *** ERROR *** DMH_SUBSYSTEM_GUI not yet implemented\n", progname ); } int dmhTypeGUI::printf( const char *fmt, va_list argv ) { /* Display arbitrary text messages via the diagnostic message handler. * * FIXME: this is a stub; implementation to be provided. */ return notify( DMH_ERROR, fmt, argv ); } uint16_t dmhTypeTTY::control( const uint16_t request, const uint16_t mask ) { /* Select optional features of the console class message handler. * This message handler provides no optional features; we make this * a "no-op". */ return 0; } int dmhTypeTTY::notify( const dmh_severity code, const char *fmt, va_list argv ) { /* Message dispatcher for console class applications. */ static const char *severity[] = { /* Labels to identify message severity... */ "INFO", /* DMH_INFO */ "WARNING", /* DMH_WARNING */ "ERROR", /* DMH_ERROR */ "FATAL" /* DMH_FATAL */ }; /* Dispatch the message to standard error, terminate application * if DMH_FATAL, else continue, returning the message length. */ int retcode = fprintf( stderr, "%s: *** %s *** ", progname, severity[code] ); return abort_if_fatal( code, retcode + vfprintf( stderr, fmt, argv ) ); } int dmhTypeTTY::printf( const char *fmt, va_list argv ) { /* Display arbitrary text messages via the diagnostic message handler; * for the TTY subsystem, this is equivalent to printf() on stderr. */ return vfprintf( stderr, fmt, argv ); } EXTERN_C uint16_t dmh_control( const uint16_t request, const uint16_t mask ) { return dmh->control( request, mask ); } EXTERN_C int dmh_notify( const dmh_severity code, const char *fmt, ... ) { /* Public entry point for diagnostic message dispatcher. */ if( dmh == NULL ) { /* The message handler has been called before initialising it; * this is an internal program error -- treat it as fatal! */ dmh_init( DMH_SUBSYSTEM_TTY, "dmh" ); dmh_notify( DMH_FATAL, "message handler was not initialised\n" ); } /* Normal operation; pass the message on to the active handler. */ va_list argv; va_start( argv, fmt ); int retcode = dmh->notify( code, fmt, argv ); va_end( argv ); return retcode; } EXTERN_C int dmh_printf( const char *fmt, ... ) { /* Simulate standard printf() function calls, redirecting the display * of formatted output through the diagnostic message handler. */ va_list argv; va_start( argv, fmt ); int retcode = dmh->printf( fmt, argv ); va_end( argv ); return retcode; } /* $RCSfile: dmh.cpp,v $: end of file */ |
From: Keith M. <kei...@us...> - 2009-11-11 21:59:52
|
Update of /cvsroot/mingw/mingw-get In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv11100 Modified Files: ChangeLog Log Message: Create diagnostic message handler for CLI usage. Index: ChangeLog =================================================================== RCS file: /cvsroot/mingw/mingw-get/ChangeLog,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** ChangeLog 5 Nov 2009 21:53:19 -0000 1.6 --- ChangeLog 11 Nov 2009 21:59:43 -0000 1.7 *************** *** 1,2 **** --- 1,9 ---- + 2009-11-11 Keith Marshall <kei...@us...> + + Create diagnostic message handler for CLI usage. + + * src/dmh.h: New header file; it defines the public interface. + * src/dmh.cpp: New file; it implements the message handler. + 2009-11-05 Keith Marshall <kei...@us...> |
From: Keith M. <kei...@us...> - 2009-11-05 21:53:29
|
Update of /cvsroot/mingw/mingw-get In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv10294 Modified Files: ChangeLog Log Message: Correct some identified TinyXML issues. Index: ChangeLog =================================================================== RCS file: /cvsroot/mingw/mingw-get/ChangeLog,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** ChangeLog 31 Oct 2009 23:38:07 -0000 1.5 --- ChangeLog 5 Nov 2009 21:53:19 -0000 1.6 *************** *** 1,2 **** --- 1,15 ---- + 2009-11-05 Keith Marshall <kei...@us...> + + Correct some identified TinyXML issues. + + * tinyxml/tinyxml.h (IsWhiteSpace): Add FIXME annotation to flag + probable redundancy of checks for '\n' and '\r'. + * tinyxml/tinyxmlparser.cpp: Revert John E's 2008-08-09 change; remove + all such redundancies in IsWhiteSpace() calls throughout. + + * tinyxml/tinyxml.cpp (TiXmlAttribute::SetDoubleValue): Correct format + specification in sprintf()/snprintf() calls; "%lf" is invalid; replace + with "%f". + 2009-10-31 Keith Marshall <kei...@us...> |
From: Keith M. <kei...@us...> - 2009-11-05 21:52:42
|
Update of /cvsroot/mingw/mingw-get/tinyxml In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv10230 Modified Files: tinyxml.cpp tinyxml.h tinyxmlparser.cpp Log Message: Correct some identified TinyXML issues. Index: tinyxmlparser.cpp =================================================================== RCS file: /cvsroot/mingw/mingw-get/tinyxml/tinyxmlparser.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** tinyxmlparser.cpp 15 Aug 2008 02:45:34 -0000 1.1 --- tinyxmlparser.cpp 5 Nov 2009 21:52:29 -0000 1.2 *************** *** 23,30 **** */ - /* Modified: JohnE, 2008-08-09 - * Add parentheses to fix GCC -Wall warning - */ - #include <ctype.h> #include <stddef.h> --- 23,26 ---- *************** *** 351,355 **** } ! if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. ++p; else --- 347,351 ---- } ! if ( IsWhiteSpace( *p ) ) ++p; else *************** *** 359,363 **** else { ! while ( ( *p && IsWhiteSpace( *p ) ) || *p == '\n' || *p =='\r' ) ++p; } --- 355,359 ---- else { ! while ( *p && IsWhiteSpace( *p ) ) ++p; } *************** *** 1451,1455 **** value = ""; while ( p && *p // existence ! && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace && *p != '/' && *p != '>' ) // tag end { --- 1447,1451 ---- value = ""; while ( p && *p // existence ! && !IsWhiteSpace( *p ) // whitespace && *p != '/' && *p != '>' ) // tag end { Index: tinyxml.h =================================================================== RCS file: /cvsroot/mingw/mingw-get/tinyxml/tinyxml.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** tinyxml.h 15 Aug 2008 02:45:34 -0000 1.1 --- tinyxml.h 5 Nov 2009 21:52:29 -0000 1.2 *************** *** 291,294 **** --- 291,299 ---- inline static bool IsWhiteSpace( char c ) { + // FIXME: Explicit tests for '\n' and '\r' seem redundant here; + // POSIX requires isspace() to match both of these characters as + // white space anyway; is there any know implementation which + // does not comply with this requirement? + // return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); } Index: tinyxml.cpp =================================================================== RCS file: /cvsroot/mingw/mingw-get/tinyxml/tinyxml.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** tinyxml.cpp 15 Aug 2008 02:45:33 -0000 1.1 --- tinyxml.cpp 5 Nov 2009 21:52:28 -0000 1.2 *************** *** 1267,1273 **** char buf [256]; #if defined(TIXML_SNPRINTF) ! TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); #else ! sprintf (buf, "%lf", _value); #endif SetValue (buf); --- 1267,1273 ---- char buf [256]; #if defined(TIXML_SNPRINTF) ! TIXML_SNPRINTF( buf, sizeof(buf), "%f", _value); #else ! sprintf (buf, "%f", _value); #endif SetValue (buf); |