2 * Copyright 2009-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
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>
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
,
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
)
72 static inline status_t
InitReader(PackageReader
& packageReader
,
75 return packageReader
.Init(fileName
,
77 ::B_HPKG_READER_DONT_PRINT_VERSION_MISMATCH_MESSAGE
);
89 template<typename VersionPolicy
>
90 struct PackageContentListHandler
: VersionPolicy::PackageContentHandler
{
91 PackageContentListHandler(bool listEntries
, bool listAttributes
)
95 fListEntries(listEntries
),
96 fListAttribute(listEntries
&& listAttributes
)
100 virtual status_t
HandleEntry(typename
VersionPolicy::PackageEntry
* entry
)
107 int indentation
= (fLevel
- 1) * 2;
108 printf("%*s", indentation
, "");
111 printf("%-*s", indentation
< 32 ? 32 - indentation
: 0, entry
->Name());
113 (unsigned long long)VersionPolicy::PackageDataSize(entry
->Data()));
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
);
122 mode_t mode
= entry
->Mode();
125 else if (S_ISDIR(mode
))
127 else if (S_ISLNK(mode
))
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
142 printf(" -> %s", entry
->SymlinkPath());
148 virtual status_t
HandleEntryAttribute(
149 typename
VersionPolicy::PackageEntry
* entry
,
150 typename
VersionPolicy::PackageEntryAttribute
* attribute
)
155 int indentation
= fLevel
* 2;
156 printf("%*s<", indentation
, "");
157 printf("%-*s %8llu", indentation
< 31 ? 31 - indentation
: 0,
159 (unsigned long long)VersionPolicy::PackageDataSize(
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));
168 printf(" %#" B_PRIx32
, type
);
174 virtual status_t
HandleEntryDone(
175 typename
VersionPolicy::PackageEntry
* entry
)
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
);
199 virtual void HandleErrorOccurred()
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';
218 static void _PrintPackageVersion(const BPackageVersionData
& version
)
220 printf("%s", BPackageVersion(version
).ToString().String());
224 PackageInfoPrinter fPrinter
;
231 template<typename VersionPolicy
>
232 struct PackageContentListPathsHandler
: VersionPolicy::PackageContentHandler
{
233 PackageContentListPathsHandler()
239 virtual status_t
HandleEntry(typename
VersionPolicy::PackageEntry
* entry
)
241 fPathComponents
.Add(entry
->Name());
242 printf("%s\n", fPathComponents
.Join("/").String());
246 virtual status_t
HandleEntryAttribute(
247 typename
VersionPolicy::PackageEntry
* entry
,
248 typename
VersionPolicy::PackageEntryAttribute
* attribute
)
253 virtual status_t
HandleEntryDone(
254 typename
VersionPolicy::PackageEntry
* entry
)
256 fPathComponents
.Remove(fPathComponents
.CountStrings() - 1);
260 virtual status_t
HandlePackageAttribute(
261 const BPackageInfoAttributeValue
& value
)
266 virtual void HandleErrorOccurred()
271 BStringList fPathComponents
;
275 template<typename VersionPolicy
>
277 do_list(const char* packageFileName
, bool listAttributes
, ListMode listMode
,
278 bool ignoreVersionError
)
281 BStandardErrorOutput errorOutput
;
282 typename
VersionPolicy::PackageReader
packageReader(&errorOutput
);
283 status_t error
= VersionPolicy::InitReader(packageReader
, packageFileName
);
285 if (ignoreVersionError
&& error
== B_MISMATCHED_VALUES
)
292 case LIST_PATHS_ONLY
:
294 PackageContentListPathsHandler
<VersionPolicy
> handler
;
295 error
= packageReader
.ParseContent(&handler
);
300 case LIST_META_INFO_ONLY
:
302 PackageContentListHandler
<VersionPolicy
> handler(
303 listMode
!= LIST_META_INFO_ONLY
, listAttributes
);
304 error
= packageReader
.ParseContent(&handler
);
316 command_list(int argc
, const char* const* argv
)
318 ListMode listMode
= LIST_ALL
;
319 bool listAttributes
= false;
322 static struct option sLongOptions
[] = {
323 { "help", no_argument
, 0, 'h' },
327 opterr
= 0; // don't print errors
328 int c
= getopt_long(argc
, (char**)argv
, "+ahip", sLongOptions
, NULL
);
334 listAttributes
= true;
338 listMode
= LIST_META_INFO_ONLY
;
342 print_usage_and_exit(false);
346 listMode
= LIST_PATHS_ONLY
;
350 print_usage_and_exit(true);
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
,
373 errorListener
.fPath
= packageFileName
;
376 if (info
.ReadFromConfigFile(BEntry(packageFileName
), &errorListener
)
381 printf("package-attributes:\n");
382 PackageInfoPrinter().PrintPackageInfo(info
);
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);