1 /* 2 * Copyright 2009-2013, 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 #include <package/hpkg/StandardErrorOutput.h> 21 22 #include "package.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 HandleSectionStart(BHPKGPackageSectionID sectionID, 38 bool& _handleSection) 39 { 40 const char* sectionName; 41 42 switch (sectionID) { 43 case B_HPKG_SECTION_HEADER: 44 sectionName = "header"; 45 break; 46 case B_HPKG_SECTION_HEAP: 47 sectionName = "heap"; 48 break; 49 case B_HPKG_SECTION_PACKAGE_TOC: 50 sectionName = "TOC"; 51 break; 52 case B_HPKG_SECTION_PACKAGE_ATTRIBUTES: 53 sectionName = "package attributes"; 54 break; 55 case B_HPKG_SECTION_REPOSITORY_INFO: 56 sectionName = "repository info"; 57 break; 58 default: 59 sectionName = "<unknown section>"; 60 break; 61 } 62 63 printf("\n==== SECTION: %s ====\n", sectionName); 64 65 _handleSection = true; 66 return B_OK; 67 } 68 69 virtual status_t HandleSectionEnd(BHPKGPackageSectionID sectionID) 70 { 71 return B_OK; 72 } 73 74 virtual status_t HandleAttribute(BHPKGAttributeID attributeID, 75 const BPackageAttributeValue& value, void* parentToken, void*& _token) 76 { 77 if (fErrorOccurred) 78 return B_OK; 79 80 printf("%*s>%s: ", fLevel * 2, "", AttributeNameForID(attributeID)); 81 _PrintValue(value); 82 printf("\n"); 83 84 fHasChildren = false; 85 fLevel++; 86 return B_OK; 87 } 88 89 virtual status_t HandleAttributeDone(BHPKGAttributeID attributeID, 90 const BPackageAttributeValue& value, void* parentToken, void* token) 91 { 92 if (fErrorOccurred) 93 return B_OK; 94 95 fLevel--; 96 97 if (fHasChildren) 98 printf("%*s<%s\n", fLevel * 2, "", AttributeNameForID(attributeID)); 99 100 fHasChildren = true; 101 return B_OK; 102 } 103 104 virtual void HandleErrorOccurred() 105 { 106 fErrorOccurred = true; 107 } 108 109 private: 110 void _PrintValue(const BPackageAttributeValue& value) 111 { 112 switch (value.type) { 113 case B_HPKG_ATTRIBUTE_TYPE_INT: 114 printf("%lld (%#llx)", (long long)value.signedInt, 115 (long long)value.signedInt); 116 break; 117 case B_HPKG_ATTRIBUTE_TYPE_UINT: 118 printf("%llu (%#llx)", (unsigned long long)value.unsignedInt, 119 (unsigned long long)value.unsignedInt); 120 break; 121 case B_HPKG_ATTRIBUTE_TYPE_STRING: 122 printf("\"%s\"", value.string); 123 break; 124 case B_HPKG_ATTRIBUTE_TYPE_RAW: 125 switch (value.encoding) { 126 case B_HPKG_ATTRIBUTE_ENCODING_RAW_INLINE: 127 printf("data: size: %llu, inline", 128 (unsigned long long)value.data.size); 129 // TODO: Print the data bytes! 130 break; 131 case B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP: 132 printf("data: size: %llu, offset: %llu", 133 (unsigned long long)value.data.size, 134 (unsigned long long)value.data.offset); 135 break; 136 default: 137 break; 138 } 139 break; 140 default: 141 printf("<unknown type %u>\n", value.type); 142 break; 143 } 144 } 145 146 private: 147 int fLevel; 148 bool fErrorOccurred; 149 bool fHasChildren; 150 }; 151 152 153 int 154 command_dump(int argc, const char* const* argv) 155 { 156 while (true) { 157 static struct option sLongOptions[] = { 158 { "help", no_argument, 0, 'h' }, 159 { 0, 0, 0, 0 } 160 }; 161 162 opterr = 0; // don't print errors 163 int c = getopt_long(argc, (char**)argv, "+h", sLongOptions, NULL); 164 if (c == -1) 165 break; 166 167 switch (c) { 168 case 'h': 169 print_usage_and_exit(false); 170 break; 171 172 default: 173 print_usage_and_exit(true); 174 break; 175 } 176 } 177 178 // One argument should remain -- the package file name. 179 if (optind + 1 != argc) 180 print_usage_and_exit(true); 181 182 const char* packageFileName = argv[optind++]; 183 184 // open package 185 BStandardErrorOutput errorOutput; 186 BPackageReader packageReader(&errorOutput); 187 status_t error = packageReader.Init(packageFileName); 188 if (error != B_OK) 189 return 1; 190 191 // list 192 PackageContentDumpHandler handler; 193 error = packageReader.ParseContent(&handler); 194 if (error != B_OK) 195 return 1; 196 197 return 0; 198 } 199