1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "package.h" 8 9 #include <ctype.h> 10 #include <errno.h> 11 #include <getopt.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 16 #include "package.h" 17 #include "PackageEntry.h" 18 #include "PackageEntryAttribute.h" 19 #include "PackageReader.h" 20 #include "StandardErrorOutput.h" 21 22 23 struct PackageContentListHandler : PackageContentHandler { 24 PackageContentListHandler(bool listAttributes) 25 : 26 fLevel(0), 27 fListAttribute(listAttributes) 28 { 29 } 30 31 virtual status_t HandleEntry(PackageEntry* entry) 32 { 33 fLevel++; 34 35 int indentation = (fLevel - 1) * 2; 36 printf("%*s", indentation, ""); 37 38 // name and size 39 printf("%-*s", indentation < 32 ? 32 - indentation : 0, entry->Name()); 40 printf(" %8llu", entry->Data().UncompressedSize()); 41 42 // time 43 struct tm* time = localtime(&entry->ModifiedTime().tv_sec); 44 printf(" %04d-%02d-%02d %02d:%02d:%02d", 45 1900 + time->tm_year, time->tm_mon + 1, time->tm_mday, 46 time->tm_hour, time->tm_min, time->tm_sec); 47 48 // file type 49 mode_t mode = entry->Mode(); 50 if (S_ISREG(mode)) 51 printf(" -"); 52 else if (S_ISDIR(mode)) 53 printf(" d"); 54 else if (S_ISLNK(mode)) 55 printf(" l"); 56 else 57 printf(" ?"); 58 59 // permissions 60 char buffer[4]; 61 printf("%s", _PermissionString(buffer, mode >> 6, 62 (mode & S_ISUID) != 0)); 63 printf("%s", _PermissionString(buffer, mode >> 3, 64 (mode & S_ISGID) != 0)); 65 printf("%s", _PermissionString(buffer, mode, false)); 66 67 // print the symlink path 68 if (S_ISLNK(mode)) 69 printf(" -> %s", entry->SymlinkPath()); 70 71 printf("\n"); 72 return B_OK; 73 } 74 75 virtual status_t HandleEntryAttribute(PackageEntry* entry, 76 PackageEntryAttribute* attribute) 77 { 78 if (!fListAttribute) 79 return B_OK; 80 81 int indentation = fLevel * 2; 82 printf("%*s<", indentation, ""); 83 printf("%-*s %8llu", indentation < 31 ? 31 - indentation : 0, 84 attribute->Name(), attribute->Data().UncompressedSize()); 85 86 uint32 type = attribute->Type(); 87 if (isprint(type & 0xff) && isprint((type >> 8) & 0xff) 88 && isprint((type >> 16) & 0xff) && isprint(type >> 24)) { 89 printf(" '%c%c%c%c'", int(type >> 24), int((type >> 16) & 0xff), 90 int((type >> 8) & 0xff), int(type & 0xff)); 91 } else 92 printf(" %#lx", type); 93 94 printf(">\n"); 95 return B_OK; 96 } 97 98 virtual status_t HandleEntryDone(PackageEntry* entry) 99 { 100 fLevel--; 101 return B_OK; 102 } 103 104 virtual void HandleErrorOccurred() 105 { 106 } 107 108 private: 109 static const char* _PermissionString(char* buffer, uint32 mode, bool sticky) 110 { 111 buffer[0] = (mode & 0x4) != 0 ? 'r' : '-'; 112 buffer[1] = (mode & 0x2) != 0 ? 'w' : '-'; 113 114 if ((mode & 0x1) != 0) 115 buffer[2] = sticky ? 's' : 'x'; 116 else 117 buffer[2] = '-'; 118 119 buffer[3] = '\0'; 120 return buffer; 121 } 122 123 private: 124 int fLevel; 125 bool fListAttribute; 126 }; 127 128 129 int 130 command_list(int argc, const char* const* argv) 131 { 132 bool listAttributes = false; 133 134 while (true) { 135 static struct option sLongOptions[] = { 136 { "help", no_argument, 0, 'h' }, 137 { 0, 0, 0, 0 } 138 }; 139 140 opterr = 0; // don't print errors 141 int c = getopt_long(argc, (char**)argv, "+ha", sLongOptions, NULL); 142 if (c == -1) 143 break; 144 145 switch (c) { 146 case 'a': 147 listAttributes = true; 148 break; 149 150 case 'h': 151 print_usage_and_exit(false); 152 break; 153 154 default: 155 print_usage_and_exit(true); 156 break; 157 } 158 } 159 160 // One argument should remain -- the package file name. 161 if (optind + 1 != argc) 162 print_usage_and_exit(true); 163 164 const char* packageFileName = argv[optind++]; 165 166 // open package 167 StandardErrorOutput errorOutput; 168 PackageReader packageReader(&errorOutput); 169 status_t error = packageReader.Init(packageFileName); 170 printf("Init(): %s\n", strerror(error)); 171 if (error != B_OK) 172 return 1; 173 174 // list 175 PackageContentListHandler handler(listAttributes); 176 error = packageReader.ParseContent(&handler); 177 printf("ParseContent(): %s\n", strerror(error)); 178 if (error != B_OK) 179 return 1; 180 181 return 0; 182 } 183