arc: Reintroduce the output file option
-o argument was previously removed in favor of new api and consent dialog but now it is being reintroduced to go along with limited mode dumpstate logs that do not require user consent. This argument is effective only during limited mode but we do not throw an error if supplied with other arguemnts for backwards compatibility reasons. Bug: 142684959 Bug: 136273873 Bug: 139379357 Bug: 138805202 Bug: 142685922 Test: adb bugreport Test: adb bugreport xyz.zip Test: adb shell bugreport Test: atest dumpstate_test Test: flash android to dut, android-sh, setenforce 1, arc-bugreport Change-Id: Ib2cadf13c101dd2e957033a7657a647d043f2b72
This commit is contained in:
parent
d451a47124
commit
2d75c44e61
3 changed files with 52 additions and 6 deletions
|
@ -209,6 +209,10 @@ static int Open(std::string path, int flags, mode_t mode = 0) {
|
|||
return fd;
|
||||
}
|
||||
|
||||
static int OpenForWrite(std::string path) {
|
||||
return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
}
|
||||
|
||||
static int OpenForRead(std::string path) {
|
||||
return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
|
||||
|
@ -274,6 +278,27 @@ int64_t GetModuleMetadataVersion() {
|
|||
return version_code;
|
||||
}
|
||||
|
||||
static bool PathExists(const std::string& path) {
|
||||
struct stat sb;
|
||||
return stat(path.c_str(), &sb) == 0;
|
||||
}
|
||||
|
||||
static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
|
||||
if (input_file == output_file) {
|
||||
MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
|
||||
output_file.c_str());
|
||||
return false;
|
||||
}
|
||||
else if (PathExists(output_file)) {
|
||||
MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
|
||||
android::base::unique_fd out_fd(OpenForWrite(output_file));
|
||||
return CopyFileToFd(input_file, out_fd.get());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace os
|
||||
} // namespace android
|
||||
|
@ -2092,11 +2117,12 @@ void Dumpstate::DumpstateBoard() {
|
|||
|
||||
static void ShowUsage() {
|
||||
fprintf(stderr,
|
||||
"usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-d] [-p] "
|
||||
"usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-d] [-p] "
|
||||
"[-z] [-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
|
||||
" -h: display this help message\n"
|
||||
" -b: play sound file instead of vibrate, at beginning of job\n"
|
||||
" -e: play sound file instead of vibrate, at end of job\n"
|
||||
" -o: write to custom directory (only in limited mode)\n"
|
||||
" -d: append date to filename\n"
|
||||
" -p: capture screenshot to filename.png\n"
|
||||
" -z: generate zipped file\n"
|
||||
|
@ -2267,6 +2293,14 @@ static void FinalizeFile() {
|
|||
do_text_file = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string final_path = ds.path_;
|
||||
if (ds.options_->OutputToCustomFile()) {
|
||||
std::string bugreport_dir = dirname(ds.options_->use_outfile.c_str());
|
||||
final_path = ds.GetPath(bugreport_dir, ".zip");
|
||||
android::os::CopyFileToFile(ds.path_, final_path);
|
||||
}
|
||||
|
||||
if (ds.options_->use_control_socket) {
|
||||
if (do_text_file) {
|
||||
dprintf(ds.control_socket_fd_,
|
||||
|
@ -2274,7 +2308,7 @@ static void FinalizeFile() {
|
|||
"for more details\n",
|
||||
ds.log_path_.c_str());
|
||||
} else {
|
||||
dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
|
||||
dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2384,6 +2418,7 @@ Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[])
|
|||
// clang-format off
|
||||
case 'd': do_add_date = true; break;
|
||||
case 'z': do_zip_file = true; break;
|
||||
case 'o': use_outfile = optarg; break;
|
||||
case 's': use_socket = true; break;
|
||||
case 'S': use_control_socket = true; break;
|
||||
case 'v': show_header_only = true; break;
|
||||
|
@ -2505,8 +2540,8 @@ void Dumpstate::Cancel() {
|
|||
* If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
|
||||
* gets added to the archive.
|
||||
*
|
||||
* Bugreports are first generated in a local directory and later copied to the caller's fd if
|
||||
* supplied.
|
||||
* Bugreports are first generated in a local directory and later copied to the caller's fd
|
||||
* or directory if supplied.
|
||||
*/
|
||||
Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
|
||||
const std::string& calling_package) {
|
||||
|
|
|
@ -386,10 +386,12 @@ class Dumpstate {
|
|||
// The HAL is actually an API surface that can be validated, while the AIDL is not (@hide).
|
||||
::android::hardware::dumpstate::V1_1::DumpstateMode dumpstate_hal_mode =
|
||||
::android::hardware::dumpstate::V1_1::DumpstateMode::DEFAULT;
|
||||
// File descriptor to output zip file.
|
||||
// File descriptor to output zip file. Takes precedence over use_outfile..
|
||||
android::base::unique_fd bugreport_fd;
|
||||
// File descriptor to screenshot file.
|
||||
android::base::unique_fd screenshot_fd;
|
||||
// Partial path to output file.
|
||||
std::string use_outfile;
|
||||
// Bugreport mode of the bugreport.
|
||||
std::string bugreport_mode;
|
||||
// Command-line arguments as string
|
||||
|
@ -415,6 +417,12 @@ class Dumpstate {
|
|||
// specified, it is preferred. If not bugreport is written to /bugreports.
|
||||
return !use_socket;
|
||||
}
|
||||
|
||||
/* Returns if options specified require writing to custom file location */
|
||||
bool OutputToCustomFile() {
|
||||
// Custom location is only honored in limited mode.
|
||||
return limited_only && !use_outfile.empty() && bugreport_fd.get() == -1;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: initialize fields on constructor
|
||||
|
|
|
@ -172,6 +172,7 @@ TEST_F(DumpOptionsTest, InitializeNone) {
|
|||
|
||||
EXPECT_FALSE(options_.do_add_date);
|
||||
EXPECT_FALSE(options_.do_zip_file);
|
||||
EXPECT_EQ("", options_.use_outfile);
|
||||
EXPECT_FALSE(options_.use_socket);
|
||||
EXPECT_FALSE(options_.use_control_socket);
|
||||
EXPECT_FALSE(options_.show_header_only);
|
||||
|
@ -352,7 +353,8 @@ TEST_F(DumpOptionsTest, InitializeLimitedOnlyBugreport) {
|
|||
const_cast<char*>("-d"),
|
||||
const_cast<char*>("-z"),
|
||||
const_cast<char*>("-q"),
|
||||
const_cast<char*>("-L")
|
||||
const_cast<char*>("-L"),
|
||||
const_cast<char*>("-o abc")
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
@ -364,6 +366,7 @@ TEST_F(DumpOptionsTest, InitializeLimitedOnlyBugreport) {
|
|||
EXPECT_TRUE(options_.use_control_socket);
|
||||
EXPECT_FALSE(options_.do_vibrate);
|
||||
EXPECT_TRUE(options_.limited_only);
|
||||
EXPECT_EQ(" abc", std::string(options_.use_outfile));
|
||||
|
||||
// Other options retain default values
|
||||
EXPECT_FALSE(options_.show_header_only);
|
||||
|
|
Loading…
Reference in a new issue