pmt: initial 2.9.1 update

This commit is contained in:
2024-10-02 21:37:57 +03:00
parent 82bd2939cd
commit 7259d451c4
459 changed files with 86355 additions and 2404 deletions

114
jni/PartitionManager/Debug.cpp Executable file
View File

@@ -0,0 +1,114 @@
/* By YZBruh */
/**
* Copyright 2024 Partition Manager
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define INC_MAIN_LIBS
#define INC_STRINGKEYS
#include <PartitionManager/PartitionManager.h>
using namespace PartitionManager;
/* it's prints standart logs */
void Functions::DisplayLog(LogLevel status, const char* _Nullable fmt, ...)
{
va_list args;
va_start(args, fmt);
switch (status)
{
case LOG_LEVEL_ERROR:
if (!Booleans::SilentEnabled)
{
fprintf(stderr, "%s: ", Strings::ExecutingName.c_str());
vfprintf(stderr, fmt, args);
}
exit(1);
break;
case LOG_LEVEL_WARN:
if (!Booleans::SilentEnabled)
{
fprintf(stdout, "%s: ", Display::UsingDispString->warn);
vfprintf(stdout, fmt, args);
}
break;
case LOG_LEVEL_FATAL:
if (!Booleans::SilentEnabled)
{
fprintf(stderr, "%s: ", Display::UsingDispString->fatal);
vfprintf(stderr, fmt, args);
}
abort();
break;
case LOG_LEVEL_DEBUG:
if (!Booleans::SilentEnabled)
vfprintf(stdout, fmt, args);
break;
}
va_end(args);
}
/* it's prints verbose logs */
void Functions::DisplayVerboseLog(LogLevel status, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
switch (status)
{
case LOG_LEVEL_ERROR:
if (Booleans::VerboseMode)
{
fprintf(stderr, "E:[stderr]: ");
vfprintf(stderr, fmt, args);
}
break;
case LOG_LEVEL_WARN:
if (Booleans::VerboseMode)
{
fprintf(stdout, "W:[stdout]: ");
vfprintf(stdout, fmt, args);
}
break;
case LOG_LEVEL_FATAL:
if (Booleans::VerboseMode)
{
fprintf(stderr, "F:[stderr]: ");
vfprintf(stderr, fmt, args);
abort();
}
break;
case LOG_LEVEL_DEBUG:
if (Booleans::VerboseMode)
{
fprintf(stdout, "D:[stdout]: ");
vfprintf(stdout, fmt, args);
}
break;
}
va_end(args);
}
/**
* Last error is taken from strerror by taking
* the contents of errno or taking a special entry
*/
char* strqerror(int errno_macro) { return strerror(errno_macro); }
/* end of code */

View File

@@ -0,0 +1,54 @@
/* By YZBruh */
/**
* Copyright 2024 Partition Manager
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define INC_MAIN_LIBS
#define INC_STAT
#include <PartitionManager/PartitionManager.h>
/**
* The target file is controlled by the stat function.
* Files, directories, links and blocks (disks) are for.
* If it is never found, it returns 1 value.
* If he finds 0 value is returned.
* If the desired type is not in -1 value is returned.
* If the search type is unknown, 3 value is returned
*/
int PartitionManager::Functions::GetState(const string& filepath, const string& stype)
{
static struct stat GetStat;
VLOGD("GetStat: checking `%s' with 'stat <sys/stat.h>'...\n", filepath.c_str());
if (stat(filepath.c_str(), &GetStat) != 0)
return 1;
if (stype == "dir")
return (S_ISDIR(GetStat.st_mode)) ? 0 : -1;
else if (stype == "file")
return (S_ISREG(GetStat.st_mode)) ? 0 : -1;
else if (stype == "blk")
return (S_ISBLK(GetStat.st_mode)) ? 0 : -1;
else if (stype == "link")
return (S_ISLNK(GetStat.st_mode)) ? 0 : -1;
else
return 3;
return 2;
}
/* end of code */

74
jni/PartitionManager/Help.cpp Executable file
View File

@@ -0,0 +1,74 @@
/* By YZBruh */
/*
* Copyright 2024 Partition Manager
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define INC_MAIN_LIBS
#define INC_STRINGKEYS
#define HELP
#include <PartitionManager/PartitionManager.h>
#include <PartitionManager/HelpFn.h>
using namespace PartitionManager;
struct langdb_docs* Display::UsingDocDispString = nullptr;
static void
prepare_langconf_docs(void)
{
if (Strings::CurrentLanguage == "en")
Display::UsingDocDispString = &Display::LangDocEn;
else if (Strings::CurrentLanguage == "tr")
Display::UsingDocDispString = &Display::LangDocTr;
}
void Functions::DisplayHelp(void)
{
VLOGD("DisplayHelp: Loading language for help messages... Calling prepare_langconf_docs() <local function>...\n");
prepare_langconf_docs();
VLOGD("DisplayHelp: Printing...\n");
LOGD("%s: %s %s\n", Display::UsingDocDispString->usage_docstr, Strings::ExecutingName.c_str(), Display::UsingDocDispString->docs_strs_l1);
LOGD(" %s: %s %s\n", Display::UsingDocDispString->or_str, Strings::ExecutingName.c_str(), Display::UsingDocDispString->docs_strs_l2);
LOGD(" %s: %s %s\n", Display::UsingDocDispString->or_str, Strings::ExecutingName.c_str(), Display::UsingDocDispString->docs_strs_l3);
LOGD(" %s: %s %s\n\n", Display::UsingDocDispString->or_str, Strings::ExecutingName.c_str(), Display::UsingDocDispString->docs_strs_l4);
LOGD("%s:\n", Display::UsingDocDispString->docs_strs_l5);
LOGD(" -l, --logical %s\n", Display::UsingDocDispString->docs_strs_l6);
LOGD(" -P, --search-path %s\n", Display::UsingDocDispString->docs_strs_l7);
LOGD(" -p, --list %s\n", Display::UsingDocDispString->docs_strs_l8);
LOGD(" -s, --silent %s\n", Display::UsingDocDispString->docs_strs_l9);
LOGD(" -f, --force %s\n", Display::UsingDocDispString->docs_strs_l10);
LOGD(" -V, --verbose %s\n", Display::UsingDocDispString->docs_strs_l11);
LOGD(" -S, --set-lang %s\n", Display::UsingDocDispString->docs_strs_l12);
LOGD(" -v, --version %s\n", Display::UsingDocDispString->docs_strs_l13);
LOGD(" --help %s\n\n", Display::UsingDocDispString->docs_strs_l14);
LOGD("%s:\n", Display::UsingDocDispString->docs_strs_l15);
LOGD(" --only-size %s\n", Display::UsingDocDispString->docs_strs_l16);
LOGD(" --as-byte %s\n", Display::UsingDocDispString->docs_strs_l17);
LOGD(" --as-kilobyte %s\n", Display::UsingDocDispString->docs_strs_l18);
LOGD(" --as-megabyte %s\n", Display::UsingDocDispString->docs_strs_l19);
LOGD(" --as-gigabyte %s\n\n", Display::UsingDocDispString->docs_strs_l20);
LOGD("%s:\n", Display::UsingDocDispString->docs_strs_l21);
LOGD(" %s backup boot_a -P /dev/block/platform/bootdevice/by-name\n", Strings::ExecutingName.c_str());
LOGD(" %s flash boot_a /sdcard/twrp/boot.img -c /dev/block/platform/bootdevice/by-name\n", Strings::ExecutingName.c_str());
LOGD(" %s format system_a ext4 --logical\n", Strings::ExecutingName.c_str());
LOGD(" %s -P /dev/block/platform/bootdevice/by-name --list\n", Strings::ExecutingName.c_str());
LOGD(" %s partition-size boot --as-byte\n", Strings::ExecutingName.c_str());
LOGD(" %s partition-size system --only-size --as-gigabyte --logical\n\n", Strings::ExecutingName.c_str());
LOGD("%s <t.me/ShawkTeam | Topics | pmt>\n", Display::UsingDocDispString->docs_strs_l22);
}
/* end of code */

View File

@@ -0,0 +1,183 @@
/* By YZBruh */
/**
* Copyright 2024 Partition Manager
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define INC_MAIN_LIBS
#define INC_DEBUGERS
#define INC_STAT
#define INC_STRINGKEYS
#include <PartitionManager/PartitionManager.h>
using namespace PartitionManager;
/* pmt's man doc file path on termux */
#define INTERNAL_STORAGE_DIR "/sdcard"
#define TERMUX_PMT_MANDOC "/data/data/com.termux/files/usr/share/man/man8/pmt.8.gz"
#define PMTLANG_CONF "/sdcard/.pmtlang.conf"
#define PMT_SW_POINT "/sdcard/.pmtlangsw"
struct langdb_general* Display::UsingDispString = nullptr;
static fstream langconf;
string supp_langs[] = {
"en",
"tr",
""
};
static bool
InternalStorageDirFound(void)
{
return (Functions::GetState(INTERNAL_STORAGE_DIR, "dir") == 0) ? true : false;
}
static bool
LanguageControl(const string& lang)
{
for (int i = 0; !supp_langs[i].empty(); i++)
{
if (lang == supp_langs[i])
return true;
}
return false;
}
bool Functions::LoadLanguage(void)
{
string lang_fpr = "en";
langconf.close();
VLOGD("LoadLanguage: checking install type...\n");
if (Functions::GetState(TERMUX_PMT_MANDOC) == 0)
Booleans::InstalledOnTermux = true;
VLOGD("LoadLanguage: checking internal storage dir: `%s'\n", INTERNAL_STORAGE_DIR);
if (!InternalStorageDirFound())
LOGE("PartitionManagerLoadLanguage: internal storage directory (`%s') not found or accessible.\n", INTERNAL_STORAGE_DIR);
VLOGD("LoadLanguage: trying to open `%s' with 'open <fstream>'\n", PMTLANG_CONF);
langconf.open(PMTLANG_CONF, ios::in | ios::out);
VLOGD("LoadLanguage: checking status: `%s'...\n", PMTLANG_CONF);
if (!langconf.is_open())
{
langconf.open(PMTLANG_CONF, ios::out | ios::trunc);
VLOGD("LoadLanguage: calling SetLanguage()...\n");
Functions::SetLanguage("en", 1);
Display::UsingDispString = &Display::LangEn;
Strings::CurrentLanguage = "en";
if (langconf.is_open())
langconf.close();
return true;
}
else
{
VLOGD("LoadLanguage: reading `%s'\n", PMTLANG_CONF);
while (getline(langconf, lang_fpr))
{
if (lang_fpr == "en")
goto SetEn;
else if (lang_fpr == "tr")
goto SetTr;
else
{
VLOGD("LoadLanguage: calling SetLanguage()\n");
Functions::SetLanguage("en", 1);
VLOGD("LoadLanguage: re-calling LoadLanguage()\n");
Functions::LoadLanguage();
return true;
}
}
if (!getline(langconf, lang_fpr))
{
VLOGD("LoadLanguage: calling SetLanguage()\n");
Functions::SetLanguage("en", 1);
VLOGD("LoadLanguage: re-calling LoadLanguage()\n");
Functions::LoadLanguage();
return true;
}
}
SetEn:
langconf.close();
Display::UsingDispString = &Display::LangEn;
Strings::CurrentLanguage = "en";
VLOGD("LoadLanguage: loaded \"en\"\n");
return true;
SetTr:
langconf.close();
Display::UsingDispString = &Display::LangTr;
Strings::CurrentLanguage = "tr";
VLOGD("LoadLanguage: loaded \"tr\"\n");
return true;
return false;
}
void Functions::SetLanguage(const string& lang, unsigned short null_conf_stat)
{
VLOGD("SetLanguage: checking speficed language (from input).\n");
if (!LanguageControl(lang))
LOGE("Unknown language: %s.\n", lang.c_str());
langconf.close();
VLOGD("SetLanguage: checking internal storage dir: `%s'\n", INTERNAL_STORAGE_DIR);
if (!InternalStorageDirFound())
LOGE("PartitionManagerSetLanguage: internal storage directory (`%s') not found or accessible.\n", INTERNAL_STORAGE_DIR);
VLOGD("SetLanguage: trying to open `%s' with 'open <fstream>'\n", PMTLANG_CONF);
langconf.open(PMTLANG_CONF, ios::out | ios::trunc);
if (!langconf.is_open())
LOGE("PartitionManagerLanguageTools: Cannot open/write config file!!!\n");
VLOGD("SetLanguage: write \"%s\" to `%s' with 'std <iostream>'\n", lang.c_str(), PMTLANG_CONF);
langconf << lang;
if (!langconf)
LOGE("PartitionManagerLanguageTools: Couldn't write config!!!\n");
else
langconf.close();
if (null_conf_stat != 1)
{
VLOGD("SetLanguage: generating dummy file `%s' with 'ofstream <fstream>'\n", PMT_SW_POINT);
ofstream sw_point(PMT_SW_POINT, ios::trunc);
if (sw_point.is_open())
sw_point.close();
}
}
bool Functions::CleanSWPoint(void)
{
if (Functions::GetState(PMT_SW_POINT) == 0)
{
VLOGD("CleanSWPoint: removing (force) `%s' with 'remove <unistd.h>'\n", PMT_SW_POINT);
remove(PMT_SW_POINT);
return true;
}
else
return false;
}
/* end of code */

View File

@@ -0,0 +1,248 @@
/* By YZBruh */
/**
* Copyright 2024 Partition Manager
*
* Licensed under the Apache License, Version 2.0 (the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define INC_MAIN_LIBS
#define INC_STRINGKEYS
#include <PartitionManager/PartitionManager.h>
namespace PartitionManager {
namespace Display {
struct langdb_general LangEn = {
.lang_by_s = "YZBruh & r0manas",
.language = "English",
.lang_prefix = "en",
.not_logical = "This device does not have logical partitions!",
.not_file = "is not a file.",
.not_dir = "is not a directory.",
.not_in_dev = "Nothing found in /dev. Use force mode to avoid this error.",
.not_open = "Couldn't open",
.not_block = "The specified partition is not recognized as a block device. Use force mode to avoid this error.",
.not_read = "Couldn't read",
.not_readdir = "Couldn't read directory",
.not_write = "Couldn't write",
.not_gen = "Couldn't generate",
.no_root = "Root access could not be detected! Please run this with root permissions.",
.expected_backup_arg = "Expected backup argument 2 (1 of them are not mandatory), retrieved",
.expected_flash_arg = "Expected flash argument 2, retrieved",
.expected_format_arg = "Expected format argument 2, retrieved",
.expected_partsz_arg = "Expacted partition-size argument 2, retrieved",
.missing_operand = "Missing operand",
.multiple_wiewers = "Multiple viewers can't be used on the same line.",
.symbol_rule = "When specifying arguments for an option, ensure they do not begin with '-'. Each argument must correspond correctly to its respective option.",
.req_part_name = "Partition name required.",
.part_not_found = "Partition not found! Maybe a logical partition?",
.unsupported_fs = "Formatter: unsupported filesystem",
.cannot_stat = "Cannot stat",
.ffile_more_part = "Flash file size exceeds partition capacity. Use force mode to avoid this error (not recommended, riscy!).",
.cannot_get_bsz = "Failed to retrieve partition block size.",
.format_fail = "Formatting failed! There is a possibility of data damage.",
.fail_get_psize = "Cannot get partition size",
.depr_backup_opt = "These options for the backup are unavailable.",
.depr_flash_opt = "These options for the flash are unavailable.",
.depr_format_opt = "These options for the format are unavailable.",
.depr_Vlicense_opt = "Deprecated because it was unnecessary.",
.depr_ch_list_opt = "Use -p argument for listing partitions.",
.depr_ch_sp_opt = "Use -P (--search-path) argument instead of -c (--context).",
.not_spec_opt = "Specify the necessary arguments, not option",
.some_spec = "You may have indicated options, but they don't work much unless you speficy a main transaction",
.logical_warn = "This device uses logical partitions.",
.ab_warn = "This device uses A/B partition style.",
.out_not_spec = "Output file name not specified. Using created name",
.no_found_on_process = "The file that was processed was not found. Something wen wrong...",
.please_rerun = "Please rerun the command.",
.part_disk_sz = "Partition (backup) size",
.flash_file_sz = "Flash file size",
.part_disk_sz_fail = "Failed to retrieve partition disk size.",
.flash_file_sz_fail = "Failed to retrieve flash file size.",
.unknown_opr = "Unknown operand",
.req_an_arg = "option requires an argument",
.list_of_general = "List of general partitions",
.list_of_logc = "List of logical partitions",
.success_backup = "Backup successful. Output",
.success_flash = "Flash successful",
.success_format = "Format successful",
.formatting = "Formatting",
.warn = "WARNING",
.fatal = "FATAL ERROR",
.is_requires_arg = "requires an argument",
.only_partsz_args = "Flags can be used only in partition size view were identified. But target not this",
.unknw_arg = "unknown option",
.switching_lang = "Switching language...",
.welcome = "language!",
.welcome_ = "Welcome to ",
.for_more = "for more information",
.s_and_v = "Silent and verbose mode cannot be used together!",
.try_h = "Try",
.usage_head = "Usage",
.depr_opt_str = "DEPRECATED OPTION",
.switched_opt_str = "SWITCHED OPTION",
.not_changed_opt = "not changed",
.compiler_str = "compiler",
.version_str = "version",
.bin_str = "binary",
.part_name = "Partition name",
.part_type = "Partition is dynamic",
.fs_str = "Filesystem",
.unknw_str = "unknown",
.by_str = "By",
.yes = "true",
.no = "false"
};
struct langdb_general LangTr = {
.lang_by_s = "YZBruh",
.language = "Türkçe",
.lang_prefix = "tr",
.not_logical = "Bu cihaz mantıksal (logical) bölümlere sahip değil!",
.not_file = "Bu bir dosya değil",
.not_dir = "Bu bir dizin değil",
.not_in_dev = "Bu bir şakamı? Bunun /dev dizini ile bir ilgisi yok (içermiyor). Bu hatayla karşılaşmak istemiyorsanız zorlama (force) modu kullanın.",
.not_open = "ılamıyor",
.not_block = "Belirtilen bölüm bir blok değil. Yani aslında bu bir bölüm bile değil (disk). Bu hatayı almak için şanslı olmak gerek..! Bu hatayla karşılaşmak istemiyorsanız zorlama (force) modu kullanın.",
.not_read = "Veri okunamıyor",
.not_readdir = "Dizin verisi okunamıyor",
.not_write = "Veri yazılamıyor",
.not_gen = "Oluşturulamıyor",
.no_root = "Root erişimi tespit edilemedi! Lütfen root erişimi ile çalıştırın.",
.expected_backup_arg = "Beklenen yedekleme argümanı 2 (bir tanesi zorunlu değil), alınan",
.expected_flash_arg = "Beklenen flaş argümanı 2, alınan",
.expected_format_arg = "Beklenen format argümanı 2, alınan",
.expected_partsz_arg = "Beklenen partition-size argümanı 1, alınan",
.missing_operand = "İşlem belirtilmedi",
.multiple_wiewers = "Birden fazla görüntüleme işlemi yapan fonksiyonlar bir arada kullanılamaz. Aynı anda sadece bir tanesi kullanılabilir.",
.symbol_rule = "Bir seçeneğin argümanını verirken argüman önüne '-' sembolü getirilemez. Sembolü kaldırın ve tekrar deneyin.",
.req_part_name = "Bölüm adı gereklidir.",
.part_not_found = "Bölüm bulunamadı! Belki mantıksal (logical) bir bölümdür?",
.unsupported_fs = "Formatlayıcı: desteklenmeyen dosya sistemi:",
.cannot_stat = "Durumu tespit edilemedi",
.ffile_more_part = "Flaşlanacak dosyanın boyutu mevcut bölüm boyutundan fazla. Bu hatayla karşılaşmak istemiyorsanız zorlama (force) modu kullanın (bunu yapmanız asla önerilmez).",
.cannot_get_bsz = "Bölüm blok boyutu tespit edilemedi!",
.format_fail = "Formatlama başarısız oldu. Bazı şeyler zarar görmüş olabilir!",
.fail_get_psize = "Bölüm boyutu alınamadı",
.depr_backup_opt = "Yedek için artık bu seçeneği kullanamazsınız.",
.depr_flash_opt = "Flaşlama için artık bu seçeneği kullanamazsınız.",
.depr_format_opt = "Formatlama için artıi bu seçeneği kullanamazsınız.",
.depr_Vlicense_opt = "Gereksiz seçeneklere bellek yok!",
.depr_ch_list_opt = "Listeleme için -p seçeneğini kullanabilirsiniz.",
.depr_ch_sp_opt = "Özel arama dizini belirtmek için -P (--search-path) seçeneğini kullanabilirsiniz.",
.logical_warn = "Bu cihaz mantıksal (logical) bölümlere sahip.",
.not_spec_opt = "Seçenek değil, şuan gerekli argümanları verin",
.some_spec = "Seçenek belirtmiş olabilirsiniz fakat, ana işlem belirtmedikçe pek işe yaramazlar",
.ab_warn = "Bu cihazın bazı bölümleri A/B kullanıyor.",
.out_not_spec = "Çıktı dosya adı belirtilmedi. Oluşturulan çıktı adı",
.no_found_on_process = "İşlenmekte olan dosya bulunamadı. Bir şeyler yanlış...",
.please_rerun = "Lütfen yeniden çalıştırın",
.part_disk_sz = "Bölümün (yedek) boyutu",
.flash_file_sz = "Flaşlanacak dosyanın boyutu",
.flash_file_sz_fail = "Uyarı: flaşlanacak dosyanın boyutu tespit edilemedi.",
.part_disk_sz_fail = "Uyarı: bölüm boyutunun boyutu tespit edilemedi.",
.unknown_opr = "Bilinmeyen işlem",
.req_an_arg = "bu seçenek argüman gerektirir",
.list_of_general = "Genel bölümlerin listesi",
.list_of_logc = "Mantıksal (logical) bölümlerin listesi",
.success_backup = "Başarılı. Çıktı",
.success_flash = "Başarılı.",
.success_format = "Formatlama başarılı",
.formatting = "Formatlanıyor",
.warn = "UYARI",
.fatal = "KRİTİK HATA",
.is_requires_arg = "bir argüman gereklidir",
.only_partsz_args = "Sadece bölüm boyutu görüntülemesinde kullanılabilecek bayraklar tespit edildi. Ama hedef bu değil",
.unknw_arg = "bilinmeyen seçenek",
.switching_lang = "Dil değiştiriliyor...",
.welcome = "diline hoş geldiniz!",
.welcome_ = NULL,
.for_more = "komutunu kullanabilirsiniz",
.s_and_v = "Sessiz ve ayrıntılı günlüklenme aynı anda kullanılamaz!",
.try_h = "Daha fazla bilgi",
.usage_head = "Kullanımı",
.depr_opt_str = "KALDIRILMIŞ SEÇENEK",
.switched_opt_str = "DEĞİŞTİRİLMİŞ SEÇENEK",
.not_changed_opt = "değiştirilmedi",
.compiler_str = "derleyicisi",
.version_str = "versiyon",
.bin_str = "yapı",
.part_name = "Bölüm adı",
.part_type = "Dinamik bölüm",
.fs_str = "Dosya sistemi",
.unknw_str = "bilinmeyen",
.by_str = "Çeviriyi yapan(lar):",
.yes = "evet",
.no = "hayır"
};
struct langdb_docs LangDocEn = {
.docs_strs_l1 = "[OPTIONS] backup PARTITION [OUTPUT] [OPTIONS]...",
.docs_strs_l2 = "[OPTIONS] flash PARTITION FILE [OPTIONS]...",
.docs_strs_l3 = "[OPTIONS] format PARTITION FILE_SYSTEM[ext/2/3/4] [OPTIONS]...",
.docs_strs_l4 = "[OPTIONS] partition-size PARTITION [OPTIONS]...",
.docs_strs_l5 = "Options",
.docs_strs_l6 = "It is meant to determine whether the target partition is logical.",
.docs_strs_l7 = "It is meant to specify a custom partition search path. Only normal partitions (default: /dev/block/by-name).",
.docs_strs_l8 = "List partitions.",
.docs_strs_l9 = "Information and warning messages are silenced in normal work.",
.docs_strs_l10 = "Force mode. Some things are ignored.",
.docs_strs_l11 = "Verbose mode. Print detailed informations etc.",
.docs_strs_l12 = "Set current language.",
.docs_strs_l13 = "See version.",
.docs_strs_l14 = "See this help message.",
.docs_strs_l15 = "partition-size flags",
.docs_strs_l16 = "Only the size is displayed, the partition name etc is not displayed.",
.docs_strs_l17 = "Display size as byte.",
.docs_strs_l18 = "Display size as kilobyte.",
.docs_strs_l19 = "Display size as megabyte.",
.docs_strs_l20 = "Display size as gigabyte.",
.docs_strs_l21 = "Examples",
.docs_strs_l22 = "Report bugs and suggestions to",
.or_str = "or",
.usage_docstr = "Usage"
};
struct langdb_docs LangDocTr = {
.docs_strs_l1 = "[SEÇENEKLER] backup BÖLÜM [ÇIKTI] [SEÇENEKLER]...",
.docs_strs_l2 = "[SEÇENEKLER] flash BÖLÜM DOSYA [SEÇENEKLER]...",
.docs_strs_l3 = "[SEÇENEKLER] format BÖLÜM DOSYA_SİSTEMİ[ext/2/3/4] [SEÇENEKLER]...",
.docs_strs_l4 = "[SEÇENEKLER] partition-size BÖLÜM [SEÇENEKLER]...",
.docs_strs_l5 = "Seçenekler",
.docs_strs_l6 = "Mantıksal (logical) bölüm ile işlem yapın.",
.docs_strs_l7 = "Özel bir bölüm arama dizini belirtin. Sadece normal bölümler içindir (Varsayılan: /dev/block/by-name).",
.docs_strs_l8 = "Bölümler listelenir.",
.docs_strs_l9 = "Bilgi ve uyarı mesajları susturulur.",
.docs_strs_l10 = "Zorlama modu. Bazı şeyler göz ardı edilir.",
.docs_strs_l11 = "Ayrıntılı bilgi modu. Daha fazla bilgi mesajı verilir.",
.docs_strs_l12 = "Mevcut dili ayarlayın.",
.docs_strs_l13 = "Sürümü görüntüleyin.",
.docs_strs_l14 = "Bu yardım mesajını görüntüleyin.",
.docs_strs_l15 = "partition-size bayrakları",
.docs_strs_l16 = "Boyut görüntülenirken bölüm adı vb gibi bilgiler verilmez, sadece boyut görüntülenir.",
.docs_strs_l17 = "Boyutu bayt olarak görüntüleyin.",
.docs_strs_l18 = "Boyutu kilobayt olarak görüntüleyin.",
.docs_strs_l19 = "Boyutu megabyte olarak görüntüleyin.",
.docs_strs_l20 = "Boyutu gigabayt olarak görüntüleyin.",
.docs_strs_l21 = "Örnekler",
.docs_strs_l22 = "Sorunları ve önerileri şuraya bildirin:",
.or_str = "yada",
.usage_docstr = "Kullanımı"
};
} /* namespace Display */
} /* namespace PartitionManager */
/* end of code */

View File

@@ -0,0 +1,140 @@
/* By YZBruh */
/**
* Copyright 2024 Partition Manager
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define INC_MAIN_LIBS
#define INC_DEBUGERS
#define INC_DIRENT
#define INC_STRINGKEYS
#include <PartitionManager/PartitionManager.h>
using namespace PartitionManager;
#define CUR_DEV_SP "/dev/block/by-name"
#define LGC_DEV_SP "/dev/block/mapper"
static DIR* Directory;
static int
ListDir(const string& TargetDir, const bool ListTargetDir = false)
{
static int count;
struct dirent **List;
bool ListParts = (ListTargetDir) ? true : false;
Directory = nullptr;
Directory = opendir(TargetDir.c_str());
if (ListParts)
{
count = scandir(TargetDir.c_str(), &List, nullptr, alphasort);
if (count < 0)
LOGE("%s: `%s': %s\n",
Display::UsingDispString->not_readdir,
TargetDir.c_str(),
strqerror());
for (int i = 0; i < count; i++)
{
if (List[i]->d_name[0] != '.'
&& strncmp(List[i]->d_name, "com.", 4) != 0
&& strcmp(List[i]->d_name, "by-uuid") != 0
&& strcmp(List[i]->d_name, "userdata") != 0)
LOGD(" - [ %-16s ]\n", List[i]->d_name);
free(List[i]);
}
free(List);
List = nullptr;
goto directory;
}
directory:
if (Directory != nullptr)
{
closedir(Directory);
return 0;
}
else
return -1;
return 2;
}
/* list existing partitions */
int Functions::ListPartitions(void)
{
VLOGD("ListPartitions: selecting search path...\n");
string AccessDir = (Booleans::UseCustomSearchPath) ? Strings::CustomSearchPath : CUR_DEV_SP;
VLOGD("ListPartitions: trying to access `%s'...\n", AccessDir.c_str());
if (ListDir(AccessDir) != 0)
{
if (!Booleans::ForceMode)
LOGE("%s: `%s': %s\n",
Display::UsingDispString->not_open,
AccessDir.c_str(),
strqerror());
else
return 1;
}
else
{
LOGD("%s:\n", Display::UsingDispString->list_of_general);
ListDir(AccessDir, true);
}
if (Booleans::UsesLogical)
{
VLOGD("ListPartitions: checking for listing `%s'...\n", LGC_DEV_SP);
if (ListDir(LGC_DEV_SP) != 0)
LOGE("%s: `%s': %s\n",
Display::UsingDispString->not_open,
LGC_DEV_SP,
strqerror());
else
{
LOGD("\n%s:\n", Display::UsingDispString->list_of_logc);
ListDir(LGC_DEV_SP, true);
}
}
VLOGD("ListPartitions: (if have) warnings are printed...\n");
if (Booleans::UsesLogical)
{
LOGD("\n");
LOGW("%s\n", Display::UsingDispString->logical_warn);
}
if (Booleans::UsesSlots)
{
if (!Booleans::UsesSlots)
LOGD("\n");
LOGW("%s\n", Display::UsingDispString->ab_warn);
}
return 0;
}
/* end of code */

View File

@@ -0,0 +1,833 @@
/* By YZBruh */
/**
* Copyright 2024 Partition Manager
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define INC_MAIN_LIBS
#define INC_DEBUGERS
#define INC_STAT
#define INC_LIBGEN
#define INC_STRINGKEYS
#define IS_MAIN
#include <PartitionManager/PartitionManager.h>
#include <PartitionManager/Deprecates.h>
#include <PartitionManager/HelpFn.h>
#include <PartitionManager/VersionFnVars.h>
#include <PartitionManager/PartSizeMacros.h>
/* add value to variables that are added globally and are not worth */
namespace PartitionManager {
namespace Strings {
string OutputName = "";
string CustomSearchPath = "";
string TargetPartition = "";
string TargetFlashFile = "";
string TargetFormatFS = "";
string PartitionType = "";
string ExecutingName = "";
string CurrentLanguage = "";
} /* namespace Strings */
namespace Booleans {
bool UseLogical = false;
bool UseCustomSearchPath = false;
bool UsesSlots = false;
bool UsesLogical = false;
bool OnlyViewSize = false;
bool SilentEnabled = false;
bool FlashMode = false;
bool BackupMode = false;
bool FormatMode = false;
bool PartSizeViewMode = false;
bool ForceMode = false;
bool VerboseMode = false;
bool InstalledOnTermux = false;
} /* namespace Booleans */
namespace Integers {
int PartSizeViewType = VIEW_AS_MIB;
} /* namespace Integers */
} /* namespace PartitionManager */
/* variable for use in control of '-' expression */
static string SymbolRule;
namespace PartitionManager {
namespace Functions {
/**
* He controls whether the '-' sign at
* the beginning of the given word
*/
static void
CheckOptSymbol(const string& Symbol)
{
if (!Symbol.empty())
{
if (strncmp(Symbol.c_str(), "-", 1) == 0)
LOGE("%s\n", SymbolRule.c_str());
}
}
static bool
ControlArg(const char* ArgvHolder)
{
if (ArgvHolder[0] != '-')
return true;
return false;
}
} /* namespace Functions */
} /* namespace PartitionManager */
static void
deprecated(const char opt, const char* deprecation_message, const char* opt_long = "ISNULL")
{
VLOGE("Deprecated Option: -%c (--%s). Printing error...\n", opt, opt_long);
DEPR_HANDLE(opt, opt_long, deprecation_message);
exit(1);
}
static void
PrSpInput(const string& sp)
{
PartitionManager::Booleans::UseCustomSearchPath = true;
PartitionManager::Strings::CustomSearchPath = sp;
PartitionManager::Functions::CheckOptSymbol(PartitionManager::Strings::CustomSearchPath);
}
using namespace PartitionManager;
class PartitionManagerBase {
protected:
char* BaseFunctionName = nullptr;
int StartCode = -1;
bool IsRequiredOnlyOneArg = false;
public:
void CallTargetBaseFunction(void)
{
VLOGD("CallTargetBaseFunction [class]: Start(%d)\n", StartCode);
Functions::Start(StartCode);
}
void GenericNumericalController(int searchOn, int total, const char* MissingArgMessage)
{
if (total <= searchOn)
{
VLOGE("ArgumentProcessor [class]: Missing argument total (for %s function).\n", BaseFunctionName);
LOGE("%s 0.\n", MissingArgMessage);
}
if (!IsRequiredOnlyOneArg)
{
if (total <= (searchOn + 1))
{
VLOGE("ArgumentProcessor [class]: Missing argument total (for %s function).\n", BaseFunctionName);
LOGE("%s 1.\n", MissingArgMessage);
}
}
}
virtual void ArgumentProcessor(int searchOn, int total, char** arguments) { /* dummy */ }
};
class PartitionManagerBackup : public PartitionManagerBase {
public:
void ArgumentProcessor(int searchOn, int total, char** arguments) override
{
BaseFunctionName = "backup";
StartCode = 1;
IsRequiredOnlyOneArg = true;
GenericNumericalController(searchOn, total, Display::UsingDispString->expected_backup_arg);
if (Functions::ControlArg(arguments[searchOn]))
Strings::TargetPartition = arguments[searchOn];
else
LOGE("%s.\n", Display::UsingDispString->not_spec_opt);
Strings::OutputName = Strings::TargetPartition;
if (total > (searchOn + 1) && Functions::ControlArg(arguments[(searchOn + 1)]))
{
VLOGD("ArgumentProcessor [class]: Non-mandatory argument was detected and retrieved (for %s function).\n", BaseFunctionName);
Strings::OutputName = arguments[(searchOn + 1)];
}
Functions::CheckOptSymbol(Strings::TargetPartition);
Functions::CheckOptSymbol(Strings::OutputName);
}
};
class PartitionManagerFlash : public PartitionManagerBase {
public:
void ArgumentProcessor(int searchOn, int total, char** arguments) override
{
BaseFunctionName = "flash";
StartCode = 2;
IsRequiredOnlyOneArg = false;
GenericNumericalController(searchOn, total, Display::UsingDispString->expected_flash_arg);
if (Functions::ControlArg(arguments[searchOn]))
Strings::TargetPartition = arguments[searchOn ];
else
LOGE("%s.\n", Display::UsingDispString->not_spec_opt);
if (Functions::ControlArg(arguments[(searchOn + 1)]))
Strings::TargetFlashFile = arguments[(searchOn + 1)];
else
LOGE("%s.\n", Display::UsingDispString->not_spec_opt);
Functions::CheckOptSymbol(Strings::TargetFlashFile);
Functions::CheckOptSymbol(Strings::TargetPartition);
}
};
class PartitionManagerFormat : public PartitionManagerBase {
public:
void ArgumentProcessor(int searchOn, int total, char** arguments) override
{
BaseFunctionName = "format";
StartCode = 3;
IsRequiredOnlyOneArg = false;
GenericNumericalController(searchOn, total, Display::UsingDispString->expected_format_arg);
if (Functions::ControlArg(arguments[searchOn]))
Strings::TargetPartition = arguments[searchOn];
else
LOGE("%s.\n", Display::UsingDispString->not_spec_opt);
if (Functions::ControlArg(arguments[(searchOn + 1)]))
Strings::TargetFormatFS = arguments[(searchOn + 1)];
else
LOGE("%s.\n", Display::UsingDispString->not_spec_opt);
Functions::CheckOptSymbol(Strings::TargetFormatFS);
Functions::CheckOptSymbol(Strings::TargetPartition);
}
};
class PartitionManagerPartSize : public PartitionManagerBase {
public:
void ArgumentProcessor(int searchOn, int total, char** arguments) override
{
BaseFunctionName = "partition-size";
StartCode = 4;
IsRequiredOnlyOneArg = true;
GenericNumericalController(searchOn, total, Display::UsingDispString->expected_partsz_arg);
if (Functions::ControlArg(arguments[searchOn]))
Strings::TargetPartition = arguments[searchOn];
else
LOGE("%s.\n", Display::UsingDispString->not_spec_opt);
Functions::CheckOptSymbol(Strings::TargetPartition);
}
};
int main(int argc, char** argv)
{
Strings::ExecutingName = basename(argv[0]);
for (int i = 0; i <= (argc - 1); i++)
{
if (strncmp(argv[i], "-V", 2) == 0 || strcmp(argv[i], "--verbose") == 0)
Booleans::VerboseMode = true;
else
continue;
}
/* Generate classes */
VLOGD("Generating classes...\n");
PartitionManagerBase* Base;
PartitionManagerBase BaseTemplate;
PartitionManagerBackup BackupArgProcessorBase;
PartitionManagerFlash FlashArgProcessorBase;
PartitionManagerFormat FormatArgProcessorBase;
PartitionManagerPartSize PartSizeArgProcessorBase;
VLOGD("Main function started. Setting up locale. Calling 'setlocale <clocale>'\n");
setlocale(LC_ALL, "");
int argc_n = argc;
char buf[256];
char** args = argv;
VLOGD("Checking stdin status...\n");
if (!isatty(fileno(stdin)))
{
VLOGD("stdin is not empty.\n");
VLOGD("Parsing stdin arguments...\n");
while (fgets(buf, sizeof(buf), stdin) != nullptr)
{
buf[strcspn(buf, "\n")] = 0;
args[argc_n] = strdup(buf);
argc_n++;
}
VLOGD("Parsing completed.\n");
}
else
VLOGD("stdin empty.\n");
/* load language */
VLOGD("Loading language... Calling LoadLanguage()...\n");
if (!Functions::LoadLanguage())
{
cout << "LoadLanguage() process failed..!" << endl;
abort();
}
SymbolRule = Display::UsingDispString->symbol_rule;
argc = argc_n;
int argc_parse = (argc - 1);
char** args_ctrl = args;
args_ctrl++;
static bool ViewHelp = false;
static bool ViewVersion = false;
static bool LogicalSpeficy = false;
static bool ListRequired = false;
static bool MultipleViewers = false;
static bool SetLanguageReq = false;
static bool SomeSpec = false;
static bool PartSizeArgSpeficed = false;
static char* SpeficedLanguagePr;
static string Option;
static string Target;
static int SearchResult = 3;
static int SearchOnMainInt = -1;
VLOGD("Parsing standart arguments...\n");
while (argc_parse && args_ctrl[0] != nullptr)
{
if (args_ctrl[0][0] != '-')
{
argc_parse--;
args_ctrl++;
continue;
}
for (int x = 1; true; x++)
{
Option = args_ctrl[0];
SomeSpec = true;
switch (args_ctrl[0][x])
{
case '-':
if (Option == "--backup")
deprecated('b',
Display::UsingDispString->depr_backup_opt,
"backup");
else if (Option == "--flash")
deprecated('F',
Display::UsingDispString->depr_flash_opt,
"flash");
else if (Option == "--format")
deprecated('r',
Display::UsingDispString->depr_format_opt,
"format");
else if (Option == "--license")
deprecated('L',
Display::UsingDispString->depr_Vlicense_opt,
"license");
else if (Option == "--context")
deprecated('c',
Display::UsingDispString->depr_ch_sp_opt,
"context");
else if (Option == "--logical")
{
VLOGD("Logical partition type specified.\n");
LogicalSpeficy = true;
break;
}
else if (Option == "--search-path")
{
VLOGD("Custom search path specified.\n");
if (argc_parse > 1)
PrSpInput(args_ctrl[1]);
else
LOGE("--search-path: %s.\n%s `%s --help' %s.\n", \
Display::UsingDispString->is_requires_arg, \
Display::UsingDispString->try_h, \
Strings::ExecutingName.c_str(), \
Display::UsingDispString->for_more);
break;
}
else if (Option == "--list")
{
VLOGD("It was requested to list the partitions.\n");
ListRequired = true;
if (ViewVersion || ViewHelp)
MultipleViewers = true;
break;
}
else if (Option == "--force")
{
VLOGD("Force mode speficed.\n");
Booleans::ForceMode = true;
break;
}
else if (Option == "--verbose")
{
VLOGD("Verbose mode speficed.\n");
Booleans::VerboseMode = true;
break;
}
else if (Option == "--silent")
{
VLOGD("Silent mode speficed.\n");
Booleans::SilentEnabled = true;
break;
}
else if (Option == "--set-language")
{
VLOGD("It was requested to adjust the language.\n");
if (argc_parse > 1)
{
VLOGE("Language inputs: getting inputs...\n");
SetLanguageReq = true;
SpeficedLanguagePr = args_ctrl[1];
}
else
LOGE("--set-language: %s.\n%s `%s --help' %s.\n",
Display::UsingDispString->is_requires_arg,
Display::UsingDispString->try_h,
Strings::ExecutingName.c_str(),
Display::UsingDispString->for_more);
break;
}
else if (Option == "--as-byte")
{
PartSizeArgSpeficed = true;
Integers::PartSizeViewType = VIEW_AS_BYTE;
break;
}
else if (Option == "--as-kilobyte")
{
PartSizeArgSpeficed = true;
Integers::PartSizeViewType = VIEW_AS_KIB;
break;
}
else if (Option == "--as-megabyte")
{
PartSizeArgSpeficed = true;
Integers::PartSizeViewType = VIEW_AS_MIB;
break;
}
else if (Option == "--as-gigabyte")
{
PartSizeArgSpeficed = true;
Integers::PartSizeViewType = VIEW_AS_GIB;
break;
}
else if (Option == "--only-size")
{
PartSizeArgSpeficed = true;
Booleans::OnlyViewSize = true;
break;
}
else if (Option == "--version")
{
VLOGD("The version info was requested to be displayed.\n");
ViewVersion = true;
if (ListRequired || ViewHelp)
MultipleViewers = true;
break;
}
else if (Option == "--help")
{
VLOGD("The help message was requested to be displayed.\n");
ViewHelp = true;
if (ViewVersion || ListRequired)
MultipleViewers = true;
break;
}
else
{
VLOGE("Unknown Option: %s\n", args_ctrl[0]);
LOGE("%s: %s.\n%s `%s --help' %s.\n", args_ctrl[0],
Display::UsingDispString->unknw_arg,
Display::UsingDispString->try_h,
Strings::ExecutingName.c_str(),
Display::UsingDispString->for_more);
}
break;
case 'b':
deprecated('b',
Display::UsingDispString->depr_backup_opt,
"backup");
break;
case 'F':
deprecated('F',
Display::UsingDispString->depr_flash_opt,
"flash");
break;
case 'r':
deprecated('r',
Display::UsingDispString->depr_format_opt,
"format");
break;
case 'L':
deprecated('L',
Display::UsingDispString->depr_Vlicense_opt,
"license");
break;
case 'D':
deprecated('D',
Display::UsingDispString->depr_ch_list_opt);
break;
case 'c':
deprecated('c',
Display::UsingDispString->depr_ch_sp_opt,
"context");
case 'l':
VLOGD("Logical partition type specified.\n");
LogicalSpeficy = true;
continue;
case 'P':
VLOGD("Custom search path speficed.\n");
if (argc_parse > 1)
{
VLOGE("Search-path inputs: getting inputs...\n");
PrSpInput(args_ctrl[1]);
continue;
}
else
LOGE("-P: %s.\n%s `%s --help' %s.\n",
Display::UsingDispString->is_requires_arg,
Display::UsingDispString->try_h,
Strings::ExecutingName.c_str(),
Display::UsingDispString->for_more);
break;
case 'p':
VLOGD("It was requested to list the partitions.\n");
ListRequired = true;
if (ViewVersion || ViewHelp)
MultipleViewers = true;
continue;
case 'f':
VLOGD("Force mode speficed.\n");
Booleans::ForceMode = true;
continue;
case 'V':
VLOGD("Verbose mode speficed.\n");
Booleans::VerboseMode = true;
continue;
case 's':
VLOGD("Silent mode speficed.\n");
Booleans::SilentEnabled = true;
continue;
case 'S':
VLOGD("It was requested to adjust the language.\n");
if (argc_parse > 1)
{
VLOGE("Language inputs: getting inputs...\n");
SetLanguageReq = true;
SpeficedLanguagePr = args_ctrl[1];
continue;
}
else
LOGE("-S: %s.\n%s `%s --help' %s.\n",
Display::UsingDispString->is_requires_arg,
Display::UsingDispString->try_h,
Strings::ExecutingName.c_str(),
Display::UsingDispString->for_more);
case 'v':
VLOGD("The version info was requested to be displayed.\n");
ViewVersion = true;
if (ListRequired || ViewHelp)
MultipleViewers = true;
continue;
case '\0':
break;
default:
VLOGE("Unknown Option: -%c\n", args_ctrl[0][x]);
LOGE("-%c: %s.\n%s `%s --help' %s.\n",
args_ctrl[0][x],
Display::UsingDispString->unknw_arg,
Display::UsingDispString->try_h,
Strings::ExecutingName.c_str(),
Display::UsingDispString->for_more);
}
break;
}
argc_parse--;
args_ctrl++;
}
Base = &BaseTemplate;
argc_parse = argc;
VLOGD("Starting cycle for trapping main options...\n");
while (1)
{
if ((argc_parse - 1) == 0)
{
VLOGD("MainFnController: argc - 1 = 0. Breaking...\n");
break;
}
if (args[(argc_parse - 1)][0] == '-')
{
VLOGD("MainFnController: args[%d] starts with '-'. Continue.\n", (argc_parse - 1));
argc_parse--;
continue;
}
else
{
Target = args[(argc_parse - 1)];
SearchOnMainInt = argc_parse;
VLOGD("MainFnController: args[%d] = %s\n", (argc_parse - 1), args[(argc_parse - 1)]);
VLOGD("MainFnController: variable of \"Target\" (string): %s\n", Target.c_str());
if (Target == "backup")
{
Base = &BackupArgProcessorBase;
Booleans::BackupMode = true;
break;
}
else if (Target == "flash")
{
Base = &FlashArgProcessorBase;
Booleans::FlashMode = true;
break;
}
else if (Target == "format")
{
Base = &FormatArgProcessorBase;
Booleans::FormatMode = true;
break;
}
else if (Target == "partition-size")
{
Base = &PartSizeArgProcessorBase;
Booleans::PartSizeViewMode = true;
break;
}
else
{
Target = "";
SearchOnMainInt = -1;
argc_parse--;
continue;
}
}
break;
}
if (Booleans::SilentEnabled && Booleans::VerboseMode)
{
VLOGE("Silent and verbose mode is one-way.\n");
cout << Strings::ExecutingName << ": " << Display::UsingDispString->s_and_v << endl;
exit(1);
}
VLOGD("Checking last language switch status...\n");
if (Functions::CleanSWPoint())
{
VLOGD("Last transactions found that language was changed between.\n");
if (Display::UsingDispString->welcome_ != nullptr)
LOGD("%s", Display::UsingDispString->welcome_);
LOGD("%s %s %s %s.\n",
Display::UsingDispString->language,
Display::UsingDispString->welcome,
Display::UsingDispString->by_str,
Display::UsingDispString->lang_by_s);
}
/* check argument total */
VLOGD("argc (arguments) total: %d.\n", argc);
if (argc < 2)
LOGE("%s.\n%s '%s --help' %s.\n",
Display::UsingDispString->missing_operand,
Display::UsingDispString->try_h,
Strings::ExecutingName.c_str(),
Display::UsingDispString->for_more);
/* stop the program if multiple viewer is used */
if (MultipleViewers)
{
VLOGE("Multiple viewer option selected!\n");
LOGE("%s\n", Display::UsingDispString->multiple_wiewers);
}
if (!Booleans::PartSizeViewMode && PartSizeArgSpeficed)
{
VLOGE("Related flags were detected, although some partition size was not requested.\n");
LOGE("%s.\n", Display::UsingDispString->only_partsz_args);
}
/* controller to handle viewer */
if (ViewHelp)
{
VLOGD("The help message was asked to display. It's displayed... Calling DisplayHelp()\n");
Functions::DisplayHelp();
return 0;
}
else if (ViewVersion)
{
VLOGD("The version info message was asked to display. It's displayed... Calling DisplayVersion()\n");
Functions::DisplayVersion();
return 0;
}
else if (ListRequired)
{
VLOGD("Partitions were asked to be listed. It's listed... Calling CheckRoot() (root check is required), CheckDevPoint() (for generating warnings etc.) and ListPartitions()\n");
Functions::CheckRoot();
VLOGD("CheckRoot() completed.\n");
Functions::CheckDevPoint();
VLOGD("CheckDevPoint() completed.\n");
return Functions::ListPartitions();
}
if (SetLanguageReq)
{
VLOGD("The language was asked to adjust. Calling SetLanguage()...\n");
LOGD("%s: %s\n",
Strings::ExecutingName.c_str(),
Display::UsingDispString->switching_lang);
Functions::SetLanguage(SpeficedLanguagePr, 0);
sleep(2);
VLOGD("SetLanguage() completed.\n");
LOGD("%s: %s.\n",
Strings::ExecutingName.c_str(),
Display::UsingDispString->please_rerun);
return 0;
}
if (Target.empty())
{
VLOGE("There's no job to do.\n");
LOGD("%s: %s.\n",
Strings::ExecutingName.c_str(),
Display::UsingDispString->missing_operand);
if (SomeSpec)
LOGD("%s.\n", Display::UsingDispString->some_spec);
LOGD("%s '%s --help' %s.\n",
Display::UsingDispString->try_h,
Strings::ExecutingName.c_str(),
Display::UsingDispString->for_more);
exit(1);
}
Base->ArgumentProcessor(SearchOnMainInt, argc, args);
if (Booleans::FormatMode)
{
VLOGD("File system name specified for formatting is being contaminated...\n");
if (Strings::TargetFormatFS != "ext4" \
&& Strings::TargetFormatFS != "ext3" \
&& Strings::TargetFormatFS != "ext2")
{
VLOGE("Unsupported file system: %s.\n", Strings::TargetFormatFS.c_str());
LOGE("%s: %s\n",
Display::UsingDispString->unsupported_fs,
Strings::TargetFormatFS.c_str());
}
}
/* checks */
VLOGD("Checking root status... Calling CheckRoot()...\n");
Functions::CheckRoot();
VLOGD("Checking A/B and logical device status... Calling CheckDevPoint()...\n");
Functions::CheckDevPoint();
if (LogicalSpeficy)
{
VLOGD("Logical partition type speficed. Checking partition statust's...\n");
if (Booleans::UsesLogical)
Booleans::UseLogical = true;
else
LOGE("%s\n", Display::UsingDispString->not_logical);
}
if (Booleans::FlashMode)
{
VLOGD("The status of the specified file for flashing is being checked...\n");
SearchResult = Functions::GetState(Strings::TargetFlashFile);
if (SearchResult == 1)
LOGE("%s: `%s': %s\n",
Display::UsingDispString->cannot_stat,
Strings::TargetFlashFile.c_str(),
strqerror());
else if (SearchResult == -1)
LOGE("`%s': %s\n",
Strings::TargetFlashFile.c_str(),
Display::UsingDispString->not_file);
}
/* custom search path checker */
if (Booleans::UseCustomSearchPath)
{
VLOGD("The status of the \"dev\" is controlled in the specified custom /dev search path...\n");
if (strncmp(Strings::CustomSearchPath.c_str(), "/dev", 4) != 0)
{
if (!Booleans::ForceMode)
LOGE("%s\n", Display::UsingDispString->not_in_dev);
}
VLOGD("The specified custom /dev search path is being put in countless...\n");
SearchResult = Functions::GetState(Strings::CustomSearchPath, "dir");
if (SearchResult == 1)
LOGE("%s: `%s': %s\n",
Display::UsingDispString->cannot_stat,
Strings::CustomSearchPath.c_str(),
strqerror());
else if (SearchResult == -1)
LOGE("`%s': %s\n",
Strings::CustomSearchPath.c_str(),
Display::UsingDispString->not_dir);
}
VLOGD("The partition specification status is controlled...\n");
if (Strings::TargetPartition.empty())
{
if (!Booleans::ForceMode)
LOGE("%s\n%s `%s --help' %s\n",
Display::UsingDispString->req_part_name,
Display::UsingDispString->try_h,
Strings::ExecutingName.c_str(),
Display::UsingDispString->for_more);
}
else
{
VLOGD("The call of main operations is being checked in case of the call...\n");
if (!Target.empty())
Base->CallTargetBaseFunction();
}
}
/* end of code */

View File

@@ -0,0 +1,92 @@
/* By YZBruh */
/**
* Copyright 2024 Partition Manager
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define INC_MAIN_LIBS
#include <PartitionManager/PartitionManager.h>
#include <sys/system_properties.h>
static int
GetProperty(const char* _Nonnull property, const char* desired_val, const char* desired_val2 = nullptr)
{
char val[PROP_VALUE_MAX];
int len = __system_property_get(property, val);
VLOGD("GetProperty: get property value: '%s'\n", property);
if (len > 0)
{
VLOGD("GetProperty: %s=%s\n", property, val);
VLOGD("GetProperty: comparing '%s' property value '%s'\n", property, desired_val);
if (strcmp(val, desired_val) == 0)
{
VLOGD("GetProperty: '%s' is '%s'. Stop (0).\n", property, desired_val);
return 0;
}
else
{
VLOGE("GetProperty: '%s' property is not '%s'. Comparing desired value 2 (if speficed).\n", property, desired_val);
if (desired_val2 != nullptr)
{
if (strcmp(val, desired_val2) == 0)
{
VLOGD("GetProperty: '%s' is '%s'.Stop (0).\n", property, desired_val2);
return 0;
}
else
{
VLOGE("GetProperty: '%s' is not '%s'. Stop (1).\n", property, desired_val2);
return 1;
}
}
else
{
VLOGE("GetProperty: '%s' is not '%s'. Stop (1).\n", property, desired_val);
return 1;
}
}
}
else
{
VLOGE("GetProperty: cannot get property '%s'. No such property or empty. Stop (1).\n", property);
return 1;
}
return 2;
}
using namespace PartitionManager;
/* check parts */
void Functions::CheckDevPoint(void)
{
/* true = ab | false = a only */
Booleans::UsesSlots = (GetProperty("ro.boot.slot_suffix", "_a", "_b") == 0 || GetProperty("ro.boot.slot", "_a", "_b") == 0) ? true : false;
if (Booleans::UsesSlots)
VLOGW("CheckDevPoint: 1 warning generated: A/B partitions status.\n");
/* true = logical | false = normal */
Booleans::UsesLogical = (GetProperty("ro.boot.dynamic_partitions", "true") == 0) ? true : false;
if (Booleans::UsesLogical)
VLOGW("CheckDevPoint: 1 warning generated: logical partitions status.\n");
}
/* end of code */

37
jni/PartitionManager/Root.cpp Executable file
View File

@@ -0,0 +1,37 @@
/* By YZBruh */
/**
* Copyright 2024 Partition Manager
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define INC_MAIN_LIBS
#define INC_DEBUGERS
#define INC_STRINGKEYS
#include <PartitionManager/PartitionManager.h>
/* root checker function */
void PartitionManager::Functions::CheckRoot(void)
{
VLOGD("CheckRoot: trying to get UID with 'getuid <unistd.h>'\n");
if (getuid() != 0)
{
VLOGE("CheckRoot: cannot get UID. Not executed with root!\n");
LOGE("%s\n", PartitionManager::Display::UsingDispString->no_root);
}
}
/* end of code */

347
jni/PartitionManager/Tools.cpp Executable file
View File

@@ -0,0 +1,347 @@
/* By YZBruh */
/**
* Copyright 2024 Partition Manager
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define INC_MAIN_LIBS
#define INC_STAT
#define INC_LIBGEN
#define INC_DEBUGERS
#define INC_TOOLS_REQS
#define INC_STRINGKEYS
#include <PartitionManager/PartitionManager.h>
#include <PartitionManager/PartSizeMacros.h>
#include <PartitionManager/FileSystemUtils.h>
namespace PartitionManager {
namespace Functions {
/**
* it is meant to calculate the size of the quickly given file.
* its purpose is for rapid processing
*/
static long long
CalculateSizeLongLong(const string& fp)
{
VLOGD("CalculateSizeLongLong: calculating file size: `%s'\n", fp.c_str());
VLOGD("CalculateSizeLongLong: reading `%s' with 'ifstream <fstream>'\n", fp.c_str());
ifstream file(fp, ios::binary | ios::ate);
return (!file) ? -1 : static_cast<long long>(file.tellg());
}
/**
* error that the partition is not found.
* It's for quick action.
*/
static void
PartitionNotFound(const char* p) { LOGE("%s: %s\n", p, Display::UsingDispString->part_not_found); }
/* the partitions are meant to quickly find. */
static void
SearchPartition(const string& fp)
{
VLOGD("SearchPartition: calling GetState()...\n");
static int op = GetState(fp, "blk");
if (op == 1)
PartitionNotFound(basename(fp.c_str()));
else if (op == -1 && !Booleans::ForceMode)
LOGE("%s\n", Display::UsingDispString->not_block);
}
static void
PrintInfo(ushort_t pcode, double psz, double fsz)
{
LOGD("##########################################\n");
LOGD("# --> %s: %s\n",
Display::UsingDispString->part_name,
Strings::TargetPartition.c_str());
LOGD("# --> %s: %s\n",
Display::UsingDispString->part_type,
(Booleans::UseLogical) ? Display::UsingDispString->yes : Display::UsingDispString->no);
if (psz != -1)
LOGD("# --> %s: %.2fMB\n",
Display::UsingDispString->part_disk_sz,
psz);
else
LOGD("# --> %s: %s\n",
Display::UsingDispString->warn,
Display::UsingDispString->part_disk_sz_fail);
if (pcode == 3)
{
if (fsz != -1)
LOGD("# --> %s: %.2fMB\n",
Display::UsingDispString->flash_file_sz,
fsz);
else
LOGW("# --> %s: %s\n",
Display::UsingDispString->warn,
Display::UsingDispString->flash_file_sz_fail);
}
LOGD("##########################################\n");
}
static bool
IsDoubleOf1024(float size)
{
float num = size / 1024;
char str[35];
sprintf(str, "%f", num);
return (strstr(str, ".000000") != nullptr) ? true : false;
}
} /* namespace Functions */
} /* namespace PartitionManager */
using namespace PartitionManager;
int Functions::Start(ushort_t progress_code)
{
/* Some required variables */
fstream sourceF, targetF;
string accessPrefix, opName;
long long copiedData = 0;
bool IsFirstProcessOnTarget = true;
if (Booleans::UseLogical)
accessPrefix = "/dev/block/mapper/" + Strings::TargetPartition;
else
accessPrefix = (Booleans::UseCustomSearchPath) ? (Strings::CustomSearchPath) + ("/") + (Strings::TargetPartition) : ("/dev/block/by-name/") + (Strings::TargetPartition);
VLOGD("PartitionManager: calling SearchPartition() for searching partition (path); `%s'\n", accessPrefix.c_str());
Functions::SearchPartition(accessPrefix);
static long long count = (long long)(CalculateSizeLongLong(accessPrefix) + ((1024 * 1024) * 4));
const int BFSIZE = (Functions::IsDoubleOf1024((float)Functions::CalculateSizeLongLong(accessPrefix))) ? 1024 : 1;
char buffer[BFSIZE];
double FlashFileSize = 0;
double PartitionSize = (double)(static_cast<double>(Functions::CalculateSizeLongLong(accessPrefix)) / (1024 * 1024));
if (!Strings::TargetFlashFile.empty())
FlashFileSize = (double)(static_cast<double>(Functions::CalculateSizeLongLong(Strings::TargetFlashFile)) / (1024 * 1024));
if (progress_code != 4) PrintInfo(progress_code, PartitionSize, FlashFileSize);
if (progress_code == 1)
{
VLOGD("PartitionManager: trying to open `%s' with 'open <fstream>'.\n", accessPrefix.c_str());
sourceF.open(accessPrefix, ios::binary | ios::in);
if (!sourceF.is_open())
LOGE("%s: %s: %s\n",
Display::UsingDispString->not_read,
accessPrefix.c_str(),
strqerror());
/* determine output */
if (Strings::OutputName == Strings::TargetPartition)
{
opName = Strings::OutputName + ".img";
VLOGW("PartitionManager: output not speficed. Selecting automaticly.\n");
LOGW("%s: %s\n",
Display::UsingDispString->out_not_spec,
opName.c_str());
}
else
opName = Strings::OutputName;
VLOGD("Checking output status...\n");
if (GetState(opName) == 0)
LOGE("'%s': File exits.\n", opName.c_str());
VLOGD("PartitionManager: trying to open `%s' with 'open <fstream>'.\n", opName.c_str());
targetF.open(opName, ios::binary | ios::out);
if (!targetF.is_open())
LOGE("%s: %s: %s\n",
Display::UsingDispString->not_gen,
opName.c_str(),
strqerror());
VLOGD("PartitionManager: read (partition) and write (output) 'read, write <fstream>'\n");
/* start writing */
while (sourceF.read(buffer, BFSIZE) && copiedData < count)
{
if (GetState(opName) != 0 && IsFirstProcessOnTarget)
LOGE("%s\n", Display::UsingDispString->no_found_on_process);
streamsize readed_data = sourceF.gcount();
targetF.write(buffer, readed_data);
if (targetF.fail() || targetF.bad())
{
if (Functions::GetState(opName) == 0)
remove(opName.c_str());
LOGF("%s: %s: %s\n",
Display::UsingDispString->not_write,
opName.c_str(),
strqerror());
}
IsFirstProcessOnTarget = false;
copiedData += readed_data;
}
/* close files */
sourceF.close();
targetF.close();
LOGD("%s: %s\n",
Display::UsingDispString->success_backup,
opName.c_str());
}
else if (progress_code == 2)
{
if (PartitionSize != -1 && FlashFileSize != -1)
{
if (FlashFileSize > PartitionSize && !Booleans::ForceMode)
LOGE("%s\n", Display::UsingDispString->ffile_more_part);
}
VLOGD("PartitionManager: trying to open `%s' with 'open <fstream>'.\n", Strings::TargetFlashFile.c_str());
sourceF.open(Strings::TargetFlashFile, ios::binary | ios::in);
if (!sourceF.is_open())
LOGF("%s: %s: %s\n",
Display::UsingDispString->not_read,
Strings::TargetFlashFile.c_str(),
strqerror());
VLOGD("PartitionManager: trying to open `%s' with 'open <fstream>'.\n", accessPrefix.c_str());
targetF.open(accessPrefix, ios::binary | ios::in | ios::out | ios::trunc);
if (!targetF.is_open())
LOGF("%s: %s: %s\n",
Display::UsingDispString->not_read,
accessPrefix.c_str(),
strqerror());
VLOGD("PartitionManager: read (flash file) and write (partition) 'read, write <fstream>'\n");
/* start writing */
while (sourceF.read(buffer, BFSIZE) && copiedData < count)
{
streamsize readed_data = sourceF.gcount();
targetF.write(buffer, readed_data);
if (targetF.fail() || targetF.bad())
LOGF("%s: %s: %s\n",
Display::UsingDispString->not_write,
accessPrefix.c_str(),
strqerror());
copiedData += readed_data;
}
sourceF.close();
targetF.close();
LOGD("%s.\n", Display::UsingDispString->success_flash);
}
else if (progress_code == 3)
{
/* get target partition block size */
VLOGD("PartitionManager: getting block size `%s' with 'statfs <sys/vfs.h>'\n", accessPrefix.c_str());
struct statfs file_sys_inf;
if (statfs(accessPrefix.c_str(), &file_sys_inf) != 0)
LOGE("%s\n", Display::UsingDispString->cannot_get_bsz);
/* generate mke2fs argument list */
VLOGD("PartitionManager: generating mke2fs argument list...\n");
char bsize[25] = "";
sprintf(bsize, "%lu", file_sys_inf.f_bsize);
char* arguments[] = {
"mke2fs-static",
"-Fq",
"-t",
(char*)Strings::TargetFormatFS.c_str(),
"-b",
(char*)bsize,
(char*)accessPrefix.c_str(),
};
LOGD("%s: `%s'. %s: %s\n",
Display::UsingDispString->formatting,
accessPrefix.c_str(),
Display::UsingDispString->fs_str,
Strings::TargetFormatFS.c_str());
/* run mke2fs */
VLOGD("PartitionManager: calling mke2fs_main...\n");
if (mke2fs_main(sizeof(arguments), arguments) != 0)
LOGF("%s\n", Display::UsingDispString->format_fail);
LOGD("%s.\n", Display::UsingDispString->success_format);
}
else if (progress_code == 4)
{
VLOGD("PartitionManager: getting size of '%s' (long long)\n", accessPrefix.c_str());
long long psize = (long long)CalculateSizeLongLong(accessPrefix);
if (psize == -1)
{
VLOGE("PartitionManager: cannot get partition size!\n");
LOGE("%s: %s\n",
Display::UsingDispString->fail_get_psize,
strqerror());
}
static char* SizeType;
static char Holder[50];
if (!Booleans::OnlyViewSize)
{
sprintf(Holder, "%s: ", Strings::TargetPartition.c_str());
if (Integers::PartSizeViewType == VIEW_AS_BYTE) SizeType = "B";
else if (Integers::PartSizeViewType == VIEW_AS_KIB) SizeType = "KB";
else if (Integers::PartSizeViewType == VIEW_AS_MIB) SizeType = "MB";
else if (Integers::PartSizeViewType == VIEW_AS_GIB) SizeType = "GB";
}
else
SizeType = "";
VLOGD("PartitionManager: Displaying partition size...\n");
if (Integers::PartSizeViewType == VIEW_AS_BYTE)
LOGD("%s%llu%s\n",
Holder,
(long long)psize,
SizeType);
else if (Integers::PartSizeViewType == VIEW_AS_KIB)
LOGD("%s%lu%s\n",
Holder,
(long)(psize / 1024),
SizeType);
else if (Integers::PartSizeViewType == VIEW_AS_MIB)
LOGD("%s%.2f%s\n",
Holder,
(double)(static_cast<double>(psize) / (1024 * 1024)),
SizeType);
else if (Integers::PartSizeViewType == VIEW_AS_GIB)
LOGD("%s%.2f%s\n",
Holder,
(double)(static_cast<double>(psize) / (1024 * 1024 * 1024)),
SizeType);
}
return 0;
}
/* end of code */

View File

@@ -0,0 +1,77 @@
/* By YZBruh */
/**
* Copyright 2024 Partition Manager
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define INC_MAIN_LIBS
#define INC_STRINGKEYS
#define VERSIONING
#include <PartitionManager/PartitionManager.h>
#include <PartitionManager/VersionFnVars.h>
using namespace PartitionManager;
void Functions::DisplayVersion(void)
{
VLOGD("DisplayVersion: printing main info...\n");
LOGD("%s %s %d.%d.%d (%d%d%d / C++) ",
Strings::ExecutingName.c_str(),
Display::UsingDispString->version_str,
PMT_MAJOR,
PMT_MINOR,
PMT_PATCHLEVEL,
PMT_MAJOR,
PMT_MINOR,
PMT_PATCHLEVEL);
#if __SIZEOF_POINTER__ == 4
LOGD("32-bit %s\n", Display::UsingDispString->bin_str);
#elif __SIZEOF_POINTER__ == 8
LOGD("64-bit %s\n", Display::UsingDispString->bin_str);
#else
LOGD("<%s> %s\n",
Display::UsingDispString->unknw_str,
Display::UsingDispString->bin_str);
#endif
LOGD("mke2fs %s %s (%s)\n",
Display::UsingDispString->version_str,
E2FSPROGS_VERSION_PRIVATE,
E2FSPROGS_DATE);
LOGD("libext2fs %s %s (%s / %s)\n",
Display::UsingDispString->version_str,
E2FSPROGS_VERSION_PRIVATE,
EXT2FS_LIB_VERSION_PRIVATE,
E2FSPROGS_DATE);
VLOGD("DisplayVersion: build type: ");
if (Booleans::VerboseMode)
#if defined(__clang__) && !defined(__NDK_BUILD)
printf("clang (manual).\n");
LOGD("pmt %s: clang %d.%d.%d\n",
Display::UsingDispString->compiler_str,
__clang_major__,
__clang_minor__,
__clang_patchlevel__);
#elif defined(__NDK_BUILD)
printf("NDK.\n");
LOGD("\n%s\n", __NDK_CXX_VERSION__);
#endif
}
/* end of code */