| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #library("entry"); | 5 #library("entry"); |
| 6 | 6 |
| 7 #import("dart:io"); | 7 #import("dart:io"); |
| 8 #import("read_request.dart"); | 8 #import("archive.dart", prefix: "archive"); |
| 9 #import("entry_request.dart"); |
| 10 #import("read_request.dart", prefix: 'read'); |
| 9 #import("utils.dart"); | 11 #import("utils.dart"); |
| 10 | 12 |
| 11 /** | 13 /** |
| 12 * A single file in an archive. | 14 * A single file in an archive. |
| 13 * | 15 * |
| 14 * This is accessible via [ArchiveInputStream.onEntry]. | 16 * This is accessible via [ArchiveInputStream.onEntry]. |
| 15 */ | 17 */ |
| 16 class ArchiveEntry { | 18 class ArchiveEntry { |
| 17 /** | 19 /** |
| 18 * The various properties of this archive entry, as sent over from the C | 20 * The various properties of this archive entry, as sent over from the C |
| (...skipping 16 matching lines...) Expand all Loading... |
| 35 | 37 |
| 36 // TODO(nweiz): Get rid of this once issue 4202 is fixed. | 38 // TODO(nweiz): Get rid of this once issue 4202 is fixed. |
| 37 /** | 39 /** |
| 38 * A future that only exists once [openInputStream] is called, and completes | 40 * A future that only exists once [openInputStream] is called, and completes |
| 39 * once the input stream is closed. | 41 * once the input stream is closed. |
| 40 * | 42 * |
| 41 * For internal use only. | 43 * For internal use only. |
| 42 */ | 44 */ |
| 43 Future inputComplete; | 45 Future inputComplete; |
| 44 | 46 |
| 45 ArchiveEntry(this._archiveId, this._properties); | 47 ArchiveEntry.internal(this._properties, this._archiveId) { |
| 48 attachFinalizer(this, (id) => call(FREE, id), _id); |
| 49 } |
| 50 |
| 51 /** Create a new [ArchiveEntry] with default values for all of its fields. */ |
| 52 static Future<ArchiveEntry> create() { |
| 53 return call(NEW).transform((properties) { |
| 54 return new archive.ArchiveEntry.internal(properties, null); |
| 55 }); |
| 56 } |
| 57 |
| 58 /** The id of the underlying archive entry. */ |
| 59 int get _id() => _properties[0]; |
| 46 | 60 |
| 47 /** If this entry is a hardlink, this is the destination. Otherwise, null. */ | 61 /** If this entry is a hardlink, this is the destination. Otherwise, null. */ |
| 48 String get hardlink() => _properties[0]; | 62 String get hardlink() => _properties[1]; |
| 63 set hardlink(String value) => _set(SET_HARDLINK, 1, value); |
| 49 | 64 |
| 50 /** The path to this entry in the archive. */ | 65 /** The path to this entry in the archive. */ |
| 51 String get pathname() => _properties[1]; | 66 String get pathname() => _properties[2]; |
| 67 set pathname(String value) => _set(SET_PATHNAME, 2, value); |
| 52 | 68 |
| 53 /** The path to this entry on disk, */ | 69 /** The path to this entry on disk, */ |
| 54 String get sourcepath() => _properties[2]; | 70 String get sourcepath() => _properties[3]; |
| 71 set sourcepath(String value) => _set(SET_SOURCEPATH, 3, value); |
| 55 | 72 |
| 56 /** If this entry is a symlink, this is the destination. Otherwise, null. */ | 73 /** If this entry is a symlink, this is the destination. Otherwise, null. */ |
| 57 String get symlink() => _properties[3]; | 74 String get symlink() => _properties[4]; |
| 75 set symlink(String value) => _set(SET_SYMLINK, 4, value); |
| 58 | 76 |
| 59 /** The group identifier for this entry. */ | 77 /** The group identifier for this entry. */ |
| 60 int get gid() => _properties[4]; | 78 int get gid() => _properties[5]; |
| 79 set gid(int value) => _set(SET_GID, 5, value); |
| 61 | 80 |
| 62 /** The user identifier for this entry. */ | 81 /** The user identifier for this entry. */ |
| 63 int get uid() => _properties[5]; | 82 int get uid() => _properties[6]; |
| 83 set uid(int value) => _set(SET_UID, 6, value); |
| 64 | 84 |
| 65 /** The permissions bitmask for this entry. */ | 85 /** The permissions bitmask for this entry. */ |
| 66 int get perm_mask() => _properties[6]; | 86 int get perm_mask() => _properties[7]; |
| 87 set perm_mask(int value) => _set(SET_PERM, 7, value); |
| 67 | 88 |
| 68 /** The String representation of the permissions for this entry. */ | 89 /** |
| 69 String get strmode() => _properties[7]; | 90 * The String representation of the permissions for this entry. |
| 91 * |
| 92 * Note that if you set [perm_mask], this value will not change. |
| 93 */ |
| 94 String get strmode() => _properties[8]; |
| 70 | 95 |
| 71 /** The name of the group this entry belongs to. */ | 96 /** The name of the group this entry belongs to. */ |
| 72 String get gname() => _properties[8]; | 97 String get gname() => _properties[9]; |
| 98 set gname(String value) => _set(SET_GNAME, 9, value); |
| 73 | 99 |
| 74 /** The name of the user this entry belongs to. */ | 100 /** The name of the user this entry belongs to. */ |
| 75 String get uname() => _properties[9]; | 101 String get uname() => _properties[10]; |
| 102 set uname(String value) => _set(SET_UNAME, 10, value); |
| 76 | 103 |
| 77 /** The file flag bits that should be set for this entry. */ | 104 /** |
| 78 int get fflags_set() => _properties[10]; | 105 * The file flag bits that should be set for this entry. |
| 106 * |
| 107 * Note that if you set [fflags_text], this value will not change, and vice |
| 108 * versa. |
| 109 */ |
| 110 int get fflags_set() => _properties[11]; |
| 111 set fflags_set(int value) => _set(SET_FFLAGS_SET, 11, value); |
| 79 | 112 |
| 80 /** The file flag bits that should be cleared for this entry. */ | 113 /** |
| 81 int get fflags_clear() => _properties[11]; | 114 * The file flag bits that should be cleared for this entry. |
| 115 * |
| 116 * Note that if you set [fflags_text], this value will not change, and vice |
| 117 * versa. |
| 118 */ |
| 119 int get fflags_clear() => _properties[12]; |
| 120 set fflags_clear(int value) => _set(SET_FFLAGS_CLEAR, 12, value); |
| 82 | 121 |
| 83 /** The textual representation of the file flags for this entry. */ | 122 /** |
| 84 String get fflags_text() => _properties[12]; | 123 * The textual representation of the file flags for this entry. |
| 124 * |
| 125 * Note that if you set [fflags_set] or [fflags_clear], this value will not |
| 126 * change, and vice versa. |
| 127 */ |
| 128 String get fflags_text() => _properties[13]; |
| 129 set fflags_text(String value) => _set(SET_FFLAGS_TEXT, 13, value); |
| 85 | 130 |
| 86 /** The filetype bitmask for this entry. */ | 131 /** The filetype bitmask for this entry. */ |
| 87 int get filetype_mask() => _properties[13]; | 132 int get filetype_mask() => _properties[14]; |
| 133 set filetype_mask(int value) => _set(SET_FILETYPE, 14, value); |
| 88 | 134 |
| 89 /** The filetype and permissions bitmask for this entry. */ | 135 /** The filetype and permissions bitmask for this entry. */ |
| 90 int get mode_mask() => _properties[14]; | 136 int get mode_mask() => _properties[15]; |
| 137 set mode_mask(int value) => _set(SET_MODE, 15, value); |
| 91 | 138 |
| 92 /** The size of this entry in bytes, or null if it's unset. */ | 139 /** The size of this entry in bytes, or null if it's unset. */ |
| 93 int get size() => _properties[15]; | 140 int get size() => _properties[16]; |
| 141 set size(int value) => _set(SET_SIZE, 16, value); |
| 94 | 142 |
| 95 /** The ID of the device containing this entry, or null if it's unset. */ | 143 /** The ID of the device containing this entry, or null if it's unset. */ |
| 96 int get dev() => _properties[16]; | 144 int get dev() => _properties[17]; |
| 145 set dev(int value) => _set(SET_DEV, 17, value); |
| 97 | 146 |
| 98 /** The major number of the ID of the device containing this entry. */ | 147 /** The major number of the ID of the device containing this entry. */ |
| 99 int get devmajor() => _properties[17]; | 148 int get devmajor() => _properties[18]; |
| 149 set devmajor(int value) => _set(SET_DEVMAJOR, 18, value); |
| 100 | 150 |
| 101 /** The minor number of the ID of the device containing this entry. */ | 151 /** The minor number of the ID of the device containing this entry. */ |
| 102 int get devminor() => _properties[18]; | 152 int get devminor() => _properties[19]; |
| 153 set devminor(int value) => _set(SET_DEVMINOR, 19, value); |
| 103 | 154 |
| 104 /** The inode number of this entry, or null if it's unset. */ | 155 /** The inode number of this entry, or null if it's unset. */ |
| 105 int get ino() => _properties[19]; | 156 int get ino() => _properties[20]; |
| 157 set ino(int value) => _set(SET_INO, 20, value); |
| 106 | 158 |
| 107 /** The number of references to this entry. */ | 159 /** The number of references to this entry. */ |
| 108 int get nlink() => _properties[20]; | 160 int get nlink() => _properties[21]; |
| 161 set nlink(int value) => _set(SET_NLINK, 21, value); |
| 109 | 162 |
| 110 /** The device ID of this entry. */ | 163 /** The device ID of this entry. */ |
| 111 int get rdev() => _properties[21]; | 164 int get rdev() => _properties[22]; |
| 165 set rdev(int value) => _set(SET_RDEV, 22, value); |
| 112 | 166 |
| 113 /** The major number of the device ID of this entry. */ | 167 /** The major number of the device ID of this entry. */ |
| 114 int get rdevmajor() => _properties[22]; | 168 int get rdevmajor() => _properties[23]; |
| 169 set rdevmajor(int value) => _set(SET_RDEVMAJOR, 23, value); |
| 115 | 170 |
| 116 /** The minor number of the device ID of this entry. */ | 171 /** The minor number of the device ID of this entry. */ |
| 117 int get rdevminor() => _properties[23]; | 172 int get rdevminor() => _properties[24]; |
| 173 set rdevminor(int value) => _set(SET_RDEVMINOR, 24, value); |
| 118 | 174 |
| 119 /** The last time this entry was accessed. */ | 175 /** The last time this entry was accessed, or null if it's unset. */ |
| 120 Date get atime() => new Date.fromMillisecondsSinceEpoch(_properties[24]); | 176 Date get atime() => _fromMs(_properties[25]); |
| 177 set atime(Date value) => _set(SET_ATIME, 25, _toMs(value)); |
| 121 | 178 |
| 122 /** The nanoseconds at the last time this entry was accessed. */ | 179 /** The time this entry was created, or null if it's unset. */ |
| 123 int get atime_nsec() => _properties[25]; | 180 Date get birthtime() => _fromMs(_properties[26]); |
| 124 | 181 set birthtime(Date value) => _set(SET_BIRTHTIME, 26, _toMs(value)); |
| 125 /** The time this entry was created. */ | |
| 126 Date get birthtime() => new Date.fromMillisecondsSinceEpoch(_properties[26]); | |
| 127 | |
| 128 /** The nanoseconds at the time this entry was created. */ | |
| 129 int get birthtime_nsec() => _properties[27]; | |
| 130 | |
| 131 /** The last time an inode property of this entry was changed. */ | |
| 132 Date get ctime() => new Date.fromMillisecondsSinceEpoch(_properties[28]); | |
| 133 | 182 |
| 134 /** | 183 /** |
| 135 * The nanoseconds at the last time an inode property of this entry was | 184 * The last time an inode property of this entry was changed, or null if it's |
| 136 * changed. | 185 * unset. |
| 137 */ | 186 */ |
| 138 int get ctime_nsec() => _properties[29]; | 187 Date get ctime() => _fromMs(_properties[27]); |
| 188 set ctime(Date value) => _set(SET_CTIME, 27, _toMs(value)); |
| 139 | 189 |
| 140 /** The last time this entry was modified. */ | 190 /** The last time this entry was modified, or null if it's unset. */ |
| 141 Date get mtime() => new Date.fromMillisecondsSinceEpoch(_properties[30]); | 191 Date get mtime() => _fromMs(_properties[28]); |
| 142 | 192 set mtime(Date value) => _set(SET_MTIME, 28, _toMs(value)); |
| 143 /** The nanoseconds at the last time this entry was modified. */ | |
| 144 int get mtime_nsec() => _properties[31]; | |
| 145 | 193 |
| 146 /** Whether [openInputStream] has been called. */ | 194 /** Whether [openInputStream] has been called. */ |
| 147 bool get isInputOpen() => _input != null; | 195 bool get isInputOpen() => _input != null; |
| 148 | 196 |
| 197 /** Create a deep copy of this [ArchiveEntry]. */ |
| 198 Future<ArchiveEntry> clone() { |
| 199 return call(CLONE, _id). |
| 200 transform((array) => new archive.ArchiveEntry.internal(array, null)); |
| 201 } |
| 202 |
| 203 /** |
| 204 * Set a property value with index [value] on the local representation of the |
| 205 * archive entry and on the native representation. |
| 206 */ |
| 207 void _set(int requestType, int index, value) { |
| 208 _properties[index] = value; |
| 209 // Since the native code processes messages in order, the SET_* messages |
| 210 // will be received and processed before any further messages. |
| 211 call(requestType, _id, [value]).then((_) {}); |
| 212 } |
| 213 |
| 214 /** |
| 215 * Converts [ms], the (possibly null) number of milliseconds since the epoch |
| 216 * into a Date object (which may also be null). |
| 217 */ |
| 218 Date _fromMs(int ms) { |
| 219 if (ms == null) return null; |
| 220 return new Date.fromMillisecondsSinceEpoch(ms); |
| 221 } |
| 222 |
| 223 /** |
| 224 * Converts [date], which may be null, into the number of milliseconds since |
| 225 * the epoch (which may also be null). |
| 226 */ |
| 227 int _toMs(Date date) { |
| 228 if (date == null) return null; |
| 229 return date.millisecondsSinceEpoch; |
| 230 } |
| 231 |
| 149 /** | 232 /** |
| 150 * Creates a new input stream for reading the contents of this entry. | 233 * Creates a new input stream for reading the contents of this entry. |
| 151 * | 234 * |
| 152 * The contents of an entry must be consumed before the next entry is read | 235 * The contents of an entry must be consumed before the next entry is read |
| 153 * from the parent [ArchiveInputStream]. This means that [openInputStream] | 236 * from the parent [ArchiveInputStream]. This means that [openInputStream] |
| 154 * must be called from the [ArchiveInputStream.onEntry] callback, or before | 237 * must be called from the [ArchiveInputStream.onEntry] callback, or before |
| 155 * the future returned by that callback completes. Once the next entry has | 238 * the future returned by that callback completes. Once the next entry has |
| 156 * been read, calling [openInputStream] will throw an [ArchiveException]. | 239 * been read, calling [openInputStream] will throw an [ArchiveException]. |
| 157 * | 240 * |
| 158 * Only one input stream may be opened per entry. | 241 * Only one input stream may be opened per entry. |
| 159 */ | 242 */ |
| 160 InputStream openInputStream() { | 243 InputStream openInputStream() { |
| 161 if (_archiveId == null) { | 244 if (_archiveId == null) { |
| 162 throw new UnsupportedOperationException("Archive entry $pathname is no " | 245 throw new UnsupportedOperationException("Cannot open input stream for " |
| 163 "longer being read from the archive."); | 246 "archive entry $pathname."); |
| 164 } else if (_input != null) { | 247 } else if (_input != null) { |
| 165 throw new UnsupportedOperationException("An input stream has already been" | 248 throw new UnsupportedOperationException("An input stream has already been" |
| 166 "opened for archive entry $pathname."); | 249 "opened for archive entry $pathname."); |
| 167 } | 250 } |
| 168 | 251 |
| 169 var inputCompleter = new Completer(); | 252 var inputCompleter = new Completer(); |
| 170 inputComplete = inputCompleter.future; | 253 inputComplete = inputCompleter.future; |
| 171 | 254 |
| 172 _input = new ListInputStream(); | 255 _input = new ListInputStream(); |
| 173 // TODO(nweiz): Report errors once issue 3657 is fixed | 256 // TODO(nweiz): Report errors once issue 3657 is fixed |
| (...skipping 25 matching lines...) Expand all Loading... |
| 199 /** | 282 /** |
| 200 * Read all data from the archive and write it to [_input]. Returns a future | 283 * Read all data from the archive and write it to [_input]. Returns a future |
| 201 * that completes once this is done. | 284 * that completes once this is done. |
| 202 * | 285 * |
| 203 * This assumes that both [_input] and [_archiveId] are non-null and that | 286 * This assumes that both [_input] and [_archiveId] are non-null and that |
| 204 * [_input] is open, although if that changes before this completes it will | 287 * [_input] is open, although if that changes before this completes it will |
| 205 * handle it gracefully. | 288 * handle it gracefully. |
| 206 */ | 289 */ |
| 207 Future _consumeInput() { | 290 Future _consumeInput() { |
| 208 var data; | 291 var data; |
| 209 return call(DATA_BLOCK, _archiveId).chain((_data) { | 292 return call(read.DATA_BLOCK, _archiveId).chain((_data) { |
| 210 data = _data; | 293 data = _data; |
| 211 // TODO(nweiz): This async() call is only necessary because of issue 4222. | 294 // TODO(nweiz): This async() call is only necessary because of issue 4222. |
| 212 return async(); | 295 return async(); |
| 213 }).chain((_) { | 296 }).chain((_) { |
| 214 if (_input.closed || _archiveId == null || data == null) { | 297 if (_input.closed || _archiveId == null || data == null) { |
| 215 return new Future.immediate(null); | 298 return new Future.immediate(null); |
| 216 } | 299 } |
| 217 _input.write(data); | 300 _input.write(data); |
| 218 return _consumeInput(); | 301 return _consumeInput(); |
| 219 }); | 302 }); |
| 220 } | 303 } |
| 221 } | 304 } |
| OLD | NEW |