]> git.saurik.com Git - apt.git/blob - cmdline/apt-sortpkgs.cc
Added locale.h for LC_ALL
[apt.git] / cmdline / apt-sortpkgs.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-sortpkgs.cc,v 1.4 2002/02/15 03:40:00 jgg Exp $
4 /* ######################################################################
5
6 APT Sort Packages - Program to sort Package and Source files
7
8 This program is quite simple, it just sorts the package files by
9 package and sorts the fields inside by the internal APT sort order.
10 Input is taken from a named file and sent to stdout.
11
12 ##################################################################### */
13 /*}}}*/
14 // Include Files /*{{{*/
15 #include <apt-pkg/tagfile.h>
16 #include <apt-pkg/error.h>
17 #include <apt-pkg/configuration.h>
18 #include <apt-pkg/cmndline.h>
19 #include <apt-pkg/init.h>
20 #include <apt-pkg/strutl.h>
21
22 #include <config.h>
23 #include <apti18n.h>
24
25 #include <vector>
26 #include <algorithm>
27
28 #include <locale.h>
29 #include <unistd.h>
30 /*}}}*/
31
32 struct PkgName
33 {
34 string Name;
35 string Ver;
36 string Arch;
37 unsigned long Offset;
38 unsigned long Length;
39
40 inline int Compare3(const PkgName &x) const
41 {
42 int A = stringcasecmp(Name,x.Name);
43 if (A == 0)
44 {
45 A = stringcasecmp(Ver,x.Ver);
46 if (A == 0)
47 A = stringcasecmp(Arch,x.Arch);
48 }
49 return A;
50 }
51
52 bool operator <(const PkgName &x) const {return Compare3(x) < 0;};
53 bool operator >(const PkgName &x) const {return Compare3(x) > 0;};
54 bool operator ==(const PkgName &x) const {return Compare3(x) == 0;};
55 };
56
57 // DoIt - Sort a single file /*{{{*/
58 // ---------------------------------------------------------------------
59 /* */
60 bool DoIt(string InFile)
61 {
62 FileFd Fd(InFile,FileFd::ReadOnly);
63 pkgTagFile Tags(&Fd);
64 if (_error->PendingError() == true)
65 return false;
66
67 // Parse.
68 vector<PkgName> List;
69 pkgTagSection Section;
70 unsigned long Largest = 0;
71 unsigned long Offset = Tags.Offset();
72 bool Source = _config->FindB("APT::SortPkgs::Source",false);
73 while (Tags.Step(Section) == true)
74 {
75 PkgName Tmp;
76
77 /* Fetch the name, auto-detecting if this is a source file or a
78 package file */
79 Tmp.Name = Section.FindS("Package");
80 Tmp.Ver = Section.FindS("Version");
81 Tmp.Arch = Section.FindS("Architecture");
82
83 if (Tmp.Name.empty() == true)
84 return _error->Error(_("Unknown package record!"));
85
86 Tmp.Offset = Offset;
87 Tmp.Length = Section.size();
88 if (Largest < Tmp.Length)
89 Largest = Tmp.Length;
90
91 List.push_back(Tmp);
92
93 Offset = Tags.Offset();
94 }
95 if (_error->PendingError() == true)
96 return false;
97
98 // Sort it
99 sort(List.begin(),List.end());
100
101 const char **Order = TFRewritePackageOrder;
102 if (Source == true)
103 Order = TFRewriteSourceOrder;
104
105 // Emit
106 unsigned char *Buffer = new unsigned char[Largest+1];
107 for (vector<PkgName>::iterator I = List.begin(); I != List.end(); I++)
108 {
109 // Read in the Record.
110 if (Fd.Seek(I->Offset) == false || Fd.Read(Buffer,I->Length) == false)
111 {
112 delete [] Buffer;
113 return false;
114 }
115
116 Buffer[I->Length] = '\n';
117 if (Section.Scan((char *)Buffer,I->Length+1) == false)
118 {
119 delete [] Buffer;
120 return _error->Error("Internal error, failed to scan buffer");
121 }
122
123 // Sort the section
124 if (TFRewrite(stdout,Section,Order,0) == false)
125 {
126 delete [] Buffer;
127 return _error->Error("Internal error, failed to sort fields");
128 }
129
130 fputc('\n',stdout);
131 }
132
133 delete [] Buffer;
134 return true;
135 }
136 /*}}}*/
137 // ShowHelp - Show the help text /*{{{*/
138 // ---------------------------------------------------------------------
139 /* */
140 int ShowHelp()
141 {
142 ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
143 COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
144 if (_config->FindB("version") == true)
145 return 0;
146
147 cout <<
148 _("Usage: apt-sortpkgs [options] file1 [file2 ...]\n"
149 "\n"
150 "apt-sortpkgs is a simple tool to sort package files. The -s option is used\n"
151 "to indicate what kind of file it is.\n"
152 "\n"
153 "Options:\n"
154 " -h This help text\n"
155 " -s Use source file sorting\n"
156 " -c=? Read this configuration file\n"
157 " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp\n");
158
159 return 0;
160 }
161 /*}}}*/
162
163 int main(unsigned int argc,const char *argv[])
164 {
165 CommandLine::Args Args[] = {
166 {'h',"help","help",0},
167 {'v',"version","version",0},
168 {'s',"source","APT::SortPkgs::Source",0},
169 {'c',"config-file",0,CommandLine::ConfigFile},
170 {'o',"option",0,CommandLine::ArbItem},
171 {0,0,0,0}};
172
173 // Set up gettext support
174 setlocale(LC_ALL,"");
175 textdomain(PACKAGE);
176
177 // Parse the command line and initialize the package library
178 CommandLine CmdL(Args,_config);
179 if (pkgInitConfig(*_config) == false ||
180 CmdL.Parse(argc,argv) == false ||
181 pkgInitSystem(*_config,_system) == false)
182 {
183 _error->DumpErrors();
184 return 100;
185 }
186
187 // See if the help should be shown
188 if (_config->FindB("help") == true ||
189 CmdL.FileSize() == 0)
190 return ShowHelp();
191
192 // Match the operation
193 for (unsigned int I = 0; I != CmdL.FileSize(); I++)
194 if (DoIt(CmdL.FileList[I]) == false)
195 break;
196
197 // Print any errors or warnings found during parsing
198 if (_error->empty() == false)
199 {
200 bool Errors = _error->PendingError();
201 _error->DumpErrors();
202 return Errors == true?100:0;
203 }
204
205 return 0;
206 }