blob: f39908ebd1c7f3e7481fd6c227006b4dbd41f776 [file] [log] [blame]
François Degrosd6a775f2020-02-05 15:05:21 +11001// Copyright 2020 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
Sergei Datsenkoc9904bb2020-12-11 12:46:02 +11005#ifndef CROS_DISKS_RAR_MOUNTER_H_
6#define CROS_DISKS_RAR_MOUNTER_H_
François Degrosd6a775f2020-02-05 15:05:21 +11007
8#include <memory>
9#include <string>
10#include <vector>
11
12#include <base/strings/string_piece.h>
13#include <gtest/gtest_prod.h>
14
Sergei Datsenkoc9904bb2020-12-11 12:46:02 +110015#include "cros-disks/archive_mounter.h"
François Degrosd6a775f2020-02-05 15:05:21 +110016#include "cros-disks/fuse_mounter.h"
François Degrosd6a775f2020-02-05 15:05:21 +110017
18namespace cros_disks {
19
Sergei Datsenkoc9904bb2020-12-11 12:46:02 +110020// An ArchiveMounter with handling of RAR multipart archives.
21class RarMounter : public ArchiveMounter {
François Degrosd6a775f2020-02-05 15:05:21 +110022 public:
Sergei Datsenkoc9904bb2020-12-11 12:46:02 +110023 RarMounter(const Platform* platform,
24 brillo::ProcessReaper* process_reaper,
Sergei Datsenko1d2cbf82020-12-08 21:54:42 +110025 Metrics* metrics,
Sergei Datsenkoc9904bb2020-12-11 12:46:02 +110026 std::unique_ptr<SandboxedProcessFactory> sandbox_factory);
27 RarMounter(const RarMounter&) = delete;
28 RarMounter& operator=(const RarMounter&) = delete;
François Degrosd6a775f2020-02-05 15:05:21 +110029
Sergei Datsenkoc9904bb2020-12-11 12:46:02 +110030 ~RarMounter() override;
31
32 protected:
33 MountErrorType FormatInvocationCommand(
34 const base::FilePath& archive,
35 std::vector<std::string> params,
36 SandboxedProcess* sandbox) const override;
François Degrosd6a775f2020-02-05 15:05:21 +110037
38 private:
François Degros02e81492020-02-05 16:37:19 +110039 // Increments a sequence of digits or letters [begin, end). Returns true if
40 // success, and false in case of overflow.
41 static bool Increment(std::string::iterator begin, std::string::iterator end);
42
43 // A semi-open index range [begin, end).
44 struct IndexRange {
45 size_t begin, end;
46
47 bool empty() const { return begin == end; }
48 size_t size() const { return end - begin; }
49
50 // Friend operators for testing, logging and debugging.
51 friend std::ostream& operator<<(std::ostream& out, const IndexRange& r) {
52 return out << "{ begin: " << r.begin << ", end: " << r.end << " }";
53 }
54
55 friend bool operator==(const IndexRange& a, const IndexRange& b) {
56 return a.begin == b.begin && a.end == b.end;
57 }
58 };
59
60 // Checks if the given path ends with ".partNNNN.rar", which is the new
61 // naming pattern for multipart archives. Returns the range of characters
62 // forming the numeric part NNNN if path matches the pattern, or an empty
63 // range otherwise.
64 static IndexRange ParseDigits(base::StringPiece path);
65
66 // Adds bind paths using old naming scheme.
Sergei Datsenko1d2cbf82020-12-08 21:54:42 +110067 void AddPathsWithOldNamingScheme(std::vector<std::string>* bind_paths,
François Degrosa28315e2020-07-13 00:24:48 +100068 base::StringPiece original_path) const;
François Degros02e81492020-02-05 16:37:19 +110069
70 // Adds bind paths using new naming scheme.
Sergei Datsenko1d2cbf82020-12-08 21:54:42 +110071 void AddPathsWithNewNamingScheme(std::vector<std::string>* bind_paths,
François Degrosa28315e2020-07-13 00:24:48 +100072 base::StringPiece original_path,
73 const IndexRange& digits) const;
François Degros02e81492020-02-05 16:37:19 +110074
François Degrosd6a775f2020-02-05 15:05:21 +110075 // Prepares the bind paths for the given RAR file path.
François Degros02e81492020-02-05 16:37:19 +110076 //
77 // If the given path is considered to be part of a multipart archive, this
78 // function tries to find all the related files.
79 //
80 // Two different naming schemes are supported.
81 //
82 // The old naming scheme is:
83 //
84 // basename.rar
85 // basename.r00
86 // basename.r01
87 // ...
88 // basename.r99
89 // basename.s00
90 // basename.s01
91 // ...
92 //
93 //
94 // The new naming scheme is:
95 //
François Degros97f6a0d2020-08-24 15:58:30 +100096 // basename1.rar
97 // basename2.rar
François Degros02e81492020-02-05 16:37:19 +110098 // ...
François Degros97f6a0d2020-08-24 15:58:30 +100099 // basename9.rar
François Degros02e81492020-02-05 16:37:19 +1100100 //
101 // or
102 //
François Degros97f6a0d2020-08-24 15:58:30 +1000103 // basename01.rar
104 // basename02.rar
François Degros02e81492020-02-05 16:37:19 +1100105 // ...
François Degros97f6a0d2020-08-24 15:58:30 +1000106 // basename99.rar
François Degros02e81492020-02-05 16:37:19 +1100107 //
108 // or
109 //
François Degros97f6a0d2020-08-24 15:58:30 +1000110 // basename001.rar
111 // basename002.rar
François Degros02e81492020-02-05 16:37:19 +1100112 // ...
François Degros97f6a0d2020-08-24 15:58:30 +1000113 // basename999.rar
François Degros02e81492020-02-05 16:37:19 +1100114 // etc.
Sergei Datsenko1d2cbf82020-12-08 21:54:42 +1100115 std::vector<std::string> GetBindPaths(base::StringPiece original_path) const;
116
Sergei Datsenkoc9904bb2020-12-11 12:46:02 +1100117 FRIEND_TEST(RarMounterTest, Increment);
118 FRIEND_TEST(RarMounterTest, ParseDigits);
119 FRIEND_TEST(RarMounterTest, GetBindPathsWithOldNamingScheme);
120 FRIEND_TEST(RarMounterTest, GetBindPathsWithNewNamingScheme);
121 FRIEND_TEST(RarMounterTest, GetBindPathsStopsOnOverflow);
François Degrosd6a775f2020-02-05 15:05:21 +1100122};
123
124} // namespace cros_disks
125
Sergei Datsenkoc9904bb2020-12-11 12:46:02 +1100126#endif // CROS_DISKS_RAR_MOUNTER_H_