[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bug#47379: [patch] local install



On Wed, Jan 28, 2004 at 11:46:39PM -0700, Jason Gunthorpe wrote:
> 
> On Mon, 26 Jan 2004, Michael Vogt wrote:
> 
> > We need a FileFd that contains the needed tags. In what way we obtain
> > the tags is irrelevant of course. I hope we find a better way than the
> > above for this :)
> 
> You need to use the utils in apt-inst that provide raw .deb access in a
> way that is compatible with the tag record parser. Read the source to
> apt-ftparchive to find out how.. Though I'd rather not have apt-get linked
> with apt-utils :|

Thanks for this hints Jason. I attached another patch that does no
longer calls dpkg but uses debDebFile::MemControlExtract Extract("control")
instead. 

The patch still has (at least) two problems:
1. It needs to link apt-pkg with apt-inst to get access to the debFile
   class. 
2. It creates a temporary file $pkgname.records in a insecure way. 

The problem with 2) is that the temporary records file is needed in
debSinglePkgIndex::Merge() and debSPTypePkg::CreatePkgParser(). I
don't know how to pass additional information to CreatePkgParser() so
I used a predictable filename for now. This can be solved by creating
a temporary file in each of the two functions. 

As for 1) I don't know what to do. We could use the dpkg fork/exec a
approach. Or we could copy-n-paste some code to extract only the
control file from a deb. All solutions are not optimal IMHO.

What do you think about this?

> Jason
Michael

-- 
Linux is not The Answer. Yes is the answer. Linux is The Question. - Neo
Index: apt-pkg/makefile
===================================================================
RCS file: /cvs/deity/apt/apt-pkg/makefile,v
retrieving revision 1.38
diff -u -r1.38 makefile
--- apt-pkg/makefile	9 Feb 2003 22:02:45 -0000	1.38
+++ apt-pkg/makefile	19 Mar 2004 13:27:12 -0000
@@ -15,7 +15,7 @@
 LIBEXT=$(GLIBC_VER)$(LIBSTDCPP_VER)
 MAJOR=3.3
 MINOR=0
-SLIBS=$(PTHREADLIB) $(INTLLIBS)
+SLIBS=$(PTHREADLIB) $(INTLLIBS) -lapt-inst
 APT_DOMAIN:=libapt-pkg$(MAJOR)
 
 # Source code for the contributed non-core things
Index: apt-pkg/pkgsystem.h
===================================================================
RCS file: /cvs/deity/apt/apt-pkg/pkgsystem.h,v
retrieving revision 1.6
diff -u -r1.6 pkgsystem.h
--- apt-pkg/pkgsystem.h	11 Nov 2002 06:55:50 -0000	1.6
+++ apt-pkg/pkgsystem.h	19 Mar 2004 13:27:13 -0000
@@ -80,6 +80,7 @@
 
    // Return a list of system index files..
    virtual bool AddStatusFiles(std::vector<pkgIndexFile *> &List) = 0;   
+   virtual bool AddSourceFiles(std::vector<pkgIndexFile *> &List) {};   
    virtual bool FindIndex(pkgCache::PkgFileIterator File,
 			  pkgIndexFile *&Found) const = 0;
    
Index: apt-pkg/sourcelist.cc
===================================================================
RCS file: /cvs/deity/apt/apt-pkg/sourcelist.cc,v
retrieving revision 1.24
diff -u -r1.24 sourcelist.cc
--- apt-pkg/sourcelist.cc	8 Jul 2002 04:18:07 -0000	1.24
+++ apt-pkg/sourcelist.cc	19 Mar 2004 13:27:14 -0000
@@ -18,6 +18,9 @@
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/strutl.h>
 
+// CNC:2003-11-21
+#include <apt-pkg/pkgsystem.h>
+
 #include <apti18n.h>
 
 #include <fstream>
@@ -237,6 +240,8 @@
    for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
       delete *I;
    SrcList.erase(SrcList.begin(),SrcList.end());
+   // CNC:2003-11-21
+   _system->AddSourceFiles(SrcList);
    char Buffer[300];
 
    int CurLine = 0;
Index: apt-pkg/deb/debindexfile.cc
===================================================================
RCS file: /cvs/deity/apt/apt-pkg/deb/debindexfile.cc,v
retrieving revision 1.6
diff -u -r1.6 debindexfile.cc
--- apt-pkg/deb/debindexfile.cc	4 Jan 2004 07:41:30 -0000	1.6
+++ apt-pkg/deb/debindexfile.cc	19 Mar 2004 13:27:18 -0000
@@ -23,8 +23,10 @@
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/acquire-item.h>
+#include <apt-pkg/debfile.h>
     
 #include <sys/stat.h>
+#include <stdio.h>
 									/*}}}*/
 
 // SourcesIndex::debSourcesIndex - Constructor				/*{{{*/
@@ -502,6 +504,176 @@
 const pkgIndexFile::Type *debStatusIndex::GetType() const
 {
    return &_apt_Status;
+}
+
+// ---------------------------------------------------------
+
+class debSPTypePkg : public pkgIndexFile::Type
+{
+   public:
+   
+   virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const 
+    {
+	string FieldsFile = string(File.FileName()) + string(".records");
+	return new debRecordParser(FieldsFile,  *File.Cache());
+    };
+   debSPTypePkg() 
+    {
+	Label = "Debian Single File Package Index";
+    };
+};
+
+static debSPTypePkg _apt_Single_Pkg;
+
+debSinglePkgIndex::debSinglePkgIndex(string File) 
+    : FilePath(File)
+{ 
+    // empty
+};
+
+bool debSinglePkgIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
+{
+    FileFd Fd(FilePath,FileFd::ReadOnly);
+    debDebFile Deb(Fd);
+
+    if(_error->PendingError() == true)
+       return false;
+
+    debDebFile::MemControlExtract Extract("control");
+    if (Extract.Read(Deb) == false) {
+       return false;
+    }
+
+    // write a temporary control file
+    string RecordsFile = string(FilePath+".records");
+    FILE *controlFile = fopen(RecordsFile.c_str(),"a");
+    struct stat S;
+    if(stat(FilePath.c_str(),&S) != 0)
+	_error->Error("Error stat() for %s ", FieldsFile.c_str());
+    fwrite(Extract.Control ,Extract.Length, 1 , controlFile);
+    fprintf(controlFile,"Size: %i\n",S.st_size);
+    fprintf(controlFile,"Filename: %s\n", FilePath.c_str());
+    fclose(controlFile);
+
+    // create file fd
+    FileFd Pkg(RecordsFile,FileFd::ReadOnly);
+    debListParser Parser(&Pkg);
+
+    Parser.setIsSingleFile(true);
+    Parser.setSingleFileName(FilePath);
+
+    if (_error->PendingError() == true)
+	return _error->Error("Problem opening %s",FilePath.c_str());
+
+    Prog.SubProgress(0,"mvo");
+    ::URI Tmp(URI);
+    //if (Gen.SelectFile(string(FilePath+".fields"),"host?",*this) == false)
+    if (Gen.SelectFile(FilePath,"host?",*this) == false)
+	return _error->Error("Problem with SelectFile %s",FilePath.c_str());
+    
+    pkgCache::PkgFileIterator File = Gen.GetCurFile();
+    struct stat St;
+    if (stat(FilePath.c_str(),&St) != 0)
+	return _error->Errno("fstat","Failed to stat");
+    File->Size = St.st_size;
+    File->mtime = St.st_mtime;
+
+    if (Gen.MergeList(Parser) == false)
+	return _error->Error("Problem with MergeList %s", FilePath.c_str());
+
+    return true;
+};
+
+string debSinglePkgIndex::ArchiveURI(string File) const
+{
+   char *cwd = getcwd(NULL,0);
+   if (File[0] == '.' && File[1] == '/')
+      File = string(File, 2);
+   string URI = "file://"+flCombine(cwd, File);
+
+   return URI;
+}
+
+string debSinglePkgIndex::Describe(bool Short) const
+{
+    return FilePath;
+}
+ 
+bool debSinglePkgIndex::Exists() const
+{
+    return FileExists(FilePath);
+}
+bool debSinglePkgIndex::HasPackages() const
+{
+    return true;
+}
+unsigned long debSinglePkgIndex::Size() const
+{
+    struct stat St;
+    if(stat(FilePath.c_str(), &St) != 0) {
+	return 0;
+    }
+    return St.st_size;
+}
+
+const pkgIndexFile::Type *debSinglePkgIndex::GetType() const
+{
+    return &_apt_Single_Pkg;
+}
+
+string debSinglePkgIndex::MainType() const 
+{
+    return "pkg";
+}
+
+string debSinglePkgIndex::IndexPath() const 
+{
+    return FilePath;
+}
+
+bool debSinglePkgIndex::GetReleases(pkgAcquire *Owner) const 
+{ 
+    return true; 
+}
+
+
+bool debSinglePkgIndex::GetIndexes(pkgAcquire *Owner) const 
+{ 
+    return true; 
+}
+
+string debSinglePkgIndex::ArchiveInfo(pkgCache::VerIterator Ver) const
+{
+    return FilePath;
+}
+
+string  debSinglePkgIndex::SourceInfo(pkgSrcRecords::Parser const &Record,
+			     pkgSrcRecords::File const &File) const
+{
+    return string();
+}
+
+pkgCache::PkgFileIterator debSinglePkgIndex::FindInCache(pkgCache &Cache) const
+{
+    // stolen from rpmindexfile
+   string FileName = IndexPath();
+   pkgCache::PkgFileIterator File = Cache.FileBegin();
+   for (; File.end() == false; File++)
+   {
+      if (FileName != File.FileName())
+	 continue;
+      
+      struct stat St;
+      if (stat(File.FileName(),&St) != 0) {
+	 return pkgCache::PkgFileIterator(Cache);
+      }
+      if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) {
+	 return pkgCache::PkgFileIterator(Cache);
+      }
+      return File;
+   }
+   
+   return File;
 }
 
 									/*}}}*/
Index: apt-pkg/deb/debindexfile.h
===================================================================
RCS file: /cvs/deity/apt/apt-pkg/deb/debindexfile.h,v
retrieving revision 1.3
diff -u -r1.3 debindexfile.h
--- apt-pkg/deb/debindexfile.h	29 Apr 2001 05:13:51 -0000	1.3
+++ apt-pkg/deb/debindexfile.h	19 Mar 2004 13:27:18 -0000
@@ -16,11 +16,49 @@
 #ifndef PKGLIB_DEBINDEXFILE_H
 #define PKGLIB_DEBINDEXFILE_H
 
+
 #ifdef __GNUG__
 #pragma interface "apt-pkg/debindexfile.h"
 #endif
 
 #include <apt-pkg/indexfile.h>
+#include <iostream>
+
+class debSinglePkgIndex : public pkgIndexFile
+{
+ protected:
+    string FilePath;
+    // this is the file with the package field information
+    string FieldsFile;
+
+    virtual string MainType() const;
+    virtual string IndexPath() const;
+
+ public:
+    virtual const Type *GetType() const;
+
+   virtual string ArchiveInfo(pkgCache::VerIterator Ver) const;
+   virtual string SourceInfo(pkgSrcRecords::Parser const &Record,
+			     pkgSrcRecords::File const &File) const;
+
+    virtual bool GetReleases(pkgAcquire *Owner) const;
+    virtual bool GetIndexes(pkgAcquire *Owner) const; 
+
+    virtual string ArchiveURI(string File) const;
+
+    virtual string Describe(bool Short = false) const;
+    virtual bool Exists() const;
+    virtual bool HasPackages() const;
+    virtual unsigned long Size() const;
+    virtual bool Merge(pkgCacheGenerator &/*Gen*/,OpProgress &/*Prog*/) const;
+    virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
+
+    debSinglePkgIndex(string File);
+
+};
+
+
+
 
 class debStatusIndex : public pkgIndexFile
 {
Index: apt-pkg/deb/deblistparser.cc
===================================================================
RCS file: /cvs/deity/apt/apt-pkg/deb/deblistparser.cc,v
retrieving revision 1.29
diff -u -r1.29 deblistparser.cc
--- apt-pkg/deb/deblistparser.cc	22 Sep 2003 04:16:26 -0000	1.29
+++ apt-pkg/deb/deblistparser.cc	19 Mar 2004 13:27:21 -0000
@@ -31,7 +31,7 @@
 // ListParser::debListParser - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-debListParser::debListParser(FileFd *File) : Tags(File)
+debListParser::debListParser(FileFd *File) : Tags(File), isSingleFile(false)
 {
    Arch = _config->Find("APT::architecture");
 }
@@ -47,6 +47,19 @@
       return 0;
    return WriteUniqString(Start,Stop - Start);
 }
+
+void debListParser::setIsSingleFile(bool val) 
+{
+    isSingleFile=val;
+};
+
+
+void debListParser::setSingleFileName(string s) 
+{
+    SingleFileName=s;
+};
+
+
 									/*}}}*/
 // ListParser::Package - Return the package name			/*{{{*/
 // ---------------------------------------------------------------------
@@ -113,7 +126,14 @@
    
    if (ParseProvides(Ver) == false)
       return false;
-   
+
+   // mvo: we have a special case here for installing single local debs
+   if (isSingleFile) {
+       if(NewProvides(Ver, SingleFileName, "") == false) {
+	   return false;
+       }
+   }
+
    return true;
 }
 									/*}}}*/
Index: apt-pkg/deb/deblistparser.h
===================================================================
RCS file: /cvs/deity/apt/apt-pkg/deb/deblistparser.h,v
retrieving revision 1.9
diff -u -r1.9 deblistparser.h
--- apt-pkg/deb/deblistparser.h	20 Feb 2001 07:03:17 -0000	1.9
+++ apt-pkg/deb/deblistparser.h	19 Mar 2004 13:27:21 -0000
@@ -31,7 +31,10 @@
    pkgTagSection Section;
    unsigned long iOffset;
    string Arch;
-   
+
+   bool isSingleFile;
+   string SingleFileName;
+
    unsigned long UniqFindTagWrite(const char *Tag);
    bool ParseStatus(pkgCache::PkgIterator Pkg,pkgCache::VerIterator Ver);
    bool ParseDepends(pkgCache::VerIterator Ver,const char *Tag,
@@ -40,6 +43,8 @@
    static bool GrabWord(string Word,WordList *List,unsigned char &Out);
    
    public:
+   void setIsSingleFile(bool val);
+   void setSingleFileName(string s);
 
    static unsigned char GetPrio(string Str);
       
Index: apt-pkg/deb/debsystem.cc
===================================================================
RCS file: /cvs/deity/apt/apt-pkg/deb/debsystem.cc,v
retrieving revision 1.4
diff -u -r1.4 debsystem.cc
--- apt-pkg/deb/debsystem.cc	26 Jan 2004 17:01:53 -0000	1.4
+++ apt-pkg/deb/debsystem.cc	19 Mar 2004 13:27:22 -0000
@@ -50,6 +50,26 @@
 {
    delete StatusFile;
 }
+
+
+bool debSystem::AddSourceFiles(vector<pkgIndexFile *> &List)
+{
+   const Configuration::Item *Top;
+   Top = _config->Tree("APT::Arguments");
+   if (Top != 0)
+   {
+      for (Top = Top->Child; Top != 0; Top = Top->Next) {
+	 const string &S = Top->Value;
+	 if (FileExists(S) && flExtension(S) == "deb")
+	 {
+	       List.push_back(new debSinglePkgIndex(S));
+	 }
+      }
+   }
+   return true;
+}
+
+
 									/*}}}*/
 // System::Lock - Get the lock						/*{{{*/
 // ---------------------------------------------------------------------
Index: apt-pkg/deb/debsystem.h
===================================================================
RCS file: /cvs/deity/apt/apt-pkg/deb/debsystem.h,v
retrieving revision 1.4
diff -u -r1.4 debsystem.h
--- apt-pkg/deb/debsystem.h	11 Jan 2003 07:16:33 -0000	1.4
+++ apt-pkg/deb/debsystem.h	19 Mar 2004 13:27:22 -0000
@@ -35,6 +35,8 @@
    virtual bool ArchiveSupported(const char *Type);
    virtual signed Score(Configuration const &Cnf);
    virtual bool AddStatusFiles(std::vector<pkgIndexFile *> &List);
+   //mvo
+   virtual bool AddSourceFiles(std::vector<pkgIndexFile *> &List);
    virtual bool FindIndex(pkgCache::PkgFileIterator File,
 			  pkgIndexFile *&Found) const;
 
Index: cmdline/apt-get.cc
===================================================================
RCS file: /cvs/deity/apt/cmdline/apt-get.cc,v
retrieving revision 1.155
diff -u -r1.155 apt-get.cc
--- cmdline/apt-get.cc	26 Feb 2004 19:17:55 -0000	1.155
+++ cmdline/apt-get.cc	19 Mar 2004 13:27:33 -0000
@@ -978,6 +978,41 @@
       pkgCache::PkgIterator Tmp = Pkg.ProvidesList().OwnerPkg();
       ioprintf(c1out,_("Note, selecting %s instead of %s\n"),
 	       Tmp.Name(),Pkg.Name());
+      // CNC:2003-11-21 - Check if the current candidate is really
+      //                  providing that dependency
+      pkgCache::VerIterator Ver = Cache[Tmp].CandidateVerIter(Cache);
+      pkgCache::PrvIterator Prv = Ver.ProvidesList();
+      bool Found = false;
+
+      for (; Prv.end() == false; Prv++) {
+	 if (strcmp(Prv.Name(), Pkg.Name()) == 0) {
+	    Found = true;
+	    break;
+	 }
+      }
+      if (Found == false) {
+	 // The current candidate doesn't provide the needed dependency.
+	 // Look for one that does.
+	 Ver = Tmp.VersionList();
+	 for (; Ver.end() == false; Ver++) {
+	    Prv = Ver.ProvidesList();
+	    Found = false;
+	    for (; Prv.end() == false; Prv++) {
+	       if (strcmp(Prv.Name(), Pkg.Name()) == 0) {
+		  Found = true;
+		  break;
+	       }
+	    }
+	    if (Found) {
+	       Cache.SetCandidateVersion(Ver);
+	       break;
+	    }
+	 }
+	 if (Found == false) {
+	    ioprintf(c1out,_("Internal error. Package %s doesn't provide %s\n"),Tmp.Name(),Pkg.Name());
+	    return false;
+	 }
+      }
       Pkg = Tmp;
    }
    
@@ -1374,7 +1409,7 @@
 	    S[--Length] = 0;
 	    continue;
 	 }
-	 
+
 	 char *Slash = strchr(S,'=');
 	 if (Slash != 0)
 	 {
@@ -2445,6 +2480,14 @@
 	 
       _error->DumpErrors();
       return 100;
+   }
+
+   // CNC:2003-11-21
+   if (CmdL.FileSize() != 1)
+   {
+      for (const char **I = CmdL.FileList + 1; *I != 0; I++) {
+	 _config->Set("APT::Arguments::", *I);
+      }
    }
 
    // See if the help should be shown

Reply to: