• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2023 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #include <android-base/file.h>
17 #include <android-base/logging.h>
18 #include <libsnapshot/cow_compress.h>
19 #include <libsnapshot/cow_format.h>
20 #include <libsnapshot/cow_writer.h>
21 
22 #include <gflags/gflags.h>
23 #include <iostream>
24 
25 #include "android-base/unique_fd.h"
26 
27 DEFINE_bool(silent, false, "Run silently");
28 DEFINE_int32(writer_version, 2, "which version of COW writer to be used");
29 DEFINE_bool(write_legacy, false,
30             "Writes a legacy cow_v2 in current directory, this cow was used to test backwards "
31             "compatibility between version 2 and version 3");
32 DEFINE_bool(write_header, false, "Test reading/writing just the header");
33 using namespace android::snapshot;
34 
35 // This writes a simple cow v2 file in the current directory. This file will serve as testdata for
36 // ensuring our v3 cow reader will be able to read a cow file created by the v2 writer.
37 //
38 // WARNING: We should not be overriding this test file, as it will serve as historic marker for what
39 // a device with old writer_v2 will write as a cow.
write_legacy_cow_v2()40 static void write_legacy_cow_v2() {
41     CowOptions options;
42     options.cluster_ops = 5;
43     options.num_merge_ops = 1;
44     std::string data = "This is some data, believe it";
45     data.resize(options.block_size, '\0');
46 
47     char cwd_buffer[1024];
48     size_t cwd_buffer_size = sizeof(cwd_buffer);
49 
50     // Get the current working directory path.
51     char* err = getcwd(cwd_buffer, cwd_buffer_size);
52     if (!err) {
53         LOG(ERROR) << "Couldn't get current directory";
54     }
55     android::base::unique_fd fd(open(strcat(cwd_buffer, "/cow_v2"), O_CREAT | O_RDWR, 0666));
56     if (fd.get() == -1) {
57         LOG(FATAL) << "couldn't open tmp_cow";
58     }
59     std::unique_ptr<ICowWriter> writer = CreateCowWriter(2, options, std::move(fd));
60     writer->AddCopy(0, 5);
61     writer->AddRawBlocks(2, data.data(), data.size());
62     writer->AddLabel(1);
63     writer->AddXorBlocks(50, data.data(), data.size(), 24, 10);
64     writer->AddZeroBlocks(5, 10);
65     writer->AddLabel(2);
66     writer->Finalize();
67 }
68 
WriteCow(const std::string & path)69 static bool WriteCow(const std::string& path) {
70     android::base::unique_fd fd(open(path.c_str(), O_RDONLY));
71     fd.reset(open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0664));
72     if (fd < 0) {
73         PLOG(ERROR) << "could not open " << path << " for writing";
74         return false;
75     }
76     CowOptions options;
77     std::string data = "This is some data, believe it";
78     data.resize(options.block_size, '\0');
79 
80     std::unique_ptr<ICowWriter> writer =
81             CreateCowWriter(FLAGS_writer_version, options, std::move(fd));
82     if (!writer) {
83         return false;
84     }
85 
86     writer->AddCopy(0, 5);
87     writer->AddRawBlocks(2, data.data(), data.size());
88     writer->AddLabel(1);
89     writer->AddXorBlocks(50, data.data(), data.size(), 24, 10);
90     writer->AddZeroBlocks(5, 10);
91     writer->AddLabel(2);
92     writer->Finalize();
93 
94     if (!FLAGS_silent) {
95         std::cout << "Writing COW with writer v" << FLAGS_writer_version << "\n";
96     }
97 
98     return true;
99 }
100 
main(int argc,char ** argv)101 int main(int argc, char** argv) {
102     gflags::ParseCommandLineFlags(&argc, &argv, true);
103     if (FLAGS_write_legacy) {
104         write_legacy_cow_v2();
105         return 0;
106     }
107     if (argc < 2) {
108         gflags::ShowUsageWithFlags(argv[0]);
109         return 1;
110     }
111     if (!WriteCow(argv[1])) {
112         return 1;
113     }
114 }
115