| OLD | NEW | 
|---|
| 1 // Copyright 2014 The Chromium OS Authors. All rights reserved. | 1 // Copyright 2014 The Chromium OS Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "volume_reader_javascript_stream.h" | 5 #include "volume_reader_javascript_stream.h" | 
| 6 | 6 | 
| 7 #include <algorithm> | 7 #include <algorithm> | 
| 8 #include <limits> | 8 #include <limits> | 
| 9 | 9 | 
| 10 #include "archive.h" | 10 #include "third_party/zlib/contrib/minizip/unzip.h" | 
|  | 11 | 
| 11 #include "ppapi/cpp/logging.h" | 12 #include "ppapi/cpp/logging.h" | 
| 12 | 13 | 
| 13 VolumeReaderJavaScriptStream::VolumeReaderJavaScriptStream( | 14 VolumeReaderJavaScriptStream::VolumeReaderJavaScriptStream( | 
| 14     int64_t archive_size, | 15     int64_t archive_size, | 
| 15     JavaScriptRequestorInterface* requestor) | 16     JavaScriptRequestorInterface* requestor) | 
| 16     : archive_size_(archive_size), | 17     : archive_size_(archive_size), | 
| 17       requestor_(requestor), | 18       requestor_(requestor), | 
| 18       available_data_(false), | 19       available_data_(false), | 
| 19       read_error_(false), | 20       read_error_(false), | 
| 20       passphrase_error_(false), | 21       passphrase_error_(false), | 
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 113 | 114 | 
| 114   pthread_mutex_lock(&shared_state_lock_); | 115   pthread_mutex_lock(&shared_state_lock_); | 
| 115 | 116 | 
| 116   // No more data, so signal end of reading. | 117   // No more data, so signal end of reading. | 
| 117   if (offset_ >= archive_size_) { | 118   if (offset_ >= archive_size_) { | 
| 118     pthread_mutex_unlock(&shared_state_lock_); | 119     pthread_mutex_unlock(&shared_state_lock_); | 
| 119     return 0; | 120     return 0; | 
| 120   } | 121   } | 
| 121 | 122 | 
| 122   // Call in case of first read or read after Seek and Skip. | 123   // Call in case of first read or read after Seek and Skip. | 
| 123   if (last_read_chunk_offset_ != offset_) | 124   if (last_read_chunk_offset_ != offset_ || !available_data_) | 
| 124     RequestChunk(bytes_to_read); | 125     RequestChunk(bytes_to_read); | 
| 125 | 126 | 
| 126   if (!available_data_) { | 127   if (!available_data_) { | 
| 127     // Wait for data from JavaScript. | 128     // Wait for data from JavaScript. | 
| 128     while (!available_data_) {  // Check again available data as first call | 129     while (!available_data_) {  // Check again available data as first call | 
| 129                                 // was done outside guarded zone. | 130                                 // was done outside guarded zone. | 
| 130       if (read_error_) { | 131       if (read_error_) { | 
| 131         pthread_mutex_unlock(&shared_state_lock_); | 132         pthread_mutex_unlock(&shared_state_lock_); | 
| 132         return ARCHIVE_FATAL; | 133         return -1; | 
| 133       } | 134       } | 
| 134       pthread_cond_wait(&available_data_cond_, &shared_state_lock_); | 135       pthread_cond_wait(&available_data_cond_, &shared_state_lock_); | 
| 135     } | 136     } | 
| 136   } | 137   } | 
| 137 | 138 | 
| 138   if (read_error_) {  // Read ahead failed. | 139   if (read_error_) {  // Read ahead failed. | 
| 139     pthread_mutex_unlock(&shared_state_lock_); | 140     pthread_mutex_unlock(&shared_state_lock_); | 
| 140     return ARCHIVE_FATAL; | 141     return -1; | 
| 141   } | 142   } | 
| 142 | 143 | 
| 143   // Make data available for libarchive custom read. No need to lock this part. | 144   // Make data available for libarchive custom read. No need to lock this part. | 
| 144   // The reason is that VolumeReaderJavaScriptStream::RequestChunk is the only | 145   // The reason is that VolumeReaderJavaScriptStream::RequestChunk is the only | 
| 145   // function that can set available_data_ back to false and let | 146   // function that can set available_data_ back to false and let | 
| 146   // VolumeReaderJavaScriptStream::SetBufferAndSignal overwrite the buffer. But | 147   // VolumeReaderJavaScriptStream::SetBufferAndSignal overwrite the buffer. But | 
| 147   // reading ahead is done only at the end of this function after the buffers | 148   // reading ahead is done only at the end of this function after the buffers | 
| 148   // are switched. | 149   // are switched. | 
| 149   *destination_buffer = read_ahead_array_buffer_ptr_->Map(); | 150   *destination_buffer = read_ahead_array_buffer_ptr_->Map(); | 
| 150   int64_t bytes_read = | 151   int64_t bytes_read = | 
| (...skipping 29 matching lines...) Expand all  Loading... | 
| 180   pthread_mutex_unlock(&shared_state_lock_); | 181   pthread_mutex_unlock(&shared_state_lock_); | 
| 181 | 182 | 
| 182   return bytes_read; | 183   return bytes_read; | 
| 183 } | 184 } | 
| 184 | 185 | 
| 185 int64_t VolumeReaderJavaScriptStream::Seek(int64_t offset, int whence) { | 186 int64_t VolumeReaderJavaScriptStream::Seek(int64_t offset, int whence) { | 
| 186   pthread_mutex_lock(&shared_state_lock_); | 187   pthread_mutex_lock(&shared_state_lock_); | 
| 187 | 188 | 
| 188   int64_t new_offset = offset_; | 189   int64_t new_offset = offset_; | 
| 189   switch (whence) { | 190   switch (whence) { | 
| 190     case SEEK_SET: | 191     case ZLIB_FILEFUNC_SEEK_SET: | 
| 191       new_offset = offset; | 192       new_offset = offset; | 
| 192       break; | 193       break; | 
| 193     case SEEK_CUR: | 194     case ZLIB_FILEFUNC_SEEK_CUR: | 
| 194       new_offset += offset; | 195       new_offset += offset; | 
| 195       break; | 196       break; | 
| 196     case SEEK_END: | 197     case ZLIB_FILEFUNC_SEEK_END: | 
| 197       new_offset = archive_size_ + offset; | 198       new_offset = archive_size_ + offset; | 
| 198       break; | 199       break; | 
| 199     default: | 200     default: | 
| 200       PP_NOTREACHED(); | 201       PP_NOTREACHED(); | 
| 201       pthread_mutex_unlock(&shared_state_lock_); | 202       pthread_mutex_unlock(&shared_state_lock_); | 
| 202       return ARCHIVE_FATAL; | 203       return -1; | 
| 203   } | 204   } | 
| 204 | 205 | 
| 205   if (new_offset < 0 || new_offset > archive_size_) { | 206   if (new_offset < 0) { | 
| 206     pthread_mutex_unlock(&shared_state_lock_); | 207     pthread_mutex_unlock(&shared_state_lock_); | 
| 207     return ARCHIVE_FATAL; | 208     return -1; | 
| 208   } | 209   } | 
| 209 | 210 | 
| 210   offset_ = new_offset; | 211   offset_ = new_offset; | 
| 211   pthread_mutex_unlock(&shared_state_lock_); | 212   pthread_mutex_unlock(&shared_state_lock_); | 
| 212 | 213 | 
| 213   return new_offset; | 214   return new_offset; | 
| 214 } | 215 } | 
| 215 | 216 | 
| 216 int64_t VolumeReaderJavaScriptStream::Skip(int64_t bytes_to_skip) { | 217 int64_t VolumeReaderJavaScriptStream::offset() { | 
| 217   pthread_mutex_lock(&shared_state_lock_); | 218   return offset_; | 
| 218   // Invalid bytes_to_skip. This "if" can be triggered for corrupted archives. |  | 
| 219   // We return 0 instead of ARCHIVE_FATAL in order for libarchive to use normal |  | 
| 220   // Read and return the correct error. In case we return ARCHIVE_FATAL here |  | 
| 221   // then libarchive just stops without telling us why it wasn't able to |  | 
| 222   // process the archive. |  | 
| 223   if (archive_size_ - offset_ < bytes_to_skip || bytes_to_skip < 0) { |  | 
| 224     pthread_mutex_unlock(&shared_state_lock_); |  | 
| 225     return 0; |  | 
| 226   } |  | 
| 227 |  | 
| 228   offset_ += bytes_to_skip; |  | 
| 229   pthread_mutex_unlock(&shared_state_lock_); |  | 
| 230 |  | 
| 231   return bytes_to_skip; |  | 
| 232 } | 219 } | 
| 233 | 220 | 
| 234 void VolumeReaderJavaScriptStream::SetRequestId(const std::string& request_id) { | 221 void VolumeReaderJavaScriptStream::SetRequestId(const std::string& request_id) { | 
| 235   // No lock necessary, as request_id is used by one thread only. | 222   // No lock necessary, as request_id is used by one thread only. | 
| 236   request_id_ = request_id; | 223   request_id_ = request_id; | 
| 237 } | 224 } | 
| 238 | 225 | 
| 239 const char* VolumeReaderJavaScriptStream::Passphrase() { | 226 const char* VolumeReaderJavaScriptStream::Passphrase() { | 
| 240   // The error is not recoverable. Once passphrase fails to be provided, it is | 227   // The error is not recoverable. Once passphrase fails to be provided, it is | 
| 241   // never asked again. Note, that still users are able to retry entering the | 228   // never asked again. Note, that still users are able to retry entering the | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
| 265   // Read next chunk only if not at the end of archive. | 252   // Read next chunk only if not at the end of archive. | 
| 266   if (archive_size_ <= offset_) | 253   if (archive_size_ <= offset_) | 
| 267     return; | 254     return; | 
| 268 | 255 | 
| 269   int64_t bytes_to_read = | 256   int64_t bytes_to_read = | 
| 270       std::min(length, archive_size_ - offset_ /* Positive check above. */); | 257       std::min(length, archive_size_ - offset_ /* Positive check above. */); | 
| 271   available_data_ = false; | 258   available_data_ = false; | 
| 272 | 259 | 
| 273   requestor_->RequestFileChunk(request_id_, offset_, bytes_to_read); | 260   requestor_->RequestFileChunk(request_id_, offset_, bytes_to_read); | 
| 274 } | 261 } | 
| OLD | NEW | 
|---|