1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 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 14 #include <package/hpkg/HPKGDefs.h> 15 #include <package/hpkg/PackageAttributeValue.h> 16 #include <package/hpkg/PackageContentHandler.h> 17 #include <package/hpkg/PackageEntry.h> 18 #include <package/hpkg/PackageEntryAttribute.h> 19 #include <package/hpkg/PackageReader.h> 20 21 #include "package.h" 22 #include "StandardErrorOutput.h" 23 24 25 using namespace BPackageKit::BHPKG; 26 27 28 struct PackageContentDumpHandler : BLowLevelPackageContentHandler { 29 PackageContentDumpHandler() 30 : 31 fLevel(0), 32 fErrorOccurred(false), 33 fHasChildren(false) 34 { 35 } 36 37 virtual status_t HandleAttribute(BHPKGAttributeID attributeID, 38 const BPackageAttributeValue& value, void* parentToken, void*& _token) 39 { 40 if (fErrorOccurred) 41 return B_OK; 42 43 printf("%*s>%s: ", fLevel * 2, "", AttributeNameForID(attributeID)); 44 _PrintValue(value); 45 printf("\n"); 46 47 fHasChildren = false; 48 fLevel++; 49 return B_OK; 50 } 51 52 virtual status_t HandleAttributeDone(BHPKGAttributeID attributeID, 53 const BPackageAttributeValue& value, void* token) 54 { 55 if (fErrorOccurred) 56 return B_OK; 57 58 fLevel--; 59 60 if (fHasChildren) 61 printf("%*s<%s\n", fLevel * 2, "", AttributeNameForID(attributeID)); 62 63 fHasChildren = true; 64 return B_OK; 65 } 66 67 virtual void HandleErrorOccurred() 68 { 69 fErrorOccurred = true; 70 } 71 72 private: 73 void _PrintValue(const BPackageAttributeValue& value) 74 { 75 switch (value.type) { 76 case B_HPKG_ATTRIBUTE_TYPE_INT: 77 printf("%lld (%#llx)", value.signedInt, value.signedInt); 78 break; 79 case B_HPKG_ATTRIBUTE_TYPE_UINT: 80 printf("%llu (%#llx)", value.unsignedInt, value.unsignedInt); 81 break; 82 case B_HPKG_ATTRIBUTE_TYPE_STRING: 83 printf("\"%s\"", value.string); 84 break; 85 case B_HPKG_ATTRIBUTE_TYPE_RAW: 86 switch (value.encoding) { 87 case B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE: 88 printf("data: size: %llu, inline", value.data.size); 89 // TODO: Print the data bytes! 90 break; 91 case B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP: 92 printf("data: size: %llu, offset: %llu", 93 value.data.size, value.data.offset); 94 break; 95 default: 96 break; 97 } 98 break; 99 default: 100 printf("<unknown type %u>\n", value.type); 101 break; 102 } 103 } 104 105 private: 106 int fLevel; 107 bool fErrorOccurred; 108 bool fHasChildren; 109 }; 110 111 112 int 113 command_dump(int argc, const char* const* argv) 114 { 115 while (true) { 116 static struct option sLongOptions[] = { 117 { "help", no_argument, 0, 'h' }, 118 { 0, 0, 0, 0 } 119 }; 120 121 opterr = 0; // don't print errors 122 int c = getopt_long(argc, (char**)argv, "+h", sLongOptions, NULL); 123 if (c == -1) 124 break; 125 126 switch (c) { 127 case 'h': 128 print_usage_and_exit(false); 129 break; 130 131 default: 132 print_usage_and_exit(true); 133 break; 134 } 135 } 136 137 // One argument should remain -- the package file name. 138 if (optind + 1 != argc) 139 print_usage_and_exit(true); 140 141 const char* packageFileName = argv[optind++]; 142 143 // open package 144 StandardErrorOutput errorOutput; 145 BPackageReader packageReader(&errorOutput); 146 status_t error = packageReader.Init(packageFileName); 147 if (error != B_OK) 148 return 1; 149 150 // list 151 PackageContentDumpHandler handler; 152 error = packageReader.ParseContent(&handler); 153 if (error != B_OK) 154 return 1; 155 156 return 0; 157 } 158