RemoteDrawingEngine: Reduce RP_READ_BITMAP result timeout.
[haiku.git] / src / bin / package / command_list.cpp
blob9670fa5ab8fd9c37d757328e31f87418126afeb8
1 /*
2 * Copyright 2009-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <ctype.h>
8 #include <errno.h>
9 #include <getopt.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <time.h>
15 #include <Entry.h>
16 #include <package/hpkg/PackageContentHandler.h>
17 #include <package/hpkg/PackageEntry.h>
18 #include <package/hpkg/PackageEntryAttribute.h>
19 #include <package/hpkg/PackageInfoAttributeValue.h>
20 #include <package/hpkg/PackageReader.h>
21 #include <package/hpkg/StandardErrorOutput.h>
22 #include <package/hpkg/v1/PackageContentHandler.h>
23 #include <package/hpkg/v1/PackageEntry.h>
24 #include <package/hpkg/v1/PackageEntryAttribute.h>
25 #include <package/hpkg/v1//PackageReader.h>
27 #include <package/PackageInfo.h>
29 #include "package.h"
30 #include "PackageInfoPrinter.h"
33 using namespace BPackageKit;
34 using BPackageKit::BHPKG::BErrorOutput;
35 using BPackageKit::BHPKG::BPackageInfoAttributeValue;
36 using BPackageKit::BHPKG::BStandardErrorOutput;
39 struct VersionPolicyV1 {
40 typedef BPackageKit::BHPKG::V1::BPackageContentHandler
41 PackageContentHandler;
42 typedef BPackageKit::BHPKG::V1::BPackageEntry PackageEntry;
43 typedef BPackageKit::BHPKG::V1::BPackageEntryAttribute
44 PackageEntryAttribute;
45 typedef BPackageKit::BHPKG::V1::BPackageReader PackageReader;
47 static inline uint64 PackageDataSize(
48 const BPackageKit::BHPKG::V1::BPackageData& data)
50 return data.UncompressedSize();
53 static inline status_t InitReader(PackageReader& packageReader,
54 const char* fileName)
56 return packageReader.Init(fileName);
60 struct VersionPolicyV2 {
61 typedef BPackageKit::BHPKG::BPackageContentHandler PackageContentHandler;
62 typedef BPackageKit::BHPKG::BPackageEntry PackageEntry;
63 typedef BPackageKit::BHPKG::BPackageEntryAttribute PackageEntryAttribute;
64 typedef BPackageKit::BHPKG::BPackageReader PackageReader;
66 static inline uint64 PackageDataSize(
67 const BPackageKit::BHPKG::BPackageData& data)
69 return data.Size();
72 static inline status_t InitReader(PackageReader& packageReader,
73 const char* fileName)
75 return packageReader.Init(fileName,
76 BPackageKit::BHPKG
77 ::B_HPKG_READER_DONT_PRINT_VERSION_MISMATCH_MESSAGE);
82 enum ListMode {
83 LIST_ALL,
84 LIST_PATHS_ONLY,
85 LIST_META_INFO_ONLY
89 template<typename VersionPolicy>
90 struct PackageContentListHandler : VersionPolicy::PackageContentHandler {
91 PackageContentListHandler(bool listEntries, bool listAttributes)
93 fPrinter(),
94 fLevel(0),
95 fListEntries(listEntries),
96 fListAttribute(listEntries && listAttributes)
100 virtual status_t HandleEntry(typename VersionPolicy::PackageEntry* entry)
102 if (!fListEntries)
103 return B_OK;
105 fLevel++;
107 int indentation = (fLevel - 1) * 2;
108 printf("%*s", indentation, "");
110 // name and size
111 printf("%-*s", indentation < 32 ? 32 - indentation : 0, entry->Name());
112 printf(" %8llu",
113 (unsigned long long)VersionPolicy::PackageDataSize(entry->Data()));
115 // time
116 struct tm* time = localtime(&entry->ModifiedTime().tv_sec);
117 printf(" %04d-%02d-%02d %02d:%02d:%02d",
118 1900 + time->tm_year, time->tm_mon + 1, time->tm_mday,
119 time->tm_hour, time->tm_min, time->tm_sec);
121 // file type
122 mode_t mode = entry->Mode();
123 if (S_ISREG(mode))
124 printf(" -");
125 else if (S_ISDIR(mode))
126 printf(" d");
127 else if (S_ISLNK(mode))
128 printf(" l");
129 else
130 printf(" ?");
132 // permissions
133 char buffer[4];
134 printf("%s", _PermissionString(buffer, mode >> 6,
135 (mode & S_ISUID) != 0));
136 printf("%s", _PermissionString(buffer, mode >> 3,
137 (mode & S_ISGID) != 0));
138 printf("%s", _PermissionString(buffer, mode, false));
140 // print the symlink path
141 if (S_ISLNK(mode))
142 printf(" -> %s", entry->SymlinkPath());
144 printf("\n");
145 return B_OK;
148 virtual status_t HandleEntryAttribute(
149 typename VersionPolicy::PackageEntry* entry,
150 typename VersionPolicy::PackageEntryAttribute* attribute)
152 if (!fListAttribute)
153 return B_OK;
155 int indentation = fLevel * 2;
156 printf("%*s<", indentation, "");
157 printf("%-*s %8llu", indentation < 31 ? 31 - indentation : 0,
158 attribute->Name(),
159 (unsigned long long)VersionPolicy::PackageDataSize(
160 attribute->Data()));
162 uint32 type = attribute->Type();
163 if (isprint(type & 0xff) && isprint((type >> 8) & 0xff)
164 && isprint((type >> 16) & 0xff) && isprint(type >> 24)) {
165 printf(" '%c%c%c%c'", int(type >> 24), int((type >> 16) & 0xff),
166 int((type >> 8) & 0xff), int(type & 0xff));
167 } else
168 printf(" %#" B_PRIx32, type);
170 printf(">\n");
171 return B_OK;
174 virtual status_t HandleEntryDone(
175 typename VersionPolicy::PackageEntry* entry)
177 if (!fListEntries)
178 return B_OK;
180 fLevel--;
181 return B_OK;
184 virtual status_t HandlePackageAttribute(
185 const BPackageInfoAttributeValue& value)
187 if (value.attributeID == B_PACKAGE_INFO_NAME)
188 printf("package-attributes:\n");
190 if (!fPrinter.PrintAttribute(value)) {
191 printf("*** Invalid package attribute section: unexpected "
192 "package attribute id %d encountered\n", value.attributeID);
193 return B_BAD_DATA;
196 return B_OK;
199 virtual void HandleErrorOccurred()
203 private:
204 static const char* _PermissionString(char* buffer, uint32 mode, bool sticky)
206 buffer[0] = (mode & 0x4) != 0 ? 'r' : '-';
207 buffer[1] = (mode & 0x2) != 0 ? 'w' : '-';
209 if ((mode & 0x1) != 0)
210 buffer[2] = sticky ? 's' : 'x';
211 else
212 buffer[2] = '-';
214 buffer[3] = '\0';
215 return buffer;
218 static void _PrintPackageVersion(const BPackageVersionData& version)
220 printf("%s", BPackageVersion(version).ToString().String());
223 private:
224 PackageInfoPrinter fPrinter;
225 int fLevel;
226 bool fListEntries;
227 bool fListAttribute;
231 template<typename VersionPolicy>
232 struct PackageContentListPathsHandler : VersionPolicy::PackageContentHandler {
233 PackageContentListPathsHandler()
235 fPathComponents()
239 virtual status_t HandleEntry(typename VersionPolicy::PackageEntry* entry)
241 fPathComponents.Add(entry->Name());
242 printf("%s\n", fPathComponents.Join("/").String());
243 return B_OK;
246 virtual status_t HandleEntryAttribute(
247 typename VersionPolicy::PackageEntry* entry,
248 typename VersionPolicy::PackageEntryAttribute* attribute)
250 return B_OK;
253 virtual status_t HandleEntryDone(
254 typename VersionPolicy::PackageEntry* entry)
256 fPathComponents.Remove(fPathComponents.CountStrings() - 1);
257 return B_OK;
260 virtual status_t HandlePackageAttribute(
261 const BPackageInfoAttributeValue& value)
263 return B_OK;
266 virtual void HandleErrorOccurred()
270 private:
271 BStringList fPathComponents;
275 template<typename VersionPolicy>
276 static void
277 do_list(const char* packageFileName, bool listAttributes, ListMode listMode,
278 bool ignoreVersionError)
280 // open package
281 BStandardErrorOutput errorOutput;
282 typename VersionPolicy::PackageReader packageReader(&errorOutput);
283 status_t error = VersionPolicy::InitReader(packageReader, packageFileName);
284 if (error != B_OK) {
285 if (ignoreVersionError && error == B_MISMATCHED_VALUES)
286 return;
287 exit(1);
290 // list
291 switch (listMode) {
292 case LIST_PATHS_ONLY:
294 PackageContentListPathsHandler<VersionPolicy> handler;
295 error = packageReader.ParseContent(&handler);
296 break;
299 case LIST_ALL:
300 case LIST_META_INFO_ONLY:
302 PackageContentListHandler<VersionPolicy> handler(
303 listMode != LIST_META_INFO_ONLY, listAttributes);
304 error = packageReader.ParseContent(&handler);
308 if (error != B_OK)
309 exit(1);
311 exit(0);
316 command_list(int argc, const char* const* argv)
318 ListMode listMode = LIST_ALL;
319 bool listAttributes = false;
321 while (true) {
322 static struct option sLongOptions[] = {
323 { "help", no_argument, 0, 'h' },
324 { 0, 0, 0, 0 }
327 opterr = 0; // don't print errors
328 int c = getopt_long(argc, (char**)argv, "+ahip", sLongOptions, NULL);
329 if (c == -1)
330 break;
332 switch (c) {
333 case 'a':
334 listAttributes = true;
335 break;
337 case 'i':
338 listMode = LIST_META_INFO_ONLY;
339 break;
341 case 'h':
342 print_usage_and_exit(false);
343 break;
345 case 'p':
346 listMode = LIST_PATHS_ONLY;
347 break;
349 default:
350 print_usage_and_exit(true);
351 break;
355 // One argument should remain -- the package file name.
356 if (optind + 1 != argc)
357 print_usage_and_exit(true);
359 const char* packageFileName = argv[optind++];
361 // If the file doesn't look like a package file, try to load it as a
362 // package info file.
363 if (!BString(packageFileName).EndsWith(".hpkg")) {
364 struct ErrorListener : BPackageInfo::ParseErrorListener {
365 virtual void OnError(const BString& msg, int line, int col)
367 fprintf(stderr, "%s:%d:%d: %s\n", fPath, line, col,
368 msg.String());
371 const char* fPath;
372 } errorListener;
373 errorListener.fPath = packageFileName;
375 BPackageInfo info;
376 if (info.ReadFromConfigFile(BEntry(packageFileName), &errorListener)
377 != B_OK) {
378 return 1;
381 printf("package-attributes:\n");
382 PackageInfoPrinter().PrintPackageInfo(info);
383 return 0;
386 BHPKG::BStandardErrorOutput errorOutput;
388 // current package file format version
389 do_list<VersionPolicyV2>(packageFileName, listAttributes, listMode, true);
390 do_list<VersionPolicyV1>(packageFileName, listAttributes, listMode, false);
392 return 0;