diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ea5ec9f..da93c6f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,16 +15,22 @@ jobs: id: cleanup uses: rokibhasansagar/slimhub_actions@main - - name: Update and setup packages - id: general-packages-progress + - name: Setup GitHub CLI + id: setup-gh run: | type -p curl >/dev/null || (sudo apt update && sudo apt install curl -y) curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \ && sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \ && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \ && sudo apt update \ + && sudo apt install gh -y + + - name: Update and setup packages + id: general-packages-progress + run: | + sudo apt update \ && sudo apt upgrade -y \ - && sudo apt install make xz-utils aria2 gawk gh -y + && sudo apt install make xz-utils aria2 gawk -y - name: Save spefic version variables id: save-vars @@ -40,7 +46,6 @@ jobs: sudo chmod -R 777 pmt echo "PMT_SRCDIR=/home/pmt" >> $GITHUB_ENV echo "NDK_DIR=/home/ndk/android-ndk" >> $GITHUB_ENV - echo "NDK_IN_DIR=/home/ndk" >> $GITHUB_ENV sudo mkdir -p "/home/ndk" && cd "/home/ndk" && sudo chmod 777 "/home/ndk" - name: Setup Android NDK @@ -57,9 +62,11 @@ jobs: - name: Build pmt id: build-pmt run: | + make gen-ndk-makefiles export NDK_PROJECT_PATH=${PWD} export NDK_ROOT_DIR=${{ env.NDK_DIR }} - . build/bash/gen-header + echo "NDK_ROOT_DIR=${NDK_ROOT_DIR}" >> $GITHUB_ENV + bash build/bash/gen-header cd ${{ env.NDK_DIR }} ./ndk-build working-directory: ${{ env.PMT_SRCDIR }} @@ -68,18 +75,26 @@ jobs: id: small-transactions run: | export CXX_64="${PWD}/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++" + export CXX_32="${PWD}/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang++" + export AR="${PWD}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" export CXX_VERSION=$(${CXX_64} --version | head -n 1) echo "CXX_VERSION=${CXX_VERSION}" >> $GITHUB_ENV . ${{ env.PMT_SRCDIR }}/build/workflow/build.config . ${{ env.PMT_SRCDIR }}/build/workflow/relnotes > /home/pmt/release_body.txt cd ${{ env.PMT_SRCDIR }} zip -rq pmt-objs-local.zip obj/local/arm64-v8a obj/local/armeabi-v7a - xz libs/arm64-v8a/pmt - xz libs/armeabi-v7a/pmt - mv libs/arm64-v8a/pmt.xz ${PWD}/pmt-arm64-v8a-$(date +%Y%m%d).xz - mv libs/armeabi-v7a/pmt.xz ${PWD}/pmt-armeabi-v7a-$(date +%Y%m%d).xz - cp build/mandoc/mandoc pmt.8 - gzip -c pmt.8 > mandoc.gz + for arch in arm64-v8a armeabi-v7a; do + xz libs/${arch}/pmt + mv libs/${arch}/pmt.xz ${PWD}/pmt-${arch}-$(date +%Y%m%d).xz + done + for CXX_COMP in ${CXX_64} ${CXX_32}; do + make clean + make PMT_CXX="${CXX_COMP}" PMT_AR="${AR}" PMT_EXTRA_CFLAGS="-D__NDK_BUILD" + [[ "${CXX_COMP}" == *"aarch64"* ]] && make deb FOR_THIS=64 + [[ "${CXX_COMP}" == *"armv7a"* ]] && make deb FOR_THIS=32 + mv out/debpackage/*.deb . + make clean + done working-directory: ${{ env.NDK_DIR }} - name: Upload to release @@ -88,8 +103,8 @@ jobs: with: files: | /home/pmt/pmt*.xz + /home/pmt/pmt*.deb /home/pmt/pmt-objs-local.zip - /home/pmt/mandoc.gz name: Partition Manager ${{ env.PMT_VERSION }} Release tag_name: ${{ env.PMT_VERSION }} body_path: /home/pmt/release_body.txt diff --git a/build/mandoc/mandoc b/build/mandoc/mandoc index ffefbfa..19e3f2c 100755 --- a/build/mandoc/mandoc +++ b/build/mandoc/mandoc @@ -14,7 +14,7 @@ .\" See the License for the specific language governing permissions and .\" limitations under the License. .\" -.TH "PMT" "8" "September 2024" "PMT 2.9.0" "Partition Manager" +.TH "PMT" "8" "October 2024" "PMT 2.9.6" "Partition Manager" .SH NAME .B pmt \- Android Partition Manager Tool diff --git a/build/workflow/build.config b/build/workflow/build.config index 8a462f5..3da624f 100755 --- a/build/workflow/build.config +++ b/build/workflow/build.config @@ -1,5 +1,5 @@ -export PMT_VERSION="2.9.1" -export PMT_VERSION_CODE=291 +export PMT_VERSION="2.9.6" +export PMT_VERSION_CODE=296 export NDK_VERSION="r27" export NDK_IS="android-ndk" export NDK_LINK="https://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-linux.zip" diff --git a/include/PartitionManager/Deprecates.h b/include/PartitionManager/Deprecates.h index e7eca8b..afb71c2 100755 --- a/include/PartitionManager/Deprecates.h +++ b/include/PartitionManager/Deprecates.h @@ -18,84 +18,84 @@ #pragma once -#define deprecated_opt 1 -#define changed_opt 2 -#define end_depr_pointer 0 -#define not_changed 0 -#define not_changed_long nullptr +/* annotated macros */ +#define DeprecatedOption 1 +#define ChangedOption 2 +#define EndDeprcationPoint 0 +#define NotChanged 0 +#define NotChangedLong nullptr /* versions */ -#define v150 "1.5.0" -#define v160 "1.6.0" -#define v170 "1.7.0" -#define v180 "1.8.0" -#define v190 "1.9.0" -#define v200 "2.0.0" -#define v210 "2.1.0" -#define v220 "2.2.0" -#define v230 "2.3.0" -#define v240 "2.4.0" -#define v250 "2.5.0" -#define v260 "2.6.0" -#define v270 "2.7.0" -#define v280 "2.8.0" -#define v290 "2.9.0" -#define vUNK nullptr +#define v150 "1.5.0" +#define v160 "1.6.0" +#define v170 "1.7.0" +#define v180 "1.8.0" +#define v190 "1.9.0" +#define v200 "2.0.0" +#define v210 "2.1.0" +#define v220 "2.2.0" +#define v230 "2.3.0" +#define v240 "2.4.0" +#define v250 "2.5.0" +#define v260 "2.6.0" +#define v270 "2.7.0" +#define v280 "2.8.0" +#define v290 "2.9.0" +#define v291 "2.9.1" +#define v296 "2.9.6" +#define vUNKNOWN nullptr -struct pmt_deprecates { - int depr_type; - int option; - int option_new; - const char* option_long; - const char* option_long_new; - const char* depr_version; +struct DeprecationVarTab { + const int DeprecationType; + const int Option; + const int Option_new; + const char* Option_long; + const char* Option_long_new; + const char* DeprecatedOnVersion; }; -static struct pmt_deprecates depr_table[] = { - {deprecated_opt, 'b', not_changed, "backup", not_changed_long, v210}, - {deprecated_opt, 'F', not_changed, "flash", not_changed_long, v210}, - {deprecated_opt, 'r', not_changed, "format", not_changed_long, v210}, - {deprecated_opt, 'L', not_changed, "license", not_changed_long, v250}, - {changed_opt, 'D', 'p', "list", not_changed_long, v210}, - {changed_opt, 'c', 'P', "context", "search-path", v290}, - {end_depr_pointer, not_changed, not_changed, not_changed_long, not_changed_long, vUNK} +static struct DeprecationVarTab DeprecationTable[] = { + {DeprecatedOption, 'b', NotChanged, "backup", NotChangedLong, v210}, + {DeprecatedOption, 'F', NotChanged, "flash", NotChangedLong, v210}, + {DeprecatedOption, 'r', NotChanged, "format", NotChangedLong, v210}, + {DeprecatedOption, 'L', NotChanged, "license", NotChangedLong, v250}, + {ChangedOption, 'D', 'p', "list", NotChangedLong, v210}, + {ChangedOption, 'c', 'P', "context", "search-path", v290}, + {EndDeprcationPoint, NotChanged, NotChanged, NotChangedLong, NotChanged, vUNKNOWN} }; static void -__process_deprecated_opts(int opt, const string& opt_long, const char* depr_msg) +__process_deprecated_opts(int Opt, const string& OptionLong, const char* DeprecationMsg) { - static string long_e_msg; + string LongErrMsg = (OptionLong.empty()) ? PartitionManager::Display::UsingDispString->not_changed_opt : OptionLong; - if (opt_long.empty()) - long_e_msg = PartitionManager::Display::UsingDispString->not_changed_opt; - else - long_e_msg = opt_long; - - for (int optctrl = 0; depr_table[optctrl].depr_type != 0; optctrl++) + for (int optctrl = 0; DeprecationTable[optctrl].DeprecationType != 0; optctrl++) { - if (depr_table[optctrl].depr_type == 1) + if (DeprecationTable[optctrl].DeprecationType == 1) { - if (opt == depr_table[optctrl].option || strcmp(opt_long.c_str(), depr_table[optctrl].option_long) == 0) - { - LOGD("%s [%s]: -%c (%s): %s\n", PartitionManager::Display::UsingDispString->depr_opt_str, depr_table[optctrl].depr_version, (char)depr_table[optctrl].option, depr_table[optctrl].option_long, depr_msg); - exit(1); - } - + if (Opt == DeprecationTable[optctrl].Option || strcmp(OptionLong.c_str(), DeprecationTable[optctrl].Option_long) == 0) + LOGD("%s [%s]: -%c (%s): %s\n", + PartitionManager::Display::UsingDispString->depr_opt_str, + DeprecationTable[optctrl].DeprecatedOnVersion, + (char)DeprecationTable[optctrl].Option, + DeprecationTable[optctrl].Option_long, + DeprecationMsg); exit(1); } - else if (depr_table[optctrl].depr_type == 2) + else if (DeprecationTable[optctrl].DeprecationType == 2) { - if (opt == depr_table[optctrl].option || strcmp(opt_long.c_str(), depr_table[optctrl].option_long) == 0) - { - LOGD("%s [%s]: -%c (%s): %s\n", PartitionManager::Display::UsingDispString->switched_opt_str, depr_table[optctrl].depr_version, (char)depr_table[optctrl].option, long_e_msg.c_str(), depr_msg); - exit(1); - } - + if (Opt == DeprecationTable[optctrl].Option || strcmp(OptionLong.c_str(), DeprecationTable[optctrl].Option_long) == 0) + LOGD("%s [%s]: -%c (%s): %s\n", + PartitionManager::Display::UsingDispString->switched_opt_str, + DeprecationTable[optctrl].DeprecatedOnVersion, + (char)DeprecationTable[optctrl].Option, + LongErrMsg.c_str(), + DeprecationMsg); exit(1); } + } } -#define DEPR_HANDLE(x, y, z) \ - __process_deprecated_opts(x, y, z) +#define DEPR_HANDLE __process_deprecated_opts /* end of code */ diff --git a/include/PartitionManager/FileSystemUtils.h b/include/PartitionManager/FileSystemUtils.h index 93af138..31eb6ee 100755 --- a/include/PartitionManager/FileSystemUtils.h +++ b/include/PartitionManager/FileSystemUtils.h @@ -18,8 +18,6 @@ #pragma once -extern "C" { - int mke2fs_main(int argc, char* argv[]); -} +extern "C" int mke2fs_main(int argc, char* argv[]); /* end of code */ \ No newline at end of file diff --git a/include/PartitionManager/HelpFn.h b/include/PartitionManager/HelpFn.h index 5898726..3fd4f33 100755 --- a/include/PartitionManager/HelpFn.h +++ b/include/PartitionManager/HelpFn.h @@ -18,10 +18,6 @@ #pragma once -namespace PartitionManager { - namespace Functions { - void DisplayHelp(void); - } -} +namespace PartitionManager { void DisplayHelp(void); } /* end */ diff --git a/include/PartitionManager/PartitionManager.h b/include/PartitionManager/PartitionManager.h index 3bbaa04..e651525 100755 --- a/include/PartitionManager/PartitionManager.h +++ b/include/PartitionManager/PartitionManager.h @@ -29,7 +29,6 @@ #include #include #include - #ifdef IS_MAIN #include #endif @@ -54,8 +53,6 @@ #endif #ifdef INC_TOOLS_REQS #include - - typedef unsigned short ushort_t; #endif #ifdef INC_LIBGEN #include @@ -71,11 +68,38 @@ typedef enum { LOG_LEVEL_DEBUG } LogLevel; +/* config structure */ +struct Configuration { + bool UseLogical; + bool UseCustomSearchPath; + bool UsesSlots; + bool UsesLogical; + bool OnlyViewSize; + bool SilentEnabled; + bool FlashMode; + bool BackupMode; + bool FormatMode; + bool PartSizeViewMode; + bool ForceMode; + bool VerboseMode; + bool InstalledOnTermux; +}; + /** - * Fast error processing without errno entry + * Fast error processing without errno entry * but errno can be given in the entrance */ -extern "C" char* strqerror(int errno_macro = errno); +extern "C" char* strqerror(int __qerrno = errno); + +/** + * ushort_t = unsigned short type + */ +typedef unsigned short ushort_t; + +/** + * bool type configurations + */ +extern struct Configuration Config; /* create a special namespace */ namespace PartitionManager { @@ -94,22 +118,6 @@ namespace PartitionManager { extern int PartSizeViewType; } /* namespace Integers */ - namespace Booleans { - extern bool UseLogical; - extern bool UseCustomSearchPath; - extern bool UsesSlots; - extern bool UsesLogical; - extern bool OnlyViewSize; - extern bool SilentEnabled; - extern bool FlashMode; - extern bool BackupMode; - extern bool FormatMode; - extern bool PartSizeViewMode; - extern bool ForceMode; - extern bool VerboseMode; - extern bool InstalledOnTermux; - } /* namespace Booleans */ - namespace Display { extern struct langdb_general* UsingDispString; extern struct langdb_docs* UsingDocDispString; @@ -119,39 +127,37 @@ namespace PartitionManager { extern struct langdb_docs LangDocTr; } /* namespace Display */ - namespace Functions { - int ListPartitions(void); - int GetState(const string& filepath, const string& stype = "file"); - int Start(unsigned short progress_code); - void SetLanguage(const string& lang, unsigned short null_conf_stat); - void DisplayLog(LogLevel status, const char* fmt, ...); - void DisplayVerboseLog(LogLevel status, const char* fmt, ...); - void CheckDevPoint(void); - void CheckRoot(void); - bool CleanSWPoint(void); - bool LoadLanguage(void); - } /* namespace Functions */ - + /* functions */ + int ListPartitions(void); + int GetState(const string& filepath, const string& stype = "file"); + int PartitionManagerMain(const ushort_t& progress_code); + void SetLanguage(const string& lang, ushort_t null_conf_stat); + void DisplayLog(LogLevel LogPriority, const char* fmt, ...); + void DisplayVerboseLog(LogLevel LogPriority, const char* func, const int& line, const char* fmt, ...); + void CheckDevPoint(void); + void CheckRoot(void); + bool CleanSWPoint(void); + bool LoadLanguage(void); } /* namespace PartitionManager */ /* logging macros */ #define LOGF(fmt, ...) \ - PartitionManager::Functions::DisplayLog(LOG_LEVEL_FATAL, fmt, ##__VA_ARGS__) + ((void)PartitionManager::DisplayLog(LOG_LEVEL_FATAL, (fmt)__VA_OPT__(, ) __VA_ARGS__)) #define LOGE(fmt, ...) \ - PartitionManager::Functions::DisplayLog(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__) + ((void)PartitionManager::DisplayLog(LOG_LEVEL_ERROR, (fmt)__VA_OPT__(, ) __VA_ARGS__)) #define LOGW(fmt, ...) \ - PartitionManager::Functions::DisplayLog(LOG_LEVEL_WARN, fmt, ##__VA_ARGS__) + ((void)PartitionManager::DisplayLog(LOG_LEVEL_WARN, (fmt)__VA_OPT__(, ) __VA_ARGS__)) #define LOGD(fmt, ...) \ - PartitionManager::Functions::DisplayLog(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__) + ((void)PartitionManager::DisplayLog(LOG_LEVEL_DEBUG, (fmt)__VA_OPT__(, ) __VA_ARGS__)) /* verbose logging macros */ #define VLOGF(fmt, ...) \ - PartitionManager::Functions::DisplayVerboseLog(LOG_LEVEL_FATAL, fmt, ##__VA_ARGS__) + ((void)PartitionManager::DisplayVerboseLog(LOG_LEVEL_FATAL, __func__, __LINE__, (fmt)__VA_OPT__(, ) __VA_ARGS__)) #define VLOGE(fmt, ...) \ - PartitionManager::Functions::DisplayVerboseLog(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__) + ((void)PartitionManager::DisplayVerboseLog(LOG_LEVEL_ERROR, __func__, __LINE__, (fmt)__VA_OPT__(, ) __VA_ARGS__)) #define VLOGW(fmt, ...) \ - PartitionManager::Functions::DisplayVerboseLog(LOG_LEVEL_WARN, fmt, ##__VA_ARGS__) + ((void)PartitionManager::DisplayVerboseLog(LOG_LEVEL_WARN, __func__, __LINE__, (fmt)__VA_OPT__(, ) __VA_ARGS__)) #define VLOGD(fmt, ...) \ - PartitionManager::Functions::DisplayVerboseLog(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__) + ((void)PartitionManager::DisplayVerboseLog(LOG_LEVEL_DEBUG, __func__, __LINE__, (fmt)__VA_OPT__(, ) __VA_ARGS__)) /* end of code */ diff --git a/include/PartitionManager/VersionFnVars.h b/include/PartitionManager/VersionFnVars.h index 58f9dfe..d8d14d4 100755 --- a/include/PartitionManager/VersionFnVars.h +++ b/include/PartitionManager/VersionFnVars.h @@ -25,7 +25,7 @@ /* versioning */ #define PMT_MAJOR 2 #define PMT_MINOR 9 -#define PMT_PATCHLEVEL 1 +#define PMT_PATCHLEVEL 6 namespace PartitionManager { namespace Functions { diff --git a/jni/Android.mk b/jni/Android.mk index 0a81da3..1397b4a 100755 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -15,7 +15,7 @@ # limitations under the License. ######## -# 2.9.1 +# 2.9.6 ######## LOCAL_PATH := $(call my-dir) diff --git a/jni/Application.mk b/jni/Application.mk index ac3ede1..e5e12e8 100755 --- a/jni/Application.mk +++ b/jni/Application.mk @@ -15,7 +15,7 @@ # limitations under the License. ######## -# 2.9.1 +# 2.9.6 ######## # architecture diff --git a/jni/PartitionManager/Debug.cpp b/jni/PartitionManager/Debug.cpp index a4e527b..676c2a4 100755 --- a/jni/PartitionManager/Debug.cpp +++ b/jni/PartitionManager/Debug.cpp @@ -24,82 +24,66 @@ using namespace PartitionManager; /* it's prints standart logs */ -void Functions::DisplayLog(LogLevel status, const char* _Nullable fmt, ...) +void PartitionManager::DisplayLog(LogLevel LogPriority, const char* _Nonnull fmt, ...) { va_list args; va_start(args, fmt); - switch (status) + if (!Config.SilentEnabled) { + switch (LogPriority) + { case LOG_LEVEL_ERROR: - if (!Booleans::SilentEnabled) - { - fprintf(stderr, "%s: ", Strings::ExecutingName.c_str()); - vfprintf(stderr, fmt, args); - } - exit(1); + fprintf(stderr, "%s: ", Strings::ExecutingName.c_str()); + vfprintf(stderr, fmt, args); break; case LOG_LEVEL_WARN: - if (!Booleans::SilentEnabled) - { - fprintf(stdout, "%s: ", Display::UsingDispString->warn); - vfprintf(stdout, fmt, args); - } + 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(); + fprintf(stderr, "%s: ", Display::UsingDispString->fatal); + vfprintf(stderr, fmt, args); break; case LOG_LEVEL_DEBUG: - if (!Booleans::SilentEnabled) - vfprintf(stdout, fmt, args); + vfprintf(stdout, fmt, args); break; + } } + if (LogPriority == LOG_LEVEL_ERROR) exit(1); + else if (LogPriority == LOG_LEVEL_FATAL) abort(); + va_end(args); } /* it's prints verbose logs */ -void Functions::DisplayVerboseLog(LogLevel status, const char* fmt, ...) +void PartitionManager::DisplayVerboseLog(LogLevel LogPriority, const char* func, const int& line, const char* _Nonnull fmt, ...) { va_list args; va_start(args, fmt); - switch (status) + if (Config.VerboseMode) { - case LOG_LEVEL_ERROR: - if (Booleans::VerboseMode) - { - fprintf(stderr, "E:[stderr]: "); - vfprintf(stderr, fmt, args); - } + switch (LogPriority) + { + case LOG_LEVEL_ERROR: + fprintf(stderr, " [%s() Line<%d>]: ", func, line); + vfprintf(stderr, fmt, args); break; case LOG_LEVEL_WARN: - if (Booleans::VerboseMode) - { - fprintf(stdout, "W:[stdout]: "); - vfprintf(stdout, fmt, args); - } + fprintf(stdout, " [%s() Line<%d>]: ", func, line); + vfprintf(stdout, fmt, args); break; case LOG_LEVEL_FATAL: - if (Booleans::VerboseMode) - { - fprintf(stderr, "F:[stderr]: "); - vfprintf(stderr, fmt, args); - abort(); - } + fprintf(stderr, " [%s() Line<%d>]: ", func, line); + vfprintf(stderr, fmt, args); break; case LOG_LEVEL_DEBUG: - if (Booleans::VerboseMode) - { - fprintf(stdout, "D:[stdout]: "); - vfprintf(stdout, fmt, args); - } + fprintf(stdout, " [%s() Line<%d>]: ", func, line); + vfprintf(stdout, fmt, args); break; + } } va_end(args); @@ -109,6 +93,6 @@ void Functions::DisplayVerboseLog(LogLevel status, const char* fmt, ...) * 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); } +char* strqerror(int __qerrno) { return strerror(__qerrno); } /* end of code */ diff --git a/jni/PartitionManager/GetState.cpp b/jni/PartitionManager/GetState.cpp index b3dc508..04bed8d 100755 --- a/jni/PartitionManager/GetState.cpp +++ b/jni/PartitionManager/GetState.cpp @@ -29,15 +29,13 @@ * 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) +int PartitionManager::GetState(const string& filepath, const string& stype) { - static struct stat GetStat; + struct stat GetStat; + VLOGD("Checking `%s' with 'stat '...\n", filepath.c_str()); - VLOGD("GetStat: checking `%s' with 'stat '...\n", filepath.c_str()); - if (stat(filepath.c_str(), &GetStat) != 0) - return 1; - - if (stype == "dir") + 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; @@ -45,10 +43,9 @@ int PartitionManager::Functions::GetState(const string& filepath, const string& return (S_ISBLK(GetStat.st_mode)) ? 0 : -1; else if (stype == "link") return (S_ISLNK(GetStat.st_mode)) ? 0 : -1; - else - return 3; + else return 3; - return 2; + return 2; /* it's a dummy value */ } /* end of code */ diff --git a/jni/PartitionManager/Help.cpp b/jni/PartitionManager/Help.cpp index 667ebe2..c60112e 100755 --- a/jni/PartitionManager/Help.cpp +++ b/jni/PartitionManager/Help.cpp @@ -28,7 +28,7 @@ using namespace PartitionManager; struct langdb_docs* Display::UsingDocDispString = nullptr; static void -prepare_langconf_docs(void) +PrepareLangconfDocs(void) { if (Strings::CurrentLanguage == "en") Display::UsingDocDispString = &Display::LangDocEn; @@ -36,11 +36,11 @@ prepare_langconf_docs(void) Display::UsingDocDispString = &Display::LangDocTr; } -void Functions::DisplayHelp(void) +void PartitionManager::DisplayHelp(void) { - VLOGD("DisplayHelp: Loading language for help messages... Calling prepare_langconf_docs() ...\n"); - prepare_langconf_docs(); - VLOGD("DisplayHelp: Printing...\n"); + VLOGD("Loading language for help messages... Calling PrepareLangconfDocs() ...\n"); + PrepareLangconfDocs(); + VLOGD("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); diff --git a/jni/PartitionManager/LanguageTools.cpp b/jni/PartitionManager/LanguageTools.cpp index 3128ca8..4b9e93b 100755 --- a/jni/PartitionManager/LanguageTools.cpp +++ b/jni/PartitionManager/LanguageTools.cpp @@ -42,7 +42,7 @@ string supp_langs[] = { static bool InternalStorageDirFound(void) { - return (Functions::GetState(INTERNAL_STORAGE_DIR, "dir") == 0) ? true : false; + return (GetState(INTERNAL_STORAGE_DIR, "dir") == 0) ? true : false; } static bool @@ -57,29 +57,29 @@ LanguageControl(const string& lang) return false; } -bool Functions::LoadLanguage(void) +bool PartitionManager::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("Checking install type...\n"); + if (GetState(TERMUX_PMT_MANDOC) == 0) + Config.InstalledOnTermux = true; - VLOGD("LoadLanguage: checking internal storage dir: `%s'\n", INTERNAL_STORAGE_DIR); + VLOGD("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); + LOGE("PartitionManagerLanguageTools: İnternal storage directory (`%s') not found or accessible.\n", INTERNAL_STORAGE_DIR); - VLOGD("LoadLanguage: trying to open `%s' with 'open '\n", PMTLANG_CONF); + VLOGD("Trying to open `%s' with 'open '\n", PMTLANG_CONF); langconf.open(PMTLANG_CONF, ios::in | ios::out); - VLOGD("LoadLanguage: checking status: `%s'...\n", PMTLANG_CONF); + VLOGD("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); + VLOGD("Calling SetLanguage()...\n"); + SetLanguage("en", 1); Display::UsingDispString = &Display::LangEn; Strings::CurrentLanguage = "en"; @@ -90,7 +90,7 @@ bool Functions::LoadLanguage(void) } else { - VLOGD("LoadLanguage: reading `%s'\n", PMTLANG_CONF); + VLOGD("Reading `%s'\n", PMTLANG_CONF); while (getline(langconf, lang_fpr)) { if (lang_fpr == "en") @@ -99,20 +99,20 @@ bool Functions::LoadLanguage(void) goto SetTr; else { - VLOGD("LoadLanguage: calling SetLanguage()\n"); - Functions::SetLanguage("en", 1); - VLOGD("LoadLanguage: re-calling LoadLanguage()\n"); - Functions::LoadLanguage(); + VLOGD("Calling SetLanguage()\n"); + SetLanguage("en", 1); + VLOGD("Re-calling LoadLanguage()\n"); + PartitionManager::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(); + VLOGD("Calling SetLanguage()\n"); + SetLanguage("en", 1); + VLOGD("Re-calling LoadLanguage()\n"); + PartitionManager::LoadLanguage(); return true; } } @@ -121,38 +121,38 @@ SetEn: langconf.close(); Display::UsingDispString = &Display::LangEn; Strings::CurrentLanguage = "en"; - VLOGD("LoadLanguage: loaded \"en\"\n"); + VLOGD("Loaded \"en\"\n"); return true; SetTr: langconf.close(); Display::UsingDispString = &Display::LangTr; Strings::CurrentLanguage = "tr"; - VLOGD("LoadLanguage: loaded \"tr\"\n"); + VLOGD("Loaded \"tr\"\n"); return true; return false; } -void Functions::SetLanguage(const string& lang, unsigned short null_conf_stat) +void PartitionManager::SetLanguage(const string& lang, ushort_t null_conf_stat) { - VLOGD("SetLanguage: checking speficed language (from input).\n"); + VLOGD("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); + VLOGD("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); + LOGE("PartitionManagerSetLanguage: Internal storage directory (`%s') not found or accessible.\n", INTERNAL_STORAGE_DIR); - VLOGD("SetLanguage: trying to open `%s' with 'open '\n", PMTLANG_CONF); + VLOGD("Trying to open `%s' with 'open '\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 '\n", lang.c_str(), PMTLANG_CONF); + VLOGD("Write \"%s\" to `%s' with 'std '\n", lang.c_str(), PMTLANG_CONF); langconf << lang; if (!langconf) LOGE("PartitionManagerLanguageTools: Couldn't write config!!!\n"); @@ -161,23 +161,23 @@ void Functions::SetLanguage(const string& lang, unsigned short null_conf_stat) if (null_conf_stat != 1) { - VLOGD("SetLanguage: generating dummy file `%s' with 'ofstream '\n", PMT_SW_POINT); + VLOGD("Generating dummy file `%s' with 'ofstream '\n", PMT_SW_POINT); ofstream sw_point(PMT_SW_POINT, ios::trunc); if (sw_point.is_open()) sw_point.close(); } } -bool Functions::CleanSWPoint(void) +bool PartitionManager::CleanSWPoint(void) { - if (Functions::GetState(PMT_SW_POINT) == 0) + if (GetState(PMT_SW_POINT) == 0) { - VLOGD("CleanSWPoint: removing (force) `%s' with 'remove '\n", PMT_SW_POINT); + VLOGD("Removing (force) `%s' with 'remove '\n", PMT_SW_POINT); remove(PMT_SW_POINT); return true; } - else - return false; + + return false; } /* end of code */ diff --git a/jni/PartitionManager/ListPartitions.cpp b/jni/PartitionManager/ListPartitions.cpp index 12a05c9..4ad4eb9 100755 --- a/jni/PartitionManager/ListPartitions.cpp +++ b/jni/PartitionManager/ListPartitions.cpp @@ -80,15 +80,15 @@ directory: } /* list existing partitions */ -int Functions::ListPartitions(void) +int PartitionManager::ListPartitions(void) { - VLOGD("ListPartitions: selecting search path...\n"); - string AccessDir = (Booleans::UseCustomSearchPath) ? Strings::CustomSearchPath : CUR_DEV_SP; + VLOGD("Selecting search path...\n"); + string AccessDir = (Config.UseCustomSearchPath) ? Strings::CustomSearchPath : CUR_DEV_SP; - VLOGD("ListPartitions: trying to access `%s'...\n", AccessDir.c_str()); + VLOGD("Trying to access `%s'...\n", AccessDir.c_str()); if (ListDir(AccessDir) != 0) { - if (!Booleans::ForceMode) + if (!Config.ForceMode) LOGE("%s: `%s': %s\n", Display::UsingDispString->not_open, AccessDir.c_str(), @@ -102,9 +102,9 @@ int Functions::ListPartitions(void) ListDir(AccessDir, true); } - if (Booleans::UsesLogical) + if (Config.UsesLogical) { - VLOGD("ListPartitions: checking for listing `%s'...\n", LGC_DEV_SP); + VLOGD("Checking for listing `%s'...\n", LGC_DEV_SP); if (ListDir(LGC_DEV_SP) != 0) LOGE("%s: `%s': %s\n", @@ -118,17 +118,17 @@ int Functions::ListPartitions(void) } } - VLOGD("ListPartitions: (if have) warnings are printed...\n"); + VLOGD("(if have) warnings are printed...\n"); - if (Booleans::UsesLogical) + if (Config.UsesLogical) { LOGD("\n"); LOGW("%s\n", Display::UsingDispString->logical_warn); } - if (Booleans::UsesSlots) + if (Config.UsesSlots) { - if (!Booleans::UsesSlots) + if (!Config.UsesLogical) LOGD("\n"); LOGW("%s\n", Display::UsingDispString->ab_warn); diff --git a/jni/PartitionManager/PartitionManager.cpp b/jni/PartitionManager/PartitionManager.cpp index 3a20a7e..535a919 100755 --- a/jni/PartitionManager/PartitionManager.cpp +++ b/jni/PartitionManager/PartitionManager.cpp @@ -42,32 +42,45 @@ namespace PartitionManager { 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 */ +/* configure struct body */ +struct Configuration Config { + .UseLogical = false, + .UseCustomSearchPath = false, + .UsesSlots = false, + .UsesLogical = false, + .OnlyViewSize = false, + .SilentEnabled = false, + .FlashMode = false, + .BackupMode = false, + .FormatMode = false, + .PartSizeViewMode = false, + .ForceMode = false, + .VerboseMode = false, + .InstalledOnTermux = false +}; + +/* some variables. for parsing and processing arguments */ +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 string SymbolRule; +static int StdinArgcTotal; +static int SearchOnMainInt; namespace PartitionManager { -namespace Functions { /** * He controls whether the '-' sign at @@ -84,19 +97,17 @@ CheckOptSymbol(const string& Symbol) } static bool -ControlArg(const char* ArgvHolder) +ControlArg(char* &ArgvHolder) { - if (ArgvHolder[0] != '-') - return true; + 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") +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); @@ -107,13 +118,11 @@ deprecated(const char opt, const char* deprecation_message, const char* opt_long static void PrSpInput(const string& sp) { - PartitionManager::Booleans::UseCustomSearchPath = true; + Config.UseCustomSearchPath = true; PartitionManager::Strings::CustomSearchPath = sp; - PartitionManager::Functions::CheckOptSymbol(PartitionManager::Strings::CustomSearchPath); + PartitionManager::CheckOptSymbol(PartitionManager::Strings::CustomSearchPath); } -using namespace PartitionManager; - class PartitionManagerBase { protected: char* BaseFunctionName = nullptr; @@ -123,15 +132,15 @@ protected: public: void CallTargetBaseFunction(void) { - VLOGD("CallTargetBaseFunction [class]: Start(%d)\n", StartCode); - Functions::Start(StartCode); + VLOGD("[class]: Call PartitionManagerMain(%d)\n", StartCode); + PartitionManager::PartitionManagerMain(StartCode); } - void GenericNumericalController(int searchOn, int total, const char* MissingArgMessage) + void GenericNumericalController(int& searchOn, int& total, const char* &MissingArgMessage) { if (total <= searchOn) { - VLOGE("ArgumentProcessor [class]: Missing argument total (for %s function).\n", BaseFunctionName); + VLOGE("[class]: Missing argument total (for %s function).\n", BaseFunctionName); LOGE("%s 0.\n", MissingArgMessage); } @@ -139,139 +148,192 @@ public: { if (total <= (searchOn + 1)) { - VLOGE("ArgumentProcessor [class]: Missing argument total (for %s function).\n", BaseFunctionName); + VLOGE("[class]: Missing argument total (for %s function).\n", BaseFunctionName); LOGE("%s 1.\n", MissingArgMessage); } } } - virtual void ArgumentProcessor(int searchOn, int total, char** arguments) { /* dummy */ } + virtual void ArgumentProcessor(int& searchOn, int& total, char** &arguments) { /* dummy */ } }; class PartitionManagerBackup : public PartitionManagerBase { public: - void ArgumentProcessor(int searchOn, int total, char** arguments) override + void ArgumentProcessor(int& searchOn, int& total, char** &arguments) override { BaseFunctionName = "backup"; StartCode = 1; IsRequiredOnlyOneArg = true; - GenericNumericalController(searchOn, total, Display::UsingDispString->expected_backup_arg); + GenericNumericalController(searchOn, total, PartitionManager::Display::UsingDispString->expected_backup_arg); - if (Functions::ControlArg(arguments[searchOn])) - Strings::TargetPartition = arguments[searchOn]; + if (PartitionManager::ControlArg(arguments[searchOn])) + PartitionManager::Strings::TargetPartition = arguments[searchOn]; else - LOGE("%s.\n", Display::UsingDispString->not_spec_opt); + LOGE("%s.\n", PartitionManager::Display::UsingDispString->not_spec_opt); - Strings::OutputName = Strings::TargetPartition; + PartitionManager::Strings::OutputName = PartitionManager::Strings::TargetPartition; - if (total > (searchOn + 1) && Functions::ControlArg(arguments[(searchOn + 1)])) + if (total > (searchOn + 1) && PartitionManager::ControlArg(arguments[(searchOn + 1)])) { - VLOGD("ArgumentProcessor [class]: Non-mandatory argument was detected and retrieved (for %s function).\n", BaseFunctionName); - Strings::OutputName = arguments[(searchOn + 1)]; + VLOGD("[class]: Non-mandatory argument was detected and retrieved (for %s function).\n", BaseFunctionName); + PartitionManager::Strings::OutputName = arguments[(searchOn + 1)]; } - Functions::CheckOptSymbol(Strings::TargetPartition); - Functions::CheckOptSymbol(Strings::OutputName); + PartitionManager::CheckOptSymbol(PartitionManager::Strings::TargetPartition); + PartitionManager::CheckOptSymbol(PartitionManager::Strings::OutputName); } }; class PartitionManagerFlash : public PartitionManagerBase { public: - void ArgumentProcessor(int searchOn, int total, char** arguments) override + void ArgumentProcessor(int& searchOn, int& total, char** &arguments) override { BaseFunctionName = "flash"; StartCode = 2; IsRequiredOnlyOneArg = false; - GenericNumericalController(searchOn, total, Display::UsingDispString->expected_flash_arg); + GenericNumericalController(searchOn, total, PartitionManager::Display::UsingDispString->expected_flash_arg); - if (Functions::ControlArg(arguments[searchOn])) - Strings::TargetPartition = arguments[searchOn ]; + if (PartitionManager::ControlArg(arguments[searchOn])) + PartitionManager::Strings::TargetPartition = arguments[searchOn]; else - LOGE("%s.\n", Display::UsingDispString->not_spec_opt); + LOGE("%s.\n", PartitionManager::Display::UsingDispString->not_spec_opt); - if (Functions::ControlArg(arguments[(searchOn + 1)])) - Strings::TargetFlashFile = arguments[(searchOn + 1)]; + if (PartitionManager::ControlArg(arguments[(searchOn + 1)])) + PartitionManager::Strings::TargetFlashFile = arguments[(searchOn + 1)]; else - LOGE("%s.\n", Display::UsingDispString->not_spec_opt); + LOGE("%s.\n", PartitionManager::Display::UsingDispString->not_spec_opt); - Functions::CheckOptSymbol(Strings::TargetFlashFile); - Functions::CheckOptSymbol(Strings::TargetPartition); + PartitionManager::CheckOptSymbol(PartitionManager::Strings::TargetFlashFile); + PartitionManager::CheckOptSymbol(PartitionManager::Strings::TargetPartition); } }; class PartitionManagerFormat : public PartitionManagerBase { public: - void ArgumentProcessor(int searchOn, int total, char** arguments) override + void ArgumentProcessor(int& searchOn, int& total, char** &arguments) override { BaseFunctionName = "format"; StartCode = 3; IsRequiredOnlyOneArg = false; - GenericNumericalController(searchOn, total, Display::UsingDispString->expected_format_arg); + GenericNumericalController(searchOn, total, PartitionManager::Display::UsingDispString->expected_format_arg); - if (Functions::ControlArg(arguments[searchOn])) - Strings::TargetPartition = arguments[searchOn]; + if (PartitionManager::ControlArg(arguments[searchOn])) + PartitionManager::Strings::TargetPartition = arguments[searchOn]; else - LOGE("%s.\n", Display::UsingDispString->not_spec_opt); + LOGE("%s.\n", PartitionManager::Display::UsingDispString->not_spec_opt); - if (Functions::ControlArg(arguments[(searchOn + 1)])) - Strings::TargetFormatFS = arguments[(searchOn + 1)]; + if (PartitionManager::ControlArg(arguments[(searchOn + 1)])) + PartitionManager::Strings::TargetFormatFS = arguments[(searchOn + 1)]; else - LOGE("%s.\n", Display::UsingDispString->not_spec_opt); + LOGE("%s.\n", PartitionManager::Display::UsingDispString->not_spec_opt); - Functions::CheckOptSymbol(Strings::TargetFormatFS); - Functions::CheckOptSymbol(Strings::TargetPartition); + PartitionManager::CheckOptSymbol(PartitionManager::Strings::TargetFormatFS); + PartitionManager::CheckOptSymbol(PartitionManager::Strings::TargetPartition); } }; class PartitionManagerPartSize : public PartitionManagerBase { public: - void ArgumentProcessor(int searchOn, int total, char** arguments) override + void ArgumentProcessor(int& searchOn, int& total, char** &arguments) override { BaseFunctionName = "partition-size"; StartCode = 4; IsRequiredOnlyOneArg = true; - GenericNumericalController(searchOn, total, Display::UsingDispString->expected_partsz_arg); + GenericNumericalController(searchOn, total, PartitionManager::Display::UsingDispString->expected_partsz_arg); - if (Functions::ControlArg(arguments[searchOn])) - Strings::TargetPartition = arguments[searchOn]; + if (PartitionManager::ControlArg(arguments[searchOn])) + PartitionManager::Strings::TargetPartition = arguments[searchOn]; else - LOGE("%s.\n", Display::UsingDispString->not_spec_opt); + LOGE("%s.\n", PartitionManager::Display::UsingDispString->not_spec_opt); - Functions::CheckOptSymbol(Strings::TargetPartition); + PartitionManager::CheckOptSymbol(PartitionManager::Strings::TargetPartition); } }; -int main(int argc, char** argv) +/* Generate classes */ +PartitionManagerBase* Base; +PartitionManagerBase BaseTemplate; +PartitionManagerBackup BackupArgProcessorBase; +PartitionManagerFlash FlashArgProcessorBase; +PartitionManagerFormat FormatArgProcessorBase; +PartitionManagerPartSize PartSizeArgProcessorBase; + +namespace PartitionManager { + +static void +ParseMainOperations(int argc, char** argv) { - Strings::ExecutingName = basename(argv[0]); + SearchOnMainInt = -1; + Base = &BaseTemplate; - for (int i = 0; i <= (argc - 1); i++) + VLOGD("Starting cycle for trapping main options...\n"); + while (1) { - if (strncmp(argv[i], "-V", 2) == 0 || strcmp(argv[i], "--verbose") == 0) - Booleans::VerboseMode = true; - else + if ((argc - 1) == 0) + { + VLOGD("argc - 1 = 0. Breaking...\n"); + break; + } + + if (argv[(argc - 1)][0] == '-') + { + VLOGD("argv[%d] starts with '-'. Continue.\n", (argc - 1)); + argc--; continue; + } + else + { + Target = argv[(argc - 1)]; + SearchOnMainInt = argc; + VLOGD("argv[%d] = %s\n", (argc - 1), argv[(argc - 1)]); + VLOGD("Variable of \"Target\" (string): %s\n", Target.c_str()); + + if (Target == "backup") + { + Base = &BackupArgProcessorBase; + Config.BackupMode = true; + break; + } + else if (Target == "flash") + { + Base = &FlashArgProcessorBase; + Config.FlashMode = true; + break; + } + else if (Target == "format") + { + Base = &FormatArgProcessorBase; + Config.FormatMode = true; + break; + } + else if (Target == "partition-size") + { + Base = &PartSizeArgProcessorBase; + Config.PartSizeViewMode = true; + break; + } + else + { + Target = ""; + SearchOnMainInt = -1; + argc--; + continue; + } + } + + break; } +} - /* 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 '\n"); - setlocale(LC_ALL, ""); - - int argc_n = argc; +static char** +ParseStdin(int argc, char** argv) +{ + StdinArgcTotal = 0; char buf[256]; - char** args = argv; VLOGD("Checking stdin status...\n"); if (!isatty(fileno(stdin))) @@ -283,80 +345,61 @@ int main(int argc, char** argv) { buf[strcspn(buf, "\n")] = 0; - args[argc_n] = strdup(buf); - argc_n++; + argv[argc] = strdup(buf); + argc++; + StdinArgcTotal++; } 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(); - } + VLOGD("stdin empty.\n"); + return argv; +} - 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; +static void +ParseOptions(int argc, char** argv) +{ + argc--; + argv++; VLOGD("Parsing standart arguments...\n"); - while (argc_parse && args_ctrl[0] != nullptr) + while (argc && argv[0] != nullptr) { - if (args_ctrl[0][0] != '-') + if (argv[0][0] != '-') { - argc_parse--; - args_ctrl++; + argc--; + argv++; continue; } for (int x = 1; true; x++) { - Option = args_ctrl[0]; + Option = argv[0]; SomeSpec = true; - switch (args_ctrl[0][x]) + switch (argv[0][x]) { case '-': if (Option == "--backup") deprecated('b', - Display::UsingDispString->depr_backup_opt, + PartitionManager::Display::UsingDispString->depr_backup_opt, "backup"); else if (Option == "--flash") deprecated('F', - Display::UsingDispString->depr_flash_opt, + PartitionManager::Display::UsingDispString->depr_flash_opt, "flash"); else if (Option == "--format") deprecated('r', - Display::UsingDispString->depr_format_opt, + PartitionManager::Display::UsingDispString->depr_format_opt, "format"); else if (Option == "--license") deprecated('L', - Display::UsingDispString->depr_Vlicense_opt, + PartitionManager::Display::UsingDispString->depr_Vlicense_opt, "license"); else if (Option == "--context") deprecated('c', - Display::UsingDispString->depr_ch_sp_opt, + PartitionManager::Display::UsingDispString->depr_ch_sp_opt, "context"); else if (Option == "--logical") { @@ -367,14 +410,14 @@ int main(int argc, char** argv) else if (Option == "--search-path") { VLOGD("Custom search path specified.\n"); - if (argc_parse > 1) - PrSpInput(args_ctrl[1]); + if (argc > 1) + PrSpInput(argv[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); + PartitionManager::Display::UsingDispString->is_requires_arg, \ + PartitionManager::Display::UsingDispString->try_h, \ + PartitionManager::Strings::ExecutingName.c_str(), \ + PartitionManager::Display::UsingDispString->for_more); break; } else if (Option == "--list") @@ -388,66 +431,66 @@ int main(int argc, char** argv) else if (Option == "--force") { VLOGD("Force mode speficed.\n"); - Booleans::ForceMode = true; + Config.ForceMode = true; break; } else if (Option == "--verbose") { VLOGD("Verbose mode speficed.\n"); - Booleans::VerboseMode = true; + Config.VerboseMode = true; break; } else if (Option == "--silent") { VLOGD("Silent mode speficed.\n"); - Booleans::SilentEnabled = true; + Config.SilentEnabled = true; break; } else if (Option == "--set-language") { VLOGD("It was requested to adjust the language.\n"); - if (argc_parse > 1) + if (argc > 1) { VLOGE("Language inputs: getting inputs...\n"); SetLanguageReq = true; - SpeficedLanguagePr = args_ctrl[1]; + SpeficedLanguagePr = argv[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); + PartitionManager::Display::UsingDispString->is_requires_arg, + PartitionManager::Display::UsingDispString->try_h, + PartitionManager::Strings::ExecutingName.c_str(), + PartitionManager::Display::UsingDispString->for_more); break; } else if (Option == "--as-byte") { PartSizeArgSpeficed = true; - Integers::PartSizeViewType = VIEW_AS_BYTE; + PartitionManager::Integers::PartSizeViewType = VIEW_AS_BYTE; break; } else if (Option == "--as-kilobyte") { PartSizeArgSpeficed = true; - Integers::PartSizeViewType = VIEW_AS_KIB; + PartitionManager::Integers::PartSizeViewType = VIEW_AS_KIB; break; } else if (Option == "--as-megabyte") { PartSizeArgSpeficed = true; - Integers::PartSizeViewType = VIEW_AS_MIB; + PartitionManager::Integers::PartSizeViewType = VIEW_AS_MIB; break; } else if (Option == "--as-gigabyte") { PartSizeArgSpeficed = true; - Integers::PartSizeViewType = VIEW_AS_GIB; + PartitionManager::Integers::PartSizeViewType = VIEW_AS_GIB; break; } else if (Option == "--only-size") { PartSizeArgSpeficed = true; - Booleans::OnlyViewSize = true; + Config.OnlyViewSize = true; break; } else if (Option == "--version") @@ -468,41 +511,41 @@ int main(int argc, char** argv) } 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); + VLOGE("Unknown Option: %s\n", argv[0]); + LOGE("%s: %s.\n%s `%s --help' %s.\n", argv[0], + PartitionManager::Display::UsingDispString->unknw_arg, + PartitionManager::Display::UsingDispString->try_h, + PartitionManager::Strings::ExecutingName.c_str(), + PartitionManager::Display::UsingDispString->for_more); } break; case 'b': deprecated('b', - Display::UsingDispString->depr_backup_opt, + PartitionManager::Display::UsingDispString->depr_backup_opt, "backup"); break; case 'F': deprecated('F', - Display::UsingDispString->depr_flash_opt, + PartitionManager::Display::UsingDispString->depr_flash_opt, "flash"); break; case 'r': deprecated('r', - Display::UsingDispString->depr_format_opt, + PartitionManager::Display::UsingDispString->depr_format_opt, "format"); break; case 'L': deprecated('L', - Display::UsingDispString->depr_Vlicense_opt, + PartitionManager::Display::UsingDispString->depr_Vlicense_opt, "license"); break; case 'D': deprecated('D', - Display::UsingDispString->depr_ch_list_opt); + PartitionManager::Display::UsingDispString->depr_ch_list_opt); break; case 'c': deprecated('c', - Display::UsingDispString->depr_ch_sp_opt, + PartitionManager::Display::UsingDispString->depr_ch_sp_opt, "context"); case 'l': VLOGD("Logical partition type specified.\n"); @@ -510,18 +553,18 @@ int main(int argc, char** argv) continue; case 'P': VLOGD("Custom search path speficed.\n"); - if (argc_parse > 1) + if (argc > 1) { VLOGE("Search-path inputs: getting inputs...\n"); - PrSpInput(args_ctrl[1]); + PrSpInput(argv[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); + PartitionManager::Display::UsingDispString->is_requires_arg, + PartitionManager::Display::UsingDispString->try_h, + PartitionManager::Strings::ExecutingName.c_str(), + PartitionManager::Display::UsingDispString->for_more); break; case 'p': VLOGD("It was requested to list the partitions.\n"); @@ -531,31 +574,31 @@ int main(int argc, char** argv) continue; case 'f': VLOGD("Force mode speficed.\n"); - Booleans::ForceMode = true; + Config.ForceMode = true; continue; case 'V': VLOGD("Verbose mode speficed.\n"); - Booleans::VerboseMode = true; + Config.VerboseMode = true; continue; case 's': VLOGD("Silent mode speficed.\n"); - Booleans::SilentEnabled = true; + Config.SilentEnabled = true; continue; case 'S': VLOGD("It was requested to adjust the language.\n"); - if (argc_parse > 1) + if (argc > 1) { VLOGE("Language inputs: getting inputs...\n"); SetLanguageReq = true; - SpeficedLanguagePr = args_ctrl[1]; + SpeficedLanguagePr = argv[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); + PartitionManager::Display::UsingDispString->is_requires_arg, + PartitionManager::Display::UsingDispString->try_h, + PartitionManager::Strings::ExecutingName.c_str(), + PartitionManager::Display::UsingDispString->for_more); case 'v': VLOGD("The version info was requested to be displayed.\n"); ViewVersion = true; @@ -565,162 +608,137 @@ int main(int argc, char** argv) case '\0': break; default: - VLOGE("Unknown Option: -%c\n", args_ctrl[0][x]); + VLOGE("Unknown Option: -%c\n", argv[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); + argv[0][x], + PartitionManager::Display::UsingDispString->unknw_arg, + PartitionManager::Display::UsingDispString->try_h, + PartitionManager::Strings::ExecutingName.c_str(), + PartitionManager::Display::UsingDispString->for_more); } break; } - argc_parse--; - args_ctrl++; + argc--; + argv++; } +} - Base = &BaseTemplate; - argc_parse = argc; +} /* namespace PartitionManager */ - VLOGD("Starting cycle for trapping main options...\n"); - while (1) +int main(int argc, char** argv) +{ + PartitionManager::Strings::ExecutingName = basename(argv[0]); + + for (int i = 0; i <= (argc - 1); i++) { - 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; - } + if (strncmp(argv[i], "-V", 2) == 0 || strcmp(argv[i], "--verbose") == 0) + Config.VerboseMode = true; 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; + continue; } - if (Booleans::SilentEnabled && Booleans::VerboseMode) + VLOGD("Main function started. Setting up locale. Calling 'setlocale '\n"); + setlocale(LC_ALL, ""); + + char** args = PartitionManager::ParseStdin(argc, argv); + argc = (argc + StdinArgcTotal); + /* It's not gonna be okay even 0. */ + + /* load language */ + VLOGD("Loading language... Calling LoadLanguage()...\n"); + if (!PartitionManager::LoadLanguage()) + { + cout << "LoadLanguage() process failed..!" << endl; + abort(); + } + + SymbolRule = PartitionManager::Display::UsingDispString->symbol_rule; + int SearchResult = 3; + + PartitionManager::ParseOptions(argc, argv); + PartitionManager::ParseMainOperations(argc, argv); + + if (Config.SilentEnabled && Config.VerboseMode) { VLOGE("Silent and verbose mode is one-way.\n"); - cout << Strings::ExecutingName << ": " << Display::UsingDispString->s_and_v << endl; + cout << PartitionManager::Strings::ExecutingName << ": " << PartitionManager::Display::UsingDispString->s_and_v << endl; exit(1); } VLOGD("Checking last language switch status...\n"); - if (Functions::CleanSWPoint()) + if (PartitionManager::CleanSWPoint()) { VLOGD("Last transactions found that language was changed between.\n"); - if (Display::UsingDispString->welcome_ != nullptr) - LOGD("%s", Display::UsingDispString->welcome_); + if (PartitionManager::Display::UsingDispString->welcome_ != nullptr) + LOGD("%s", PartitionManager::Display::UsingDispString->welcome_); LOGD("%s %s %s %s.\n", - Display::UsingDispString->language, - Display::UsingDispString->welcome, - Display::UsingDispString->by_str, - Display::UsingDispString->lang_by_s); + PartitionManager::Display::UsingDispString->language, + PartitionManager::Display::UsingDispString->welcome, + PartitionManager::Display::UsingDispString->by_str, + PartitionManager::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); + PartitionManager::Display::UsingDispString->missing_operand, + PartitionManager::Display::UsingDispString->try_h, + PartitionManager::Strings::ExecutingName.c_str(), + PartitionManager::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); + LOGE("%s\n", PartitionManager::Display::UsingDispString->multiple_wiewers); } - if (!Booleans::PartSizeViewMode && PartSizeArgSpeficed) + if (!Config.PartSizeViewMode && PartSizeArgSpeficed) { VLOGE("Related flags were detected, although some partition size was not requested.\n"); - LOGE("%s.\n", Display::UsingDispString->only_partsz_args); + LOGE("%s.\n", PartitionManager::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(); + PartitionManager::DisplayHelp(); return 0; } else if (ViewVersion) { VLOGD("The version info message was asked to display. It's displayed... Calling DisplayVersion()\n"); - Functions::DisplayVersion(); + PartitionManager::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(); + PartitionManager::CheckRoot(); VLOGD("CheckRoot() completed.\n"); - Functions::CheckDevPoint(); + PartitionManager::CheckDevPoint(); VLOGD("CheckDevPoint() completed.\n"); - return Functions::ListPartitions(); + return PartitionManager::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); + PartitionManager::Strings::ExecutingName.c_str(), + PartitionManager::Display::UsingDispString->switching_lang); + PartitionManager::SetLanguage(SpeficedLanguagePr, 0); sleep(2); VLOGD("SetLanguage() completed.\n"); LOGD("%s: %s.\n", - Strings::ExecutingName.c_str(), - Display::UsingDispString->please_rerun); + PartitionManager::Strings::ExecutingName.c_str(), + PartitionManager::Display::UsingDispString->please_rerun); return 0; } @@ -728,99 +746,99 @@ int main(int argc, char** argv) { VLOGE("There's no job to do.\n"); LOGD("%s: %s.\n", - Strings::ExecutingName.c_str(), - Display::UsingDispString->missing_operand); + PartitionManager::Strings::ExecutingName.c_str(), + PartitionManager::Display::UsingDispString->missing_operand); if (SomeSpec) - LOGD("%s.\n", Display::UsingDispString->some_spec); + LOGD("%s.\n", PartitionManager::Display::UsingDispString->some_spec); LOGD("%s '%s --help' %s.\n", - Display::UsingDispString->try_h, - Strings::ExecutingName.c_str(), - Display::UsingDispString->for_more); + PartitionManager::Display::UsingDispString->try_h, + PartitionManager::Strings::ExecutingName.c_str(), + PartitionManager::Display::UsingDispString->for_more); exit(1); } Base->ArgumentProcessor(SearchOnMainInt, argc, args); - if (Booleans::FormatMode) + if (Config.FormatMode) { VLOGD("File system name specified for formatting is being contaminated...\n"); - if (Strings::TargetFormatFS != "ext4" \ - && Strings::TargetFormatFS != "ext3" \ - && Strings::TargetFormatFS != "ext2") + if (PartitionManager::Strings::TargetFormatFS != "ext4" \ + && PartitionManager::Strings::TargetFormatFS != "ext3" \ + && PartitionManager::Strings::TargetFormatFS != "ext2") { - VLOGE("Unsupported file system: %s.\n", Strings::TargetFormatFS.c_str()); + VLOGE("Unsupported file system: %s.\n", PartitionManager::Strings::TargetFormatFS.c_str()); LOGE("%s: %s\n", - Display::UsingDispString->unsupported_fs, - Strings::TargetFormatFS.c_str()); + PartitionManager::Display::UsingDispString->unsupported_fs, + PartitionManager::Strings::TargetFormatFS.c_str()); } } /* checks */ VLOGD("Checking root status... Calling CheckRoot()...\n"); - Functions::CheckRoot(); + PartitionManager::CheckRoot(); VLOGD("Checking A/B and logical device status... Calling CheckDevPoint()...\n"); - Functions::CheckDevPoint(); + PartitionManager::CheckDevPoint(); if (LogicalSpeficy) { VLOGD("Logical partition type speficed. Checking partition statust's...\n"); - if (Booleans::UsesLogical) - Booleans::UseLogical = true; + if (Config.UsesLogical) + Config.UseLogical = true; else - LOGE("%s\n", Display::UsingDispString->not_logical); + LOGE("%s\n", PartitionManager::Display::UsingDispString->not_logical); } - if (Booleans::FlashMode) + if (Config.FlashMode) { VLOGD("The status of the specified file for flashing is being checked...\n"); - SearchResult = Functions::GetState(Strings::TargetFlashFile); + SearchResult = PartitionManager::GetState(PartitionManager::Strings::TargetFlashFile); if (SearchResult == 1) LOGE("%s: `%s': %s\n", - Display::UsingDispString->cannot_stat, - Strings::TargetFlashFile.c_str(), + PartitionManager::Display::UsingDispString->cannot_stat, + PartitionManager::Strings::TargetFlashFile.c_str(), strqerror()); else if (SearchResult == -1) LOGE("`%s': %s\n", - Strings::TargetFlashFile.c_str(), - Display::UsingDispString->not_file); + PartitionManager::Strings::TargetFlashFile.c_str(), + PartitionManager::Display::UsingDispString->not_file); } /* custom search path checker */ - if (Booleans::UseCustomSearchPath) + if (Config.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 (strncmp(PartitionManager::Strings::CustomSearchPath.c_str(), "/dev", 4) != 0) { - if (!Booleans::ForceMode) - LOGE("%s\n", Display::UsingDispString->not_in_dev); + if (!Config.ForceMode) + LOGE("%s\n", PartitionManager::Display::UsingDispString->not_in_dev); } VLOGD("The specified custom /dev search path is being put in countless...\n"); - SearchResult = Functions::GetState(Strings::CustomSearchPath, "dir"); + SearchResult = PartitionManager::GetState(PartitionManager::Strings::CustomSearchPath, "dir"); if (SearchResult == 1) LOGE("%s: `%s': %s\n", - Display::UsingDispString->cannot_stat, - Strings::CustomSearchPath.c_str(), + PartitionManager::Display::UsingDispString->cannot_stat, + PartitionManager::Strings::CustomSearchPath.c_str(), strqerror()); else if (SearchResult == -1) LOGE("`%s': %s\n", - Strings::CustomSearchPath.c_str(), - Display::UsingDispString->not_dir); + PartitionManager::Strings::CustomSearchPath.c_str(), + PartitionManager::Display::UsingDispString->not_dir); } VLOGD("The partition specification status is controlled...\n"); - if (Strings::TargetPartition.empty()) + if (PartitionManager::Strings::TargetPartition.empty()) { - if (!Booleans::ForceMode) + if (!Config.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); + PartitionManager::Display::UsingDispString->req_part_name, + PartitionManager::Display::UsingDispString->try_h, + PartitionManager::Strings::ExecutingName.c_str(), + PartitionManager::Display::UsingDispString->for_more); } else { diff --git a/jni/PartitionManager/PartitionTool.cpp b/jni/PartitionManager/PartitionTool.cpp index d717010..36261be 100755 --- a/jni/PartitionManager/PartitionTool.cpp +++ b/jni/PartitionManager/PartitionTool.cpp @@ -22,49 +22,49 @@ #include static int -GetProperty(const char* _Nonnull property, const char* desired_val, const char* desired_val2 = nullptr) +GetProperty(const char* _Nonnull property, const char* _Nonnull val1, const char* _Nullable val2 = nullptr) { char val[PROP_VALUE_MAX]; int len = __system_property_get(property, val); - VLOGD("GetProperty: get property value: '%s'\n", property); + VLOGD("Get property value: '%s'\n", property); if (len > 0) { - VLOGD("GetProperty: %s=%s\n", property, val); + VLOGD("%s=%s\n", property, val); - VLOGD("GetProperty: comparing '%s' property value '%s'\n", property, desired_val); - if (strcmp(val, desired_val) == 0) + VLOGD("Comparing '%s' property value '%s'\n", property, val1); + if (strcmp(val, val1) == 0) { - VLOGD("GetProperty: '%s' is '%s'. Stop (0).\n", property, desired_val); + VLOGD("'%s' is '%s'. Stop (0).\n", property, val1); return 0; } else { - VLOGE("GetProperty: '%s' property is not '%s'. Comparing desired value 2 (if speficed).\n", property, desired_val); + VLOGE("'%s' property is not '%s'. Comparing desired value 2 (if speficed).\n", property, val1); - if (desired_val2 != nullptr) + if (val2 != nullptr) { - if (strcmp(val, desired_val2) == 0) + if (strcmp(val, val2) == 0) { - VLOGD("GetProperty: '%s' is '%s'.Stop (0).\n", property, desired_val2); + VLOGD("'%s' is '%s'.Stop (0).\n", property, val2); return 0; } else { - VLOGE("GetProperty: '%s' is not '%s'. Stop (1).\n", property, desired_val2); + VLOGE("'%s' is not '%s'. Stop (1).\n", property, val2); return 1; } } else { - VLOGE("GetProperty: '%s' is not '%s'. Stop (1).\n", property, desired_val); + VLOGE("'%s' is not '%s'. Stop (1).\n", property, val1); return 1; } } } else { - VLOGE("GetProperty: cannot get property '%s'. No such property or empty. Stop (1).\n", property); + VLOGE("Cannot get property '%s'. No such property or empty. Stop (1).\n", property); return 1; } @@ -74,19 +74,19 @@ GetProperty(const char* _Nonnull property, const char* desired_val, const char* using namespace PartitionManager; /* check parts */ -void Functions::CheckDevPoint(void) +void PartitionManager::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; + Config.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"); + if (Config.UsesSlots) + VLOGW("1 warning generated: A/B partitions status.\n"); /* true = logical | false = normal */ - Booleans::UsesLogical = (GetProperty("ro.boot.dynamic_partitions", "true") == 0) ? true : false; + Config.UsesLogical = (GetProperty("ro.boot.dynamic_partitions", "true") == 0) ? true : false; - if (Booleans::UsesLogical) - VLOGW("CheckDevPoint: 1 warning generated: logical partitions status.\n"); + if (Config.UsesLogical) + VLOGW("1 warning generated: logical partitions status.\n"); } /* end of code */ diff --git a/jni/PartitionManager/Root.cpp b/jni/PartitionManager/Root.cpp index f6236f1..8646752 100755 --- a/jni/PartitionManager/Root.cpp +++ b/jni/PartitionManager/Root.cpp @@ -23,13 +23,13 @@ #include /* root checker function */ -void PartitionManager::Functions::CheckRoot(void) +void PartitionManager::CheckRoot(void) { - VLOGD("CheckRoot: trying to get UID with 'getuid '\n"); + VLOGD("Trying to get UID with 'getuid '\n"); if (getuid() != 0) { - VLOGE("CheckRoot: cannot get UID. Not executed with root!\n"); + VLOGE("You are not superuser!\n"); LOGE("%s\n", PartitionManager::Display::UsingDispString->no_root); } } diff --git a/jni/PartitionManager/Tools.cpp b/jni/PartitionManager/Tools.cpp index 16a5f7f..51bdbc7 100755 --- a/jni/PartitionManager/Tools.cpp +++ b/jni/PartitionManager/Tools.cpp @@ -27,8 +27,10 @@ #include #include +static fstream sourceF, targetF; +static long long Count; + namespace PartitionManager { -namespace Functions { /** * it is meant to calculate the size of the quickly given file. @@ -37,9 +39,9 @@ namespace Functions { static long long CalculateSizeLongLong(const string& fp) { - VLOGD("CalculateSizeLongLong: calculating file size: `%s'\n", fp.c_str()); + VLOGD("Calculating file size: `%s'\n", fp.c_str()); - VLOGD("CalculateSizeLongLong: reading `%s' with 'ifstream '\n", fp.c_str()); + VLOGD("Reading `%s' with 'ifstream '\n", fp.c_str()); ifstream file(fp, ios::binary | ios::ate); return (!file) ? -1 : static_cast(file.tellg()); @@ -50,23 +52,23 @@ CalculateSizeLongLong(const string& fp) * It's for quick action. */ static void -PartitionNotFound(const char* p) { LOGE("%s: %s\n", p, Display::UsingDispString->part_not_found); } +PartitionNotFound(const string& part) { LOGE("%s: %s\n", part.c_str(), Display::UsingDispString->part_not_found); } /* the partitions are meant to quickly find. */ static void SearchPartition(const string& fp) { - VLOGD("SearchPartition: calling GetState()...\n"); + VLOGD("Calling GetState()...\n"); static int op = GetState(fp, "blk"); if (op == 1) PartitionNotFound(basename(fp.c_str())); - else if (op == -1 && !Booleans::ForceMode) + else if (op == -1 && !Config.ForceMode) LOGE("%s\n", Display::UsingDispString->not_block); } static void -PrintInfo(ushort_t pcode, double psz, double fsz) +PrintInfo(const ushort_t& pcode, const double& psz, const double& fsz) { LOGD("##########################################\n"); LOGD("# --> %s: %s\n", @@ -74,7 +76,7 @@ PrintInfo(ushort_t pcode, double psz, double fsz) Strings::TargetPartition.c_str()); LOGD("# --> %s: %s\n", Display::UsingDispString->part_type, - (Booleans::UseLogical) ? Display::UsingDispString->yes : Display::UsingDispString->no); + (Config.UseLogical) ? Display::UsingDispString->yes : Display::UsingDispString->no); if (psz != -1) LOGD("# --> %s: %.2fMB\n", @@ -100,63 +102,93 @@ PrintInfo(ushort_t pcode, double psz, double fsz) LOGD("##########################################\n"); } +template static bool -IsDoubleOf1024(float size) -{ - float num = size / 1024; - char str[35]; - sprintf(str, "%f", num); +IsDoubleOf1024(T size) { return size % (T)1024 == 0; } - return (strstr(str, ".000000") != nullptr) ? true : false; +static void +ReadAndWrite(const string& FNameForMsg, const int& bfsize) +{ + long long copiedData = 0; + char buffer[bfsize]; + + 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, + FNameForMsg.c_str(), + strqerror()); + + copiedData += readed_data; + } +} + +static void +OpenSourceFile(const string& fp) +{ + VLOGD("Trying to open `%s' with 'open '.\n", fp.c_str()); + + sourceF.open(fp, ios::binary | ios::in); + if (!sourceF.is_open()) + LOGE("%s: %s: %s\n", + Display::UsingDispString->not_read, + fp.c_str(), + strqerror()); +} + +static void +OpenTargetFile(const string& fp) +{ + VLOGD("Trying to open `%s' with 'open '.\n", fp.c_str()); + + targetF.open(fp, ios::binary | ios::out); + if (!targetF.is_open()) + LOGE("%s: %s: %s\n", + Display::UsingDispString->not_gen, + fp.c_str(), + strqerror()); } -} /* namespace Functions */ } /* namespace PartitionManager */ using namespace PartitionManager; -int Functions::Start(ushort_t progress_code) +int PartitionManager::PartitionManagerMain(const ushort_t& progress_code) { /* Some required variables */ - fstream sourceF, targetF; string accessPrefix, opName; - long long copiedData = 0; - bool IsFirstProcessOnTarget = true; - if (Booleans::UseLogical) + if (Config.UseLogical) accessPrefix = "/dev/block/mapper/" + Strings::TargetPartition; else - accessPrefix = (Booleans::UseCustomSearchPath) ? (Strings::CustomSearchPath) + ("/") + (Strings::TargetPartition) : ("/dev/block/by-name/") + (Strings::TargetPartition); + accessPrefix = (Config.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); + VLOGD("Calling SearchPartition() for searching partition (path); `%s'\n", accessPrefix.c_str()); + 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]; + Count = (long long)(CalculateSizeLongLong(accessPrefix) + ((1024 * 1024) * 4)); + const int BFSIZE = (IsDoubleOf1024(CalculateSizeLongLong(accessPrefix))) ? 1024 : 1; double FlashFileSize = 0; - double PartitionSize = (double)(static_cast(Functions::CalculateSizeLongLong(accessPrefix)) / (1024 * 1024)); + double PartitionSize = (double)(static_cast(CalculateSizeLongLong(accessPrefix)) / (1024 * 1024)); if (!Strings::TargetFlashFile.empty()) - FlashFileSize = (double)(static_cast(Functions::CalculateSizeLongLong(Strings::TargetFlashFile)) / (1024 * 1024)); + FlashFileSize = (double)(static_cast(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 '.\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()); + OpenSourceFile(accessPrefix); /* determine output */ if (Strings::OutputName == Strings::TargetPartition) { opName = Strings::OutputName + ".img"; - VLOGW("PartitionManager: output not speficed. Selecting automaticly.\n"); + VLOGW("Output not speficed. Selecting automaticly.\n"); LOGW("%s: %s\n", Display::UsingDispString->out_not_spec, opName.c_str()); @@ -168,37 +200,10 @@ int Functions::Start(ushort_t progress_code) if (GetState(opName) == 0) LOGE("'%s': File exits.\n", opName.c_str()); - VLOGD("PartitionManager: trying to open `%s' with 'open '.\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()); + OpenTargetFile(opName); - VLOGD("PartitionManager: read (partition) and write (output) 'read, write '\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; - } + VLOGD("Read (partition) and write (output) 'read, write '\n"); + ReadAndWrite(opName.c_str(), BFSIZE); /* close files */ sourceF.close(); @@ -212,41 +217,15 @@ int Functions::Start(ushort_t progress_code) { if (PartitionSize != -1 && FlashFileSize != -1) { - if (FlashFileSize > PartitionSize && !Booleans::ForceMode) + if (FlashFileSize > PartitionSize && !Config.ForceMode) LOGE("%s\n", Display::UsingDispString->ffile_more_part); } - VLOGD("PartitionManager: trying to open `%s' with 'open '.\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()); + OpenSourceFile(Strings::TargetFlashFile); + OpenTargetFile(accessPrefix); - VLOGD("PartitionManager: trying to open `%s' with 'open '.\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 '\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; - } + VLOGD("Read (flash file) and write (partition) 'read, write '\n"); + ReadAndWrite(accessPrefix.c_str(), BFSIZE); sourceF.close(); targetF.close(); @@ -256,14 +235,14 @@ int Functions::Start(ushort_t progress_code) else if (progress_code == 3) { /* get target partition block size */ - VLOGD("PartitionManager: getting block size `%s' with 'statfs '\n", accessPrefix.c_str()); + VLOGD("Getting block size '%s' with 'statfs '\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"); + VLOGD("Generating mke2fs argument list...\n"); char bsize[25] = ""; #ifdef __LP64__ sprintf(bsize, "%lu", file_sys_inf.f_bsize); @@ -287,7 +266,7 @@ int Functions::Start(ushort_t progress_code) Strings::TargetFormatFS.c_str()); /* run mke2fs */ - VLOGD("PartitionManager: calling mke2fs_main...\n"); + VLOGD("Calling mke2fs_main...\n"); if (mke2fs_main(sizeof(arguments), arguments) != 0) LOGF("%s\n", Display::UsingDispString->format_fail); @@ -295,12 +274,12 @@ int Functions::Start(ushort_t progress_code) } else if (progress_code == 4) { - VLOGD("PartitionManager: getting size of '%s' (long long)\n", accessPrefix.c_str()); + VLOGD("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"); + VLOGE("Cannot get partition size!\n"); LOGE("%s: %s\n", Display::UsingDispString->fail_get_psize, strqerror()); @@ -309,7 +288,7 @@ int Functions::Start(ushort_t progress_code) static char* SizeType; static char Holder[50]; - if (!Booleans::OnlyViewSize) + if (!Config.OnlyViewSize) { sprintf(Holder, "%s: ", Strings::TargetPartition.c_str()); @@ -321,7 +300,7 @@ int Functions::Start(ushort_t progress_code) else SizeType = ""; - VLOGD("PartitionManager: Displaying partition size...\n"); + VLOGD("Displaying partition size...\n"); if (Integers::PartSizeViewType == VIEW_AS_BYTE) LOGD("%s%llu%s\n", diff --git a/jni/PartitionManager/Version.cpp b/jni/PartitionManager/Version.cpp index f2c4c97..0e0c788 100755 --- a/jni/PartitionManager/Version.cpp +++ b/jni/PartitionManager/Version.cpp @@ -25,9 +25,9 @@ using namespace PartitionManager; -void Functions::DisplayVersion(void) +void PartitionManager::DisplayVersion(void) { - VLOGD("DisplayVersion: printing main info...\n"); + VLOGD("Printing main info...\n"); LOGD("%s %s %d.%d.%d (%d%d%d / C++) ", Strings::ExecutingName.c_str(), Display::UsingDispString->version_str, @@ -38,14 +38,10 @@ void Functions::DisplayVersion(void) PMT_MINOR, PMT_PATCHLEVEL); -#if __SIZEOF_POINTER__ == 4 - LOGD("32-bit %s\n", Display::UsingDispString->bin_str); -#elif __SIZEOF_POINTER__ == 8 +#ifdef __LP64__ LOGD("64-bit %s\n", Display::UsingDispString->bin_str); #else - LOGD("<%s> %s\n", - Display::UsingDispString->unknw_str, - Display::UsingDispString->bin_str); + LOGD("32-bit %s\n", Display::UsingDispString->bin_str); #endif LOGD("mke2fs %s %s (%s)\n", diff --git a/jni/e2fsprogs/lib/ext2fs/bmove.c b/jni/e2fsprogs/lib/ext2fs/bmove.c deleted file mode 100755 index e2ea405..0000000 --- a/jni/e2fsprogs/lib/ext2fs/bmove.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * bmove.c --- Move blocks around to make way for a particular - * filesystem structure. - * - * Copyright (C) 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include "config.h" -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif -#if HAVE_SYS_TIME_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fsP.h" - -struct process_block_struct { - ext2_ino_t ino; - struct ext2_inode * inode; - ext2fs_block_bitmap reserve; - ext2fs_block_bitmap alloc_map; - errcode_t error; - char *buf; - int add_dir; - int flags; -}; - -static int process_block(ext2_filsys fs, blk64_t *block_nr, - e2_blkcnt_t blockcnt, blk64_t ref_block, - int ref_offset, void *priv_data) -{ - struct process_block_struct *pb; - errcode_t retval; - int ret; - blk64_t block, orig; - - pb = (struct process_block_struct *) priv_data; - block = orig = *block_nr; - ret = 0; - - /* - * Let's see if this is one which we need to relocate - */ - if (ext2fs_test_block_bitmap2(pb->reserve, block)) { - do { - if (++block >= ext2fs_blocks_count(fs->super)) - block = fs->super->s_first_data_block; - if (block == orig) { - pb->error = EXT2_ET_BLOCK_ALLOC_FAIL; - return BLOCK_ABORT; - } - } while (ext2fs_test_block_bitmap2(pb->reserve, block) || - ext2fs_test_block_bitmap2(pb->alloc_map, block)); - - retval = io_channel_read_blk64(fs->io, orig, 1, pb->buf); - if (retval) { - pb->error = retval; - return BLOCK_ABORT; - } - retval = io_channel_write_blk64(fs->io, block, 1, pb->buf); - if (retval) { - pb->error = retval; - return BLOCK_ABORT; - } - *block_nr = block; - ext2fs_mark_block_bitmap2(pb->alloc_map, block); - ret = BLOCK_CHANGED; - if (pb->flags & EXT2_BMOVE_DEBUG) - printf("ino=%u, blockcnt=%lld, %llu->%llu\n", - (unsigned) pb->ino, blockcnt, - (unsigned long long) orig, - (unsigned long long) block); - } - if (pb->add_dir) { - retval = ext2fs_add_dir_block2(fs->dblist, pb->ino, - block, blockcnt); - if (retval) { - pb->error = retval; - ret |= BLOCK_ABORT; - } - } - return ret; -} - -errcode_t ext2fs_move_blocks(ext2_filsys fs, - ext2fs_block_bitmap reserve, - ext2fs_block_bitmap alloc_map, - int flags) -{ - ext2_ino_t ino; - struct ext2_inode inode; - errcode_t retval; - struct process_block_struct pb; - ext2_inode_scan scan; - char *block_buf; - - retval = ext2fs_open_inode_scan(fs, 0, &scan); - if (retval) - return retval; - - pb.reserve = reserve; - pb.error = 0; - pb.alloc_map = alloc_map ? alloc_map : fs->block_map; - pb.flags = flags; - - retval = ext2fs_get_array(4, fs->blocksize, &block_buf); - if (retval) - return retval; - pb.buf = block_buf + fs->blocksize * 3; - - /* - * If GET_DBLIST is set in the flags field, then we should - * gather directory block information while we're doing the - * block move. - */ - if (flags & EXT2_BMOVE_GET_DBLIST) { - if (fs->dblist) { - ext2fs_free_dblist(fs->dblist); - fs->dblist = NULL; - } - retval = ext2fs_init_dblist(fs, 0); - if (retval) - return retval; - } - - retval = ext2fs_get_next_inode(scan, &ino, &inode); - if (retval) - return retval; - - while (ino) { - if ((inode.i_links_count == 0) || - !ext2fs_inode_has_valid_blocks2(fs, &inode)) - goto next; - - pb.ino = ino; - pb.inode = &inode; - - pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) && - flags & EXT2_BMOVE_GET_DBLIST); - - retval = ext2fs_block_iterate3(fs, ino, 0, block_buf, - process_block, &pb); - if (retval) - return retval; - if (pb.error) - return pb.error; - - next: - retval = ext2fs_get_next_inode(scan, &ino, &inode); - if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) - goto next; - } - return 0; -} - diff --git a/jni/e2fsprogs/lib/ext2fs/brel_ma.c b/jni/e2fsprogs/lib/ext2fs/brel_ma.c deleted file mode 100755 index a12afae..0000000 --- a/jni/e2fsprogs/lib/ext2fs/brel_ma.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * brel_ma.c - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * TODO: rewrite to not use a direct array!!! (Fortunately this - * module isn't really used yet.) - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include "config.h" -#include -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" -#include "brel.h" - -static errcode_t bma_put(ext2_brel brel, blk64_t old, - struct ext2_block_relocate_entry *ent); -static errcode_t bma_get(ext2_brel brel, blk64_t old, - struct ext2_block_relocate_entry *ent); -static errcode_t bma_start_iter(ext2_brel brel); -static errcode_t bma_next(ext2_brel brel, blk64_t *old, - struct ext2_block_relocate_entry *ent); -static errcode_t bma_move(ext2_brel brel, blk64_t old, blk64_t new); -static errcode_t bma_delete(ext2_brel brel, blk64_t old); -static errcode_t bma_free(ext2_brel brel); - -struct brel_ma { - __u32 magic; - blk64_t max_block; - struct ext2_block_relocate_entry *entries; -}; - -errcode_t ext2fs_brel_memarray_create(char *name, blk64_t max_block, - ext2_brel *new_brel) -{ - ext2_brel brel = 0; - errcode_t retval; - struct brel_ma *ma = 0; - size_t size; - - *new_brel = 0; - - /* - * Allocate memory structures - */ - retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table), - &brel); - if (retval) - goto errout; - memset(brel, 0, sizeof(struct ext2_block_relocation_table)); - - retval = ext2fs_get_mem(strlen(name)+1, &brel->name); - if (retval) - goto errout; - strcpy(brel->name, name); - - retval = ext2fs_get_mem(sizeof(struct brel_ma), &ma); - if (retval) - goto errout; - memset(ma, 0, sizeof(struct brel_ma)); - brel->priv_data = ma; - - size = (size_t) (sizeof(struct ext2_block_relocate_entry) * - (max_block+1)); - retval = ext2fs_get_array(max_block+1, - sizeof(struct ext2_block_relocate_entry), &ma->entries); - if (retval) - goto errout; - memset(ma->entries, 0, size); - ma->max_block = max_block; - - /* - * Fill in the brel data structure - */ - brel->put = bma_put; - brel->get = bma_get; - brel->start_iter = bma_start_iter; - brel->next = bma_next; - brel->move = bma_move; - brel->delete = bma_delete; - brel->free = bma_free; - - *new_brel = brel; - return 0; - -errout: - bma_free(brel); - return retval; -} - -static errcode_t bma_put(ext2_brel brel, blk64_t old, - struct ext2_block_relocate_entry *ent) -{ - struct brel_ma *ma; - - ma = brel->priv_data; - if (old > ma->max_block) - return EXT2_ET_INVALID_ARGUMENT; - ma->entries[(unsigned)old] = *ent; - return 0; -} - -static errcode_t bma_get(ext2_brel brel, blk64_t old, - struct ext2_block_relocate_entry *ent) -{ - struct brel_ma *ma; - - ma = brel->priv_data; - if (old > ma->max_block) - return EXT2_ET_INVALID_ARGUMENT; - if (ma->entries[(unsigned)old].new == 0) - return ENOENT; - *ent = ma->entries[old]; - return 0; -} - -static errcode_t bma_start_iter(ext2_brel brel) -{ - brel->current = 0; - return 0; -} - -static errcode_t bma_next(ext2_brel brel, blk64_t *old, - struct ext2_block_relocate_entry *ent) -{ - struct brel_ma *ma; - - ma = brel->priv_data; - while (++brel->current < ma->max_block) { - if (ma->entries[(unsigned)brel->current].new == 0) - continue; - *old = brel->current; - *ent = ma->entries[(unsigned)brel->current]; - return 0; - } - *old = 0; - return 0; -} - -static errcode_t bma_move(ext2_brel brel, blk64_t old, blk64_t new) -{ - struct brel_ma *ma; - - ma = brel->priv_data; - if ((old > ma->max_block) || (new > ma->max_block)) - return EXT2_ET_INVALID_ARGUMENT; - if (ma->entries[(unsigned)old].new == 0) - return ENOENT; - ma->entries[(unsigned)new] = ma->entries[old]; - ma->entries[(unsigned)old].new = 0; - return 0; -} - -static errcode_t bma_delete(ext2_brel brel, blk64_t old) -{ - struct brel_ma *ma; - - ma = brel->priv_data; - if (old > ma->max_block) - return EXT2_ET_INVALID_ARGUMENT; - if (ma->entries[(unsigned)old].new == 0) - return ENOENT; - ma->entries[(unsigned)old].new = 0; - return 0; -} - -static errcode_t bma_free(ext2_brel brel) -{ - struct brel_ma *ma; - - if (!brel) - return 0; - - ma = brel->priv_data; - - if (ma) { - if (ma->entries) - ext2fs_free_mem(&ma->entries); - ext2fs_free_mem(&ma); - } - if (brel->name) - ext2fs_free_mem(&brel->name); - ext2fs_free_mem(&brel); - return 0; -} diff --git a/jni/e2fsprogs/lib/ext2fs/dosio.c b/jni/e2fsprogs/lib/ext2fs/dosio.c deleted file mode 100755 index d0cf269..0000000 --- a/jni/e2fsprogs/lib/ext2fs/dosio.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * dosio.c -- Disk I/O module for the ext2fs/DOS library. - * - * Copyright (c) 1997 by Theodore Ts'o. - * - * Copyright (c) 1997 Mark Habersack - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include "config.h" -#include -#include -#include -#include -#include -#ifdef HAVE_ERRNO_H -#include -#endif - -#include -#include "utils.h" -#include "dosio.h" -#include "et/com_err.h" -#include "ext2_err.h" -#include "ext2fs/io.h" - -/* - * Some helper macros - */ -#define LINUX_EXT2FS 0x83 -#define LINUX_SWAP 0x82 -#define WRITE_ERR(_msg_) write(2, _msg_, strlen(_msg_)) -#define WRITE_ERR_S(_msg_) write(2, _msg_, sizeof(_msg_)) - -/* - * Exported variables - */ -unsigned long _dio_error; -unsigned long _dio_hw_error; - -/* - * Array of all opened partitions - */ -static PARTITION **partitions = NULL; -static unsigned short npart = 0; /* Number of mapped partitions */ -static PARTITION *active = NULL; - -/* - * I/O Manager routine prototypes - */ -static errcode_t dos_open(const char *dev, int flags, io_channel *channel); -static errcode_t dos_close(io_channel channel); -static errcode_t dos_set_blksize(io_channel channel, int blksize); -static errcode_t dos_read_blk(io_channel channel, unsigned long block, - int count, void *buf); -static errcode_t dos_write_blk(io_channel channel, unsigned long block, - int count, const void *buf); -static errcode_t dos_flush(io_channel channel); - -static struct struct_io_manager struct_dos_manager = { - .magic = EXT2_ET_MAGIC_IO_MANAGER, - .name = "DOS I/O Manager", - .open = dos_open, - .close = dos_close, - .set_blksize = dos_set_blksize, - .read_blk = dos_read_blk, - .write_blk = dos_write_blk, - .flush = dos_flush -}; - -io_manager dos_io_manager = &struct_dos_manager; - -/* - * Macro taken from unix_io.c - */ -/* - * For checking structure magic numbers... - */ - -#define EXT2_CHECK_MAGIC(struct, code) \ - if ((struct)->magic != (code)) return (code) - -/* - * Calculates a CHS address of a sector from its LBA - * offset for the given partition. - */ -static void lba2chs(unsigned long lba_addr, CHS *chs, PARTITION *part) -{ - unsigned long abss; - - chs->offset = lba_addr & 0x000001FF; - abss = (lba_addr >> 9) + part->start; - chs->cyl = abss / (part->sects * part->heads); - chs->head = (abss / part->sects) % part->heads; - chs->sector = (abss % part->sects) + 1; -} - -#ifdef __TURBOC__ -#pragma argsused -#endif -/* - * Scans the passed partition table looking for *pno partition - * that has LINUX_EXT2FS type. - * - * TODO: - * For partition numbers >5 Linux uses DOS extended partitions - - * dive into them an return an appropriate entry. Also dive into - * extended partitions when scanning for a first Linux/ext2fs. - */ -static PTABLE_ENTRY *scan_partition_table(PTABLE_ENTRY *pentry, - unsigned short phys, - unsigned char *pno) -{ - unsigned i; - - if(*pno != 0xFF && *pno >= 5) - return NULL; /* We don't support extended partitions for now */ - - if(*pno != 0xFF) - { - if(pentry[*pno].type == LINUX_EXT2FS) - return &pentry[*pno]; - else - { - if(!pentry[*pno].type) - *pno = 0xFE; - else if(pentry[*pno].type == LINUX_SWAP) - *pno = 0xFD; - return NULL; - } - } - - for(i = 0; i < 4; i++) - if(pentry[i].type == LINUX_EXT2FS) - { - *pno = i; - return &pentry[i]; - } - - return NULL; -} - -/* - * Allocate libext2fs structures associated with I/O manager - */ -static io_channel alloc_io_channel(PARTITION *part) -{ - io_channel ioch; - - ioch = (io_channel)malloc(sizeof(struct struct_io_channel)); - if (!ioch) - return NULL; - memset(ioch, 0, sizeof(struct struct_io_channel)); - ioch->magic = EXT2_ET_MAGIC_IO_CHANNEL; - ioch->manager = dos_io_manager; - ioch->name = (char *)malloc(strlen(part->dev)+1); - if (!ioch->name) { - free(ioch); - return NULL; - } - strcpy(ioch->name, part->dev); - ioch->private_data = part; - ioch->block_size = 1024; /* The smallest ext2fs block size */ - ioch->read_error = 0; - ioch->write_error = 0; - - return ioch; -} - -#ifdef __TURBOC__ -#pragma argsused -#endif -/* - * Open the 'name' partition, initialize all information structures - * we need to keep and create libext2fs I/O manager. - */ -static errcode_t dos_open(const char *dev, int flags, io_channel *channel) -{ - unsigned char *tmp, sec[512]; - PARTITION *part; - PTABLE_ENTRY *pent; - PARTITION **newparts; - - if(!dev) - { - _dio_error = ERR_BADDEV; - return EXT2_ET_BAD_DEVICE_NAME; - } - - /* - * First check whether the dev name is OK - */ - tmp = (unsigned char*)strrchr(dev, '/'); - if(!tmp) - { - _dio_error = ERR_BADDEV; - return EXT2_ET_BAD_DEVICE_NAME; - } - *tmp = 0; - if(strcmp(dev, "/dev")) - { - _dio_error = ERR_BADDEV; - return EXT2_ET_BAD_DEVICE_NAME; - } - *tmp++ = '/'; - - /* - * Check whether the partition data is already in cache - */ - - part = (PARTITION*)malloc(sizeof(PARTITION)); - if (!part) - return ENOMEM; - { - int i = 0; - - for(;i < npart; i++) - if(!strcmp(partitions[i]->dev, dev)) - { - /* Found it! Make it the active one */ - active = partitions[i]; - *channel = alloc_io_channel(active); - if (!*channel) - return ENOMEM; - return 0; - } - } - - /* - * Drive number & optionally partn number - */ - switch(tmp[0]) - { - case 'h': - case 's': - part->phys = 0x80; - part->phys += toupper(tmp[2]) - 'A'; - /* - * Do we have the partition number? - */ - if(tmp[3]) - part->pno = isdigit((int)tmp[3]) ? tmp[3] - '0' - 1: 0; - else - part->pno = 0xFF; - break; - - case 'f': - if(tmp[2]) - part->phys = isdigit((int)tmp[2]) ? tmp[2] - '0' : 0; - else - part->phys = 0x00; /* We'll assume /dev/fd0 */ - break; - - default: - _dio_error = ERR_BADDEV; - return ENODEV; - } - - if(part->phys < 0x80) - { - /* We don't support floppies for now */ - _dio_error = ERR_NOTSUPP; - return EINVAL; - } - - part->dev = strdup(dev); - - /* - * Get drive's geometry - */ - _dio_hw_error = biosdisk(DISK_GET_GEOMETRY, - part->phys, - 0, /* head */ - 0, /* cylinder */ - 1, /* sector */ - 1, /* just one sector */ - sec); - - if(!HW_OK()) - { - _dio_error = ERR_HARDWARE; - free(part->dev); - free(part); - return EFAULT; - } - - /* - * Calculate the geometry - */ - part->cyls = (unsigned short)(((sec[0] >> 6) << 8) + sec[1] + 1); - part->heads = sec[3] + 1; - part->sects = sec[0] & 0x3F; - - /* - * Now that we know all we need, let's look for the partition - */ - _dio_hw_error = biosdisk(DISK_READ, part->phys, 0, 0, 1, 1, sec); - - if(!HW_OK()) - { - _dio_error = ERR_HARDWARE; - free(part->dev); - free(part); - return EFAULT; - } - - pent = (PTABLE_ENTRY*)&sec[0x1BE]; - pent = scan_partition_table(pent, part->phys, &part->pno); - - if(!pent) - { - _dio_error = part->pno == 0xFE ? ERR_EMPTYPART : - part->pno == 0xFD ? ERR_LINUXSWAP : ERR_NOTEXT2FS; - free(part->dev); - free(part); - return ENODEV; - } - - /* - * Calculate the remaining figures - */ - { - unsigned long fsec, fhead, fcyl; - - fsec = (unsigned long)(pent->start_sec & 0x3F); - fhead = (unsigned long)pent->start_head; - fcyl = ((pent->start_sec >> 6) << 8) + pent->start_cyl; - part->start = fsec + fhead * part->sects + fcyl * - (part->heads * part->sects) - 1; - part->len = pent->size; - } - - /* - * Add the partition to the table - */ - newparts = (PARTITION**)realloc(partitions, sizeof(PARTITION) * npart); - if (!newparts) { - free(part); - return ENOMEM; - } - partitions = newparts; - partitions[npart++] = active = part; - - /* - * Now alloc all libe2fs structures - */ - *channel = alloc_io_channel(active); - if (!*channel) - return ENOMEM; - - return 0; -} - -static errcode_t dos_close(io_channel channel) -{ - free(channel->name); - free(channel); - - return 0; -} - -static errcode_t dos_set_blksize(io_channel channel, int blksize) -{ - channel->block_size = blksize; - - return 0; -} - -static errcode_t dos_read_blk(io_channel channel, unsigned long block, - int count, void *buf) -{ - PARTITION *part; - size_t size; - ext2_loff_t loc; - CHS chs; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - part = (PARTITION*)channel->private_data; - - size = (size_t)((count < 0) ? -count : count * channel->block_size); - loc = (ext2_loff_t) block * channel->block_size; - - lba2chs(loc, &chs, part); - /* - * Potential bug here: - * If DJGPP is used then reads of >18 sectors will fail! - * Have to rewrite biosdisk. - */ - _dio_hw_error = biosdisk(DISK_READ, - part->phys, - chs.head, - chs.cyl, - chs.sector, - size < 512 ? 1 : size/512, - buf); - - if(!HW_OK()) - { - _dio_error = ERR_HARDWARE; - return EFAULT; - } - - return 0; -} - -static errcode_t dos_write_blk(io_channel channel, unsigned long block, - int count, const void *buf) -{ - PARTITION *part; - size_t size; - ext2_loff_t loc; - CHS chs; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - part = (PARTITION*)channel->private_data; - - if(count == 1) - size = (size_t)channel->block_size; - else - { - if (count < 0) - size = (size_t)-count; - else - size = (size_t)(count * channel->block_size); - } - - loc = (ext2_loff_t)block * channel->block_size; - lba2chs(loc, &chs, part); - _dio_hw_error = biosdisk(DISK_WRITE, - part->phys, - chs.head, - chs.cyl, - chs.sector, - size < 512 ? 1 : size/512, - (void*)buf); - - if(!HW_OK()) - { - _dio_error = ERR_HARDWARE; - return EFAULT; - } - - return 0; -} - -#ifdef __TURBOC__ -#pragma argsused -#endif -static errcode_t dos_flush(io_channel channel) -{ - /* - * No buffers, no flush... - */ - return 0; -} diff --git a/jni/e2fsprogs/lib/ext2fs/nt_io.c b/jni/e2fsprogs/lib/ext2fs/nt_io.c deleted file mode 100755 index 234f6b1..0000000 --- a/jni/e2fsprogs/lib/ext2fs/nt_io.c +++ /dev/null @@ -1,1494 +0,0 @@ -/* - * nt_io.c --- This is the Nt I/O interface to the I/O manager. - * - * Implements a one-block write-through cache. - * - * Copyright (C) 1993, 1994, 1995 Theodore Ts'o. - * Copyright (C) 1998 Andrey Shedel (andreys@ns.cr.cyco.com) - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - - -// -// I need some warnings to disable... -// - - -#pragma warning(disable:4514) // unreferenced inline function has been removed -#pragma warning(push,4) - -#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union) -#pragma warning(disable:4214) // nonstandard extension used : bit field types other than int -#pragma warning(disable:4115) // named type definition in parentheses - -#include -#include -#include - -#pragma warning(pop) - - -// -// Some native APIs. -// - -NTSYSAPI -ULONG -NTAPI -RtlNtStatusToDosError( - IN NTSTATUS Status - ); - -NTSYSAPI -NTSTATUS -NTAPI -NtClose( - IN HANDLE Handle - ); - - -NTSYSAPI -NTSTATUS -NTAPI -NtOpenFile( - OUT PHANDLE FileHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG ShareAccess, - IN ULONG OpenOptions - ); - -NTSYSAPI -NTSTATUS -NTAPI -NtFlushBuffersFile( - IN HANDLE FileHandle, - OUT PIO_STATUS_BLOCK IoStatusBlock - ); - - -NTSYSAPI -NTSTATUS -NTAPI -NtReadFile( - IN HANDLE FileHandle, - IN HANDLE Event OPTIONAL, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, - OUT PIO_STATUS_BLOCK IoStatusBlock, - OUT PVOID Buffer, - IN ULONG Length, - IN PLARGE_INTEGER ByteOffset OPTIONAL, - IN PULONG Key OPTIONAL - ); - -NTSYSAPI -NTSTATUS -NTAPI -NtWriteFile( - IN HANDLE FileHandle, - IN HANDLE Event OPTIONAL, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN PVOID Buffer, - IN ULONG Length, - IN PLARGE_INTEGER ByteOffset OPTIONAL, - IN PULONG Key OPTIONAL - ); - -NTSYSAPI -NTSTATUS -NTAPI -NtDeviceIoControlFile( - IN HANDLE FileHandle, - IN HANDLE Event OPTIONAL, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG IoControlCode, - IN PVOID InputBuffer OPTIONAL, - IN ULONG InputBufferLength, - OUT PVOID OutputBuffer OPTIONAL, - IN ULONG OutputBufferLength - ); - -NTSYSAPI -NTSTATUS -NTAPI -NtFsControlFile( - IN HANDLE FileHandle, - IN HANDLE Event OPTIONAL, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG IoControlCode, - IN PVOID InputBuffer OPTIONAL, - IN ULONG InputBufferLength, - OUT PVOID OutputBuffer OPTIONAL, - IN ULONG OutputBufferLength - ); - - -NTSYSAPI -NTSTATUS -NTAPI -NtDelayExecution( - IN BOOLEAN Alertable, - IN PLARGE_INTEGER Interval - ); - - -#define FSCTL_LOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define FSCTL_UNLOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define FSCTL_IS_VOLUME_MOUNTED CTL_CODE(FILE_DEVICE_FILE_SYSTEM,10, METHOD_BUFFERED, FILE_ANY_ACCESS) - - -// -// useful macros -// - -#define BooleanFlagOn(Flags,SingleFlag) ((BOOLEAN)((((Flags) & (SingleFlag)) != 0))) - - -// -// Include Win32 error codes. -// - -#include - -// -// standard stuff -// - -#include -#include -#include -#include -#include - -#include -#include "ext2_fs.h" -#include - -#include "et/com_err.h" -#include "ext2fs/ext2fs.h" -#include "ext2fs/ext2_err.h" - - - - -// -// For checking structure magic numbers... -// - - -#define EXT2_CHECK_MAGIC(struct, code) \ - if ((struct)->magic != (code)) return (code) - -#define EXT2_ET_MAGIC_NT_IO_CHANNEL 0x10ed - - -// -// Private data block -// - -typedef struct _NT_PRIVATE_DATA { - int magic; - HANDLE Handle; - int Flags; - PCHAR Buffer; - __u32 BufferBlockNumber; - ULONG BufferSize; - BOOLEAN OpenedReadonly; - BOOLEAN Written; -}NT_PRIVATE_DATA, *PNT_PRIVATE_DATA; - - - -// -// Standard interface prototypes -// - -static errcode_t nt_open(const char *name, int flags, io_channel *channel); -static errcode_t nt_close(io_channel channel); -static errcode_t nt_set_blksize(io_channel channel, int blksize); -static errcode_t nt_read_blk(io_channel channel, unsigned long block, - int count, void *data); -static errcode_t nt_write_blk(io_channel channel, unsigned long block, - int count, const void *data); -static errcode_t nt_flush(io_channel channel); - -static struct struct_io_manager struct_nt_manager = { - .magic = EXT2_ET_MAGIC_IO_MANAGER, - .name = "NT I/O Manager", - .open = nt_open, - .close = nt_close, - .set_blksize = nt_set_blksize, - .read_blk = nt_read_blk, - .write_blk = nt_write_blk, - .flush = nt_flush -}; - -// -// function to get API -// - -io_manager nt_io_manager() -{ - return &struct_nt_manager; -} - - - - - -// -// This is a code to convert Win32 errors to unix errno -// - -typedef struct { - ULONG WinError; - int errnocode; -}ERROR_ENTRY; - -static ERROR_ENTRY ErrorTable[] = { - { ERROR_INVALID_FUNCTION, EINVAL }, - { ERROR_FILE_NOT_FOUND, ENOENT }, - { ERROR_PATH_NOT_FOUND, ENOENT }, - { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, - { ERROR_ACCESS_DENIED, EACCES }, - { ERROR_INVALID_HANDLE, EBADF }, - { ERROR_ARENA_TRASHED, ENOMEM }, - { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, - { ERROR_INVALID_BLOCK, ENOMEM }, - { ERROR_BAD_ENVIRONMENT, E2BIG }, - { ERROR_BAD_FORMAT, ENOEXEC }, - { ERROR_INVALID_ACCESS, EINVAL }, - { ERROR_INVALID_DATA, EINVAL }, - { ERROR_INVALID_DRIVE, ENOENT }, - { ERROR_CURRENT_DIRECTORY, EACCES }, - { ERROR_NOT_SAME_DEVICE, EXDEV }, - { ERROR_NO_MORE_FILES, ENOENT }, - { ERROR_LOCK_VIOLATION, EACCES }, - { ERROR_BAD_NETPATH, ENOENT }, - { ERROR_NETWORK_ACCESS_DENIED, EACCES }, - { ERROR_BAD_NET_NAME, ENOENT }, - { ERROR_FILE_EXISTS, EEXIST }, - { ERROR_CANNOT_MAKE, EACCES }, - { ERROR_FAIL_I24, EACCES }, - { ERROR_INVALID_PARAMETER, EINVAL }, - { ERROR_NO_PROC_SLOTS, EAGAIN }, - { ERROR_DRIVE_LOCKED, EACCES }, - { ERROR_BROKEN_PIPE, EPIPE }, - { ERROR_DISK_FULL, ENOSPC }, - { ERROR_INVALID_TARGET_HANDLE, EBADF }, - { ERROR_INVALID_HANDLE, EINVAL }, - { ERROR_WAIT_NO_CHILDREN, ECHILD }, - { ERROR_CHILD_NOT_COMPLETE, ECHILD }, - { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, - { ERROR_NEGATIVE_SEEK, EINVAL }, - { ERROR_SEEK_ON_DEVICE, EACCES }, - { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, - { ERROR_NOT_LOCKED, EACCES }, - { ERROR_BAD_PATHNAME, ENOENT }, - { ERROR_MAX_THRDS_REACHED, EAGAIN }, - { ERROR_LOCK_FAILED, EACCES }, - { ERROR_ALREADY_EXISTS, EEXIST }, - { ERROR_FILENAME_EXCED_RANGE, ENOENT }, - { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, - { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } -}; - - - - -static -unsigned -_MapDosError ( - IN ULONG WinError - ) -{ - int i; - - // - // Lookup - // - - for (i = 0; i < (sizeof(ErrorTable)/sizeof(ErrorTable[0])); ++i) - { - if (WinError == ErrorTable[i].WinError) - { - return ErrorTable[i].errnocode; - } - } - - // - // not in table. Check ranges - // - - if ((WinError >= ERROR_WRITE_PROTECT) && - (WinError <= ERROR_SHARING_BUFFER_EXCEEDED)) - { - return EACCES; - } - else if ((WinError >= ERROR_INVALID_STARTING_CODESEG) && - (WinError <= ERROR_INFLOOP_IN_RELOC_CHAIN)) - { - return ENOEXEC; - } - else - { - return EINVAL; - } -} - - - - - - - -// -// Function to map NT status to dos error. -// - -static -__inline -unsigned -_MapNtStatus( - IN NTSTATUS Status - ) -{ - return _MapDosError(RtlNtStatusToDosError(Status)); -} - - - - - -// -// Helper functions to make things easier -// - -static -NTSTATUS -_OpenNtName( - IN PCSTR Name, - IN BOOLEAN Readonly, - OUT PHANDLE Handle, - OUT PBOOLEAN OpenedReadonly OPTIONAL - ) -{ - UNICODE_STRING UnicodeString; - ANSI_STRING AnsiString; - WCHAR Buffer[512]; - NTSTATUS Status; - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - - // - // Make Unicode name from input string - // - - UnicodeString.Buffer = &Buffer[0]; - UnicodeString.Length = 0; - UnicodeString.MaximumLength = sizeof(Buffer); // in bytes!!! - - RtlInitAnsiString(&AnsiString, Name); - - Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE); - - if(!NT_SUCCESS(Status)) - { - return Status; // Unmappable character? - } - - // - // Initialize object - // - - InitializeObjectAttributes(&ObjectAttributes, - &UnicodeString, - OBJ_CASE_INSENSITIVE, - NULL, - NULL ); - - // - // Try to open it in initial mode - // - - if(ARGUMENT_PRESENT(OpenedReadonly)) - { - *OpenedReadonly = Readonly; - } - - - Status = NtOpenFile(Handle, - SYNCHRONIZE | FILE_READ_DATA | (Readonly ? 0 : FILE_WRITE_DATA), - &ObjectAttributes, - &IoStatusBlock, - FILE_SHARE_WRITE | FILE_SHARE_READ, - FILE_SYNCHRONOUS_IO_NONALERT); - - if(!NT_SUCCESS(Status)) - { - // - // Maybe was just mounted? wait 0.5 sec and retry. - // - - LARGE_INTEGER Interval; - Interval.QuadPart = -5000000; // 0.5 sec. from now - - NtDelayExecution(FALSE, &Interval); - - Status = NtOpenFile(Handle, - SYNCHRONIZE | FILE_READ_DATA | (Readonly ? 0 : FILE_WRITE_DATA), - &ObjectAttributes, - &IoStatusBlock, - FILE_SHARE_WRITE | FILE_SHARE_READ, - FILE_SYNCHRONOUS_IO_NONALERT); - - // - // Try to satisfy mode - // - - if((STATUS_ACCESS_DENIED == Status) && !Readonly) - { - if(ARGUMENT_PRESENT(OpenedReadonly)) - { - *OpenedReadonly = TRUE; - } - - Status = NtOpenFile(Handle, - SYNCHRONIZE | FILE_READ_DATA, - &ObjectAttributes, - &IoStatusBlock, - FILE_SHARE_WRITE | FILE_SHARE_READ, - FILE_SYNCHRONOUS_IO_NONALERT); - } - } - - - - // - // done - // - - return Status; -} - - -static -NTSTATUS -_OpenDriveLetter( - IN CHAR Letter, - IN BOOLEAN ReadOnly, - OUT PHANDLE Handle, - OUT PBOOLEAN OpenedReadonly OPTIONAL - ) -{ - CHAR Buffer[100]; - - sprintf(Buffer, "\\DosDevices\\%c:", Letter); - - return _OpenNtName(Buffer, ReadOnly, Handle, OpenedReadonly); -} - - -// -// Flush device -// - -static -__inline -NTSTATUS -_FlushDrive( - IN HANDLE Handle - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - return NtFlushBuffersFile(Handle, &IoStatusBlock); -} - - -// -// lock drive -// - -static -__inline -NTSTATUS -_LockDrive( - IN HANDLE Handle - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_LOCK_VOLUME, 0, 0, 0, 0); -} - - -// -// unlock drive -// - -static -__inline -NTSTATUS -_UnlockDrive( - IN HANDLE Handle - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0); -} - -static -__inline -NTSTATUS -_DismountDrive( - IN HANDLE Handle - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - return NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0); -} - - -// -// is mounted -// - -static -__inline -BOOLEAN -_IsMounted( - IN HANDLE Handle - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - Status = NtFsControlFile(Handle, 0, 0, 0, &IoStatusBlock, FSCTL_IS_VOLUME_MOUNTED, 0, 0, 0, 0); - return (BOOLEAN)(STATUS_SUCCESS == Status); -} - - -static -__inline -NTSTATUS -_CloseDisk( - IN HANDLE Handle - ) -{ - return NtClose(Handle); -} - - - - -// -// Make NT name from any recognized name -// - -static -PCSTR -_NormalizeDeviceName( - IN PCSTR Device, - IN PSTR NormalizedDeviceNameBuffer - ) -{ - int PartitionNumber = -1; - UCHAR DiskNumber; - PSTR p; - - - // - // Do not try to parse NT name - // - - if('\\' == *Device) - return Device; - - - - // - // Strip leading '/dev/' if any - // - - if(('/' == *(Device)) && - ('d' == *(Device + 1)) && - ('e' == *(Device + 2)) && - ('v' == *(Device + 3)) && - ('/' == *(Device + 4))) - { - Device += 5; - } - - if('\0' == *Device) - { - return NULL; - } - - - // - // forms: hda[n], fd[n] - // - - if('d' != *(Device + 1)) - { - return NULL; - } - - if('h' == *Device) - { - if((*(Device + 2) < 'a') || (*(Device + 2) > ('a' + 9)) || - ((*(Device + 3) != '\0') && - ((*(Device + 4) != '\0') || - ((*(Device + 3) < '0') || (*(Device + 3) > '9')) - ) - ) - ) - { - return NULL; - } - - DiskNumber = (UCHAR)(*(Device + 2) - 'a'); - - if(*(Device + 3) != '\0') - { - PartitionNumber = (*(Device + 3) - '0'); - } - - } - else if('f' == *Device) - { - // - // 3-d letter should be a digit. - // - - if((*(Device + 3) != '\0') || - (*(Device + 2) < '0') || (*(Device + 2) > '9')) - { - return NULL; - } - - DiskNumber = (UCHAR)(*(Device + 2) - '0'); - - } - else - { - // - // invalid prefix - // - - return NULL; - } - - - - // - // Prefix - // - - strcpy(NormalizedDeviceNameBuffer, "\\Device\\"); - - // - // Media name - // - - switch(*Device) - { - - case 'f': - strcat(NormalizedDeviceNameBuffer, "Floppy0"); - break; - - case 'h': - strcat(NormalizedDeviceNameBuffer, "Harddisk0"); - break; - } - - - p = NormalizedDeviceNameBuffer + strlen(NormalizedDeviceNameBuffer) - 1; - *p = (CHAR)(*p + DiskNumber); - - - // - // Partition nr. - // - - if(PartitionNumber >= 0) - { - strcat(NormalizedDeviceNameBuffer, "\\Partition0"); - - p = NormalizedDeviceNameBuffer + strlen(NormalizedDeviceNameBuffer) - 1; - *p = (CHAR)(*p + PartitionNumber); - } - - - return NormalizedDeviceNameBuffer; -} - - - - -static -VOID -_GetDeviceSize( - IN HANDLE h, - OUT unsigned __int64 *FsSize - ) -{ - PARTITION_INFORMATION pi; - DISK_GEOMETRY gi; - NTSTATUS Status; - IO_STATUS_BLOCK IoStatusBlock; - - // - // Zero it - // - - *FsSize = 0; - - // - // Call driver - // - - RtlZeroMemory(&pi, sizeof(PARTITION_INFORMATION)); - - Status = NtDeviceIoControlFile( - h, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_PARTITION_INFO, - &pi, sizeof(PARTITION_INFORMATION), - &pi, sizeof(PARTITION_INFORMATION)); - - - if(NT_SUCCESS(Status)) - { - *FsSize = pi.PartitionLength.QuadPart; - } - else if(STATUS_INVALID_DEVICE_REQUEST == Status) - { - // - // No partitions: get device info. - // - - RtlZeroMemory(&gi, sizeof(DISK_GEOMETRY)); - - Status = NtDeviceIoControlFile( - h, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_GET_DRIVE_GEOMETRY, - &gi, sizeof(DISK_GEOMETRY), - &gi, sizeof(DISK_GEOMETRY)); - - - if(NT_SUCCESS(Status)) - { - *FsSize = - gi.BytesPerSector * - gi.SectorsPerTrack * - gi.TracksPerCylinder * - gi.Cylinders.QuadPart; - } - - } -} - - - -// -// Open device by name. -// - -static -BOOLEAN -_Ext2OpenDevice( - IN PCSTR Name, - IN BOOLEAN ReadOnly, - OUT PHANDLE Handle, - OUT PBOOLEAN OpenedReadonly OPTIONAL, - OUT unsigned *Errno OPTIONAL - ) -{ - CHAR NormalizedDeviceName[512]; - NTSTATUS Status; - - if(NULL == Name) - { - // - // Set not found - // - - if(ARGUMENT_PRESENT(Errno)) - *Errno = ENOENT; - - return FALSE; - } - - - if((((*Name) | 0x20) >= 'a') && (((*Name) | 0x20) <= 'z') && - (':' == *(Name + 1)) && ('\0' == *(Name + 2))) - { - Status = _OpenDriveLetter(*Name, ReadOnly, Handle, OpenedReadonly); - } - else - { - // - // Make name - // - - Name = _NormalizeDeviceName(Name, NormalizedDeviceName); - - if(NULL == Name) - { - // - // Set not found - // - - if(ARGUMENT_PRESENT(Errno)) - *Errno = ENOENT; - - return FALSE; - } - - // - // Try to open it - // - - Status = _OpenNtName(Name, ReadOnly, Handle, OpenedReadonly); - } - - - if(!NT_SUCCESS(Status)) - { - if(ARGUMENT_PRESENT(Errno)) - *Errno = _MapNtStatus(Status); - - return FALSE; - } - - return TRUE; -} - - -// -// Raw block io. Sets dos errno -// - -static -BOOLEAN -_BlockIo( - IN HANDLE Handle, - IN LARGE_INTEGER Offset, - IN ULONG Bytes, - IN OUT PCHAR Buffer, - IN BOOLEAN Read, - OUT unsigned* Errno - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS Status; - - // - // Should be aligned - // - - ASSERT(0 == (Bytes % 512)); - ASSERT(0 == (Offset.LowPart % 512)); - - - // - // perform io - // - - if(Read) - { - Status = NtReadFile(Handle, NULL, NULL, NULL, - &IoStatusBlock, Buffer, Bytes, &Offset, NULL); - } - else - { - Status = NtWriteFile(Handle, NULL, NULL, NULL, - &IoStatusBlock, Buffer, Bytes, &Offset, NULL); - } - - - // - // translate error - // - - if(NT_SUCCESS(Status)) - { - *Errno = 0; - return TRUE; - } - - *Errno = _MapNtStatus(Status); - - return FALSE; -} - - - -__inline -BOOLEAN -_RawWrite( - IN HANDLE Handle, - IN LARGE_INTEGER Offset, - IN ULONG Bytes, - OUT const CHAR* Buffer, - OUT unsigned* Errno - ) -{ - return _BlockIo(Handle, Offset, Bytes, (PCHAR)Buffer, FALSE, Errno); -} - -__inline -BOOLEAN -_RawRead( - IN HANDLE Handle, - IN LARGE_INTEGER Offset, - IN ULONG Bytes, - IN PCHAR Buffer, - OUT unsigned* Errno - ) -{ - return _BlockIo(Handle, Offset, Bytes, Buffer, TRUE, Errno); -} - - - -__inline -BOOLEAN -_SetPartType( - IN HANDLE Handle, - IN UCHAR Type - ) -{ - IO_STATUS_BLOCK IoStatusBlock; - return STATUS_SUCCESS == NtDeviceIoControlFile( - Handle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_DISK_SET_PARTITION_INFO, - &Type, sizeof(Type), - NULL, 0); -} - - - -//--------------------- interface part - -// -// Interface functions. -// Is_mounted is set to 1 if the device is mounted, 0 otherwise -// - -errcode_t -ext2fs_check_if_mounted(const char *file, int *mount_flags) -{ - HANDLE h; - BOOLEAN Readonly; - - *mount_flags = 0; - - if(!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL)) - { - return 0; - } - - - __try{ - *mount_flags &= _IsMounted(h) ? EXT2_MF_MOUNTED : 0; - } - __finally{ - _CloseDisk(h); - } - - return 0; -} - - - -// -// Returns the number of blocks in a partition -// - -static __int64 FsSize = 0; -static char knowndevice[1024] = ""; - - -errcode_t -ext2fs_get_device_size(const char *file, int blocksize, - blk_t *retblocks) -{ - HANDLE h; - BOOLEAN Readonly; - - if((0 == FsSize) || (0 != strcmp(knowndevice, file))) - { - - if(!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL)) - { - return 0; - } - - - __try{ - - // - // Get size - // - - _GetDeviceSize(h, &FsSize); - strcpy(knowndevice, file); - } - __finally{ - _CloseDisk(h); - } - - } - - *retblocks = (blk_t)(unsigned __int64)(FsSize / blocksize); - UNREFERENCED_PARAMETER(file); - return 0; -} - - - - - - -// -// Table elements -// - - -static -errcode_t -nt_open(const char *name, int flags, io_channel *channel) -{ - io_channel io = NULL; - PNT_PRIVATE_DATA NtData = NULL; - errcode_t Errno = 0; - - // - // Check name - // - - if (NULL == name) - { - return EXT2_ET_BAD_DEVICE_NAME; - } - - __try{ - - // - // Allocate channel handle - // - - io = (io_channel) malloc(sizeof(struct struct_io_channel)); - - if (NULL == io) - { - Errno = ENOMEM; - __leave; - } - - RtlZeroMemory(io, sizeof(struct struct_io_channel)); - io->magic = EXT2_ET_MAGIC_IO_CHANNEL; - - NtData = (PNT_PRIVATE_DATA)malloc(sizeof(NT_PRIVATE_DATA)); - - if (NULL == NtData) - { - Errno = ENOMEM; - __leave; - } - - - io->manager = nt_io_manager(); - io->name = malloc(strlen(name) + 1); - if (NULL == io->name) - { - Errno = ENOMEM; - __leave; - } - - strcpy(io->name, name); - io->private_data = NtData; - io->block_size = 1024; - io->read_error = 0; - io->write_error = 0; - io->refcount = 1; - - // - // Initialize data - // - - RtlZeroMemory(NtData, sizeof(NT_PRIVATE_DATA)); - - NtData->magic = EXT2_ET_MAGIC_NT_IO_CHANNEL; - NtData->BufferBlockNumber = 0xffffffff; - NtData->BufferSize = 1024; - NtData->Buffer = malloc(NtData->BufferSize); - - if (NULL == NtData->Buffer) - { - Errno = ENOMEM; - __leave; - } - - // - // Open it - // - - if(!_Ext2OpenDevice(name, (BOOLEAN)!BooleanFlagOn(flags, EXT2_FLAG_RW), &NtData->Handle, &NtData->OpenedReadonly, &Errno)) - { - __leave; - } - - - // - // get size - // - - _GetDeviceSize(NtData->Handle, &FsSize); - strcpy(knowndevice, name); - - - // - // Lock/dismount - // - - if(!NT_SUCCESS(_LockDrive(NtData->Handle)) /*|| !NT_SUCCESS(_DismountDrive(NtData->Handle))*/) - { - NtData->OpenedReadonly = TRUE; - } - - // - // Done - // - - *channel = io; - - - } - __finally{ - - if(0 != Errno) - { - // - // Cleanup - // - - if (NULL != io) - { - free(io->name); - free(io); - } - - if (NULL != NtData) - { - if(NULL != NtData->Handle) - { - _UnlockDrive(NtData->Handle); - _CloseDisk(NtData->Handle); - } - - free(NtData->Buffer); - free(NtData); - } - } - } - - return Errno; -} - - -// -// Close api -// - -static -errcode_t -nt_close(io_channel channel) -{ - PNT_PRIVATE_DATA NtData = NULL; - - if(NULL == channel) - { - return 0; - } - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - NtData = (PNT_PRIVATE_DATA) channel->private_data; - EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); - - if (--channel->refcount > 0) - { - return 0; - } - - free(channel->name); - free(channel); - - if (NULL != NtData) - { - if(NULL != NtData->Handle) - { - _DismountDrive(NtData->Handle); - _UnlockDrive(NtData->Handle); - _CloseDisk(NtData->Handle); - } - - free(NtData->Buffer); - free(NtData); - } - - return 0; -} - - - -// -// set block size -// - -static -errcode_t -nt_set_blksize(io_channel channel, int blksize) -{ - PNT_PRIVATE_DATA NtData = NULL; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - NtData = (PNT_PRIVATE_DATA) channel->private_data; - EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); - - if (channel->block_size != blksize) - { - channel->block_size = blksize; - - free(NtData->Buffer); - NtData->BufferBlockNumber = 0xffffffff; - NtData->BufferSize = channel->block_size; - ASSERT(0 == (NtData->BufferSize % 512)); - - NtData->Buffer = malloc(NtData->BufferSize); - - if (NULL == NtData->Buffer) - { - return ENOMEM; - } - - } - - return 0; -} - - -// -// read block -// - -static -errcode_t -nt_read_blk(io_channel channel, unsigned long block, - int count, void *buf) -{ - PVOID BufferToRead; - ULONG SizeToRead; - ULONG Size; - LARGE_INTEGER Offset; - PNT_PRIVATE_DATA NtData = NULL; - unsigned Errno = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - NtData = (PNT_PRIVATE_DATA) channel->private_data; - EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); - - // - // If it's in the cache, use it! - // - - if ((1 == count) && - (block == NtData->BufferBlockNumber) && - (NtData->BufferBlockNumber != 0xffffffff)) - { - memcpy(buf, NtData->Buffer, channel->block_size); - return 0; - } - - Size = (count < 0) ? (ULONG)(-count) : (ULONG)(count * channel->block_size); - - Offset.QuadPart = block * channel->block_size; - - // - // If not fit to the block - // - - if(Size <= NtData->BufferSize) - { - // - // Update the cache - // - - NtData->BufferBlockNumber = block; - BufferToRead = NtData->Buffer; - SizeToRead = NtData->BufferSize; - } - else - { - SizeToRead = Size; - BufferToRead = buf; - ASSERT(0 == (SizeToRead % channel->block_size)); - } - - if(!_RawRead(NtData->Handle, Offset, SizeToRead, BufferToRead, &Errno)) - { - - if (channel->read_error) - { - return (channel->read_error)(channel, block, count, buf, - Size, 0, Errno); - } - else - { - return Errno; - } - } - - - if(BufferToRead != buf) - { - ASSERT(Size <= SizeToRead); - memcpy(buf, BufferToRead, Size); - } - - return 0; -} - - -// -// write block -// - -static -errcode_t -nt_write_blk(io_channel channel, unsigned long block, - int count, const void *buf) -{ - ULONG SizeToWrite; - LARGE_INTEGER Offset; - PNT_PRIVATE_DATA NtData = NULL; - unsigned Errno = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - NtData = (PNT_PRIVATE_DATA) channel->private_data; - EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); - - if(NtData->OpenedReadonly) - { - return EACCES; - } - - if (count == 1) - { - SizeToWrite = channel->block_size; - } - else - { - NtData->BufferBlockNumber = 0xffffffff; - - if (count < 0) - { - SizeToWrite = (ULONG)(-count); - } - else - { - SizeToWrite = (ULONG)(count * channel->block_size); - } - } - - - ASSERT(0 == (SizeToWrite % 512)); - Offset.QuadPart = block * channel->block_size; - - if(!_RawWrite(NtData->Handle, Offset, SizeToWrite, buf, &Errno)) - { - if (channel->write_error) - { - return (channel->write_error)(channel, block, count, buf, - SizeToWrite, 0, Errno); - } - else - { - return Errno; - } - } - - - // - // Stash a copy. - // - - if(SizeToWrite >= NtData->BufferSize) - { - NtData->BufferBlockNumber = block; - memcpy(NtData->Buffer, buf, NtData->BufferSize); - } - - NtData->Written = TRUE; - - return 0; - -} - - - -// -// Flush data buffers to disk. Since we are currently using a -// write-through cache, this is a no-op. -// - -static -errcode_t -nt_flush(io_channel channel) -{ - PNT_PRIVATE_DATA NtData = NULL; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - NtData = (PNT_PRIVATE_DATA) channel->private_data; - EXT2_CHECK_MAGIC(NtData, EXT2_ET_MAGIC_NT_IO_CHANNEL); - - if(NtData->OpenedReadonly) - { - return 0; // EACCESS; - } - - - // - // Flush file buffers. - // - - _FlushDrive(NtData->Handle); - - - // - // Test and correct partition type. - // - - if(NtData->Written) - { - _SetPartType(NtData->Handle, 0x83); - } - - return 0; -} - - diff --git a/jni/e2fsprogs/lib/ext2fs/tdb.c b/jni/e2fsprogs/lib/ext2fs/tdb.c deleted file mode 100755 index b07b291..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tdb.c +++ /dev/null @@ -1,4174 +0,0 @@ -/* -URL: svn://svnanon.samba.org/samba/branches/SAMBA_4_0/source/lib/tdb/common -Rev: 23590 -Last Changed Date: 2007-06-22 13:36:10 -0400 (Fri, 22 Jun 2007) -*/ - /* - trivial database library - standalone version - - Copyright (C) Andrew Tridgell 1999-2005 - Copyright (C) Jeremy Allison 2000-2006 - Copyright (C) Paul `Rusty' Russell 2000 - - ** NOTE! The following LGPL license applies to the tdb - ** library. This does NOT imply that all of Samba is released - ** under the LGPL - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifdef CONFIG_STAND_ALONE -#define HAVE_MMAP -#define HAVE_STRDUP -#define HAVE_SYS_MMAN_H -#define HAVE_UTIME_H -#define HAVE_UTIME -#endif -#ifndef __FreeBSD__ -#define _XOPEN_SOURCE 600 -#endif - -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_SELECT_H -#include -#endif -#include -#include -#include -#ifdef HAVE_UTIME_H -#include -#endif -#include -#include -#include - -#ifdef HAVE_SYS_MMAN_H -#include -#endif - -#ifdef __GNUC__ -#define EXT2FS_ATTR(x) __attribute__(x) -#else -#define EXT2FS_ATTR(x) -#endif - -#ifndef MAP_FILE -#define MAP_FILE 0 -#endif - -#ifndef MAP_FAILED -#define MAP_FAILED ((void *)-1) -#endif - -#ifndef HAVE_STRDUP -#define strdup rep_strdup -static char *rep_strdup(const char *s) -{ - char *ret; - int length; - - if (!s) - return NULL; - length = strlen(s); - ret = malloc(length + 1); - if (ret) { - strncpy(ret, s, length); - ret[length] = '\0'; - } - return ret; -} -#endif - -#ifndef PRINTF_ATTRIBUTE -#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) -/** Use gcc attribute to check printf fns. a1 is the 1-based index of - * the parameter containing the format, and a2 the index of the first - * argument. Note that some gcc 2.x versions don't handle this - * properly **/ -#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) -#else -#define PRINTF_ATTRIBUTE(a1, a2) -#endif -#endif - -typedef int bool; - -#include "tdb.h" - -static TDB_DATA tdb_null; - -#ifndef u32 -#define u32 unsigned -#endif - -typedef u32 tdb_len_t; -typedef u32 tdb_off_t; - -#ifndef offsetof -#define offsetof(t,f) ((unsigned int)&((t *)0)->f) -#endif - -#define TDB_MAGIC_FOOD "TDB file\n" -#define TDB_VERSION (0x26011967 + 6) -#define TDB_MAGIC (0x26011999U) -#define TDB_FREE_MAGIC (~TDB_MAGIC) -#define TDB_DEAD_MAGIC (0xFEE1DEAD) -#define TDB_RECOVERY_MAGIC (0xf53bc0e7U) -#define TDB_ALIGNMENT 4 -#define MIN_REC_SIZE (2*sizeof(struct list_struct) + TDB_ALIGNMENT) -#define DEFAULT_HASH_SIZE 131 -#define FREELIST_TOP (sizeof(struct tdb_header)) -#define TDB_ALIGN(x,a) (((x) + (a)-1) & ~((a)-1)) -#define TDB_BYTEREV(x) (((((x)&0xff)<<24)|((x)&0xFF00)<<8)|(((x)>>8)&0xFF00)|((x)>>24)) -#define TDB_DEAD(r) ((r)->magic == TDB_DEAD_MAGIC) -#define TDB_BAD_MAGIC(r) ((r)->magic != TDB_MAGIC && !TDB_DEAD(r)) -#define TDB_HASH_TOP(hash) (FREELIST_TOP + (BUCKET(hash)+1)*sizeof(tdb_off_t)) -#define TDB_HASHTABLE_SIZE(tdb) ((tdb->header.hash_size+1)*sizeof(tdb_off_t)) -#define TDB_DATA_START(hash_size) TDB_HASH_TOP(hash_size-1) -#define TDB_RECOVERY_HEAD offsetof(struct tdb_header, recovery_start) -#define TDB_SEQNUM_OFS offsetof(struct tdb_header, sequence_number) -#define TDB_PAD_BYTE 0x42 -#define TDB_PAD_U32 0x42424242 - -/* NB assumes there is a local variable called "tdb" that is the - * current context, also takes doubly-parenthesized print-style - * argument. */ -#define TDB_LOG(x) tdb->log.log_fn x - -/* lock offsets */ -#define GLOBAL_LOCK 0 -#define ACTIVE_LOCK 4 -#define TRANSACTION_LOCK 8 - -/* free memory if the pointer is valid and zero the pointer */ -#ifndef SAFE_FREE -#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0) -#endif - -#define BUCKET(hash) ((hash) % tdb->header.hash_size) - -#define DOCONV() (tdb->flags & TDB_CONVERT) -#define CONVERT(x) (DOCONV() ? tdb_convert(&x, sizeof(x)) : &x) - - -/* the body of the database is made of one list_struct for the free space - plus a separate data list for each hash value */ -struct list_struct { - tdb_off_t next; /* offset of the next record in the list */ - tdb_len_t rec_len; /* total byte length of record */ - tdb_len_t key_len; /* byte length of key */ - tdb_len_t data_len; /* byte length of data */ - u32 full_hash; /* the full 32 bit hash of the key */ - u32 magic; /* try to catch errors */ - /* the following union is implied: - union { - char record[rec_len]; - struct { - char key[key_len]; - char data[data_len]; - } - u32 totalsize; (tailer) - } - */ -}; - - -/* this is stored at the front of every database */ -struct tdb_header { - char magic_food[32]; /* for /etc/magic */ - u32 version; /* version of the code */ - u32 hash_size; /* number of hash entries */ - tdb_off_t rwlocks; /* obsolete - kept to detect old formats */ - tdb_off_t recovery_start; /* offset of transaction recovery region */ - tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */ - tdb_off_t reserved[29]; -}; - -struct tdb_lock_type { - int list; - u32 count; - u32 ltype; -}; - -struct tdb_traverse_lock { - struct tdb_traverse_lock *next; - u32 off; - u32 hash; - int lock_rw; -}; - - -struct tdb_methods { - int (*tdb_read)(struct tdb_context *, tdb_off_t , void *, tdb_len_t , int ); - int (*tdb_write)(struct tdb_context *, tdb_off_t, const void *, tdb_len_t); - void (*next_hash_chain)(struct tdb_context *, u32 *); - int (*tdb_oob)(struct tdb_context *, tdb_off_t , int ); - int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t ); - int (*tdb_brlock)(struct tdb_context *, tdb_off_t , int, int, int, size_t); -}; - -struct tdb_context { - char *name; /* the name of the database */ - void *map_ptr; /* where it is currently mapped */ - int fd; /* open file descriptor for the database */ - tdb_len_t map_size; /* how much space has been mapped */ - int read_only; /* opened read-only */ - int traverse_read; /* read-only traversal */ - struct tdb_lock_type global_lock; - int num_lockrecs; - struct tdb_lock_type *lockrecs; /* only real locks, all with count>0 */ - enum TDB_ERROR ecode; /* error code for last tdb error */ - struct tdb_header header; /* a cached copy of the header */ - u32 flags; /* the flags passed to tdb_open */ - struct tdb_traverse_lock travlocks; /* current traversal locks */ - struct tdb_context *next; /* all tdbs to avoid multiple opens */ - dev_t device; /* uniquely identifies this tdb */ - ino_t inode; /* uniquely identifies this tdb */ - struct tdb_logging_context log; - unsigned int (*hash_fn)(TDB_DATA *key); - int open_flags; /* flags used in the open - needed by reopen */ - unsigned int num_locks; /* number of chain locks held */ - const struct tdb_methods *methods; - struct tdb_transaction *transaction; - int page_size; - int max_dead_records; - bool have_transaction_lock; - tdb_len_t real_map_size; /* how much space has been mapped */ -}; - - -/* - internal prototypes -*/ -static int tdb_munmap(struct tdb_context *tdb); -static void tdb_mmap(struct tdb_context *tdb); -static int tdb_lock(struct tdb_context *tdb, int list, int ltype); -int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype); -static int tdb_unlock(struct tdb_context *tdb, int list, int ltype); -static int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len); -static int tdb_transaction_lock(struct tdb_context *tdb, int ltype); -static int tdb_transaction_unlock(struct tdb_context *tdb); -static int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len); -static int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off); -static int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off); -static int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); -static int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); -static void *tdb_convert(void *buf, u32 size); -static int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec); -static tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec); -static int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); -static int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d); -static int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off); -static int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off); -static int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec); -static int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec); -static int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct *rec); -static unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len); -static int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key, - tdb_off_t offset, tdb_len_t len, - int (*parser)(TDB_DATA key, TDB_DATA data, - void *private_data), - void *private_data); -static tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype, - struct list_struct *rec); -static void tdb_io_init(struct tdb_context *tdb); -static int tdb_expand(struct tdb_context *tdb, tdb_off_t size); -static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, - struct list_struct *rec); - - -/* file: error.c */ - -enum TDB_ERROR tdb_error(struct tdb_context *tdb) -{ - return tdb->ecode; -} - -static struct tdb_errname { - enum TDB_ERROR ecode; const char *estring; -} emap[] = { {TDB_SUCCESS, "Success"}, - {TDB_ERR_CORRUPT, "Corrupt database"}, - {TDB_ERR_IO, "IO Error"}, - {TDB_ERR_LOCK, "Locking error"}, - {TDB_ERR_OOM, "Out of memory"}, - {TDB_ERR_EXISTS, "Record exists"}, - {TDB_ERR_NOLOCK, "Lock exists on other keys"}, - {TDB_ERR_EINVAL, "Invalid parameter"}, - {TDB_ERR_NOEXIST, "Record does not exist"}, - {TDB_ERR_RDONLY, "write not permitted"} }; - -/* Error string for the last tdb error */ -const char *tdb_errorstr(struct tdb_context *tdb) -{ - u32 i; - for (i = 0; i < sizeof(emap) / sizeof(struct tdb_errname); i++) - if (tdb->ecode == emap[i].ecode) - return emap[i].estring; - return "Invalid error code"; -} - -/* file: lock.c */ - -#define TDB_MARK_LOCK 0x80000000 - -/* a byte range locking function - return 0 on success - this functions locks/unlocks 1 byte at the specified offset. - - On error, errno is also set so that errors are passed back properly - through tdb_open(). - - note that a len of zero means lock to end of file -*/ -int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, - int rw_type, int lck_type, int probe, size_t len) -{ - struct flock fl; - int ret; - - if (tdb->flags & TDB_NOLOCK) { - return 0; - } - - if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) { - tdb->ecode = TDB_ERR_RDONLY; - return -1; - } - - fl.l_type = rw_type; - fl.l_whence = SEEK_SET; - fl.l_start = offset; - fl.l_len = len; - fl.l_pid = 0; - - do { - ret = fcntl(tdb->fd,lck_type,&fl); - } while (ret == -1 && errno == EINTR); - - if (ret == -1) { - /* Generic lock error. errno set by fcntl. - * EAGAIN is an expected return from non-blocking - * locks. */ - if (!probe && lck_type != F_SETLK) { - /* Ensure error code is set for log fun to examine. */ - tdb->ecode = TDB_ERR_LOCK; - TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n", - tdb->fd, offset, rw_type, lck_type, (int)len)); - } - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - return 0; -} - - -/* - upgrade a read lock to a write lock. This needs to be handled in a - special way as some OSes (such as solaris) have too conservative - deadlock detection and claim a deadlock when progress can be - made. For those OSes we may loop for a while. -*/ -int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len) -{ - int count = 1000; - while (count--) { - struct timeval tv; - if (tdb_brlock(tdb, offset, F_WRLCK, F_SETLKW, 1, len) == 0) { - return 0; - } - if (errno != EDEADLK) { - break; - } - /* sleep for as short a time as we can - more portable than usleep() */ - tv.tv_sec = 0; - tv.tv_usec = 1; - select(0, NULL, NULL, NULL, &tv); - } - TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock_upgrade failed at offset %d\n", offset)); - return -1; -} - - -/* lock a list in the database. list -1 is the alloc list */ -static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op) -{ - struct tdb_lock_type *new_lck; - int i; - bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); - - ltype &= ~TDB_MARK_LOCK; - - /* a global lock allows us to avoid per chain locks */ - if (tdb->global_lock.count && - ((u32)ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { - return 0; - } - - if (tdb->global_lock.count) { - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - - if (list < -1 || list >= (int)tdb->header.hash_size) { - TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n", - list, ltype)); - return -1; - } - if (tdb->flags & TDB_NOLOCK) - return 0; - - for (i=0; inum_lockrecs; i++) { - if (tdb->lockrecs[i].list == list) { - if (tdb->lockrecs[i].count == 0) { - /* - * Can't happen, see tdb_unlock(). It should - * be an assert. - */ - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock: " - "lck->count == 0 for list %d", list)); - } - /* - * Just increment the in-memory struct, posix locks - * don't stack. - */ - tdb->lockrecs[i].count++; - return 0; - } - } - - new_lck = (struct tdb_lock_type *)realloc( - tdb->lockrecs, - sizeof(*tdb->lockrecs) * (tdb->num_lockrecs+1)); - if (new_lck == NULL) { - errno = ENOMEM; - return -1; - } - tdb->lockrecs = new_lck; - - /* Since fcntl locks don't nest, we do a lock for the first one, - and simply bump the count for future ones */ - if (!mark_lock && - tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list, ltype, op, - 0, 1)) { - return -1; - } - - tdb->num_locks++; - - tdb->lockrecs[tdb->num_lockrecs].list = list; - tdb->lockrecs[tdb->num_lockrecs].count = 1; - tdb->lockrecs[tdb->num_lockrecs].ltype = ltype; - tdb->num_lockrecs += 1; - - return 0; -} - -/* lock a list in the database. list -1 is the alloc list */ -int tdb_lock(struct tdb_context *tdb, int list, int ltype) -{ - int ret; - ret = _tdb_lock(tdb, list, ltype, F_SETLKW); - if (ret) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d " - "ltype=%d (%s)\n", list, ltype, strerror(errno))); - } - return ret; -} - -/* lock a list in the database. list -1 is the alloc list. non-blocking lock */ -int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype) -{ - return _tdb_lock(tdb, list, ltype, F_SETLK); -} - - -/* unlock the database: returns void because it's too late for errors. */ - /* changed to return int it may be interesting to know there - has been an error --simo */ -int tdb_unlock(struct tdb_context *tdb, int list, int ltype) -{ - int ret = -1; - int i; - struct tdb_lock_type *lck = NULL; - bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); - - ltype &= ~TDB_MARK_LOCK; - - /* a global lock allows us to avoid per chain locks */ - if (tdb->global_lock.count && - ((u32)ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { - return 0; - } - - if (tdb->global_lock.count) { - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - - if (tdb->flags & TDB_NOLOCK) - return 0; - - /* Sanity checks */ - if (list < -1 || list >= (int)tdb->header.hash_size) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); - return ret; - } - - for (i=0; inum_lockrecs; i++) { - if (tdb->lockrecs[i].list == list) { - lck = &tdb->lockrecs[i]; - break; - } - } - - if ((lck == NULL) || (lck->count == 0)) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n")); - return -1; - } - - if (lck->count > 1) { - lck->count--; - return 0; - } - - /* - * This lock has count==1 left, so we need to unlock it in the - * kernel. We don't bother with decrementing the in-memory array - * element, we're about to overwrite it with the last array element - * anyway. - */ - - if (mark_lock) { - ret = 0; - } else { - ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, - F_SETLKW, 0, 1); - } - tdb->num_locks--; - - /* - * Shrink the array by overwriting the element just unlocked with the - * last array element. - */ - - if (tdb->num_lockrecs > 1) { - *lck = tdb->lockrecs[tdb->num_lockrecs-1]; - } - tdb->num_lockrecs -= 1; - - /* - * We don't bother with realloc when the array shrinks, but if we have - * a completely idle tdb we should get rid of the locked array. - */ - - if (tdb->num_lockrecs == 0) { - SAFE_FREE(tdb->lockrecs); - } - - if (ret) - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: An error occurred unlocking!\n")); - return ret; -} - -/* - get the transaction lock - */ -int tdb_transaction_lock(struct tdb_context *tdb, int ltype) -{ - if (tdb->have_transaction_lock || tdb->global_lock.count) { - return 0; - } - if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype, - F_SETLKW, 0, 1) == -1) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n")); - tdb->ecode = TDB_ERR_LOCK; - return -1; - } - tdb->have_transaction_lock = 1; - return 0; -} - -/* - release the transaction lock - */ -int tdb_transaction_unlock(struct tdb_context *tdb) -{ - int ret; - if (!tdb->have_transaction_lock) { - return 0; - } - ret = tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); - if (ret == 0) { - tdb->have_transaction_lock = 0; - } - return ret; -} - - - - -/* lock/unlock entire database */ -static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op) -{ - bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); - - ltype &= ~TDB_MARK_LOCK; - - /* There are no locks on read-only dbs */ - if (tdb->read_only || tdb->traverse_read) - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - - if (tdb->global_lock.count && tdb->global_lock.ltype == (u32)ltype) { - tdb->global_lock.count++; - return 0; - } - - if (tdb->global_lock.count) { - /* a global lock of a different type exists */ - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - - if (tdb->num_locks != 0) { - /* can't combine global and chain locks */ - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - - if (!mark_lock && - tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, op, - 0, 4*tdb->header.hash_size)) { - if (op == F_SETLKW) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno))); - } - return -1; - } - - tdb->global_lock.count = 1; - tdb->global_lock.ltype = ltype; - - return 0; -} - - - -/* unlock entire db */ -static int _tdb_unlockall(struct tdb_context *tdb, int ltype) -{ - bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); - - ltype &= ~TDB_MARK_LOCK; - - /* There are no locks on read-only dbs */ - if (tdb->read_only || tdb->traverse_read) { - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - - if (tdb->global_lock.ltype != (u32)ltype || - tdb->global_lock.count == 0) { - return TDB_ERRCODE(TDB_ERR_LOCK, -1); - } - - if (tdb->global_lock.count > 1) { - tdb->global_lock.count--; - return 0; - } - - if (!mark_lock && - tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, - 0, 4*tdb->header.hash_size)) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno))); - return -1; - } - - tdb->global_lock.count = 0; - tdb->global_lock.ltype = 0; - - return 0; -} - -/* lock entire database with write lock */ -int tdb_lockall(struct tdb_context *tdb) -{ - return _tdb_lockall(tdb, F_WRLCK, F_SETLKW); -} - -/* lock entire database with write lock - mark only */ -int tdb_lockall_mark(struct tdb_context *tdb) -{ - return _tdb_lockall(tdb, F_WRLCK | TDB_MARK_LOCK, F_SETLKW); -} - -/* unlock entire database with write lock - unmark only */ -int tdb_lockall_unmark(struct tdb_context *tdb) -{ - return _tdb_unlockall(tdb, F_WRLCK | TDB_MARK_LOCK); -} - -/* lock entire database with write lock - nonblocking variant */ -int tdb_lockall_nonblock(struct tdb_context *tdb) -{ - return _tdb_lockall(tdb, F_WRLCK, F_SETLK); -} - -/* unlock entire database with write lock */ -int tdb_unlockall(struct tdb_context *tdb) -{ - return _tdb_unlockall(tdb, F_WRLCK); -} - -/* lock entire database with read lock */ -int tdb_lockall_read(struct tdb_context *tdb) -{ - return _tdb_lockall(tdb, F_RDLCK, F_SETLKW); -} - -/* lock entire database with read lock - nonblock variant */ -int tdb_lockall_read_nonblock(struct tdb_context *tdb) -{ - return _tdb_lockall(tdb, F_RDLCK, F_SETLK); -} - -/* unlock entire database with read lock */ -int tdb_unlockall_read(struct tdb_context *tdb) -{ - return _tdb_unlockall(tdb, F_RDLCK); -} - -/* lock/unlock one hash chain. This is meant to be used to reduce - contention - it cannot guarantee how many records will be locked */ -int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key) -{ - return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); -} - -/* lock/unlock one hash chain, non-blocking. This is meant to be used - to reduce contention - it cannot guarantee how many records will be - locked */ -int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key) -{ - return tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); -} - -/* mark a chain as locked without actually locking it. Warning! use with great caution! */ -int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key) -{ - return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK); -} - -/* unmark a chain as locked without actually locking it. Warning! use with great caution! */ -int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key) -{ - return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK); -} - -int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) -{ - return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); -} - -int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key) -{ - return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); -} - -int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key) -{ - return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK); -} - - - -/* record lock stops delete underneath */ -int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off) -{ - return off ? tdb->methods->tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0, 1) : 0; -} - -/* - Write locks override our own fcntl readlocks, so check it here. - Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not - an error to fail to get the lock here. -*/ -int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off) -{ - struct tdb_traverse_lock *i; - for (i = &tdb->travlocks; i; i = i->next) - if (i->off == off) - return -1; - return tdb->methods->tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1, 1); -} - -/* - Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not - an error to fail to get the lock here. -*/ -int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off) -{ - return tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0, 1); -} - -/* fcntl locks don't stack: avoid unlocking someone else's */ -int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off) -{ - struct tdb_traverse_lock *i; - u32 count = 0; - - if (off == 0) - return 0; - for (i = &tdb->travlocks; i; i = i->next) - if (i->off == off) - count++; - return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0, 1) : 0); -} - -/* file: io.c */ - -/* check for an out of bounds access - if it is out of bounds then - see if the database has been expanded by someone else and expand - if necessary - note that "len" is the minimum length needed for the db -*/ -static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) -{ - struct stat st; - if (len <= tdb->map_size) - return 0; - if (tdb->flags & TDB_INTERNAL) { - if (!probe) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond internal malloc size %d\n", - (int)len, (int)tdb->map_size)); - } - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - - if (fstat(tdb->fd, &st) == -1) { - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - - if (st.st_size < (off_t)len) { - if (!probe) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond eof at %d\n", - (int)len, (int)st.st_size)); - } - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - - /* Unmap, update size, remap */ - if (tdb_munmap(tdb) == -1) - return TDB_ERRCODE(TDB_ERR_IO, -1); - tdb->map_size = st.st_size; - tdb_mmap(tdb); - return 0; -} - -/* write a lump of data at a specified offset */ -static int tdb_write(struct tdb_context *tdb, tdb_off_t off, - const void *buf, tdb_len_t len) -{ - if (len == 0) { - return 0; - } - - if (tdb->read_only || tdb->traverse_read) { - tdb->ecode = TDB_ERR_RDONLY; - return -1; - } - - if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) - return -1; - - if (tdb->map_ptr) { - memcpy(off + (char *)tdb->map_ptr, buf, len); - } else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_write failed at %d len=%d (%s)\n", - off, len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - return 0; -} - -/* Endian conversion: we only ever deal with 4 byte quantities */ -void *tdb_convert(void *buf, u32 size) -{ - u32 i, *p = (u32 *)buf; - for (i = 0; i < size / 4; i++) - p[i] = TDB_BYTEREV(p[i]); - return buf; -} - - -/* read a lump of data at a specified offset, maybe convert */ -static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, - tdb_len_t len, int cv) -{ - if (tdb->methods->tdb_oob(tdb, off + len, 0) != 0) { - return -1; - } - - if (tdb->map_ptr) { - memcpy(buf, off + (char *)tdb->map_ptr, len); - } else { - ssize_t ret = pread(tdb->fd, buf, len, off); - if (ret != (ssize_t)len) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_read failed at %d " - "len=%d ret=%d (%s) map_size=%d\n", - (int)off, (int)len, (int)ret, strerror(errno), - (int)tdb->map_size)); - return TDB_ERRCODE(TDB_ERR_IO, -1); - } - } - if (cv) { - tdb_convert(buf, len); - } - return 0; -} - - - -/* - do an unlocked scan of the hash table heads to find the next non-zero head. The value - will then be confirmed with the lock held -*/ -static void tdb_next_hash_chain(struct tdb_context *tdb, u32 *chain) -{ - u32 h = *chain; - if (tdb->map_ptr) { - for (;h < tdb->header.hash_size;h++) { - if (0 != *(u32 *)(TDB_HASH_TOP(h) + (unsigned char *)tdb->map_ptr)) { - break; - } - } - } else { - u32 off=0; - for (;h < tdb->header.hash_size;h++) { - if (tdb_ofs_read(tdb, TDB_HASH_TOP(h), &off) != 0 || off != 0) { - break; - } - } - } - (*chain) = h; -} - - -int tdb_munmap(struct tdb_context *tdb) -{ - if (tdb->flags & TDB_INTERNAL) - return 0; - -#ifdef HAVE_MMAP - if (tdb->map_ptr) { - int ret = munmap(tdb->map_ptr, tdb->real_map_size); - if (ret != 0) - return ret; - tdb->real_map_size = 0; - } -#endif - tdb->map_ptr = NULL; - return 0; -} - -void tdb_mmap(struct tdb_context *tdb) -{ - if (tdb->flags & TDB_INTERNAL) - return; - -#ifdef HAVE_MMAP - if (!(tdb->flags & TDB_NOMMAP)) { - tdb->map_ptr = mmap(NULL, tdb->map_size, - PROT_READ|(tdb->read_only? 0:PROT_WRITE), - MAP_SHARED|MAP_FILE, tdb->fd, 0); - - /* - * NB. When mmap fails it returns MAP_FAILED *NOT* NULL !!!! - */ - - if (tdb->map_ptr == MAP_FAILED) { - tdb->real_map_size = 0; - tdb->map_ptr = NULL; - TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_mmap failed for size %d (%s)\n", - tdb->map_size, strerror(errno))); - } - tdb->real_map_size = tdb->map_size; - } else { - tdb->map_ptr = NULL; - } -#else - tdb->map_ptr = NULL; -#endif -} - -/* expand a file. we prefer to use ftruncate, as that is what posix - says to use for mmap expansion */ -static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t addition) -{ - char buf[1024]; - - if (tdb->read_only || tdb->traverse_read) { - tdb->ecode = TDB_ERR_RDONLY; - return -1; - } - - if (ftruncate(tdb->fd, size+addition) == -1) { - char b = 0; - if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file to %d failed (%s)\n", - size+addition, strerror(errno))); - return -1; - } - } - - /* now fill the file with something. This ensures that the - file isn't sparse, which would be very bad if we ran out of - disk. This must be done with write, not via mmap */ - memset(buf, TDB_PAD_BYTE, sizeof(buf)); - while (addition) { - int n = addition>sizeof(buf)?sizeof(buf):addition; - int ret = pwrite(tdb->fd, buf, n, size); - if (ret != n) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of %d failed (%s)\n", - n, strerror(errno))); - return -1; - } - addition -= n; - size += n; - } - return 0; -} - - -/* expand the database at least size bytes by expanding the underlying - file and doing the mmap again if necessary */ -int tdb_expand(struct tdb_context *tdb, tdb_off_t size) -{ - struct list_struct rec; - tdb_off_t offset; - - if (tdb_lock(tdb, -1, F_WRLCK) == -1) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "lock failed in tdb_expand\n")); - return -1; - } - - /* must know about any previous expansions by another process */ - tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); - - /* always make room for at least 10 more records, and round - the database up to a multiple of the page size */ - size = TDB_ALIGN(tdb->map_size + size*10, tdb->page_size) - tdb->map_size; - - if (!(tdb->flags & TDB_INTERNAL)) - tdb_munmap(tdb); - - /* - * We must ensure the file is unmapped before doing this - * to ensure consistency with systems like OpenBSD where - * writes and mmaps are not consistent. - */ - - /* expand the file itself */ - if (!(tdb->flags & TDB_INTERNAL)) { - if (tdb->methods->tdb_expand_file(tdb, tdb->map_size, size) != 0) - goto fail; - } - - tdb->map_size += size; - - if (tdb->flags & TDB_INTERNAL) { - char *new_map_ptr = (char *)realloc(tdb->map_ptr, - tdb->map_size); - if (!new_map_ptr) { - tdb->map_size -= size; - goto fail; - } - tdb->map_ptr = new_map_ptr; - } else { - /* - * We must ensure the file is remapped before adding the space - * to ensure consistency with systems like OpenBSD where - * writes and mmaps are not consistent. - */ - - /* We're ok if the mmap fails as we'll fallback to read/write */ - tdb_mmap(tdb); - } - - /* form a new freelist record */ - memset(&rec,'\0',sizeof(rec)); - rec.rec_len = size - sizeof(rec); - - /* link it into the free list */ - offset = tdb->map_size - size; - if (tdb_free(tdb, offset, &rec) == -1) - goto fail; - - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return -1; -} - -/* read/write a tdb_off_t */ -int tdb_ofs_read(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) -{ - return tdb->methods->tdb_read(tdb, offset, (char*)d, sizeof(*d), DOCONV()); -} - -int tdb_ofs_write(struct tdb_context *tdb, tdb_off_t offset, tdb_off_t *d) -{ - tdb_off_t off = *d; - return tdb->methods->tdb_write(tdb, offset, CONVERT(off), sizeof(*d)); -} - - -/* read a lump of data, allocating the space for it */ -unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len) -{ - unsigned char *buf; - - /* some systems don't like zero length malloc */ - if (len == 0) { - len = 1; - } - - if (!(buf = (unsigned char *)malloc(len))) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_OOM; - TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_alloc_read malloc failed len=%d (%s)\n", - len, strerror(errno))); - return TDB_ERRCODE(TDB_ERR_OOM, buf); - } - if (tdb->methods->tdb_read(tdb, offset, buf, len, 0) == -1) { - SAFE_FREE(buf); - return NULL; - } - return buf; -} - -/* Give a piece of tdb data to a parser */ - -int tdb_parse_data(struct tdb_context *tdb, TDB_DATA key, - tdb_off_t offset, tdb_len_t len, - int (*parser)(TDB_DATA key, TDB_DATA data, - void *private_data), - void *private_data) -{ - TDB_DATA data; - int result; - - data.dsize = len; - - if ((tdb->transaction == NULL) && (tdb->map_ptr != NULL)) { - /* - * Optimize by avoiding the malloc/memcpy/free, point the - * parser directly at the mmap area. - */ - if (tdb->methods->tdb_oob(tdb, offset+len, 0) != 0) { - return -1; - } - data.dptr = offset + (unsigned char *)tdb->map_ptr; - return parser(key, data, private_data); - } - - if (!(data.dptr = tdb_alloc_read(tdb, offset, len))) { - return -1; - } - - result = parser(key, data, private_data); - free(data.dptr); - return result; -} - -/* read/write a record */ -int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) -{ - if (tdb->methods->tdb_read(tdb, offset, rec, sizeof(*rec),DOCONV()) == -1) - return -1; - if (TDB_BAD_MAGIC(rec)) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_CORRUPT; - TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); - } - return tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0); -} - -int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) -{ - struct list_struct r = *rec; - return tdb->methods->tdb_write(tdb, offset, CONVERT(r), sizeof(r)); -} - -static const struct tdb_methods io_methods = { - tdb_read, - tdb_write, - tdb_next_hash_chain, - tdb_oob, - tdb_expand_file, - tdb_brlock -}; - -/* - initialise the default methods table -*/ -void tdb_io_init(struct tdb_context *tdb) -{ - tdb->methods = &io_methods; -} - -/* file: transaction.c */ - -/* - transaction design: - - - only allow a single transaction at a time per database. This makes - using the transaction API simpler, as otherwise the caller would - have to cope with temporary failures in transactions that conflict - with other current transactions - - - keep the transaction recovery information in the same file as the - database, using a special 'transaction recovery' record pointed at - by the header. This removes the need for extra journal files as - used by some other databases - - - dynamically allocated the transaction recover record, re-using it - for subsequent transactions. If a larger record is needed then - tdb_free() the old record to place it on the normal tdb freelist - before allocating the new record - - - during transactions, keep a linked list of writes all that have - been performed by intercepting all tdb_write() calls. The hooked - transaction versions of tdb_read() and tdb_write() check this - linked list and try to use the elements of the list in preference - to the real database. - - - don't allow any locks to be held when a transaction starts, - otherwise we can end up with deadlock (plus lack of lock nesting - in posix locks would mean the lock is lost) - - - if the caller gains a lock during the transaction but doesn't - release it then fail the commit - - - allow for nested calls to tdb_transaction_start(), re-using the - existing transaction record. If the inner transaction is cancelled - then a subsequent commit will fail - - - keep a mirrored copy of the tdb hash chain heads to allow for the - fast hash heads scan on traverse, updating the mirrored copy in - the transaction version of tdb_write - - - allow callers to mix transaction and non-transaction use of tdb, - although once a transaction is started then an exclusive lock is - gained until the transaction is committed or cancelled - - - the commit strategy involves first saving away all modified data - into a linearised buffer in the transaction recovery area, then - marking the transaction recovery area with a magic value to - indicate a valid recovery record. In total 4 fsync/msync calls are - needed per commit to prevent race conditions. It might be possible - to reduce this to 3 or even 2 with some more work. - - - check for a valid recovery record on open of the tdb, while the - global lock is held. Automatically recover from the transaction - recovery area if needed, then continue with the open as - usual. This allows for smooth crash recovery with no administrator - intervention. - - - if TDB_NOSYNC is passed to flags in tdb_open then transactions are - still available, but no transaction recovery area is used and no - fsync/msync calls are made. - -*/ - -struct tdb_transaction_el { - struct tdb_transaction_el *next, *prev; - tdb_off_t offset; - tdb_len_t length; - unsigned char *data; -}; - -/* - hold the context of any current transaction -*/ -struct tdb_transaction { - /* we keep a mirrored copy of the tdb hash heads here so - tdb_next_hash_chain() can operate efficiently */ - u32 *hash_heads; - - /* the original io methods - used to do IOs to the real db */ - const struct tdb_methods *io_methods; - - /* the list of transaction elements. We use a doubly linked - list with a last pointer to allow us to keep the list - ordered, with first element at the front of the list. It - needs to be doubly linked as the read/write traversals need - to be backwards, while the commit needs to be forwards */ - struct tdb_transaction_el *elements, *elements_last; - - /* non-zero when an internal transaction error has - occurred. All write operations will then fail until the - transaction is ended */ - int transaction_error; - - /* when inside a transaction we need to keep track of any - nested tdb_transaction_start() calls, as these are allowed, - but don't create a new transaction */ - int nesting; - - /* old file size before transaction */ - tdb_len_t old_map_size; -}; - - -/* - read while in a transaction. We need to check first if the data is in our list - of transaction elements, then if not do a real read -*/ -static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf, - tdb_len_t len, int cv) -{ - struct tdb_transaction_el *el; - - /* we need to walk the list backwards to get the most recent data */ - for (el=tdb->transaction->elements_last;el;el=el->prev) { - tdb_len_t partial; - - if (off+len <= el->offset) { - continue; - } - if (off >= el->offset + el->length) { - continue; - } - - /* an overlapping read - needs to be split into up to - 2 reads and a memcpy */ - if (off < el->offset) { - partial = el->offset - off; - if (transaction_read(tdb, off, buf, partial, cv) != 0) { - goto fail; - } - len -= partial; - off += partial; - buf = (void *)(partial + (char *)buf); - } - if (off + len <= el->offset + el->length) { - partial = len; - } else { - partial = el->offset + el->length - off; - } - memcpy(buf, el->data + (off - el->offset), partial); - if (cv) { - tdb_convert(buf, len); - } - len -= partial; - off += partial; - buf = (void *)(partial + (char *)buf); - - if (len != 0 && transaction_read(tdb, off, buf, len, cv) != 0) { - goto fail; - } - - return 0; - } - - /* its not in the transaction elements - do a real read */ - return tdb->transaction->io_methods->tdb_read(tdb, off, buf, len, cv); - -fail: - TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_read: failed at off=%d len=%d\n", off, len)); - tdb->ecode = TDB_ERR_IO; - tdb->transaction->transaction_error = 1; - return -1; -} - - -/* - write while in a transaction -*/ -static int transaction_write(struct tdb_context *tdb, tdb_off_t off, - const void *buf, tdb_len_t len) -{ - struct tdb_transaction_el *el, *best_el=NULL; - - if (len == 0) { - return 0; - } - - /* if the write is to a hash head, then update the transaction - hash heads */ - if (len == sizeof(tdb_off_t) && off >= FREELIST_TOP && - off < FREELIST_TOP+TDB_HASHTABLE_SIZE(tdb)) { - u32 chain = (off-FREELIST_TOP) / sizeof(tdb_off_t); - memcpy(&tdb->transaction->hash_heads[chain], buf, len); - } - - /* first see if we can replace an existing entry */ - for (el=tdb->transaction->elements_last;el;el=el->prev) { - tdb_len_t partial; - - if (best_el == NULL && off == el->offset+el->length) { - best_el = el; - } - - if (off+len <= el->offset) { - continue; - } - if (off >= el->offset + el->length) { - continue; - } - - /* an overlapping write - needs to be split into up to - 2 writes and a memcpy */ - if (off < el->offset) { - partial = el->offset - off; - if (transaction_write(tdb, off, buf, partial) != 0) { - goto fail; - } - len -= partial; - off += partial; - buf = (const void *)(partial + (const char *)buf); - } - if (off + len <= el->offset + el->length) { - partial = len; - } else { - partial = el->offset + el->length - off; - } - memcpy(el->data + (off - el->offset), buf, partial); - len -= partial; - off += partial; - buf = (const void *)(partial + (const char *)buf); - - if (len != 0 && transaction_write(tdb, off, buf, len) != 0) { - goto fail; - } - - return 0; - } - - /* see if we can append the new entry to an existing entry */ - if (best_el && best_el->offset + best_el->length == off && - (off+len < tdb->transaction->old_map_size || - off > tdb->transaction->old_map_size)) { - unsigned char *data = best_el->data; - el = best_el; - el->data = (unsigned char *)realloc(el->data, - el->length + len); - if (el->data == NULL) { - tdb->ecode = TDB_ERR_OOM; - tdb->transaction->transaction_error = 1; - el->data = data; - return -1; - } - if (buf) { - memcpy(el->data + el->length, buf, len); - } else { - memset(el->data + el->length, TDB_PAD_BYTE, len); - } - el->length += len; - return 0; - } - - /* add a new entry at the end of the list */ - el = (struct tdb_transaction_el *)malloc(sizeof(*el)); - if (el == NULL) { - tdb->ecode = TDB_ERR_OOM; - tdb->transaction->transaction_error = 1; - return -1; - } - el->next = NULL; - el->prev = tdb->transaction->elements_last; - el->offset = off; - el->length = len; - el->data = (unsigned char *)malloc(len); - if (el->data == NULL) { - free(el); - tdb->ecode = TDB_ERR_OOM; - tdb->transaction->transaction_error = 1; - return -1; - } - if (buf) { - memcpy(el->data, buf, len); - } else { - memset(el->data, TDB_PAD_BYTE, len); - } - if (el->prev) { - el->prev->next = el; - } else { - tdb->transaction->elements = el; - } - tdb->transaction->elements_last = el; - return 0; - -fail: - TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: failed at off=%d len=%d\n", off, len)); - tdb->ecode = TDB_ERR_IO; - tdb->transaction->transaction_error = 1; - return -1; -} - -/* - accelerated hash chain head search, using the cached hash heads -*/ -static void transaction_next_hash_chain(struct tdb_context *tdb, u32 *chain) -{ - u32 h = *chain; - for (;h < tdb->header.hash_size;h++) { - /* the +1 takes account of the freelist */ - if (0 != tdb->transaction->hash_heads[h+1]) { - break; - } - } - (*chain) = h; -} - -/* - out of bounds check during a transaction -*/ -static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, - int probe EXT2FS_ATTR((unused))) -{ - if (len <= tdb->map_size) { - return 0; - } - return TDB_ERRCODE(TDB_ERR_IO, -1); -} - -/* - transaction version of tdb_expand(). -*/ -static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size, - tdb_off_t addition) -{ - /* add a write to the transaction elements, so subsequent - reads see the zero data */ - if (transaction_write(tdb, size, NULL, addition) != 0) { - return -1; - } - - return 0; -} - -/* - brlock during a transaction - ignore them -*/ -static int transaction_brlock(struct tdb_context *tdb EXT2FS_ATTR((unused)), - tdb_off_t offset EXT2FS_ATTR((unused)), - int rw_type EXT2FS_ATTR((unused)), - int lck_type EXT2FS_ATTR((unused)), - int probe EXT2FS_ATTR((unused)), - size_t len EXT2FS_ATTR((unused))) -{ - return 0; -} - -static const struct tdb_methods transaction_methods = { - transaction_read, - transaction_write, - transaction_next_hash_chain, - transaction_oob, - transaction_expand_file, - transaction_brlock -}; - - -/* - start a tdb transaction. No token is returned, as only a single - transaction is allowed to be pending per tdb_context -*/ -int tdb_transaction_start(struct tdb_context *tdb) -{ - /* some sanity checks */ - if (tdb->read_only || (tdb->flags & TDB_INTERNAL) || tdb->traverse_read) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n")); - tdb->ecode = TDB_ERR_EINVAL; - return -1; - } - - /* cope with nested tdb_transaction_start() calls */ - if (tdb->transaction != NULL) { - tdb->transaction->nesting++; - TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n", - tdb->transaction->nesting)); - return 0; - } - - if (tdb->num_locks != 0 || tdb->global_lock.count) { - /* the caller must not have any locks when starting a - transaction as otherwise we'll be screwed by lack - of nested locks in posix */ - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction with locks held\n")); - tdb->ecode = TDB_ERR_LOCK; - return -1; - } - - if (tdb->travlocks.next != NULL) { - /* you cannot use transactions inside a traverse (although you can use - traverse inside a transaction) as otherwise you can end up with - deadlock */ - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction within a traverse\n")); - tdb->ecode = TDB_ERR_LOCK; - return -1; - } - - tdb->transaction = (struct tdb_transaction *) - calloc(sizeof(struct tdb_transaction), 1); - if (tdb->transaction == NULL) { - tdb->ecode = TDB_ERR_OOM; - return -1; - } - - /* get the transaction write lock. This is a blocking lock. As - discussed with Volker, there are a number of ways we could - make this async, which we will probably do in the future */ - if (tdb_transaction_lock(tdb, F_WRLCK) == -1) { - SAFE_FREE(tdb->transaction); - return -1; - } - - /* get a read lock from the freelist to the end of file. This - is upgraded to a write lock during the commit */ - if (tdb_brlock(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get hash locks\n")); - tdb->ecode = TDB_ERR_LOCK; - goto fail; - } - - /* setup a copy of the hash table heads so the hash scan in - traverse can be fast */ - tdb->transaction->hash_heads = (u32 *) - calloc(tdb->header.hash_size+1, sizeof(u32)); - if (tdb->transaction->hash_heads == NULL) { - tdb->ecode = TDB_ERR_OOM; - goto fail; - } - if (tdb->methods->tdb_read(tdb, FREELIST_TOP, tdb->transaction->hash_heads, - TDB_HASHTABLE_SIZE(tdb), 0) != 0) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to read hash heads\n")); - tdb->ecode = TDB_ERR_IO; - goto fail; - } - - /* make sure we know about any file expansions already done by - anyone else */ - tdb->methods->tdb_oob(tdb, tdb->map_size + 1, 1); - tdb->transaction->old_map_size = tdb->map_size; - - /* finally hook the io methods, replacing them with - transaction specific methods */ - tdb->transaction->io_methods = tdb->methods; - tdb->methods = &transaction_methods; - - /* by calling this transaction write here, we ensure that we don't grow the - transaction linked list due to hash table updates */ - if (transaction_write(tdb, FREELIST_TOP, tdb->transaction->hash_heads, - TDB_HASHTABLE_SIZE(tdb)) != 0) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to prime hash table\n")); - tdb->ecode = TDB_ERR_IO; - tdb->methods = tdb->transaction->io_methods; - goto fail; - } - - return 0; - -fail: - tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); - tdb_transaction_unlock(tdb); - SAFE_FREE(tdb->transaction->hash_heads); - SAFE_FREE(tdb->transaction); - return -1; -} - - -/* - cancel the current transaction -*/ -int tdb_transaction_cancel(struct tdb_context *tdb) -{ - if (tdb->transaction == NULL) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n")); - return -1; - } - - if (tdb->transaction->nesting != 0) { - tdb->transaction->transaction_error = 1; - tdb->transaction->nesting--; - return 0; - } - - tdb->map_size = tdb->transaction->old_map_size; - - /* free all the transaction elements */ - while (tdb->transaction->elements) { - struct tdb_transaction_el *el = tdb->transaction->elements; - tdb->transaction->elements = el->next; - free(el->data); - free(el); - } - - /* remove any global lock created during the transaction */ - if (tdb->global_lock.count != 0) { - tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 4*tdb->header.hash_size); - tdb->global_lock.count = 0; - } - - /* remove any locks created during the transaction */ - if (tdb->num_locks != 0) { - int i; - for (i=0;inum_lockrecs;i++) { - tdb_brlock(tdb,FREELIST_TOP+4*tdb->lockrecs[i].list, - F_UNLCK,F_SETLKW, 0, 1); - } - tdb->num_locks = 0; - tdb->num_lockrecs = 0; - SAFE_FREE(tdb->lockrecs); - } - - /* restore the normal io methods */ - tdb->methods = tdb->transaction->io_methods; - - tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0); - tdb_transaction_unlock(tdb); - SAFE_FREE(tdb->transaction->hash_heads); - SAFE_FREE(tdb->transaction); - - return 0; -} - -/* - sync to disk -*/ -static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t length) -{ - if (fsync(tdb->fd) != 0) { - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n")); - return -1; - } -#if defined(HAVE_MSYNC) && defined(MS_SYNC) - if (tdb->map_ptr) { - tdb_off_t moffset = offset & ~(tdb->page_size-1); - if (msync(moffset + (char *)tdb->map_ptr, - length + (offset - moffset), MS_SYNC) != 0) { - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: msync failed - %s\n", - strerror(errno))); - return -1; - } - } -#endif - return 0; -} - - -/* - work out how much space the linearised recovery data will consume -*/ -static tdb_len_t tdb_recovery_size(struct tdb_context *tdb) -{ - struct tdb_transaction_el *el; - tdb_len_t recovery_size = 0; - - recovery_size = sizeof(u32); - for (el=tdb->transaction->elements;el;el=el->next) { - if (el->offset >= tdb->transaction->old_map_size) { - continue; - } - recovery_size += 2*sizeof(tdb_off_t) + el->length; - } - - return recovery_size; -} - -/* - allocate the recovery area, or use an existing recovery area if it is - large enough -*/ -static int tdb_recovery_allocate(struct tdb_context *tdb, - tdb_len_t *recovery_size, - tdb_off_t *recovery_offset, - tdb_len_t *recovery_max_size) -{ - struct list_struct rec; - const struct tdb_methods *methods = tdb->transaction->io_methods; - tdb_off_t recovery_head; - - if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery head\n")); - return -1; - } - - rec.rec_len = 0; - - if (recovery_head != 0 && - methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n")); - return -1; - } - - *recovery_size = tdb_recovery_size(tdb); - - if (recovery_head != 0 && *recovery_size <= rec.rec_len) { - /* it fits in the existing area */ - *recovery_max_size = rec.rec_len; - *recovery_offset = recovery_head; - return 0; - } - - /* we need to free up the old recovery area, then allocate a - new one at the end of the file. Note that we cannot use - tdb_allocate() to allocate the new one as that might return - us an area that is being currently used (as of the start of - the transaction) */ - if (recovery_head != 0) { - if (tdb_free(tdb, recovery_head, &rec) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to free previous recovery area\n")); - return -1; - } - } - - /* the tdb_free() call might have increased the recovery size */ - *recovery_size = tdb_recovery_size(tdb); - - /* round up to a multiple of page size */ - *recovery_max_size = TDB_ALIGN(sizeof(rec) + *recovery_size, tdb->page_size) - sizeof(rec); - *recovery_offset = tdb->map_size; - recovery_head = *recovery_offset; - - if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, - (tdb->map_size - tdb->transaction->old_map_size) + - sizeof(rec) + *recovery_max_size) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to create recovery area\n")); - return -1; - } - - /* remap the file (if using mmap) */ - methods->tdb_oob(tdb, tdb->map_size + 1, 1); - - /* we have to reset the old map size so that we don't try to expand the file - again in the transaction commit, which would destroy the recovery area */ - tdb->transaction->old_map_size = tdb->map_size; - - /* write the recovery header offset and sync - we can sync without a race here - as the magic ptr in the recovery record has not been set */ - CONVERT(recovery_head); - if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD, - &recovery_head, sizeof(tdb_off_t)) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to write recovery head\n")); - return -1; - } - - return 0; -} - - -/* - setup the recovery data that will be used on a crash during commit -*/ -static int transaction_setup_recovery(struct tdb_context *tdb, - tdb_off_t *magic_offset) -{ - struct tdb_transaction_el *el; - tdb_len_t recovery_size; - unsigned char *data, *p; - const struct tdb_methods *methods = tdb->transaction->io_methods; - struct list_struct *rec; - tdb_off_t recovery_offset, recovery_max_size; - tdb_off_t old_map_size = tdb->transaction->old_map_size; - u32 magic, tailer; - - /* - check that the recovery area has enough space - */ - if (tdb_recovery_allocate(tdb, &recovery_size, - &recovery_offset, &recovery_max_size) == -1) { - return -1; - } - - data = (unsigned char *)malloc(recovery_size + sizeof(*rec)); - if (data == NULL) { - tdb->ecode = TDB_ERR_OOM; - return -1; - } - - rec = (struct list_struct *)data; - memset(rec, 0, sizeof(*rec)); - - rec->magic = 0; - rec->data_len = recovery_size; - rec->rec_len = recovery_max_size; - rec->key_len = old_map_size; - CONVERT(rec); - - /* build the recovery data into a single blob to allow us to do a single - large write, which should be more efficient */ - p = data + sizeof(*rec); - for (el=tdb->transaction->elements;el;el=el->next) { - if (el->offset >= old_map_size) { - continue; - } - if (el->offset + el->length > tdb->transaction->old_map_size) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: transaction data over new region boundary\n")); - free(data); - tdb->ecode = TDB_ERR_CORRUPT; - return -1; - } - memcpy(p, &el->offset, 4); - memcpy(p+4, &el->length, 4); - if (DOCONV()) { - tdb_convert(p, 8); - } - /* the recovery area contains the old data, not the - new data, so we have to call the original tdb_read - method to get it */ - if (methods->tdb_read(tdb, el->offset, p + 8, el->length, 0) != 0) { - free(data); - tdb->ecode = TDB_ERR_IO; - return -1; - } - p += 8 + el->length; - } - - /* and the tailer */ - tailer = sizeof(*rec) + recovery_max_size; - memcpy(p, &tailer, 4); - CONVERT(p); - - /* write the recovery data to the recovery area */ - if (methods->tdb_write(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery data\n")); - free(data); - tdb->ecode = TDB_ERR_IO; - return -1; - } - - /* as we don't have ordered writes, we have to sync the recovery - data before we update the magic to indicate that the recovery - data is present */ - if (transaction_sync(tdb, recovery_offset, sizeof(*rec) + recovery_size) == -1) { - free(data); - return -1; - } - - free(data); - - magic = TDB_RECOVERY_MAGIC; - CONVERT(magic); - - *magic_offset = recovery_offset + offsetof(struct list_struct, magic); - - if (methods->tdb_write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery magic\n")); - tdb->ecode = TDB_ERR_IO; - return -1; - } - - /* ensure the recovery magic marker is on disk */ - if (transaction_sync(tdb, *magic_offset, sizeof(magic)) == -1) { - return -1; - } - - return 0; -} - -/* - commit the current transaction -*/ -int tdb_transaction_commit(struct tdb_context *tdb) -{ - const struct tdb_methods *methods; - tdb_off_t magic_offset = 0; - u32 zero = 0; - - if (tdb->transaction == NULL) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: no transaction\n")); - return -1; - } - - if (tdb->transaction->transaction_error) { - tdb->ecode = TDB_ERR_IO; - tdb_transaction_cancel(tdb); - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: transaction error pending\n")); - return -1; - } - - if (tdb->transaction->nesting != 0) { - tdb->transaction->nesting--; - return 0; - } - - /* check for a null transaction */ - if (tdb->transaction->elements == NULL) { - tdb_transaction_cancel(tdb); - return 0; - } - - methods = tdb->transaction->io_methods; - - /* if there are any locks pending then the caller has not - nested their locks properly, so fail the transaction */ - if (tdb->num_locks || tdb->global_lock.count) { - tdb->ecode = TDB_ERR_LOCK; - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: locks pending on commit\n")); - tdb_transaction_cancel(tdb); - return -1; - } - - /* upgrade the main transaction lock region to a write lock */ - if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to upgrade hash locks\n")); - tdb->ecode = TDB_ERR_LOCK; - tdb_transaction_cancel(tdb); - return -1; - } - - /* get the global lock - this prevents new users attaching to the database - during the commit */ - if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: failed to get global lock\n")); - tdb->ecode = TDB_ERR_LOCK; - tdb_transaction_cancel(tdb); - return -1; - } - - if (!(tdb->flags & TDB_NOSYNC)) { - /* write the recovery data to the end of the file */ - if (transaction_setup_recovery(tdb, &magic_offset) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to setup recovery data\n")); - tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); - tdb_transaction_cancel(tdb); - return -1; - } - } - - /* expand the file to the new size if needed */ - if (tdb->map_size != tdb->transaction->old_map_size) { - if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, - tdb->map_size - - tdb->transaction->old_map_size) == -1) { - tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: expansion failed\n")); - tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); - tdb_transaction_cancel(tdb); - return -1; - } - tdb->map_size = tdb->transaction->old_map_size; - methods->tdb_oob(tdb, tdb->map_size + 1, 1); - } - - /* perform all the writes */ - while (tdb->transaction->elements) { - struct tdb_transaction_el *el = tdb->transaction->elements; - - if (methods->tdb_write(tdb, el->offset, el->data, el->length) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n")); - - /* we've overwritten part of the data and - possibly expanded the file, so we need to - run the crash recovery code */ - tdb->methods = methods; - tdb_transaction_recover(tdb); - - tdb_transaction_cancel(tdb); - tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); - - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n")); - return -1; - } - tdb->transaction->elements = el->next; - free(el->data); - free(el); - } - - if (!(tdb->flags & TDB_NOSYNC)) { - /* ensure the new data is on disk */ - if (transaction_sync(tdb, 0, tdb->map_size) == -1) { - return -1; - } - - /* remove the recovery marker */ - if (methods->tdb_write(tdb, magic_offset, &zero, 4) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to remove recovery magic\n")); - return -1; - } - - /* ensure the recovery marker has been removed on disk */ - if (transaction_sync(tdb, magic_offset, 4) == -1) { - return -1; - } - } - - tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); - - /* - TODO: maybe write to some dummy hdr field, or write to magic - offset without mmap, before the last sync, instead of the - utime() call - */ - - /* on some systems (like Linux 2.6.x) changes via mmap/msync - don't change the mtime of the file, this means the file may - not be backed up (as tdb rounding to block sizes means that - file size changes are quite rare too). The following forces - mtime changes when a transaction completes */ -#ifdef HAVE_UTIME - utime(tdb->name, NULL); -#endif - - /* use a transaction cancel to free memory and remove the - transaction locks */ - tdb_transaction_cancel(tdb); - return 0; -} - - -/* - recover from an aborted transaction. Must be called with exclusive - database write access already established (including the global - lock to prevent new processes attaching) -*/ -int tdb_transaction_recover(struct tdb_context *tdb) -{ - tdb_off_t recovery_head, recovery_eof; - unsigned char *data, *p; - u32 zero = 0; - struct list_struct rec; - - /* find the recovery area */ - if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery head\n")); - tdb->ecode = TDB_ERR_IO; - return -1; - } - - if (recovery_head == 0) { - /* we have never allocated a recovery record */ - return 0; - } - - /* read the recovery record */ - if (tdb->methods->tdb_read(tdb, recovery_head, &rec, - sizeof(rec), DOCONV()) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery record\n")); - tdb->ecode = TDB_ERR_IO; - return -1; - } - - if (rec.magic != TDB_RECOVERY_MAGIC) { - /* there is no valid recovery data */ - return 0; - } - - if (tdb->read_only) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: attempt to recover read only database\n")); - tdb->ecode = TDB_ERR_CORRUPT; - return -1; - } - - recovery_eof = rec.key_len; - - data = (unsigned char *)malloc(rec.data_len); - if (data == NULL) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to allocate recovery data\n")); - tdb->ecode = TDB_ERR_OOM; - return -1; - } - - /* read the full recovery data */ - if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data, - rec.data_len, 0) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery data\n")); - tdb->ecode = TDB_ERR_IO; - free(data); - return -1; - } - - /* recover the file data */ - p = data; - while (p+8 < data + rec.data_len) { - u32 ofs, len; - if (DOCONV()) { - tdb_convert(p, 8); - } - memcpy(&ofs, p, 4); - memcpy(&len, p+4, 4); - - if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) { - free(data); - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to recover %d bytes at offset %d\n", len, ofs)); - tdb->ecode = TDB_ERR_IO; - return -1; - } - p += 8 + len; - } - - free(data); - - if (transaction_sync(tdb, 0, tdb->map_size) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync recovery\n")); - tdb->ecode = TDB_ERR_IO; - return -1; - } - - /* if the recovery area is after the recovered eof then remove it */ - if (recovery_eof <= recovery_head) { - if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery head\n")); - tdb->ecode = TDB_ERR_IO; - return -1; - } - } - - /* remove the recovery magic */ - if (tdb_ofs_write(tdb, recovery_head + offsetof(struct list_struct, magic), - &zero) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery magic\n")); - tdb->ecode = TDB_ERR_IO; - return -1; - } - - /* reduce the file size to the old size */ - tdb_munmap(tdb); - if (ftruncate(tdb->fd, recovery_eof) != 0) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n")); - tdb->ecode = TDB_ERR_IO; - return -1; - } - tdb->map_size = recovery_eof; - tdb_mmap(tdb); - - if (transaction_sync(tdb, 0, recovery_eof) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync2 recovery\n")); - tdb->ecode = TDB_ERR_IO; - return -1; - } - - TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_recover: recovered %d byte database\n", - recovery_eof)); - - /* all done */ - return 0; -} - -/* file: freelist.c */ - -/* read a freelist record and check for simple errors */ -static int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct *rec) -{ - if (tdb->methods->tdb_read(tdb, off, rec, sizeof(*rec),DOCONV()) == -1) - return -1; - - if (rec->magic == TDB_MAGIC) { - /* this happens when a app is showdown while deleting a record - we should - not completely fail when this happens */ - TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read non-free magic 0x%x at offset=%d - fixing\n", - rec->magic, off)); - rec->magic = TDB_FREE_MAGIC; - if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1) - return -1; - } - - if (rec->magic != TDB_FREE_MAGIC) { - /* Ensure ecode is set for log fn. */ - tdb->ecode = TDB_ERR_CORRUPT; - TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_rec_free_read bad magic 0x%x at offset=%d\n", - rec->magic, off)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); - } - if (tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0) != 0) - return -1; - return 0; -} - - - -/* Remove an element from the freelist. Must have alloc lock. */ -static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_t next) -{ - tdb_off_t last_ptr, i; - - /* read in the freelist top */ - last_ptr = FREELIST_TOP; - while (tdb_ofs_read(tdb, last_ptr, &i) != -1 && i != 0) { - if (i == off) { - /* We've found it! */ - return tdb_ofs_write(tdb, last_ptr, &next); - } - /* Follow chain (next offset is at start of record) */ - last_ptr = i; - } - TDB_LOG((tdb, TDB_DEBUG_FATAL,"remove_from_freelist: not on list at off=%d\n", off)); - return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); -} - - -/* update a record tailer (must hold allocation lock) */ -static int update_tailer(struct tdb_context *tdb, tdb_off_t offset, - const struct list_struct *rec) -{ - tdb_off_t totalsize; - - /* Offset of tailer from record header */ - totalsize = sizeof(*rec) + rec->rec_len; - return tdb_ofs_write(tdb, offset + totalsize - sizeof(tdb_off_t), - &totalsize); -} - -/* Add an element into the freelist. Merge adjacent records if - necessary. */ -int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) -{ - tdb_off_t right, left; - - /* Allocation and tailer lock */ - if (tdb_lock(tdb, -1, F_WRLCK) != 0) - return -1; - - /* set an initial tailer, so if we fail we don't leave a bogus record */ - if (update_tailer(tdb, offset, rec) != 0) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed!\n")); - goto fail; - } - - /* Look right first (I'm an Australian, dammit) */ - right = offset + sizeof(*rec) + rec->rec_len; - if (right + sizeof(*rec) <= tdb->map_size) { - struct list_struct r; - - if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right read failed at %u\n", right)); - goto left; - } - - /* If it's free, expand to include it. */ - if (r.magic == TDB_FREE_MAGIC) { - if (remove_from_freelist(tdb, right, r.next) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right free failed at %u\n", right)); - goto left; - } - rec->rec_len += sizeof(r) + r.rec_len; - } - } - -left: - /* Look left */ - left = offset - sizeof(tdb_off_t); - if (left > TDB_DATA_START(tdb->header.hash_size)) { - struct list_struct l; - tdb_off_t leftsize; - - /* Read in tailer and jump back to header */ - if (tdb_ofs_read(tdb, left, &leftsize) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left offset read failed at %u\n", left)); - goto update; - } - - /* it could be uninitialised data */ - if (leftsize == 0 || leftsize == TDB_PAD_U32) { - goto update; - } - - left = offset - leftsize; - - /* Now read in record */ - if (tdb->methods->tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); - goto update; - } - - /* If it's free, expand to include it. */ - if (l.magic == TDB_FREE_MAGIC) { - if (remove_from_freelist(tdb, left, l.next) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left free failed at %u\n", left)); - goto update; - } else { - offset = left; - rec->rec_len += leftsize; - } - } - } - -update: - if (update_tailer(tdb, offset, rec) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset)); - goto fail; - } - - /* Now, prepend to free list */ - rec->magic = TDB_FREE_MAGIC; - - if (tdb_ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || - tdb_rec_write(tdb, offset, rec) == -1 || - tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free record write failed at offset=%d\n", offset)); - goto fail; - } - - /* And we're done. */ - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return -1; -} - - -/* - the core of tdb_allocate - called when we have decided which - free list entry to use - */ -static tdb_off_t tdb_allocate_ofs(struct tdb_context *tdb, tdb_len_t length, tdb_off_t rec_ptr, - struct list_struct *rec, tdb_off_t last_ptr) -{ - struct list_struct newrec; - tdb_off_t newrec_ptr; - - memset(&newrec, '\0', sizeof(newrec)); - - /* found it - now possibly split it up */ - if (rec->rec_len > length + MIN_REC_SIZE) { - /* Length of left piece */ - length = TDB_ALIGN(length, TDB_ALIGNMENT); - - /* Right piece to go on free list */ - newrec.rec_len = rec->rec_len - (sizeof(*rec) + length); - newrec_ptr = rec_ptr + sizeof(*rec) + length; - - /* And left record is shortened */ - rec->rec_len = length; - } else { - newrec_ptr = 0; - } - - /* Remove allocated record from the free list */ - if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) { - return 0; - } - - /* Update header: do this before we drop alloc - lock, otherwise tdb_free() might try to - merge with us, thinking we're free. - (Thanks Jeremy Allison). */ - rec->magic = TDB_MAGIC; - if (tdb_rec_write(tdb, rec_ptr, rec) == -1) { - return 0; - } - - /* Did we create new block? */ - if (newrec_ptr) { - /* Update allocated record tailer (we - shortened it). */ - if (update_tailer(tdb, rec_ptr, rec) == -1) { - return 0; - } - - /* Free new record */ - if (tdb_free(tdb, newrec_ptr, &newrec) == -1) { - return 0; - } - } - - /* all done - return the new record offset */ - return rec_ptr; -} - -/* allocate some space from the free list. The offset returned points - to a unconnected list_struct within the database with room for at - least length bytes of total data - - 0 is returned if the space could not be allocated - */ -tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_struct *rec) -{ - tdb_off_t rec_ptr, last_ptr, newrec_ptr; - struct { - tdb_off_t rec_ptr, last_ptr; - tdb_len_t rec_len; - } bestfit; - - if (tdb_lock(tdb, -1, F_WRLCK) == -1) - return 0; - - /* Extra bytes required for tailer */ - length += sizeof(tdb_off_t); - - again: - last_ptr = FREELIST_TOP; - - /* read in the freelist top */ - if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) - goto fail; - - bestfit.rec_ptr = 0; - bestfit.last_ptr = 0; - bestfit.rec_len = 0; - - /* - this is a best fit allocation strategy. Originally we used - a first fit strategy, but it suffered from massive fragmentation - issues when faced with a slowly increasing record size. - */ - while (rec_ptr) { - if (tdb_rec_free_read(tdb, rec_ptr, rec) == -1) { - goto fail; - } - - if (rec->rec_len >= length) { - if (bestfit.rec_ptr == 0 || - rec->rec_len < bestfit.rec_len) { - bestfit.rec_len = rec->rec_len; - bestfit.rec_ptr = rec_ptr; - bestfit.last_ptr = last_ptr; - /* consider a fit to be good enough if - we aren't wasting more than half - the space */ - if (bestfit.rec_len < 2*length) { - break; - } - } - } - - /* move to the next record */ - last_ptr = rec_ptr; - rec_ptr = rec->next; - } - - if (bestfit.rec_ptr != 0) { - if (tdb_rec_free_read(tdb, bestfit.rec_ptr, rec) == -1) { - goto fail; - } - - newrec_ptr = tdb_allocate_ofs(tdb, length, bestfit.rec_ptr, rec, bestfit.last_ptr); - tdb_unlock(tdb, -1, F_WRLCK); - return newrec_ptr; - } - - /* we didn't find enough space. See if we can expand the - database and if we can then try again */ - if (tdb_expand(tdb, length + sizeof(*rec)) == 0) - goto again; - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return 0; -} - -/* file: freelistcheck.c */ - -/* Check the freelist is good and contains no loops. - Very memory intensive - only do this as a consistency - checker. Heh heh - uses an in memory tdb as the storage - for the "seen" record list. For some reason this strikes - me as extremely clever as I don't have to write another tree - data structure implementation :-). - */ - -static int seen_insert(struct tdb_context *mem_tdb, tdb_off_t rec_ptr) -{ - TDB_DATA key, data; - - memset(&data, '\0', sizeof(data)); - key.dptr = (unsigned char *)&rec_ptr; - key.dsize = sizeof(rec_ptr); - return tdb_store(mem_tdb, key, data, TDB_INSERT); -} - -int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries) -{ - struct tdb_context *mem_tdb = NULL; - struct list_struct rec; - tdb_off_t rec_ptr, last_ptr; - int ret = -1; - - *pnum_entries = 0; - - mem_tdb = tdb_open("flval", tdb->header.hash_size, - TDB_INTERNAL, O_RDWR, 0600); - if (!mem_tdb) { - return -1; - } - - if (tdb_lock(tdb, -1, F_WRLCK) == -1) { - tdb_close(mem_tdb); - return 0; - } - - last_ptr = FREELIST_TOP; - - /* Store the FREELIST_TOP record. */ - if (seen_insert(mem_tdb, last_ptr) == -1) { - ret = TDB_ERRCODE(TDB_ERR_CORRUPT, -1); - goto fail; - } - - /* read in the freelist top */ - if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1) { - goto fail; - } - - while (rec_ptr) { - - /* If we can't store this record (we've seen it - before) then the free list has a loop and must - be corrupt. */ - - if (seen_insert(mem_tdb, rec_ptr)) { - ret = TDB_ERRCODE(TDB_ERR_CORRUPT, -1); - goto fail; - } - - if (tdb_rec_free_read(tdb, rec_ptr, &rec) == -1) { - goto fail; - } - - /* move to the next record */ - last_ptr = rec_ptr; - rec_ptr = rec.next; - *pnum_entries += 1; - } - - ret = 0; - - fail: - - tdb_close(mem_tdb); - tdb_unlock(tdb, -1, F_WRLCK); - return ret; -} - -/* file: traverse.c */ - -/* Uses traverse lock: 0 = finish, -1 = error, other = record offset */ -static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tlock, - struct list_struct *rec) -{ - int want_next = (tlock->off != 0); - - /* Lock each chain from the start one. */ - for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { - if (!tlock->off && tlock->hash != 0) { - /* this is an optimisation for the common case where - the hash chain is empty, which is particularly - common for the use of tdb with ldb, where large - hashes are used. In that case we spend most of our - time in tdb_brlock(), locking empty hash chains. - - To avoid this, we do an unlocked pre-check to see - if the hash chain is empty before starting to look - inside it. If it is empty then we can avoid that - hash chain. If it isn't empty then we can't believe - the value we get back, as we read it without a - lock, so instead we get the lock and re-fetch the - value below. - - Notice that not doing this optimisation on the - first hash chain is critical. We must guarantee - that we have done at least one fcntl lock at the - start of a search to guarantee that memory is - coherent on SMP systems. If records are added by - others during the search then that's OK, and we - could possibly miss those with this trick, but we - could miss them anyway without this trick, so the - semantics don't change. - - With a non-indexed ldb search this trick gains us a - factor of around 80 in speed on a linux 2.6.x - system (testing using ldbtest). - */ - tdb->methods->next_hash_chain(tdb, &tlock->hash); - if (tlock->hash == tdb->header.hash_size) { - continue; - } - } - - if (tdb_lock(tdb, tlock->hash, tlock->lock_rw) == -1) - return -1; - - /* No previous record? Start at top of chain. */ - if (!tlock->off) { - if (tdb_ofs_read(tdb, TDB_HASH_TOP(tlock->hash), - &tlock->off) == -1) - goto fail; - } else { - /* Otherwise unlock the previous record. */ - if (tdb_unlock_record(tdb, tlock->off) != 0) - goto fail; - } - - if (want_next) { - /* We have offset of old record: grab next */ - if (tdb_rec_read(tdb, tlock->off, rec) == -1) - goto fail; - tlock->off = rec->next; - } - - /* Iterate through chain */ - while( tlock->off) { - tdb_off_t current; - if (tdb_rec_read(tdb, tlock->off, rec) == -1) - goto fail; - - /* Detect infinite loops. From "Shlomi Yaakobovich" . */ - if (tlock->off == rec->next) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: loop detected.\n")); - goto fail; - } - - if (!TDB_DEAD(rec)) { - /* Woohoo: we found one! */ - if (tdb_lock_record(tdb, tlock->off) != 0) - goto fail; - return tlock->off; - } - - /* Try to clean dead ones from old traverses */ - current = tlock->off; - tlock->off = rec->next; - if (!(tdb->read_only || tdb->traverse_read) && - tdb_do_delete(tdb, current, rec) != 0) - goto fail; - } - tdb_unlock(tdb, tlock->hash, tlock->lock_rw); - want_next = 0; - } - /* We finished iteration without finding anything */ - return TDB_ERRCODE(TDB_SUCCESS, 0); - - fail: - tlock->off = 0; - if (tdb_unlock(tdb, tlock->hash, tlock->lock_rw) != 0) - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: On error unlock failed!\n")); - return -1; -} - -/* traverse the entire database - calling fn(tdb, key, data) on each element. - return -1 on error or the record count traversed - if fn is NULL then it is not called - a non-zero return value from fn() indicates that the traversal should stop - */ -static int tdb_traverse_internal(struct tdb_context *tdb, - tdb_traverse_func fn, void *private_data, - struct tdb_traverse_lock *tl) -{ - TDB_DATA key, dbuf; - struct list_struct rec; - int ret, count = 0; - - /* This was in the initialization, above, but the IRIX compiler - * did not like it. crh - */ - tl->next = tdb->travlocks.next; - - /* fcntl locks don't stack: beware traverse inside traverse */ - tdb->travlocks.next = tl; - - /* tdb_next_lock places locks on the record returned, and its chain */ - while ((ret = tdb_next_lock(tdb, tl, &rec)) > 0) { - count++; - /* now read the full record */ - key.dptr = tdb_alloc_read(tdb, tl->off + sizeof(rec), - rec.key_len + rec.data_len); - if (!key.dptr) { - ret = -1; - if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) - goto out; - if (tdb_unlock_record(tdb, tl->off) != 0) - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); - goto out; - } - key.dsize = rec.key_len; - dbuf.dptr = key.dptr + rec.key_len; - dbuf.dsize = rec.data_len; - - /* Drop chain lock, call out */ - if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) { - ret = -1; - SAFE_FREE(key.dptr); - goto out; - } - if (fn && fn(tdb, key, dbuf, private_data)) { - /* They want us to terminate traversal */ - ret = count; - if (tdb_unlock_record(tdb, tl->off) != 0) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: unlock_record failed!\n"));; - ret = -1; - } - SAFE_FREE(key.dptr); - goto out; - } - SAFE_FREE(key.dptr); - } -out: - tdb->travlocks.next = tl->next; - if (ret < 0) - return -1; - else - return count; -} - - -/* - a write style traverse - temporarily marks the db read only -*/ -int tdb_traverse_read(struct tdb_context *tdb, - tdb_traverse_func fn, void *private_data) -{ - struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK }; - int ret; - - /* we need to get a read lock on the transaction lock here to - cope with the lock ordering semantics of solaris10 */ - if (tdb_transaction_lock(tdb, F_RDLCK)) { - return -1; - } - - tdb->traverse_read++; - ret = tdb_traverse_internal(tdb, fn, private_data, &tl); - tdb->traverse_read--; - - tdb_transaction_unlock(tdb); - - return ret; -} - -/* - a write style traverse - needs to get the transaction lock to - prevent deadlocks -*/ -int tdb_traverse(struct tdb_context *tdb, - tdb_traverse_func fn, void *private_data) -{ - struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK }; - int ret; - - if (tdb->read_only || tdb->traverse_read) { - return tdb_traverse_read(tdb, fn, private_data); - } - - if (tdb_transaction_lock(tdb, F_WRLCK)) { - return -1; - } - - ret = tdb_traverse_internal(tdb, fn, private_data, &tl); - - tdb_transaction_unlock(tdb); - - return ret; -} - - -/* find the first entry in the database and return its key */ -TDB_DATA tdb_firstkey(struct tdb_context *tdb) -{ - TDB_DATA key; - struct list_struct rec; - - /* release any old lock */ - if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) - return tdb_null; - tdb->travlocks.off = tdb->travlocks.hash = 0; - tdb->travlocks.lock_rw = F_RDLCK; - - /* Grab first record: locks chain and returned record. */ - if (tdb_next_lock(tdb, &tdb->travlocks, &rec) <= 0) - return tdb_null; - /* now read the key */ - key.dsize = rec.key_len; - key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); - - /* Unlock the hash chain of the record we just read. */ - if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_firstkey: error occurred while tdb_unlocking!\n")); - return key; -} - -/* find the next entry in the database, returning its key */ -TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey) -{ - u32 oldhash; - TDB_DATA key = tdb_null; - struct list_struct rec; - unsigned char *k = NULL; - - /* Is locked key the old key? If so, traverse will be reliable. */ - if (tdb->travlocks.off) { - if (tdb_lock(tdb,tdb->travlocks.hash,tdb->travlocks.lock_rw)) - return tdb_null; - if (tdb_rec_read(tdb, tdb->travlocks.off, &rec) == -1 - || !(k = tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec), - rec.key_len)) - || memcmp(k, oldkey.dptr, oldkey.dsize) != 0) { - /* No, it wasn't: unlock it and start from scratch */ - if (tdb_unlock_record(tdb, tdb->travlocks.off) != 0) { - SAFE_FREE(k); - return tdb_null; - } - if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) { - SAFE_FREE(k); - return tdb_null; - } - tdb->travlocks.off = 0; - } - - SAFE_FREE(k); - } - - if (!tdb->travlocks.off) { - /* No previous element: do normal find, and lock record */ - tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), tdb->travlocks.lock_rw, &rec); - if (!tdb->travlocks.off) - return tdb_null; - tdb->travlocks.hash = BUCKET(rec.full_hash); - if (tdb_lock_record(tdb, tdb->travlocks.off) != 0) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); - return tdb_null; - } - } - oldhash = tdb->travlocks.hash; - - /* Grab next record: locks chain and returned record, - unlocks old record */ - if (tdb_next_lock(tdb, &tdb->travlocks, &rec) > 0) { - key.dsize = rec.key_len; - key.dptr = tdb_alloc_read(tdb, tdb->travlocks.off+sizeof(rec), - key.dsize); - /* Unlock the chain of this new record */ - if (tdb_unlock(tdb, tdb->travlocks.hash, tdb->travlocks.lock_rw) != 0) - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); - } - /* Unlock the chain of old record */ - if (tdb_unlock(tdb, BUCKET(oldhash), tdb->travlocks.lock_rw) != 0) - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); - return key; -} - -/* file: dump.c */ - -static tdb_off_t tdb_dump_record(struct tdb_context *tdb, int hash, - tdb_off_t offset) -{ - struct list_struct rec; - tdb_off_t tailer_ofs, tailer; - - if (tdb->methods->tdb_read(tdb, offset, (char *)&rec, - sizeof(rec), DOCONV()) == -1) { - printf("ERROR: failed to read record at %u\n", offset); - return 0; - } - - printf(" rec: hash=%d offset=0x%08x next=0x%08x rec_len=%d " - "key_len=%d data_len=%d full_hash=0x%x magic=0x%x\n", - hash, offset, rec.next, rec.rec_len, rec.key_len, rec.data_len, - rec.full_hash, rec.magic); - - tailer_ofs = offset + sizeof(rec) + rec.rec_len - sizeof(tdb_off_t); - - if (tdb_ofs_read(tdb, tailer_ofs, &tailer) == -1) { - printf("ERROR: failed to read tailer at %u\n", tailer_ofs); - return rec.next; - } - - if (tailer != rec.rec_len + sizeof(rec)) { - printf("ERROR: tailer does not match record! tailer=%u totalsize=%u\n", - (unsigned int)tailer, (unsigned int)(rec.rec_len + sizeof(rec))); - } - return rec.next; -} - -static int tdb_dump_chain(struct tdb_context *tdb, int i) -{ - tdb_off_t rec_ptr, top; - - top = TDB_HASH_TOP(i); - - if (tdb_lock(tdb, i, F_WRLCK) != 0) - return -1; - - if (tdb_ofs_read(tdb, top, &rec_ptr) == -1) - return tdb_unlock(tdb, i, F_WRLCK); - - if (rec_ptr) - printf("hash=%d\n", i); - - while (rec_ptr) { - rec_ptr = tdb_dump_record(tdb, i, rec_ptr); - } - - return tdb_unlock(tdb, i, F_WRLCK); -} - -void tdb_dump_all(struct tdb_context *tdb) -{ - int i; - for (i = 0; i < (int)tdb->header.hash_size; i++) { - tdb_dump_chain(tdb, i); - } - printf("freelist:\n"); - tdb_dump_chain(tdb, -1); -} - -int tdb_printfreelist(struct tdb_context *tdb) -{ - int ret; - long total_free = 0; - tdb_off_t offset, rec_ptr; - struct list_struct rec; - - if ((ret = tdb_lock(tdb, -1, F_WRLCK)) != 0) - return ret; - - offset = FREELIST_TOP; - - /* read in the freelist top */ - if (tdb_ofs_read(tdb, offset, &rec_ptr) == -1) { - tdb_unlock(tdb, -1, F_WRLCK); - return 0; - } - - printf("freelist top=[0x%08x]\n", rec_ptr ); - while (rec_ptr) { - if (tdb->methods->tdb_read(tdb, rec_ptr, (char *)&rec, - sizeof(rec), DOCONV()) == -1) { - tdb_unlock(tdb, -1, F_WRLCK); - return -1; - } - - if (rec.magic != TDB_FREE_MAGIC) { - printf("bad magic 0x%08x in free list\n", rec.magic); - tdb_unlock(tdb, -1, F_WRLCK); - return -1; - } - - printf("entry offset=[0x%08x], rec.rec_len = [0x%08x (%d)] (end = 0x%08x)\n", - rec_ptr, rec.rec_len, rec.rec_len, rec_ptr + rec.rec_len); - total_free += rec.rec_len; - - /* move to the next record */ - rec_ptr = rec.next; - } - printf("total rec_len = [0x%08x (%d)]\n", (int)total_free, - (int)total_free); - - return tdb_unlock(tdb, -1, F_WRLCK); -} - -/* file: tdb.c */ - -/* - non-blocking increment of the tdb sequence number if the tdb has been opened using - the TDB_SEQNUM flag -*/ -void tdb_increment_seqnum_nonblock(struct tdb_context *tdb) -{ - tdb_off_t seqnum=0; - - if (!(tdb->flags & TDB_SEQNUM)) { - return; - } - - /* we ignore errors from this, as we have no sane way of - dealing with them. - */ - if (tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum) == -1) - return; - seqnum++; - (void) tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum); -} - -/* - increment the tdb sequence number if the tdb has been opened using - the TDB_SEQNUM flag -*/ -static void tdb_increment_seqnum(struct tdb_context *tdb) -{ - if (!(tdb->flags & TDB_SEQNUM)) { - return; - } - - if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) { - return; - } - - tdb_increment_seqnum_nonblock(tdb); - - tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1); -} - -static int tdb_key_compare(TDB_DATA key, TDB_DATA data, - void *private_data EXT2FS_ATTR((unused))) -{ - return memcmp(data.dptr, key.dptr, data.dsize); -} - -/* Returns 0 on fail. On success, return offset of record, and fills - in rec */ -static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, u32 hash, - struct list_struct *r) -{ - tdb_off_t rec_ptr; - - /* read in the hash top */ - if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) - return 0; - - /* keep looking until we find the right record */ - while (rec_ptr) { - if (tdb_rec_read(tdb, rec_ptr, r) == -1) - return 0; - - if (!TDB_DEAD(r) && hash==r->full_hash - && key.dsize==r->key_len - && tdb_parse_data(tdb, key, rec_ptr + sizeof(*r), - r->key_len, tdb_key_compare, - NULL) == 0) { - return rec_ptr; - } - rec_ptr = r->next; - } - return TDB_ERRCODE(TDB_ERR_NOEXIST, 0); -} - -/* As tdb_find, but if you succeed, keep the lock */ -tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, int locktype, - struct list_struct *rec) -{ - u32 rec_ptr; - - if (tdb_lock(tdb, BUCKET(hash), locktype) == -1) - return 0; - if (!(rec_ptr = tdb_find(tdb, key, hash, rec))) - tdb_unlock(tdb, BUCKET(hash), locktype); - return rec_ptr; -} - - -/* update an entry in place - this only works if the new data size - is <= the old data size and the key exists. - on failure return -1. -*/ -static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf) -{ - struct list_struct rec; - tdb_off_t rec_ptr; - - /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) - return -1; - - /* must be long enough key, data and tailer */ - if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off_t)) { - tdb->ecode = TDB_SUCCESS; /* Not really an error */ - return -1; - } - - if (tdb->methods->tdb_write(tdb, rec_ptr + sizeof(rec) + rec.key_len, - dbuf.dptr, dbuf.dsize) == -1) - return -1; - - if (dbuf.dsize != rec.data_len) { - /* update size */ - rec.data_len = dbuf.dsize; - return tdb_rec_write(tdb, rec_ptr, &rec); - } - - return 0; -} - -/* find an entry in the database given a key */ -/* If an entry doesn't exist tdb_err will be set to - * TDB_ERR_NOEXIST. If a key has no data attached - * then the TDB_DATA will have zero length but - * a non-zero pointer - */ -TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key) -{ - tdb_off_t rec_ptr; - struct list_struct rec; - TDB_DATA ret; - u32 hash; - - /* find which hash bucket it is in */ - hash = tdb->hash_fn(&key); - if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) - return tdb_null; - - ret.dptr = tdb_alloc_read(tdb, rec_ptr + sizeof(rec) + rec.key_len, - rec.data_len); - ret.dsize = rec.data_len; - tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); - return ret; -} - -/* - * Find an entry in the database and hand the record's data to a parsing - * function. The parsing function is executed under the chain read lock, so it - * should be fast and should not block on other syscalls. - * - * DONT CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS. - * - * For mmapped tdb's that do not have a transaction open it points the parsing - * function directly at the mmap area, it avoids the malloc/memcpy in this - * case. If a transaction is open or no mmap is available, it has to do - * malloc/read/parse/free. - * - * This is interesting for all readers of potentially large data structures in - * the tdb records, ldb indexes being one example. - */ - -int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key, - int (*parser)(TDB_DATA key, TDB_DATA data, - void *private_data), - void *private_data) -{ - tdb_off_t rec_ptr; - struct list_struct rec; - int ret; - u32 hash; - - /* find which hash bucket it is in */ - hash = tdb->hash_fn(&key); - - if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) { - return TDB_ERRCODE(TDB_ERR_NOEXIST, 0); - } - - ret = tdb_parse_data(tdb, key, rec_ptr + sizeof(rec) + rec.key_len, - rec.data_len, parser, private_data); - - tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); - - return ret; -} - -/* check if an entry in the database exists - - note that 1 is returned if the key is found and 0 is returned if not found - this doesn't match the conventions in the rest of this module, but is - compatible with gdbm -*/ -static int tdb_exists_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash) -{ - struct list_struct rec; - - if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0) - return 0; - tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); - return 1; -} - -int tdb_exists(struct tdb_context *tdb, TDB_DATA key) -{ - u32 hash = tdb->hash_fn(&key); - return tdb_exists_hash(tdb, key, hash); -} - -/* actually delete an entry in the database given the offset */ -int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct*rec) -{ - tdb_off_t last_ptr, i; - struct list_struct lastrec; - - if (tdb->read_only || tdb->traverse_read) return -1; - - if (tdb_write_lock_record(tdb, rec_ptr) == -1) { - /* Someone traversing here: mark it as dead */ - rec->magic = TDB_DEAD_MAGIC; - return tdb_rec_write(tdb, rec_ptr, rec); - } - if (tdb_write_unlock_record(tdb, rec_ptr) != 0) - return -1; - - /* find previous record in hash chain */ - if (tdb_ofs_read(tdb, TDB_HASH_TOP(rec->full_hash), &i) == -1) - return -1; - for (last_ptr = 0; i != rec_ptr; last_ptr = i, i = lastrec.next) - if (tdb_rec_read(tdb, i, &lastrec) == -1) - return -1; - - /* unlink it: next ptr is at start of record. */ - if (last_ptr == 0) - last_ptr = TDB_HASH_TOP(rec->full_hash); - if (tdb_ofs_write(tdb, last_ptr, &rec->next) == -1) - return -1; - - /* recover the space */ - if (tdb_free(tdb, rec_ptr, rec) == -1) - return -1; - return 0; -} - -static int tdb_count_dead(struct tdb_context *tdb, u32 hash) -{ - int res = 0; - tdb_off_t rec_ptr; - struct list_struct rec; - - /* read in the hash top */ - if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) - return 0; - - while (rec_ptr) { - if (tdb_rec_read(tdb, rec_ptr, &rec) == -1) - return 0; - - if (rec.magic == TDB_DEAD_MAGIC) { - res += 1; - } - rec_ptr = rec.next; - } - return res; -} - -/* - * Purge all DEAD records from a hash chain - */ -static int tdb_purge_dead(struct tdb_context *tdb, u32 hash) -{ - int res = -1; - struct list_struct rec; - tdb_off_t rec_ptr; - - if (tdb_lock(tdb, -1, F_WRLCK) == -1) { - return -1; - } - - /* read in the hash top */ - if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) - goto fail; - - while (rec_ptr) { - tdb_off_t next; - - if (tdb_rec_read(tdb, rec_ptr, &rec) == -1) { - goto fail; - } - - next = rec.next; - - if (rec.magic == TDB_DEAD_MAGIC - && tdb_do_delete(tdb, rec_ptr, &rec) == -1) { - goto fail; - } - rec_ptr = next; - } - res = 0; - fail: - tdb_unlock(tdb, -1, F_WRLCK); - return res; -} - -/* delete an entry in the database given a key */ -static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash) -{ - tdb_off_t rec_ptr; - struct list_struct rec; - int ret; - - if (tdb->max_dead_records != 0) { - - /* - * Allow for some dead records per hash chain, mainly for - * tdb's with a very high create/delete rate like locking.tdb. - */ - - if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) - return -1; - - if (tdb_count_dead(tdb, hash) >= tdb->max_dead_records) { - /* - * Don't let the per-chain freelist grow too large, - * delete all existing dead records - */ - tdb_purge_dead(tdb, hash); - } - - if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) { - tdb_unlock(tdb, BUCKET(hash), F_WRLCK); - return -1; - } - - /* - * Just mark the record as dead. - */ - rec.magic = TDB_DEAD_MAGIC; - ret = tdb_rec_write(tdb, rec_ptr, &rec); - } - else { - if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, - &rec))) - return -1; - - ret = tdb_do_delete(tdb, rec_ptr, &rec); - } - - if (ret == 0) { - tdb_increment_seqnum(tdb); - } - - if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) - TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_delete: WARNING tdb_unlock failed!\n")); - return ret; -} - -int tdb_delete(struct tdb_context *tdb, TDB_DATA key) -{ - u32 hash = tdb->hash_fn(&key); - return tdb_delete_hash(tdb, key, hash); -} - -/* - * See if we have a dead record around with enough space - */ -static tdb_off_t tdb_find_dead(struct tdb_context *tdb, u32 hash, - struct list_struct *r, tdb_len_t length) -{ - tdb_off_t rec_ptr; - - /* read in the hash top */ - if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) - return 0; - - /* keep looking until we find the right record */ - while (rec_ptr) { - if (tdb_rec_read(tdb, rec_ptr, r) == -1) - return 0; - - if (TDB_DEAD(r) && r->rec_len >= length) { - /* - * First fit for simple coding, TODO: change to best - * fit - */ - return rec_ptr; - } - rec_ptr = r->next; - } - return 0; -} - -/* store an element in the database, replacing any existing element - with the same key - - return 0 on success, -1 on failure -*/ -int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) -{ - struct list_struct rec; - u32 hash; - tdb_off_t rec_ptr; - char *p = NULL; - int ret = -1; - - if (tdb->read_only || tdb->traverse_read) { - tdb->ecode = TDB_ERR_RDONLY; - return -1; - } - - /* find which hash bucket it is in */ - hash = tdb->hash_fn(&key); - if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) - return -1; - - /* check for it existing, on insert. */ - if (flag == TDB_INSERT) { - if (tdb_exists_hash(tdb, key, hash)) { - tdb->ecode = TDB_ERR_EXISTS; - goto fail; - } - } else { - /* first try in-place update, on modify or replace. */ - if (tdb_update_hash(tdb, key, hash, dbuf) == 0) { - goto done; - } - if (tdb->ecode == TDB_ERR_NOEXIST && - flag == TDB_MODIFY) { - /* if the record doesn't exist and we are in TDB_MODIFY mode then - we should fail the store */ - goto fail; - } - } - /* reset the error code potentially set by the tdb_update() */ - tdb->ecode = TDB_SUCCESS; - - /* delete any existing record - if it doesn't exist we don't - care. Doing this first reduces fragmentation, and avoids - coalescing with `allocated' block before it's updated. */ - if (flag != TDB_INSERT) - tdb_delete_hash(tdb, key, hash); - - /* Copy key+value *before* allocating free space in case malloc - fails and we are left with a dead spot in the tdb. */ - - if (!(p = (char *)malloc(key.dsize + dbuf.dsize))) { - tdb->ecode = TDB_ERR_OOM; - goto fail; - } - - memcpy(p, key.dptr, key.dsize); - if (dbuf.dsize) - memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize); - - if (tdb->max_dead_records != 0) { - /* - * Allow for some dead records per hash chain, look if we can - * find one that can hold the new record. We need enough space - * for key, data and tailer. If we find one, we don't have to - * consult the central freelist. - */ - rec_ptr = tdb_find_dead( - tdb, hash, &rec, - key.dsize + dbuf.dsize + sizeof(tdb_off_t)); - - if (rec_ptr != 0) { - rec.key_len = key.dsize; - rec.data_len = dbuf.dsize; - rec.full_hash = hash; - rec.magic = TDB_MAGIC; - if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 - || tdb->methods->tdb_write( - tdb, rec_ptr + sizeof(rec), - p, key.dsize + dbuf.dsize) == -1) { - goto fail; - } - goto done; - } - } - - /* - * We have to allocate some space from the freelist, so this means we - * have to lock it. Use the chance to purge all the DEAD records from - * the hash chain under the freelist lock. - */ - - if (tdb_lock(tdb, -1, F_WRLCK) == -1) { - goto fail; - } - - if ((tdb->max_dead_records != 0) - && (tdb_purge_dead(tdb, hash) == -1)) { - tdb_unlock(tdb, -1, F_WRLCK); - goto fail; - } - - /* we have to allocate some space */ - rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec); - - tdb_unlock(tdb, -1, F_WRLCK); - - if (rec_ptr == 0) { - goto fail; - } - - /* Read hash top into next ptr */ - if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1) - goto fail; - - rec.key_len = key.dsize; - rec.data_len = dbuf.dsize; - rec.full_hash = hash; - rec.magic = TDB_MAGIC; - - /* write out and point the top of the hash chain at it */ - if (tdb_rec_write(tdb, rec_ptr, &rec) == -1 - || tdb->methods->tdb_write(tdb, rec_ptr+sizeof(rec), p, key.dsize+dbuf.dsize)==-1 - || tdb_ofs_write(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) { - /* Need to tdb_unallocate() here */ - goto fail; - } - - done: - ret = 0; - fail: - if (ret == 0) { - tdb_increment_seqnum(tdb); - } - - SAFE_FREE(p); - tdb_unlock(tdb, BUCKET(hash), F_WRLCK); - return ret; -} - - -/* Append to an entry. Create if not exist. */ -int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf) -{ - u32 hash; - TDB_DATA dbuf; - int ret = -1; - - /* find which hash bucket it is in */ - hash = tdb->hash_fn(&key); - if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1) - return -1; - - dbuf = tdb_fetch(tdb, key); - - if (dbuf.dptr == NULL) { - dbuf.dptr = (unsigned char *)malloc(new_dbuf.dsize); - } else { - unsigned char *new_dptr = (unsigned char *)realloc(dbuf.dptr, - dbuf.dsize + new_dbuf.dsize); - if (new_dptr == NULL) { - free(dbuf.dptr); - } - dbuf.dptr = new_dptr; - } - - if (dbuf.dptr == NULL) { - tdb->ecode = TDB_ERR_OOM; - goto failed; - } - - memcpy(dbuf.dptr + dbuf.dsize, new_dbuf.dptr, new_dbuf.dsize); - dbuf.dsize += new_dbuf.dsize; - - ret = tdb_store(tdb, key, dbuf, 0); - -failed: - tdb_unlock(tdb, BUCKET(hash), F_WRLCK); - SAFE_FREE(dbuf.dptr); - return ret; -} - - -/* - return the name of the current tdb file - useful for external logging functions -*/ -const char *tdb_name(struct tdb_context *tdb) -{ - return tdb->name; -} - -/* - return the underlying file descriptor being used by tdb, or -1 - useful for external routines that want to check the device/inode - of the fd -*/ -int tdb_fd(struct tdb_context *tdb) -{ - return tdb->fd; -} - -/* - return the current logging function - useful for external tdb routines that wish to log tdb errors -*/ -tdb_log_func tdb_log_fn(struct tdb_context *tdb) -{ - return tdb->log.log_fn; -} - - -/* - get the tdb sequence number. Only makes sense if the writers opened - with TDB_SEQNUM set. Note that this sequence number will wrap quite - quickly, so it should only be used for a 'has something changed' - test, not for code that relies on the count of the number of changes - made. If you want a counter then use a tdb record. - - The aim of this sequence number is to allow for a very lightweight - test of a possible tdb change. -*/ -int tdb_get_seqnum(struct tdb_context *tdb) -{ - tdb_off_t seqnum=0; - - if (tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum) == -1) - return 0; - return seqnum; -} - -int tdb_hash_size(struct tdb_context *tdb) -{ - return tdb->header.hash_size; -} - -size_t tdb_map_size(struct tdb_context *tdb) -{ - return tdb->map_size; -} - -int tdb_get_flags(struct tdb_context *tdb) -{ - return tdb->flags; -} - - -/* - enable sequence number handling on an open tdb -*/ -void tdb_enable_seqnum(struct tdb_context *tdb) -{ - tdb->flags |= TDB_SEQNUM; -} - -/* file: open.c */ - -/* all contexts, to ensure no double-opens (fcntl locks don't nest!) */ -static struct tdb_context *tdbs = NULL; - - -/* This is from a hash algorithm suggested by Rogier Wolff */ -static unsigned int default_tdb_hash(TDB_DATA *key) -{ - u32 value; /* Used to compute the hash value. */ - u32 i; /* Used to cycle through random values. */ - - /* Set the initial value from the key size. */ - for (value = 0, i=0; i < key->dsize; i++) - value = value * 256 + key->dptr[i] + (value >> 24) * 241; - - return value; -} - - -/* initialise a new database with a specified hash size */ -static int tdb_new_database(struct tdb_context *tdb, int hash_size) -{ - struct tdb_header *newdb; - int size, ret = -1; - - /* We make it up in memory, then write it out if not internal */ - size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t); - if (!(newdb = (struct tdb_header *)calloc(size, 1))) - return TDB_ERRCODE(TDB_ERR_OOM, -1); - - /* Fill in the header */ - newdb->version = TDB_VERSION; - newdb->hash_size = hash_size; - if (tdb->flags & TDB_INTERNAL) { - tdb->map_size = size; - tdb->map_ptr = (char *)newdb; - memcpy(&tdb->header, newdb, sizeof(tdb->header)); - /* Convert the `ondisk' version if asked. */ - CONVERT(*newdb); - return 0; - } - if (lseek(tdb->fd, 0, SEEK_SET) == -1) - goto fail; - - if (ftruncate(tdb->fd, 0) == -1) - goto fail; - - /* This creates an endian-converted header, as if read from disk */ - CONVERT(*newdb); - memcpy(&tdb->header, newdb, sizeof(tdb->header)); - /* Don't endian-convert the magic food! */ - memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1); - if (write(tdb->fd, newdb, size) != size) { - ret = -1; - } else { - ret = 0; - } - - fail: - SAFE_FREE(newdb); - return ret; -} - - - -static int tdb_already_open(dev_t device, - ino_t ino) -{ - struct tdb_context *i; - - for (i = tdbs; i; i = i->next) { - if (i->device == device && i->inode == ino) { - return 1; - } - } - - return 0; -} - -/* open the database, creating it if necessary - - The open_flags and mode are passed straight to the open call on the - database file. A flags value of O_WRONLY is invalid. The hash size - is advisory, use zero for a default value. - - Return is NULL on error, in which case errno is also set. Don't - try to call tdb_error or tdb_errname, just do strerror(errno). - - @param name may be NULL for internal databases. */ -struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode) -{ - return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL); -} - -/* a default logging function */ -static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); -static void null_log_fn(struct tdb_context *tdb EXT2FS_ATTR((unused)), - enum tdb_debug_level level EXT2FS_ATTR((unused)), - const char *fmt EXT2FS_ATTR((unused)), ...) -{ -} - - -struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode, - const struct tdb_logging_context *log_ctx, - tdb_hash_func hash_fn) -{ - struct tdb_context *tdb; - struct stat st; - int rev = 0, locked = 0; - unsigned char *vp; - u32 vertest; - - if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) { - /* Can't log this */ - errno = ENOMEM; - goto fail; - } - tdb_io_init(tdb); - tdb->fd = -1; - tdb->name = NULL; - tdb->map_ptr = NULL; - tdb->flags = tdb_flags; - tdb->open_flags = open_flags; - if (log_ctx) { - tdb->log = *log_ctx; - } else { - tdb->log.log_fn = null_log_fn; - tdb->log.log_private = NULL; - } - tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; - - /* cache the page size */ - tdb->page_size = sysconf(_SC_PAGESIZE); - if (tdb->page_size <= 0) { - tdb->page_size = 0x2000; - } - - if ((open_flags & O_ACCMODE) == O_WRONLY) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n", - name)); - errno = EINVAL; - goto fail; - } - - if (hash_size == 0) - hash_size = DEFAULT_HASH_SIZE; - if ((open_flags & O_ACCMODE) == O_RDONLY) { - tdb->read_only = 1; - /* read only databases don't do locking or clear if first */ - tdb->flags |= TDB_NOLOCK; - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - } - - /* internal databases don't mmap or lock, and start off cleared */ - if (tdb->flags & TDB_INTERNAL) { - tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - if (tdb_new_database(tdb, hash_size) != 0) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: tdb_new_database failed!")); - goto fail; - } - goto internal; - } - - if ((tdb->fd = open(name, open_flags, mode)) == -1) { - TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_open_ex: could not open file %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by open(2) */ - } - - /* ensure there is only one process initialising at once */ - if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get global lock on %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by tdb_brlock */ - } - - /* we need to zero database if we are the only one with it open */ - if ((tdb_flags & TDB_CLEAR_IF_FIRST) && - (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0, 1) == 0))) { - open_flags |= O_CREAT; - if (ftruncate(tdb->fd, 0) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " - "failed to truncate %s: %s\n", - name, strerror(errno))); - goto fail; /* errno set by ftruncate */ - } - } - - if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) - || memcmp(tdb->header.magic_food, TDB_MAGIC_FOOD, - sizeof(TDB_MAGIC_FOOD)) != 0 - || (tdb->header.version != TDB_VERSION - && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) { - /* its not a valid database - possibly initialise it */ - if (!(open_flags & O_CREAT) || tdb_new_database(tdb, hash_size) == -1) { - errno = EIO; /* ie bad format or something */ - goto fail; - } - rev = (tdb->flags & TDB_CONVERT); - } - vp = (unsigned char *)&tdb->header.version; - vertest = (((u32)vp[0]) << 24) | (((u32)vp[1]) << 16) | - (((u32)vp[2]) << 8) | (u32)vp[3]; - tdb->flags |= (vertest==TDB_VERSION) ? TDB_BIGENDIAN : 0; - if (!rev) - tdb->flags &= ~TDB_CONVERT; - else { - tdb->flags |= TDB_CONVERT; - tdb_convert(&tdb->header, sizeof(tdb->header)); - } - if (fstat(tdb->fd, &st) == -1) - goto fail; - - if (tdb->header.rwlocks != 0) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n")); - goto fail; - } - - /* Is it already in the open list? If so, fail. */ - if (tdb_already_open(st.st_dev, st.st_ino)) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " - "%s (%d,%d) is already open in this process\n", - name, (int)st.st_dev, (int)st.st_ino)); - errno = EBUSY; - goto fail; - } - - if (!(tdb->name = (char *)strdup(name))) { - errno = ENOMEM; - goto fail; - } - - tdb->map_size = st.st_size; - tdb->device = st.st_dev; - tdb->inode = st.st_ino; - tdb->max_dead_records = 0; - tdb_mmap(tdb); - if (locked) { - if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0, 1) == -1) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " - "failed to take ACTIVE_LOCK on %s: %s\n", - name, strerror(errno))); - goto fail; - } - - } - - /* We always need to do this if the CLEAR_IF_FIRST flag is set, even if - we didn't get the initial exclusive lock as we need to let all other - users know we're using it. */ - - if (tdb_flags & TDB_CLEAR_IF_FIRST) { - /* leave this lock in place to indicate it's in use */ - if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1) - goto fail; - } - - /* if needed, run recovery */ - if (tdb_transaction_recover(tdb) == -1) { - goto fail; - } - - internal: - /* Internal (memory-only) databases skip all the code above to - * do with disk files, and resume here by releasing their - * global lock and hooking into the active list. */ - if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1) == -1) - goto fail; - tdb->next = tdbs; - tdbs = tdb; - return tdb; - - fail: - { int save_errno = errno; - - if (!tdb) - return NULL; - - if (tdb->map_ptr) { - if (tdb->flags & TDB_INTERNAL) - SAFE_FREE(tdb->map_ptr); - else - tdb_munmap(tdb); - } - SAFE_FREE(tdb->name); - if (tdb->fd != -1) - if (close(tdb->fd) != 0) - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n")); - SAFE_FREE(tdb); - errno = save_errno; - return NULL; - } -} - -/* - * Set the maximum number of dead records per hash chain - */ - -void tdb_set_max_dead(struct tdb_context *tdb, int max_dead) -{ - tdb->max_dead_records = max_dead; -} - -/** - * Close a database. - * - * @returns -1 for error; 0 for success. - **/ -int tdb_close(struct tdb_context *tdb) -{ - struct tdb_context **i; - int ret = 0; - - if (tdb->transaction) { - tdb_transaction_cancel(tdb); - } - - if (tdb->map_ptr) { - if (tdb->flags & TDB_INTERNAL) - SAFE_FREE(tdb->map_ptr); - else - tdb_munmap(tdb); - } - SAFE_FREE(tdb->name); - if (tdb->fd != -1) - ret = close(tdb->fd); - SAFE_FREE(tdb->lockrecs); - - /* Remove from contexts list */ - for (i = &tdbs; *i; i = &(*i)->next) { - if (*i == tdb) { - *i = tdb->next; - break; - } - } - - memset(tdb, 0, sizeof(*tdb)); - SAFE_FREE(tdb); - - return ret; -} - -/* register a logging function */ -void tdb_set_logging_function(struct tdb_context *tdb, - const struct tdb_logging_context *log_ctx) -{ - tdb->log = *log_ctx; -} - -void *tdb_get_logging_private(struct tdb_context *tdb) -{ - return tdb->log.log_private; -} - -/* reopen a tdb - this can be used after a fork to ensure that we have an independent - seek pointer from our parent and to re-establish locks */ -int tdb_reopen(struct tdb_context *tdb) -{ - struct stat st; - - if (tdb->flags & TDB_INTERNAL) { - return 0; /* Nothing to do. */ - } - - if (tdb->num_locks != 0 || tdb->global_lock.count) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n")); - goto fail; - } - - if (tdb->transaction != 0) { - TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed inside a transaction\n")); - goto fail; - } - - if (tdb_munmap(tdb) != 0) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); - goto fail; - } - if (close(tdb->fd) != 0) - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: WARNING closing tdb->fd failed!\n")); - tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); - if (tdb->fd == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno))); - goto fail; - } - if ((tdb->flags & TDB_CLEAR_IF_FIRST) && - (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n")); - goto fail; - } - if (fstat(tdb->fd, &st) != 0) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); - goto fail; - } - if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: file dev/inode has changed!\n")); - goto fail; - } - tdb_mmap(tdb); - - return 0; - -fail: - tdb_close(tdb); - return -1; -} - -/* reopen all tdb's */ -int tdb_reopen_all(int parent_longlived) -{ - struct tdb_context *tdb; - - for (tdb=tdbs; tdb; tdb = tdb->next) { - /* - * If the parent is longlived (ie. a - * parent daemon architecture), we know - * it will keep it's active lock on a - * tdb opened with CLEAR_IF_FIRST. Thus - * for child processes we don't have to - * add an active lock. This is essential - * to improve performance on systems that - * keep POSIX locks as a non-scalable data - * structure in the kernel. - */ - if (parent_longlived) { - /* Ensure no clear-if-first. */ - tdb->flags &= ~TDB_CLEAR_IF_FIRST; - } - - if (tdb_reopen(tdb) != 0) - return -1; - } - - return 0; -} - -/** - * Flush a database file from the page cache. - **/ -int tdb_flush(struct tdb_context *tdb) -{ - if (tdb->fd != -1) - return fsync(tdb->fd); - return 0; -} diff --git a/jni/e2fsprogs/lib/ext2fs/tdbtool.c b/jni/e2fsprogs/lib/ext2fs/tdbtool.c deleted file mode 100755 index eeac0c8..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tdbtool.c +++ /dev/null @@ -1,621 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba database functions - Copyright (C) Andrew Tridgell 1999-2000 - Copyright (C) Paul `Rusty' Russell 2000 - Copyright (C) Jeremy Allison 2000 - Copyright (C) Andrew Esh 2001 - - 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. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "config.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tdb.h" - -static int do_command(void); -const char *cmdname; -char *arg1, *arg2; -size_t arg1len, arg2len; -int bIterate = 0; -char *line; -TDB_DATA iterate_kbuf; -char cmdline[1024]; - -enum commands { - CMD_CREATE_TDB, - CMD_OPEN_TDB, - CMD_ERASE, - CMD_DUMP, - CMD_INSERT, - CMD_MOVE, - CMD_STORE, - CMD_SHOW, - CMD_KEYS, - CMD_HEXKEYS, - CMD_DELETE, - CMD_LIST_HASH_FREE, - CMD_LIST_FREE, - CMD_INFO, - CMD_FIRST, - CMD_NEXT, - CMD_SYSTEM, - CMD_QUIT, - CMD_HELP -}; - -typedef struct { - const char *name; - enum commands cmd; -} COMMAND_TABLE; - -COMMAND_TABLE cmd_table[] = { - {"create", CMD_CREATE_TDB}, - {"open", CMD_OPEN_TDB}, - {"erase", CMD_ERASE}, - {"dump", CMD_DUMP}, - {"insert", CMD_INSERT}, - {"move", CMD_MOVE}, - {"store", CMD_STORE}, - {"show", CMD_SHOW}, - {"keys", CMD_KEYS}, - {"hexkeys", CMD_HEXKEYS}, - {"delete", CMD_DELETE}, - {"list", CMD_LIST_HASH_FREE}, - {"free", CMD_LIST_FREE}, - {"info", CMD_INFO}, - {"first", CMD_FIRST}, - {"1", CMD_FIRST}, - {"next", CMD_NEXT}, - {"n", CMD_NEXT}, - {"quit", CMD_QUIT}, - {"q", CMD_QUIT}, - {"!", CMD_SYSTEM}, - {NULL, CMD_HELP} -}; - -/* a tdb tool for manipulating a tdb database */ - -static TDB_CONTEXT *tdb; - -static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); -static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); -static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state); - -static void print_asc(const char *buf,int len) -{ - int i; - - /* We're probably printing ASCII strings so don't try to display - the trailing NULL character. */ - - if (buf[len - 1] == 0) - len--; - - for (i=0;i8) printf(" "); - while (n--) printf(" "); - - n = i%16; - if (n > 8) n = 8; - print_asc(&buf[i-(i%16)],n); printf(" "); - n = (i%16) - n; - if (n>0) print_asc(&buf[i-n],n); - printf("\n"); - } -} - -static void help(void) -{ - printf("\n" -"tdbtool: \n" -" create dbname : create a database\n" -" open dbname : open an existing database\n" -" erase : erase the database\n" -" dump : dump the database as strings\n" -" keys : dump the database keys as strings\n" -" hexkeys : dump the database keys as hex values\n" -" info : print summary info about the database\n" -" insert key data : insert a record\n" -" move key file : move a record to a destination tdb\n" -" store key data : store a record (replace)\n" -" show key : show a record by key\n" -" delete key : delete a record by key\n" -" list : print the database hash table and freelist\n" -" free : print the database freelist\n" -" ! command : execute system command\n" -" 1 | first : print the first record\n" -" n | next : print the next record\n" -" q | quit : terminate\n" -" \\n : repeat 'next' command\n" -"\n"); -} - -static void terror(const char *why) -{ - printf("%s\n", why); -} - -static void create_tdb(const char *tdbname) -{ - if (tdb) tdb_close(tdb); - tdb = tdb_open(tdbname, 0, TDB_CLEAR_IF_FIRST, - O_RDWR | O_CREAT | O_TRUNC, 0600); - if (!tdb) { - printf("Could not create %s: %s\n", tdbname, strerror(errno)); - } -} - -static void open_tdb(const char *tdbname) -{ - if (tdb) tdb_close(tdb); - tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600); - if (!tdb) { - printf("Could not open %s: %s\n", tdbname, strerror(errno)); - } -} - -static void insert_tdb(char *keyname, size_t keylen, char* data, size_t datalen) -{ - TDB_DATA key, dbuf; - - if ((keyname == NULL) || (keylen == 0)) { - terror("need key"); - return; - } - - key.dptr = (unsigned char *)keyname; - key.dsize = keylen; - dbuf.dptr = (unsigned char *)data; - dbuf.dsize = datalen; - - if (tdb_store(tdb, key, dbuf, TDB_INSERT) == -1) { - terror("insert failed"); - } -} - -static void store_tdb(char *keyname, size_t keylen, char* data, size_t datalen) -{ - TDB_DATA key, dbuf; - - if ((keyname == NULL) || (keylen == 0)) { - terror("need key"); - return; - } - - if ((data == NULL) || (datalen == 0)) { - terror("need data"); - return; - } - - key.dptr = (unsigned char *)keyname; - key.dsize = keylen; - dbuf.dptr = (unsigned char *)data; - dbuf.dsize = datalen; - - printf("Storing key:\n"); - print_rec(tdb, key, dbuf, NULL); - - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) { - terror("store failed"); - } -} - -static void show_tdb(char *keyname, size_t keylen) -{ - TDB_DATA key, dbuf; - - if ((keyname == NULL) || (keylen == 0)) { - terror("need key"); - return; - } - - key.dptr = (unsigned char *)keyname; - key.dsize = keylen; - - dbuf = tdb_fetch(tdb, key); - if (!dbuf.dptr) { - terror("fetch failed"); - return; - } - - print_rec(tdb, key, dbuf, NULL); - - free( dbuf.dptr ); - - return; -} - -static void delete_tdb(char *keyname, size_t keylen) -{ - TDB_DATA key; - - if ((keyname == NULL) || (keylen == 0)) { - terror("need key"); - return; - } - - key.dptr = (unsigned char *)keyname; - key.dsize = keylen; - - if (tdb_delete(tdb, key) != 0) { - terror("delete failed"); - } -} - -static void move_rec(char *keyname, size_t keylen, char* tdbname) -{ - TDB_DATA key, dbuf; - TDB_CONTEXT *dst_tdb; - - if ((keyname == NULL) || (keylen == 0)) { - terror("need key"); - return; - } - - if ( !tdbname ) { - terror("need destination tdb name"); - return; - } - - key.dptr = (unsigned char *)keyname; - key.dsize = keylen; - - dbuf = tdb_fetch(tdb, key); - if (!dbuf.dptr) { - terror("fetch failed"); - return; - } - - print_rec(tdb, key, dbuf, NULL); - - dst_tdb = tdb_open(tdbname, 0, 0, O_RDWR, 0600); - if ( !dst_tdb ) { - terror("unable to open destination tdb"); - return; - } - - if ( tdb_store( dst_tdb, key, dbuf, TDB_REPLACE ) == -1 ) { - terror("failed to move record"); - } - else - printf("record moved\n"); - - tdb_close( dst_tdb ); - - return; -} - -static int print_rec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) -{ - printf("\nkey %d bytes\n", (int)key.dsize); - print_asc((const char *)key.dptr, key.dsize); - printf("\ndata %d bytes\n", (int)dbuf.dsize); - print_data((const char *)dbuf.dptr, dbuf.dsize); - return 0; -} - -static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) -{ - printf("key %d bytes: ", (int)key.dsize); - print_asc((const char *)key.dptr, key.dsize); - printf("\n"); - return 0; -} - -static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) -{ - printf("key %d bytes\n", (int)key.dsize); - print_data((const char *)key.dptr, key.dsize); - printf("\n"); - return 0; -} - -static int total_bytes; - -static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) -{ - total_bytes += dbuf.dsize; - return 0; -} - -static void info_tdb(void) -{ - int count; - total_bytes = 0; - if ((count = tdb_traverse(tdb, traverse_fn, NULL)) == -1) - printf("Error = %s\n", tdb_errorstr(tdb)); - else - printf("%d records totalling %d bytes\n", count, total_bytes); -} - -static char *tdb_getline(const char *prompt) -{ - static char thisline[1024]; - char *p; - fputs(prompt, stdout); - thisline[0] = 0; - p = fgets(thisline, sizeof(thisline)-1, stdin); - if (p) p = strchr(p, '\n'); - if (p) *p = 0; - return p?thisline:NULL; -} - -static int do_delete_fn(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, - void *state) -{ - return tdb_delete(the_tdb, key); -} - -static void first_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey) -{ - TDB_DATA dbuf; - *pkey = tdb_firstkey(the_tdb); - - dbuf = tdb_fetch(the_tdb, *pkey); - if (!dbuf.dptr) terror("fetch failed"); - else { - print_rec(the_tdb, *pkey, dbuf, NULL); - } -} - -static void next_record(TDB_CONTEXT *the_tdb, TDB_DATA *pkey) -{ - TDB_DATA dbuf; - *pkey = tdb_nextkey(the_tdb, *pkey); - - dbuf = tdb_fetch(the_tdb, *pkey); - if (!dbuf.dptr) - terror("fetch failed"); - else - print_rec(the_tdb, *pkey, dbuf, NULL); -} - -static int do_command(void) -{ - COMMAND_TABLE *ctp = cmd_table; - enum commands mycmd = CMD_HELP; - int cmd_len; - - if (cmdname && strlen(cmdname) == 0) { - mycmd = CMD_NEXT; - } else { - while (ctp->name) { - cmd_len = strlen(ctp->name); - if (strncmp(ctp->name,cmdname,cmd_len) == 0) { - mycmd = ctp->cmd; - break; - } - ctp++; - } - } - - switch (mycmd) { - case CMD_CREATE_TDB: - bIterate = 0; - create_tdb(arg1); - return 0; - case CMD_OPEN_TDB: - bIterate = 0; - open_tdb(arg1); - return 0; - case CMD_SYSTEM: - /* Shell command */ - system(arg1); - return 0; - case CMD_QUIT: - return 1; - default: - /* all the rest require a open database */ - if (!tdb) { - bIterate = 0; - terror("database not open"); - help(); - return 0; - } - switch (mycmd) { - case CMD_ERASE: - bIterate = 0; - tdb_traverse(tdb, do_delete_fn, NULL); - return 0; - case CMD_DUMP: - bIterate = 0; - tdb_traverse(tdb, print_rec, NULL); - return 0; - case CMD_INSERT: - bIterate = 0; - insert_tdb(arg1, arg1len,arg2,arg2len); - return 0; - case CMD_MOVE: - bIterate = 0; - move_rec(arg1,arg1len,arg2); - return 0; - case CMD_STORE: - bIterate = 0; - store_tdb(arg1,arg1len,arg2,arg2len); - return 0; - case CMD_SHOW: - bIterate = 0; - show_tdb(arg1, arg1len); - return 0; - case CMD_KEYS: - tdb_traverse(tdb, print_key, NULL); - return 0; - case CMD_HEXKEYS: - tdb_traverse(tdb, print_hexkey, NULL); - return 0; - case CMD_DELETE: - bIterate = 0; - delete_tdb(arg1,arg1len); - return 0; - case CMD_LIST_HASH_FREE: - tdb_dump_all(tdb); - return 0; - case CMD_LIST_FREE: - tdb_printfreelist(tdb); - return 0; - case CMD_INFO: - info_tdb(); - return 0; - case CMD_FIRST: - bIterate = 1; - first_record(tdb, &iterate_kbuf); - return 0; - case CMD_NEXT: - if (bIterate) - next_record(tdb, &iterate_kbuf); - return 0; - case CMD_HELP: - help(); - return 0; - case CMD_CREATE_TDB: - case CMD_OPEN_TDB: - case CMD_SYSTEM: - case CMD_QUIT: - /* - * unhandled commands. cases included here to avoid compiler - * warnings. - */ - return 0; - } - } - - return 0; -} - -static char *convert_string(char *instring, size_t *sizep) -{ - size_t length = 0; - char *outp, *inp; - char temp[3]; - - - outp = inp = instring; - - while (*inp) { - if (*inp == '\\') { - inp++; - if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) { - temp[0] = *inp++; - temp[1] = '\0'; - if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) { - temp[1] = *inp++; - temp[2] = '\0'; - } - *outp++ = (char)strtol((const char *)temp,NULL,16); - } else { - *outp++ = *inp++; - } - } else { - *outp++ = *inp++; - } - length++; - } - *sizep = length; - return instring; -} - -int main(int argc, char *argv[]) -{ - cmdname = ""; - arg1 = NULL; - arg1len = 0; - arg2 = NULL; - arg2len = 0; - - if (argv[1]) { - cmdname = "open"; - arg1 = argv[1]; - do_command(); - cmdname = ""; - arg1 = NULL; - } - - switch (argc) { - case 1: - case 2: - /* Interactive mode */ - while ((cmdname = tdb_getline("tdb> "))) { - arg2 = arg1 = NULL; - if ((arg1 = strchr((const char *)cmdname,' ')) != NULL) { - arg1++; - arg2 = arg1; - while (*arg2) { - if (*arg2 == ' ') { - *arg2++ = '\0'; - break; - } - if ((*arg2++ == '\\') && (*arg2 == ' ')) { - arg2++; - } - } - } - if (arg1) arg1 = convert_string(arg1,&arg1len); - if (arg2) arg2 = convert_string(arg2,&arg2len); - if (do_command()) break; - } - break; - case 5: - arg2 = convert_string(argv[4],&arg2len); - case 4: - arg1 = convert_string(argv[3],&arg1len); - case 3: - cmdname = argv[2]; - default: - do_command(); - break; - } - - if (tdb) tdb_close(tdb); - - return 0; -} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_badblocks.c b/jni/e2fsprogs/lib/ext2fs/tst_badblocks.c deleted file mode 100755 index b6e766a..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_badblocks.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * This testing program makes sure the badblocks implementation works. - * - * Copyright (C) 1996 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include "config.h" -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include -#if HAVE_ERRNO_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -#define ADD_BLK 0x0001 -#define DEL_BLK 0x0002 - -blk_t test1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 }; -blk_t test2[] = { 11, 10, 9, 8, 7, 6, 5, 4, 3, 3, 2, 1, 0 }; -blk_t test3[] = { 3, 1, 4, 5, 9, 2, 7, 10, 5, 6, 10, 8, 0 }; -blk_t test4[] = { 20, 50, 12, 17, 13, 2, 66, 23, 56, 0 }; -blk_t test4a[] = { - 20, 1, - 50, 1, - 3, 0, - 17, 1, - 18, 0, - 16, 0, - 11, 0, - 12, 1, - 13, 1, - 14, 0, - 80, 0, - 45, 0, - 66, 1, - 0 }; -blk_t test5[] = { 31, 20, 17, 51, 23, 1, 56, 57, 0 }; -blk_t test5a[] = { - 50, ADD_BLK, - 51, DEL_BLK, - 57, DEL_BLK, - 66, ADD_BLK, - 31, DEL_BLK, - 12, ADD_BLK, - 2, ADD_BLK, - 13, ADD_BLK, - 1, DEL_BLK, - 0 - }; - - -static int test_fail = 0; -static int test_expected_fail = 0; - -static errcode_t create_test_list(blk_t *vec, badblocks_list *ret) -{ - errcode_t retval; - badblocks_list bb; - int i; - - retval = ext2fs_badblocks_list_create(&bb, 5); - if (retval) { - com_err("create_test_list", retval, "while creating list"); - return retval; - } - for (i=0; vec[i]; i++) { - retval = ext2fs_badblocks_list_add(bb, vec[i]); - if (retval) { - com_err("create_test_list", retval, - "while adding test vector %d", i); - ext2fs_badblocks_list_free(bb); - return retval; - } - } - *ret = bb; - return 0; -} - -static void print_list(badblocks_list bb, int verify) -{ - errcode_t retval; - badblocks_iterate iter; - blk_t blk; - int i, ok; - - retval = ext2fs_badblocks_list_iterate_begin(bb, &iter); - if (retval) { - com_err("print_list", retval, "while setting up iterator"); - return; - } - ok = i = 1; - while (ext2fs_badblocks_list_iterate(iter, &blk)) { - printf("%u ", blk); - if (i++ != blk) - ok = 0; - } - ext2fs_badblocks_list_iterate_end(iter); - if (verify) { - if (ok) - printf("--- OK"); - else { - printf("--- NOT OK"); - test_fail++; - } - } -} - -static void validate_test_seq(badblocks_list bb, blk_t *vec) -{ - int i, match, ok; - - for (i = 0; vec[i]; i += 2) { - match = ext2fs_badblocks_list_test(bb, vec[i]); - if (match == vec[i+1]) - ok = 1; - else { - ok = 0; - test_fail++; - } - printf("\tblock %u is %s --- %s\n", vec[i], - match ? "present" : "absent", - ok ? "OK" : "NOT OK"); - } -} - -static void do_test_seq(badblocks_list bb, blk_t *vec) -{ - int i, match; - - for (i = 0; vec[i]; i += 2) { - switch (vec[i+1]) { - case ADD_BLK: - ext2fs_badblocks_list_add(bb, vec[i]); - match = ext2fs_badblocks_list_test(bb, vec[i]); - printf("Adding block %u --- now %s\n", vec[i], - match ? "present" : "absent"); - if (!match) { - printf("FAILURE!\n"); - test_fail++; - } - break; - case DEL_BLK: - ext2fs_badblocks_list_del(bb, vec[i]); - match = ext2fs_badblocks_list_test(bb, vec[i]); - printf("Removing block %u --- now %s\n", vec[i], - ext2fs_badblocks_list_test(bb, vec[i]) ? - "present" : "absent"); - if (match) { - printf("FAILURE!\n"); - test_fail++; - } - break; - } - } -} - - -int file_test(badblocks_list bb) -{ - badblocks_list new_bb = 0; - errcode_t retval; - FILE *f; - - f = tmpfile(); - if (!f) { - fprintf(stderr, "Error opening temp file: %s\n", - error_message(errno)); - return 1; - } - retval = ext2fs_write_bb_FILE(bb, 0, f); - if (retval) { - com_err("file_test", retval, "while writing bad blocks"); - return 1; - } - - rewind(f); - retval = ext2fs_read_bb_FILE2(0, f, &new_bb, 0, 0); - if (retval) { - com_err("file_test", retval, "while reading bad blocks"); - return 1; - } - fclose(f); - - if (ext2fs_badblocks_equal(bb, new_bb)) { - printf("Block bitmap matched after reading and writing.\n"); - } else { - printf("Block bitmap NOT matched.\n"); - test_fail++; - } - ext2fs_badblocks_list_free(new_bb); - return 0; -} - -static void invalid_proc(ext2_filsys fs, blk_t blk) -{ - if (blk == 34500) { - printf("Expected invalid block\n"); - test_expected_fail++; - } else { - printf("Invalid block #: %u\n", blk); - test_fail++; - } -} - -void file_test_invalid(badblocks_list bb) -{ - badblocks_list new_bb = 0; - errcode_t retval; - ext2_filsys fs; - FILE *f; - - fs = malloc(sizeof(struct struct_ext2_filsys)); - memset(fs, 0, sizeof(struct struct_ext2_filsys)); - fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS; - fs->super = malloc(SUPERBLOCK_SIZE); - memset(fs->super, 0, SUPERBLOCK_SIZE); - fs->super->s_first_data_block = 1; - ext2fs_blocks_count_set(fs->super, 100); - - f = tmpfile(); - if (!f) { - fprintf(stderr, "Error opening temp file: %s\n", - error_message(errno)); - test_fail++; - goto out; - } - retval = ext2fs_write_bb_FILE(bb, 0, f); - if (retval) { - com_err("file_test", retval, "while writing bad blocks"); - test_fail++; - goto out; - } - fprintf(f, "34500\n"); - - rewind(f); - test_expected_fail = 0; - retval = ext2fs_read_bb_FILE(fs, f, &new_bb, invalid_proc); - if (retval) { - com_err("file_test", retval, "while reading bad blocks"); - test_fail++; - goto out; - } - fclose(f); - if (!test_expected_fail) { - printf("Expected test failure didn't happen!\n"); - test_fail++; - } - - - if (ext2fs_badblocks_equal(bb, new_bb)) { - printf("Block bitmap matched after reading and writing.\n"); - } else { - printf("Block bitmap NOT matched.\n"); - test_fail++; - } - ext2fs_badblocks_list_free(new_bb); -out: - free(fs->super); - free(fs); -} - -int main(int argc, char **argv) -{ - badblocks_list bb1, bb2, bb3, bb4, bb5; - int equal; - errcode_t retval; - - add_error_table(&et_ext2_error_table); - - bb1 = bb2 = bb3 = bb4 = bb5 = 0; - - printf("test1: "); - retval = create_test_list(test1, &bb1); - if (retval == 0) - print_list(bb1, 1); - printf("\n"); - - printf("test2: "); - retval = create_test_list(test2, &bb2); - if (retval == 0) - print_list(bb2, 1); - printf("\n"); - - printf("test3: "); - retval = create_test_list(test3, &bb3); - if (retval == 0) - print_list(bb3, 1); - printf("\n"); - - printf("test4: "); - retval = create_test_list(test4, &bb4); - if (retval == 0) { - print_list(bb4, 0); - printf("\n"); - validate_test_seq(bb4, test4a); - } - printf("\n"); - - printf("test5: "); - retval = create_test_list(test5, &bb5); - if (retval == 0) { - print_list(bb5, 0); - printf("\n"); - do_test_seq(bb5, test5a); - printf("After test5 sequence: "); - print_list(bb5, 0); - printf("\n"); - } - printf("\n"); - - if (bb1 && bb2 && bb3 && bb4 && bb5) { - printf("Comparison tests:\n"); - equal = ext2fs_badblocks_equal(bb1, bb2); - printf("bb1 and bb2 are %sequal.\n", equal ? "" : "NOT "); - if (equal) - test_fail++; - - equal = ext2fs_badblocks_equal(bb1, bb3); - printf("bb1 and bb3 are %sequal.\n", equal ? "" : "NOT "); - if (!equal) - test_fail++; - - equal = ext2fs_badblocks_equal(bb1, bb4); - printf("bb1 and bb4 are %sequal.\n", equal ? "" : "NOT "); - if (equal) - test_fail++; - - equal = ext2fs_badblocks_equal(bb4, bb5); - printf("bb4 and bb5 are %sequal.\n", equal ? "" : "NOT "); - if (!equal) - test_fail++; - printf("\n"); - } - - file_test(bb4); - - file_test_invalid(bb4); - - if (test_fail == 0) - printf("ext2fs library badblocks tests checks out OK!\n"); - - if (bb1) - ext2fs_badblocks_list_free(bb1); - if (bb2) - ext2fs_badblocks_list_free(bb2); - if (bb3) - ext2fs_badblocks_list_free(bb3); - if (bb4) - ext2fs_badblocks_list_free(bb4); - if (bb5) - ext2fs_badblocks_list_free(bb5); - - return test_fail; - -} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_bitmaps.c b/jni/e2fsprogs/lib/ext2fs/tst_bitmaps.c deleted file mode 100755 index cb3c70d..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_bitmaps.c +++ /dev/null @@ -1,732 +0,0 @@ -/* - * tst_bitmaps.c - * - * Copyright (C) 2011 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include "config.h" -#include -#include -#include -#ifdef HAVE_GETOPT_H -#include -#endif -#include -#include -#include -#include -#include -#include "ss/ss.h" - -#include "ext2_fs.h" -#include "ext2fs.h" -#include "ext2fsP.h" - -extern ss_request_table tst_bitmaps_cmds; - -static char subsystem_name[] = "tst_bitmaps"; -static char version[] = "1.0"; - -ext2_filsys test_fs; -int exit_status = 0; - -static int source_file(const char *cmd_file, int sci_idx) -{ - FILE *f; - char buf[256]; - char *cp; - int retval; - int noecho; - - if (strcmp(cmd_file, "-") == 0) - f = stdin; - else { - f = fopen(cmd_file, "r"); - if (!f) { - perror(cmd_file); - exit(1); - } - } - fflush(stdout); - fflush(stderr); - setbuf(stdout, NULL); - setbuf(stderr, NULL); - while (!feof(f)) { - if (fgets(buf, sizeof(buf), f) == NULL) - break; - if (buf[0] == '#') - continue; - noecho = 0; - if (buf[0] == '-') { - noecho = 1; - buf[0] = ' '; - } - cp = strchr(buf, '\n'); - if (cp) - *cp = 0; - cp = strchr(buf, '\r'); - if (cp) - *cp = 0; - if (!noecho) - printf("%s: %s\n", subsystem_name, buf); - retval = ss_execute_line(sci_idx, buf); - if (retval) { - ss_perror(sci_idx, retval, buf); - exit_status++; - } - } - return exit_status; -} - - -/* - * This function resets the libc getopt() function, which keeps - * internal state. Bad design! Stupid libc API designers! No - * biscuit! - * - * BSD-derived getopt() functions require that optind be reset to 1 in - * order to reset getopt() state. This used to be generally accepted - * way of resetting getopt(). However, glibc's getopt() - * has additional getopt() state beyond optind, and requires that - * optind be set zero to reset its state. So the unfortunate state of - * affairs is that BSD-derived versions of getopt() misbehave if - * optind is set to 0 in order to reset getopt(), and glibc's getopt() - * will core dump if optind is set 1 in order to reset getopt(). - * - * More modern versions of BSD require that optreset be set to 1 in - * order to reset getopt(). Sigh. Standards, anyone? - * - * We hide the hair here. - */ -void reset_getopt(void) -{ -#if defined(__GLIBC__) || defined(__linux__) - optind = 0; -#else - optind = 1; -#endif -#ifdef HAVE_OPTRESET - optreset = 1; /* Makes BSD getopt happy */ -#endif -} - -/* - * This function will convert a string to an unsigned long, printing - * an error message if it fails, and returning success or failure in err. - */ -unsigned long parse_ulong(const char *str, const char *cmd, - const char *descr, int *err) -{ - char *tmp; - unsigned long ret; - - ret = strtoul(str, &tmp, 0); - if (*tmp == 0) { - if (err) - *err = 0; - return ret; - } - com_err(cmd, 0, "Bad %s - %s", descr, str); - if (err) - *err = 1; - else - exit(1); - return 0; -} - - -int check_fs_open(char *name) -{ - if (!test_fs) { - com_err(name, 0, "Filesystem not open"); - return 1; - } - return 0; -} - -static void setup_filesystem(const char *name, - unsigned int blocks, unsigned int inodes, - unsigned int type, int flags) -{ - struct ext2_super_block param; - errcode_t retval; - - memset(¶m, 0, sizeof(param)); - ext2fs_blocks_count_set(¶m, blocks); - param.s_inodes_count = inodes; - - retval = ext2fs_initialize("test fs", flags, ¶m, - test_io_manager, &test_fs); - - if (retval) { - com_err(name, retval, "while initializing filesystem"); - return; - } - test_fs->default_bitmap_type = type; - ext2fs_free_block_bitmap(test_fs->block_map); - test_fs->block_map = 0; - ext2fs_free_inode_bitmap(test_fs->inode_map); - test_fs->inode_map = 0; - retval = ext2fs_allocate_block_bitmap(test_fs, "block bitmap", - &test_fs->block_map); - if (retval) { - com_err(name, retval, "while allocating block bitmap"); - goto errout; - } - retval = ext2fs_allocate_inode_bitmap(test_fs, "inode bitmap", - &test_fs->inode_map); - if (retval) { - com_err(name, retval, "while allocating inode bitmap"); - goto errout; - } - return; - -errout: - ext2fs_close_free(&test_fs); -} - -void setup_cmd(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - int c, err; - unsigned int blocks = 128; - unsigned int inodes = 0; - unsigned int type = EXT2FS_BMAP64_BITARRAY; - int flags = EXT2_FLAG_64BITS; - - if (test_fs) - ext2fs_close_free(&test_fs); - - reset_getopt(); - while ((c = getopt(argc, argv, "b:i:lt:")) != EOF) { - switch (c) { - case 'b': - blocks = parse_ulong(optarg, argv[0], - "number of blocks", &err); - if (err) - return; - break; - case 'i': - inodes = parse_ulong(optarg, argv[0], - "number of blocks", &err); - if (err) - return; - break; - case 'l': /* Legacy bitmaps */ - flags = 0; - break; - case 't': - type = parse_ulong(optarg, argv[0], - "bitmap backend type", &err); - if (err) - return; - break; - default: - fprintf(stderr, "%s: usage: setup [-b blocks] " - "[-i inodes] [-t type]\n", argv[0]); - return; - } - } - setup_filesystem(argv[0], blocks, inodes, type, flags); -} - -void close_cmd(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - if (check_fs_open(argv[0])) - return; - - ext2fs_close_free(&test_fs); -} - - -void dump_bitmap(ext2fs_generic_bitmap bmap, unsigned int start, unsigned num) -{ - unsigned char *buf; - errcode_t retval; - int i, len = (num - start + 7) / 8; - - buf = malloc(len); - if (!buf) { - com_err("dump_bitmap", 0, "couldn't allocate buffer"); - return; - } - memset(buf, 0, len); - retval = ext2fs_get_generic_bmap_range(bmap, (__u64) start, num, buf); - if (retval) { - com_err("dump_bitmap", retval, - "while calling ext2fs_generic_bmap_range"); - free(buf); - return; - } - for (i=0; i < len; i++) - printf("%02x", buf[i]); - printf("\n"); - printf("bits set: %u\n", ext2fs_bitcount(buf, len)); - free(buf); -} - -void dump_inode_bitmap_cmd(int argc, char **argv, - int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - if (check_fs_open(argv[0])) - return; - - printf("inode bitmap: "); - dump_bitmap(test_fs->inode_map, 1, test_fs->super->s_inodes_count); -} - -void dump_block_bitmap_cmd(int argc, char **argv, - int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - if (check_fs_open(argv[0])) - return; - - printf("block bitmap: "); - dump_bitmap(test_fs->block_map, test_fs->super->s_first_data_block, - test_fs->super->s_blocks_count); -} - -void do_setb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - unsigned int block, num; - int err; - int test_result, op_result; - - if (check_fs_open(argv[0])) - return; - - if (argc != 2 && argc != 3) { - com_err(argv[0], 0, "Usage: setb [num]"); - return; - } - - block = parse_ulong(argv[1], argv[0], "block", &err); - if (err) - return; - - if (argc == 3) { - num = parse_ulong(argv[2], argv[0], "num", &err); - if (err) - return; - - ext2fs_mark_block_bitmap_range2(test_fs->block_map, - block, num); - printf("Marking blocks %u to %u\n", block, block + num - 1); - return; - } - - test_result = ext2fs_test_block_bitmap2(test_fs->block_map, block); - op_result = ext2fs_mark_block_bitmap2(test_fs->block_map, block); - printf("Setting block %u, was %s before\n", block, op_result ? - "set" : "clear"); - if (!test_result != !op_result) - com_err(argv[0], 0, "*ERROR* test_result different! (%d, %d)", - test_result, op_result); -} - -void do_clearb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - unsigned int block, num; - int err; - int test_result, op_result; - - if (check_fs_open(argv[0])) - return; - - if (argc != 2 && argc != 3) { - com_err(argv[0], 0, "Usage: clearb [num]"); - return; - } - - block = parse_ulong(argv[1], argv[0], "block", &err); - if (err) - return; - - if (argc == 3) { - num = parse_ulong(argv[2], argv[0], "num", &err); - if (err) - return; - - ext2fs_unmark_block_bitmap_range2(test_fs->block_map, - block, num); - printf("Clearing blocks %u to %u\n", block, block + num - 1); - return; - } - - test_result = ext2fs_test_block_bitmap2(test_fs->block_map, block); - op_result = ext2fs_unmark_block_bitmap2(test_fs->block_map, block); - printf("Clearing block %u, was %s before\n", block, op_result ? - "set" : "clear"); - if (!test_result != !op_result) - com_err(argv[0], 0, "*ERROR* test_result different! (%d, %d)", - test_result, op_result); -} - -void do_testb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - unsigned int block, num; - int err; - int test_result; - - if (check_fs_open(argv[0])) - return; - - if (argc != 2 && argc != 3) { - com_err(argv[0], 0, "Usage: testb [num]"); - return; - } - - block = parse_ulong(argv[1], argv[0], "block", &err); - if (err) - return; - - if (argc == 3) { - num = parse_ulong(argv[2], argv[0], "num", &err); - if (err) - return; - - test_result = - ext2fs_test_block_bitmap_range2(test_fs->block_map, - block, num); - printf("Blocks %u to %u are %sall clear.\n", - block, block + num - 1, test_result ? "" : "NOT "); - return; - } - - test_result = ext2fs_test_block_bitmap2(test_fs->block_map, block); - printf("Block %u is %s\n", block, test_result ? "set" : "clear"); -} - -void do_ffzb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - unsigned int start, end; - int err; - errcode_t retval; - blk64_t out; - - if (check_fs_open(argv[0])) - return; - - if (argc != 3 && argc != 3) { - com_err(argv[0], 0, "Usage: ffzb "); - return; - } - - start = parse_ulong(argv[1], argv[0], "start", &err); - if (err) - return; - - end = parse_ulong(argv[2], argv[0], "end", &err); - if (err) - return; - - retval = ext2fs_find_first_zero_block_bitmap2(test_fs->block_map, - start, end, &out); - if (retval) { - printf("ext2fs_find_first_zero_block_bitmap2() returned %s\n", - error_message(retval)); - return; - } - printf("First unmarked block is %llu\n", (unsigned long long) out); -} - -void do_ffsb(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - unsigned int start, end; - int err; - errcode_t retval; - blk64_t out; - - if (check_fs_open(argv[0])) - return; - - if (argc != 3 && argc != 3) { - com_err(argv[0], 0, "Usage: ffsb "); - return; - } - - start = parse_ulong(argv[1], argv[0], "start", &err); - if (err) - return; - - end = parse_ulong(argv[2], argv[0], "end", &err); - if (err) - return; - - retval = ext2fs_find_first_set_block_bitmap2(test_fs->block_map, - start, end, &out); - if (retval) { - printf("ext2fs_find_first_set_block_bitmap2() returned %s\n", - error_message(retval)); - return; - } - printf("First marked block is %llu\n", (unsigned long long) out); -} - - -void do_zerob(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - if (check_fs_open(argv[0])) - return; - - printf("Clearing block bitmap.\n"); - ext2fs_clear_block_bitmap(test_fs->block_map); -} - -void do_seti(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - unsigned int inode; - int err; - int test_result, op_result; - - if (check_fs_open(argv[0])) - return; - - if (argc != 2) { - com_err(argv[0], 0, "Usage: seti "); - return; - } - - inode = parse_ulong(argv[1], argv[0], "inode", &err); - if (err) - return; - - test_result = ext2fs_test_inode_bitmap2(test_fs->inode_map, inode); - op_result = ext2fs_mark_inode_bitmap2(test_fs->inode_map, inode); - printf("Setting inode %u, was %s before\n", inode, op_result ? - "set" : "clear"); - if (!test_result != !op_result) { - com_err(argv[0], 0, "*ERROR* test_result different! (%d, %d)", - test_result, op_result); - exit_status++; - } -} - -void do_cleari(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - unsigned int inode; - int err; - int test_result, op_result; - - if (check_fs_open(argv[0])) - return; - - if (argc != 2) { - com_err(argv[0], 0, "Usage: clearb "); - return; - } - - inode = parse_ulong(argv[1], argv[0], "inode", &err); - if (err) - return; - - test_result = ext2fs_test_inode_bitmap2(test_fs->inode_map, inode); - op_result = ext2fs_unmark_inode_bitmap2(test_fs->inode_map, inode); - printf("Clearing inode %u, was %s before\n", inode, op_result ? - "set" : "clear"); - if (!test_result != !op_result) { - com_err(argv[0], 0, "*ERROR* test_result different! (%d, %d)", - test_result, op_result); - exit_status++; - } -} - -void do_testi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - unsigned int inode; - int err; - int test_result; - - if (check_fs_open(argv[0])) - return; - - if (argc != 2) { - com_err(argv[0], 0, "Usage: testb "); - return; - } - - inode = parse_ulong(argv[1], argv[0], "inode", &err); - if (err) - return; - - test_result = ext2fs_test_inode_bitmap2(test_fs->inode_map, inode); - printf("Inode %u is %s\n", inode, test_result ? "set" : "clear"); -} - -void do_ffzi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - unsigned int start, end; - int err; - errcode_t retval; - ext2_ino_t out; - - if (check_fs_open(argv[0])) - return; - - if (argc != 3 && argc != 3) { - com_err(argv[0], 0, "Usage: ffzi "); - return; - } - - start = parse_ulong(argv[1], argv[0], "start", &err); - if (err) - return; - - end = parse_ulong(argv[2], argv[0], "end", &err); - if (err) - return; - - retval = ext2fs_find_first_zero_inode_bitmap2(test_fs->inode_map, - start, end, &out); - if (retval) { - printf("ext2fs_find_first_zero_inode_bitmap2() returned %s\n", - error_message(retval)); - return; - } - printf("First unmarked inode is %u\n", out); -} - -void do_ffsi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - unsigned int start, end; - int err; - errcode_t retval; - ext2_ino_t out; - - if (check_fs_open(argv[0])) - return; - - if (argc != 3 && argc != 3) { - com_err(argv[0], 0, "Usage: ffsi "); - return; - } - - start = parse_ulong(argv[1], argv[0], "start", &err); - if (err) - return; - - end = parse_ulong(argv[2], argv[0], "end", &err); - if (err) - return; - - retval = ext2fs_find_first_set_inode_bitmap2(test_fs->inode_map, - start, end, &out); - if (retval) { - printf("ext2fs_find_first_set_inode_bitmap2() returned %s\n", - error_message(retval)); - return; - } - printf("First marked inode is %u\n", out); -} - -void do_zeroi(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - if (check_fs_open(argv[0])) - return; - - printf("Clearing inode bitmap.\n"); - ext2fs_clear_inode_bitmap(test_fs->inode_map); -} - -int main(int argc, char **argv) -{ - unsigned int blocks = 128; - unsigned int inodes = 0; - unsigned int type = EXT2FS_BMAP64_BITARRAY; - int c, err, code; - char *request = (char *)NULL; - char *cmd_file = 0; - int sci_idx; - int flags = EXT2_FLAG_64BITS; - - add_error_table(&et_ss_error_table); - add_error_table(&et_ext2_error_table); - while ((c = getopt (argc, argv, "b:i:lt:R:f:")) != EOF) { - switch (c) { - case 'b': - blocks = parse_ulong(optarg, argv[0], - "number of blocks", &err); - if (err) - exit(1); - break; - case 'i': - inodes = parse_ulong(optarg, argv[0], - "number of blocks", &err); - if (err) - exit(1); - break; - case 'l': /* Legacy bitmaps */ - flags = 0; - break; - case 't': - type = parse_ulong(optarg, argv[0], - "bitmap backend type", &err); - if (err) - exit(1); - break; - case 'R': - request = optarg; - break; - case 'f': - cmd_file = optarg; - break; - default: - com_err(argv[0], 0, "Usage: %s [-R request] " - "[-f cmd_file]", subsystem_name); - exit(1); - } - } - - sci_idx = ss_create_invocation(subsystem_name, version, - (char *)NULL, &tst_bitmaps_cmds, &code); - if (code) { - ss_perror(sci_idx, code, "creating invocation"); - exit(1); - } - - (void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &code); - if (code) { - ss_perror(sci_idx, code, "adding standard requests"); - exit (1); - } - - printf("%s %s. Type '?' for a list of commands.\n\n", - subsystem_name, version); - - setup_filesystem(argv[0], blocks, inodes, type, flags); - - if (request) { - code = ss_execute_line(sci_idx, request); - if (code) { - ss_perror(sci_idx, code, request); - exit_status++; - } - } else if (cmd_file) { - exit_status = source_file(cmd_file, sci_idx); - } else { - ss_listen(sci_idx); - } - - exit(exit_status); -} - diff --git a/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmd.ct b/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmd.ct deleted file mode 100755 index 13b7fa7..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmd.ct +++ /dev/null @@ -1,51 +0,0 @@ -command_table tst_bitmaps_cmds; - -request setup_cmd, "Setup file system", - setup; - -request close_cmd, "Close file system", - close; - -request dump_inode_bitmap_cmd, "Dump the inode bitmap", - dump_inode_bitmap, dump_ib; - -request dump_block_bitmap_cmd, "Dump the block bitmap", - dump_block_bitmap, dump_bb; - -request do_setb, "Set block", - set_block, setb; - -request do_clearb, "Clear block", - clear_block, clearb; - -request do_testb, "Test block", - test_block, testb; - -request do_ffzb, "Find first zero block", - find_first_zero_block, ffzb; - -request do_ffsb, "Find first set block", - find_first_set_block, ffsb; - -request do_zerob, "Clear block bitmap", - clear_block_bitmap, zerob; - -request do_seti, "Set inode", - set_inode, seti; - -request do_cleari, "Clear inode", - clear_inode, cleari; - -request do_testi, "Test inode", - test_inode, testi; - -request do_ffzi, "Find first zero inode", - find_first_zero_inode, ffzi; - -request do_ffsi, "Find first set inode", - find_first_set_inode, ffsi; - -request do_zeroi, "Clear inode bitmap", - clear_inode_bitmap, zeroi; - -end; diff --git a/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmds b/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmds deleted file mode 100755 index dc116b1..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_cmds +++ /dev/null @@ -1,150 +0,0 @@ -setb 12 0 -setb 12 -setb 12 -clearb 12 -clearb 12 -setb 12 -setb 14 -setb 16 -testb 13 -testb 15 -testb 12 -testb 14 -setb 13 -setb 15 -testb 12 -testb 11 -testb 15 -testb 16 -dump_bb -ffzb 11 16 -ffzb 12 16 -ffzb 12 20 -ffsb 0 127 -ffsb 1 128 -ffsb 1 127 -ffsb 1 10 -ffsb 1 11 -ffsb 12 12 -ffsb 13 12 -ffsb 12 15 -clearb 13 -ffzb 12 20 -ffsb 13 18 -setb 13 -clearb 12 7 -testb 12 7 -setb 15 -testb 12 7 -clearb 15 -testb 12 7 -setb 12 0 -setb 12 7 -dump_bb -seti 2 -seti 5 -seti 4 -seti 3 -seti 4 -seti 5 -testi 6 -testi 1 -dump_ib -ffzi 1 6 -ffzi 2 5 -ffzi 2 6 -ffsi 0 31 -ffsi 1 33 -ffsi 1 32 -ffsi 2 32 -ffsi 6 32 -cleari 4 -ffzi 2 6 -ffsi 4 32 -ffsi 5 32 -zeroi -testi 5 -seti 5 -seti 5 -cleari 5 -cleari 5 -testi 17 -testi 6 -testi 4 -clearb 7 12 -dump_bb -setb 1 -dump_bb -setb 2 -dump_bb -setb 3 -dump_bb -setb 4 -dump_bb -setb 5 -dump_bb -setb 6 -dump_bb -setb 7 -dump_bb -setb 8 -dump_bb -setb 10 -setb 12 -setb 14 -setb 17 -setb 19 -setb 24 -setb 26 -setb 27 -setb 30 -setb 31 -setb 32 -setb 35 -setb 39 -setb 40 -setb 44 -setb 46 -setb 47 -setb 49 -setb 51 -setb 52 -clearb 2 -clearb 3 -clearb 7 -dump_bb -ffsb 14 127 -ffsb 15 127 -ffsb 36 127 -ffsb 32 127 -ffsb 52 127 -ffsb 53 127 -ffsb 46 127 -ffsb 45 127 -ffsb 41 127 -ffsb 20 127 -ffsb 1 127 -ffsb 2 127 -ffsb 3 127 -ffsb 4 127 -ffsb 5 127 -ffsb 6 127 -ffsb 7 127 -ffsb 8 127 -ffzb 1 127 -ffzb 2 127 -ffzb 3 127 -ffzb 4 127 -ffzb 5 127 -ffzb 6 127 -ffzb 7 127 -ffzb 8 127 -ffzb 45 127 -ffzb 46 127 -ffzb 47 127 -ffzb 48 127 -ffzb 49 127 -ffzb 50 127 -ffzb 51 127 -quit - diff --git a/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_exp b/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_exp deleted file mode 100755 index 9cfea13..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_bitmaps_exp +++ /dev/null @@ -1,313 +0,0 @@ -tst_bitmaps 1.0. Type '?' for a list of commands. - -tst_bitmaps: setb 12 0 -Marking blocks 12 to 11 -tst_bitmaps: setb 12 -Setting block 12, was clear before -tst_bitmaps: setb 12 -Setting block 12, was set before -tst_bitmaps: clearb 12 -Clearing block 12, was set before -tst_bitmaps: clearb 12 -Clearing block 12, was clear before -tst_bitmaps: setb 12 -Setting block 12, was clear before -tst_bitmaps: setb 14 -Setting block 14, was clear before -tst_bitmaps: setb 16 -Setting block 16, was clear before -tst_bitmaps: testb 13 -Block 13 is clear -tst_bitmaps: testb 15 -Block 15 is clear -tst_bitmaps: testb 12 -Block 12 is set -tst_bitmaps: testb 14 -Block 14 is set -tst_bitmaps: setb 13 -Setting block 13, was clear before -tst_bitmaps: setb 15 -Setting block 15, was clear before -tst_bitmaps: testb 12 -Block 12 is set -tst_bitmaps: testb 11 -Block 11 is clear -tst_bitmaps: testb 15 -Block 15 is set -tst_bitmaps: testb 16 -Block 16 is set -tst_bitmaps: dump_bb -block bitmap: 00f80000000000000000000000000000 -bits set: 5 -tst_bitmaps: ffzb 11 16 -First unmarked block is 11 -tst_bitmaps: ffzb 12 16 -ext2fs_find_first_zero_block_bitmap2() returned No such file or directory -tst_bitmaps: ffzb 12 20 -First unmarked block is 17 -tst_bitmaps: ffsb 0 127 -ext2fs_find_first_set_block_bitmap2() returned Invalid argument -tst_bitmaps: ffsb 1 128 -ext2fs_find_first_set_block_bitmap2() returned Invalid argument -tst_bitmaps: ffsb 1 127 -First marked block is 12 -tst_bitmaps: ffsb 1 10 -ext2fs_find_first_set_block_bitmap2() returned No such file or directory -tst_bitmaps: ffsb 1 11 -ext2fs_find_first_set_block_bitmap2() returned No such file or directory -tst_bitmaps: ffsb 12 12 -First marked block is 12 -tst_bitmaps: ffsb 13 12 -ext2fs_find_first_set_block_bitmap2() returned Invalid argument -tst_bitmaps: ffsb 12 15 -First marked block is 12 -tst_bitmaps: clearb 13 -Clearing block 13, was set before -tst_bitmaps: ffzb 12 20 -First unmarked block is 13 -tst_bitmaps: ffsb 13 18 -First marked block is 14 -tst_bitmaps: setb 13 -Setting block 13, was clear before -tst_bitmaps: clearb 12 7 -Clearing blocks 12 to 18 -tst_bitmaps: testb 12 7 -Blocks 12 to 18 are all clear. -tst_bitmaps: setb 15 -Setting block 15, was clear before -tst_bitmaps: testb 12 7 -Blocks 12 to 18 are NOT all clear. -tst_bitmaps: clearb 15 -Clearing block 15, was set before -tst_bitmaps: testb 12 7 -Blocks 12 to 18 are all clear. -tst_bitmaps: setb 12 0 -Marking blocks 12 to 11 -tst_bitmaps: setb 12 7 -Marking blocks 12 to 18 -tst_bitmaps: dump_bb -block bitmap: 00f80300000000000000000000000000 -bits set: 7 -tst_bitmaps: seti 2 -Setting inode 2, was clear before -tst_bitmaps: seti 5 -Setting inode 5, was clear before -tst_bitmaps: seti 4 -Setting inode 4, was clear before -tst_bitmaps: seti 3 -Setting inode 3, was clear before -tst_bitmaps: seti 4 -Setting inode 4, was set before -tst_bitmaps: seti 5 -Setting inode 5, was set before -tst_bitmaps: testi 6 -Inode 6 is clear -tst_bitmaps: testi 1 -Inode 1 is clear -tst_bitmaps: dump_ib -inode bitmap: 1e000000 -bits set: 4 -tst_bitmaps: ffzi 1 6 -First unmarked inode is 1 -tst_bitmaps: ffzi 2 5 -ext2fs_find_first_zero_inode_bitmap2() returned No such file or directory -tst_bitmaps: ffzi 2 6 -First unmarked inode is 6 -tst_bitmaps: ffsi 0 31 -ext2fs_find_first_set_inode_bitmap2() returned Invalid argument -tst_bitmaps: ffsi 1 33 -ext2fs_find_first_set_inode_bitmap2() returned Invalid argument -tst_bitmaps: ffsi 1 32 -First marked inode is 2 -tst_bitmaps: ffsi 2 32 -First marked inode is 2 -tst_bitmaps: ffsi 6 32 -ext2fs_find_first_set_inode_bitmap2() returned No such file or directory -tst_bitmaps: cleari 4 -Clearing inode 4, was set before -tst_bitmaps: ffzi 2 6 -First unmarked inode is 4 -tst_bitmaps: ffsi 4 32 -First marked inode is 5 -tst_bitmaps: ffsi 5 32 -First marked inode is 5 -tst_bitmaps: zeroi -Clearing inode bitmap. -tst_bitmaps: testi 5 -Inode 5 is clear -tst_bitmaps: seti 5 -Setting inode 5, was clear before -tst_bitmaps: seti 5 -Setting inode 5, was set before -tst_bitmaps: cleari 5 -Clearing inode 5, was set before -tst_bitmaps: cleari 5 -Clearing inode 5, was clear before -tst_bitmaps: testi 17 -Inode 17 is clear -tst_bitmaps: testi 6 -Inode 6 is clear -tst_bitmaps: testi 4 -Inode 4 is clear -tst_bitmaps: clearb 7 12 -Clearing blocks 7 to 18 -tst_bitmaps: dump_bb -block bitmap: 00000000000000000000000000000000 -bits set: 0 -tst_bitmaps: setb 1 -Setting block 1, was clear before -tst_bitmaps: dump_bb -block bitmap: 01000000000000000000000000000000 -bits set: 1 -tst_bitmaps: setb 2 -Setting block 2, was clear before -tst_bitmaps: dump_bb -block bitmap: 03000000000000000000000000000000 -bits set: 2 -tst_bitmaps: setb 3 -Setting block 3, was clear before -tst_bitmaps: dump_bb -block bitmap: 07000000000000000000000000000000 -bits set: 3 -tst_bitmaps: setb 4 -Setting block 4, was clear before -tst_bitmaps: dump_bb -block bitmap: 0f000000000000000000000000000000 -bits set: 4 -tst_bitmaps: setb 5 -Setting block 5, was clear before -tst_bitmaps: dump_bb -block bitmap: 1f000000000000000000000000000000 -bits set: 5 -tst_bitmaps: setb 6 -Setting block 6, was clear before -tst_bitmaps: dump_bb -block bitmap: 3f000000000000000000000000000000 -bits set: 6 -tst_bitmaps: setb 7 -Setting block 7, was clear before -tst_bitmaps: dump_bb -block bitmap: 7f000000000000000000000000000000 -bits set: 7 -tst_bitmaps: setb 8 -Setting block 8, was clear before -tst_bitmaps: dump_bb -block bitmap: ff000000000000000000000000000000 -bits set: 8 -tst_bitmaps: setb 10 -Setting block 10, was clear before -tst_bitmaps: setb 12 -Setting block 12, was clear before -tst_bitmaps: setb 14 -Setting block 14, was clear before -tst_bitmaps: setb 17 -Setting block 17, was clear before -tst_bitmaps: setb 19 -Setting block 19, was clear before -tst_bitmaps: setb 24 -Setting block 24, was clear before -tst_bitmaps: setb 26 -Setting block 26, was clear before -tst_bitmaps: setb 27 -Setting block 27, was clear before -tst_bitmaps: setb 30 -Setting block 30, was clear before -tst_bitmaps: setb 31 -Setting block 31, was clear before -tst_bitmaps: setb 32 -Setting block 32, was clear before -tst_bitmaps: setb 35 -Setting block 35, was clear before -tst_bitmaps: setb 39 -Setting block 39, was clear before -tst_bitmaps: setb 40 -Setting block 40, was clear before -tst_bitmaps: setb 44 -Setting block 44, was clear before -tst_bitmaps: setb 46 -Setting block 46, was clear before -tst_bitmaps: setb 47 -Setting block 47, was clear before -tst_bitmaps: setb 49 -Setting block 49, was clear before -tst_bitmaps: setb 51 -Setting block 51, was clear before -tst_bitmaps: setb 52 -Setting block 52, was clear before -tst_bitmaps: clearb 2 -Clearing block 2, was set before -tst_bitmaps: clearb 3 -Clearing block 3, was set before -tst_bitmaps: clearb 7 -Clearing block 7, was set before -tst_bitmaps: dump_bb -block bitmap: b92a85e6c4680d000000000000000000 -bits set: 25 -tst_bitmaps: ffsb 14 127 -First marked block is 14 -tst_bitmaps: ffsb 15 127 -First marked block is 17 -tst_bitmaps: ffsb 36 127 -First marked block is 39 -tst_bitmaps: ffsb 32 127 -First marked block is 32 -tst_bitmaps: ffsb 52 127 -First marked block is 52 -tst_bitmaps: ffsb 53 127 -ext2fs_find_first_set_block_bitmap2() returned No such file or directory -tst_bitmaps: ffsb 46 127 -First marked block is 46 -tst_bitmaps: ffsb 45 127 -First marked block is 46 -tst_bitmaps: ffsb 41 127 -First marked block is 44 -tst_bitmaps: ffsb 20 127 -First marked block is 24 -tst_bitmaps: ffsb 1 127 -First marked block is 1 -tst_bitmaps: ffsb 2 127 -First marked block is 4 -tst_bitmaps: ffsb 3 127 -First marked block is 4 -tst_bitmaps: ffsb 4 127 -First marked block is 4 -tst_bitmaps: ffsb 5 127 -First marked block is 5 -tst_bitmaps: ffsb 6 127 -First marked block is 6 -tst_bitmaps: ffsb 7 127 -First marked block is 8 -tst_bitmaps: ffsb 8 127 -First marked block is 8 -tst_bitmaps: ffzb 1 127 -First unmarked block is 2 -tst_bitmaps: ffzb 2 127 -First unmarked block is 2 -tst_bitmaps: ffzb 3 127 -First unmarked block is 3 -tst_bitmaps: ffzb 4 127 -First unmarked block is 7 -tst_bitmaps: ffzb 5 127 -First unmarked block is 7 -tst_bitmaps: ffzb 6 127 -First unmarked block is 7 -tst_bitmaps: ffzb 7 127 -First unmarked block is 7 -tst_bitmaps: ffzb 8 127 -First unmarked block is 9 -tst_bitmaps: ffzb 45 127 -First unmarked block is 45 -tst_bitmaps: ffzb 46 127 -First unmarked block is 48 -tst_bitmaps: ffzb 47 127 -First unmarked block is 48 -tst_bitmaps: ffzb 48 127 -First unmarked block is 48 -tst_bitmaps: ffzb 49 127 -First unmarked block is 50 -tst_bitmaps: ffzb 50 127 -First unmarked block is 50 -tst_bitmaps: ffzb 51 127 -First unmarked block is 53 -tst_bitmaps: quit -tst_bitmaps: diff --git a/jni/e2fsprogs/lib/ext2fs/tst_bitops.c b/jni/e2fsprogs/lib/ext2fs/tst_bitops.c deleted file mode 100755 index adef12d..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_bitops.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * This testing program makes sure the bitops functions work - * - * Copyright (C) 2001 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include "config.h" -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include -#if HAVE_ERRNO_H -#include -#endif -#include -#include - -#include "ext2_fs.h" -#include "ext2fs.h" - -unsigned char bitarray[] = { - 0x80, 0xF0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, 0x10, 0x20, 0x00, 0x00 - }; - -int bits_list[] = { - 7, 12, 13, 14,15, 22, 30, 68, 77, -1, -}; - -#define BIG_TEST_BIT (((unsigned) 1 << 31) + 42) - - -int main(int argc, char **argv) -{ - int i, j, size; - unsigned char testarray[12]; - unsigned char *bigarray; - - size = sizeof(bitarray)*8; -#if 0 - i = ext2fs_find_first_bit_set(bitarray, size); - while (i < size) { - printf("Bit set: %d\n", i); - i = ext2fs_find_next_bit_set(bitarray, size, i+1); - } -#endif - - /* Test test_bit */ - for (i=0,j=0; i < size; i++) { - if (ext2fs_test_bit(i, bitarray)) { - if (bits_list[j] == i) { - j++; - } else { - printf("Bit %d set, not expected\n", i); - exit(1); - } - } else { - if (bits_list[j] == i) { - printf("Expected bit %d to be clear.\n", i); - exit(1); - } - } - } - printf("ext2fs_test_bit appears to be correct\n"); - - /* Test ext2fs_set_bit */ - memset(testarray, 0, sizeof(testarray)); - for (i=0; bits_list[i] > 0; i++) { - ext2fs_set_bit(bits_list[i], testarray); - } - if (memcmp(testarray, bitarray, sizeof(testarray)) == 0) { - printf("ext2fs_set_bit test succeeded.\n"); - } else { - printf("ext2fs_set_bit test failed.\n"); - for (i=0; i < sizeof(testarray); i++) { - printf("%02x ", testarray[i]); - } - printf("\n"); - exit(1); - } - for (i=0; bits_list[i] > 0; i++) { - ext2fs_clear_bit(bits_list[i], testarray); - } - for (i=0; i < sizeof(testarray); i++) { - if (testarray[i]) { - printf("ext2fs_clear_bit failed, " - "testarray[%d] is %d\n", i, testarray[i]); - exit(1); - } - } - printf("ext2fs_clear_bit test succeed.\n"); - - - /* Do bigarray test */ - bigarray = malloc(1 << 29); - if (!bigarray) { - fprintf(stderr, "Failed to allocate scratch memory!\n"); - exit(0); - } - - bigarray[BIG_TEST_BIT >> 3] = 0; - - ext2fs_set_bit(BIG_TEST_BIT, bigarray); - printf("big bit number (%u) test: %d, expected %d\n", BIG_TEST_BIT, - bigarray[BIG_TEST_BIT >> 3], (1 << (BIG_TEST_BIT & 7))); - if (bigarray[BIG_TEST_BIT >> 3] != (1 << (BIG_TEST_BIT & 7))) - exit(1); - - ext2fs_clear_bit(BIG_TEST_BIT, bigarray); - - printf("big bit number (%u) test: %d, expected 0\n", BIG_TEST_BIT, - bigarray[BIG_TEST_BIT >> 3]); - if (bigarray[BIG_TEST_BIT >> 3] != 0) - exit(1); - - printf("ext2fs_set_bit big_test successful\n"); - - - /* Now test ext2fs_fast_set_bit */ - memset(testarray, 0, sizeof(testarray)); - for (i=0; bits_list[i] > 0; i++) { - ext2fs_fast_set_bit(bits_list[i], testarray); - } - if (memcmp(testarray, bitarray, sizeof(testarray)) == 0) { - printf("ext2fs_fast_set_bit test succeeded.\n"); - } else { - printf("ext2fs_fast_set_bit test failed.\n"); - for (i=0; i < sizeof(testarray); i++) { - printf("%02x ", testarray[i]); - } - printf("\n"); - exit(1); - } - for (i=0; bits_list[i] > 0; i++) { - ext2fs_clear_bit(bits_list[i], testarray); - } - for (i=0; i < sizeof(testarray); i++) { - if (testarray[i]) { - printf("ext2fs_clear_bit failed, " - "testarray[%d] is %d\n", i, testarray[i]); - exit(1); - } - } - printf("ext2fs_clear_bit test succeed.\n"); - - - bigarray[BIG_TEST_BIT >> 3] = 0; - - ext2fs_fast_set_bit(BIG_TEST_BIT, bigarray); - printf("big bit number (%u) test: %d, expected %d\n", BIG_TEST_BIT, - bigarray[BIG_TEST_BIT >> 3], (1 << (BIG_TEST_BIT & 7))); - if (bigarray[BIG_TEST_BIT >> 3] != (1 << (BIG_TEST_BIT & 7))) - exit(1); - - ext2fs_fast_clear_bit(BIG_TEST_BIT, bigarray); - - printf("big bit number (%u) test: %d, expected 0\n", BIG_TEST_BIT, - bigarray[BIG_TEST_BIT >> 3]); - if (bigarray[BIG_TEST_BIT >> 3] != 0) - exit(1); - - printf("ext2fs_fast_set_bit big_test successful\n"); - - /* Repeat foregoing tests for 64-bit bitops */ - - /* Test test_bit */ - for (i=0,j=0; i < size; i++) { - if (ext2fs_test_bit64(i, bitarray)) { - if (bits_list[j] == i) { - j++; - } else { - printf("64-bit: Bit %d set, not expected\n", - i); - exit(1); - } - } else { - if (bits_list[j] == i) { - printf("64-bit: " - "Expected bit %d to be clear.\n", i); - exit(1); - } - } - } - printf("64-bit: ext2fs_test_bit appears to be correct\n"); - - /* Test ext2fs_set_bit */ - memset(testarray, 0, sizeof(testarray)); - for (i=0; bits_list[i] > 0; i++) { - ext2fs_set_bit64(bits_list[i], testarray); - } - if (memcmp(testarray, bitarray, sizeof(testarray)) == 0) { - printf("64-bit: ext2fs_set_bit test succeeded.\n"); - } else { - printf("64-bit: ext2fs_set_bit test failed.\n"); - for (i=0; i < sizeof(testarray); i++) { - printf("%02x ", testarray[i]); - } - printf("\n"); - exit(1); - } - for (i=0; bits_list[i] > 0; i++) { - ext2fs_clear_bit64(bits_list[i], testarray); - } - for (i=0; i < sizeof(testarray); i++) { - if (testarray[i]) { - printf("64-bit: ext2fs_clear_bit failed, " - "testarray[%d] is %d\n", i, testarray[i]); - exit(1); - } - } - printf("64-bit: ext2fs_clear_bit test succeed.\n"); - - /* Do bigarray test */ - bigarray[BIG_TEST_BIT >> 3] = 0; - - ext2fs_set_bit64(BIG_TEST_BIT, bigarray); - printf("64-bit: big bit number (%u) test: %d, expected %d\n", - BIG_TEST_BIT, bigarray[BIG_TEST_BIT >> 3], - (1 << (BIG_TEST_BIT & 7))); - if (bigarray[BIG_TEST_BIT >> 3] != (1 << (BIG_TEST_BIT & 7))) - exit(1); - - ext2fs_clear_bit64(BIG_TEST_BIT, bigarray); - - printf("64-bit: big bit number (%u) test: %d, expected 0\n", - BIG_TEST_BIT, - bigarray[BIG_TEST_BIT >> 3]); - if (bigarray[BIG_TEST_BIT >> 3] != 0) - exit(1); - - printf("64-bit: ext2fs_set_bit big_test successful\n"); - - /* Now test ext2fs_fast_set_bit */ - memset(testarray, 0, sizeof(testarray)); - for (i=0; bits_list[i] > 0; i++) { - ext2fs_fast_set_bit64(bits_list[i], testarray); - } - if (memcmp(testarray, bitarray, sizeof(testarray)) == 0) { - printf("64-bit: ext2fs_fast_set_bit test succeeded.\n"); - } else { - printf("64-bit: ext2fs_fast_set_bit test failed.\n"); - for (i=0; i < sizeof(testarray); i++) { - printf("%02x ", testarray[i]); - } - printf("\n"); - exit(1); - } - for (i=0; bits_list[i] > 0; i++) { - ext2fs_clear_bit64(bits_list[i], testarray); - } - for (i=0; i < sizeof(testarray); i++) { - if (testarray[i]) { - printf("64-bit: ext2fs_clear_bit failed, " - "testarray[%d] is %d\n", i, testarray[i]); - exit(1); - } - } - printf("64-bit: ext2fs_clear_bit test succeed.\n"); - - bigarray[BIG_TEST_BIT >> 3] = 0; - - ext2fs_fast_set_bit64(BIG_TEST_BIT, bigarray); - printf("64-bit: big bit number (%u) test: %d, expected %d\n", - BIG_TEST_BIT, bigarray[BIG_TEST_BIT >> 3], - (1 << (BIG_TEST_BIT & 7))); - if (bigarray[BIG_TEST_BIT >> 3] != (1 << (BIG_TEST_BIT & 7))) - exit(1); - - ext2fs_fast_clear_bit64(BIG_TEST_BIT, bigarray); - - printf("64-bit: big bit number (%u) test: %d, expected 0\n", - BIG_TEST_BIT, bigarray[BIG_TEST_BIT >> 3]); - if (bigarray[BIG_TEST_BIT >> 3] != 0) - exit(1); - - printf("64-bit: ext2fs_fast_set_bit big_test successful\n"); - free(bigarray); - exit(0); -} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_byteswap.c b/jni/e2fsprogs/lib/ext2fs/tst_byteswap.c deleted file mode 100755 index c500cae..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_byteswap.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This testing program makes sure the byteswap functions work - * - * Copyright (C) 2000 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include "config.h" -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include -#if HAVE_ERRNO_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -__u16 test1[] = { - 0x0001, 0x0100, - 0x1234, 0x3412, - 0xff00, 0x00ff, - 0x4000, 0x0040, - 0xfeff, 0xfffe, - 0x0000, 0x0000 - }; - -__u32 test2[] = { - 0x00000001, 0x01000000, - 0x80000000, 0x00000080, - 0x12345678, 0x78563412, - 0xffff0000, 0x0000ffff, - 0x00ff0000, 0x0000ff00, - 0xff000000, 0x000000ff, - 0x00000000, 0x00000000 - }; - -int main(int argc, char **argv) -{ - int i; - int errors = 0; - - printf("Testing ext2fs_swab16\n"); - i=0; - do { - printf("swab16(0x%04x) = 0x%04x\n", test1[i], - ext2fs_swab16(test1[i])); - if (ext2fs_swab16(test1[i]) != test1[i+1]) { - printf("Error!!! %04x != %04x\n", - ext2fs_swab16(test1[i]), test1[i+1]); - errors++; - } - if (ext2fs_swab16(test1[i+1]) != test1[i]) { - printf("Error!!! %04x != %04x\n", - ext2fs_swab16(test1[i+1]), test1[i]); - errors++; - } - i += 2; - } while (test1[i] != 0); - - printf("Testing ext2fs_swab32\n"); - i = 0; - do { - printf("swab32(0x%08x) = 0x%08x\n", test2[i], - ext2fs_swab32(test2[i])); - if (ext2fs_swab32(test2[i]) != test2[i+1]) { - printf("Error!!! %04x != %04x\n", - ext2fs_swab32(test2[i]), test2[i+1]); - errors++; - } - if (ext2fs_swab32(test2[i+1]) != test2[i]) { - printf("Error!!! %04x != %04x\n", - ext2fs_swab32(test2[i+1]), test2[i]); - errors++; - } - i += 2; - } while (test2[i] != 0); - - if (!errors) - printf("No errors found in the byteswap implementation!\n"); - - return errors; -} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_cmds.ct b/jni/e2fsprogs/lib/ext2fs/tst_cmds.ct deleted file mode 100755 index 45a8594..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_cmds.ct +++ /dev/null @@ -1,6 +0,0 @@ -command_table libext2fs_cmds; - -request do_block_iterate, "block_iterate", - block_iterate; - -end; diff --git a/jni/e2fsprogs/lib/ext2fs/tst_fs_struct.c b/jni/e2fsprogs/lib/ext2fs/tst_fs_struct.c deleted file mode 100755 index 6f44df1..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_fs_struct.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This testing program checks the offset of the ext2_filsys structure - * - * Copyright (C) 2007 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include -#include -#include - -#include "ext2fs.h" - -struct struct_ext2_filsys fs; - -#ifndef offsetof -#define offsetof(type, member) __builtin_offsetof (type, member) -#endif -#define check_field(x) cur_offset = do_field(#x, sizeof(fs.x), \ - offsetof(struct struct_ext2_filsys, x), \ - cur_offset) - -static int do_field(const char *field, size_t size, int offset, int cur_offset) -{ - if (offset != cur_offset) { - printf("\t(padding %d bytes?)\n", offset - cur_offset); - } - printf("%8d %-30s %3u\n", offset, field, (unsigned) size); - return offset + size; -} - -int main(int argc, char **argv) -{ -#if (__GNUC__ >= 4) - int cur_offset = 0; - - printf("%8s %-30s %3s\n", "offset", "field", "size"); - check_field(magic); - check_field(io); - check_field(flags); - check_field(device_name); - check_field(super); - check_field(blocksize); - check_field(fragsize); - check_field(group_desc_count); - check_field(desc_blocks); - check_field(group_desc); - check_field(inode_blocks_per_group); - check_field(inode_map); - check_field(block_map); - check_field(get_blocks); - check_field(check_directory); - check_field(write_bitmaps); - check_field(read_inode); - check_field(write_inode); - check_field(badblocks); - check_field(dblist); - check_field(stride); - check_field(orig_super); - check_field(image_header); - check_field(umask); - check_field(now); - check_field(cluster_ratio_bits); - check_field(reserved); - check_field(priv_data); - check_field(icache); - check_field(image_io); - check_field(get_alloc_block); - check_field(block_alloc_stats); - check_field(mmp_buf); - check_field(mmp_cmp); - check_field(mmp_fd); - check_field(mmp_last_written); - printf("Ending offset is %d\n\n", cur_offset); -#endif - exit(0); -} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_getsectsize.c b/jni/e2fsprogs/lib/ext2fs/tst_getsectsize.c deleted file mode 100755 index d616965..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_getsectsize.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * tst_getsize.c --- this function tests the getsize function - * - * Copyright (C) 1997 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include "config.h" -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include -#if HAVE_ERRNO_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -int main(int argc, char **argv) -{ - int lsectsize, psectsize; - int retval; - int fd; - - if (argc < 2) { - fprintf(stderr, "Usage: %s device\n", argv[0]); - exit(1); - } - - retval = ext2fs_get_device_sectsize(argv[1], &lsectsize); - if (retval) { - com_err(argv[0], retval, - "while calling ext2fs_get_device_sectsize"); - exit(1); - } - retval = ext2fs_get_device_phys_sectsize(argv[1], &psectsize); - if (retval) { - com_err(argv[0], retval, - "while calling ext2fs_get_device_phys_sectsize"); - exit(1); - } - printf("Device %s has logical/physical sector size of %d/%d.\n", - argv[1], lsectsize, psectsize); - fd = open(argv[1], O_RDONLY); - if (fd < 0) { - perror("open"); - exit(1); - } - printf("The device's DIO alignment is %d\n", - ext2fs_get_dio_alignment(fd)); - close(fd); - exit(0); -} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_getsize.c b/jni/e2fsprogs/lib/ext2fs/tst_getsize.c deleted file mode 100755 index ba869dc..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_getsize.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * tst_getsize.c --- this function tests the getsize function - * - * Copyright (C) 1997 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include "config.h" -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include -#if HAVE_ERRNO_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -int main(int argc, const char *argv[]) -{ - errcode_t retval; - blk64_t blocks; - - if (argc < 2) { - fprintf(stderr, "%s device\n", argv[0]); - exit(1); - } - add_error_table(&et_ext2_error_table); - retval = ext2fs_get_device_size2(argv[1], 1024, &blocks); - if (retval) { - com_err(argv[0], retval, "while getting device size"); - exit(1); - } - printf("%s is device has %llu blocks.\n", argv[1], - (unsigned long long) blocks); - return 0; -} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_inode_size.c b/jni/e2fsprogs/lib/ext2fs/tst_inode_size.c deleted file mode 100755 index cc5d165..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_inode_size.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This testing program makes sure the ext2_inode structure is 1024 bytes long - * - * Copyright (C) 2007 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include "config.h" -#include -#include -#include - -#include "ext2_fs.h" - -struct ext2_inode_large inode; - -#ifndef offsetof -#define offsetof(type, member) __builtin_offsetof(type, member) -#endif - -#define check_field(x, s) cur_offset = do_field(#x, s, sizeof(inode.x), \ - offsetof(struct ext2_inode_large, x), \ - cur_offset) - -static int do_field(const char *field, unsigned size, unsigned cur_size, - unsigned offset, unsigned cur_offset) -{ - if (size != cur_size) { - printf("error: %s size %u should be %u\n", - field, cur_size, size); - exit(1); - } - if (offset != cur_offset) { - printf("error: %s offset %u should be %u\n", - field, cur_offset, offset); - exit(1); - } - printf("%8d %-30s %3u\n", offset, field, (unsigned) size); - return offset + size; -} - -int main(int argc, char **argv) -{ -#if (__GNUC__ >= 4) - int cur_offset = 0; - - printf("%8s %-30s %3s\n", "offset", "field", "size"); - check_field(i_mode, 2); - check_field(i_uid, 2); - check_field(i_size, 4); - check_field(i_atime, 4); - check_field(i_ctime, 4); - check_field(i_mtime, 4); - check_field(i_dtime, 4); - check_field(i_gid, 2); - check_field(i_links_count, 2); - check_field(i_blocks, 4); - check_field(i_flags, 4); - check_field(osd1.linux1.l_i_version, 4); - check_field(i_block, 15 * 4); - check_field(i_generation, 4); - check_field(i_file_acl, 4); - check_field(i_size_high, 4); - check_field(i_faddr, 4); - check_field(osd2.linux2.l_i_blocks_hi, 2); - check_field(osd2.linux2.l_i_file_acl_high, 2); - check_field(osd2.linux2.l_i_uid_high, 2); - check_field(osd2.linux2.l_i_gid_high, 2); - check_field(osd2.linux2.l_i_checksum_lo, 2); - check_field(osd2.linux2.l_i_reserved, 2); - do_field("Small inode end", 0, 0, cur_offset, 128); - check_field(i_extra_isize, 2); - check_field(i_checksum_hi, 2); - check_field(i_ctime_extra, 4); - check_field(i_mtime_extra, 4); - check_field(i_atime_extra, 4); - check_field(i_crtime, 4); - check_field(i_crtime_extra, 4); - check_field(i_version_hi, 4); - check_field(i_projid, 4); - /* This size will change as new fields are added */ - do_field("Large inode end", 0, 0, cur_offset, sizeof(inode)); -#endif - return 0; -} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_iscan.c b/jni/e2fsprogs/lib/ext2fs/tst_iscan.c deleted file mode 100755 index 76aaa9a..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_iscan.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * tst_inode.c --- this function tests the inode scan function - * - * Copyright (C) 1996 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include "config.h" -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include -#if HAVE_ERRNO_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -blk64_t test_vec[] = { 8, 12, 24, 34, 43, 44, 100, 0 }; - -ext2_filsys test_fs; -ext2fs_block_bitmap bad_block_map, touched_map; -ext2fs_inode_bitmap bad_inode_map; -badblocks_list test_badblocks; - -int first_no_comma = 1; -int failed = 0; - -static void iscan_test_read_blk64(unsigned long long block, int count, errcode_t err) -{ - int i; - - if (first_no_comma) - first_no_comma = 0; - else - printf(", "); - - if (count > 1) - printf("%llu-%llu", block, block+count-1); - else - printf("%llu", block); - - for (i=0; i < count; i++, block++) { - if (ext2fs_test_block_bitmap2(touched_map, block)) { - printf("\nDuplicate block?!? --- %llu\n", block); - failed++; - first_no_comma = 1; - } - ext2fs_mark_block_bitmap2(touched_map, block); - } -} - -static void iscan_test_read_blk(unsigned long block, int count, errcode_t err) -{ - iscan_test_read_blk64(block, count, err); -} - -/* - * Setup the variables for doing the inode scan test. - */ -static void setup(void) -{ - errcode_t retval; - int i; - struct ext2_super_block param; - - initialize_ext2_error_table(); - - memset(¶m, 0, sizeof(param)); - ext2fs_blocks_count_set(¶m, 12000); - - - test_io_cb_read_blk = iscan_test_read_blk; - test_io_cb_read_blk64 = iscan_test_read_blk64; - - retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m, - test_io_manager, &test_fs); - if (retval) { - com_err("setup", retval, - "While initializing filesystem"); - exit(1); - } - retval = ext2fs_allocate_tables(test_fs); - if (retval) { - com_err("setup", retval, - "While allocating tables for test filesystem"); - exit(1); - } - retval = ext2fs_allocate_block_bitmap(test_fs, "bad block map", - &bad_block_map); - if (retval) { - com_err("setup", retval, - "While allocating bad_block bitmap"); - exit(1); - } - retval = ext2fs_allocate_block_bitmap(test_fs, "touched map", - &touched_map); - if (retval) { - com_err("setup", retval, - "While allocating touched block bitmap"); - exit(1); - } - retval = ext2fs_allocate_inode_bitmap(test_fs, "bad inode map", - &bad_inode_map); - if (retval) { - com_err("setup", retval, - "While allocating bad inode bitmap"); - exit(1); - } - - retval = ext2fs_badblocks_list_create(&test_badblocks, 5); - if (retval) { - com_err("setup", retval, "while creating badblocks list"); - exit(1); - } - for (i=0; test_vec[i]; i++) { - retval = ext2fs_badblocks_list_add(test_badblocks, test_vec[i]); - if (retval) { - com_err("setup", retval, - "while adding test vector %d", i); - exit(1); - } - ext2fs_mark_block_bitmap2(bad_block_map, test_vec[i]); - } - test_fs->badblocks = test_badblocks; -} - -/* - * Iterate using inode_scan - */ -static void iterate(void) -{ - struct ext2_inode inode; - ext2_inode_scan scan; - errcode_t retval; - ext2_ino_t ino; - - retval = ext2fs_open_inode_scan(test_fs, 8, &scan); - if (retval) { - com_err("iterate", retval, "While opening inode scan"); - exit(1); - } - printf("Reading blocks: "); - retval = ext2fs_get_next_inode(scan, &ino, &inode); - if (retval) { - com_err("iterate", retval, "while reading first inode"); - exit(1); - } - while (ino) { - retval = ext2fs_get_next_inode(scan, &ino, &inode); - if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) { - ext2fs_mark_inode_bitmap2(bad_inode_map, ino); - continue; - } - if (retval) { - com_err("iterate", retval, - "while getting next inode"); - exit(1); - } - } - printf("\n"); - ext2fs_close_inode_scan(scan); -} - -/* - * Verify the touched map - */ -static void check_map(void) -{ - int i, j, first=1; - blk64_t blk; - - for (i=0; test_vec[i]; i++) { - if (ext2fs_test_block_bitmap2(touched_map, test_vec[i])) { - printf("Bad block was touched --- %llu\n", - (unsigned long long) test_vec[i]); - failed++; - first_no_comma = 1; - } - ext2fs_mark_block_bitmap2(touched_map, test_vec[i]); - } - for (i = 0; i < test_fs->group_desc_count; i++) { - for (j=0, blk = ext2fs_inode_table_loc(test_fs, i); - j < test_fs->inode_blocks_per_group; - j++, blk++) { - if (!ext2fs_test_block_bitmap2(touched_map, blk) && - !ext2fs_test_block_bitmap2(bad_block_map, blk)) { - printf("Missing block --- %llu\n", - (unsigned long long) blk); - failed++; - } - } - } - printf("Bad inodes: "); - for (i=1; i <= test_fs->super->s_inodes_count; i++) { - if (ext2fs_test_inode_bitmap2(bad_inode_map, i)) { - if (first) - first = 0; - else - printf(", "); - printf("%u", i); - } - } - printf("\n"); -} - - -int main(int argc, char **argv) -{ - setup(); - iterate(); - check_map(); - if (!failed) - printf("Inode scan tested OK!\n"); - return failed; -} - diff --git a/jni/e2fsprogs/lib/ext2fs/tst_libext2fs.c b/jni/e2fsprogs/lib/ext2fs/tst_libext2fs.c deleted file mode 100755 index 4c86464..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_libext2fs.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * tst_libext2fs.c - */ - -#include "config.h" -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fsP.h" - -#include "ss/ss.h" -#include "debugfs.h" - -/* - * Hook in new commands into debugfs - * Override debugfs's prompt - */ -const char *debug_prog_name = "tst_libext2fs"; -extern ss_request_table libext2fs_cmds; -ss_request_table *extra_cmds = &libext2fs_cmds; - -static int print_blocks_proc(ext2_filsys fs EXT2FS_ATTR((unused)), - blk64_t *blocknr, e2_blkcnt_t blockcnt, - blk64_t ref_block, int ref_offset, - void *private EXT2FS_ATTR((unused))) -{ - printf("%6lld %8llu (%d %llu)\n", (long long) blockcnt, - (unsigned long long) *blocknr, ref_offset, - (unsigned long long) ref_block); - return 0; -} - - -void do_block_iterate(int argc, char **argv, int sci_idx EXT2FS_ATTR((unused)), - void *infop EXT2FS_ATTR((unused))) -{ - const char *usage = "block_iterate 2) { - flags = parse_ulong(argv[2], argv[0], "flags", &err); - if (err) - return; - } - flags |= BLOCK_FLAG_READ_ONLY; - - ext2fs_block_iterate3(current_fs, ino, flags, NULL, - print_blocks_proc, NULL); - putc('\n', stdout); -} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_super_size.c b/jni/e2fsprogs/lib/ext2fs/tst_super_size.c deleted file mode 100755 index 80a5269..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_super_size.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * This testing program makes sure superblock size is 1024 bytes long - * - * Copyright (C) 2007 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include "config.h" -#include -#include -#include - -#include "ext2_fs.h" - -#define sb_struct ext2_super_block -#define sb_struct_name "ext2_super_block" - -struct sb_struct sb; - -#ifndef offsetof -#define offsetof(type, member) __builtin_offsetof (type, member) -#endif - -#define check_field(x, s) cur_offset = do_field(#x, s, sizeof(sb.x), \ - offsetof(struct sb_struct, x), \ - cur_offset) - -static int do_field(const char *field, unsigned size, unsigned cur_size, - unsigned offset, unsigned cur_offset) -{ - if (size != cur_size) { - printf("error: %s size %u should be %u\n", - field, cur_size, size); - exit(1); - } - if (offset != cur_offset) { - printf("error: %s offset %u should be %u\n", - field, cur_offset, offset); - exit(1); - } - printf("%8d %-30s %3u\n", offset, field, size); - return offset + size; -} - -int main(int argc, char **argv) -{ -#if (__GNUC__ >= 4) - int cur_offset = 0; - - printf("%8s %-30s %3s\n", "offset", "field", "size"); - check_field(s_inodes_count, 4); - check_field(s_blocks_count, 4); - check_field(s_r_blocks_count, 4); - check_field(s_free_blocks_count, 4); - check_field(s_free_inodes_count, 4); - check_field(s_first_data_block, 4); - check_field(s_log_block_size, 4); - check_field(s_log_cluster_size, 4); - check_field(s_blocks_per_group, 4); - check_field(s_clusters_per_group, 4); - check_field(s_inodes_per_group, 4); - check_field(s_mtime, 4); - check_field(s_wtime, 4); - check_field(s_mnt_count, 2); - check_field(s_max_mnt_count, 2); - check_field(s_magic, 2); - check_field(s_state, 2); - check_field(s_errors, 2); - check_field(s_minor_rev_level, 2); - check_field(s_lastcheck, 4); - check_field(s_checkinterval, 4); - check_field(s_creator_os, 4); - check_field(s_rev_level, 4); - check_field(s_def_resuid, 2); - check_field(s_def_resgid, 2); - check_field(s_first_ino, 4); - check_field(s_inode_size, 2); - check_field(s_block_group_nr, 2); - check_field(s_feature_compat, 4); - check_field(s_feature_incompat, 4); - check_field(s_feature_ro_compat, 4); - check_field(s_uuid, 16); - check_field(s_volume_name, 16); - check_field(s_last_mounted, 64); - check_field(s_algorithm_usage_bitmap, 4); - check_field(s_prealloc_blocks, 1); - check_field(s_prealloc_dir_blocks, 1); - check_field(s_reserved_gdt_blocks, 2); - check_field(s_journal_uuid, 16); - check_field(s_journal_inum, 4); - check_field(s_journal_dev, 4); - check_field(s_last_orphan, 4); - check_field(s_hash_seed, 4 * 4); - check_field(s_def_hash_version, 1); - check_field(s_jnl_backup_type, 1); - check_field(s_desc_size, 2); - check_field(s_default_mount_opts, 4); - check_field(s_first_meta_bg, 4); - check_field(s_mkfs_time, 4); - check_field(s_jnl_blocks, 17 * 4); - check_field(s_blocks_count_hi, 4); - check_field(s_r_blocks_count_hi, 4); - check_field(s_free_blocks_hi, 4); - check_field(s_min_extra_isize, 2); - check_field(s_want_extra_isize, 2); - check_field(s_flags, 4); - check_field(s_raid_stride, 2); - check_field(s_mmp_update_interval, 2); - check_field(s_mmp_block, 8); - check_field(s_raid_stripe_width, 4); - check_field(s_log_groups_per_flex, 1); - check_field(s_checksum_type, 1); - check_field(s_encryption_level, 1); - check_field(s_reserved_pad, 1); - check_field(s_kbytes_written, 8); - check_field(s_snapshot_inum, 4); - check_field(s_snapshot_id, 4); - check_field(s_snapshot_r_blocks_count, 8); - check_field(s_snapshot_list, 4); - check_field(s_error_count, 4); - check_field(s_first_error_time, 4); - check_field(s_first_error_ino, 4); - check_field(s_first_error_block, 8); - check_field(s_first_error_func, 32); - check_field(s_first_error_line, 4); - check_field(s_last_error_time, 4); - check_field(s_last_error_ino, 4); - check_field(s_last_error_line, 4); - check_field(s_last_error_block, 8); - check_field(s_last_error_func, 32); - check_field(s_mount_opts, 64); - check_field(s_usr_quota_inum, 4); - check_field(s_grp_quota_inum, 4); - check_field(s_overhead_clusters, 4); - check_field(s_backup_bgs, 8); - check_field(s_encrypt_algos, 4); - check_field(s_encrypt_pw_salt, 16); - check_field(s_lpf_ino, 4); - check_field(s_prj_quota_inum, 4); - check_field(s_checksum_seed, 4); - check_field(s_wtime_hi, 1); - check_field(s_mtime_hi, 1); - check_field(s_mkfs_time_hi, 1); - check_field(s_lastcheck_hi, 1); - check_field(s_first_error_time_hi, 1); - check_field(s_last_error_time_hi, 1); - check_field(s_first_error_errcode, 1); - check_field(s_last_error_errcode, 1); - check_field(s_encoding, 2); - check_field(s_encoding_flags, 2); - check_field(s_reserved, 95 * 4); - check_field(s_checksum, 4); - do_field("Superblock end", 0, 0, cur_offset, 1024); -#endif - return 0; -} diff --git a/jni/e2fsprogs/lib/ext2fs/tst_types.c b/jni/e2fsprogs/lib/ext2fs/tst_types.c deleted file mode 100755 index 3e41128..0000000 --- a/jni/e2fsprogs/lib/ext2fs/tst_types.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This testing program makes sure the ext2_types header file - * - * Copyright (C) 2006 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Library - * General Public License, version 2. - * %End-Header% - */ - -#include "config.h" -#include -#include -#include - -#include "ext2fs/ext2_types.h" - -int main(int argc, char **argv) -{ - if (sizeof(__u8) != 1) { - printf("Sizeof(__u8) is %d should be 1\n", - (int)sizeof(__u8)); - exit(1); - } - if (sizeof(__s8) != 1) { - printf("Sizeof(_s8) is %d should be 1\n", - (int)sizeof(__s8)); - exit(1); - } - if (sizeof(__u16) != 2) { - printf("Sizeof(__u16) is %d should be 2\n", - (int)sizeof(__u16)); - exit(1); - } - if (sizeof(__s16) != 2) { - printf("Sizeof(__s16) is %d should be 2\n", - (int)sizeof(__s16)); - exit(1); - } - if (sizeof(__u32) != 4) { - printf("Sizeof(__u32) is %d should be 4\n", - (int)sizeof(__u32)); - exit(1); - } - if (sizeof(__s32) != 4) { - printf("Sizeof(__s32) is %d should be 4\n", - (int)sizeof(__s32)); - exit(1); - } - if (sizeof(__u64) != 8) { - printf("Sizeof(__u64) is %d should be 8\n", - (int)sizeof(__u64)); - exit(1); - } - if (sizeof(__s64) != 8) { - printf("Sizeof(__s64) is %d should be 8\n", - (int)sizeof(__s64)); - exit(1); - } - printf("The ext2_types.h types are correct.\n"); - exit(0); -} - diff --git a/pmt-termux.sh b/pmt-termux.sh index c06af9a..354795a 100755 --- a/pmt-termux.sh +++ b/pmt-termux.sh @@ -3,8 +3,8 @@ # By YZBruh | ShawkTeam # Variables -LOCAL_VERSION="2.9.1" -LOCAL_RELDATE="20241003" +LOCAL_VERSION="2.9.6" +LOCAL_RELDATE="20241026" LOCAL_OWNER="ShawkTeam" LOCAL_REPO="pmt" LOCAL_RELEASE_TAG="${LOCAL_VERSION}" @@ -257,9 +257,10 @@ while (($# >= 1)); do ;; --package) PACKAGE=true - [ -z ${2} ] \ - && printc "Option '--package' requires an argument (file)." \ - && exit 1 + [ -z ${2} ] && \ + { printc "Option '--package' requires an argument (file)." + exit 1 + } LOCAL_PACKAGE="${2}" ALREADY_SHIFT=true && shift 1 ;; @@ -285,7 +286,7 @@ while (($# >= 1)); do done ### Main ### -[ -z "${1}" -a "${SOME_SPEC}" != 1 ] && view_help && exit 1 +[ -z "${1}" -a "${SOME_SPEC}" != 1 ] && { view_help; exit 1; } if [ "${PROCESS}" = 1 -o "${PROCESS}" = 2 ]; then script_head