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("entry"); | |
6 | |
7 #import("dart:io"); | |
8 #import("read_request.dart"); | |
9 #import("utils.dart"); | |
10 | |
11 /** | |
12 * A single file in an archive. | |
13 * | |
14 * This is accessible via [ArchiveInputStream.onEntry]. | |
15 */ | |
16 class ArchiveEntry { | |
17 /** | |
18 * The various properties of this archive entry, as sent over from the C | |
19 * extension. | |
20 */ | |
21 final List _array; | |
Bob Nystrom
2012/07/31 21:56:48
Can you give this a better name? "_properties"?
nweiz
2012/07/31 23:38:25
Done.
| |
22 | |
23 /** | |
24 * The id of the archive to which this entry belongs. Used to read the entry | |
25 * data. This will be set to null once there's no longer data available to be | |
26 * read for this entry. | |
27 */ | |
28 int _archiveId; | |
29 | |
30 /** | |
31 * The input stream being used to read data from this entry. This is null | |
32 * until [openInputStream] is called. | |
33 */ | |
34 InputStream _input; | |
35 | |
36 // TODO(nweiz): Get rid of this once issue 4202 is fixed. | |
37 /** | |
38 * A future that only exists once [openInputStream] is called, and completes | |
39 * once the input stream is closed. | |
40 * | |
41 * For internal use only. | |
Bob Nystrom
2012/07/31 21:56:48
Make it private then?
nweiz
2012/07/31 23:38:25
It needs to be accessible from input_stream.dart.
| |
42 */ | |
43 Future inputComplete; | |
44 | |
45 ArchiveEntry(this._archiveId, this._array); | |
46 | |
47 /** If this entry is a hardlink, this is the destination. Otherwise, null. */ | |
48 String get hardlink() => _array[0]; | |
49 | |
50 /** The path to this entry in the archive. */ | |
51 String get pathname() => _array[1]; | |
52 | |
53 /** The path to this entry on disk, */ | |
54 String get sourcepath() => _array[2]; | |
55 | |
56 /** If this entry is a symlink, this is the destination. Otherwise, null. */ | |
57 String get symlink() => _array[3]; | |
58 | |
59 /** The group identifier for this entry. */ | |
60 int get gid() => _array[4]; | |
61 | |
62 /** The user identifier for this entry. */ | |
63 int get uid() => _array[5]; | |
64 | |
65 /** The permissions bitmask for this entry. */ | |
66 int get perm_mask() => _array[6]; | |
67 | |
68 /** The String representation of the permissions for this entry. */ | |
69 String get strmode() => _array[7]; | |
70 | |
71 /** The name of the group this entry belongs to. */ | |
72 String get gname() => _array[8]; | |
73 | |
74 /** The name of the user this entry belongs to. */ | |
75 String get uname() => _array[9]; | |
76 | |
77 /** The file flag bits that should be set for this entry. */ | |
78 int get fflags_set() => _array[10]; | |
79 | |
80 /** The file flag bits that should be cleared for this entry. */ | |
81 int get fflags_clear() => _array[11]; | |
82 | |
83 /** The textual representation of the file flags for this entry. */ | |
84 String get fflags_text() => _array[12]; | |
85 | |
86 /** The filetype bitmask for this entry. */ | |
87 int get filetype_mask() => _array[13]; | |
88 | |
89 /** The filetype and permissions bitmask for this entry. */ | |
90 int get mode_mask() => _array[14]; | |
91 | |
92 /** The size of this entry in bytes, or null if it's unset. */ | |
93 int get size() => _array[15]; | |
94 | |
95 /** The ID of the device containing this entry, or null if it's unset. */ | |
96 int get dev() => _array[16]; | |
97 | |
98 /** The major number of the ID of the device containing this entry. */ | |
99 int get devmajor() => _array[17]; | |
100 | |
101 /** The minor number of the ID of the device containing this entry. */ | |
102 int get devminor() => _array[18]; | |
103 | |
104 /** The inode number of this entry, or null if it's unset. */ | |
105 int get ino() => _array[19]; | |
106 | |
107 /** The number of references to this entry. */ | |
108 int get nlink() => _array[20]; | |
109 | |
110 /** The device ID of this entry. */ | |
111 int get rdev() => _array[21]; | |
112 | |
113 /** The major number of the device ID of this entry. */ | |
114 int get rdevmajor() => _array[22]; | |
115 | |
116 /** The minor number of the device ID of this entry. */ | |
117 int get rdevminor() => _array[23]; | |
118 | |
119 /** The last time this entry was accessed. */ | |
120 Date get atime() => new Date.fromMillisecondsSinceEpoch(_array[24]); | |
121 | |
122 /** The nanoseconds at the last time this entry was accessed. */ | |
123 int get atime_nsec() => _array[25]; | |
124 | |
125 /** The time this entry was created. */ | |
126 Date get birthtime() => new Date.fromMillisecondsSinceEpoch(_array[26]); | |
127 | |
128 /** The nanoseconds at the time this entry was created. */ | |
129 int get birthtime_nsec() => _array[27]; | |
130 | |
131 /** The last time an inode property of this entry was changed. */ | |
132 Date get ctime() => new Date.fromMillisecondsSinceEpoch(_array[28]); | |
133 | |
134 /** | |
135 * The nanoseconds at the last time an inode property of this entry was | |
136 * changed. | |
137 */ | |
138 int get ctime_nsec() => _array[29]; | |
139 | |
140 /** The last time this entry was modified. */ | |
141 Date get mtime() => new Date.fromMillisecondsSinceEpoch(_array[30]); | |
142 | |
143 /** The nanoseconds at the last time this entry was modified. */ | |
144 int get mtime_nsec() => _array[31]; | |
145 | |
146 /** Whether [openInputStream] has been called. */ | |
147 bool get inputOpened() => _input != null; | |
Bob Nystrom
2012/07/31 21:56:48
"isInputOpen"
Past tense names are usually for ev
nweiz
2012/07/31 23:38:25
Done.
| |
148 | |
149 /** | |
150 * Creates a new input stream for reading the contents of this entry. | |
151 * | |
152 * The contents of an entry must be consumed before the next entry is read | |
153 * from the parent [ArchiveInputStream]. This means that [openInputStream] | |
154 * must be called from the [ArchiveInputStream.onEntry] callback, or before | |
155 * the future returned by that callback completes. Once the next entry has | |
156 * been read, calling [openInputStream] will throw an [ArchiveError]. | |
157 * | |
158 * Only one input stream may be opened per entry. | |
159 */ | |
160 InputStream openInputStream() { | |
161 if (_archiveId == null) { | |
162 throw new ArchiveError("Archive entry $pathname is no longer being read " | |
163 "from the archive."); | |
Bob Nystrom
2012/07/31 21:56:48
Ideally these would be StateException, but in the
nweiz
2012/07/31 23:38:25
Done.
| |
164 } else if (_input != null) { | |
165 throw new ArchiveError("An input stream has already been opened for " | |
166 "archive entry $pathname."); | |
167 } | |
168 | |
169 var inputCompleter = new Completer(); | |
170 inputComplete = inputCompleter.future; | |
171 | |
172 _input = new ListInputStream(); | |
173 // TODO(nweiz): Report errors once issue 3657 is fixed | |
174 var fut = _consumeInput().chain((_) { | |
Bob Nystrom
2012/07/31 21:56:48
"fut" -> "future".
nweiz
2012/07/31 23:38:25
Done.
| |
175 if (!_input.closed) _input.markEndOfStream(); | |
176 // Asynchronously complete to give the InputStream callbacks a chance to | |
177 // fire. | |
178 return async(); | |
179 }).transform((_) => inputCompleter.complete(null)); | |
180 | |
181 fut.handleException((e) { | |
182 print(e); | |
183 print(fut.stackTrace); | |
184 }); | |
185 return _input; | |
186 } | |
187 | |
188 /** | |
189 * Close this entry so that its input stream no longer produces data. | |
190 * | |
191 * In addition to closing the associated input stream, this will prevent new | |
192 * input streams from being opened. | |
193 */ | |
194 void close() { | |
195 _archiveId = null; | |
196 if (_input != null) _input.close(); | |
197 } | |
198 | |
199 /** | |
200 * Read all data from the archive and write it to [_input]. Returns a future | |
201 * that completes once this is done. | |
202 * | |
203 * 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 | |
205 * handle it gracefully. | |
206 */ | |
207 Future _consumeInput() { | |
208 var data; | |
209 return call(DATA_BLOCK, _archiveId).chain((_data) { | |
210 data = _data; | |
211 // TODO(nweiz): This async() call is only necessary because of issue 4222. | |
212 return async(); | |
213 }).chain((_) { | |
214 if (_input.closed || _archiveId == null || data == null) { | |
215 return new Future.immediate(null); | |
216 } | |
217 _input.write(data); | |
218 return _consumeInput(); | |
219 }); | |
220 } | |
221 } | |
OLD | NEW |