| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library reader; | |
| 6 | |
| 7 import 'input_stream.dart'; | |
| 8 import 'options.dart'; | |
| 9 import 'read_request.dart'; | |
| 10 import 'utils.dart'; | |
| 11 | |
| 12 /** | |
| 13 * A class for extracting and decompressing an archive. | |
| 14 * | |
| 15 * Each instance of this class represents a specific set of options for | |
| 16 * extracting an archive. These options can be used to create multiple input | |
| 17 * streams using the [reader.ArchiveReader.openFilename] and | |
| 18 * [reader.ArchiveReader.openMemory] methods. | |
| 19 * | |
| 20 * Before opening an archive, this needs to be configured. [filter] should be | |
| 21 * used to enable specific decompression algorithms, and [format] should be used | |
| 22 * to enable specific archive formats. | |
| 23 */ | |
| 24 class ArchiveReader { | |
| 25 /** | |
| 26 * The configuration for the filter(s) to use when decompressing the contents | |
| 27 * of an archive. The precise compression used is auto-detected from among all | |
| 28 * enabled options. | |
| 29 */ | |
| 30 final Filter filter; | |
| 31 | |
| 32 /** | |
| 33 * The configuration for the archive format(s) to look for when extracting the | |
| 34 * contents of an archive. The format used is auto-detected from among all | |
| 35 * enabled options. | |
| 36 */ | |
| 37 final Format format; | |
| 38 | |
| 39 /** | |
| 40 * Options for both [filter] and [format]. See [the libarchive | |
| 41 * documentation][wiki] for a list of available options. | |
| 42 * | |
| 43 * [wiki]: https://github.com/libarchive/libarchive/wiki/ManPageArchiveReadSet
Options3 | |
| 44 */ | |
| 45 final ArchiveOptions options; | |
| 46 | |
| 47 /** Creates a new, unconfigured archive reader. */ | |
| 48 ArchiveReader() : filter = new Filter._(), | |
| 49 format = new Format._(), | |
| 50 options = new ArchiveOptions(); | |
| 51 | |
| 52 /** | |
| 53 * Begins extracting from [file]. | |
| 54 * | |
| 55 * [block_size] only needs to be specified for reading from devices that | |
| 56 * require strict I/O blocking. | |
| 57 */ | |
| 58 Future<ArchiveInputStream> openFilename(String file, [int block_size=16384]) { | |
| 59 var id; | |
| 60 return _createArchive().then((_id) { | |
| 61 id = _id; | |
| 62 return call(OPEN_FILENAME, id, [file, block_size]); | |
| 63 }).then((_) => new ArchiveInputStream(id)); | |
| 64 } | |
| 65 | |
| 66 /** Begins extracting from [data], which should be a list of bytes. */ | |
| 67 Future<ArchiveInputStream> openData(List<int> data) { | |
| 68 var id; | |
| 69 return _createArchive().then((_id) { | |
| 70 id = _id; | |
| 71 return call(OPEN_MEMORY, id, [bytesForC(data)]); | |
| 72 }).then((_) => new ArchiveInputStream(id)); | |
| 73 } | |
| 74 | |
| 75 /** | |
| 76 * Creates an archive struct, applies all the configuration options to it, and | |
| 77 * returns its id. | |
| 78 */ | |
| 79 Future<int> _createArchive() { | |
| 80 return call(NEW).then((id) { | |
| 81 if (id == 0 || id == null) { | |
| 82 throw new ArchiveException("Archive is invalid or closed."); | |
| 83 } | |
| 84 return _pushConfiguration(id).then((_) => id); | |
| 85 }); | |
| 86 } | |
| 87 | |
| 88 /** | |
| 89 * Applies all configuration in this archive to the archive identified by | |
| 90 * [id]. Returns a future that completes once all the configuration is | |
| 91 * applied. | |
| 92 */ | |
| 93 Future _pushConfiguration(int id) { | |
| 94 var pending = <Future>[]; | |
| 95 if (filter.program != null) { | |
| 96 if (filter.programSignature != null) { | |
| 97 var signature = bytesForC(filter.programSignature); | |
| 98 pending.add(call(SUPPORT_FILTER_PROGRAM_SIGNATURE, id, | |
| 99 [filter.program, signature])); | |
| 100 } else { | |
| 101 pending.add(call(SUPPORT_FILTER_PROGRAM, id, [filter.program])); | |
| 102 } | |
| 103 } else if (filter.all) { | |
| 104 pending.add(call(SUPPORT_FILTER_ALL, id)); | |
| 105 } else { | |
| 106 if (filter.bzip2) pending.add(call(SUPPORT_FILTER_BZIP2, id)); | |
| 107 if (filter.compress) { | |
| 108 pending.add(call(SUPPORT_FILTER_COMPRESS, id)); | |
| 109 } | |
| 110 if (filter.gzip) pending.add(call(SUPPORT_FILTER_GZIP, id)); | |
| 111 if (filter.lzma) pending.add(call(SUPPORT_FILTER_LZMA, id)); | |
| 112 if (filter.xz) pending.add(call(SUPPORT_FILTER_XZ, id)); | |
| 113 } | |
| 114 | |
| 115 if (format.all) { | |
| 116 pending.add(call(SUPPORT_FORMAT_ALL, id)); | |
| 117 } else { | |
| 118 if (format.ar) pending.add(call(SUPPORT_FORMAT_AR, id)); | |
| 119 if (format.cpio) pending.add(call(SUPPORT_FORMAT_CPIO, id)); | |
| 120 if (format.empty) pending.add(call(SUPPORT_FORMAT_EMPTY, id)); | |
| 121 if (format.iso9660) pending.add(call(SUPPORT_FORMAT_ISO9660, id)); | |
| 122 if (format.mtree) pending.add(call(SUPPORT_FORMAT_MTREE, id)); | |
| 123 if (format.raw) pending.add(call(SUPPORT_FORMAT_RAW, id)); | |
| 124 if (format.tar) pending.add(call(SUPPORT_FORMAT_TAR, id)); | |
| 125 if (format.zip) pending.add(call(SUPPORT_FORMAT_ZIP, id)); | |
| 126 } | |
| 127 | |
| 128 void addOption(request, option) { | |
| 129 var value; | |
| 130 if (option.value == false || option.value == null) { | |
| 131 value = null; | |
| 132 } else if (option.value == true) { | |
| 133 value = '1'; | |
| 134 } else { | |
| 135 value = option.value.toString(); | |
| 136 } | |
| 137 | |
| 138 pending.add(CALL(request, id, [module, option.name, value])); | |
| 139 }; | |
| 140 | |
| 141 for (var option in filter.options.all) { | |
| 142 addOption(SET_FILTER_OPTION, option); | |
| 143 } | |
| 144 | |
| 145 for (var option in format.options.all) { | |
| 146 addOption(SET_FORMAT_OPTION, option); | |
| 147 } | |
| 148 | |
| 149 for (var option in options.all) { | |
| 150 addOption(SET_OPTION, option); | |
| 151 } | |
| 152 | |
| 153 return Future.wait(pending); | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 /** | |
| 158 * The configuration for the filter(s) to use when decompressing the contents | |
| 159 * of an archive. The precise compression used is auto-detected from among all | |
| 160 * enabled options. | |
| 161 */ | |
| 162 class Filter { | |
| 163 /** | |
| 164 * Auto-detect among all possible filters. If this is set, all other filter | |
| 165 * flags are ignored. [program] takes precedence over this. | |
| 166 */ | |
| 167 bool all = false; | |
| 168 | |
| 169 /** | |
| 170 * Enable [bzip2][wp] compression. | |
| 171 * | |
| 172 * [wp]: http://en.wikipedia.org/wiki/Bzip2 | |
| 173 */ | |
| 174 bool bzip2 = false; | |
| 175 | |
| 176 /** | |
| 177 * Enable the compression used by [the `compress` utility][wp]. | |
| 178 * | |
| 179 * [wp]: http://en.wikipedia.org/wiki/Compress | |
| 180 */ | |
| 181 bool compress = false; | |
| 182 | |
| 183 /** | |
| 184 * Enable [gzip][wp] compression. | |
| 185 * | |
| 186 * [wp]: http://en.wikipedia.org/wiki/Gzip | |
| 187 */ | |
| 188 bool gzip = false; | |
| 189 | |
| 190 /** | |
| 191 * Enable [lzma][wp] compression. | |
| 192 * | |
| 193 * [wp]: http://en.wikipedia.org/wiki/Lzma | |
| 194 */ | |
| 195 bool lzma = false; | |
| 196 | |
| 197 /** | |
| 198 * Enable [xz][wp] compression. | |
| 199 * | |
| 200 * [wp]: http://en.wikipedia.org/wiki/Xz | |
| 201 */ | |
| 202 bool xz = false; | |
| 203 | |
| 204 /** | |
| 205 * Compress using the command-line program `program`. If this is specified and | |
| 206 * [programSignature] is not, all other filter flags are ignored. This takes | |
| 207 * precedence over [all]. | |
| 208 */ | |
| 209 String program; | |
| 210 | |
| 211 // TODO(nweiz): allow multiple programs with signatures to be specified. | |
| 212 /** | |
| 213 * If set, `program` will be applied only to files whose initial bytes match | |
| 214 * [programSignature]. | |
| 215 */ | |
| 216 List<int> programSignature; | |
| 217 | |
| 218 /** | |
| 219 * Options for individual filters. See [the libarchive documentation][wiki] | |
| 220 * for a list of available options. | |
| 221 * | |
| 222 * [wiki]: https://github.com/libarchive/libarchive/wiki/ManPageArchiveReadSet
Options3 | |
| 223 */ | |
| 224 final ArchiveOptions options; | |
| 225 | |
| 226 Filter._() : options = new ArchiveOptions(); | |
| 227 } | |
| 228 | |
| 229 /** | |
| 230 * The configuration for the archive format(s) to look for when extracting the | |
| 231 * contents of an archive. The format used is auto-detected from among all | |
| 232 * enabled options. | |
| 233 */ | |
| 234 class Format { | |
| 235 /** | |
| 236 * Auto-detect among all possible formats. If this is set, all other format | |
| 237 * flags are ignored. | |
| 238 */ | |
| 239 bool all = false; | |
| 240 | |
| 241 /** | |
| 242 * Enable the [ar][wp] format. | |
| 243 * | |
| 244 * [wp]: http://en.wikipedia.org/wiki/Ar_(Unix) | |
| 245 */ | |
| 246 bool ar = false; | |
| 247 | |
| 248 /** | |
| 249 * Enable the [cpio][wp] format. | |
| 250 * | |
| 251 * [wp]: http://en.wikipedia.org/wiki/Cpio | |
| 252 */ | |
| 253 bool cpio = false; | |
| 254 | |
| 255 /** Enable treating empty files as archives with no entries. */ | |
| 256 bool empty = false; | |
| 257 | |
| 258 /** | |
| 259 * Enable the [ISO 9660][wp] format. | |
| 260 * | |
| 261 * [wp]: http://en.wikipedia.org/wiki/ISO_9660 | |
| 262 */ | |
| 263 bool iso9660 = false; | |
| 264 | |
| 265 /** | |
| 266 * Enable the [mtree][wiki] format. | |
| 267 * | |
| 268 * [wiki]: https://github.com/libarchive/libarchive/wiki/ManPageMtree5 | |
| 269 */ | |
| 270 bool mtree = false; | |
| 271 | |
| 272 /** Enable treating unknown files as archives containing a single file. */ | |
| 273 bool raw = false; | |
| 274 | |
| 275 /** | |
| 276 * Enable the [tar][wp] format. | |
| 277 * | |
| 278 * [wp]: http://en.wikipedia.org/wiki/Tar_(file_format) | |
| 279 */ | |
| 280 bool tar = false; | |
| 281 | |
| 282 /** | |
| 283 * Enable the [zip][wp] format. | |
| 284 * | |
| 285 * [wp]: http://en.wikipedia.org/wiki/ZIP_(file_format) | |
| 286 */ | |
| 287 bool zip = false; | |
| 288 | |
| 289 | |
| 290 /** | |
| 291 * Options for individual formats. See [the libarchive documentation][wiki] | |
| 292 * for a list of available options. | |
| 293 * | |
| 294 * [wiki]: https://github.com/libarchive/libarchive/wiki/ManPageArchiveReadSet
Options3 | |
| 295 */ | |
| 296 final ArchiveOptions options; | |
| 297 | |
| 298 Format._() : options = new ArchiveOptions(); | |
| 299 } | |
| OLD | NEW |