mirror of
https://github.com/openharmony/third_party_gptfdisk.git
synced 2026-07-01 13:17:25 -04:00
!50 merge master into master
Add ohos fixparts func
Created-by: jiangqianrong
Commit-by: jiangqianrong
Merged-by: openharmony_ci
Description: ### 一、内容说明(相关的Issue)
### 二、建议测试周期和提测地址
建议测试完成时间:xxxx.xx.xx
投产上线时间:xxxx.xx.xx
提测地址:CI环境/压测环境
测试账号:
### 三、变更内容
* 3.1 关联PR列表
* 3.2 数据库和部署说明
1. 常规更新
2. 重启unicorn
3. 重启sidekiq
4. 迁移任务:是否有迁移任务,没有写 "无"
5. rake脚本:`bundle exec xxx RAILS_ENV = production`;没有写 "无"
* 3.4 其他技术优化内容(做了什么,变更了什么)
- 重构了 xxxx 代码
- xxxx 算法优化
* 3.5 废弃通知(什么字段、方法弃用?)
* 3.6 后向不兼容变更(是否有无法向后兼容的变更?)
### 四、研发自测点(自测哪些?冒烟用例全部自测?)
自测测试结论:
### 五、测试关注点(需要提醒QA重点关注的、可能会忽略的地方)
检查点:
| 需求名称 | 是否影响xx公共模块 | 是否需要xx功能 | 需求升级是否依赖其他子产品 |
|------|------------|----------|---------------|
| xxx | 否 | 需要 | 不需要 |
| | | | |
接口测试:
性能测试:
并发测试:
其他:
See merge request: openharmony/third_party_gptfdisk!50
This commit is contained in:
@@ -47,3 +47,34 @@ ohos_executable("sgdisk") {
|
||||
part_name = "gptfdisk"
|
||||
install_images = [ "system" ]
|
||||
}
|
||||
|
||||
ohos_executable("ohos_fixparts") {
|
||||
install_enable = true
|
||||
|
||||
sources = [
|
||||
"ohos/ohos_fixparts.cpp",
|
||||
"ohos/ohos_mbr_helper.cpp",
|
||||
]
|
||||
|
||||
sources += [
|
||||
"basicmbr.cc",
|
||||
"crc32.cc",
|
||||
"diskio-unix.cc",
|
||||
"diskio.cc",
|
||||
"mbrpart.cc",
|
||||
"support.cc",
|
||||
]
|
||||
|
||||
include_dirs = [
|
||||
".",
|
||||
"//third_party/gptfdisk/",
|
||||
]
|
||||
|
||||
public_configs = [ ":gptdisk_config" ]
|
||||
|
||||
external_deps = [ "e2fsprogs:libext2_uuid" ]
|
||||
|
||||
subsystem_name = "thirdparty"
|
||||
part_name = "gptfdisk"
|
||||
install_images = [ "system" ]
|
||||
}
|
||||
|
||||
+6
-1
@@ -31,10 +31,15 @@
|
||||
"third_party": []
|
||||
},
|
||||
"build": {
|
||||
"sub_component": [],
|
||||
"sub_component": [
|
||||
"//third_party/gptfdisk:ohos_fixparts"
|
||||
],
|
||||
"inner_kits": [
|
||||
{
|
||||
"name": "//third_party/gptfdisk:sgdisk"
|
||||
},
|
||||
{
|
||||
"name": "//third_party/gptfdisk:ohos_fixparts"
|
||||
}
|
||||
],
|
||||
"test": []
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "ohos_fixparts.h"
|
||||
#include "basicmbr.h"
|
||||
#include "support.h"
|
||||
#include <cstring>
|
||||
#include <getopt.h>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <unistd.h>
|
||||
|
||||
OhosFixparts::OhosFixparts() {}
|
||||
|
||||
OhosFixparts::~OhosFixparts() {}
|
||||
|
||||
MbrResult OhosFixparts::ParseArgs(int argc, char *argv[], OhosFixpartsArgs &args)
|
||||
{
|
||||
int opt;
|
||||
int option_index = 0;
|
||||
int typecodeCount = 0; // Count of -t options
|
||||
|
||||
static struct option long_options[] = {{"print", no_argument, nullptr, 'p'},
|
||||
{"typecode", required_argument, nullptr, 't'},
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{nullptr, 0, nullptr, 0}};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "pt:h", long_options, &option_index)) != -1) {
|
||||
switch (opt) {
|
||||
case 'p':
|
||||
args.printMBR = true;
|
||||
break;
|
||||
case 't': {
|
||||
typecodeCount++;
|
||||
if (typecodeCount > 1) {
|
||||
std::cerr << "Error: Only one -t option is supported" << std::endl;
|
||||
ShowHelp(argv[0]);
|
||||
return MbrResult::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
MbrResult result = ParseOption(optarg, args.partitionNum, args.typeCode);
|
||||
if (result != MbrResult::SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
args.hasTypeCode = true;
|
||||
break;
|
||||
}
|
||||
case 'h':
|
||||
args.showHelp = true;
|
||||
ShowHelp(argv[0]);
|
||||
return MbrResult::SUCCESS;
|
||||
default:
|
||||
ShowHelp(argv[0]);
|
||||
return MbrResult::ERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse device path (remaining argument)
|
||||
if (optind < argc) {
|
||||
args.device = argv[optind];
|
||||
}
|
||||
|
||||
// Validate device path
|
||||
if (args.device.empty()) {
|
||||
std::cerr << "Device path is required" << std::endl;
|
||||
ShowHelp(argv[0]);
|
||||
return MbrResult::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return MbrResult::SUCCESS;
|
||||
}
|
||||
|
||||
MbrResult OhosFixparts::ParseOption(const std::string &option, int &partitionNum, uint8_t &typeCode)
|
||||
{
|
||||
// Parse partition number and type code
|
||||
std::string paramStr = option;
|
||||
size_t colonPos = paramStr.find(':');
|
||||
|
||||
if (colonPos == std::string::npos || colonPos == 0 || colonPos == paramStr.length() - 1) {
|
||||
std::cerr << "Invalid option format (expected partnum:typecode): " << option.c_str() << std::endl;
|
||||
return MbrResult::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
std::string partNumStr = paramStr.substr(0, colonPos);
|
||||
std::string typeCodeStr = paramStr.substr(colonPos + 1);
|
||||
|
||||
MbrResult result = ParsePartNum(partNumStr, partitionNum);
|
||||
if (result != MbrResult::SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Validate and parse type code
|
||||
if (!ParseTypeCode(typeCodeStr, typeCode)) {
|
||||
return MbrResult::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return MbrResult::SUCCESS;
|
||||
}
|
||||
|
||||
MbrResult OhosFixparts::ParsePartNum(const std::string &str, int &partitionNum)
|
||||
{
|
||||
// Validate partition number - manual validation without exceptions
|
||||
if (str.empty()) {
|
||||
std::cerr << "Invalid partition number: empty string" << std::endl;
|
||||
return MbrResult::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
// Check if all characters are digits
|
||||
for (char c : str) {
|
||||
if (!isdigit(c)) {
|
||||
std::cerr << "Invalid partition number (must be a pure number): " << c << std::endl;
|
||||
return MbrResult::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to integer (safe because we validated all characters are digits)
|
||||
std::istringstream iss(str);
|
||||
iss >> partitionNum;
|
||||
|
||||
if (iss.fail() || !iss.eof()) {
|
||||
std::cerr << "Parse partNum fail: fail=" << iss.fail() << ", eof=" << iss.eof() << ", str: " << str.c_str()
|
||||
<< std::endl;
|
||||
return MbrResult::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (partitionNum < MIN_MBR_PARTS || partitionNum > MAX_MBR_PARTS) {
|
||||
std::cerr << "Invalid partition number (must be 1-128): " << str.c_str() << std::endl;
|
||||
return MbrResult::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return MbrResult::SUCCESS;
|
||||
}
|
||||
|
||||
bool OhosFixparts::ParseTypeCode(const std::string &str, uint8_t &code)
|
||||
{
|
||||
unsigned int value = 0;
|
||||
|
||||
if (!IsHex(str)) {
|
||||
std::cerr << "Invalid hex format: " << str.c_str() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse hex value using std::istringstream (type-safe, no sscanf)
|
||||
std::istringstream iss(str);
|
||||
iss >> std::hex >> value;
|
||||
|
||||
if (iss.fail() || !iss.eof()) {
|
||||
std::cerr << "Parse typecode fail: fail=" << iss.fail() << ", eof=" << iss.eof() << ", str: " << str.c_str()
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate range before conversion to prevent truncation
|
||||
if (value < MIN_TYPE_CODE || value > MAX_TYPE_CODE) {
|
||||
std::cerr << "Invalid type code (must be 0x01-0xFF): 0x" << std::hex << value << std::dec << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
code = static_cast<uint8_t>(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
int OhosFixparts::Run(const OhosFixpartsArgs &args)
|
||||
{
|
||||
MbrResult result = helper_.LoadMbrData(args.device);
|
||||
if (result != MbrResult::SUCCESS) {
|
||||
return static_cast<int>(result);
|
||||
}
|
||||
|
||||
// Print mode: display MBR partition table
|
||||
if (args.printMBR) {
|
||||
helper_.DisplayMBRData();
|
||||
}
|
||||
|
||||
// Modify mode: change partition type code
|
||||
if (args.hasTypeCode) {
|
||||
std::cout << "Changing partition " << args.partitionNum << " type code to 0x" << std::hex
|
||||
<< static_cast<int>(args.typeCode) << std::dec << std::endl;
|
||||
|
||||
result = helper_.ChangePartitionType(args.partitionNum, args.typeCode);
|
||||
if (result != MbrResult::SUCCESS) {
|
||||
return static_cast<int>(result);
|
||||
}
|
||||
|
||||
result = helper_.SaveMbrData();
|
||||
if (result != MbrResult::SUCCESS) {
|
||||
return static_cast<int>(result);
|
||||
}
|
||||
|
||||
std::cout << "Partition type code changed successfully." << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OhosFixparts::ShowHelp(const char *programName)
|
||||
{
|
||||
std::cout << "Usage : " << programName << " [OPTION...] <device>" << std::endl;
|
||||
std::cout << " -p, --print Print MBR partition table" << std::endl;
|
||||
std::cout << " -t partnum:typecode Change partition type code" << std::endl;
|
||||
std::cout << " -h, --help Show this help message" << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
OhosFixparts fixparts;
|
||||
OhosFixpartsArgs args;
|
||||
|
||||
MbrResult result = fixparts.ParseArgs(argc, argv, args);
|
||||
if (result != MbrResult::SUCCESS) {
|
||||
return static_cast<int>(result);
|
||||
}
|
||||
|
||||
// If help was requested, exit successfully
|
||||
if (args.showHelp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fixparts.Run(args);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef OHOS_FIXPARTS_H
|
||||
#define OHOS_FIXPARTS_H
|
||||
|
||||
#include "ohos_mbr_helper.h"
|
||||
#include <string>
|
||||
|
||||
// Command line arguments structure
|
||||
struct OhosFixpartsArgs {
|
||||
std::string device; // Device path
|
||||
bool printMBR; // Print MBR partition table
|
||||
bool showHelp; // Show help information
|
||||
bool hasTypeCode; // Flag to indicate if -t option is present
|
||||
int partitionNum; // Partition number
|
||||
uint8_t typeCode; // Type code
|
||||
|
||||
OhosFixpartsArgs() : printMBR(false), showHelp(false), hasTypeCode(false), partitionNum(-1), typeCode(0) {}
|
||||
};
|
||||
|
||||
// Main program class
|
||||
class OhosFixparts {
|
||||
public:
|
||||
OhosFixparts();
|
||||
~OhosFixparts();
|
||||
|
||||
// Parse command line arguments
|
||||
MbrResult ParseArgs(int argc, char *argv[], OhosFixpartsArgs &args);
|
||||
|
||||
// Execute partition type code modification
|
||||
int Run(const OhosFixpartsArgs &args);
|
||||
|
||||
// Show help information
|
||||
void ShowHelp(const char *programName);
|
||||
|
||||
private:
|
||||
OhosMbrHelper helper_;
|
||||
|
||||
// Parse hexadecimal type code
|
||||
bool ParseTypeCode(const std::string &str, uint8_t &code);
|
||||
|
||||
// Parse partnumber
|
||||
MbrResult ParsePartNum(const std::string &str, int &partitionNum);
|
||||
|
||||
// Parse option string (format: partnum:typecode) and validate all parameters
|
||||
MbrResult ParseOption(const std::string &option, int &partitionNum, uint8_t &typeCode);
|
||||
};
|
||||
|
||||
#endif // OHOS_FIXPARTS_H
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "ohos_mbr_helper.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
OhosMbrHelper::OhosMbrHelper() : mbrData_(nullptr), device_(""), loaded_(false)
|
||||
{
|
||||
mbrData_ = new (std::nothrow) BasicMBRData();
|
||||
if (mbrData_ == nullptr) {
|
||||
std::cerr << "Failed to allocate memory for MBR data" << std::endl;
|
||||
loaded_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
OhosMbrHelper::~OhosMbrHelper()
|
||||
{
|
||||
if (mbrData_ != nullptr) {
|
||||
delete mbrData_;
|
||||
mbrData_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
MbrResult OhosMbrHelper::LoadMbrData(const std::string &device)
|
||||
{
|
||||
// mbrData_ is initialized in constructor, no need to check here
|
||||
device_ = device;
|
||||
|
||||
MbrResult result = ReadMbrFromDevice();
|
||||
if (result != MbrResult::SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = ValidateMbrData();
|
||||
if (result != MbrResult::SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
mbrData_->MakeItLegal();
|
||||
loaded_ = true;
|
||||
|
||||
return MbrResult::SUCCESS;
|
||||
}
|
||||
|
||||
MbrResult OhosMbrHelper::ReadMbrFromDevice()
|
||||
{
|
||||
if (!mbrData_->ReadMBRData(device_)) {
|
||||
std::cerr << "Failed to read MBR data from device: " << device_ << std::endl;
|
||||
return MbrResult::ERROR_READ_FAILED;
|
||||
}
|
||||
|
||||
return MbrResult::SUCCESS;
|
||||
}
|
||||
|
||||
MbrResult OhosMbrHelper::ValidateMbrData()
|
||||
{
|
||||
MBRValidity validity = mbrData_->GetValidity();
|
||||
|
||||
if (validity == gpt || validity == hybrid) {
|
||||
std::cerr << "Device appears to be a GPT disk, not MBR" << std::endl;
|
||||
return MbrResult::ERROR_GPT_PART;
|
||||
}
|
||||
|
||||
if (validity == invalid) {
|
||||
std::cerr << "Invalid MBR data on device" << std::endl;
|
||||
return MbrResult::ERROR_NOT_SUPPORT_PART;
|
||||
}
|
||||
|
||||
return MbrResult::SUCCESS;
|
||||
}
|
||||
|
||||
MbrResult OhosMbrHelper::ChangePartitionType(int partNum, uint8_t typeCode)
|
||||
{
|
||||
// Check if MBR data is loaded
|
||||
if (!loaded_) {
|
||||
std::cerr << "MBR data not loaded. Call LoadMbrData() first." << std::endl;
|
||||
return MbrResult::ERROR_READ_FAILED;
|
||||
}
|
||||
|
||||
// Validate partition number range (1-128)
|
||||
if (partNum < MIN_MBR_PARTS || partNum > MAX_MBR_PARTS) {
|
||||
std::cerr << "Invalid partition number (must be 1-128): " << partNum << std::endl;
|
||||
return MbrResult::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
// Validate range before conversion to prevent truncation
|
||||
if (typeCode < MIN_TYPE_CODE || typeCode > MAX_TYPE_CODE) {
|
||||
std::cerr << "Invalid typecode (must be 0x01-0xFF): 0x" << std::hex << static_cast<int>(typeCode) << std::dec
|
||||
<< std::endl;
|
||||
return MbrResult::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
// Check if partition exists and is not empty
|
||||
if (mbrData_->GetLength(partNum - 1) == 0) {
|
||||
std::cerr << "Partition " << partNum << " is empty or does not exist" << std::endl;
|
||||
return MbrResult::ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
// Set partition type code
|
||||
int result = mbrData_->SetPartType(partNum - 1, typeCode);
|
||||
if (result == 0) {
|
||||
std::cerr << "Failed to set type code for partition: " << partNum << std::endl;
|
||||
return MbrResult::ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
return MbrResult::SUCCESS;
|
||||
}
|
||||
|
||||
MbrResult OhosMbrHelper::SaveMbrData()
|
||||
{
|
||||
if (!loaded_) {
|
||||
std::cerr << "MBR data not loaded. Call LoadMbrData() first." << std::endl;
|
||||
return MbrResult::ERROR_READ_FAILED;
|
||||
}
|
||||
|
||||
if (!mbrData_->WriteMBRData()) {
|
||||
std::cerr << "Failed to write MBR data to device: " << device_ << std::endl;
|
||||
return MbrResult::ERROR_WRITE_FAILED;
|
||||
}
|
||||
|
||||
mbrData_->DiskSync();
|
||||
return MbrResult::SUCCESS;
|
||||
}
|
||||
|
||||
void OhosMbrHelper::DisplayMBRData()
|
||||
{
|
||||
if (!loaded_) {
|
||||
std::cerr << "MBR data not loaded. Call LoadMbrData() first." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Reuse existing DisplayMBRData implementation from basicmbr.cc
|
||||
// This provides more comprehensive MBR information including disk size,
|
||||
// disk identifier, and detailed partition information
|
||||
mbrData_->DisplayMBRData();
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef OHOS_MBR_HELPER_H
|
||||
#define OHOS_MBR_HELPER_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "basicmbr.h"
|
||||
|
||||
// MBR operation result codes
|
||||
enum class MbrResult {
|
||||
SUCCESS = 0,
|
||||
ERROR_UNKNOWN = 1,
|
||||
ERROR_READ_FAILED = 2,
|
||||
ERROR_WRITE_FAILED = 3,
|
||||
ERROR_INVALID_ARGUMENT = 4,
|
||||
ERROR_NOT_SUPPORT_PART = 5,
|
||||
ERROR_GPT_PART = 6
|
||||
};
|
||||
|
||||
#define MIN_MBR_PARTS 1
|
||||
#define MIN_TYPE_CODE 0x01
|
||||
#define MAX_TYPE_CODE 0xFF
|
||||
|
||||
// MBR partition type code modifier class
|
||||
class OhosMbrHelper final {
|
||||
public:
|
||||
OhosMbrHelper();
|
||||
~OhosMbrHelper();
|
||||
|
||||
// Load MBR data
|
||||
MbrResult LoadMbrData(const std::string &device);
|
||||
|
||||
// Read MBR data from device
|
||||
MbrResult ReadMbrFromDevice();
|
||||
|
||||
// Validate MBR data
|
||||
MbrResult ValidateMbrData();
|
||||
|
||||
// Change partition type code
|
||||
// partNum: Partition number (1-128)
|
||||
// typeCode: Type code (0x01-0xFF)
|
||||
MbrResult ChangePartitionType(int partNum, uint8_t typeCode);
|
||||
|
||||
// Save MBR data to disk
|
||||
MbrResult SaveMbrData();
|
||||
|
||||
// Display MBR partition table
|
||||
void DisplayMBRData();
|
||||
|
||||
private:
|
||||
BasicMBRData *mbrData_; // MBR data object pointer (initialized in constructor)
|
||||
std::string device_;
|
||||
bool loaded_;
|
||||
};
|
||||
|
||||
#endif // OHOS_MBR_HELPER_H
|
||||
Reference in New Issue
Block a user