Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: ui/file_manager/zip_archiver/unpacker/cpp/compressor_archive_libarchive.cc

Issue 2804453002: Move files from zip_archiver/unpacker/ to zip_archiver/. (Closed)
Patch Set: Move files from zip_archiver/unpacker/ to zip_archiver/. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "compressor_archive_libarchive.h"
6
7 #include <cerrno>
8 #include <cstring>
9
10 #include "archive_entry.h"
11 #include "ppapi/cpp/logging.h"
12
13 namespace {
14 // Nothing to do here because JavaScript takes care of file open operations.
15 int CustomArchiveOpen(archive* archive_object, void* client_data) {
16 return ARCHIVE_OK;
17 }
18
19 // Called when any data chunk must be written on the archive. It copies data
20 // from the given buffer processed by libarchive to an array buffer and passes
21 // it to compressor_stream.
22 ssize_t CustomArchiveWrite(archive* archive_object, void* client_data,
23 const void* buffer, size_t length) {
24 CompressorArchiveLibarchive* compressor_libarchive =
25 static_cast<CompressorArchiveLibarchive*>(client_data);
26
27 const char* char_buffer = static_cast<const char*>(buffer);
28
29 // Copy the data in buffer to array_buffer.
30 PP_DCHECK(length > 0);
31 pp::VarArrayBuffer array_buffer(length);
32 char* array_buffer_data = static_cast<char*>(array_buffer.Map());
33 memcpy(array_buffer_data, char_buffer, length);
34 array_buffer.Unmap();
35
36 ssize_t written_bytes =
37 compressor_libarchive->compressor_stream()->Write(length, array_buffer);
38
39 // Negative written_bytes represents an error.
40 if (written_bytes < 0) {
41 // When writing fails, archive_set_error() should be called and -1 should
42 // be returned.
43 archive_set_error(
44 compressor_libarchive->archive(), EIO, "Failed to write a chunk.");
45 return -1;
46 }
47 return written_bytes;
48 }
49
50 // Nothing to do here because JavaScript takes care of file close operations.
51 int CustomArchiveClose(archive* archive_object, void* client_data) {
52 return ARCHIVE_OK;
53 }
54 }
55
56 CompressorArchiveLibarchive::CompressorArchiveLibarchive(
57 CompressorStream* compressor_stream)
58 : CompressorArchive(compressor_stream),
59 compressor_stream_(compressor_stream) {
60 destination_buffer_ =
61 new char[compressor_archive_constants::kMaximumDataChunkSize];
62 }
63
64 CompressorArchiveLibarchive::~CompressorArchiveLibarchive() {
65 delete destination_buffer_;
66 }
67
68 void CompressorArchiveLibarchive::CreateArchive() {
69 archive_ = archive_write_new();
70 archive_write_set_format_zip(archive_);
71
72 // Passing 1 as the second argument causes the final chunk not to be padded.
73 archive_write_set_bytes_in_last_block(archive_, 1);
74 archive_write_set_bytes_per_block(
75 archive_, compressor_archive_constants::kMaximumDataChunkSize);
76 archive_write_open(archive_, this, CustomArchiveOpen,
77 CustomArchiveWrite, CustomArchiveClose);
78 }
79
80 void CompressorArchiveLibarchive::AddToArchive(
81 const std::string& filename,
82 int64_t file_size,
83 time_t modification_time,
84 bool is_directory) {
85 entry = archive_entry_new();
86
87 archive_entry_set_pathname(entry, filename.c_str());
88 archive_entry_set_size(entry, file_size);
89 archive_entry_set_mtime(entry, modification_time, 0 /* millisecond */);
90
91 if (is_directory) {
92 archive_entry_set_filetype(entry, AE_IFDIR);
93 archive_entry_set_perm(
94 entry, compressor_archive_constants::kDirectoryPermission);
95 } else {
96 archive_entry_set_filetype(entry, AE_IFREG);
97 archive_entry_set_perm(
98 entry, compressor_archive_constants::kFilePermission);
99 }
100 archive_write_header(archive_, entry);
101 // If archive_errno() returns 0, the header was written correctly.
102 if (archive_errno(archive_) != 0) {
103 CloseArchive(true /* hasError */);
104 return;
105 }
106
107 if (!is_directory) {
108 int64_t remaining_size = file_size;
109 while (remaining_size > 0) {
110 int64_t chunk_size = std::min(remaining_size,
111 compressor_archive_constants::kMaximumDataChunkSize);
112 PP_DCHECK(chunk_size > 0);
113
114 int64_t read_bytes =
115 compressor_stream_->Read(chunk_size, destination_buffer_);
116 // Negative read_bytes indicates an error occurred when reading chunks.
117 if (read_bytes < 0) {
118 CloseArchive(true /* hasError */);
119 break;
120 }
121
122 int64_t written_bytes =
123 archive_write_data(archive_, destination_buffer_, read_bytes);
124 // If archive_errno() returns 0, the buffer was written correctly.
125 if (archive_errno(archive_) != 0) {
126 CloseArchive(true /* hasError */);
127 break;
128 }
129 PP_DCHECK(written_bytes > 0);
130
131 remaining_size -= written_bytes;
132 }
133 }
134
135 archive_entry_free(entry);
136 }
137
138 void CompressorArchiveLibarchive::CloseArchive(bool has_error) {
139 // If has_error is true, mark the archive object as being unusable and
140 // release resources without writing no more data on the archive.
141 if (has_error)
142 archive_write_fail(archive_);
143 if (archive_) {
144 archive_write_free(archive_);
145 archive_ = NULL;
146 }
147 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698