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/PackageContentHandler.h> 15 #include <package/hpkg/PackageEntry.h> 16 #include <package/hpkg/PackageEntryAttribute.h> 17 #include <package/hpkg/PackageInfoAttributeValue.h> 18 #include <package/hpkg/PackageReader.h> 19 20 #include <package/PackageInfo.h> 21 22 #include "package.h" 23 #include "StandardErrorOutput.h" 24 25 26 using namespace BPackageKit::BHPKG; 27 using namespace BPackageKit; 28 29 30 struct PackageContentListHandler : BPackageContentHandler { 31 PackageContentListHandler(bool listAttributes) 32 : 33 fLevel(0), 34 fListAttribute(listAttributes) 35 { 36 } 37 38 virtual status_t HandleEntry(BPackageEntry* entry) 39 { 40 fLevel++; 41 42 int indentation = (fLevel - 1) * 2; 43 printf("%*s", indentation, ""); 44 45 // name and size 46 printf("%-*s", indentation < 32 ? 32 - indentation : 0, entry->Name()); 47 printf(" %8llu", entry->Data().UncompressedSize()); 48 49 // time 50 struct tm* time = localtime(&entry->ModifiedTime().tv_sec); 51 printf(" %04d-%02d-%02d %02d:%02d:%02d", 52 1900 + time->tm_year, time->tm_mon + 1, time->tm_mday, 53 time->tm_hour, time->tm_min, time->tm_sec); 54 55 // file type 56 mode_t mode = entry->Mode(); 57 if (S_ISREG(mode)) 58 printf(" -"); 59 else if (S_ISDIR(mode)) 60 printf(" d"); 61 else if (S_ISLNK(mode)) 62 printf(" l"); 63 else 64 printf(" ?"); 65 66 // permissions 67 char buffer[4]; 68 printf("%s", _PermissionString(buffer, mode >> 6, 69 (mode & S_ISUID) != 0)); 70 printf("%s", _PermissionString(buffer, mode >> 3, 71 (mode & S_ISGID) != 0)); 72 printf("%s", _PermissionString(buffer, mode, false)); 73 74 // print the symlink path 75 if (S_ISLNK(mode)) 76 printf(" -> %s", entry->SymlinkPath()); 77 78 printf("\n"); 79 return B_OK; 80 } 81 82 virtual status_t HandleEntryAttribute(BPackageEntry* entry, 83 BPackageEntryAttribute* attribute) 84 { 85 if (!fListAttribute) 86 return B_OK; 87 88 int indentation = fLevel * 2; 89 printf("%*s<", indentation, ""); 90 printf("%-*s %8llu", indentation < 31 ? 31 - indentation : 0, 91 attribute->Name(), attribute->Data().UncompressedSize()); 92 93 uint32 type = attribute->Type(); 94 if (isprint(type & 0xff) && isprint((type >> 8) & 0xff) 95 && isprint((type >> 16) & 0xff) && isprint(type >> 24)) { 96 printf(" '%c%c%c%c'", int(type >> 24), int((type >> 16) & 0xff), 97 int((type >> 8) & 0xff), int(type & 0xff)); 98 } else 99 printf(" %#lx", type); 100 101 printf(">\n"); 102 return B_OK; 103 } 104 105 virtual status_t HandleEntryDone(BPackageEntry* entry) 106 { 107 fLevel--; 108 return B_OK; 109 } 110 111 virtual status_t HandlePackageAttribute( 112 const BPackageInfoAttributeValue& value) 113 { 114 switch (value.attributeIndex) { 115 case B_PACKAGE_INFO_NAME: 116 printf("package-attributes:\n"); 117 printf("\tname: %s\n", value.string); 118 break; 119 120 case B_PACKAGE_INFO_SUMMARY: 121 printf("\tsummary: %s\n", value.string); 122 break; 123 124 case B_PACKAGE_INFO_DESCRIPTION: 125 printf("\tdescription: %s\n", value.string); 126 break; 127 128 case B_PACKAGE_INFO_VENDOR: 129 printf("\tvendor: %s\n", value.string); 130 break; 131 132 case B_PACKAGE_INFO_PACKAGER: 133 printf("\tpackager: %s\n", value.string); 134 break; 135 136 case B_PACKAGE_INFO_ARCHITECTURE: 137 printf("\tarchitecure: %s\n", 138 BPackageInfo::kArchitectureNames[value.unsignedInt]); 139 break; 140 141 case B_PACKAGE_INFO_VERSION: 142 printf("\tversion: %s.%s.%s-%d\n", value.version.major, 143 value.version.minor, value.version.micro, 144 value.version.release); 145 break; 146 147 case B_PACKAGE_INFO_COPYRIGHTS: 148 printf("\tcopyright: %s\n", value.string); 149 break; 150 151 case B_PACKAGE_INFO_LICENSES: 152 printf("\tlicense: %s\n", value.string); 153 break; 154 155 case B_PACKAGE_INFO_PROVIDES: 156 printf("\tprovides: %s", value.resolvable.name); 157 if (value.resolvable.haveVersion) { 158 printf(" = "); 159 _PrintPackageVersion(value.resolvable.version); 160 } 161 printf("\n"); 162 break; 163 164 case B_PACKAGE_INFO_REQUIRES: 165 printf("\trequires: %s", value.resolvableExpression.name); 166 if (value.resolvableExpression.haveOpAndVersion) { 167 printf(" %s ", BPackageResolvableExpression::kOperatorNames[ 168 value.resolvableExpression.op]); 169 _PrintPackageVersion(value.resolvableExpression.version); 170 } 171 printf("\n"); 172 break; 173 174 case B_PACKAGE_INFO_SUPPLEMENTS: 175 printf("\tsupplements: %s", value.resolvableExpression.name); 176 if (value.resolvableExpression.haveOpAndVersion) { 177 printf(" %s ", BPackageResolvableExpression::kOperatorNames[ 178 value.resolvableExpression.op]); 179 _PrintPackageVersion(value.resolvableExpression.version); 180 } 181 printf("\n"); 182 break; 183 184 case B_PACKAGE_INFO_CONFLICTS: 185 printf("\tconflicts: %s", value.resolvableExpression.name); 186 if (value.resolvableExpression.haveOpAndVersion) { 187 printf(" %s ", BPackageResolvableExpression::kOperatorNames[ 188 value.resolvableExpression.op]); 189 _PrintPackageVersion(value.resolvableExpression.version); 190 } 191 printf("\n"); 192 break; 193 194 case B_PACKAGE_INFO_FRESHENS: 195 printf("\tfreshens: %s", value.resolvableExpression.name); 196 if (value.resolvableExpression.haveOpAndVersion) { 197 printf(" %s ", BPackageResolvableExpression::kOperatorNames[ 198 value.resolvableExpression.op]); 199 _PrintPackageVersion(value.resolvableExpression.version); 200 } 201 printf("\n"); 202 break; 203 204 case B_PACKAGE_INFO_REPLACES: 205 printf("\treplaces: %s\n", value.string); 206 break; 207 208 default: 209 printf( 210 "*** Invalid package attribute section: unexpected " 211 "package attribute index %d encountered\n", 212 value.attributeIndex); 213 return B_BAD_DATA; 214 } 215 216 return B_OK; 217 } 218 219 virtual void HandleErrorOccurred() 220 { 221 } 222 223 private: 224 static const char* _PermissionString(char* buffer, uint32 mode, bool sticky) 225 { 226 buffer[0] = (mode & 0x4) != 0 ? 'r' : '-'; 227 buffer[1] = (mode & 0x2) != 0 ? 'w' : '-'; 228 229 if ((mode & 0x1) != 0) 230 buffer[2] = sticky ? 's' : 'x'; 231 else 232 buffer[2] = '-'; 233 234 buffer[3] = '\0'; 235 return buffer; 236 } 237 238 static void _PrintPackageVersion(const BPackageVersionData& version) 239 { 240 printf("%s", version.major); 241 if (version.minor != NULL && version.minor[0] != '\0') 242 printf(".%s", version.minor); 243 if (version.micro != NULL && version.micro[0] != '\0') 244 printf(".%s", version.micro); 245 if (version.release > 0) 246 printf("-%d", version.release); 247 } 248 249 private: 250 int fLevel; 251 bool fListAttribute; 252 }; 253 254 255 int 256 command_list(int argc, const char* const* argv) 257 { 258 bool listAttributes = false; 259 260 while (true) { 261 static struct option sLongOptions[] = { 262 { "help", no_argument, 0, 'h' }, 263 { 0, 0, 0, 0 } 264 }; 265 266 opterr = 0; // don't print errors 267 int c = getopt_long(argc, (char**)argv, "+ha", sLongOptions, NULL); 268 if (c == -1) 269 break; 270 271 switch (c) { 272 case 'a': 273 listAttributes = true; 274 break; 275 276 case 'h': 277 print_usage_and_exit(false); 278 break; 279 280 default: 281 print_usage_and_exit(true); 282 break; 283 } 284 } 285 286 // One argument should remain -- the package file name. 287 if (optind + 1 != argc) 288 print_usage_and_exit(true); 289 290 const char* packageFileName = argv[optind++]; 291 292 // open package 293 StandardErrorOutput errorOutput; 294 BPackageReader packageReader(&errorOutput); 295 status_t error = packageReader.Init(packageFileName); 296 printf("Init(): %s\n", strerror(error)); 297 if (error != B_OK) 298 return 1; 299 300 // list 301 PackageContentListHandler handler(listAttributes); 302 error = packageReader.ParseContent(&handler); 303 printf("ParseContent(): %s\n", strerror(error)); 304 if (error != B_OK) 305 return 1; 306 307 return 0; 308 } 309