]> git.saurik.com Git - apt-legacy.git/blob - cmdline/apt-sortpkgs.cc
Added some initial debtags data.
[apt-legacy.git] / cmdline / apt-sortpkgs.cc
1 extern "C" {
2 #include <mach-o/nlist.h>
3 }
4
5 // -*- mode: cpp; mode: fold -*-
6 // Description /*{{{*/
7 // $Id: apt-sortpkgs.cc,v 1.5 2003/01/11 07:18:44 jgg Exp $
8 /* ######################################################################
9
10 APT Sort Packages - Program to sort Package and Source files
11
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.
15
16 ##################################################################### */
17 /*}}}*/
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>
25
26 #include <config.h>
27 #include <apti18n.h>
28
29 #include <vector>
30 #include <algorithm>
31
32 #include <locale.h>
33 #include <unistd.h>
34 /*}}}*/
35
36 using namespace std;
37
38 struct PkgName
39 {
40 string Name;
41 string Ver;
42 string Arch;
43 unsigned long Offset;
44 unsigned long Length;
45
46 inline int Compare3(const PkgName &x) const
47 {
48 int A = stringcasecmp(Name,x.Name);
49 if (A == 0)
50 {
51 A = stringcasecmp(Ver,x.Ver);
52 if (A == 0)
53 A = stringcasecmp(Arch,x.Arch);
54 }
55 return A;
56 }
57
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;};
61 };
62
63 // DoIt - Sort a single file /*{{{*/
64 // ---------------------------------------------------------------------
65 /* */
66 bool DoIt(string InFile)
67 {
68 FileFd Fd(InFile,FileFd::ReadOnly);
69 pkgTagFile Tags(&Fd);
70 if (_error->PendingError() == true)
71 return false;
72
73 // Parse.
74 vector<PkgName> List;
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)
80 {
81 PkgName Tmp;
82
83 /* Fetch the name, auto-detecting if this is a source file or a
84 package file */
85 Tmp.Name = Section.FindS("Package");
86 Tmp.Ver = Section.FindS("Version");
87 Tmp.Arch = Section.FindS("Architecture");
88
89 if (Tmp.Name.empty() == true)
90 return _error->Error(_("Unknown package record!"));
91
92 Tmp.Offset = Offset;
93 Tmp.Length = Section.size();
94 if (Largest < Tmp.Length)
95 Largest = Tmp.Length;
96
97 List.push_back(Tmp);
98
99 Offset = Tags.Offset();
100 }
101 if (_error->PendingError() == true)
102 return false;
103
104 // Sort it
105 sort(List.begin(),List.end());
106
107 const char **Order = TFRewritePackageOrder;
108 if (Source == true)
109 Order = TFRewriteSourceOrder;
110
111 // Emit
112 unsigned char *Buffer = new unsigned char[Largest+1];
113 for (vector<PkgName>::iterator I = List.begin(); I != List.end(); I++)
114 {
115 // Read in the Record.
116 if (Fd.Seek(I->Offset) == false || Fd.Read(Buffer,I->Length) == false)
117 {
118 delete [] Buffer;
119 return false;
120 }
121
122 Buffer[I->Length] = '\n';
123 if (Section.Scan((char *)Buffer,I->Length+1) == false)
124 {
125 delete [] Buffer;
126 return _error->Error("Internal error, failed to scan buffer");
127 }
128
129 // Sort the section
130 if (TFRewrite(stdout,Section,Order,0) == false)
131 {
132 delete [] Buffer;
133 return _error->Error("Internal error, failed to sort fields");
134 }
135
136 fputc('\n',stdout);
137 }
138
139 delete [] Buffer;
140 return true;
141 }
142 /*}}}*/
143 // ShowHelp - Show the help text /*{{{*/
144 // ---------------------------------------------------------------------
145 /* */
146 int ShowHelp()
147 {
148 ioprintf(cout,_("%s %s for %s %s\n"),PACKAGE,VERSION,
149 COMMON_OS,COMMON_CPU);
150 if (_config->FindB("version") == true)
151 return 0;
152
153 cout <<
154 _("Usage: apt-sortpkgs [options] file1 [file2 ...]\n"
155 "\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"
158 "\n"
159 "Options:\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");
164
165 return 0;
166 }
167 /*}}}*/
168
169 int main(unsigned int argc,const char *argv[])
170 {
171 #if !defined(__ENVIRONMENT_ASPEN_VERSION_MIN_REQUIRED__) || __ENVIRONMENT_ASPEN_VERSION_MIN_REQUIRED__ < 10200
172 struct nlist nl[2];
173 memset(nl, 0, sizeof(nl));
174 nl[0].n_un.n_name = (char *) "_useMDNSResponder";
175 nlist("/usr/lib/libc.dylib", nl);
176 if (nl[0].n_type != N_UNDF)
177 *(int *) nl[0].n_value = 0;
178 #endif
179
180 CommandLine::Args Args[] = {
181 {'h',"help","help",0},
182 {'v',"version","version",0},
183 {'s',"source","APT::SortPkgs::Source",0},
184 {'c',"config-file",0,CommandLine::ConfigFile},
185 {'o',"option",0,CommandLine::ArbItem},
186 {0,0,0,0}};
187
188 // Set up gettext support
189 setlocale(LC_ALL,"");
190 //textdomain(PACKAGE);
191
192 // Parse the command line and initialize the package library
193 CommandLine CmdL(Args,_config);
194 if (pkgInitConfig(*_config) == false ||
195 CmdL.Parse(argc,argv) == false ||
196 pkgInitSystem(*_config,_system) == false)
197 {
198 _error->DumpErrors();
199 return 100;
200 }
201
202 // See if the help should be shown
203 if (_config->FindB("help") == true ||
204 CmdL.FileSize() == 0)
205 return ShowHelp();
206
207 // Match the operation
208 for (unsigned int I = 0; I != CmdL.FileSize(); I++)
209 if (DoIt(CmdL.FileList[I]) == false)
210 break;
211
212 // Print any errors or warnings found during parsing
213 if (_error->empty() == false)
214 {
215 bool Errors = _error->PendingError();
216 _error->DumpErrors();
217 return Errors == true?100:0;
218 }
219
220 return 0;
221 }