2 #include <mach-o/nlist.h>
5 // -*- mode: cpp; mode: fold -*-
7 // $Id: apt-sortpkgs.cc,v 1.5 2003/01/11 07:18:44 jgg Exp $
8 /* ######################################################################
10 APT Sort Packages - Program to sort Package and Source files
12 This program is quite simple, it just sorts the package files by
13 package and sorts the fields inside by the internal APT sort order.
14 Input is taken from a named file and sent to stdout.
16 ##################################################################### */
18 // Include Files /*{{{*/
19 #include <apt-pkg/tagfile.h>
20 #include <apt-pkg/error.h>
21 #include <apt-pkg/configuration.h>
22 #include <apt-pkg/cmndline.h>
23 #include <apt-pkg/init.h>
24 #include <apt-pkg/strutl.h>
46 inline int Compare3(const PkgName &x) const
48 int A = stringcasecmp(Name,x.Name);
51 A = stringcasecmp(Ver,x.Ver);
53 A = stringcasecmp(Arch,x.Arch);
58 bool operator <(const PkgName &x) const {return Compare3(x) < 0;};
59 bool operator >(const PkgName &x) const {return Compare3(x) > 0;};
60 bool operator ==(const PkgName &x) const {return Compare3(x) == 0;};
63 // DoIt - Sort a single file /*{{{*/
64 // ---------------------------------------------------------------------
66 bool DoIt(string InFile)
68 FileFd Fd(InFile,FileFd::ReadOnly);
70 if (_error->PendingError() == true)
75 pkgTagSection Section;
76 unsigned long Largest = 0;
77 unsigned long Offset = Tags.Offset();
78 bool Source = _config->FindB("APT::SortPkgs::Source",false);
79 while (Tags.Step(Section) == true)
83 /* Fetch the name, auto-detecting if this is a source file or a
85 Tmp.Name = Section.FindS("Package");
86 Tmp.Ver = Section.FindS("Version");
87 Tmp.Arch = Section.FindS("Architecture");
89 if (Tmp.Name.empty() == true)
90 return _error->Error(_("Unknown package record!"));
93 Tmp.Length = Section.size();
94 if (Largest < Tmp.Length)
99 Offset = Tags.Offset();
101 if (_error->PendingError() == true)
105 sort(List.begin(),List.end());
107 const char **Order = TFRewritePackageOrder;
109 Order = TFRewriteSourceOrder;
112 unsigned char *Buffer = new unsigned char[Largest+1];
113 for (vector<PkgName>::iterator I = List.begin(); I != List.end(); I++)
115 // Read in the Record.
116 if (Fd.Seek(I->Offset) == false || Fd.Read(Buffer,I->Length) == false)
122 Buffer[I->Length] = '\n';
123 if (Section.Scan((char *)Buffer,I->Length+1) == false)
126 return _error->Error("Internal error, failed to scan buffer");
130 if (TFRewrite(stdout,Section,Order,0) == false)
133 return _error->Error("Internal error, failed to sort fields");
143 // ShowHelp - Show the help text /*{{{*/
144 // ---------------------------------------------------------------------
148 ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
149 COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
150 if (_config->FindB("version") == true)
154 _("Usage: apt-sortpkgs [options] file1 [file2 ...]\n"
156 "apt-sortpkgs is a simple tool to sort package files. The -s option is used\n"
157 "to indicate what kind of file it is.\n"
160 " -h This help text\n"
161 " -s Use source file sorting\n"
162 " -c=? Read this configuration file\n"
163 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n");
169 int main(unsigned int argc,const char *argv[])
172 memset(nl, 0, sizeof(nl));
173 nl[0].n_un.n_name = (char *) "_useMDNSResponder";
174 nlist("/usr/lib/libc.dylib", nl);
175 if (nl[0].n_type != N_UNDF)
176 *(int *) nl[0].n_value = 0;
178 CommandLine::Args Args[] = {
179 {'h',"help","help",0},
180 {'v',"version","version",0},
181 {'s',"source","APT::SortPkgs::Source",0},
182 {'c',"config-file",0,CommandLine::ConfigFile},
183 {'o',"option",0,CommandLine::ArbItem},
186 // Set up gettext support
187 setlocale(LC_ALL,"");
190 // Parse the command line and initialize the package library
191 CommandLine CmdL(Args,_config);
192 if (pkgInitConfig(*_config) == false ||
193 CmdL.Parse(argc,argv) == false ||
194 pkgInitSystem(*_config,_system) == false)
196 _error->DumpErrors();
200 // See if the help should be shown
201 if (_config->FindB("help") == true ||
202 CmdL.FileSize() == 0)
205 // Match the operation
206 for (unsigned int I = 0; I != CmdL.FileSize(); I++)
207 if (DoIt(CmdL.FileList[I]) == false)
210 // Print any errors or warnings found during parsing
211 if (_error->empty() == false)
213 bool Errors = _error->PendingError();
214 _error->DumpErrors();
215 return Errors == true?100:0;