nandroid in C now has a progress bar
This commit is contained in:
parent
928d605435
commit
ee57bbc1b6
@ -8,7 +8,8 @@ commands_recovery_local_path := $(LOCAL_PATH)
|
||||
# LOCAL_CPP_EXTENSION := .c
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
extendedcommands.c \
|
||||
extendedcommands.c \
|
||||
nandroid.c \
|
||||
legacy.c \
|
||||
commands.c \
|
||||
recovery.c \
|
||||
@ -50,7 +51,6 @@ LOCAL_STATIC_LIBRARIES += libstdc++ libc
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
include $(commands_recovery_local_path)/amend/Android.mk
|
||||
include $(commands_recovery_local_path)/nandroid/Android.mk
|
||||
include $(commands_recovery_local_path)/minui/Android.mk
|
||||
include $(commands_recovery_local_path)/minzip/Android.mk
|
||||
include $(commands_recovery_local_path)/mtdutils/Android.mk
|
||||
|
@ -779,7 +779,7 @@ cmd_backup_rom(const char *name, void *cookie, int argc, const char *argv[],
|
||||
return 1;
|
||||
}
|
||||
|
||||
return do_nandroid_backup(backup_name);
|
||||
return nandroid_backup(backup_name);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -794,7 +794,7 @@ cmd_restore_rom(const char *name, void *cookie, int argc, const char *argv[],
|
||||
return 1;
|
||||
}
|
||||
|
||||
return do_nandroid_restore(argv[0]);
|
||||
return nandroid_restore(argv[0]);
|
||||
}
|
||||
|
||||
static int
|
||||
|
2
common.h
2
common.h
@ -33,6 +33,8 @@ void ui_clear_key_queue();
|
||||
// so keep the output short and not too cryptic.
|
||||
void ui_print(const char *fmt, ...);
|
||||
|
||||
void ui_reset_text_col();
|
||||
|
||||
// Display some header text followed by a menu of items, which appears
|
||||
// at the top of the screen (in place of any scrolling ui_print()
|
||||
// output, if necessary).
|
||||
|
@ -37,6 +37,9 @@
|
||||
#include "../../external/yaffs2/yaffs2/utils/mkyaffs2image.h"
|
||||
#include "../../external/yaffs2/yaffs2/utils/unyaffs.h"
|
||||
|
||||
#include "extendedcommands.h"
|
||||
#include "nandroid.h"
|
||||
|
||||
int signature_check_enabled = 1;
|
||||
int script_assert_enabled = 1;
|
||||
static const char *SDCARD_PACKAGE_FILE = "SDCARD:update.zip";
|
||||
@ -120,7 +123,7 @@ char** gather_files(const char* directory, const char* fileExtensionOrDirectory,
|
||||
struct dirent *de;
|
||||
int total = 0;
|
||||
int i;
|
||||
char** files;
|
||||
char** files = NULL;
|
||||
int pass;
|
||||
*numFiles = 0;
|
||||
int dirLen = strlen(directory);
|
||||
@ -131,7 +134,7 @@ char** gather_files(const char* directory, const char* fileExtensionOrDirectory,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int extension_length;
|
||||
int extension_length = 0;
|
||||
if (fileExtensionOrDirectory != NULL)
|
||||
extension_length = strlen(fileExtensionOrDirectory);
|
||||
|
||||
@ -225,7 +228,7 @@ char* choose_file_menu(const char* directory, const char* fileExtensionOrDirecto
|
||||
int dir_len = strlen(directory);
|
||||
|
||||
char** files = gather_files(directory, fileExtensionOrDirectory, &numFiles);
|
||||
char** dirs;
|
||||
char** dirs = NULL;
|
||||
if (fileExtensionOrDirectory != NULL)
|
||||
dirs = gather_files(directory, NULL, &numDirs);
|
||||
int total = numDirs + numFiles;
|
||||
@ -291,10 +294,10 @@ void show_choose_zip_menu()
|
||||
// This was pulled from bionic: The default system command always looks
|
||||
// for shell in /system/bin/sh. This is bad.
|
||||
#define _PATH_BSHELL "/sbin/sh"
|
||||
#define system recovery_system
|
||||
|
||||
extern char **environ;
|
||||
int
|
||||
system(const char *command)
|
||||
__system(const char *command)
|
||||
{
|
||||
pid_t pid;
|
||||
sig_t intsave, quitsave;
|
||||
@ -335,124 +338,11 @@ int print_and_error(char* message)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO : Separate file for Nandroid?
|
||||
int do_nandroid_backup(char* backup_name)
|
||||
{
|
||||
if (ensure_root_path_mounted("SDCARD:") != 0) {
|
||||
LOGE ("Can't mount /sdcard\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct timeval tp;
|
||||
gettimeofday(&tp, NULL);
|
||||
|
||||
char backupdir[PATH_MAX];
|
||||
char tmp[PATH_MAX];
|
||||
if (NULL != backup_name)
|
||||
sprintf(backupdir, "/sdcard/clockworkmod/backup/%s", backup_name);
|
||||
else
|
||||
sprintf(backupdir, "/sdcard/clockworkmod/backup/%d", tp.tv_sec);
|
||||
|
||||
sprintf(tmp, "mkdir -p %s", backupdir);
|
||||
system(tmp);
|
||||
|
||||
int ret;
|
||||
ui_print("Backing up boot...\n");
|
||||
sprintf(tmp, "%s/%s", backupdir, "boot.img");
|
||||
ret = dump_image("boot", tmp, NULL);
|
||||
if (0 != ret)
|
||||
return print_and_error("Error while dumping boot image!\n");
|
||||
|
||||
// TODO: Wrap this up in a loop?
|
||||
ui_print("Backing up system...\n");
|
||||
sprintf(tmp, "%s/%s", backupdir, "system.img");
|
||||
if (ensure_root_path_mounted("SYSTEM:") != 0)
|
||||
return print_and_error("Can't mount /system!\n");
|
||||
ret = mkyaffs2image("/system", tmp, 0, NULL);
|
||||
ensure_root_path_unmounted("SYSTEM:");
|
||||
if (0 != ret)
|
||||
return print_and_error("Error while making a yaffs2 image of system!\n");
|
||||
|
||||
ui_print("Backing up data...\n");
|
||||
sprintf(tmp, "%s/%s", backupdir, "data.img");
|
||||
if (ensure_root_path_mounted("DATA:") != 0)
|
||||
return print_and_error("Can't mount /data!\n");
|
||||
ret = mkyaffs2image("/data", tmp, 0, NULL);
|
||||
ensure_root_path_unmounted("DATA:");
|
||||
if (0 != ret)
|
||||
return print_and_error("Error while making a yaffs2 image of data!\n");
|
||||
|
||||
ui_print("Backing up cache...\n");
|
||||
sprintf(tmp, "%s/%s", backupdir, "cache.img");
|
||||
if (ensure_root_path_mounted("CACHE:") != 0)
|
||||
return print_and_error("Can't mount /cache!\n");
|
||||
ret = mkyaffs2image("/cache", tmp, 0, NULL);
|
||||
ensure_root_path_unmounted("CACHE:");
|
||||
if (0 != ret)
|
||||
return print_and_error("Error while making a yaffs2 image of cache!\n");
|
||||
|
||||
sprintf(tmp, "md5sum %s/*img > %s/nandroid.md5", backupdir, backupdir);
|
||||
system(tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_nandroid_restore(char* backup_path)
|
||||
{
|
||||
if (ensure_root_path_mounted("SDCARD:") != 0) {
|
||||
LOGE ("Can't mount /sdcard\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char tmp[PATH_MAX];
|
||||
|
||||
ui_print("Checking MD5 sums...\n");
|
||||
sprintf(tmp, "md5sum -c %s/nandroid.md5", backup_path);
|
||||
if (0 != system(tmp))
|
||||
return print_and_error("MD5 mismatch!\n");
|
||||
|
||||
// TODO: put this in a loop?
|
||||
ui_print("Restoring system...\n");
|
||||
if (0 != ensure_root_path_unmounted("SYSTEM:"))
|
||||
return print_and_error("Can't unmount /system!\n");
|
||||
if (0 != format_root_device("SYSTEM:"))
|
||||
return print_and_error("Error while formatting /system!\n");
|
||||
if (ensure_root_path_mounted("SYSTEM:") != 0)
|
||||
return print_and_error("Can't mount /system!\n");
|
||||
sprintf(tmp, "%s/system.img", backup_path);
|
||||
if (0 != unyaffs(tmp, "/system", NULL))
|
||||
return print_and_error("Error while restoring /system!\n");
|
||||
|
||||
ui_print("Restoring data...\n");
|
||||
if (0 != ensure_root_path_unmounted("DATA:"))
|
||||
return print_and_error("Can't unmount /data!\n");
|
||||
if (0 != format_root_device("DATA:"))
|
||||
return print_and_error("Error while formatting /data!\n");
|
||||
if (ensure_root_path_mounted("DATA:") != 0)
|
||||
return print_and_error("Can't mount /data!\n");
|
||||
sprintf(tmp, "%s/data.img", backup_path);
|
||||
if (0 != unyaffs(tmp, "/data", NULL))
|
||||
return print_and_error("Error while restoring /data!\n");
|
||||
|
||||
ui_print("Restoring cache...\n");
|
||||
if (0 != ensure_root_path_unmounted("CACHE:"))
|
||||
return print_and_error("Can't unmount /cache!\n");
|
||||
if (0 != format_root_device("CACHE:"))
|
||||
return print_and_error("Error while formatting /cache!\n");
|
||||
if (ensure_root_path_mounted("CACHE:") != 0)
|
||||
return print_and_error("Can't mount /cache!\n");
|
||||
sprintf(tmp, "%s/cache.img", backup_path);
|
||||
if (0 != unyaffs(tmp, "/cache", NULL))
|
||||
return print_and_error("Error while restoring /cache!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void show_nandroid_restore_menu()
|
||||
{
|
||||
if (ensure_root_path_mounted("SDCARD:") != 0) {
|
||||
LOGE ("Can't mount /sdcard\n");
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
|
||||
static char* headers[] = { "Choose an image to restore",
|
||||
@ -463,7 +353,7 @@ void show_nandroid_restore_menu()
|
||||
char* file = choose_file_menu("/sdcard/clockworkmod/backup/", NULL, headers);
|
||||
if (file == NULL)
|
||||
return;
|
||||
do_nandroid_restore(file);
|
||||
nandroid_restore(file);
|
||||
}
|
||||
|
||||
void do_mount_usb_storage()
|
||||
@ -514,7 +404,7 @@ int run_script_from_buffer(char* script_data, int script_len, char* filename)
|
||||
int ret = execCommandList((ExecContext *)1, commands);
|
||||
if (ret != 0) {
|
||||
int num = ret;
|
||||
char *line, *next = script_data;
|
||||
char *line = NULL, *next = script_data;
|
||||
while (next != NULL && ret-- > 0) {
|
||||
line = next;
|
||||
next = memchr(line, '\n', script_data + script_len - line);
|
||||
|
@ -34,3 +34,5 @@ show_choose_zip_menu();
|
||||
int
|
||||
install_zip(const char* packagefilepath);
|
||||
|
||||
int
|
||||
__system(const char *command);
|
||||
|
183
nandroid.c
Normal file
183
nandroid.c
Normal file
@ -0,0 +1,183 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <linux/input.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <sys/limits.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "bootloader.h"
|
||||
#include "common.h"
|
||||
#include "cutils/properties.h"
|
||||
#include "firmware.h"
|
||||
#include "install.h"
|
||||
#include "minui/minui.h"
|
||||
#include "minzip/DirUtil.h"
|
||||
#include "roots.h"
|
||||
#include "recovery_ui.h"
|
||||
|
||||
#include "commands.h"
|
||||
#include "amend/amend.h"
|
||||
|
||||
#include "mtdutils/dump_image.h"
|
||||
#include "../../external/yaffs2/yaffs2/utils/mkyaffs2image.h"
|
||||
#include "../../external/yaffs2/yaffs2/utils/unyaffs.h"
|
||||
|
||||
#include "extendedcommands.h"
|
||||
#include "nandroid.h"
|
||||
|
||||
int yaffs_files_total = 0;
|
||||
int yaffs_files_count = 0;
|
||||
void yaffs_callback(char* filename)
|
||||
{
|
||||
char* justfile = basename(filename);
|
||||
if (strlen(justfile) < 30)
|
||||
ui_print(basename(filename));
|
||||
yaffs_files_count++;
|
||||
if (yaffs_files_total != 0)
|
||||
ui_set_progress((float)yaffs_files_count / (float)yaffs_files_total);
|
||||
ui_reset_text_col();
|
||||
}
|
||||
|
||||
void compute_directory_stats(char* directory)
|
||||
{
|
||||
char tmp[PATH_MAX];
|
||||
sprintf(tmp, "find %s | wc -l > /tmp/dircount", directory);
|
||||
__system(tmp);
|
||||
char count_text[100];
|
||||
FILE* f = fopen("/tmp/dircount", "r");
|
||||
fread(count_text, 1, sizeof(count_text), f);
|
||||
fclose(f);
|
||||
yaffs_files_count = 0;
|
||||
yaffs_files_total = atoi(count_text);
|
||||
ui_reset_progress();
|
||||
ui_show_progress(1, 0);
|
||||
}
|
||||
|
||||
int nandroid_backup(char* backup_path)
|
||||
{
|
||||
ui_set_background(BACKGROUND_ICON_INSTALLING);
|
||||
|
||||
if (ensure_root_path_mounted("SDCARD:") != 0)
|
||||
return print_and_error("Can't mount /sdcard\n");
|
||||
|
||||
char tmp[PATH_MAX];
|
||||
sprintf(tmp, "mkdir -p %s", backup_path);
|
||||
__system(tmp);
|
||||
|
||||
int ret;
|
||||
ui_print("Backing up boot...\n");
|
||||
sprintf(tmp, "%s/%s", backup_path, "boot.img");
|
||||
ret = dump_image("boot", tmp, NULL);
|
||||
if (0 != ret)
|
||||
return print_and_error("Error while dumping boot image!\n");
|
||||
|
||||
// TODO: Wrap this up in a loop?
|
||||
ui_print("Backing up system...\n");
|
||||
sprintf(tmp, "%s/%s", backup_path, "system.img");
|
||||
if (ensure_root_path_mounted("SYSTEM:") != 0)
|
||||
return print_and_error("Can't mount /system!\n");
|
||||
compute_directory_stats("/system");
|
||||
ret = mkyaffs2image("/system", tmp, 0, yaffs_callback);
|
||||
ensure_root_path_unmounted("SYSTEM:");
|
||||
if (0 != ret)
|
||||
return print_and_error("Error while making a yaffs2 image of system!\n");
|
||||
|
||||
ui_print("Backing up data...\n");
|
||||
sprintf(tmp, "%s/%s", backup_path, "data.img");
|
||||
if (ensure_root_path_mounted("DATA:") != 0)
|
||||
return print_and_error("Can't mount /data!\n");
|
||||
compute_directory_stats("/data");
|
||||
ret = mkyaffs2image("/data", tmp, 0, yaffs_callback);
|
||||
ensure_root_path_unmounted("DATA:");
|
||||
if (0 != ret)
|
||||
return print_and_error("Error while making a yaffs2 image of data!\n");
|
||||
|
||||
ui_print("Backing up cache...\n");
|
||||
sprintf(tmp, "%s/%s", backup_path, "cache.img");
|
||||
if (ensure_root_path_mounted("CACHE:") != 0)
|
||||
return print_and_error("Can't mount /cache!\n");
|
||||
compute_directory_stats("/cache");
|
||||
ret = mkyaffs2image("/cache", tmp, 0, yaffs_callback);
|
||||
ensure_root_path_unmounted("CACHE:");
|
||||
if (0 != ret)
|
||||
return print_and_error("Error while making a yaffs2 image of cache!\n");
|
||||
|
||||
sprintf(tmp, "md5sum %s/*img > %s/nandroid.md5", backup_path, backup_path);
|
||||
__system(tmp);
|
||||
|
||||
ui_set_background(BACKGROUND_ICON_NONE);
|
||||
ui_reset_progress();
|
||||
ui_print("Backup complete!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nandroid_restore(char* backup_path)
|
||||
{
|
||||
ui_set_background(BACKGROUND_ICON_INSTALLING);
|
||||
ui_show_indeterminate_progress();
|
||||
yaffs_files_total = 0;
|
||||
|
||||
if (ensure_root_path_mounted("SDCARD:") != 0)
|
||||
return print_and_error("Can't mount /sdcard\n");
|
||||
|
||||
char tmp[PATH_MAX];
|
||||
|
||||
ui_print("Checking MD5 sums...\n");
|
||||
sprintf(tmp, "md5sum -c %s/nandroid.md5", backup_path);
|
||||
if (0 != __system(tmp))
|
||||
return print_and_error("MD5 mismatch!\n");
|
||||
|
||||
// TODO: put this in a loop?
|
||||
ui_print("Restoring system...\n");
|
||||
if (0 != ensure_root_path_unmounted("SYSTEM:"))
|
||||
return print_and_error("Can't unmount /system!\n");
|
||||
if (0 != format_root_device("SYSTEM:"))
|
||||
return print_and_error("Error while formatting /system!\n");
|
||||
if (ensure_root_path_mounted("SYSTEM:") != 0)
|
||||
return print_and_error("Can't mount /system!\n");
|
||||
sprintf(tmp, "%s/system.img", backup_path);
|
||||
if (0 != unyaffs(tmp, "/system", yaffs_callback))
|
||||
return print_and_error("Error while restoring /system!\n");
|
||||
|
||||
ui_print("Restoring data...\n");
|
||||
if (0 != ensure_root_path_unmounted("DATA:"))
|
||||
return print_and_error("Can't unmount /data!\n");
|
||||
if (0 != format_root_device("DATA:"))
|
||||
return print_and_error("Error while formatting /data!\n");
|
||||
if (ensure_root_path_mounted("DATA:") != 0)
|
||||
return print_and_error("Can't mount /data!\n");
|
||||
sprintf(tmp, "%s/data.img", backup_path);
|
||||
if (0 != unyaffs(tmp, "/data", yaffs_callback))
|
||||
return print_and_error("Error while restoring /data!\n");
|
||||
|
||||
ui_print("Restoring cache...\n");
|
||||
if (0 != ensure_root_path_unmounted("CACHE:"))
|
||||
return print_and_error("Can't unmount /cache!\n");
|
||||
if (0 != format_root_device("CACHE:"))
|
||||
return print_and_error("Error while formatting /cache!\n");
|
||||
if (ensure_root_path_mounted("CACHE:") != 0)
|
||||
return print_and_error("Can't mount /cache!\n");
|
||||
sprintf(tmp, "%s/cache.img", backup_path);
|
||||
if (0 != unyaffs(tmp, "/cache", yaffs_callback))
|
||||
return print_and_error("Error while restoring /cache!\n");
|
||||
|
||||
ui_set_background(BACKGROUND_ICON_NONE);
|
||||
ui_reset_progress();
|
||||
ui_print("Restore complete!\n");
|
||||
return 0;
|
||||
}
|
8
nandroid.h
Normal file
8
nandroid.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef NANDROID_H
|
||||
#define NANDROID_H
|
||||
|
||||
int nandroid_main(int argc, char** argv);
|
||||
int nandroid_backup(char* backup_path);
|
||||
int nandroid_restore(char* backup_path);
|
||||
|
||||
#endif
|
@ -1,21 +0,0 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := recovery_nandroid
|
||||
LOCAL_MODULE_TAGS := eng
|
||||
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
|
||||
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
|
||||
LOCAL_SRC_FILES := nandroid-mobile.sh
|
||||
LOCAL_MODULE_STEM := nandroid-mobile.sh
|
||||
ADDITIONAL_RECOVERY_EXECUTABLES += recovery_nandroid
|
||||
include $(BUILD_PREBUILT)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := recovery_mkfstab
|
||||
LOCAL_MODULE_TAGS := eng
|
||||
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
|
||||
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
|
||||
LOCAL_SRC_FILES := mkfstab.sh
|
||||
LOCAL_MODULE_STEM := mkfstab.sh
|
||||
ADDITIONAL_RECOVERY_EXECUTABLES += recovery_mkfstab
|
||||
include $(BUILD_PREBUILT)
|
||||
|
@ -1,33 +0,0 @@
|
||||
#!/sbin/sh
|
||||
|
||||
cat /proc/mtd | while read mtdentry
|
||||
do
|
||||
mtd=$(echo $mtdentry | awk '{print $1}')
|
||||
mtd=$(echo $mtd | sed s/mtd//)
|
||||
mtd=$(echo $mtd | sed s/://)
|
||||
exist=$(ls -l /dev/block/mtdblock$mtd) 2> /dev/null
|
||||
if [ -z "$exist" ]
|
||||
then
|
||||
continue
|
||||
fi
|
||||
partition=$(echo $mtdentry | awk '{print $4}')
|
||||
partition=$(echo $partition | sed s/\"//g)
|
||||
mount=$partition
|
||||
type=
|
||||
if [ "$partition" = "system" ]
|
||||
then
|
||||
type=yaffs2
|
||||
elif [ "$partition" = "userdata" ]
|
||||
then
|
||||
type=yaffs2
|
||||
mount=data
|
||||
elif [ "$partition" == "cache" ]
|
||||
then
|
||||
type=yaffs2
|
||||
else
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "/dev/block/mtdblock$mtd /$mount $type rw"
|
||||
done
|
||||
echo "/dev/block/mmcblk0p1" /sdcard vfat rw
|
@ -446,7 +446,13 @@ prompt_and_wait()
|
||||
show_install_update_menu();
|
||||
break;
|
||||
case ITEM_BACKUP:
|
||||
do_nandroid_backup(NULL);
|
||||
{
|
||||
struct timeval tp;
|
||||
gettimeofday(&tp, NULL);
|
||||
char backup_path[PATH_MAX];
|
||||
sprintf(backup_path, "/sdcard/clockworkmod/backup/%d", tp.tv_sec);
|
||||
nandroid_backup(backup_path);
|
||||
}
|
||||
break;
|
||||
case ITEM_RESTORE:
|
||||
show_nandroid_restore_menu();
|
||||
|
7
ui.c
7
ui.c
@ -480,6 +480,13 @@ void ui_print(const char *fmt, ...)
|
||||
pthread_mutex_unlock(&gUpdateMutex);
|
||||
}
|
||||
|
||||
void ui_reset_text_col()
|
||||
{
|
||||
pthread_mutex_lock(&gUpdateMutex);
|
||||
text_col = 0;
|
||||
pthread_mutex_unlock(&gUpdateMutex);
|
||||
}
|
||||
|
||||
#define MENU_ITEM_HEADER " - "
|
||||
#define MENU_ITEM_HEADER_LENGTH strlen(MENU_ITEM_HEADER)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user