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", 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(), attribute->Data().UncompressedSize()); 93 94 uint32 type = attribute->Type(); 95 if (isprint(type & 0xff) && isprint((type >> 8) & 0xff) 96 && isprint((type >> 16) & 0xff) && isprint(type >> 24)) { 97 printf(" '%c%c%c%c'", int(type >> 24), int((type >> 16) & 0xff), 98 int((type >> 8) & 0xff), int(type & 0xff)); 99 } else 100 printf(" %#" B_PRIx32, type); 101 102 printf(">\n"); 103 return B_OK; 104 } 105 106 virtual status_t HandleEntryDone(BPackageEntry* entry) 107 { 108 fLevel--; 109 return B_OK; 110 } 111 112 virtual status_t HandlePackageAttribute( 113 const BPackageInfoAttributeValue& value) 114 { 115 switch (value.attributeID) { 116 case B_PACKAGE_INFO_NAME: 117 printf("package-attributes:\n"); 118 printf("\tname: %s\n", value.string); 119 break; 120 121 case B_PACKAGE_INFO_SUMMARY: 122 printf("\tsummary: %s\n", value.string); 123 break; 124 125 case B_PACKAGE_INFO_DESCRIPTION: 126 printf("\tdescription: %s\n", value.string); 127 break; 128 129 case B_PACKAGE_INFO_VENDOR: 130 printf("\tvendor: %s\n", value.string); 131 break; 132 133 case B_PACKAGE_INFO_PACKAGER: 134 printf("\tpackager: %s\n", value.string); 135 break; 136 137 case B_PACKAGE_INFO_FLAGS: 138 if (value.unsignedInt == 0) 139 break; 140 printf("\tflags:\n"); 141 if ((value.unsignedInt & B_PACKAGE_FLAG_APPROVE_LICENSE) != 0) 142 printf("\t\tapprove_license\n"); 143 if ((value.unsignedInt & B_PACKAGE_FLAG_SYSTEM_PACKAGE) != 0) 144 printf("\t\tsystem_package\n"); 145 break; 146 147 case B_PACKAGE_INFO_ARCHITECTURE: 148 printf("\tarchitecture: %s\n", 149 BPackageInfo::kArchitectureNames[value.unsignedInt]); 150 break; 151 152 case B_PACKAGE_INFO_VERSION: 153 _PrintPackageVersion(value.version); 154 break; 155 156 case B_PACKAGE_INFO_COPYRIGHTS: 157 printf("\tcopyright: %s\n", value.string); 158 break; 159 160 case B_PACKAGE_INFO_LICENSES: 161 printf("\tlicense: %s\n", value.string); 162 break; 163 164 case B_PACKAGE_INFO_PROVIDES: 165 printf("\tprovides: %s", value.resolvable.name); 166 if (value.resolvable.haveVersion) { 167 printf(" = "); 168 _PrintPackageVersion(value.resolvable.version); 169 } 170 printf("\n"); 171 break; 172 173 case B_PACKAGE_INFO_REQUIRES: 174 printf("\trequires: %s", value.resolvableExpression.name); 175 if (value.resolvableExpression.haveOpAndVersion) { 176 printf(" %s ", BPackageResolvableExpression::kOperatorNames[ 177 value.resolvableExpression.op]); 178 _PrintPackageVersion(value.resolvableExpression.version); 179 } 180 printf("\n"); 181 break; 182 183 case B_PACKAGE_INFO_SUPPLEMENTS: 184 printf("\tsupplements: %s", value.resolvableExpression.name); 185 if (value.resolvableExpression.haveOpAndVersion) { 186 printf(" %s ", BPackageResolvableExpression::kOperatorNames[ 187 value.resolvableExpression.op]); 188 _PrintPackageVersion(value.resolvableExpression.version); 189 } 190 printf("\n"); 191 break; 192 193 case B_PACKAGE_INFO_CONFLICTS: 194 printf("\tconflicts: %s", value.resolvableExpression.name); 195 if (value.resolvableExpression.haveOpAndVersion) { 196 printf(" %s ", BPackageResolvableExpression::kOperatorNames[ 197 value.resolvableExpression.op]); 198 _PrintPackageVersion(value.resolvableExpression.version); 199 } 200 printf("\n"); 201 break; 202 203 case B_PACKAGE_INFO_FRESHENS: 204 printf("\tfreshens: %s", value.resolvableExpression.name); 205 if (value.resolvableExpression.haveOpAndVersion) { 206 printf(" %s ", BPackageResolvableExpression::kOperatorNames[ 207 value.resolvableExpression.op]); 208 _PrintPackageVersion(value.resolvableExpression.version); 209 } 210 printf("\n"); 211 break; 212 213 case B_PACKAGE_INFO_REPLACES: 214 printf("\treplaces: %s\n", value.string); 215 break; 216 217 default: 218 printf( 219 "*** Invalid package attribute section: unexpected " 220 "package attribute id %d encountered\n", value.attributeID); 221 return B_BAD_DATA; 222 } 223 224 return B_OK; 225 } 226 227 virtual void HandleErrorOccurred() 228 { 229 } 230 231 private: 232 static const char* _PermissionString(char* buffer, uint32 mode, bool sticky) 233 { 234 buffer[0] = (mode & 0x4) != 0 ? 'r' : '-'; 235 buffer[1] = (mode & 0x2) != 0 ? 'w' : '-'; 236 237 if ((mode & 0x1) != 0) 238 buffer[2] = sticky ? 's' : 'x'; 239 else 240 buffer[2] = '-'; 241 242 buffer[3] = '\0'; 243 return buffer; 244 } 245 246 static void _PrintPackageVersion(const BPackageVersionData& version) 247 { 248 printf("%s", version.major); 249 if (version.minor != NULL && version.minor[0] != '\0') 250 printf(".%s", version.minor); 251 if (version.micro != NULL && version.micro[0] != '\0') 252 printf(".%s", version.micro); 253 if (version.release > 0) 254 printf("-%d", version.release); 255 } 256 257 private: 258 int fLevel; 259 bool fListAttribute; 260 }; 261 262 263 int 264 command_list(int argc, const char* const* argv) 265 { 266 bool listAttributes = false; 267 268 while (true) { 269 static struct option sLongOptions[] = { 270 { "help", no_argument, 0, 'h' }, 271 { 0, 0, 0, 0 } 272 }; 273 274 opterr = 0; // don't print errors 275 int c = getopt_long(argc, (char**)argv, "+ha", sLongOptions, NULL); 276 if (c == -1) 277 break; 278 279 switch (c) { 280 case 'a': 281 listAttributes = true; 282 break; 283 284 case 'h': 285 print_usage_and_exit(false); 286 break; 287 288 default: 289 print_usage_and_exit(true); 290 break; 291 } 292 } 293 294 // One argument should remain -- the package file name. 295 if (optind + 1 != argc) 296 print_usage_and_exit(true); 297 298 const char* packageFileName = argv[optind++]; 299 300 // open package 301 StandardErrorOutput errorOutput; 302 BPackageReader packageReader(&errorOutput); 303 status_t error = packageReader.Init(packageFileName); 304 if (error != B_OK) 305 return 1; 306 307 // list 308 PackageContentListHandler handler(listAttributes); 309 error = packageReader.ParseContent(&handler); 310 if (error != B_OK) 311 return 1; 312 313 return 0; 314 } 315