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