xref: /aosp_15_r20/external/sandboxed-api/contrib/libzip/example/main.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <fcntl.h>
16 #include <unistd.h>
17 
18 #include <cstdlib>
19 #include <fstream>
20 #include <iostream>
21 #include <string>
22 #include <vector>
23 
24 #include "absl/flags/flag.h"
25 #include "absl/flags/parse.h"
26 #include "absl/log/globals.h"
27 #include "absl/log/initialize.h"
28 #include "contrib/libzip/sandboxed.h"
29 #include "contrib/libzip/utils/utils_zip.h"
30 
31 ABSL_FLAG(bool, list, false, "list files");
32 ABSL_FLAG(std::string, unzip, "", "unzip");
33 ABSL_FLAG(std::string, add_file, "", "add file");
34 ABSL_FLAG(std::string, delete, "", "delete");
35 
ListFiles(LibZip & zip)36 absl::Status ListFiles(LibZip& zip) {
37   SAPI_ASSIGN_OR_RETURN(int64_t num, zip.GetNumberEntries());
38   for (uint64_t i = 0; i < num; i++) {
39     SAPI_ASSIGN_OR_RETURN(std::string name, zip.GetName(i));
40     std::cout << name << "\n";
41   }
42 
43   return absl::OkStatus();
44 }
45 
UnzipToStdout(LibZip & zip,const std::string & filename)46 absl::Status UnzipToStdout(LibZip& zip, const std::string& filename) {
47   SAPI_ASSIGN_OR_RETURN(std::vector<uint8_t> buf, zip.ReadFile(filename));
48 
49   std::cout << buf.data();
50 
51   return absl::OkStatus();
52 }
53 
AddFile(LibZip & zip,const std::string & filename)54 absl::Status AddFile(LibZip& zip, const std::string& filename) {
55   int fd = open(filename.c_str(), O_RDONLY);
56   if (fd < 0) {
57     return absl::UnavailableError(
58         absl::StrCat("Unable to open file ", filename));
59   }
60 
61   // The fd will be consumed
62   SAPI_ASSIGN_OR_RETURN(uint64_t index, zip.AddFile(filename, fd));
63 
64   return absl::OkStatus();
65 }
66 
DeleteFile(LibZip & zip,const std::string & filename)67 absl::Status DeleteFile(LibZip& zip, const std::string& filename) {
68   int64_t index = -1;
69 
70   SAPI_ASSIGN_OR_RETURN(int64_t num, zip.GetNumberEntries());
71   for (uint64_t i = 0; i < num; i++) {
72     SAPI_ASSIGN_OR_RETURN(std::string name, zip.GetName(i));
73     if (name == filename) {
74       index = i;
75       break;
76     }
77   }
78   if (index == -1) {
79     return absl::UnavailableError(
80         absl::StrCat("Unable to remove file ", filename));
81   }
82 
83   return zip.DeleteFile(index);
84 }
85 
main(int argc,char * argv[])86 int main(int argc, char* argv[]) {
87   std::string prog_name(argv[0]);
88   absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
89   std::vector<char*> args = absl::ParseCommandLine(argc, argv);
90   absl::InitializeLog();
91 
92   if (args.size() < 2 || args.size() > 3) {
93     std::cerr << "Usage:\n  " << prog_name << " ZIPFILE [OUTFILE]\n";
94     return EXIT_FAILURE;
95   }
96 
97   std::string filename(args[1]);
98   ZipSapiSandbox sandbox;
99   if (!sandbox.Init().ok()) {
100     std::cerr << "Unable to start sandbox\n";
101     return EXIT_FAILURE;
102   }
103 
104   LibZip zip(&sandbox, filename, 0);
105 
106   if (!zip.IsOpen()) {
107     std::cerr << "Unable to open file " << filename << "\n";
108     return EXIT_FAILURE;
109   }
110 
111   int outfd = -1;
112   if (args.size() == 3) {
113     outfd = open(args[2], O_WRONLY | O_CREAT);
114     if (outfd < 0) {
115       std::cerr << "Unable to open file " << args[2] << "\n";
116       return EXIT_FAILURE;
117     }
118   }
119 
120   bool needs_saving = false;
121   absl::Status status;
122   if (absl::GetFlag(FLAGS_list)) {
123     status = ListFiles(zip);
124   }
125   if (!absl::GetFlag(FLAGS_unzip).empty()) {
126     status = UnzipToStdout(zip, absl::GetFlag(FLAGS_unzip));
127   }
128   if (!absl::GetFlag(FLAGS_add_file).empty()) {
129     status = AddFile(zip, absl::GetFlag(FLAGS_add_file));
130     needs_saving = true;
131   }
132   if (!absl::GetFlag(FLAGS_delete).empty()) {
133     status = DeleteFile(zip, absl::GetFlag(FLAGS_delete));
134     needs_saving = true;
135   }
136 
137   if (!status.ok()) {
138     std::cerr << status << "\n";
139     return EXIT_FAILURE;
140   }
141 
142   status = zip.Finish();
143   if (!status.ok()) {
144     std::cerr << status << "\n";
145     return EXIT_FAILURE;
146   }
147 
148   if (needs_saving) {
149     if (outfd == -1) {
150       status = zip.Save();
151     } else {
152       status = zip.Save(outfd);
153     }
154     if (!status.ok()) {
155       std::cerr << status << "\n";
156       return EXIT_FAILURE;
157     }
158   }
159 
160   return EXIT_SUCCESS;
161 }
162